switch ixp4xx and ubicom32 to 2.6.30, get rid of 2.6.28 files
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18952 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
4060780e57
commit
2434746dd4
|
@ -1,57 +0,0 @@
|
||||||
--- a/arch/mips/Kconfig
|
|
||||||
+++ b/arch/mips/Kconfig
|
|
||||||
@@ -19,6 +19,21 @@ choice
|
|
||||||
prompt "System type"
|
|
||||||
default SGI_IP22
|
|
||||||
|
|
||||||
+config ADM5120
|
|
||||||
+ bool "Infineon/ADMtek ADM5120 SoC based machines"
|
|
||||||
+ select CEVT_R4K
|
|
||||||
+ select CSRC_R4K
|
|
||||||
+ select SYS_HAS_CPU_MIPS32_R1
|
|
||||||
+ select SYS_HAS_EARLY_PRINTK
|
|
||||||
+ select DMA_NONCOHERENT
|
|
||||||
+ select IRQ_CPU
|
|
||||||
+ select SYS_SUPPORTS_LITTLE_ENDIAN
|
|
||||||
+ select SYS_SUPPORTS_BIG_ENDIAN
|
|
||||||
+ select SYS_SUPPORTS_32BIT_KERNEL
|
|
||||||
+ select ARCH_REQUIRE_GPIOLIB
|
|
||||||
+ select SWAP_IO_SPACE if CPU_BIG_ENDIAN
|
|
||||||
+ select MIPS_MACHINE
|
|
||||||
+
|
|
||||||
config MACH_ALCHEMY
|
|
||||||
bool "Alchemy processor based machines"
|
|
||||||
|
|
||||||
@@ -597,6 +612,7 @@ config WR_PPMC
|
|
||||||
|
|
||||||
endchoice
|
|
||||||
|
|
||||||
+source "arch/mips/adm5120/Kconfig"
|
|
||||||
source "arch/mips/alchemy/Kconfig"
|
|
||||||
source "arch/mips/basler/excite/Kconfig"
|
|
||||||
source "arch/mips/emma/Kconfig"
|
|
||||||
--- a/arch/mips/Makefile
|
|
||||||
+++ b/arch/mips/Makefile
|
|
||||||
@@ -183,6 +183,22 @@ cflags-$(CONFIG_MACH_JAZZ) += -I$(srctre
|
|
||||||
load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000
|
|
||||||
|
|
||||||
#
|
|
||||||
+# Infineon/ADMtek ADM5120
|
|
||||||
+#
|
|
||||||
+libs-$(CONFIG_ADM5120) += arch/mips/adm5120/prom/
|
|
||||||
+core-$(CONFIG_ADM5120) += arch/mips/adm5120/common/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_CELLVISION) += arch/mips/adm5120/cellvision/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_COMPEX) += arch/mips/adm5120/compex/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_EDIMAX) += arch/mips/adm5120/edimax/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_INFINEON) += arch/mips/adm5120/infineon/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_MIKROTIK) += arch/mips/adm5120/mikrotik/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_MOTOROLA) += arch/mips/adm5120/motorola/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_OSBRIDGE) += arch/mips/adm5120/osbridge/
|
|
||||||
+core-$(CONFIG_ADM5120_OEM_ZYXEL) += arch/mips/adm5120/zyxel/
|
|
||||||
+cflags-$(CONFIG_ADM5120) += -I$(srctree)/arch/mips/include/asm/mach-adm5120
|
|
||||||
+load-$(CONFIG_ADM5120) += 0xffffffff80001000
|
|
||||||
+
|
|
||||||
+#
|
|
||||||
# Common Alchemy Au1x00 stuff
|
|
||||||
#
|
|
||||||
core-$(CONFIG_SOC_AU1X00) += arch/mips/alchemy/common/
|
|
|
@ -1,22 +0,0 @@
|
||||||
--- a/drivers/mtd/maps/Kconfig
|
|
||||||
+++ b/drivers/mtd/maps/Kconfig
|
|
||||||
@@ -540,5 +540,9 @@ config MTD_PLATRAM
|
|
||||||
|
|
||||||
This selection automatically selects the map_ram driver.
|
|
||||||
|
|
||||||
+config MTD_ADM5120
|
|
||||||
+ tristate "Map driver for ADM5120 based boards"
|
|
||||||
+ depends on ADM5120
|
|
||||||
+
|
|
||||||
endmenu
|
|
||||||
|
|
||||||
--- a/drivers/mtd/maps/Makefile
|
|
||||||
+++ b/drivers/mtd/maps/Makefile
|
|
||||||
@@ -42,6 +42,7 @@ obj-$(CONFIG_MTD_DBOX2) += dbox2-flash.
|
|
||||||
obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
|
|
||||||
obj-$(CONFIG_MTD_PCI) += pci.o
|
|
||||||
obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o
|
|
||||||
+obj-$(CONFIG_MTD_ADM5120) += adm5120-flash.o
|
|
||||||
obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o
|
|
||||||
obj-$(CONFIG_MTD_EDB7312) += edb7312.o
|
|
||||||
obj-$(CONFIG_MTD_IMPA7) += impa7.o
|
|
|
@ -1,23 +0,0 @@
|
||||||
--- a/drivers/net/Kconfig
|
|
||||||
+++ b/drivers/net/Kconfig
|
|
||||||
@@ -602,6 +602,10 @@ config MIPS_AU1X00_ENET
|
|
||||||
If you have an Alchemy Semi AU1X00 based system
|
|
||||||
say Y. Otherwise, say N.
|
|
||||||
|
|
||||||
+config ADM5120_ENET
|
|
||||||
+ tristate "ADM5120 Ethernet switch support"
|
|
||||||
+ depends on ADM5120
|
|
||||||
+
|
|
||||||
config SGI_IOC3_ETH
|
|
||||||
bool "SGI IOC3 Ethernet"
|
|
||||||
depends on PCI && SGI_IP27
|
|
||||||
--- a/drivers/net/Makefile
|
|
||||||
+++ b/drivers/net/Makefile
|
|
||||||
@@ -191,6 +191,7 @@ obj-$(CONFIG_SC92031) += sc92031.o
|
|
||||||
# This is also a 82596 and should probably be merged
|
|
||||||
obj-$(CONFIG_LP486E) += lp486e.o
|
|
||||||
|
|
||||||
+obj-$(CONFIG_ADM5120_ENET) += adm5120sw.o
|
|
||||||
obj-$(CONFIG_ETH16I) += eth16i.o
|
|
||||||
obj-$(CONFIG_ZORRO8390) += zorro8390.o
|
|
||||||
obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
|
|
|
@ -1,33 +0,0 @@
|
||||||
--- a/drivers/usb/Makefile
|
|
||||||
+++ b/drivers/usb/Makefile
|
|
||||||
@@ -17,6 +17,7 @@ obj-$(CONFIG_USB_SL811_HCD) += host/
|
|
||||||
obj-$(CONFIG_USB_U132_HCD) += host/
|
|
||||||
obj-$(CONFIG_USB_R8A66597_HCD) += host/
|
|
||||||
obj-$(CONFIG_USB_HWA_HCD) += host/
|
|
||||||
+obj-$(CONFIG_USB_ADM5120_HCD) += host/
|
|
||||||
|
|
||||||
obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
|
|
||||||
|
|
||||||
--- a/drivers/usb/host/Kconfig
|
|
||||||
+++ b/drivers/usb/host/Kconfig
|
|
||||||
@@ -4,6 +4,10 @@
|
|
||||||
comment "USB Host Controller Drivers"
|
|
||||||
depends on USB
|
|
||||||
|
|
||||||
+config USB_ADM5120_HCD
|
|
||||||
+ tristate "ADM5120 HCD support (EXPERIMENTAL)"
|
|
||||||
+ depends on USB && ADM5120 && EXPERIMENTAL
|
|
||||||
+
|
|
||||||
config USB_C67X00_HCD
|
|
||||||
tristate "Cypress C67x00 HCD support"
|
|
||||||
depends on USB
|
|
||||||
--- a/drivers/usb/host/Makefile
|
|
||||||
+++ b/drivers/usb/host/Makefile
|
|
||||||
@@ -12,6 +12,7 @@ obj-$(CONFIG_USB_WHCI_HCD) += whci/
|
|
||||||
|
|
||||||
obj-$(CONFIG_PCI) += pci-quirks.o
|
|
||||||
|
|
||||||
+obj-$(CONFIG_USB_ADM5120_HCD) += adm5120-hcd.o
|
|
||||||
obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
|
|
||||||
obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o
|
|
||||||
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
|
|
|
@ -1,19 +0,0 @@
|
||||||
--- a/arch/mips/pci/Makefile
|
|
||||||
+++ b/arch/mips/pci/Makefile
|
|
||||||
@@ -52,3 +52,4 @@ obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc
|
|
||||||
obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o
|
|
||||||
obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o
|
|
||||||
obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o
|
|
||||||
+obj-$(CONFIG_ADM5120) += pci-adm5120.o
|
|
||||||
--- a/include/linux/pci_ids.h
|
|
||||||
+++ b/include/linux/pci_ids.h
|
|
||||||
@@ -1729,6 +1729,9 @@
|
|
||||||
#define PCI_VENDOR_ID_ESDGMBH 0x12fe
|
|
||||||
#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
|
|
||||||
|
|
||||||
+#define PCI_VENDOR_ID_ADMTEK 0x1317
|
|
||||||
+#define PCI_DEVICE_ID_ADMTEK_ADM5120 0x5120
|
|
||||||
+
|
|
||||||
#define PCI_VENDOR_ID_SIIG 0x131f
|
|
||||||
#define PCI_SUBVENDOR_ID_SIIG 0x131f
|
|
||||||
#define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000
|
|
|
@ -1,22 +0,0 @@
|
||||||
--- a/drivers/leds/Kconfig
|
|
||||||
+++ b/drivers/leds/Kconfig
|
|
||||||
@@ -234,4 +234,12 @@ config LEDS_TRIGGER_NETDEV
|
|
||||||
This allows LEDs to be controlled by network device activity.
|
|
||||||
If unsure, say Y.
|
|
||||||
|
|
||||||
+config LEDS_TRIGGER_ADM5120_SWITCH
|
|
||||||
+ tristate "LED ADM5120 Switch Port Status Trigger"
|
|
||||||
+ depends on LEDS_TRIGGERS && ADM5120
|
|
||||||
+ help
|
|
||||||
+ This allows LEDs to be controlled by the port states of
|
|
||||||
+ the ADM5120 built-in Ethernet Switch
|
|
||||||
+ If unsure, say N.
|
|
||||||
+
|
|
||||||
endif # NEW_LEDS
|
|
||||||
--- a/drivers/leds/Makefile
|
|
||||||
+++ b/drivers/leds/Makefile
|
|
||||||
@@ -33,3 +33,4 @@ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) +=
|
|
||||||
obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
|
|
||||||
obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
|
|
||||||
obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
|
|
||||||
+obj-$(CONFIG_LEDS_TRIGGER_ADM5120_SWITCH) += ledtrig-adm5120-switch.o
|
|
|
@ -1,84 +0,0 @@
|
||||||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
|
||||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
|
||||||
@@ -53,6 +53,12 @@
|
|
||||||
#define AT49BV6416 0x00d6
|
|
||||||
#define MANUFACTURER_SAMSUNG 0x00ec
|
|
||||||
|
|
||||||
+/* Macronix */
|
|
||||||
+#define MX29LV160B 0x2249 /* MX29LV160 Bottom-boot chip */
|
|
||||||
+#define MX29LV160T 0x22C4 /* MX29LV160 Top-boot chip */
|
|
||||||
+#define MX29LV320B 0x22A8 /* MX29LV320 Bottom-boot chip */
|
|
||||||
+#define MX29LV320T 0x22A7 /* MX29LV320 Top-boot chip */
|
|
||||||
+
|
|
||||||
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
|
||||||
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
|
||||||
static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
|
||||||
@@ -283,6 +289,41 @@ static void fixup_s29gl032n_sectors(stru
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC
|
|
||||||
+/*
|
|
||||||
+ * Some Macronix chips has no/bad bootblock information in the CFI table
|
|
||||||
+ */
|
|
||||||
+static void fixup_macronix_bootloc(struct mtd_info *mtd, void* param)
|
|
||||||
+{
|
|
||||||
+ struct map_info *map = mtd->priv;
|
|
||||||
+ struct cfi_private *cfi = map->fldrv_priv;
|
|
||||||
+ struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
|
|
||||||
+ __u8 t;
|
|
||||||
+
|
|
||||||
+ switch (cfi->id) {
|
|
||||||
+ /* TODO: put affected chip ids here */
|
|
||||||
+ case MX29LV160B:
|
|
||||||
+ case MX29LV320B:
|
|
||||||
+ t = 2; /* Bottom boot */
|
|
||||||
+ break;
|
|
||||||
+ case MX29LV160T:
|
|
||||||
+ case MX29LV320T:
|
|
||||||
+ t = 3; /* Top boot */
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (extp->TopBottom == t)
|
|
||||||
+ /* boot location detected by the CFI layer is correct */
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ extp->TopBottom = t;
|
|
||||||
+ printk("%s: Macronix chip detected, id:0x%04X, boot location forced "
|
|
||||||
+ "to %s\n", map->name, cfi->id, (t == 2) ? "bottom" : "top");
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC */
|
|
||||||
+
|
|
||||||
static struct cfi_fixup cfi_fixup_table[] = {
|
|
||||||
{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
|
|
||||||
#ifdef AMD_BOOTLOC_BUG
|
|
||||||
@@ -319,6 +360,9 @@ static struct cfi_fixup fixup_table[] =
|
|
||||||
*/
|
|
||||||
{ CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL },
|
|
||||||
{ CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL },
|
|
||||||
+#ifdef CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC
|
|
||||||
+ { MANUFACTURER_MACRONIX, CFI_ID_ANY, fixup_macronix_bootloc, NULL, },
|
|
||||||
+#endif
|
|
||||||
{ 0, 0, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
--- a/drivers/mtd/chips/Kconfig
|
|
||||||
+++ b/drivers/mtd/chips/Kconfig
|
|
||||||
@@ -198,6 +198,14 @@ config MTD_CFI_AMDSTD
|
|
||||||
provides support for one of those command sets, used on chips
|
|
||||||
including the AMD Am29LV320.
|
|
||||||
|
|
||||||
+config MTD_CFI_FIXUP_MACRONIX_BOOTLOC
|
|
||||||
+ bool "Fix boot-block location for Macronix flash chips"
|
|
||||||
+ depends on MTD_CFI_AMDSTD
|
|
||||||
+ help
|
|
||||||
+ Some Macronix flash chips have no/wrong boot-block location in the
|
|
||||||
+ CFI table, and the driver may detect the type incorrectly. Select
|
|
||||||
+ this if your board has such chip.
|
|
||||||
+
|
|
||||||
config MTD_CFI_STAA
|
|
||||||
tristate "Support for ST (Advanced Architecture) flash chips"
|
|
||||||
depends on MTD_GEN_PROBE
|
|
|
@ -1,68 +0,0 @@
|
||||||
--- a/drivers/mtd/chips/jedec_probe.c
|
|
||||||
+++ b/drivers/mtd/chips/jedec_probe.c
|
|
||||||
@@ -128,6 +128,10 @@
|
|
||||||
#define UPD29F064115 0x221C
|
|
||||||
|
|
||||||
/* PMC */
|
|
||||||
+#define PM39LV512 0x001B
|
|
||||||
+#define PM39LV010 0x001C
|
|
||||||
+#define PM39LV020 0x003D
|
|
||||||
+#define PM39LV040 0x003E
|
|
||||||
#define PM49FL002 0x006D
|
|
||||||
#define PM49FL004 0x006E
|
|
||||||
#define PM49FL008 0x006A
|
|
||||||
@@ -1248,6 +1252,54 @@ static const struct amd_flash_info jedec
|
|
||||||
ERASEINFO(0x02000,2),
|
|
||||||
ERASEINFO(0x04000,1),
|
|
||||||
}
|
|
||||||
+ }, {
|
|
||||||
+ .mfr_id = MANUFACTURER_PMC,
|
|
||||||
+ .dev_id = PM39LV512,
|
|
||||||
+ .name = "PMC Pm39LV512",
|
|
||||||
+ .devtypes = CFI_DEVICETYPE_X8,
|
|
||||||
+ .uaddr = MTD_UADDR_0x0555_0x02AA,
|
|
||||||
+ .dev_size = SIZE_64KiB,
|
|
||||||
+ .cmd_set = P_ID_AMD_STD,
|
|
||||||
+ .nr_regions = 1,
|
|
||||||
+ .regions = {
|
|
||||||
+ ERASEINFO(0x01000,16),
|
|
||||||
+ }
|
|
||||||
+ }, {
|
|
||||||
+ .mfr_id = MANUFACTURER_PMC,
|
|
||||||
+ .dev_id = PM39LV010,
|
|
||||||
+ .name = "PMC Pm39LV010",
|
|
||||||
+ .devtypes = CFI_DEVICETYPE_X8,
|
|
||||||
+ .uaddr = MTD_UADDR_0x0555_0x02AA,
|
|
||||||
+ .dev_size = SIZE_128KiB,
|
|
||||||
+ .cmd_set = P_ID_AMD_STD,
|
|
||||||
+ .nr_regions = 1,
|
|
||||||
+ .regions = {
|
|
||||||
+ ERASEINFO(0x01000,32),
|
|
||||||
+ }
|
|
||||||
+ }, {
|
|
||||||
+ .mfr_id = MANUFACTURER_PMC,
|
|
||||||
+ .dev_id = PM39LV020,
|
|
||||||
+ .name = "PMC Pm39LV020",
|
|
||||||
+ .devtypes = CFI_DEVICETYPE_X8,
|
|
||||||
+ .uaddr = MTD_UADDR_0x0555_0x02AA,
|
|
||||||
+ .dev_size = SIZE_256KiB,
|
|
||||||
+ .cmd_set = P_ID_AMD_STD,
|
|
||||||
+ .nr_regions = 1,
|
|
||||||
+ .regions = {
|
|
||||||
+ ERASEINFO(0x01000,64),
|
|
||||||
+ }
|
|
||||||
+ }, {
|
|
||||||
+ .mfr_id = MANUFACTURER_PMC,
|
|
||||||
+ .dev_id = PM39LV040,
|
|
||||||
+ .name = "PMC Pm39LV040",
|
|
||||||
+ .devtypes = CFI_DEVICETYPE_X8,
|
|
||||||
+ .uaddr = MTD_UADDR_0x0555_0x02AA,
|
|
||||||
+ .dev_size = SIZE_512KiB,
|
|
||||||
+ .cmd_set = P_ID_AMD_STD,
|
|
||||||
+ .nr_regions = 1,
|
|
||||||
+ .regions = {
|
|
||||||
+ ERASEINFO(0x01000,128),
|
|
||||||
+ }
|
|
||||||
}, {
|
|
||||||
.mfr_id = MANUFACTURER_PMC,
|
|
||||||
.dev_id = PM49FL002,
|
|
|
@ -1,24 +0,0 @@
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -55,6 +55,11 @@ config MTD_ROOTFS_SPLIT
|
|
||||||
depends on MTD_PARTITIONS
|
|
||||||
default y
|
|
||||||
|
|
||||||
+config MTD_TRXSPLIT
|
|
||||||
+ bool "Automatically find and split TRX partitions"
|
|
||||||
+ depends on MTD_PARTITIONS
|
|
||||||
+ default n
|
|
||||||
+
|
|
||||||
config MTD_REDBOOT_PARTS
|
|
||||||
tristate "RedBoot partition table parsing"
|
|
||||||
depends on MTD_PARTITIONS
|
|
||||||
--- a/drivers/mtd/Makefile
|
|
||||||
+++ b/drivers/mtd/Makefile
|
|
||||||
@@ -8,6 +8,7 @@ mtd-y := mtdcore.o mtdsuper.o
|
|
||||||
mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
|
|
||||||
+obj-$(CONFIG_MTD_TRXSPLIT) += trxsplit.o
|
|
||||||
obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
|
|
||||||
obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
|
|
||||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
|
|
@ -1,28 +0,0 @@
|
||||||
--- a/drivers/ata/Makefile
|
|
||||||
+++ b/drivers/ata/Makefile
|
|
||||||
@@ -72,6 +72,7 @@ obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
|
|
||||||
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
|
|
||||||
obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
|
|
||||||
obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
|
|
||||||
+obj-$(CONFIG_PATA_RB153_CF) += pata_rb153_cf.o
|
|
||||||
# Should be last but two libata driver
|
|
||||||
obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
|
|
||||||
# Should be last but one libata driver
|
|
||||||
--- a/drivers/ata/Kconfig
|
|
||||||
+++ b/drivers/ata/Kconfig
|
|
||||||
@@ -567,6 +567,15 @@ config PATA_RADISYS
|
|
||||||
|
|
||||||
If unsure, say N.
|
|
||||||
|
|
||||||
+config PATA_RB153_CF
|
|
||||||
+ tristate "RouterBOARD 153 Compact Flash support"
|
|
||||||
+ depends on ADM5120_MACH_RB_153
|
|
||||||
+ help
|
|
||||||
+ This option enables support for a Compact Flash connected on
|
|
||||||
+ the RouterBOARD 153.
|
|
||||||
+
|
|
||||||
+ If unsure, say N.
|
|
||||||
+
|
|
||||||
config PATA_RB532
|
|
||||||
tristate "RouterBoard 532 PATA CompactFlash support"
|
|
||||||
depends on MIKROTIK_RB532
|
|
|
@ -1,378 +0,0 @@
|
||||||
--- a/drivers/serial/amba-pl010.c
|
|
||||||
+++ b/drivers/serial/amba-pl010.c
|
|
||||||
@@ -50,11 +50,10 @@
|
|
||||||
|
|
||||||
#include <asm/io.h>
|
|
||||||
|
|
||||||
-#define UART_NR 8
|
|
||||||
-
|
|
||||||
#define SERIAL_AMBA_MAJOR 204
|
|
||||||
#define SERIAL_AMBA_MINOR 16
|
|
||||||
-#define SERIAL_AMBA_NR UART_NR
|
|
||||||
+#define SERIAL_AMBA_NR CONFIG_SERIAL_AMBA_PL010_NUMPORTS
|
|
||||||
+#define SERIAL_AMBA_NAME CONFIG_SERIAL_AMBA_PL010_PORTNAME
|
|
||||||
|
|
||||||
#define AMBA_ISR_PASS_LIMIT 256
|
|
||||||
|
|
||||||
@@ -80,9 +79,9 @@ static void pl010_stop_tx(struct uart_po
|
|
||||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
|
||||||
unsigned int cr;
|
|
||||||
|
|
||||||
- cr = readb(uap->port.membase + UART010_CR);
|
|
||||||
+ cr = __raw_readl(uap->port.membase + UART010_CR);
|
|
||||||
cr &= ~UART010_CR_TIE;
|
|
||||||
- writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pl010_start_tx(struct uart_port *port)
|
|
||||||
@@ -90,9 +89,9 @@ static void pl010_start_tx(struct uart_p
|
|
||||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
|
||||||
unsigned int cr;
|
|
||||||
|
|
||||||
- cr = readb(uap->port.membase + UART010_CR);
|
|
||||||
+ cr = __raw_readl(uap->port.membase + UART010_CR);
|
|
||||||
cr |= UART010_CR_TIE;
|
|
||||||
- writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pl010_stop_rx(struct uart_port *port)
|
|
||||||
@@ -100,9 +99,9 @@ static void pl010_stop_rx(struct uart_po
|
|
||||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
|
||||||
unsigned int cr;
|
|
||||||
|
|
||||||
- cr = readb(uap->port.membase + UART010_CR);
|
|
||||||
+ cr = __raw_readl(uap->port.membase + UART010_CR);
|
|
||||||
cr &= ~(UART010_CR_RIE | UART010_CR_RTIE);
|
|
||||||
- writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pl010_enable_ms(struct uart_port *port)
|
|
||||||
@@ -110,9 +109,9 @@ static void pl010_enable_ms(struct uart_
|
|
||||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
|
||||||
unsigned int cr;
|
|
||||||
|
|
||||||
- cr = readb(uap->port.membase + UART010_CR);
|
|
||||||
+ cr = __raw_readl(uap->port.membase + UART010_CR);
|
|
||||||
cr |= UART010_CR_MSIE;
|
|
||||||
- writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(cr, uap->port.membase + UART010_CR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pl010_rx_chars(struct uart_amba_port *uap)
|
|
||||||
@@ -120,9 +119,9 @@ static void pl010_rx_chars(struct uart_a
|
|
||||||
struct tty_struct *tty = uap->port.info->port.tty;
|
|
||||||
unsigned int status, ch, flag, rsr, max_count = 256;
|
|
||||||
|
|
||||||
- status = readb(uap->port.membase + UART01x_FR);
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART01x_FR);
|
|
||||||
while (UART_RX_DATA(status) && max_count--) {
|
|
||||||
- ch = readb(uap->port.membase + UART01x_DR);
|
|
||||||
+ ch = __raw_readl(uap->port.membase + UART01x_DR);
|
|
||||||
flag = TTY_NORMAL;
|
|
||||||
|
|
||||||
uap->port.icount.rx++;
|
|
||||||
@@ -131,9 +130,9 @@ static void pl010_rx_chars(struct uart_a
|
|
||||||
* Note that the error handling code is
|
|
||||||
* out of the main execution path
|
|
||||||
*/
|
|
||||||
- rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
|
|
||||||
+ rsr = __raw_readl(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX;
|
|
||||||
if (unlikely(rsr & UART01x_RSR_ANY)) {
|
|
||||||
- writel(0, uap->port.membase + UART01x_ECR);
|
|
||||||
+ __raw_writel(0, uap->port.membase + UART01x_ECR);
|
|
||||||
|
|
||||||
if (rsr & UART01x_RSR_BE) {
|
|
||||||
rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE);
|
|
||||||
@@ -163,7 +162,7 @@ static void pl010_rx_chars(struct uart_a
|
|
||||||
uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag);
|
|
||||||
|
|
||||||
ignore_char:
|
|
||||||
- status = readb(uap->port.membase + UART01x_FR);
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART01x_FR);
|
|
||||||
}
|
|
||||||
spin_unlock(&uap->port.lock);
|
|
||||||
tty_flip_buffer_push(tty);
|
|
||||||
@@ -176,7 +175,7 @@ static void pl010_tx_chars(struct uart_a
|
|
||||||
int count;
|
|
||||||
|
|
||||||
if (uap->port.x_char) {
|
|
||||||
- writel(uap->port.x_char, uap->port.membase + UART01x_DR);
|
|
||||||
+ __raw_writel(uap->port.x_char, uap->port.membase + UART01x_DR);
|
|
||||||
uap->port.icount.tx++;
|
|
||||||
uap->port.x_char = 0;
|
|
||||||
return;
|
|
||||||
@@ -188,7 +187,7 @@ static void pl010_tx_chars(struct uart_a
|
|
||||||
|
|
||||||
count = uap->port.fifosize >> 1;
|
|
||||||
do {
|
|
||||||
- writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
|
|
||||||
+ __raw_writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
|
|
||||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
|
||||||
uap->port.icount.tx++;
|
|
||||||
if (uart_circ_empty(xmit))
|
|
||||||
@@ -206,9 +205,9 @@ static void pl010_modem_status(struct ua
|
|
||||||
{
|
|
||||||
unsigned int status, delta;
|
|
||||||
|
|
||||||
- writel(0, uap->port.membase + UART010_ICR);
|
|
||||||
+ __raw_writel(0, uap->port.membase + UART010_ICR);
|
|
||||||
|
|
||||||
- status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
|
||||||
|
|
||||||
delta = status ^ uap->old_status;
|
|
||||||
uap->old_status = status;
|
|
||||||
@@ -236,7 +235,7 @@ static irqreturn_t pl010_int(int irq, vo
|
|
||||||
|
|
||||||
spin_lock(&uap->port.lock);
|
|
||||||
|
|
||||||
- status = readb(uap->port.membase + UART010_IIR);
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART010_IIR);
|
|
||||||
if (status) {
|
|
||||||
do {
|
|
||||||
if (status & (UART010_IIR_RTIS | UART010_IIR_RIS))
|
|
||||||
@@ -249,7 +248,7 @@ static irqreturn_t pl010_int(int irq, vo
|
|
||||||
if (pass_counter-- == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
- status = readb(uap->port.membase + UART010_IIR);
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART010_IIR);
|
|
||||||
} while (status & (UART010_IIR_RTIS | UART010_IIR_RIS |
|
|
||||||
UART010_IIR_TIS));
|
|
||||||
handled = 1;
|
|
||||||
@@ -263,7 +262,7 @@ static irqreturn_t pl010_int(int irq, vo
|
|
||||||
static unsigned int pl010_tx_empty(struct uart_port *port)
|
|
||||||
{
|
|
||||||
struct uart_amba_port *uap = (struct uart_amba_port *)port;
|
|
||||||
- unsigned int status = readb(uap->port.membase + UART01x_FR);
|
|
||||||
+ unsigned int status = __raw_readl(uap->port.membase + UART01x_FR);
|
|
||||||
return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -273,7 +272,7 @@ static unsigned int pl010_get_mctrl(stru
|
|
||||||
unsigned int result = 0;
|
|
||||||
unsigned int status;
|
|
||||||
|
|
||||||
- status = readb(uap->port.membase + UART01x_FR);
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART01x_FR);
|
|
||||||
if (status & UART01x_FR_DCD)
|
|
||||||
result |= TIOCM_CAR;
|
|
||||||
if (status & UART01x_FR_DSR)
|
|
||||||
@@ -299,12 +298,12 @@ static void pl010_break_ctl(struct uart_
|
|
||||||
unsigned int lcr_h;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&uap->port.lock, flags);
|
|
||||||
- lcr_h = readb(uap->port.membase + UART010_LCRH);
|
|
||||||
+ lcr_h = __raw_readl(uap->port.membase + UART010_LCRH);
|
|
||||||
if (break_state == -1)
|
|
||||||
lcr_h |= UART01x_LCRH_BRK;
|
|
||||||
else
|
|
||||||
lcr_h &= ~UART01x_LCRH_BRK;
|
|
||||||
- writel(lcr_h, uap->port.membase + UART010_LCRH);
|
|
||||||
+ __raw_writel(lcr_h, uap->port.membase + UART010_LCRH);
|
|
||||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -332,12 +331,12 @@ static int pl010_startup(struct uart_por
|
|
||||||
/*
|
|
||||||
* initialise the old status of the modem signals
|
|
||||||
*/
|
|
||||||
- uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
|
||||||
+ uap->old_status = __raw_readl(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Finally, enable interrupts
|
|
||||||
*/
|
|
||||||
- writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
|
|
||||||
+ __raw_writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE,
|
|
||||||
uap->port.membase + UART010_CR);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
@@ -360,10 +359,10 @@ static void pl010_shutdown(struct uart_p
|
|
||||||
/*
|
|
||||||
* disable all interrupts, disable the port
|
|
||||||
*/
|
|
||||||
- writel(0, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(0, uap->port.membase + UART010_CR);
|
|
||||||
|
|
||||||
/* disable break condition and fifos */
|
|
||||||
- writel(readb(uap->port.membase + UART010_LCRH) &
|
|
||||||
+ __raw_writel(__raw_readl(uap->port.membase + UART010_LCRH) &
|
|
||||||
~(UART01x_LCRH_BRK | UART01x_LCRH_FEN),
|
|
||||||
uap->port.membase + UART010_LCRH);
|
|
||||||
|
|
||||||
@@ -385,7 +384,7 @@ pl010_set_termios(struct uart_port *port
|
|
||||||
/*
|
|
||||||
* Ask the core to calculate the divisor for us.
|
|
||||||
*/
|
|
||||||
- baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
|
|
||||||
+ baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16);
|
|
||||||
quot = uart_get_divisor(port, baud);
|
|
||||||
|
|
||||||
switch (termios->c_cflag & CSIZE) {
|
|
||||||
@@ -448,25 +447,25 @@ pl010_set_termios(struct uart_port *port
|
|
||||||
uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX;
|
|
||||||
|
|
||||||
/* first, disable everything */
|
|
||||||
- old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
|
|
||||||
+ old_cr = __raw_readl(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE;
|
|
||||||
|
|
||||||
if (UART_ENABLE_MS(port, termios->c_cflag))
|
|
||||||
old_cr |= UART010_CR_MSIE;
|
|
||||||
|
|
||||||
- writel(0, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(0, uap->port.membase + UART010_CR);
|
|
||||||
|
|
||||||
/* Set baud rate */
|
|
||||||
quot -= 1;
|
|
||||||
- writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
|
|
||||||
- writel(quot & 0xff, uap->port.membase + UART010_LCRL);
|
|
||||||
+ __raw_writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM);
|
|
||||||
+ __raw_writel(quot & 0xff, uap->port.membase + UART010_LCRL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ----------v----------v----------v----------v-----
|
|
||||||
* NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L
|
|
||||||
* ----------^----------^----------^----------^-----
|
|
||||||
*/
|
|
||||||
- writel(lcr_h, uap->port.membase + UART010_LCRH);
|
|
||||||
- writel(old_cr, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(lcr_h, uap->port.membase + UART010_LCRH);
|
|
||||||
+ __raw_writel(old_cr, uap->port.membase + UART010_CR);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&uap->port.lock, flags);
|
|
||||||
}
|
|
||||||
@@ -538,7 +537,7 @@ static struct uart_ops amba_pl010_pops =
|
|
||||||
.verify_port = pl010_verify_port,
|
|
||||||
};
|
|
||||||
|
|
||||||
-static struct uart_amba_port *amba_ports[UART_NR];
|
|
||||||
+static struct uart_amba_port *amba_ports[SERIAL_AMBA_NR];
|
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE
|
|
||||||
|
|
||||||
@@ -548,10 +547,10 @@ static void pl010_console_putchar(struct
|
|
||||||
unsigned int status;
|
|
||||||
|
|
||||||
do {
|
|
||||||
- status = readb(uap->port.membase + UART01x_FR);
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART01x_FR);
|
|
||||||
barrier();
|
|
||||||
} while (!UART_TX_READY(status));
|
|
||||||
- writel(ch, uap->port.membase + UART01x_DR);
|
|
||||||
+ __raw_writel(ch, uap->port.membase + UART01x_DR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
@@ -565,8 +564,8 @@ pl010_console_write(struct console *co,
|
|
||||||
/*
|
|
||||||
* First save the CR then disable the interrupts
|
|
||||||
*/
|
|
||||||
- old_cr = readb(uap->port.membase + UART010_CR);
|
|
||||||
- writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
|
|
||||||
+ old_cr = __raw_readl(uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR);
|
|
||||||
|
|
||||||
uart_console_write(&uap->port, s, count, pl010_console_putchar);
|
|
||||||
|
|
||||||
@@ -575,10 +574,10 @@ pl010_console_write(struct console *co,
|
|
||||||
* and restore the TCR
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
- status = readb(uap->port.membase + UART01x_FR);
|
|
||||||
+ status = __raw_readl(uap->port.membase + UART01x_FR);
|
|
||||||
barrier();
|
|
||||||
} while (status & UART01x_FR_BUSY);
|
|
||||||
- writel(old_cr, uap->port.membase + UART010_CR);
|
|
||||||
+ __raw_writel(old_cr, uap->port.membase + UART010_CR);
|
|
||||||
|
|
||||||
clk_disable(uap->clk);
|
|
||||||
}
|
|
||||||
@@ -587,9 +586,9 @@ static void __init
|
|
||||||
pl010_console_get_options(struct uart_amba_port *uap, int *baud,
|
|
||||||
int *parity, int *bits)
|
|
||||||
{
|
|
||||||
- if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
|
|
||||||
+ if (__raw_readl(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) {
|
|
||||||
unsigned int lcr_h, quot;
|
|
||||||
- lcr_h = readb(uap->port.membase + UART010_LCRH);
|
|
||||||
+ lcr_h = __raw_readl(uap->port.membase + UART010_LCRH);
|
|
||||||
|
|
||||||
*parity = 'n';
|
|
||||||
if (lcr_h & UART01x_LCRH_PEN) {
|
|
||||||
@@ -604,8 +603,8 @@ pl010_console_get_options(struct uart_am
|
|
||||||
else
|
|
||||||
*bits = 8;
|
|
||||||
|
|
||||||
- quot = readb(uap->port.membase + UART010_LCRL) |
|
|
||||||
- readb(uap->port.membase + UART010_LCRM) << 8;
|
|
||||||
+ quot = __raw_readl(uap->port.membase + UART010_LCRL) |
|
|
||||||
+ __raw_readl(uap->port.membase + UART010_LCRM) << 8;
|
|
||||||
*baud = uap->port.uartclk / (16 * (quot + 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -623,7 +622,7 @@ static int __init pl010_console_setup(st
|
|
||||||
* if so, search for the first available port that does have
|
|
||||||
* console support.
|
|
||||||
*/
|
|
||||||
- if (co->index >= UART_NR)
|
|
||||||
+ if (co->index >= SERIAL_AMBA_NR)
|
|
||||||
co->index = 0;
|
|
||||||
uap = amba_ports[co->index];
|
|
||||||
if (!uap)
|
|
||||||
@@ -641,7 +640,7 @@ static int __init pl010_console_setup(st
|
|
||||||
|
|
||||||
static struct uart_driver amba_reg;
|
|
||||||
static struct console amba_console = {
|
|
||||||
- .name = "ttyAM",
|
|
||||||
+ .name = SERIAL_AMBA_NAME,
|
|
||||||
.write = pl010_console_write,
|
|
||||||
.device = uart_console_device,
|
|
||||||
.setup = pl010_console_setup,
|
|
||||||
@@ -657,11 +656,11 @@ static struct console amba_console = {
|
|
||||||
|
|
||||||
static struct uart_driver amba_reg = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
- .driver_name = "ttyAM",
|
|
||||||
- .dev_name = "ttyAM",
|
|
||||||
+ .driver_name = SERIAL_AMBA_NAME,
|
|
||||||
+ .dev_name = SERIAL_AMBA_NAME,
|
|
||||||
.major = SERIAL_AMBA_MAJOR,
|
|
||||||
.minor = SERIAL_AMBA_MINOR,
|
|
||||||
- .nr = UART_NR,
|
|
||||||
+ .nr = SERIAL_AMBA_NR,
|
|
||||||
.cons = AMBA_CONSOLE,
|
|
||||||
};
|
|
||||||
|
|
||||||
--- a/drivers/serial/Kconfig
|
|
||||||
+++ b/drivers/serial/Kconfig
|
|
||||||
@@ -284,10 +284,25 @@ config SERIAL_AMBA_PL010
|
|
||||||
help
|
|
||||||
This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have
|
|
||||||
an Integrator/AP or Integrator/PP2 platform, or if you have a
|
|
||||||
- Cirrus Logic EP93xx CPU, say Y or M here.
|
|
||||||
+ Cirrus Logic EP93xx CPU or an Infineon ADM5120 SOC, say Y or M here.
|
|
||||||
|
|
||||||
If unsure, say N.
|
|
||||||
|
|
||||||
+config SERIAL_AMBA_PL010_NUMPORTS
|
|
||||||
+ int "Maximum number of AMBA PL010 serial ports"
|
|
||||||
+ depends on SERIAL_AMBA_PL010
|
|
||||||
+ default "8"
|
|
||||||
+ ---help---
|
|
||||||
+ Set this to the number of serial ports you want the AMBA PL010 driver
|
|
||||||
+ to support.
|
|
||||||
+
|
|
||||||
+config SERIAL_AMBA_PL010_PORTNAME
|
|
||||||
+ string "Name of the AMBA PL010 serial ports"
|
|
||||||
+ depends on SERIAL_AMBA_PL010
|
|
||||||
+ default "ttyAM"
|
|
||||||
+ ---help---
|
|
||||||
+ ::: To be written :::
|
|
||||||
+
|
|
||||||
config SERIAL_AMBA_PL010_CONSOLE
|
|
||||||
bool "Support for console on AMBA serial port"
|
|
||||||
depends on SERIAL_AMBA_PL010=y
|
|
|
@ -1,13 +0,0 @@
|
||||||
--- a/drivers/amba/bus.c
|
|
||||||
+++ b/drivers/amba/bus.c
|
|
||||||
@@ -17,6 +17,10 @@
|
|
||||||
#include <asm/io.h>
|
|
||||||
#include <asm/sizes.h>
|
|
||||||
|
|
||||||
+#ifndef NO_IRQ
|
|
||||||
+#define NO_IRQ (-1)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#define to_amba_device(d) container_of(d, struct amba_device, dev)
|
|
||||||
#define to_amba_driver(d) container_of(d, struct amba_driver, drv)
|
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
--- a/drivers/leds/leds-gpio.c
|
|
||||||
+++ b/drivers/leds/leds-gpio.c
|
|
||||||
@@ -43,13 +43,17 @@ static void gpio_led_set(struct led_clas
|
|
||||||
container_of(led_cdev, struct gpio_led_data, cdev);
|
|
||||||
int level;
|
|
||||||
|
|
||||||
- if (value == LED_OFF)
|
|
||||||
- level = 0;
|
|
||||||
- else
|
|
||||||
- level = 1;
|
|
||||||
-
|
|
||||||
- if (led_dat->active_low)
|
|
||||||
- level = !level;
|
|
||||||
+ switch (value) {
|
|
||||||
+ case LED_OFF:
|
|
||||||
+ level = led_dat->active_low ? 1 : 0;
|
|
||||||
+ break;
|
|
||||||
+ case LED_FULL:
|
|
||||||
+ level = led_dat->active_low ? 0 : 1;
|
|
||||||
+ break;
|
|
||||||
+ default:
|
|
||||||
+ level = value;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* Setting GPIOs with I2C/etc requires a task context, and we don't
|
|
||||||
* seem to have a reliable way to know if we're already in one; so
|
|
|
@ -1,31 +0,0 @@
|
||||||
--- a/drivers/watchdog/Kconfig
|
|
||||||
+++ b/drivers/watchdog/Kconfig
|
|
||||||
@@ -696,6 +696,18 @@ config RC32434_WDT
|
|
||||||
To compile this driver as a module, choose M here: the
|
|
||||||
module will be called rc32434_wdt.
|
|
||||||
|
|
||||||
+config ADM5120_WDT
|
|
||||||
+ tristate "Infineon ADM5120 SoC hardware watchdog"
|
|
||||||
+ depends on WATCHDOG && ADM5120
|
|
||||||
+ help
|
|
||||||
+ This is a driver for hardware watchdog integrated in Infineon
|
|
||||||
+ ADM5120 SoC. This watchdog simply watches your kernel to make sure
|
|
||||||
+ it doesn't freeze, and if it does, it reboots your computer after a
|
|
||||||
+ certain amount of time.
|
|
||||||
+
|
|
||||||
+ To compile this driver as a module, choose M here: the module will be
|
|
||||||
+ called adm5120_wdt.
|
|
||||||
+
|
|
||||||
config INDYDOG
|
|
||||||
tristate "Indy/I2 Hardware Watchdog"
|
|
||||||
depends on SGI_HAS_INDYDOG
|
|
||||||
--- a/drivers/watchdog/Makefile
|
|
||||||
+++ b/drivers/watchdog/Makefile
|
|
||||||
@@ -106,6 +106,7 @@ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
|
|
||||||
obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
|
|
||||||
obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
|
|
||||||
obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
|
|
||||||
+obj-$(CONFIG_ADM5120_WDT) += adm5120_wdt.o
|
|
||||||
|
|
||||||
# PARISC Architecture
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/drivers/mtd/trxsplit.c
|
|
||||||
+++ b/drivers/mtd/trxsplit.c
|
|
||||||
@@ -18,7 +18,7 @@
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/mtd/partitions.h>
|
|
||||||
|
|
||||||
-#include <linux/byteorder/generic.h>
|
|
||||||
+//#include <linux/byteorder/generic.h>
|
|
||||||
|
|
||||||
#define PFX "trxsplit: "
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/arch/mips/alchemy/mtx-1/init.c
|
|
||||||
+++ b/arch/mips/alchemy/mtx-1/init.c
|
|
||||||
@@ -49,7 +49,7 @@ void __init prom_init(void)
|
|
||||||
prom_argv = (char **)fw_arg1;
|
|
||||||
prom_envp = (char **)fw_arg2;
|
|
||||||
|
|
||||||
- prom_init_cmdline();
|
|
||||||
+ strcpy(arcs_cmdline, CONFIG_CMDLINE);
|
|
||||||
|
|
||||||
memsize_str = prom_getenv("memsize");
|
|
||||||
if (!memsize_str)
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/arch/mips/alchemy/mtx-1/platform.c
|
|
||||||
+++ b/arch/mips/alchemy/mtx-1/platform.c
|
|
||||||
@@ -90,7 +90,7 @@ static struct platform_device mtx1_gpio_
|
|
||||||
|
|
||||||
static struct mtd_partition mtx1_mtd_partitions[] = {
|
|
||||||
{
|
|
||||||
- .name = "filesystem",
|
|
||||||
+ .name = "rootfs",
|
|
||||||
.size = 0x01C00000,
|
|
||||||
.offset = 0,
|
|
||||||
},
|
|
|
@ -1,15 +0,0 @@
|
||||||
--- a/drivers/net/au1000_eth.c
|
|
||||||
+++ b/drivers/net/au1000_eth.c
|
|
||||||
@@ -1293,9 +1293,12 @@ static void set_rx_mode(struct net_devic
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#define AU1000_KNOWN_PHY_IOCTLS (SIOCGMIIPHY & 0xfff0)
|
|
||||||
static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
|
||||||
{
|
|
||||||
struct au1000_private *aup = (struct au1000_private *)dev->priv;
|
|
||||||
+ if((cmd & AU1000_KNOWN_PHY_IOCTLS) != AU1000_KNOWN_PHY_IOCTLS)
|
|
||||||
+ return -EINVAL;
|
|
||||||
|
|
||||||
if (!netif_running(dev)) return -EINVAL;
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
--- a/drivers/net/au1000_eth.c
|
|
||||||
+++ b/drivers/net/au1000_eth.c
|
|
||||||
@@ -184,6 +184,15 @@ struct au1000_private *au_macs[NUM_ETH_I
|
|
||||||
# undef AU1XXX_PHY1_IRQ
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#if defined(CONFIG_MIPS_MTX1)
|
|
||||||
+/*
|
|
||||||
+ * 4G MeshCube (MTX-1) board
|
|
||||||
+ * PHY is at address 31 on MAC0
|
|
||||||
+ * autodetect fails if not searched for highest address !
|
|
||||||
+ */
|
|
||||||
+# define AU1XXX_PHY_SEARCH_HIGHEST_ADDR
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#if defined(AU1XXX_PHY0_BUSID) && (AU1XXX_PHY0_BUSID > 0)
|
|
||||||
# error MAC0-associated PHY attached 2nd MACs MII bus not supported yet
|
|
||||||
#endif
|
|
||||||
@@ -380,6 +389,12 @@ static int mii_probe (struct net_device
|
|
||||||
aup->old_duplex = -1;
|
|
||||||
aup->phy_dev = phydev;
|
|
||||||
|
|
||||||
+#ifdef CONFIG_MIPS_MTX1
|
|
||||||
+ /* set up ethernet jack LEDs on the 4G MeshCube (MTX-1 board) */
|
|
||||||
+ printk(KERN_INFO "MTX-1 PHY: updating LED settings\n");
|
|
||||||
+ phy_write(phydev, 0x11, 0xff80);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
printk(KERN_INFO "%s: attached PHY driver [%s] "
|
|
||||||
"(mii_bus:phy_addr=%s, irq=%d)\n",
|
|
||||||
dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/arch/mips/alchemy/mtx-1/init.c
|
|
||||||
+++ b/arch/mips/alchemy/mtx-1/init.c
|
|
||||||
@@ -32,6 +32,7 @@
|
|
||||||
#include <linux/init.h>
|
|
||||||
|
|
||||||
#include <asm/bootinfo.h>
|
|
||||||
+#include <asm/string.h>
|
|
||||||
|
|
||||||
#include <prom.h>
|
|
||||||
|
|
|
@ -1,396 +0,0 @@
|
||||||
--- a/arch/mips/alchemy/Kconfig
|
|
||||||
+++ b/arch/mips/alchemy/Kconfig
|
|
||||||
@@ -134,3 +134,4 @@ config SOC_AU1X00
|
|
||||||
select SYS_HAS_CPU_MIPS32_R1
|
|
||||||
select SYS_SUPPORTS_32BIT_KERNEL
|
|
||||||
select SYS_SUPPORTS_APM_EMULATION
|
|
||||||
+ select ARCH_REQUIRE_GPIOLIB
|
|
||||||
--- a/arch/mips/alchemy/common/gpio.c
|
|
||||||
+++ b/arch/mips/alchemy/common/gpio.c
|
|
||||||
@@ -1,5 +1,5 @@
|
|
||||||
/*
|
|
||||||
- * Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
|
|
||||||
+ * Copyright (C) 2007-2008, OpenWrt.org, Florian Fainelli <florian@openwrt.org>
|
|
||||||
* Architecture specific GPIO support
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
@@ -27,122 +27,222 @@
|
|
||||||
* others have a second one : GPIO2
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+#include <linux/platform_device.h>
|
|
||||||
+#include <linux/gpio.h>
|
|
||||||
|
|
||||||
#include <asm/mach-au1x00/au1000.h>
|
|
||||||
-#include <asm/gpio.h>
|
|
||||||
+#include <asm/mach-au1x00/gpio.h>
|
|
||||||
|
|
||||||
-#define gpio1 sys
|
|
||||||
-#if !defined(CONFIG_SOC_AU1000)
|
|
||||||
+struct au1000_gpio_chip {
|
|
||||||
+ struct gpio_chip chip;
|
|
||||||
+ void __iomem *regbase;
|
|
||||||
+};
|
|
||||||
|
|
||||||
-static struct au1x00_gpio2 *const gpio2 = (struct au1x00_gpio2 *) GPIO2_BASE;
|
|
||||||
+#if !defined(CONFIG_SOC_AU1000)
|
|
||||||
#define GPIO2_OUTPUT_ENABLE_MASK 0x00010000
|
|
||||||
|
|
||||||
-static int au1xxx_gpio2_read(unsigned gpio)
|
|
||||||
+/*
|
|
||||||
+ * Return GPIO bank 2 level
|
|
||||||
+ */
|
|
||||||
+static int au1000_gpio2_get(struct gpio_chip *chip, unsigned offset)
|
|
||||||
{
|
|
||||||
- gpio -= AU1XXX_GPIO_BASE;
|
|
||||||
- return ((gpio2->pinstate >> gpio) & 0x01);
|
|
||||||
+ u32 mask = 1 << offset;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+ return readl(gpch->regbase + AU1000_GPIO2_ST) & mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void au1xxx_gpio2_write(unsigned gpio, int value)
|
|
||||||
+/*
|
|
||||||
+ * Set output GPIO bank 2 level
|
|
||||||
+ */
|
|
||||||
+static void au1000_gpio2_set(struct gpio_chip *chip,
|
|
||||||
+ unsigned offset, int value)
|
|
||||||
{
|
|
||||||
- gpio -= AU1XXX_GPIO_BASE;
|
|
||||||
-
|
|
||||||
- gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
|
|
||||||
+ u32 mask = (!!value) << offset;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+ unsigned long flags;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+
|
|
||||||
+ local_irq_save(flags);
|
|
||||||
+ writel((GPIO2_OUTPUT_ENABLE_MASK << offset) | mask,
|
|
||||||
+ gpch->regbase + AU1000_GPIO2_OUT);
|
|
||||||
+ local_irq_restore(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int au1xxx_gpio2_direction_input(unsigned gpio)
|
|
||||||
+/*
|
|
||||||
+ * Set GPIO bank 2 direction to input
|
|
||||||
+ */
|
|
||||||
+static int au1000_gpio2_direction_input(struct gpio_chip *chip, unsigned offset)
|
|
||||||
{
|
|
||||||
- gpio -= AU1XXX_GPIO_BASE;
|
|
||||||
- gpio2->dir &= ~(0x01 << gpio);
|
|
||||||
+ unsigned long flags;
|
|
||||||
+ u32 mask = 1 << offset;
|
|
||||||
+ u32 value;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+ void __iomem *gpdr;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+ gpdr = gpch->regbase + AU1000_GPIO2_DIR;
|
|
||||||
+
|
|
||||||
+ local_irq_save(flags);
|
|
||||||
+ value = readl(gpdr);
|
|
||||||
+ value &= ~mask;
|
|
||||||
+ writel(value, gpdr);
|
|
||||||
+ local_irq_restore(flags);
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int au1xxx_gpio2_direction_output(unsigned gpio, int value)
|
|
||||||
+/*
|
|
||||||
+ * Set GPIO bank2 direction to output
|
|
||||||
+ */
|
|
||||||
+static int au1000_gpio2_direction_output(struct gpio_chip *chip,
|
|
||||||
+ unsigned offset, int value)
|
|
||||||
{
|
|
||||||
- gpio -= AU1XXX_GPIO_BASE;
|
|
||||||
- gpio2->dir |= 0x01 << gpio;
|
|
||||||
- gpio2->output = (GPIO2_OUTPUT_ENABLE_MASK << gpio) | ((!!value) << gpio);
|
|
||||||
+ unsigned long flags;
|
|
||||||
+ u32 mask = 1 << offset;
|
|
||||||
+ u32 tmp;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+ void __iomem *gpdr;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+ gpdr = gpch->regbase + AU1000_GPIO2_DIR;
|
|
||||||
+
|
|
||||||
+ local_irq_save(flags);
|
|
||||||
+ tmp = readl(gpdr);
|
|
||||||
+ tmp |= mask;
|
|
||||||
+ writel(tmp, gpdr);
|
|
||||||
+ mask = (!!value) << offset;
|
|
||||||
+ writel((GPIO2_OUTPUT_ENABLE_MASK << offset) | mask,
|
|
||||||
+ gpch->regbase + AU1000_GPIO2_OUT);
|
|
||||||
+ local_irq_restore(flags);
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
#endif /* !defined(CONFIG_SOC_AU1000) */
|
|
||||||
|
|
||||||
-static int au1xxx_gpio1_read(unsigned gpio)
|
|
||||||
+/*
|
|
||||||
+ * Return GPIO bank 2 level
|
|
||||||
+ */
|
|
||||||
+static int au1000_gpio1_get(struct gpio_chip *chip, unsigned offset)
|
|
||||||
{
|
|
||||||
- return (gpio1->pinstaterd >> gpio) & 0x01;
|
|
||||||
+ u32 mask = 1 << offset;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+ return readl(gpch->regbase + 0x0110) & mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void au1xxx_gpio1_write(unsigned gpio, int value)
|
|
||||||
+/*
|
|
||||||
+ * Set GPIO bank 1 level
|
|
||||||
+ */
|
|
||||||
+static void au1000_gpio1_set(struct gpio_chip *chip,
|
|
||||||
+ unsigned offset, int value)
|
|
||||||
{
|
|
||||||
+ unsigned long flags;
|
|
||||||
+ u32 mask = 1 << offset;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+
|
|
||||||
+ local_irq_save(flags);
|
|
||||||
if (value)
|
|
||||||
- gpio1->outputset = (0x01 << gpio);
|
|
||||||
+ writel(mask, gpch->regbase + 0x0108);
|
|
||||||
else
|
|
||||||
- /* Output a zero */
|
|
||||||
- gpio1->outputclr = (0x01 << gpio);
|
|
||||||
+ writel(mask, gpch->regbase + 0x010C);
|
|
||||||
+ local_irq_restore(flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int au1xxx_gpio1_direction_input(unsigned gpio)
|
|
||||||
+/*
|
|
||||||
+ * Set GPIO bank 1 direction to input
|
|
||||||
+ */
|
|
||||||
+static int au1000_gpio1_direction_input(struct gpio_chip *chip, unsigned offset)
|
|
||||||
{
|
|
||||||
- gpio1->pininputen = (0x01 << gpio);
|
|
||||||
- return 0;
|
|
||||||
-}
|
|
||||||
+ unsigned long flags;
|
|
||||||
+ u32 mask = 1 << offset;
|
|
||||||
+ u32 value;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+ void __iomem *gpdr;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+ gpdr = gpch->regbase + 0x0110;
|
|
||||||
+
|
|
||||||
+ local_irq_save(flags);
|
|
||||||
+ value = readl(gpdr);
|
|
||||||
+ value |= mask;
|
|
||||||
+ writel(mask, gpdr);
|
|
||||||
+ local_irq_restore(flags);
|
|
||||||
|
|
||||||
-static int au1xxx_gpio1_direction_output(unsigned gpio, int value)
|
|
||||||
-{
|
|
||||||
- gpio1->trioutclr = (0x01 & gpio);
|
|
||||||
- au1xxx_gpio1_write(gpio, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-int au1xxx_gpio_get_value(unsigned gpio)
|
|
||||||
+/*
|
|
||||||
+ * Set GPIO bank 1 direction to output
|
|
||||||
+ */
|
|
||||||
+static int au1000_gpio1_direction_output(struct gpio_chip *chip,
|
|
||||||
+ unsigned offset, int value)
|
|
||||||
{
|
|
||||||
- if (gpio >= AU1XXX_GPIO_BASE)
|
|
||||||
-#if defined(CONFIG_SOC_AU1000)
|
|
||||||
- return 0;
|
|
||||||
-#else
|
|
||||||
- return au1xxx_gpio2_read(gpio);
|
|
||||||
-#endif
|
|
||||||
+ unsigned long flags;
|
|
||||||
+ u32 mask = 1 << offset;
|
|
||||||
+ u32 tmp;
|
|
||||||
+ struct au1000_gpio_chip *gpch;
|
|
||||||
+ void __iomem *gpdr;
|
|
||||||
+
|
|
||||||
+ gpch = container_of(chip, struct au1000_gpio_chip, chip);
|
|
||||||
+ gpdr = gpch->regbase + 0x0100;
|
|
||||||
+
|
|
||||||
+ local_irq_save(flags);
|
|
||||||
+ tmp = readl(gpdr);
|
|
||||||
+ writel(tmp, gpdr);
|
|
||||||
+ if (value)
|
|
||||||
+ writel(mask, gpch->regbase + 0x0108);
|
|
||||||
else
|
|
||||||
- return au1xxx_gpio1_read(gpio);
|
|
||||||
-}
|
|
||||||
-EXPORT_SYMBOL(au1xxx_gpio_get_value);
|
|
||||||
+ writel(mask, gpch->regbase + 0x0108);
|
|
||||||
+ local_irq_restore(flags);
|
|
||||||
|
|
||||||
-void au1xxx_gpio_set_value(unsigned gpio, int value)
|
|
||||||
-{
|
|
||||||
- if (gpio >= AU1XXX_GPIO_BASE)
|
|
||||||
-#if defined(CONFIG_SOC_AU1000)
|
|
||||||
- ;
|
|
||||||
-#else
|
|
||||||
- au1xxx_gpio2_write(gpio, value);
|
|
||||||
-#endif
|
|
||||||
- else
|
|
||||||
- au1xxx_gpio1_write(gpio, value);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
-EXPORT_SYMBOL(au1xxx_gpio_set_value);
|
|
||||||
|
|
||||||
-int au1xxx_gpio_direction_input(unsigned gpio)
|
|
||||||
-{
|
|
||||||
- if (gpio >= AU1XXX_GPIO_BASE)
|
|
||||||
-#if defined(CONFIG_SOC_AU1000)
|
|
||||||
- return -ENODEV;
|
|
||||||
-#else
|
|
||||||
- return au1xxx_gpio2_direction_input(gpio);
|
|
||||||
+struct au1000_gpio_chip au1000_gpio_chip[] = {
|
|
||||||
+ [0] = {
|
|
||||||
+ .regbase = (void __iomem *)SYS_BASE,
|
|
||||||
+ .chip = {
|
|
||||||
+ .label = "au1000-gpio1",
|
|
||||||
+ .direction_input = au1000_gpio1_direction_input,
|
|
||||||
+ .direction_output = au1000_gpio1_direction_output,
|
|
||||||
+ .get = au1000_gpio1_get,
|
|
||||||
+ .set = au1000_gpio1_set,
|
|
||||||
+ .base = 0,
|
|
||||||
+ .ngpio = 32,
|
|
||||||
+ },
|
|
||||||
+ },
|
|
||||||
+#if !defined(CONFIG_SOC_AU1000)
|
|
||||||
+ [1] = {
|
|
||||||
+ .regbase = (void __iomem *)GPIO2_BASE,
|
|
||||||
+ .chip = {
|
|
||||||
+ .label = "au1000-gpio2",
|
|
||||||
+ .direction_input = au1000_gpio2_direction_input,
|
|
||||||
+ .direction_output = au1000_gpio2_direction_output,
|
|
||||||
+ .get = au1000_gpio2_get,
|
|
||||||
+ .set = au1000_gpio2_set,
|
|
||||||
+ .base = AU1XXX_GPIO_BASE,
|
|
||||||
+ .ngpio = 32,
|
|
||||||
+ },
|
|
||||||
+ },
|
|
||||||
#endif
|
|
||||||
+};
|
|
||||||
|
|
||||||
- return au1xxx_gpio1_direction_input(gpio);
|
|
||||||
-}
|
|
||||||
-EXPORT_SYMBOL(au1xxx_gpio_direction_input);
|
|
||||||
-
|
|
||||||
-int au1xxx_gpio_direction_output(unsigned gpio, int value)
|
|
||||||
+int __init au1000_gpio_init(void)
|
|
||||||
{
|
|
||||||
- if (gpio >= AU1XXX_GPIO_BASE)
|
|
||||||
-#if defined(CONFIG_SOC_AU1000)
|
|
||||||
- return -ENODEV;
|
|
||||||
-#else
|
|
||||||
- return au1xxx_gpio2_direction_output(gpio, value);
|
|
||||||
+ gpiochip_add(&au1000_gpio_chip[0].chip);
|
|
||||||
+#if !defined(CONFIG_SOC_AU1000)
|
|
||||||
+ gpiochip_add(&au1000_gpio_chip[1].chip);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- return au1xxx_gpio1_direction_output(gpio, value);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
-EXPORT_SYMBOL(au1xxx_gpio_direction_output);
|
|
||||||
+arch_initcall(au1000_gpio_init);
|
|
||||||
--- a/arch/mips/include/asm/mach-au1x00/gpio.h
|
|
||||||
+++ b/arch/mips/include/asm/mach-au1x00/gpio.h
|
|
||||||
@@ -1,69 +1,21 @@
|
|
||||||
#ifndef _AU1XXX_GPIO_H_
|
|
||||||
#define _AU1XXX_GPIO_H_
|
|
||||||
|
|
||||||
-#include <linux/types.h>
|
|
||||||
-
|
|
||||||
#define AU1XXX_GPIO_BASE 200
|
|
||||||
|
|
||||||
-struct au1x00_gpio2 {
|
|
||||||
- u32 dir;
|
|
||||||
- u32 reserved;
|
|
||||||
- u32 output;
|
|
||||||
- u32 pinstate;
|
|
||||||
- u32 inten;
|
|
||||||
- u32 enable;
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-extern int au1xxx_gpio_get_value(unsigned gpio);
|
|
||||||
-extern void au1xxx_gpio_set_value(unsigned gpio, int value);
|
|
||||||
-extern int au1xxx_gpio_direction_input(unsigned gpio);
|
|
||||||
-extern int au1xxx_gpio_direction_output(unsigned gpio, int value);
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-/* Wrappers for the arch-neutral GPIO API */
|
|
||||||
-
|
|
||||||
-static inline int gpio_request(unsigned gpio, const char *label)
|
|
||||||
-{
|
|
||||||
- /* Not yet implemented */
|
|
||||||
- return 0;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline void gpio_free(unsigned gpio)
|
|
||||||
-{
|
|
||||||
- /* Not yet implemented */
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline int gpio_direction_input(unsigned gpio)
|
|
||||||
-{
|
|
||||||
- return au1xxx_gpio_direction_input(gpio);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline int gpio_direction_output(unsigned gpio, int value)
|
|
||||||
-{
|
|
||||||
- return au1xxx_gpio_direction_output(gpio, value);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline int gpio_get_value(unsigned gpio)
|
|
||||||
-{
|
|
||||||
- return au1xxx_gpio_get_value(gpio);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline void gpio_set_value(unsigned gpio, int value)
|
|
||||||
-{
|
|
||||||
- au1xxx_gpio_set_value(gpio, value);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline int gpio_to_irq(unsigned gpio)
|
|
||||||
-{
|
|
||||||
- return gpio;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static inline int irq_to_gpio(unsigned irq)
|
|
||||||
-{
|
|
||||||
- return irq;
|
|
||||||
-}
|
|
||||||
+#define AU1000_GPIO2_DIR 0x00
|
|
||||||
+#define AU1000_GPIO2_RSVD 0x04
|
|
||||||
+#define AU1000_GPIO2_OUT 0x08
|
|
||||||
+#define AU1000_GPIO2_ST 0x0C
|
|
||||||
+#define AU1000_GPIO2_INT 0x10
|
|
||||||
+#define AU1000_GPIO2_EN 0x14
|
|
||||||
+
|
|
||||||
+#define gpio_get_value __gpio_get_value
|
|
||||||
+#define gpio_set_value __gpio_set_value
|
|
||||||
+
|
|
||||||
+#define gpio_to_irq(gpio) NULL
|
|
||||||
+#define irq_to_gpio(irq) NULL
|
|
||||||
|
|
||||||
-/* For cansleep */
|
|
||||||
#include <asm-generic/gpio.h>
|
|
||||||
|
|
||||||
#endif /* _AU1XXX_GPIO_H_ */
|
|
|
@ -1,163 +0,0 @@
|
||||||
CONFIG_32BIT=y
|
|
||||||
# CONFIG_64BIT is not set
|
|
||||||
# CONFIG_8139TOO is not set
|
|
||||||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
|
||||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
|
||||||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
|
||||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
|
||||||
CONFIG_ARCH_SUPPORTS_OPROFILE=y
|
|
||||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
|
||||||
# CONFIG_ARPD is not set
|
|
||||||
CONFIG_B44_PCI_AUTOSELECT=y
|
|
||||||
CONFIG_B44_PCICORE_AUTOSELECT=y
|
|
||||||
CONFIG_B44_PCI=y
|
|
||||||
CONFIG_B44=y
|
|
||||||
CONFIG_BCM47XX_WDT=y
|
|
||||||
CONFIG_BCM47XX=y
|
|
||||||
CONFIG_BITREVERSE=y
|
|
||||||
# CONFIG_BSD_DISKLABEL is not set
|
|
||||||
# CONFIG_BSD_PROCESS_ACCT is not set
|
|
||||||
CONFIG_CEVT_R4K=y
|
|
||||||
CONFIG_CFE=y
|
|
||||||
CONFIG_CLASSIC_RCU=y
|
|
||||||
CONFIG_CMDLINE="root=/dev/mtdblock2 rootfstype=squashfs,jffs2 noinitrd console=ttyS0,115200"
|
|
||||||
# CONFIG_CPU_BIG_ENDIAN is not set
|
|
||||||
CONFIG_CPU_HAS_LLSC=y
|
|
||||||
CONFIG_CPU_HAS_PREFETCH=y
|
|
||||||
CONFIG_CPU_HAS_SYNC=y
|
|
||||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
|
||||||
# CONFIG_CPU_LOONGSON2 is not set
|
|
||||||
CONFIG_CPU_MIPS32_R1=y
|
|
||||||
# CONFIG_CPU_MIPS32_R2 is not set
|
|
||||||
CONFIG_CPU_MIPS32=y
|
|
||||||
# CONFIG_CPU_MIPS64_R1 is not set
|
|
||||||
# CONFIG_CPU_MIPS64_R2 is not set
|
|
||||||
CONFIG_CPU_MIPSR1=y
|
|
||||||
# CONFIG_CPU_NEVADA is not set
|
|
||||||
# CONFIG_CPU_R10000 is not set
|
|
||||||
# CONFIG_CPU_R3000 is not set
|
|
||||||
# CONFIG_CPU_R4300 is not set
|
|
||||||
# CONFIG_CPU_R4X00 is not set
|
|
||||||
# CONFIG_CPU_R5000 is not set
|
|
||||||
# CONFIG_CPU_R5432 is not set
|
|
||||||
# CONFIG_CPU_R5500 is not set
|
|
||||||
# CONFIG_CPU_R6000 is not set
|
|
||||||
# CONFIG_CPU_R8000 is not set
|
|
||||||
# CONFIG_CPU_RM7000 is not set
|
|
||||||
# CONFIG_CPU_RM9000 is not set
|
|
||||||
# CONFIG_CPU_SB1 is not set
|
|
||||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
|
|
||||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
|
||||||
# CONFIG_CPU_TX39XX is not set
|
|
||||||
# CONFIG_CPU_TX49XX is not set
|
|
||||||
# CONFIG_CPU_VR41XX is not set
|
|
||||||
CONFIG_CSRC_R4K=y
|
|
||||||
CONFIG_DEVPORT=y
|
|
||||||
# CONFIG_DM9000 is not set
|
|
||||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
|
||||||
CONFIG_DMA_NONCOHERENT=y
|
|
||||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
|
||||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
|
||||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
|
||||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
|
||||||
CONFIG_GENERIC_GPIO=y
|
|
||||||
# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set
|
|
||||||
# CONFIG_HAMRADIO is not set
|
|
||||||
CONFIG_HARDWARE_WATCHPOINTS=y
|
|
||||||
CONFIG_HAS_DMA=y
|
|
||||||
CONFIG_HAS_IOMEM=y
|
|
||||||
CONFIG_HAS_IOPORT=y
|
|
||||||
CONFIG_HAVE_ARCH_KGDB=y
|
|
||||||
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
|
|
||||||
CONFIG_HAVE_IDE=y
|
|
||||||
CONFIG_HAVE_OPROFILE=y
|
|
||||||
CONFIG_HW_HAS_PCI=y
|
|
||||||
CONFIG_HW_RANDOM=y
|
|
||||||
# CONFIG_HZ_100 is not set
|
|
||||||
CONFIG_HZ=250
|
|
||||||
CONFIG_HZ_250=y
|
|
||||||
# CONFIG_IDE is not set
|
|
||||||
CONFIG_INITRAMFS_SOURCE=""
|
|
||||||
# CONFIG_IP_ROUTE_VERBOSE is not set
|
|
||||||
CONFIG_IRQ_CPU=y
|
|
||||||
# CONFIG_ISDN is not set
|
|
||||||
CONFIG_KALLSYMS=y
|
|
||||||
CONFIG_LEDS_GPIO=y
|
|
||||||
# CONFIG_LEMOTE_FULONG is not set
|
|
||||||
# CONFIG_MACH_ALCHEMY is not set
|
|
||||||
# CONFIG_MACH_DECSTATION is not set
|
|
||||||
# CONFIG_MACH_EMMA is not set
|
|
||||||
# CONFIG_MACH_JAZZ is not set
|
|
||||||
# CONFIG_MACH_TX39XX is not set
|
|
||||||
# CONFIG_MACH_TX49XX is not set
|
|
||||||
# CONFIG_MACH_VR41XX is not set
|
|
||||||
# CONFIG_MIKROTIK_RB532 is not set
|
|
||||||
# CONFIG_MIPS_COBALT is not set
|
|
||||||
CONFIG_MIPS_L1_CACHE_SHIFT=5
|
|
||||||
# CONFIG_MIPS_MACHINE is not set
|
|
||||||
# CONFIG_MIPS_MALTA is not set
|
|
||||||
CONFIG_MIPS_MT_DISABLED=y
|
|
||||||
# CONFIG_MIPS_MT_SMP is not set
|
|
||||||
# CONFIG_MIPS_MT_SMTC is not set
|
|
||||||
# CONFIG_MIPS_SIM is not set
|
|
||||||
CONFIG_MIPS=y
|
|
||||||
CONFIG_MTD_BCM47XX=y
|
|
||||||
# CONFIG_NO_IOPORT is not set
|
|
||||||
# CONFIG_NXP_STB220 is not set
|
|
||||||
# CONFIG_NXP_STB225 is not set
|
|
||||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
|
||||||
CONFIG_PCI_DOMAINS=y
|
|
||||||
CONFIG_PHYLIB=y
|
|
||||||
# CONFIG_PMC_MSP is not set
|
|
||||||
# CONFIG_PMC_YOSEMITE is not set
|
|
||||||
# CONFIG_PNX8550_JBS is not set
|
|
||||||
# CONFIG_PNX8550_STB810 is not set
|
|
||||||
# CONFIG_PROBE_INITRD_HEADER is not set
|
|
||||||
# CONFIG_PROC_KCORE is not set
|
|
||||||
# CONFIG_R6040 is not set
|
|
||||||
CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y
|
|
||||||
# CONFIG_SCSI_DMA is not set
|
|
||||||
# CONFIG_SERIAL_8250_DETECT_IRQ is not set
|
|
||||||
CONFIG_SERIAL_8250_EXTENDED=y
|
|
||||||
# CONFIG_SERIAL_8250_MANY_PORTS is not set
|
|
||||||
# CONFIG_SERIAL_8250_RSA is not set
|
|
||||||
CONFIG_SERIAL_8250_SHARE_IRQ=y
|
|
||||||
# CONFIG_SGI_IP22 is not set
|
|
||||||
# CONFIG_SGI_IP27 is not set
|
|
||||||
# CONFIG_SGI_IP28 is not set
|
|
||||||
# CONFIG_SGI_IP32 is not set
|
|
||||||
# CONFIG_SIBYTE_BIGSUR is not set
|
|
||||||
# CONFIG_SIBYTE_CARMEL is not set
|
|
||||||
# CONFIG_SIBYTE_CRHINE is not set
|
|
||||||
# CONFIG_SIBYTE_CRHONE is not set
|
|
||||||
# CONFIG_SIBYTE_LITTLESUR is not set
|
|
||||||
# CONFIG_SIBYTE_RHONE is not set
|
|
||||||
# CONFIG_SIBYTE_SENTOSA is not set
|
|
||||||
# CONFIG_SIBYTE_SWARM is not set
|
|
||||||
CONFIG_SSB_B43_PCI_BRIDGE=y
|
|
||||||
CONFIG_SSB_DEBUG=y
|
|
||||||
CONFIG_SSB_DRIVER_EXTIF=y
|
|
||||||
CONFIG_SSB_DRIVER_GIGE=y
|
|
||||||
CONFIG_SSB_DRIVER_MIPS=y
|
|
||||||
CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y
|
|
||||||
CONFIG_SSB_DRIVER_PCICORE=y
|
|
||||||
CONFIG_SSB_EMBEDDED=y
|
|
||||||
CONFIG_SSB_PCICORE_HOSTMODE=y
|
|
||||||
CONFIG_SSB_PCIHOST_POSSIBLE=y
|
|
||||||
CONFIG_SSB_PCIHOST=y
|
|
||||||
CONFIG_SSB_SERIAL=y
|
|
||||||
CONFIG_SSB_SPROM=y
|
|
||||||
CONFIG_SSB=y
|
|
||||||
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
|
|
||||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
|
||||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
|
||||||
CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
|
|
||||||
# CONFIG_TC35815 is not set
|
|
||||||
CONFIG_TRAD_SIGNALS=y
|
|
||||||
CONFIG_USB_EHCI_HCD_SSB=y
|
|
||||||
CONFIG_USB_OHCI_HCD_SSB=y
|
|
||||||
CONFIG_USB_SUPPORT=y
|
|
||||||
# CONFIG_VGASTATE is not set
|
|
||||||
# CONFIG_VIA_RHINE is not set
|
|
||||||
CONFIG_WATCHDOG_NOWAYOUT=y
|
|
||||||
CONFIG_ZONE_DMA_FLAG=0
|
|
|
@ -1,25 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/bootinfo.h
|
|
||||||
+++ b/arch/mips/include/asm/bootinfo.h
|
|
||||||
@@ -57,6 +57,12 @@
|
|
||||||
#define MACH_MIKROTIK_RB532 0 /* Mikrotik RouterBoard 532 */
|
|
||||||
#define MACH_MIKROTIK_RB532A 1 /* Mikrotik RouterBoard 532A */
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Valid machtype for group Broadcom
|
|
||||||
+ */
|
|
||||||
+#define MACH_GROUP_BRCM 23 /* Broadcom */
|
|
||||||
+#define MACH_BCM47XX 1 /* Broadcom BCM47xx */
|
|
||||||
+
|
|
||||||
#define CL_SIZE COMMAND_LINE_SIZE
|
|
||||||
|
|
||||||
extern char *system_type;
|
|
||||||
--- a/include/linux/pci_ids.h
|
|
||||||
+++ b/include/linux/pci_ids.h
|
|
||||||
@@ -2069,6 +2069,7 @@
|
|
||||||
#define PCI_DEVICE_ID_TIGON3_5906M 0x1713
|
|
||||||
#define PCI_DEVICE_ID_BCM4401 0x4401
|
|
||||||
#define PCI_DEVICE_ID_BCM4401B0 0x4402
|
|
||||||
+#define PCI_DEVICE_ID_BCM4713 0x4713
|
|
||||||
|
|
||||||
#define PCI_VENDOR_ID_TOPIC 0x151f
|
|
||||||
#define PCI_DEVICE_ID_TOPIC_TP560 0x0000
|
|
|
@ -1,25 +0,0 @@
|
||||||
--- a/drivers/mtd/maps/Kconfig
|
|
||||||
+++ b/drivers/mtd/maps/Kconfig
|
|
||||||
@@ -332,6 +332,12 @@ config MTD_CFI_FLAGADM
|
|
||||||
Mapping for the Flaga digital module. If you don't have one, ignore
|
|
||||||
this setting.
|
|
||||||
|
|
||||||
+config MTD_BCM47XX
|
|
||||||
+ tristate "BCM47xx flash device"
|
|
||||||
+ depends on MIPS && MTD_CFI && BCM47XX
|
|
||||||
+ help
|
|
||||||
+ Support for the flash chips on the BCM947xx board.
|
|
||||||
+
|
|
||||||
config MTD_REDWOOD
|
|
||||||
tristate "CFI Flash devices mapped on IBM Redwood"
|
|
||||||
depends on MTD_CFI && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
|
|
||||||
--- a/drivers/mtd/maps/Makefile
|
|
||||||
+++ b/drivers/mtd/maps/Makefile
|
|
||||||
@@ -29,6 +29,7 @@ obj-$(CONFIG_MTD_PMC_MSP_RAMROOT)+= pmcm
|
|
||||||
obj-$(CONFIG_MTD_PCMCIA) += pcmciamtd.o
|
|
||||||
obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o
|
|
||||||
obj-$(CONFIG_MTD_TQM8XXL) += tqm8xxl.o
|
|
||||||
+obj-$(CONFIG_MTD_BCM47XX) += bcm47xx-flash.o
|
|
||||||
obj-$(CONFIG_MTD_SA1100) += sa1100-flash.o
|
|
||||||
obj-$(CONFIG_MTD_IPAQ) += ipaq-flash.o
|
|
||||||
obj-$(CONFIG_MTD_SBC_GXX) += sbc_gxx.o
|
|
|
@ -1,89 +0,0 @@
|
||||||
--- a/arch/mips/Kconfig
|
|
||||||
+++ b/arch/mips/Kconfig
|
|
||||||
@@ -198,7 +198,6 @@ config MIPS_MALTA
|
|
||||||
select I8259
|
|
||||||
select MIPS_BOARDS_GEN
|
|
||||||
select MIPS_BONITO64
|
|
||||||
- select MIPS_CPU_SCACHE
|
|
||||||
select PCI_GT64XXX_PCI0
|
|
||||||
select MIPS_MSC
|
|
||||||
select SWAP_IO_SPACE
|
|
||||||
@@ -1395,13 +1394,6 @@ config IP22_CPU_SCACHE
|
|
||||||
bool
|
|
||||||
select BOARD_SCACHE
|
|
||||||
|
|
||||||
-#
|
|
||||||
-# Support for a MIPS32 / MIPS64 style S-caches
|
|
||||||
-#
|
|
||||||
-config MIPS_CPU_SCACHE
|
|
||||||
- bool
|
|
||||||
- select BOARD_SCACHE
|
|
||||||
-
|
|
||||||
config R5000_CPU_SCACHE
|
|
||||||
bool
|
|
||||||
select BOARD_SCACHE
|
|
||||||
--- a/arch/mips/kernel/cpu-probe.c
|
|
||||||
+++ b/arch/mips/kernel/cpu-probe.c
|
|
||||||
@@ -755,6 +755,8 @@ static inline void cpu_probe_mips(struct
|
|
||||||
case PRID_IMP_25KF:
|
|
||||||
c->cputype = CPU_25KF;
|
|
||||||
__cpu_name[cpu] = "MIPS 25Kc";
|
|
||||||
+ /* Probe for L2 cache */
|
|
||||||
+ c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT;
|
|
||||||
break;
|
|
||||||
case PRID_IMP_34K:
|
|
||||||
c->cputype = CPU_34K;
|
|
||||||
--- a/arch/mips/mm/Makefile
|
|
||||||
+++ b/arch/mips/mm/Makefile
|
|
||||||
@@ -31,6 +31,5 @@ obj-$(CONFIG_CPU_VR41XX) += c-r4k.o cex-
|
|
||||||
obj-$(CONFIG_IP22_CPU_SCACHE) += sc-ip22.o
|
|
||||||
obj-$(CONFIG_R5000_CPU_SCACHE) += sc-r5k.o
|
|
||||||
obj-$(CONFIG_RM7000_CPU_SCACHE) += sc-rm7k.o
|
|
||||||
-obj-$(CONFIG_MIPS_CPU_SCACHE) += sc-mips.o
|
|
||||||
|
|
||||||
EXTRA_CFLAGS += -Werror
|
|
||||||
--- a/arch/mips/mm/c-r4k.c
|
|
||||||
+++ b/arch/mips/mm/c-r4k.c
|
|
||||||
@@ -1121,7 +1121,6 @@ static void __init loongson2_sc_init(voi
|
|
||||||
|
|
||||||
extern int r5k_sc_init(void);
|
|
||||||
extern int rm7k_sc_init(void);
|
|
||||||
-extern int mips_sc_init(void);
|
|
||||||
|
|
||||||
static void __cpuinit setup_scache(void)
|
|
||||||
{
|
|
||||||
@@ -1175,29 +1174,17 @@ static void __cpuinit setup_scache(void)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
- if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
|
|
||||||
- c->isa_level == MIPS_CPU_ISA_M32R2 ||
|
|
||||||
- c->isa_level == MIPS_CPU_ISA_M64R1 ||
|
|
||||||
- c->isa_level == MIPS_CPU_ISA_M64R2) {
|
|
||||||
-#ifdef CONFIG_MIPS_CPU_SCACHE
|
|
||||||
- if (mips_sc_init ()) {
|
|
||||||
- scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
|
|
||||||
- printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
|
|
||||||
- scache_size >> 10,
|
|
||||||
- way_string[c->scache.ways], c->scache.linesz);
|
|
||||||
- }
|
|
||||||
-#else
|
|
||||||
- if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
|
|
||||||
- panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
|
|
||||||
-#endif
|
|
||||||
- return;
|
|
||||||
- }
|
|
||||||
sc_present = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sc_present)
|
|
||||||
return;
|
|
||||||
|
|
||||||
+ if ((c->isa_level == MIPS_CPU_ISA_M32R1 ||
|
|
||||||
+ c->isa_level == MIPS_CPU_ISA_M64R1) &&
|
|
||||||
+ !(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
|
|
||||||
+ panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
|
|
||||||
+
|
|
||||||
/* compute a couple of other cache variables */
|
|
||||||
c->scache.waysize = scache_size / c->scache.ways;
|
|
||||||
|
|
|
@ -1,365 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/r4kcache.h
|
|
||||||
+++ b/arch/mips/include/asm/r4kcache.h
|
|
||||||
@@ -17,6 +17,20 @@
|
|
||||||
#include <asm/cpu-features.h>
|
|
||||||
#include <asm/mipsmtregs.h>
|
|
||||||
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+#include <asm/paccess.h>
|
|
||||||
+#include <linux/ssb/ssb.h>
|
|
||||||
+#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)))
|
|
||||||
+
|
|
||||||
+#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
|
|
||||||
+#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
|
|
||||||
+#else
|
|
||||||
+#define BCM4710_DUMMY_RREG()
|
|
||||||
+
|
|
||||||
+#define BCM4710_FILL_TLB(addr)
|
|
||||||
+#define BCM4710_PROTECTED_FILL_TLB(addr)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* This macro return a properly sign-extended address suitable as base address
|
|
||||||
* for indexed cache operations. Two issues here:
|
|
||||||
@@ -150,6 +164,7 @@ static inline void flush_icache_line_ind
|
|
||||||
static inline void flush_dcache_line_indexed(unsigned long addr)
|
|
||||||
{
|
|
||||||
__dflush_prologue
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
cache_op(Index_Writeback_Inv_D, addr);
|
|
||||||
__dflush_epilogue
|
|
||||||
}
|
|
||||||
@@ -169,6 +184,7 @@ static inline void flush_icache_line(uns
|
|
||||||
static inline void flush_dcache_line(unsigned long addr)
|
|
||||||
{
|
|
||||||
__dflush_prologue
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
cache_op(Hit_Writeback_Inv_D, addr);
|
|
||||||
__dflush_epilogue
|
|
||||||
}
|
|
||||||
@@ -176,6 +192,7 @@ static inline void flush_dcache_line(uns
|
|
||||||
static inline void invalidate_dcache_line(unsigned long addr)
|
|
||||||
{
|
|
||||||
__dflush_prologue
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
cache_op(Hit_Invalidate_D, addr);
|
|
||||||
__dflush_epilogue
|
|
||||||
}
|
|
||||||
@@ -208,6 +225,7 @@ static inline void flush_scache_line(uns
|
|
||||||
*/
|
|
||||||
static inline void protected_flush_icache_line(unsigned long addr)
|
|
||||||
{
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
protected_cache_op(Hit_Invalidate_I, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -219,6 +237,7 @@ static inline void protected_flush_icach
|
|
||||||
*/
|
|
||||||
static inline void protected_writeback_dcache_line(unsigned long addr)
|
|
||||||
{
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
protected_cache_op(Hit_Writeback_Inv_D, addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -339,8 +358,52 @@ static inline void invalidate_tcache_pag
|
|
||||||
: "r" (base), \
|
|
||||||
"i" (op));
|
|
||||||
|
|
||||||
+static inline void blast_dcache(void)
|
|
||||||
+{
|
|
||||||
+ unsigned long start = KSEG0;
|
|
||||||
+ unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways;
|
|
||||||
+ unsigned long end = (start + dcache_size);
|
|
||||||
+
|
|
||||||
+ do {
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
+ cache_op(Index_Writeback_Inv_D, start);
|
|
||||||
+ start += current_cpu_data.dcache.linesz;
|
|
||||||
+ } while(start < end);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void blast_dcache_page(unsigned long page)
|
|
||||||
+{
|
|
||||||
+ unsigned long start = page;
|
|
||||||
+ unsigned long end = start + PAGE_SIZE;
|
|
||||||
+
|
|
||||||
+ BCM4710_FILL_TLB(start);
|
|
||||||
+ do {
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
+ cache_op(Hit_Writeback_Inv_D, start);
|
|
||||||
+ start += current_cpu_data.dcache.linesz;
|
|
||||||
+ } while(start < end);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void blast_dcache_page_indexed(unsigned long page)
|
|
||||||
+{
|
|
||||||
+ unsigned long start = page;
|
|
||||||
+ unsigned long end = start + PAGE_SIZE;
|
|
||||||
+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
|
|
||||||
+ unsigned long ws_end = current_cpu_data.dcache.ways <<
|
|
||||||
+ current_cpu_data.dcache.waybit;
|
|
||||||
+ unsigned long ws, addr;
|
|
||||||
+ for (ws = 0; ws < ws_end; ws += ws_inc) {
|
|
||||||
+ start = page + ws;
|
|
||||||
+ for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) {
|
|
||||||
+ BCM4710_DUMMY_RREG();
|
|
||||||
+ cache_op(Index_Writeback_Inv_D, addr);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
/* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */
|
|
||||||
-#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize) \
|
|
||||||
+#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, war) \
|
|
||||||
static inline void blast_##pfx##cache##lsize(void) \
|
|
||||||
{ \
|
|
||||||
unsigned long start = INDEX_BASE; \
|
|
||||||
@@ -352,6 +415,7 @@ static inline void blast_##pfx##cache##l
|
|
||||||
\
|
|
||||||
__##pfx##flush_prologue \
|
|
||||||
\
|
|
||||||
+ war \
|
|
||||||
for (ws = 0; ws < ws_end; ws += ws_inc) \
|
|
||||||
for (addr = start; addr < end; addr += lsize * 32) \
|
|
||||||
cache##lsize##_unroll32(addr|ws, indexop); \
|
|
||||||
@@ -366,6 +430,7 @@ static inline void blast_##pfx##cache##l
|
|
||||||
\
|
|
||||||
__##pfx##flush_prologue \
|
|
||||||
\
|
|
||||||
+ war \
|
|
||||||
do { \
|
|
||||||
cache##lsize##_unroll32(start, hitop); \
|
|
||||||
start += lsize * 32; \
|
|
||||||
@@ -384,6 +449,8 @@ static inline void blast_##pfx##cache##l
|
|
||||||
current_cpu_data.desc.waybit; \
|
|
||||||
unsigned long ws, addr; \
|
|
||||||
\
|
|
||||||
+ war \
|
|
||||||
+ \
|
|
||||||
__##pfx##flush_prologue \
|
|
||||||
\
|
|
||||||
for (ws = 0; ws < ws_end; ws += ws_inc) \
|
|
||||||
@@ -393,35 +460,37 @@ static inline void blast_##pfx##cache##l
|
|
||||||
__##pfx##flush_epilogue \
|
|
||||||
}
|
|
||||||
|
|
||||||
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
|
|
||||||
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
|
|
||||||
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
|
|
||||||
-__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
|
|
||||||
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
|
|
||||||
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
|
|
||||||
-__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
|
|
||||||
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
|
|
||||||
-__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
|
|
||||||
-
|
|
||||||
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
|
|
||||||
-__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
|
|
||||||
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
|
|
||||||
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
|
|
||||||
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
|
|
||||||
-__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
|
|
||||||
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, )
|
|
||||||
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, BCM4710_FILL_TLB(start);)
|
|
||||||
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, )
|
|
||||||
+__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, )
|
|
||||||
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, BCM4710_FILL_TLB(start);)
|
|
||||||
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, )
|
|
||||||
+__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, BCM4710_FILL_TLB(start);)
|
|
||||||
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, )
|
|
||||||
+__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, )
|
|
||||||
+
|
|
||||||
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, )
|
|
||||||
+__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, )
|
|
||||||
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, )
|
|
||||||
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, )
|
|
||||||
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, )
|
|
||||||
+__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, )
|
|
||||||
|
|
||||||
/* build blast_xxx_range, protected_blast_xxx_range */
|
|
||||||
-#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
|
|
||||||
+#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, war, war2) \
|
|
||||||
static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
|
|
||||||
unsigned long end) \
|
|
||||||
{ \
|
|
||||||
unsigned long lsize = cpu_##desc##_line_size(); \
|
|
||||||
unsigned long addr = start & ~(lsize - 1); \
|
|
||||||
unsigned long aend = (end - 1) & ~(lsize - 1); \
|
|
||||||
+ war \
|
|
||||||
\
|
|
||||||
__##pfx##flush_prologue \
|
|
||||||
\
|
|
||||||
while (1) { \
|
|
||||||
+ war2 \
|
|
||||||
prot##cache_op(hitop, addr); \
|
|
||||||
if (addr == aend) \
|
|
||||||
break; \
|
|
||||||
@@ -431,13 +500,13 @@ static inline void prot##blast_##pfx##ca
|
|
||||||
__##pfx##flush_epilogue \
|
|
||||||
}
|
|
||||||
|
|
||||||
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
|
|
||||||
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
|
|
||||||
-__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
|
|
||||||
-__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
|
|
||||||
-__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
|
|
||||||
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
|
|
||||||
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_,, )
|
|
||||||
+__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_,, )
|
|
||||||
+__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D,, BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();)
|
|
||||||
+__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD,,, )
|
|
||||||
/* blast_inv_dcache_range */
|
|
||||||
-__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
|
|
||||||
-__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
|
|
||||||
+__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D,,,BCM4710_DUMMY_RREG();)
|
|
||||||
+__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD,,, )
|
|
||||||
|
|
||||||
#endif /* _ASM_R4KCACHE_H */
|
|
||||||
--- a/arch/mips/include/asm/stackframe.h
|
|
||||||
+++ b/arch/mips/include/asm/stackframe.h
|
|
||||||
@@ -409,6 +409,10 @@
|
|
||||||
.macro RESTORE_SP_AND_RET
|
|
||||||
LONG_L sp, PT_R29(sp)
|
|
||||||
.set mips3
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ nop
|
|
||||||
+ nop
|
|
||||||
+#endif
|
|
||||||
eret
|
|
||||||
.set mips0
|
|
||||||
.endm
|
|
||||||
--- a/arch/mips/kernel/genex.S
|
|
||||||
+++ b/arch/mips/kernel/genex.S
|
|
||||||
@@ -52,6 +52,10 @@ NESTED(except_vec1_generic, 0, sp)
|
|
||||||
NESTED(except_vec3_generic, 0, sp)
|
|
||||||
.set push
|
|
||||||
.set noat
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ nop
|
|
||||||
+ nop
|
|
||||||
+#endif
|
|
||||||
#if R5432_CP0_INTERRUPT_WAR
|
|
||||||
mfc0 k0, CP0_INDEX
|
|
||||||
#endif
|
|
||||||
--- a/arch/mips/mm/c-r4k.c
|
|
||||||
+++ b/arch/mips/mm/c-r4k.c
|
|
||||||
@@ -34,6 +34,9 @@
|
|
||||||
#include <asm/cacheflush.h> /* for run_uncached() */
|
|
||||||
|
|
||||||
|
|
||||||
+/* For enabling BCM4710 cache workarounds */
|
|
||||||
+int bcm4710 = 0;
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Special Variant of smp_call_function for use by cache functions:
|
|
||||||
*
|
|
||||||
@@ -104,6 +107,9 @@ static void __cpuinit r4k_blast_dcache_p
|
|
||||||
{
|
|
||||||
unsigned long dc_lsize = cpu_dcache_line_size();
|
|
||||||
|
|
||||||
+ if (bcm4710)
|
|
||||||
+ r4k_blast_dcache_page = blast_dcache_page;
|
|
||||||
+ else
|
|
||||||
if (dc_lsize == 0)
|
|
||||||
r4k_blast_dcache_page = (void *)cache_noop;
|
|
||||||
else if (dc_lsize == 16)
|
|
||||||
@@ -118,6 +124,9 @@ static void __cpuinit r4k_blast_dcache_p
|
|
||||||
{
|
|
||||||
unsigned long dc_lsize = cpu_dcache_line_size();
|
|
||||||
|
|
||||||
+ if (bcm4710)
|
|
||||||
+ r4k_blast_dcache_page_indexed = blast_dcache_page_indexed;
|
|
||||||
+ else
|
|
||||||
if (dc_lsize == 0)
|
|
||||||
r4k_blast_dcache_page_indexed = (void *)cache_noop;
|
|
||||||
else if (dc_lsize == 16)
|
|
||||||
@@ -132,6 +141,9 @@ static void __cpuinit r4k_blast_dcache_s
|
|
||||||
{
|
|
||||||
unsigned long dc_lsize = cpu_dcache_line_size();
|
|
||||||
|
|
||||||
+ if (bcm4710)
|
|
||||||
+ r4k_blast_dcache = blast_dcache;
|
|
||||||
+ else
|
|
||||||
if (dc_lsize == 0)
|
|
||||||
r4k_blast_dcache = (void *)cache_noop;
|
|
||||||
else if (dc_lsize == 16)
|
|
||||||
@@ -647,6 +659,8 @@ static void local_r4k_flush_cache_sigtra
|
|
||||||
unsigned long addr = (unsigned long) arg;
|
|
||||||
|
|
||||||
R4600_HIT_CACHEOP_WAR_IMPL;
|
|
||||||
+ BCM4710_PROTECTED_FILL_TLB(addr);
|
|
||||||
+ BCM4710_PROTECTED_FILL_TLB(addr + 4);
|
|
||||||
if (dc_lsize)
|
|
||||||
protected_writeback_dcache_line(addr & ~(dc_lsize - 1));
|
|
||||||
if (!cpu_icache_snoops_remote_store && scache_size)
|
|
||||||
@@ -1271,6 +1285,17 @@ static void __cpuinit coherency_setup(vo
|
|
||||||
* silly idea of putting something else there ...
|
|
||||||
*/
|
|
||||||
switch (current_cpu_type()) {
|
|
||||||
+ case CPU_BCM3302:
|
|
||||||
+ {
|
|
||||||
+ u32 cm;
|
|
||||||
+ cm = read_c0_diag();
|
|
||||||
+ /* Enable icache */
|
|
||||||
+ cm |= (1 << 31);
|
|
||||||
+ /* Enable dcache */
|
|
||||||
+ cm |= (1 << 30);
|
|
||||||
+ write_c0_diag(cm);
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
case CPU_R4000PC:
|
|
||||||
case CPU_R4000SC:
|
|
||||||
case CPU_R4000MC:
|
|
||||||
@@ -1328,6 +1353,15 @@ void __cpuinit r4k_cache_init(void)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Check if special workarounds are required */
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ if (current_cpu_data.cputype == CPU_BCM4710 && (current_cpu_data.processor_id & 0xff) == 0) {
|
|
||||||
+ printk("Enabling BCM4710A0 cache workarounds.\n");
|
|
||||||
+ bcm4710 = 1;
|
|
||||||
+ } else
|
|
||||||
+#endif
|
|
||||||
+ bcm4710 = 0;
|
|
||||||
+
|
|
||||||
probe_pcache();
|
|
||||||
setup_scache();
|
|
||||||
|
|
||||||
@@ -1386,5 +1420,13 @@ void __cpuinit r4k_cache_init(void)
|
|
||||||
#if !defined(CONFIG_MIPS_CMP)
|
|
||||||
local_r4k___flush_cache_all(NULL);
|
|
||||||
#endif
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ {
|
|
||||||
+ static void (*_coherency_setup)(void);
|
|
||||||
+ _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup);
|
|
||||||
+ _coherency_setup();
|
|
||||||
+ }
|
|
||||||
+#else
|
|
||||||
coherency_setup();
|
|
||||||
+#endif
|
|
||||||
}
|
|
||||||
--- a/arch/mips/mm/tlbex.c
|
|
||||||
+++ b/arch/mips/mm/tlbex.c
|
|
||||||
@@ -678,6 +678,9 @@ static void __cpuinit build_r4000_tlb_re
|
|
||||||
/* No need for uasm_i_nop */
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ uasm_i_nop(&p);
|
|
||||||
+#endif
|
|
||||||
#ifdef CONFIG_64BIT
|
|
||||||
build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
|
|
||||||
#else
|
|
||||||
@@ -1085,6 +1088,9 @@ build_r4000_tlbchange_handler_head(u32 *
|
|
||||||
struct uasm_reloc **r, unsigned int pte,
|
|
||||||
unsigned int ptr)
|
|
||||||
{
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ uasm_i_nop(p);
|
|
||||||
+#endif
|
|
||||||
#ifdef CONFIG_64BIT
|
|
||||||
build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
|
|
||||||
#else
|
|
|
@ -1,77 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/cpu-features.h
|
|
||||||
+++ b/arch/mips/include/asm/cpu-features.h
|
|
||||||
@@ -101,6 +101,9 @@
|
|
||||||
#ifndef cpu_has_pindexed_dcache
|
|
||||||
#define cpu_has_pindexed_dcache (cpu_data[0].dcache.flags & MIPS_CACHE_PINDEX)
|
|
||||||
#endif
|
|
||||||
+#ifndef cpu_use_kmap_coherent
|
|
||||||
+#define cpu_use_kmap_coherent 1
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* I-Cache snoops remote store. This only matters on SMP. Some multiprocessors
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/arch/mips/include/asm/mach-bcm47xx/cpu-feature-overrides.h
|
|
||||||
@@ -0,0 +1,13 @@
|
|
||||||
+/*
|
|
||||||
+ * This file is subject to the terms and conditions of the GNU General Public
|
|
||||||
+ * License. See the file "COPYING" in the main directory of this archive
|
|
||||||
+ * for more details.
|
|
||||||
+ *
|
|
||||||
+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
|
|
||||||
+ */
|
|
||||||
+#ifndef __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H
|
|
||||||
+#define __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H
|
|
||||||
+
|
|
||||||
+#define cpu_use_kmap_coherent 0
|
|
||||||
+
|
|
||||||
+#endif /* __ASM_MACH_BCM47XX_CPU_FEATURE_OVERRIDES_H */
|
|
||||||
--- a/arch/mips/mm/c-r4k.c
|
|
||||||
+++ b/arch/mips/mm/c-r4k.c
|
|
||||||
@@ -494,7 +494,7 @@ static inline void local_r4k_flush_cache
|
|
||||||
*/
|
|
||||||
map_coherent = (cpu_has_dc_aliases &&
|
|
||||||
page_mapped(page) && !Page_dcache_dirty(page));
|
|
||||||
- if (map_coherent)
|
|
||||||
+ if (map_coherent && cpu_use_kmap_coherent)
|
|
||||||
vaddr = kmap_coherent(page, addr);
|
|
||||||
else
|
|
||||||
vaddr = kmap_atomic(page, KM_USER0);
|
|
||||||
@@ -517,7 +517,7 @@ static inline void local_r4k_flush_cache
|
|
||||||
}
|
|
||||||
|
|
||||||
if (vaddr) {
|
|
||||||
- if (map_coherent)
|
|
||||||
+ if (map_coherent && cpu_use_kmap_coherent)
|
|
||||||
kunmap_coherent();
|
|
||||||
else
|
|
||||||
kunmap_atomic(vaddr, KM_USER0);
|
|
||||||
--- a/arch/mips/mm/init.c
|
|
||||||
+++ b/arch/mips/mm/init.c
|
|
||||||
@@ -212,7 +212,7 @@ void copy_user_highpage(struct page *to,
|
|
||||||
void *vfrom, *vto;
|
|
||||||
|
|
||||||
vto = kmap_atomic(to, KM_USER1);
|
|
||||||
- if (cpu_has_dc_aliases &&
|
|
||||||
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
|
|
||||||
page_mapped(from) && !Page_dcache_dirty(from)) {
|
|
||||||
vfrom = kmap_coherent(from, vaddr);
|
|
||||||
copy_page(vto, vfrom);
|
|
||||||
@@ -234,7 +234,7 @@ void copy_to_user_page(struct vm_area_st
|
|
||||||
struct page *page, unsigned long vaddr, void *dst, const void *src,
|
|
||||||
unsigned long len)
|
|
||||||
{
|
|
||||||
- if (cpu_has_dc_aliases &&
|
|
||||||
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
|
|
||||||
page_mapped(page) && !Page_dcache_dirty(page)) {
|
|
||||||
void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
|
|
||||||
memcpy(vto, src, len);
|
|
||||||
@@ -252,7 +252,7 @@ void copy_from_user_page(struct vm_area_
|
|
||||||
struct page *page, unsigned long vaddr, void *dst, const void *src,
|
|
||||||
unsigned long len)
|
|
||||||
{
|
|
||||||
- if (cpu_has_dc_aliases &&
|
|
||||||
+ if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
|
|
||||||
page_mapped(page) && !Page_dcache_dirty(page)) {
|
|
||||||
void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
|
|
||||||
memcpy(dst, vfrom, len);
|
|
|
@ -1,17 +0,0 @@
|
||||||
--- a/arch/mips/bcm47xx/prom.c
|
|
||||||
+++ b/arch/mips/bcm47xx/prom.c
|
|
||||||
@@ -141,6 +141,14 @@ static __init void prom_init_mem(void)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Ignoring the last page when ddr size is 128M. Cached
|
|
||||||
+ * accesses to last page is causing the processor to prefetch
|
|
||||||
+ * using address above 128M stepping out of the ddr address
|
|
||||||
+ * space.
|
|
||||||
+ */
|
|
||||||
+ if (mem == 0x8000000)
|
|
||||||
+ mem -= 0x1000;
|
|
||||||
+
|
|
||||||
add_memory_region(0, mem, BOOT_MEM_RAM);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
--- a/drivers/net/b44.c
|
|
||||||
+++ b/drivers/net/b44.c
|
|
||||||
@@ -339,7 +339,7 @@ static int b44_phy_reset(struct b44 *bp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- return 0;
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __b44_set_flow_ctrl(struct b44 *bp, u32 pause_flags)
|
|
||||||
@@ -384,7 +384,7 @@ static void b44_set_flow_ctrl(struct b44
|
|
||||||
__b44_set_flow_ctrl(bp, pause_enab);
|
|
||||||
}
|
|
||||||
|
|
||||||
-#ifdef SSB_DRIVER_MIPS
|
|
||||||
+#ifdef CONFIG_SSB_DRIVER_MIPS
|
|
||||||
extern char *nvram_get(char *name);
|
|
||||||
static void b44_wap54g10_workaround(struct b44 *bp)
|
|
||||||
{
|
|
||||||
@@ -2213,6 +2213,10 @@ static int __devinit b44_init_one(struct
|
|
||||||
*/
|
|
||||||
b44_chip_reset(bp, B44_CHIP_RESET_FULL);
|
|
||||||
|
|
||||||
+ /* do a phy reset to test if there is an active phy */
|
|
||||||
+ if (b44_phy_reset(bp) < 0)
|
|
||||||
+ bp->phy_addr = B44_PHY_ADDR_NO_PHY;
|
|
||||||
+
|
|
||||||
printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %s\n",
|
|
||||||
dev->name, print_mac(mac, dev->dev_addr));
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
--- a/drivers/net/b44.c
|
|
||||||
+++ b/drivers/net/b44.c
|
|
||||||
@@ -73,8 +73,8 @@
|
|
||||||
(BP)->tx_cons - (BP)->tx_prod - TX_RING_GAP(BP))
|
|
||||||
#define NEXT_TX(N) (((N) + 1) & (B44_TX_RING_SIZE - 1))
|
|
||||||
|
|
||||||
-#define RX_PKT_OFFSET 30
|
|
||||||
-#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET + 64)
|
|
||||||
+#define RX_PKT_OFFSET (RX_HEADER_LEN + 2)
|
|
||||||
+#define RX_PKT_BUF_SZ (1536 + RX_PKT_OFFSET)
|
|
||||||
|
|
||||||
/* minimum number of free TX descriptors required to wake up TX process */
|
|
||||||
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)
|
|
||||||
@@ -682,7 +682,6 @@ static int b44_alloc_rx_skb(struct b44 *
|
|
||||||
}
|
|
||||||
|
|
||||||
rh = (struct rx_header *) skb->data;
|
|
||||||
- skb_reserve(skb, RX_PKT_OFFSET);
|
|
||||||
|
|
||||||
rh->len = 0;
|
|
||||||
rh->flags = 0;
|
|
||||||
@@ -693,13 +692,13 @@ static int b44_alloc_rx_skb(struct b44 *
|
|
||||||
if (src_map != NULL)
|
|
||||||
src_map->skb = NULL;
|
|
||||||
|
|
||||||
- ctrl = (DESC_CTRL_LEN & (RX_PKT_BUF_SZ - RX_PKT_OFFSET));
|
|
||||||
+ ctrl = (DESC_CTRL_LEN & RX_PKT_BUF_SZ);
|
|
||||||
if (dest_idx == (B44_RX_RING_SIZE - 1))
|
|
||||||
ctrl |= DESC_CTRL_EOT;
|
|
||||||
|
|
||||||
dp = &bp->rx_ring[dest_idx];
|
|
||||||
dp->ctrl = cpu_to_le32(ctrl);
|
|
||||||
- dp->addr = cpu_to_le32((u32) mapping + RX_PKT_OFFSET + bp->dma_offset);
|
|
||||||
+ dp->addr = cpu_to_le32((u32) mapping + bp->dma_offset);
|
|
||||||
|
|
||||||
if (bp->flags & B44_FLAG_RX_RING_HACK)
|
|
||||||
b44_sync_dma_desc_for_device(bp->sdev, bp->rx_ring_dma,
|
|
||||||
@@ -809,8 +808,8 @@ static int b44_rx(struct b44 *bp, int bu
|
|
||||||
ssb_dma_unmap_single(bp->sdev, map,
|
|
||||||
skb_size, DMA_FROM_DEVICE);
|
|
||||||
/* Leave out rx_header */
|
|
||||||
- skb_put(skb, len + RX_PKT_OFFSET);
|
|
||||||
- skb_pull(skb, RX_PKT_OFFSET);
|
|
||||||
+ skb_put(skb, len + RX_PKT_OFFSET);
|
|
||||||
+ skb_pull(skb, RX_PKT_OFFSET);
|
|
||||||
} else {
|
|
||||||
struct sk_buff *copy_skb;
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
--- a/drivers/ssb/driver_chipcommon.c
|
|
||||||
+++ b/drivers/ssb/driver_chipcommon.c
|
|
||||||
@@ -258,6 +258,8 @@ void ssb_chipco_resume(struct ssb_chipco
|
|
||||||
void ssb_chipco_get_clockcpu(struct ssb_chipcommon *cc,
|
|
||||||
u32 *plltype, u32 *n, u32 *m)
|
|
||||||
{
|
|
||||||
+ if ((chipco_read32(cc, SSB_CHIPCO_CHIPID) & SSB_CHIPCO_IDMASK) == 0x5354)
|
|
||||||
+ return;
|
|
||||||
*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
|
|
||||||
*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
|
|
||||||
switch (*plltype) {
|
|
||||||
@@ -281,6 +283,8 @@ void ssb_chipco_get_clockcpu(struct ssb_
|
|
||||||
void ssb_chipco_get_clockcontrol(struct ssb_chipcommon *cc,
|
|
||||||
u32 *plltype, u32 *n, u32 *m)
|
|
||||||
{
|
|
||||||
+ if ((chipco_read32(cc, SSB_CHIPCO_CHIPID) & SSB_CHIPCO_IDMASK) == 0x5354)
|
|
||||||
+ return;
|
|
||||||
*n = chipco_read32(cc, SSB_CHIPCO_CLOCK_N);
|
|
||||||
*plltype = (cc->capabilities & SSB_CHIPCO_CAP_PLLT);
|
|
||||||
switch (*plltype) {
|
|
||||||
--- a/drivers/ssb/driver_mipscore.c
|
|
||||||
+++ b/drivers/ssb/driver_mipscore.c
|
|
||||||
@@ -161,6 +161,8 @@ u32 ssb_cpu_clock(struct ssb_mipscore *m
|
|
||||||
|
|
||||||
if ((pll_type == SSB_PLLTYPE_5) || (bus->chip_id == 0x5365)) {
|
|
||||||
rate = 200000000;
|
|
||||||
+ } else if (bus->chip_id == 0x5354) {
|
|
||||||
+ rate = 240000000;
|
|
||||||
} else {
|
|
||||||
rate = ssb_calc_clock_rate(pll_type, n, m);
|
|
||||||
}
|
|
||||||
--- a/drivers/ssb/main.c
|
|
||||||
+++ b/drivers/ssb/main.c
|
|
||||||
@@ -1013,6 +1013,8 @@ u32 ssb_clockspeed(struct ssb_bus *bus)
|
|
||||||
|
|
||||||
if (bus->chip_id == 0x5365) {
|
|
||||||
rate = 100000000;
|
|
||||||
+ } else if (bus->chip_id == 0x5354) {
|
|
||||||
+ rate = 120000000;
|
|
||||||
} else {
|
|
||||||
rate = ssb_calc_clock_rate(plltype, clkctl_n, clkctl_m);
|
|
||||||
if (plltype == SSB_PLLTYPE_3) /* 25Mhz, 2 dividers */
|
|
|
@ -1,60 +0,0 @@
|
||||||
---
|
|
||||||
drivers/usb/host/ohci-ssb.c | 39 ++++++++++++++++++++++++++++++++++++---
|
|
||||||
1 file changed, 36 insertions(+), 3 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/usb/host/ohci-ssb.c
|
|
||||||
+++ b/drivers/usb/host/ohci-ssb.c
|
|
||||||
@@ -106,10 +106,42 @@ static int ssb_ohci_attach(struct ssb_de
|
|
||||||
int err = -ENOMEM;
|
|
||||||
u32 tmp, flags = 0;
|
|
||||||
|
|
||||||
- if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV)
|
|
||||||
+ if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
|
|
||||||
+ /* Put the device into host-mode. */
|
|
||||||
flags |= SSB_OHCI_TMSLOW_HOSTMODE;
|
|
||||||
-
|
|
||||||
- ssb_device_enable(dev, flags);
|
|
||||||
+ ssb_device_enable(dev, flags);
|
|
||||||
+ } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
|
|
||||||
+ /*
|
|
||||||
+ * USB 2.0 special considerations:
|
|
||||||
+ *
|
|
||||||
+ * 1. Since the core supports both OHCI and EHCI functions, it must
|
|
||||||
+ * only be reset once.
|
|
||||||
+ *
|
|
||||||
+ * 2. In addition to the standard SSB reset sequence, the Host Control
|
|
||||||
+ * Register must be programmed to bring the USB core and various
|
|
||||||
+ * phy components out of reset.
|
|
||||||
+ */
|
|
||||||
+ ssb_device_enable(dev, 0);
|
|
||||||
+ ssb_write32(dev, 0x200, 0x7ff);
|
|
||||||
+ udelay(1);
|
|
||||||
+ if (dev->id.revision == 1) { // bug in rev 1
|
|
||||||
+
|
|
||||||
+ /* Change Flush control reg */
|
|
||||||
+ tmp = ssb_read32(dev, 0x400);
|
|
||||||
+ tmp &= ~8;
|
|
||||||
+ ssb_write32(dev, 0x400, tmp);
|
|
||||||
+ tmp = ssb_read32(dev, 0x400);
|
|
||||||
+ printk("USB20H fcr: 0x%0x\n", tmp);
|
|
||||||
+
|
|
||||||
+ /* Change Shim control reg */
|
|
||||||
+ tmp = ssb_read32(dev, 0x304);
|
|
||||||
+ tmp &= ~0x100;
|
|
||||||
+ ssb_write32(dev, 0x304, tmp);
|
|
||||||
+ tmp = ssb_read32(dev, 0x304);
|
|
||||||
+ printk("USB20H shim: 0x%0x\n", tmp);
|
|
||||||
+ }
|
|
||||||
+ } else
|
|
||||||
+ ssb_device_enable(dev, 0);
|
|
||||||
|
|
||||||
hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
|
|
||||||
dev_name(dev->dev));
|
|
||||||
@@ -200,6 +232,7 @@ static int ssb_ohci_resume(struct ssb_de
|
|
||||||
static const struct ssb_device_id ssb_ohci_table[] = {
|
|
||||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
|
|
||||||
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
|
|
||||||
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
|
|
||||||
SSB_DEVTABLE_END
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
|
|
|
@ -1,16 +0,0 @@
|
||||||
---
|
|
||||||
drivers/usb/host/ohci-ssb.c | 3 +++
|
|
||||||
1 file changed, 3 insertions(+)
|
|
||||||
|
|
||||||
--- a/drivers/usb/host/ohci-ssb.c
|
|
||||||
+++ b/drivers/usb/host/ohci-ssb.c
|
|
||||||
@@ -106,6 +106,9 @@ static int ssb_ohci_attach(struct ssb_de
|
|
||||||
int err = -ENOMEM;
|
|
||||||
u32 tmp, flags = 0;
|
|
||||||
|
|
||||||
+ if (ssb_dma_set_mask(dev, DMA_32BIT_MASK))
|
|
||||||
+ return -EOPNOTSUPP;
|
|
||||||
+
|
|
||||||
if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
|
|
||||||
/* Put the device into host-mode. */
|
|
||||||
flags |= SSB_OHCI_TMSLOW_HOSTMODE;
|
|
|
@ -1,314 +0,0 @@
|
||||||
---
|
|
||||||
drivers/usb/host/Kconfig | 13 ++
|
|
||||||
drivers/usb/host/ehci-hcd.c | 12 ++
|
|
||||||
drivers/usb/host/ehci-ssb.c | 201 ++++++++++++++++++++++++++++++++++++++++++++
|
|
||||||
drivers/usb/host/ohci-ssb.c | 23 +++++
|
|
||||||
4 files changed, 247 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/usb/host/Kconfig
|
|
||||||
+++ b/drivers/usb/host/Kconfig
|
|
||||||
@@ -96,6 +96,19 @@ config USB_EHCI_HCD_PPC_OF
|
|
||||||
Enables support for the USB controller present on the PowerPC
|
|
||||||
OpenFirmware platform bus.
|
|
||||||
|
|
||||||
+config USB_EHCI_HCD_SSB
|
|
||||||
+ bool "EHCI support for Broadcom SSB EHCI core"
|
|
||||||
+ depends on USB_EHCI_HCD && SSB && EXPERIMENTAL
|
|
||||||
+ default n
|
|
||||||
+ ---help---
|
|
||||||
+ Support for the Sonics Silicon Backplane (SSB) attached
|
|
||||||
+ Broadcom USB EHCI core.
|
|
||||||
+
|
|
||||||
+ This device is present in some embedded devices with
|
|
||||||
+ Broadcom based SSB bus.
|
|
||||||
+
|
|
||||||
+ If unsure, say N.
|
|
||||||
+
|
|
||||||
config USB_ISP116X_HCD
|
|
||||||
tristate "ISP116X HCD support"
|
|
||||||
depends on USB
|
|
||||||
--- a/drivers/usb/host/ehci-hcd.c
|
|
||||||
+++ b/drivers/usb/host/ehci-hcd.c
|
|
||||||
@@ -1036,8 +1036,16 @@ MODULE_LICENSE ("GPL");
|
|
||||||
#define PLATFORM_DRIVER ixp4xx_ehci_driver
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
|
|
||||||
- !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
|
|
||||||
+#ifdef CONFIG_USB_EHCI_HCD_SSB
|
|
||||||
+#include "ehci-ssb.c"
|
|
||||||
+#define SSB_EHCI_DRIVER ssb_ehci_driver
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#if !defined(PCI_DRIVER) && \
|
|
||||||
+ !defined(PLATFORM_DRIVER) && \
|
|
||||||
+ !defined(PS3_SYSTEM_BUS_DRIVER) && \
|
|
||||||
+ !defined(OF_PLATFORM_DRIVER) && \
|
|
||||||
+ !defined(SSB_EHCI_DRIVER)
|
|
||||||
#error "missing bus glue for ehci-hcd"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/usb/host/ehci-ssb.c
|
|
||||||
@@ -0,0 +1,201 @@
|
|
||||||
+/*
|
|
||||||
+ * Sonics Silicon Backplane
|
|
||||||
+ * Broadcom USB-core EHCI driver (SSB bus glue)
|
|
||||||
+ *
|
|
||||||
+ * Copyright 2007 Steven Brown <sbrown@cortland.com>
|
|
||||||
+ *
|
|
||||||
+ * Derived from the OHCI-SSB driver
|
|
||||||
+ * Copyright 2007 Michael Buesch <mb@bu3sch.de>
|
|
||||||
+ *
|
|
||||||
+ * Derived from the EHCI-PCI driver
|
|
||||||
+ * Copyright (c) 2000-2004 by David Brownell
|
|
||||||
+ *
|
|
||||||
+ * Derived from the OHCI-PCI driver
|
|
||||||
+ * Copyright 1999 Roman Weissgaerber
|
|
||||||
+ * Copyright 2000-2002 David Brownell
|
|
||||||
+ * Copyright 1999 Linus Torvalds
|
|
||||||
+ * Copyright 1999 Gregory P. Smith
|
|
||||||
+ *
|
|
||||||
+ * Derived from the USBcore related parts of Broadcom-SB
|
|
||||||
+ * Copyright 2005 Broadcom Corporation
|
|
||||||
+ *
|
|
||||||
+ * Licensed under the GNU/GPL. See COPYING for details.
|
|
||||||
+ */
|
|
||||||
+#include <linux/ssb/ssb.h>
|
|
||||||
+
|
|
||||||
+#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
|
|
||||||
+
|
|
||||||
+struct ssb_ehci_device {
|
|
||||||
+ struct ehci_hcd ehci; /* _must_ be at the beginning. */
|
|
||||||
+
|
|
||||||
+ u32 enable_flags;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static inline
|
|
||||||
+struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd)
|
|
||||||
+{
|
|
||||||
+ return (struct ssb_ehci_device *)(hcd->hcd_priv);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int ssb_ehci_reset(struct usb_hcd *hcd)
|
|
||||||
+{
|
|
||||||
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ ehci->caps = hcd->regs;
|
|
||||||
+ ehci->regs = hcd->regs +
|
|
||||||
+ HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
|
|
||||||
+
|
|
||||||
+ dbg_hcs_params(ehci, "reset");
|
|
||||||
+ dbg_hcc_params(ehci, "reset");
|
|
||||||
+
|
|
||||||
+ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
|
|
||||||
+
|
|
||||||
+ err = ehci_halt(ehci);
|
|
||||||
+
|
|
||||||
+ if (err)
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ err = ehci_init(hcd);
|
|
||||||
+
|
|
||||||
+ if (err)
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ ehci_port_power(ehci, 0);
|
|
||||||
+
|
|
||||||
+ return err;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int ssb_ehci_start(struct usb_hcd *hcd)
|
|
||||||
+{
|
|
||||||
+ struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ err = ehci_run(hcd);
|
|
||||||
+ if (err < 0) {
|
|
||||||
+ ehci_err(ehci, "can't start\n");
|
|
||||||
+ ehci_stop(hcd);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return err;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_PM
|
|
||||||
+static int ssb_ehci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message)
|
|
||||||
+{
|
|
||||||
+ struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd);
|
|
||||||
+ struct ehci_hcd *ehci = &ehcidev->ehci;
|
|
||||||
+ unsigned long flags;
|
|
||||||
+
|
|
||||||
+ spin_lock_irqsave(&ehci->lock, flags);
|
|
||||||
+
|
|
||||||
+ ehci_writel(ehci, EHCI_INTR_MIE, &ehci->regs->intrdisable);
|
|
||||||
+ ehci_readl(ehci, &ehci->regs->intrdisable); /* commit write */
|
|
||||||
+
|
|
||||||
+ /* make sure snapshot being resumed re-enumerates everything */
|
|
||||||
+ if (message.event == PM_EVENT_PRETHAW)
|
|
||||||
+ ehci_usb_reset(ehci);
|
|
||||||
+
|
|
||||||
+ clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
|
||||||
+
|
|
||||||
+ spin_unlock_irqrestore(&ehci->lock, flags);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int ssb_ehci_hcd_resume(struct usb_hcd *hcd)
|
|
||||||
+{
|
|
||||||
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
|
||||||
+ usb_hcd_resume_root_hub(hcd);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_PM */
|
|
||||||
+
|
|
||||||
+static const struct hc_driver ssb_ehci_hc_driver = {
|
|
||||||
+ .description = "ssb-usb-ehci",
|
|
||||||
+ .product_desc = "SSB EHCI Controller",
|
|
||||||
+ .hcd_priv_size = sizeof(struct ssb_ehci_device),
|
|
||||||
+
|
|
||||||
+ .irq = ehci_irq,
|
|
||||||
+ .flags = HCD_MEMORY | HCD_USB2,
|
|
||||||
+
|
|
||||||
+ .reset = ssb_ehci_reset,
|
|
||||||
+ .start = ssb_ehci_start,
|
|
||||||
+ .stop = ehci_stop,
|
|
||||||
+ .shutdown = ehci_shutdown,
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_PM
|
|
||||||
+ .suspend = ssb_ehci_hcd_suspend,
|
|
||||||
+ .resume = ssb_ehci_hcd_resume,
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ .urb_enqueue = ehci_urb_enqueue,
|
|
||||||
+ .urb_dequeue = ehci_urb_dequeue,
|
|
||||||
+ .endpoint_disable = ehci_endpoint_disable,
|
|
||||||
+
|
|
||||||
+ .get_frame_number = ehci_get_frame,
|
|
||||||
+
|
|
||||||
+ .hub_status_data = ehci_hub_status_data,
|
|
||||||
+ .hub_control = ehci_hub_control,
|
|
||||||
+#ifdef CONFIG_PM
|
|
||||||
+ .bus_suspend = ehci_bus_suspend,
|
|
||||||
+ .bus_resume = ehci_bus_resume,
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd)
|
|
||||||
+{
|
|
||||||
+
|
|
||||||
+ usb_remove_hcd(hcd);
|
|
||||||
+ iounmap(hcd->regs);
|
|
||||||
+ usb_put_hcd(hcd);
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(ssb_ehci_detach);
|
|
||||||
+
|
|
||||||
+static int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **ehci_hcd)
|
|
||||||
+{
|
|
||||||
+ struct ssb_ehci_device *ehcidev;
|
|
||||||
+ struct usb_hcd *hcd;
|
|
||||||
+ int err = -ENOMEM;
|
|
||||||
+ u32 tmp, flags = 0;
|
|
||||||
+
|
|
||||||
+ hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev,
|
|
||||||
+ dev->dev->bus_id);
|
|
||||||
+ if (!hcd)
|
|
||||||
+ goto err_dev_disable;
|
|
||||||
+
|
|
||||||
+ ehcidev = hcd_to_ssb_ehci(hcd);
|
|
||||||
+ ehcidev->enable_flags = flags;
|
|
||||||
+ tmp = ssb_read32(dev, SSB_ADMATCH0);
|
|
||||||
+ hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */
|
|
||||||
+ hcd->rsrc_len = 0x100; /* ehci reg block size */
|
|
||||||
+ /*
|
|
||||||
+ * start & size modified per sbutils.c
|
|
||||||
+ */
|
|
||||||
+ hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
|
|
||||||
+ if (!hcd->regs)
|
|
||||||
+ goto err_put_hcd;
|
|
||||||
+ err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED | IRQF_DISABLED);
|
|
||||||
+ if (err)
|
|
||||||
+ goto err_iounmap;
|
|
||||||
+
|
|
||||||
+ *ehci_hcd = hcd;
|
|
||||||
+
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+err_iounmap:
|
|
||||||
+ iounmap(hcd->regs);
|
|
||||||
+err_put_hcd:
|
|
||||||
+ usb_put_hcd(hcd);
|
|
||||||
+err_dev_disable:
|
|
||||||
+ ssb_device_disable(dev, flags);
|
|
||||||
+ return err;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(ssb_ehci_attach);
|
|
||||||
+
|
|
||||||
+static const struct ssb_device_id ssb_ehci_table[] = {
|
|
||||||
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
|
|
||||||
+ SSB_DEVTABLE_END
|
|
||||||
+};
|
|
||||||
+MODULE_DEVICE_TABLE(ssb, ssb_ehci_table);
|
|
||||||
--- a/drivers/usb/host/ohci-ssb.c
|
|
||||||
+++ b/drivers/usb/host/ohci-ssb.c
|
|
||||||
@@ -17,6 +17,8 @@
|
|
||||||
*/
|
|
||||||
#include <linux/ssb/ssb.h>
|
|
||||||
|
|
||||||
+extern int ssb_ehci_attach(struct ssb_device *dev, struct usb_hcd **hcd);
|
|
||||||
+extern void ssb_ehci_detach(struct ssb_device *dev, struct usb_hcd *hcd);
|
|
||||||
|
|
||||||
#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
|
|
||||||
|
|
||||||
@@ -24,6 +26,7 @@ struct ssb_ohci_device {
|
|
||||||
struct ohci_hcd ohci; /* _must_ be at the beginning. */
|
|
||||||
|
|
||||||
u32 enable_flags;
|
|
||||||
+ struct usb_hcd *ehci_hcd;
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline
|
|
||||||
@@ -92,13 +95,25 @@ static const struct hc_driver ssb_ohci_h
|
|
||||||
static void ssb_ohci_detach(struct ssb_device *dev)
|
|
||||||
{
|
|
||||||
struct usb_hcd *hcd = ssb_get_drvdata(dev);
|
|
||||||
+#ifdef CONFIG_USB_EHCI_HCD_SSB
|
|
||||||
+ struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
usb_remove_hcd(hcd);
|
|
||||||
iounmap(hcd->regs);
|
|
||||||
usb_put_hcd(hcd);
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_USB_EHCI_HCD_SSB
|
|
||||||
+ /*
|
|
||||||
+ * Also detach ehci function
|
|
||||||
+ */
|
|
||||||
+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
|
|
||||||
+ ssb_ehci_detach(dev, ohcidev->ehci_hcd);
|
|
||||||
+#endif
|
|
||||||
ssb_device_disable(dev, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
static int ssb_ohci_attach(struct ssb_device *dev)
|
|
||||||
{
|
|
||||||
struct ssb_ohci_device *ohcidev;
|
|
||||||
@@ -165,6 +180,14 @@ static int ssb_ohci_attach(struct ssb_de
|
|
||||||
|
|
||||||
ssb_set_drvdata(dev, hcd);
|
|
||||||
|
|
||||||
+#ifdef CONFIG_USB_EHCI_HCD_SSB
|
|
||||||
+ /*
|
|
||||||
+ * attach ehci function in this core
|
|
||||||
+ */
|
|
||||||
+ if (dev->id.coreid == SSB_DEV_USB20_HOST)
|
|
||||||
+ err = ssb_ehci_attach(dev, &(ohcidev->ehci_hcd));
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
return err;
|
|
||||||
|
|
||||||
err_iounmap:
|
|
|
@ -1,63 +0,0 @@
|
||||||
This patch significantly improves the reliability of high speed
|
|
||||||
usb writes on the bcm5354. It implements a work around for version 2
|
|
||||||
of the usb20 core that was cribbed from the GPL sources for the
|
|
||||||
Asus wl500gpv2 and verified against the wl520gu sources.
|
|
||||||
|
|
||||||
Reference:
|
|
||||||
GPL/WL-520gu-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
|
|
||||||
GPL/WL-500gPV2-NewUI/src/linux/linux/arch/mips/brcm-boards/bcm947xx/pcibios.c
|
|
||||||
|
|
||||||
Signed-off-by: Steve Brown <sbrown@cortland.com>
|
|
||||||
|
|
||||||
---
|
|
||||||
drivers/usb/host/ohci-ssb.c | 37 +++++++++++++++++++++++--------------
|
|
||||||
1 file changed, 23 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
--- a/drivers/usb/host/ohci-ssb.c
|
|
||||||
+++ b/drivers/usb/host/ohci-ssb.c
|
|
||||||
@@ -141,22 +141,31 @@ static int ssb_ohci_attach(struct ssb_de
|
|
||||||
*/
|
|
||||||
ssb_device_enable(dev, 0);
|
|
||||||
ssb_write32(dev, 0x200, 0x7ff);
|
|
||||||
+
|
|
||||||
+ /* Change Flush control reg */
|
|
||||||
+ tmp = ssb_read32(dev, 0x400);
|
|
||||||
+ tmp &= ~8;
|
|
||||||
+ ssb_write32(dev, 0x400, tmp);
|
|
||||||
+ tmp = ssb_read32(dev, 0x400);
|
|
||||||
+
|
|
||||||
+ /* Change Shim control reg */
|
|
||||||
+ tmp = ssb_read32(dev, 0x304);
|
|
||||||
+ tmp &= ~0x100;
|
|
||||||
+ ssb_write32(dev, 0x304, tmp);
|
|
||||||
+ tmp = ssb_read32(dev, 0x304);
|
|
||||||
+
|
|
||||||
udelay(1);
|
|
||||||
- if (dev->id.revision == 1) { // bug in rev 1
|
|
||||||
|
|
||||||
- /* Change Flush control reg */
|
|
||||||
- tmp = ssb_read32(dev, 0x400);
|
|
||||||
- tmp &= ~8;
|
|
||||||
- ssb_write32(dev, 0x400, tmp);
|
|
||||||
- tmp = ssb_read32(dev, 0x400);
|
|
||||||
- printk("USB20H fcr: 0x%0x\n", tmp);
|
|
||||||
-
|
|
||||||
- /* Change Shim control reg */
|
|
||||||
- tmp = ssb_read32(dev, 0x304);
|
|
||||||
- tmp &= ~0x100;
|
|
||||||
- ssb_write32(dev, 0x304, tmp);
|
|
||||||
- tmp = ssb_read32(dev, 0x304);
|
|
||||||
- printk("USB20H shim: 0x%0x\n", tmp);
|
|
||||||
+ /* Work around for 5354 failures */
|
|
||||||
+ if ((dev->id.revision == 2) && (dev->bus->chip_id == 0x5354)) {
|
|
||||||
+ /* Change syn01 reg */
|
|
||||||
+ tmp = 0x00fe00fe;
|
|
||||||
+ ssb_write32(dev, 0x894, tmp);
|
|
||||||
+
|
|
||||||
+ /* Change syn03 reg */
|
|
||||||
+ tmp = ssb_read32(dev, 0x89c);
|
|
||||||
+ tmp |= 0x1;
|
|
||||||
+ ssb_write32(dev, 0x89c, tmp);
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
ssb_device_enable(dev, 0);
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/cacheflush.h
|
|
||||||
+++ b/arch/mips/include/asm/cacheflush.h
|
|
||||||
@@ -32,7 +32,7 @@
|
|
||||||
extern void (*flush_cache_all)(void);
|
|
||||||
extern void (*__flush_cache_all)(void);
|
|
||||||
extern void (*flush_cache_mm)(struct mm_struct *mm);
|
|
||||||
-#define flush_cache_dup_mm(mm) do { (void) (mm); } while (0)
|
|
||||||
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
|
|
||||||
extern void (*flush_cache_range)(struct vm_area_struct *vma,
|
|
||||||
unsigned long start, unsigned long end);
|
|
||||||
extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
|
|
|
@ -1,31 +0,0 @@
|
||||||
--- a/arch/mips/mm/c-r4k.c
|
|
||||||
+++ b/arch/mips/mm/c-r4k.c
|
|
||||||
@@ -360,7 +360,7 @@ static inline void local_r4k___flush_cac
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void r4k___flush_cache_all(void)
|
|
||||||
+void r4k___flush_cache_all(void)
|
|
||||||
{
|
|
||||||
r4k_on_each_cpu(local_r4k___flush_cache_all, NULL, 1);
|
|
||||||
}
|
|
||||||
@@ -524,7 +524,7 @@ static inline void local_r4k_flush_cache
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void r4k_flush_cache_page(struct vm_area_struct *vma,
|
|
||||||
+void r4k_flush_cache_page(struct vm_area_struct *vma,
|
|
||||||
unsigned long addr, unsigned long pfn)
|
|
||||||
{
|
|
||||||
struct flush_cache_page_args args;
|
|
||||||
@@ -1430,3 +1430,10 @@ void __cpuinit r4k_cache_init(void)
|
|
||||||
coherency_setup();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+// fuse package DCACHE BUG patch exports
|
|
||||||
+void (*fuse_flush_cache_all)(void) = r4k___flush_cache_all;
|
|
||||||
+void (*fuse_flush_cache_page)(struct vm_area_struct *vma, unsigned long page,
|
|
||||||
+ unsigned long pfn) = r4k_flush_cache_page;
|
|
||||||
+EXPORT_SYMBOL(fuse_flush_cache_page);
|
|
||||||
+EXPORT_SYMBOL(fuse_flush_cache_all);
|
|
|
@ -1,82 +0,0 @@
|
||||||
--- a/fs/fuse/dev.c
|
|
||||||
+++ b/fs/fuse/dev.c
|
|
||||||
@@ -525,6 +525,11 @@ static void fuse_copy_finish(struct fuse
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef DCACHE_BUG
|
|
||||||
+extern void (*fuse_flush_cache_all)(void);
|
|
||||||
+extern void (*fuse_flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Get another pagefull of userspace buffer, and map it to kernel
|
|
||||||
* address space, and lock request
|
|
||||||
@@ -533,6 +538,9 @@ static int fuse_copy_fill(struct fuse_co
|
|
||||||
{
|
|
||||||
unsigned long offset;
|
|
||||||
int err;
|
|
||||||
+#ifdef DCACHE_BUG
|
|
||||||
+ struct vm_area_struct *vma;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
unlock_request(cs->fc, cs->req);
|
|
||||||
fuse_copy_finish(cs);
|
|
||||||
@@ -544,14 +552,22 @@ static int fuse_copy_fill(struct fuse_co
|
|
||||||
cs->nr_segs --;
|
|
||||||
}
|
|
||||||
down_read(¤t->mm->mmap_sem);
|
|
||||||
+#ifndef DCACHE_BUG
|
|
||||||
err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
|
|
||||||
&cs->pg, NULL);
|
|
||||||
+#else
|
|
||||||
+ err = get_user_pages(current, current->mm, cs->addr, 1, cs->write, 0,
|
|
||||||
+ &cs->pg, &vma);
|
|
||||||
+#endif
|
|
||||||
up_read(¤t->mm->mmap_sem);
|
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
BUG_ON(err != 1);
|
|
||||||
offset = cs->addr % PAGE_SIZE;
|
|
||||||
cs->mapaddr = kmap_atomic(cs->pg, KM_USER0);
|
|
||||||
+#ifdef DCACHE_BUG
|
|
||||||
+ fuse_flush_cache_page(vma, cs->addr, page_to_pfn(cs->pg));
|
|
||||||
+#endif
|
|
||||||
cs->buf = cs->mapaddr + offset;
|
|
||||||
cs->len = min(PAGE_SIZE - offset, cs->seglen);
|
|
||||||
cs->seglen -= cs->len;
|
|
||||||
@@ -565,6 +581,11 @@ static int fuse_copy_do(struct fuse_copy
|
|
||||||
{
|
|
||||||
unsigned ncpy = min(*size, cs->len);
|
|
||||||
if (val) {
|
|
||||||
+#ifdef DCACHE_BUG
|
|
||||||
+ // patch from mailing list, it is very important, otherwise,
|
|
||||||
+ // can't mount, or ls mount point will hang
|
|
||||||
+ fuse_flush_cache_all();
|
|
||||||
+#endif
|
|
||||||
if (cs->write)
|
|
||||||
memcpy(cs->buf, *val, ncpy);
|
|
||||||
else
|
|
||||||
--- a/fs/fuse/fuse_i.h
|
|
||||||
+++ b/fs/fuse/fuse_i.h
|
|
||||||
@@ -8,6 +8,7 @@
|
|
||||||
|
|
||||||
#ifndef _FS_FUSE_I_H
|
|
||||||
#define _FS_FUSE_I_H
|
|
||||||
+#define DCACHE_BUG
|
|
||||||
|
|
||||||
#include <linux/fuse.h>
|
|
||||||
#include <linux/fs.h>
|
|
||||||
--- a/fs/fuse/inode.c
|
|
||||||
+++ b/fs/fuse/inode.c
|
|
||||||
@@ -1038,6 +1038,10 @@ static int __init fuse_init(void)
|
|
||||||
printk("fuse init (API version %i.%i)\n",
|
|
||||||
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
|
|
||||||
|
|
||||||
+#ifdef DCACHE_BUG
|
|
||||||
+printk("fuse init: DCACHE_BUG enabled\n");
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
INIT_LIST_HEAD(&fuse_conn_list);
|
|
||||||
res = fuse_fs_init();
|
|
||||||
if (res)
|
|
|
@ -1,66 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/page.h
|
|
||||||
+++ b/arch/mips/include/asm/page.h
|
|
||||||
@@ -32,6 +32,7 @@
|
|
||||||
#ifndef __ASSEMBLY__
|
|
||||||
|
|
||||||
#include <linux/pfn.h>
|
|
||||||
+#include <asm/cpu-features.h>
|
|
||||||
#include <asm/io.h>
|
|
||||||
|
|
||||||
extern void build_clear_page(void);
|
|
||||||
@@ -67,13 +68,16 @@ static inline void clear_user_page(void
|
|
||||||
flush_data_cache_page((unsigned long)addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
-extern void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
|
|
||||||
- struct page *to);
|
|
||||||
-struct vm_area_struct;
|
|
||||||
-extern void copy_user_highpage(struct page *to, struct page *from,
|
|
||||||
- unsigned long vaddr, struct vm_area_struct *vma);
|
|
||||||
+static inline void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
|
|
||||||
+ struct page *to)
|
|
||||||
+{
|
|
||||||
+ extern void (*flush_data_cache_page)(unsigned long addr);
|
|
||||||
|
|
||||||
-#define __HAVE_ARCH_COPY_USER_HIGHPAGE
|
|
||||||
+ copy_page(vto, vfrom);
|
|
||||||
+ if (!cpu_has_ic_fills_f_dc ||
|
|
||||||
+ pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
|
|
||||||
+ flush_data_cache_page((unsigned long)vto);
|
|
||||||
+}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These are used to make use of C type-checking..
|
|
||||||
--- a/arch/mips/mm/init.c
|
|
||||||
+++ b/arch/mips/mm/init.c
|
|
||||||
@@ -206,30 +206,6 @@ void kunmap_coherent(void)
|
|
||||||
preempt_check_resched();
|
|
||||||
}
|
|
||||||
|
|
||||||
-void copy_user_highpage(struct page *to, struct page *from,
|
|
||||||
- unsigned long vaddr, struct vm_area_struct *vma)
|
|
||||||
-{
|
|
||||||
- void *vfrom, *vto;
|
|
||||||
-
|
|
||||||
- vto = kmap_atomic(to, KM_USER1);
|
|
||||||
- if (cpu_has_dc_aliases && cpu_use_kmap_coherent &&
|
|
||||||
- page_mapped(from) && !Page_dcache_dirty(from)) {
|
|
||||||
- vfrom = kmap_coherent(from, vaddr);
|
|
||||||
- copy_page(vto, vfrom);
|
|
||||||
- kunmap_coherent();
|
|
||||||
- } else {
|
|
||||||
- vfrom = kmap_atomic(from, KM_USER0);
|
|
||||||
- copy_page(vto, vfrom);
|
|
||||||
- kunmap_atomic(vfrom, KM_USER0);
|
|
||||||
- }
|
|
||||||
- if ((!cpu_has_ic_fills_f_dc) ||
|
|
||||||
- pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
|
|
||||||
- flush_data_cache_page((unsigned long)vto);
|
|
||||||
- kunmap_atomic(vto, KM_USER1);
|
|
||||||
- /* Make sure this page is cleared on other CPU's too before using it */
|
|
||||||
- smp_wmb();
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
void copy_to_user_page(struct vm_area_struct *vma,
|
|
||||||
struct page *page, unsigned long vaddr, void *dst, const void *src,
|
|
||||||
unsigned long len)
|
|
|
@ -1,319 +0,0 @@
|
||||||
--- a/arch/mips/Kconfig
|
|
||||||
+++ b/arch/mips/Kconfig
|
|
||||||
@@ -53,6 +53,7 @@ config BCM47XX
|
|
||||||
select SSB_DRIVER_MIPS
|
|
||||||
select SSB_DRIVER_EXTIF
|
|
||||||
select SSB_EMBEDDED
|
|
||||||
+ select SSB_B43_PCI_BRIDGE if PCI
|
|
||||||
select SSB_PCICORE_HOSTMODE if PCI
|
|
||||||
select GENERIC_GPIO
|
|
||||||
select SYS_HAS_EARLY_PRINTK
|
|
||||||
--- a/arch/mips/bcm47xx/Makefile
|
|
||||||
+++ b/arch/mips/bcm47xx/Makefile
|
|
||||||
@@ -3,4 +3,4 @@
|
|
||||||
# under Linux.
|
|
||||||
#
|
|
||||||
|
|
||||||
-obj-y := gpio.o irq.o prom.o serial.o setup.o time.o wgt634u.o
|
|
||||||
+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
|
|
||||||
--- a/arch/mips/bcm47xx/irq.c
|
|
||||||
+++ b/arch/mips/bcm47xx/irq.c
|
|
||||||
@@ -1,5 +1,6 @@
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
|
|
||||||
+ * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
@@ -23,10 +24,19 @@
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/types.h>
|
|
||||||
+#include <linux/errno.h>
|
|
||||||
+#include <linux/init.h>
|
|
||||||
#include <linux/interrupt.h>
|
|
||||||
#include <linux/irq.h>
|
|
||||||
+#include <linux/pci.h>
|
|
||||||
+#include <linux/ssb/ssb.h>
|
|
||||||
+
|
|
||||||
#include <asm/irq_cpu.h>
|
|
||||||
|
|
||||||
+
|
|
||||||
+extern struct ssb_bus ssb_bcm47xx;
|
|
||||||
+
|
|
||||||
+
|
|
||||||
void plat_irq_dispatch(void)
|
|
||||||
{
|
|
||||||
u32 cause;
|
|
||||||
--- a/arch/mips/bcm47xx/nvram.c
|
|
||||||
+++ b/arch/mips/bcm47xx/nvram.c
|
|
||||||
@@ -24,10 +24,10 @@
|
|
||||||
#include <asm/io.h>
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
|
|
||||||
-#include <nvram.h>
|
|
||||||
+#include "include/nvram.h"
|
|
||||||
|
|
||||||
#define MB * 1048576
|
|
||||||
-extern struct ssb_bus ssb;
|
|
||||||
+extern struct ssb_bus ssb_bcm47xx;
|
|
||||||
|
|
||||||
static char nvram_buf[NVRAM_SPACE];
|
|
||||||
static int cfe_env;
|
|
||||||
@@ -36,7 +36,7 @@ extern char *cfe_env_get(char *nv_buf, c
|
|
||||||
/* Probe for NVRAM header */
|
|
||||||
static void __init early_nvram_init(void)
|
|
||||||
{
|
|
||||||
- struct ssb_mipscore *mcore = &ssb.mipscore;
|
|
||||||
+ struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
|
|
||||||
struct nvram_header *header;
|
|
||||||
int i;
|
|
||||||
u32 base, lim, off;
|
|
||||||
--- a/arch/mips/bcm47xx/setup.c
|
|
||||||
+++ b/arch/mips/bcm47xx/setup.c
|
|
||||||
@@ -2,7 +2,7 @@
|
|
||||||
* Copyright (C) 2004 Florian Schirmer <jolt@tuxbox.org>
|
|
||||||
* Copyright (C) 2005 Waldemar Brodkorb <wbx@openwrt.org>
|
|
||||||
* Copyright (C) 2006 Felix Fietkau <nbd@openwrt.org>
|
|
||||||
- * Copyright (C) 2006 Michael Buesch <mb@bu3sch.de>
|
|
||||||
+ * Copyright (C) 2006-2008 Michael Buesch <mb@bu3sch.de>
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
@@ -25,18 +25,28 @@
|
|
||||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#include <linux/init.h>
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/ssb/ssb.h>
|
|
||||||
#include <linux/ssb/ssb_embedded.h>
|
|
||||||
+#include <linux/tty.h>
|
|
||||||
+#include <linux/serial.h>
|
|
||||||
+#include <linux/serial_core.h>
|
|
||||||
+#include <linux/serial_reg.h>
|
|
||||||
+#include <linux/serial_8250.h>
|
|
||||||
#include <asm/bootinfo.h>
|
|
||||||
#include <asm/reboot.h>
|
|
||||||
#include <asm/time.h>
|
|
||||||
-#include <bcm47xx.h>
|
|
||||||
#include <asm/fw/cfe/cfe_api.h>
|
|
||||||
+#include <linux/pm.h>
|
|
||||||
+
|
|
||||||
+#include "include/nvram.h"
|
|
||||||
|
|
||||||
struct ssb_bus ssb_bcm47xx;
|
|
||||||
EXPORT_SYMBOL(ssb_bcm47xx);
|
|
||||||
|
|
||||||
+extern void bcm47xx_pci_init(void);
|
|
||||||
+
|
|
||||||
static void bcm47xx_machine_restart(char *command)
|
|
||||||
{
|
|
||||||
printk(KERN_ALERT "Please stand by while rebooting the system...\n");
|
|
||||||
@@ -56,7 +66,7 @@ static void bcm47xx_machine_halt(void)
|
|
||||||
cpu_relax();
|
|
||||||
}
|
|
||||||
|
|
||||||
-static void str2eaddr(char *str, char *dest)
|
|
||||||
+static void e_aton(char *str, char *dest)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
@@ -73,52 +83,142 @@ static void str2eaddr(char *str, char *d
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int bcm47xx_get_invariants(struct ssb_bus *bus,
|
|
||||||
- struct ssb_init_invariants *iv)
|
|
||||||
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
|
|
||||||
{
|
|
||||||
- char buf[100];
|
|
||||||
+ char *s;
|
|
||||||
|
|
||||||
- /* Fill boardinfo structure */
|
|
||||||
- memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
|
|
||||||
+ memset(sprom, 0xFF, sizeof(struct ssb_sprom));
|
|
||||||
|
|
||||||
- if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0)
|
|
||||||
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
|
|
||||||
- if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0)
|
|
||||||
- iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
|
|
||||||
- if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0)
|
|
||||||
- iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
|
|
||||||
-
|
|
||||||
- /* Fill sprom structure */
|
|
||||||
- memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
|
|
||||||
- iv->sprom.revision = 3;
|
|
||||||
-
|
|
||||||
- if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
|
|
||||||
- str2eaddr(buf, iv->sprom.et0mac);
|
|
||||||
- if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
|
|
||||||
- str2eaddr(buf, iv->sprom.et1mac);
|
|
||||||
- if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
|
|
||||||
- iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 10);
|
|
||||||
- if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
|
|
||||||
- iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 10);
|
|
||||||
- if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
|
|
||||||
- iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
|
|
||||||
- if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
|
|
||||||
- iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
|
|
||||||
+ sprom->revision = 1;
|
|
||||||
+ if ((s = nvram_get("il0macaddr")))
|
|
||||||
+ e_aton(s, sprom->il0mac);
|
|
||||||
+ if ((s = nvram_get("et0macaddr")))
|
|
||||||
+ e_aton(s, sprom->et0mac);
|
|
||||||
+ if ((s = nvram_get("et1macaddr")))
|
|
||||||
+ e_aton(s, sprom->et1mac);
|
|
||||||
+ if ((s = nvram_get("et0phyaddr")))
|
|
||||||
+ sprom->et0phyaddr = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("et1phyaddr")))
|
|
||||||
+ sprom->et1phyaddr = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("et0mdcport")))
|
|
||||||
+ sprom->et0mdcport = !!simple_strtoul(s, NULL, 10);
|
|
||||||
+ if ((s = nvram_get("et1mdcport")))
|
|
||||||
+ sprom->et1mdcport = !!simple_strtoul(s, NULL, 10);
|
|
||||||
+ if ((s = nvram_get("pa0b0")))
|
|
||||||
+ sprom->pa0b0 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa0b1")))
|
|
||||||
+ sprom->pa0b1 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa0b2")))
|
|
||||||
+ sprom->pa0b2 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa1b0")))
|
|
||||||
+ sprom->pa1b0 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa1b1")))
|
|
||||||
+ sprom->pa1b1 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa1b2")))
|
|
||||||
+ sprom->pa1b2 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("wl0gpio0")))
|
|
||||||
+ sprom->gpio0 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("wl0gpio1")))
|
|
||||||
+ sprom->gpio1 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("wl0gpio2")))
|
|
||||||
+ sprom->gpio2 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("wl0gpio3")))
|
|
||||||
+ sprom->gpio3 = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa0maxpwr")))
|
|
||||||
+ sprom->maxpwr_bg = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa1maxpwr")))
|
|
||||||
+ sprom->maxpwr_a = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa0itssit")))
|
|
||||||
+ sprom->itssi_bg = simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("pa1itssit")))
|
|
||||||
+ sprom->itssi_a = simple_strtoul(s, NULL, 0);
|
|
||||||
+ sprom->boardflags_lo = 0;
|
|
||||||
+ if ((s = nvram_get("boardflags")))
|
|
||||||
+ sprom->boardflags_lo = simple_strtoul(s, NULL, 0);
|
|
||||||
+ sprom->boardflags_hi = 0;
|
|
||||||
+ if ((s = nvram_get("boardflags2")))
|
|
||||||
+ sprom->boardflags_hi = simple_strtoul(s, NULL, 0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int bcm47xx_get_invariants(struct ssb_bus *bus, struct ssb_init_invariants *iv)
|
|
||||||
+{
|
|
||||||
+ char *s;
|
|
||||||
+
|
|
||||||
+ iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
|
|
||||||
+ if ((s = nvram_get("boardtype")))
|
|
||||||
+ iv->boardinfo.type = (u16)simple_strtoul(s, NULL, 0);
|
|
||||||
+ if ((s = nvram_get("boardrev")))
|
|
||||||
+ iv->boardinfo.rev = (u16)simple_strtoul(s, NULL, 0);
|
|
||||||
+
|
|
||||||
+ bcm47xx_fill_sprom(&iv->sprom);
|
|
||||||
+
|
|
||||||
+ if ((s = nvram_get("cardbus")))
|
|
||||||
+ iv->has_cardbus_slot = !!simple_strtoul(s, NULL, 10);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void __init plat_mem_setup(void)
|
|
||||||
{
|
|
||||||
- int err;
|
|
||||||
+ int i, err;
|
|
||||||
+ char *s;
|
|
||||||
+ struct ssb_mipscore *mcore;
|
|
||||||
+
|
|
||||||
+ err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE, bcm47xx_get_invariants);
|
|
||||||
+ if (err) {
|
|
||||||
+ const char *msg = "Failed to initialize SSB bus (err %d)\n";
|
|
||||||
+ printk(msg, err); /* Make sure the message gets out of the box. */
|
|
||||||
+ panic(msg, err);
|
|
||||||
+ }
|
|
||||||
+ mcore = &ssb_bcm47xx.mipscore;
|
|
||||||
|
|
||||||
- err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
|
|
||||||
- bcm47xx_get_invariants);
|
|
||||||
- if (err)
|
|
||||||
- panic("Failed to initialize SSB bus (err %d)\n", err);
|
|
||||||
+ s = nvram_get("kernel_args");
|
|
||||||
+ if (s && !strncmp(s, "console=ttyS1", 13)) {
|
|
||||||
+ struct ssb_serial_port port;
|
|
||||||
+
|
|
||||||
+ printk("Swapping serial ports!\n");
|
|
||||||
+ /* swap serial ports */
|
|
||||||
+ memcpy(&port, &mcore->serial_ports[0], sizeof(port));
|
|
||||||
+ memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1], sizeof(port));
|
|
||||||
+ memcpy(&mcore->serial_ports[1], &port, sizeof(port));
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (i = 0; i < mcore->nr_serial_ports; i++) {
|
|
||||||
+ struct ssb_serial_port *port = &(mcore->serial_ports[i]);
|
|
||||||
+ struct uart_port s;
|
|
||||||
+
|
|
||||||
+ memset(&s, 0, sizeof(s));
|
|
||||||
+ s.line = i;
|
|
||||||
+ s.mapbase = (unsigned int) port->regs;
|
|
||||||
+ s.membase = port->regs;
|
|
||||||
+ s.irq = port->irq + 2;
|
|
||||||
+ s.uartclk = port->baud_base;
|
|
||||||
+ s.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
|
|
||||||
+ s.iotype = SERIAL_IO_MEM;
|
|
||||||
+ s.regshift = port->reg_shift;
|
|
||||||
+
|
|
||||||
+ early_serial_setup(&s);
|
|
||||||
+ }
|
|
||||||
+ printk("Serial init done.\n");
|
|
||||||
|
|
||||||
_machine_restart = bcm47xx_machine_restart;
|
|
||||||
_machine_halt = bcm47xx_machine_halt;
|
|
||||||
pm_power_off = bcm47xx_machine_halt;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int __init bcm47xx_register_gpiodev(void)
|
|
||||||
+{
|
|
||||||
+ static struct resource res = {
|
|
||||||
+ .start = 0xFFFFFFFF,
|
|
||||||
+ };
|
|
||||||
+ struct platform_device *pdev;
|
|
||||||
+
|
|
||||||
+ pdev = platform_device_register_simple("GPIODEV", 0, &res, 1);
|
|
||||||
+ if (!pdev) {
|
|
||||||
+ printk(KERN_ERR "bcm47xx: GPIODEV init failed\n");
|
|
||||||
+ return -ENODEV;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+device_initcall(bcm47xx_register_gpiodev);
|
|
||||||
--- a/arch/mips/bcm47xx/time.c
|
|
||||||
+++ b/arch/mips/bcm47xx/time.c
|
|
||||||
@@ -22,11 +22,17 @@
|
|
||||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
-
|
|
||||||
#include <linux/init.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/sched.h>
|
|
||||||
+#include <linux/serial_reg.h>
|
|
||||||
+#include <linux/interrupt.h>
|
|
||||||
#include <linux/ssb/ssb.h>
|
|
||||||
+#include <asm/addrspace.h>
|
|
||||||
+#include <asm/io.h>
|
|
||||||
#include <asm/time.h>
|
|
||||||
-#include <bcm47xx.h>
|
|
||||||
+
|
|
||||||
+extern struct ssb_bus ssb_bcm47xx;
|
|
||||||
|
|
||||||
void __init plat_time_init(void)
|
|
||||||
{
|
|
|
@ -1,125 +0,0 @@
|
||||||
--- a/init/initramfs.c
|
|
||||||
+++ b/init/initramfs.c
|
|
||||||
@@ -7,6 +7,7 @@
|
|
||||||
#include <linux/string.h>
|
|
||||||
#include <linux/syscalls.h>
|
|
||||||
#include <linux/utime.h>
|
|
||||||
+#include <linux/vmalloc.h>
|
|
||||||
|
|
||||||
static __initdata char *message;
|
|
||||||
static void __init error(char *x)
|
|
||||||
@@ -475,6 +476,69 @@ static void __init flush_window(void)
|
|
||||||
outcnt = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#include <linux/LzmaDecode.h>
|
|
||||||
+static int __init lzma_unzip(void)
|
|
||||||
+{
|
|
||||||
+ unsigned int i; /* temp value */
|
|
||||||
+ unsigned int lc; /* literal context bits */
|
|
||||||
+ unsigned int lp; /* literal pos state bits */
|
|
||||||
+ unsigned int pb; /* pos state bits */
|
|
||||||
+ unsigned int osize; /* uncompressed size */
|
|
||||||
+ unsigned char *workspace;
|
|
||||||
+ unsigned char* outputbuffer;
|
|
||||||
+ unsigned int outsizeProcessed = 0;
|
|
||||||
+ int workspace_size;
|
|
||||||
+ int res;
|
|
||||||
+
|
|
||||||
+ // lzma args
|
|
||||||
+ i = get_byte();
|
|
||||||
+ lc = i % 9, i = i / 9;
|
|
||||||
+ lp = i % 5, pb = i / 5;
|
|
||||||
+
|
|
||||||
+ // skip dictionary size
|
|
||||||
+ for (i = 0; i < 4; i++)
|
|
||||||
+ get_byte();
|
|
||||||
+
|
|
||||||
+ /* read the lower half of uncompressed size in the header */
|
|
||||||
+ osize = ((unsigned int)get_byte()) +
|
|
||||||
+ ((unsigned int)get_byte() << 8) +
|
|
||||||
+ ((unsigned int)get_byte() << 16) +
|
|
||||||
+ ((unsigned int)get_byte() << 24);
|
|
||||||
+
|
|
||||||
+ /* skip rest of the header (upper half of uncompressed size) */
|
|
||||||
+ for (i = 0; i < 4; i++)
|
|
||||||
+ get_byte();
|
|
||||||
+
|
|
||||||
+ workspace_size = ((LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp))) * sizeof(CProb)) + 100;
|
|
||||||
+ printk( KERN_NOTICE "initramfs: LZMA lc=%d,lp=%d,pb=%d,origSize=%d\n",
|
|
||||||
+ lc,lp,pb,osize);
|
|
||||||
+ outputbuffer = vmalloc(osize);
|
|
||||||
+ if (outputbuffer == 0) {
|
|
||||||
+ printk(KERN_ERR "initramfs: Couldn't allocate lzma output buffer\n");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ workspace = vmalloc(workspace_size);
|
|
||||||
+ if (workspace == NULL) {
|
|
||||||
+ printk(KERN_ERR "initramfs: Couldn't allocate lzma workspace\n");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ res = LzmaDecode(workspace, workspace_size, lc, lp, pb, inbuf + inptr, insize - inptr, outputbuffer, osize, &outsizeProcessed);
|
|
||||||
+ if( res != 0 ) {
|
|
||||||
+ panic( KERN_ERR "initramfs: Lzma decode failure\n");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ flush_buffer(outputbuffer, outsizeProcessed);
|
|
||||||
+ inptr = insize;
|
|
||||||
+
|
|
||||||
+ vfree(outputbuffer);
|
|
||||||
+ vfree(workspace);
|
|
||||||
+ state = Reset;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static char * __init unpack_to_rootfs(char *buf, unsigned len, int check_only)
|
|
||||||
{
|
|
||||||
int written;
|
|
||||||
@@ -509,12 +573,28 @@ static char * __init unpack_to_rootfs(ch
|
|
||||||
inptr = 0;
|
|
||||||
outcnt = 0; /* bytes in output buffer */
|
|
||||||
bytes_out = 0;
|
|
||||||
- crc = (ulg)0xffffffffL; /* shift register contents */
|
|
||||||
- makecrc();
|
|
||||||
- gunzip();
|
|
||||||
- if (state != Reset)
|
|
||||||
+ if( inbuf[0] == 037 && ((inbuf[1] == 0213) || (inbuf[1] == 0236)))
|
|
||||||
+ {
|
|
||||||
+ printk( KERN_NOTICE "detected gzip initramfs\n");
|
|
||||||
+ crc = (ulg)0xffffffffL; /* shift register contents */
|
|
||||||
+ makecrc();
|
|
||||||
+ gunzip();
|
|
||||||
+ if (state != Reset)
|
|
||||||
error("junk in gzipped archive");
|
|
||||||
- this_header = saved_offset + inptr;
|
|
||||||
+ }
|
|
||||||
+ else if(!memcmp(inbuf+1, "\x00\x00\x80\x00", 4)) /* FIXME: hardcoded dictionary size */
|
|
||||||
+ {
|
|
||||||
+ printk( KERN_NOTICE "detected lzma initramfs\n");
|
|
||||||
+ lzma_unzip();
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ // skip forward ?
|
|
||||||
+ crc = (ulg)0xffffffffL; /* shift register contents */
|
|
||||||
+ makecrc();
|
|
||||||
+ gunzip();
|
|
||||||
+ }
|
|
||||||
+ this_header = saved_offset + inptr;
|
|
||||||
buf += inptr;
|
|
||||||
len -= inptr;
|
|
||||||
}
|
|
||||||
--- a/scripts/gen_initramfs_list.sh
|
|
||||||
+++ b/scripts/gen_initramfs_list.sh
|
|
||||||
@@ -287,7 +287,7 @@ if [ ! -z ${output_file} ]; then
|
|
||||||
if [ "${is_cpio_compressed}" = "compressed" ]; then
|
|
||||||
cat ${cpio_tfile} > ${output_file}
|
|
||||||
else
|
|
||||||
- cat ${cpio_tfile} | gzip -f -9 - > ${output_file}
|
|
||||||
+ lzma e -lc1 -lp2 -pb2 ${cpio_tfile} ${output_file}
|
|
||||||
fi
|
|
||||||
[ -z ${cpio_file} ] && rm ${cpio_tfile}
|
|
||||||
fi
|
|
|
@ -1,18 +0,0 @@
|
||||||
--- a/arch/mips/pci/pci.c
|
|
||||||
+++ b/arch/mips/pci/pci.c
|
|
||||||
@@ -207,12 +207,10 @@ static int pcibios_enable_resources(stru
|
|
||||||
if ((idx == PCI_ROM_RESOURCE) &&
|
|
||||||
(!(r->flags & IORESOURCE_ROM_ENABLE)))
|
|
||||||
continue;
|
|
||||||
- if (!r->start && r->end) {
|
|
||||||
- printk(KERN_ERR "PCI: Device %s not available "
|
|
||||||
- "because of resource collisions\n",
|
|
||||||
+ if (!r->start && r->end)
|
|
||||||
+ printk(KERN_WARNING "PCI: Device %s resource"
|
|
||||||
+ "collisions detected. Ignoring...\n",
|
|
||||||
pci_name(dev));
|
|
||||||
- return -EINVAL;
|
|
||||||
- }
|
|
||||||
if (r->flags & IORESOURCE_IO)
|
|
||||||
cmd |= PCI_COMMAND_IO;
|
|
||||||
if (r->flags & IORESOURCE_MEM)
|
|
|
@ -1,336 +0,0 @@
|
||||||
--- a/drivers/net/tg3.c
|
|
||||||
+++ b/drivers/net/tg3.c
|
|
||||||
@@ -40,6 +40,7 @@
|
|
||||||
#include <linux/workqueue.h>
|
|
||||||
#include <linux/prefetch.h>
|
|
||||||
#include <linux/dma-mapping.h>
|
|
||||||
+#include <linux/ssb/ssb_driver_gige.h>
|
|
||||||
|
|
||||||
#include <net/checksum.h>
|
|
||||||
#include <net/ip.h>
|
|
||||||
@@ -428,8 +429,9 @@ static void _tw32_flush(struct tg3 *tp,
|
|
||||||
static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
|
|
||||||
{
|
|
||||||
tp->write32_mbox(tp, off, val);
|
|
||||||
- if (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) &&
|
|
||||||
- !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND))
|
|
||||||
+ if ((tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES) ||
|
|
||||||
+ (!(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) &&
|
|
||||||
+ !(tp->tg3_flags2 & TG3_FLG2_ICH_WORKAROUND)))
|
|
||||||
tp->read32_mbox(tp, off);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -439,7 +441,7 @@ static void tg3_write32_tx_mbox(struct t
|
|
||||||
writel(val, mbox);
|
|
||||||
if (tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG)
|
|
||||||
writel(val, mbox);
|
|
||||||
- if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
|
|
||||||
+ if ((tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER) || (tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES))
|
|
||||||
readl(mbox);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -711,7 +713,7 @@ static void tg3_switch_clocks(struct tg3
|
|
||||||
|
|
||||||
#define PHY_BUSY_LOOPS 5000
|
|
||||||
|
|
||||||
-static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
|
|
||||||
+static int __tg3_readphy(struct tg3 *tp, unsigned int phy_addr, int reg, u32 *val)
|
|
||||||
{
|
|
||||||
u32 frame_val;
|
|
||||||
unsigned int loops;
|
|
||||||
@@ -725,7 +727,7 @@ static int tg3_readphy(struct tg3 *tp, i
|
|
||||||
|
|
||||||
*val = 0x0;
|
|
||||||
|
|
||||||
- frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
|
|
||||||
+ frame_val = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) &
|
|
||||||
MI_COM_PHY_ADDR_MASK);
|
|
||||||
frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
|
|
||||||
MI_COM_REG_ADDR_MASK);
|
|
||||||
@@ -760,7 +762,12 @@ static int tg3_readphy(struct tg3 *tp, i
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
|
|
||||||
+static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
|
|
||||||
+{
|
|
||||||
+ return __tg3_readphy(tp, PHY_ADDR, reg, val);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int __tg3_writephy(struct tg3 *tp, unsigned int phy_addr, int reg, u32 val)
|
|
||||||
{
|
|
||||||
u32 frame_val;
|
|
||||||
unsigned int loops;
|
|
||||||
@@ -776,7 +783,7 @@ static int tg3_writephy(struct tg3 *tp,
|
|
||||||
udelay(80);
|
|
||||||
}
|
|
||||||
|
|
||||||
- frame_val = ((PHY_ADDR << MI_COM_PHY_ADDR_SHIFT) &
|
|
||||||
+ frame_val = ((phy_addr << MI_COM_PHY_ADDR_SHIFT) &
|
|
||||||
MI_COM_PHY_ADDR_MASK);
|
|
||||||
frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
|
|
||||||
MI_COM_REG_ADDR_MASK);
|
|
||||||
@@ -809,6 +816,11 @@ static int tg3_writephy(struct tg3 *tp,
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
|
|
||||||
+{
|
|
||||||
+ return __tg3_writephy(tp, PHY_ADDR, reg, val);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int tg3_bmcr_reset(struct tg3 *tp)
|
|
||||||
{
|
|
||||||
u32 phy_control;
|
|
||||||
@@ -2232,8 +2244,10 @@ static int tg3_set_power_state(struct tg
|
|
||||||
tg3_frob_aux_power(tp);
|
|
||||||
|
|
||||||
/* Workaround for unstable PLL clock */
|
|
||||||
- if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
|
|
||||||
- (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
|
|
||||||
+ if ((tp->phy_id & PHY_ID_MASK != PHY_ID_BCM5750_2) &&
|
|
||||||
+ /* !!! FIXME !!! */
|
|
||||||
+ ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
|
|
||||||
+ (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX))) {
|
|
||||||
u32 val = tr32(0x7d00);
|
|
||||||
|
|
||||||
val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
|
|
||||||
@@ -2725,6 +2739,14 @@ relink:
|
|
||||||
|
|
||||||
tg3_phy_copper_begin(tp);
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_ROBOSWITCH) {
|
|
||||||
+ current_link_up = 1;
|
|
||||||
+ current_speed = SPEED_1000; //FIXME
|
|
||||||
+ current_duplex = DUPLEX_FULL;
|
|
||||||
+ tp->link_config.active_speed = current_speed;
|
|
||||||
+ tp->link_config.active_duplex = current_duplex;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
tg3_readphy(tp, MII_BMSR, &tmp);
|
|
||||||
if (!tg3_readphy(tp, MII_BMSR, &tmp) &&
|
|
||||||
(tmp & BMSR_LSTATUS))
|
|
||||||
@@ -5659,6 +5681,11 @@ static int tg3_poll_fw(struct tg3 *tp)
|
|
||||||
int i;
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
|
|
||||||
+ /* We don't use firmware. */
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
|
|
||||||
/* Wait up to 20ms for init done. */
|
|
||||||
for (i = 0; i < 200; i++) {
|
|
||||||
@@ -5902,6 +5929,14 @@ static int tg3_chip_reset(struct tg3 *tp
|
|
||||||
tw32(0x5000, 0x400);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
|
|
||||||
+ /* BCM4785: In order to avoid repercussions from using potentially
|
|
||||||
+ * defective internal ROM, stop the Rx RISC CPU, which is not
|
|
||||||
+ * required. */
|
|
||||||
+ tg3_stop_fw(tp);
|
|
||||||
+ tg3_halt_cpu(tp, RX_CPU_BASE);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
tw32(GRC_MODE, tp->grc_mode);
|
|
||||||
|
|
||||||
if (tp->pci_chip_rev_id == CHIPREV_ID_5705_A0) {
|
|
||||||
@@ -6176,9 +6211,12 @@ static int tg3_halt_cpu(struct tg3 *tp,
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Clear firmware's nvram arbitration. */
|
|
||||||
- if (tp->tg3_flags & TG3_FLAG_NVRAM)
|
|
||||||
- tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
|
|
||||||
+ if (!(tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)) {
|
|
||||||
+ /* Clear firmware's nvram arbitration. */
|
|
||||||
+ if (tp->tg3_flags & TG3_FLAG_NVRAM)
|
|
||||||
+ tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -6259,6 +6297,11 @@ static int tg3_load_5701_a0_firmware_fix
|
|
||||||
struct fw_info info;
|
|
||||||
int err, i;
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
|
|
||||||
+ /* We don't use firmware. */
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
info.text_base = TG3_FW_TEXT_ADDR;
|
|
||||||
info.text_len = TG3_FW_TEXT_LEN;
|
|
||||||
info.text_data = &tg3FwText[0];
|
|
||||||
@@ -6817,6 +6860,11 @@ static int tg3_load_tso_firmware(struct
|
|
||||||
unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
|
|
||||||
int err, i;
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
|
|
||||||
+ /* We don't use firmware. */
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
@@ -7776,6 +7824,11 @@ static void tg3_timer(unsigned long __op
|
|
||||||
|
|
||||||
spin_lock(&tp->lock);
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES) {
|
|
||||||
+ /* BCM4785: Flush posted writes from GbE to host memory. */
|
|
||||||
+ tr32(HOSTCC_MODE);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (!(tp->tg3_flags & TG3_FLAG_TAGGED_STATUS)) {
|
|
||||||
/* All of this garbage is because when using non-tagged
|
|
||||||
* IRQ status the mailbox/status_block protocol the chip
|
|
||||||
@@ -9469,6 +9522,11 @@ static int tg3_test_nvram(struct tg3 *tp
|
|
||||||
__le32 *buf;
|
|
||||||
int i, j, k, err = 0, size;
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
|
|
||||||
+ /* We don't have NVRAM. */
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (tg3_nvram_read_swab(tp, 0, &magic) != 0)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
@@ -10262,7 +10320,7 @@ static int tg3_ioctl(struct net_device *
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
spin_lock_bh(&tp->lock);
|
|
||||||
- err = tg3_readphy(tp, data->reg_num & 0x1f, &mii_regval);
|
|
||||||
+ err = __tg3_readphy(tp, data->phy_id & 0x1f, data->reg_num & 0x1f, &mii_regval);
|
|
||||||
spin_unlock_bh(&tp->lock);
|
|
||||||
|
|
||||||
data->val_out = mii_regval;
|
|
||||||
@@ -10281,7 +10339,7 @@ static int tg3_ioctl(struct net_device *
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
spin_lock_bh(&tp->lock);
|
|
||||||
- err = tg3_writephy(tp, data->reg_num & 0x1f, data->val_in);
|
|
||||||
+ err = __tg3_writephy(tp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
|
|
||||||
spin_unlock_bh(&tp->lock);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
@@ -10759,6 +10817,12 @@ static void __devinit tg3_get_5906_nvram
|
|
||||||
/* Chips other than 5700/5701 use the NVRAM for fetching info. */
|
|
||||||
static void __devinit tg3_nvram_init(struct tg3 *tp)
|
|
||||||
{
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE) {
|
|
||||||
+ /* No NVRAM and EEPROM on the SSB Broadcom GigE core. */
|
|
||||||
+ tp->tg3_flags &= ~(TG3_FLAG_NVRAM | TG3_FLAG_NVRAM_BUFFERED);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
tw32_f(GRC_EEPROM_ADDR,
|
|
||||||
(EEPROM_ADDR_FSM_RESET |
|
|
||||||
(EEPROM_DEFAULT_CLOCK_PERIOD <<
|
|
||||||
@@ -10900,6 +10964,9 @@ static int tg3_nvram_read(struct tg3 *tp
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+
|
|
||||||
if (!(tp->tg3_flags & TG3_FLAG_NVRAM))
|
|
||||||
return tg3_nvram_read_using_eeprom(tp, offset, val);
|
|
||||||
|
|
||||||
@@ -11147,6 +11214,9 @@ static int tg3_nvram_write_block(struct
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+
|
|
||||||
if (tp->tg3_flags & TG3_FLAG_EEPROM_WRITE_PROT) {
|
|
||||||
tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl &
|
|
||||||
~GRC_LCLCTRL_GPIO_OUTPUT1);
|
|
||||||
@@ -12205,7 +12275,6 @@ static int __devinit tg3_get_invariants(
|
|
||||||
tp->write32 = tg3_write_flush_reg32;
|
|
||||||
}
|
|
||||||
|
|
||||||
-
|
|
||||||
if ((tp->tg3_flags & TG3_FLAG_TXD_MBOX_HWBUG) ||
|
|
||||||
(tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)) {
|
|
||||||
tp->write32_tx_mbox = tg3_write32_tx_mbox;
|
|
||||||
@@ -12241,6 +12310,11 @@ static int __devinit tg3_get_invariants(
|
|
||||||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)))
|
|
||||||
tp->tg3_flags |= TG3_FLAG_SRAM_USE_CONFIG;
|
|
||||||
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_FLUSH_POSTED_WRITES) {
|
|
||||||
+ tp->write32_tx_mbox = tg3_write_flush_reg32;
|
|
||||||
+ tp->write32_rx_mbox = tg3_write_flush_reg32;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Get eeprom hw config before calling tg3_set_power_state().
|
|
||||||
* In particular, the TG3_FLG2_IS_NIC flag must be
|
|
||||||
* determined before calling tg3_set_power_state() so that
|
|
||||||
@@ -12640,6 +12714,10 @@ static int __devinit tg3_get_device_addr
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_valid_ether_addr(&dev->dev_addr[0])) {
|
|
||||||
+ if (tp->tg3_flags3 & TG3_FLG3_IS_SSB_CORE)
|
|
||||||
+ ssb_gige_get_macaddr(tp->pdev, &dev->dev_addr[0]);
|
|
||||||
+ }
|
|
||||||
+ if (!is_valid_ether_addr(&dev->dev_addr[0])) {
|
|
||||||
#ifdef CONFIG_SPARC
|
|
||||||
if (!tg3_get_default_macaddr_sparc(tp))
|
|
||||||
return 0;
|
|
||||||
@@ -13131,6 +13209,7 @@ static char * __devinit tg3_phy_string(s
|
|
||||||
case PHY_ID_BCM5704: return "5704";
|
|
||||||
case PHY_ID_BCM5705: return "5705";
|
|
||||||
case PHY_ID_BCM5750: return "5750";
|
|
||||||
+ case PHY_ID_BCM5750_2: return "5750-2";
|
|
||||||
case PHY_ID_BCM5752: return "5752";
|
|
||||||
case PHY_ID_BCM5714: return "5714";
|
|
||||||
case PHY_ID_BCM5780: return "5780";
|
|
||||||
@@ -13317,6 +13396,13 @@ static int __devinit tg3_init_one(struct
|
|
||||||
tp->msg_enable = tg3_debug;
|
|
||||||
else
|
|
||||||
tp->msg_enable = TG3_DEF_MSG_ENABLE;
|
|
||||||
+ if (pdev_is_ssb_gige_core(pdev)) {
|
|
||||||
+ tp->tg3_flags3 |= TG3_FLG3_IS_SSB_CORE;
|
|
||||||
+ if (ssb_gige_must_flush_posted_writes(pdev))
|
|
||||||
+ tp->tg3_flags3 |= TG3_FLG3_FLUSH_POSTED_WRITES;
|
|
||||||
+ if (ssb_gige_have_roboswitch(pdev))
|
|
||||||
+ tp->tg3_flags3 |= TG3_FLG3_ROBOSWITCH;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* The word/byte swap controls here control register access byte
|
|
||||||
* swapping. DMA data byte swapping is controlled in the GRC_MODE
|
|
||||||
--- a/drivers/net/tg3.h
|
|
||||||
+++ b/drivers/net/tg3.h
|
|
||||||
@@ -2516,6 +2516,9 @@ struct tg3 {
|
|
||||||
#define TG3_FLG3_RGMII_STD_IBND_DISABLE 0x00000100
|
|
||||||
#define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200
|
|
||||||
#define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400
|
|
||||||
+#define TG3_FLG3_IS_SSB_CORE 0x00000800
|
|
||||||
+#define TG3_FLG3_FLUSH_POSTED_WRITES 0x00001000
|
|
||||||
+#define TG3_FLG3_ROBOSWITCH 0x00002000
|
|
||||||
|
|
||||||
struct timer_list timer;
|
|
||||||
u16 timer_counter;
|
|
||||||
@@ -2574,6 +2577,7 @@ struct tg3 {
|
|
||||||
#define PHY_ID_BCM5714 0x60008340
|
|
||||||
#define PHY_ID_BCM5780 0x60008350
|
|
||||||
#define PHY_ID_BCM5755 0xbc050cc0
|
|
||||||
+#define PHY_ID_BCM5750_2 0xbc050cd0
|
|
||||||
#define PHY_ID_BCM5787 0xbc050ce0
|
|
||||||
#define PHY_ID_BCM5756 0xbc050ed0
|
|
||||||
#define PHY_ID_BCM5784 0xbc050fa0
|
|
||||||
@@ -2613,7 +2617,7 @@ struct tg3 {
|
|
||||||
(X) == PHY_ID_BCM5780 || (X) == PHY_ID_BCM5787 || \
|
|
||||||
(X) == PHY_ID_BCM5755 || (X) == PHY_ID_BCM5756 || \
|
|
||||||
(X) == PHY_ID_BCM5906 || (X) == PHY_ID_BCM5761 || \
|
|
||||||
- (X) == PHY_ID_BCM8002)
|
|
||||||
+ (X) == PHY_ID_BCM8002 || (X) == PHY_ID_BCM5750_2)
|
|
||||||
|
|
||||||
struct tg3_hw_stats *hw_stats;
|
|
||||||
dma_addr_t stats_mapping;
|
|
|
@ -1,108 +0,0 @@
|
||||||
--- a/arch/mips/bcm47xx/prom.c
|
|
||||||
+++ b/arch/mips/bcm47xx/prom.c
|
|
||||||
@@ -32,6 +32,7 @@
|
|
||||||
#include <asm/fw/cfe/cfe_error.h>
|
|
||||||
|
|
||||||
static int cfe_cons_handle;
|
|
||||||
+static void (* __prom_putchar)(char c);
|
|
||||||
|
|
||||||
const char *get_system_type(void)
|
|
||||||
{
|
|
||||||
@@ -40,65 +41,40 @@ const char *get_system_type(void)
|
|
||||||
|
|
||||||
void prom_putchar(char c)
|
|
||||||
{
|
|
||||||
+ if (__prom_putchar)
|
|
||||||
+ __prom_putchar(c);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void prom_putchar_cfe(char c)
|
|
||||||
+{
|
|
||||||
while (cfe_write(cfe_cons_handle, &c, 1) == 0)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static __init void prom_init_cfe(void)
|
|
||||||
+static __init int prom_init_cfe(void)
|
|
||||||
{
|
|
||||||
uint32_t cfe_ept;
|
|
||||||
uint32_t cfe_handle;
|
|
||||||
uint32_t cfe_eptseal;
|
|
||||||
- int argc = fw_arg0;
|
|
||||||
- char **envp = (char **) fw_arg2;
|
|
||||||
- int *prom_vec = (int *) fw_arg3;
|
|
||||||
-
|
|
||||||
- /*
|
|
||||||
- * Check if a loader was used; if NOT, the 4 arguments are
|
|
||||||
- * what CFE gives us (handle, 0, EPT and EPTSEAL)
|
|
||||||
- */
|
|
||||||
- if (argc < 0) {
|
|
||||||
- cfe_handle = (uint32_t)argc;
|
|
||||||
- cfe_ept = (uint32_t)envp;
|
|
||||||
- cfe_eptseal = (uint32_t)prom_vec;
|
|
||||||
- } else {
|
|
||||||
- if ((int)prom_vec < 0) {
|
|
||||||
- /*
|
|
||||||
- * Old loader; all it gives us is the handle,
|
|
||||||
- * so use the "known" entrypoint and assume
|
|
||||||
- * the seal.
|
|
||||||
- */
|
|
||||||
- cfe_handle = (uint32_t)prom_vec;
|
|
||||||
- cfe_ept = 0xBFC00500;
|
|
||||||
- cfe_eptseal = CFE_EPTSEAL;
|
|
||||||
- } else {
|
|
||||||
- /*
|
|
||||||
- * Newer loaders bundle the handle/ept/eptseal
|
|
||||||
- * Note: prom_vec is in the loader's useg
|
|
||||||
- * which is still alive in the TLB.
|
|
||||||
- */
|
|
||||||
- cfe_handle = prom_vec[0];
|
|
||||||
- cfe_ept = prom_vec[2];
|
|
||||||
- cfe_eptseal = prom_vec[3];
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
|
|
||||||
- if (cfe_eptseal != CFE_EPTSEAL) {
|
|
||||||
- /* too early for panic to do any good */
|
|
||||||
- printk(KERN_ERR "CFE's entrypoint seal doesn't match.");
|
|
||||||
- while (1) ;
|
|
||||||
- }
|
|
||||||
+ cfe_eptseal = (uint32_t) fw_arg3;
|
|
||||||
+ cfe_handle = (uint32_t) fw_arg0;
|
|
||||||
+ cfe_ept = (uint32_t) fw_arg2;
|
|
||||||
+
|
|
||||||
+ if (cfe_eptseal != CFE_EPTSEAL)
|
|
||||||
+ return -1;
|
|
||||||
|
|
||||||
cfe_init(cfe_handle, cfe_ept);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static __init void prom_init_console(void)
|
|
||||||
+static __init void prom_init_console_cfe(void)
|
|
||||||
{
|
|
||||||
/* Initialize CFE console */
|
|
||||||
cfe_cons_handle = cfe_getstdhandle(CFE_STDHANDLE_CONSOLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
-static __init void prom_init_cmdline(void)
|
|
||||||
+static __init void prom_init_cmdline_cfe(void)
|
|
||||||
{
|
|
||||||
char buf[CL_SIZE];
|
|
||||||
|
|
||||||
@@ -154,9 +130,12 @@ static __init void prom_init_mem(void)
|
|
||||||
|
|
||||||
void __init prom_init(void)
|
|
||||||
{
|
|
||||||
- prom_init_cfe();
|
|
||||||
- prom_init_console();
|
|
||||||
- prom_init_cmdline();
|
|
||||||
+ if (prom_init_cfe() == 0) {
|
|
||||||
+ //prom_init_console_cfe();
|
|
||||||
+ //prom_init_cmdline_cfe();
|
|
||||||
+ __prom_putchar = prom_putchar_cfe;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
prom_init_mem();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
The GPIO API is supposed to return 0 or a negative error code,
|
|
||||||
but the SSB GPIO functions return the bitmask of the GPIO register.
|
|
||||||
Fix this by ignoring the bitmask and always returning 0. The SSB GPIO functions can't fail.
|
|
||||||
|
|
||||||
--mb
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- a/arch/mips/include/asm/mach-bcm47xx/gpio.h
|
|
||||||
+++ b/arch/mips/include/asm/mach-bcm47xx/gpio.h
|
|
||||||
@@ -31,24 +31,28 @@ static inline void gpio_set_value(unsign
|
|
||||||
|
|
||||||
static inline int gpio_direction_input(unsigned gpio)
|
|
||||||
{
|
|
||||||
- return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
|
|
||||||
+ ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 0);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int gpio_direction_output(unsigned gpio, int value)
|
|
||||||
{
|
|
||||||
- return ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
|
|
||||||
+ ssb_gpio_outen(&ssb_bcm47xx, 1 << gpio, 1 << gpio);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int gpio_intmask(unsigned gpio, int value)
|
|
||||||
+static inline int gpio_intmask(unsigned gpio, int value)
|
|
||||||
{
|
|
||||||
- return ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
|
|
||||||
- value ? 1 << gpio : 0);
|
|
||||||
+ ssb_gpio_intmask(&ssb_bcm47xx, 1 << gpio,
|
|
||||||
+ value ? 1 << gpio : 0);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int gpio_polarity(unsigned gpio, int value)
|
|
||||||
+static inline int gpio_polarity(unsigned gpio, int value)
|
|
||||||
{
|
|
||||||
- return ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
|
|
||||||
- value ? 1 << gpio : 0);
|
|
||||||
+ ssb_gpio_polarity(&ssb_bcm47xx, 1 << gpio,
|
|
||||||
+ value ? 1 << gpio : 0);
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,178 +0,0 @@
|
||||||
--- a/arch/mips/bcm47xx/Makefile
|
|
||||||
+++ b/arch/mips/bcm47xx/Makefile
|
|
||||||
@@ -3,4 +3,4 @@
|
|
||||||
# under Linux.
|
|
||||||
#
|
|
||||||
|
|
||||||
-obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o wgt634u.o
|
|
||||||
+obj-y := cfe_env.o gpio.o irq.o nvram.o prom.o serial.o setup.o time.o
|
|
||||||
--- a/arch/mips/bcm47xx/wgt634u.c
|
|
||||||
+++ /dev/null
|
|
||||||
@@ -1,167 +0,0 @@
|
|
||||||
-/*
|
|
||||||
- * This file is subject to the terms and conditions of the GNU General Public
|
|
||||||
- * License. See the file "COPYING" in the main directory of this archive
|
|
||||||
- * for more details.
|
|
||||||
- *
|
|
||||||
- * Copyright (C) 2007 Aurelien Jarno <aurelien@aurel32.net>
|
|
||||||
- */
|
|
||||||
-
|
|
||||||
-#include <linux/platform_device.h>
|
|
||||||
-#include <linux/module.h>
|
|
||||||
-#include <linux/leds.h>
|
|
||||||
-#include <linux/mtd/physmap.h>
|
|
||||||
-#include <linux/ssb/ssb.h>
|
|
||||||
-#include <linux/interrupt.h>
|
|
||||||
-#include <linux/reboot.h>
|
|
||||||
-#include <linux/gpio.h>
|
|
||||||
-#include <asm/mach-bcm47xx/bcm47xx.h>
|
|
||||||
-
|
|
||||||
-/* GPIO definitions for the WGT634U */
|
|
||||||
-#define WGT634U_GPIO_LED 3
|
|
||||||
-#define WGT634U_GPIO_RESET 2
|
|
||||||
-#define WGT634U_GPIO_TP1 7
|
|
||||||
-#define WGT634U_GPIO_TP2 6
|
|
||||||
-#define WGT634U_GPIO_TP3 5
|
|
||||||
-#define WGT634U_GPIO_TP4 4
|
|
||||||
-#define WGT634U_GPIO_TP5 1
|
|
||||||
-
|
|
||||||
-static struct gpio_led wgt634u_leds[] = {
|
|
||||||
- {
|
|
||||||
- .name = "power",
|
|
||||||
- .gpio = WGT634U_GPIO_LED,
|
|
||||||
- .active_low = 1,
|
|
||||||
- .default_trigger = "heartbeat",
|
|
||||||
- },
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-static struct gpio_led_platform_data wgt634u_led_data = {
|
|
||||||
- .num_leds = ARRAY_SIZE(wgt634u_leds),
|
|
||||||
- .leds = wgt634u_leds,
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-static struct platform_device wgt634u_gpio_leds = {
|
|
||||||
- .name = "leds-gpio",
|
|
||||||
- .id = -1,
|
|
||||||
- .dev = {
|
|
||||||
- .platform_data = &wgt634u_led_data,
|
|
||||||
- }
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-/* 8MiB flash. The struct mtd_partition matches original Netgear WGT634U
|
|
||||||
- firmware. */
|
|
||||||
-static struct mtd_partition wgt634u_partitions[] = {
|
|
||||||
- {
|
|
||||||
- .name = "cfe",
|
|
||||||
- .offset = 0,
|
|
||||||
- .size = 0x60000, /* 384k */
|
|
||||||
- .mask_flags = MTD_WRITEABLE /* force read-only */
|
|
||||||
- },
|
|
||||||
- {
|
|
||||||
- .name = "config",
|
|
||||||
- .offset = 0x60000,
|
|
||||||
- .size = 0x20000 /* 128k */
|
|
||||||
- },
|
|
||||||
- {
|
|
||||||
- .name = "linux",
|
|
||||||
- .offset = 0x80000,
|
|
||||||
- .size = 0x140000 /* 1280k */
|
|
||||||
- },
|
|
||||||
- {
|
|
||||||
- .name = "jffs",
|
|
||||||
- .offset = 0x1c0000,
|
|
||||||
- .size = 0x620000 /* 6272k */
|
|
||||||
- },
|
|
||||||
- {
|
|
||||||
- .name = "nvram",
|
|
||||||
- .offset = 0x7e0000,
|
|
||||||
- .size = 0x20000 /* 128k */
|
|
||||||
- },
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-static struct physmap_flash_data wgt634u_flash_data = {
|
|
||||||
- .parts = wgt634u_partitions,
|
|
||||||
- .nr_parts = ARRAY_SIZE(wgt634u_partitions)
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-static struct resource wgt634u_flash_resource = {
|
|
||||||
- .flags = IORESOURCE_MEM,
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-static struct platform_device wgt634u_flash = {
|
|
||||||
- .name = "physmap-flash",
|
|
||||||
- .id = 0,
|
|
||||||
- .dev = { .platform_data = &wgt634u_flash_data, },
|
|
||||||
- .resource = &wgt634u_flash_resource,
|
|
||||||
- .num_resources = 1,
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-/* Platform devices */
|
|
||||||
-static struct platform_device *wgt634u_devices[] __initdata = {
|
|
||||||
- &wgt634u_flash,
|
|
||||||
- &wgt634u_gpio_leds,
|
|
||||||
-};
|
|
||||||
-
|
|
||||||
-static irqreturn_t gpio_interrupt(int irq, void *ignored)
|
|
||||||
-{
|
|
||||||
- int state;
|
|
||||||
-
|
|
||||||
- /* Interrupts are shared, check if the current one is
|
|
||||||
- a GPIO interrupt. */
|
|
||||||
- if (!ssb_chipco_irq_status(&ssb_bcm47xx.chipco,
|
|
||||||
- SSB_CHIPCO_IRQ_GPIO))
|
|
||||||
- return IRQ_NONE;
|
|
||||||
-
|
|
||||||
- state = gpio_get_value(WGT634U_GPIO_RESET);
|
|
||||||
-
|
|
||||||
- /* Interrupt are level triggered, revert the interrupt polarity
|
|
||||||
- to clear the interrupt. */
|
|
||||||
- gpio_polarity(WGT634U_GPIO_RESET, state);
|
|
||||||
-
|
|
||||||
- if (!state) {
|
|
||||||
- printk(KERN_INFO "Reset button pressed");
|
|
||||||
- ctrl_alt_del();
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- return IRQ_HANDLED;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-static int __init wgt634u_init(void)
|
|
||||||
-{
|
|
||||||
- /* There is no easy way to detect that we are running on a WGT634U
|
|
||||||
- * machine. Use the MAC address as an heuristic. Netgear Inc. has
|
|
||||||
- * been allocated ranges 00:09:5b:xx:xx:xx and 00:0f:b5:xx:xx:xx.
|
|
||||||
- */
|
|
||||||
-
|
|
||||||
- u8 *et0mac = ssb_bcm47xx.sprom.et0mac;
|
|
||||||
-
|
|
||||||
- if (et0mac[0] == 0x00 &&
|
|
||||||
- ((et0mac[1] == 0x09 && et0mac[2] == 0x5b) ||
|
|
||||||
- (et0mac[1] == 0x0f && et0mac[2] == 0xb5))) {
|
|
||||||
- struct ssb_mipscore *mcore = &ssb_bcm47xx.mipscore;
|
|
||||||
-
|
|
||||||
- printk(KERN_INFO "WGT634U machine detected.\n");
|
|
||||||
-
|
|
||||||
- if (!request_irq(gpio_to_irq(WGT634U_GPIO_RESET),
|
|
||||||
- gpio_interrupt, IRQF_SHARED,
|
|
||||||
- "WGT634U GPIO", &ssb_bcm47xx.chipco)) {
|
|
||||||
- gpio_direction_input(WGT634U_GPIO_RESET);
|
|
||||||
- gpio_intmask(WGT634U_GPIO_RESET, 1);
|
|
||||||
- ssb_chipco_irq_mask(&ssb_bcm47xx.chipco,
|
|
||||||
- SSB_CHIPCO_IRQ_GPIO,
|
|
||||||
- SSB_CHIPCO_IRQ_GPIO);
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
- wgt634u_flash_data.width = mcore->flash_buswidth;
|
|
||||||
- wgt634u_flash_resource.start = mcore->flash_window;
|
|
||||||
- wgt634u_flash_resource.end = mcore->flash_window
|
|
||||||
- + mcore->flash_window_size
|
|
||||||
- - 1;
|
|
||||||
- return platform_add_devices(wgt634u_devices,
|
|
||||||
- ARRAY_SIZE(wgt634u_devices));
|
|
||||||
- } else
|
|
||||||
- return -ENODEV;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-module_init(wgt634u_init);
|
|
||||||
-
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/drivers/net/b44.c
|
|
||||||
+++ b/drivers/net/b44.c
|
|
||||||
@@ -814,7 +814,7 @@ static int b44_rx(struct b44 *bp, int bu
|
|
||||||
struct sk_buff *copy_skb;
|
|
||||||
|
|
||||||
b44_recycle_rx(bp, cons, bp->rx_prod);
|
|
||||||
- copy_skb = dev_alloc_skb(len + 2);
|
|
||||||
+ copy_skb = netdev_alloc_skb(bp->dev, len + 2);
|
|
||||||
if (copy_skb == NULL)
|
|
||||||
goto drop_it_no_recycle;
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
this patch export ssb_watchdog_timer_set to allow to use it in a Linux
|
|
||||||
watchdog driver.
|
|
||||||
|
|
||||||
|
|
||||||
Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr>
|
|
||||||
Acked-by : Michael Buesch <mb@bu3sch.de>
|
|
||||||
--- a/drivers/ssb/embedded.c
|
|
||||||
+++ b/drivers/ssb/embedded.c
|
|
||||||
@@ -29,6 +29,7 @@ int ssb_watchdog_timer_set(struct ssb_bu
|
|
||||||
}
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
+EXPORT_SYMBOL(ssb_watchdog_timer_set);
|
|
||||||
|
|
||||||
u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask)
|
|
||||||
{
|
|
|
@ -1,326 +0,0 @@
|
||||||
This add watchdog driver for broadcom 47xx device.
|
|
||||||
It uses the ssb subsytem to access embeded watchdog device.
|
|
||||||
|
|
||||||
Because the watchdog timeout is very short (about 2s), a soft timer is used
|
|
||||||
to increase the watchdog period.
|
|
||||||
|
|
||||||
Note : A patch for exporting the ssb_watchdog_timer_set will
|
|
||||||
be submitted on next linux-mips merge. Without this patch it can't
|
|
||||||
be build as a module.
|
|
||||||
|
|
||||||
Signed-off-by: Aleksandar Radovanovic <biblbroks@sezampro.rs>
|
|
||||||
Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr>
|
|
||||||
--- a/drivers/watchdog/Kconfig
|
|
||||||
+++ b/drivers/watchdog/Kconfig
|
|
||||||
@@ -747,6 +747,12 @@ config TXX9_WDT
|
|
||||||
help
|
|
||||||
Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
|
|
||||||
|
|
||||||
+config BCM47XX_WDT
|
|
||||||
+ tristate "Broadcom BCM47xx Watchdog Timer"
|
|
||||||
+ depends on BCM47XX
|
|
||||||
+ help
|
|
||||||
+ Hardware driver for the Broadcom BCM47xx Watchog Timer.
|
|
||||||
+
|
|
||||||
# PARISC Architecture
|
|
||||||
|
|
||||||
# POWERPC Architecture
|
|
||||||
--- a/drivers/watchdog/Makefile
|
|
||||||
+++ b/drivers/watchdog/Makefile
|
|
||||||
@@ -106,6 +106,7 @@ obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o
|
|
||||||
obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
|
|
||||||
obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
|
|
||||||
obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
|
|
||||||
+obj-$(CONFIG_BCM47XX_WDT) += bcm47xx_wdt.o
|
|
||||||
|
|
||||||
# PARISC Architecture
|
|
||||||
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/drivers/watchdog/bcm47xx_wdt.c
|
|
||||||
@@ -0,0 +1,286 @@
|
|
||||||
+/*
|
|
||||||
+ * Watchdog driver for Broadcom BCM47XX
|
|
||||||
+ *
|
|
||||||
+ * Copyright (C) 2008 Aleksandar Radovanovic <biblbroks@sezampro.rs>
|
|
||||||
+ * Copyright (C) 2009 Matthieu CASTET <castet.matthieu@free.fr>
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or
|
|
||||||
+ * modify it under the terms of the GNU General Public License
|
|
||||||
+ * as published by the Free Software Foundation; either version
|
|
||||||
+ * 2 of the License, or (at your option) any later version.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/bitops.h>
|
|
||||||
+#include <linux/errno.h>
|
|
||||||
+#include <linux/fs.h>
|
|
||||||
+#include <linux/init.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/miscdevice.h>
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <linux/moduleparam.h>
|
|
||||||
+#include <linux/reboot.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+#include <linux/uaccess.h>
|
|
||||||
+#include <linux/watchdog.h>
|
|
||||||
+#include <linux/timer.h>
|
|
||||||
+#include <linux/jiffies.h>
|
|
||||||
+#include <linux/ssb/ssb_embedded.h>
|
|
||||||
+#include <asm/mach-bcm47xx/bcm47xx.h>
|
|
||||||
+
|
|
||||||
+#define DRV_NAME "bcm47xx_wdt"
|
|
||||||
+
|
|
||||||
+#define WDT_DEFAULT_TIME 30 /* seconds */
|
|
||||||
+#define WDT_MAX_TIME 256 /* seconds */
|
|
||||||
+
|
|
||||||
+static int wdt_time = WDT_DEFAULT_TIME;
|
|
||||||
+static int nowayout = WATCHDOG_NOWAYOUT;
|
|
||||||
+
|
|
||||||
+module_param(wdt_time, int, 0);
|
|
||||||
+MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="
|
|
||||||
+ __MODULE_STRING(WDT_DEFAULT_TIME) ")");
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
|
|
||||||
+module_param(nowayout, int, 0);
|
|
||||||
+MODULE_PARM_DESC(nowayout,
|
|
||||||
+ "Watchdog cannot be stopped once started (default="
|
|
||||||
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+static unsigned long bcm47xx_wdt_busy;
|
|
||||||
+static char expect_release;
|
|
||||||
+static struct timer_list wdt_timer;
|
|
||||||
+static atomic_t ticks;
|
|
||||||
+
|
|
||||||
+static inline void bcm47xx_wdt_hw_start(void)
|
|
||||||
+{
|
|
||||||
+ /* this is 2,5s on 100Mhz clock and 2s on 133 Mhz */
|
|
||||||
+ ssb_watchdog_timer_set(&ssb_bcm47xx, 0xfffffff);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline int bcm47xx_wdt_hw_stop(void)
|
|
||||||
+{
|
|
||||||
+ return ssb_watchdog_timer_set(&ssb_bcm47xx, 0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void bcm47xx_timer_tick(unsigned long unused)
|
|
||||||
+{
|
|
||||||
+ if (!atomic_dec_and_test(&ticks)) {
|
|
||||||
+ bcm47xx_wdt_hw_start();
|
|
||||||
+ mod_timer(&wdt_timer, jiffies + HZ);
|
|
||||||
+ } else {
|
|
||||||
+ printk(KERN_CRIT DRV_NAME "Watchdog will fire soon!!!\n");
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void bcm47xx_wdt_pet(void)
|
|
||||||
+{
|
|
||||||
+ atomic_set(&ticks, wdt_time);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void bcm47xx_wdt_start(void)
|
|
||||||
+{
|
|
||||||
+ bcm47xx_wdt_pet();
|
|
||||||
+ bcm47xx_timer_tick(0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void bcm47xx_wdt_pause(void)
|
|
||||||
+{
|
|
||||||
+ del_timer_sync(&wdt_timer);
|
|
||||||
+ bcm47xx_wdt_hw_stop();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void bcm47xx_wdt_stop(void)
|
|
||||||
+{
|
|
||||||
+ bcm47xx_wdt_pause();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int bcm47xx_wdt_settimeout(int new_time)
|
|
||||||
+{
|
|
||||||
+ if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ wdt_time = new_time;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int bcm47xx_wdt_open(struct inode *inode, struct file *file)
|
|
||||||
+{
|
|
||||||
+ if (test_and_set_bit(0, &bcm47xx_wdt_busy))
|
|
||||||
+ return -EBUSY;
|
|
||||||
+
|
|
||||||
+ bcm47xx_wdt_start();
|
|
||||||
+ return nonseekable_open(inode, file);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int bcm47xx_wdt_release(struct inode *inode, struct file *file)
|
|
||||||
+{
|
|
||||||
+ if (expect_release == 42) {
|
|
||||||
+ bcm47xx_wdt_stop();
|
|
||||||
+ } else {
|
|
||||||
+ printk(KERN_CRIT DRV_NAME
|
|
||||||
+ ": Unexpected close, not stopping watchdog!\n");
|
|
||||||
+ bcm47xx_wdt_start();
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ clear_bit(0, &bcm47xx_wdt_busy);
|
|
||||||
+ expect_release = 0;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static ssize_t bcm47xx_wdt_write(struct file *file, const char __user *data,
|
|
||||||
+ size_t len, loff_t *ppos)
|
|
||||||
+{
|
|
||||||
+ if (len) {
|
|
||||||
+ if (!nowayout) {
|
|
||||||
+ size_t i;
|
|
||||||
+
|
|
||||||
+ expect_release = 0;
|
|
||||||
+
|
|
||||||
+ for (i = 0; i != len; i++) {
|
|
||||||
+ char c;
|
|
||||||
+ if (get_user(c, data + i))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+ if (c == 'V')
|
|
||||||
+ expect_release = 42;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ bcm47xx_wdt_pet();
|
|
||||||
+ }
|
|
||||||
+ return len;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct watchdog_info bcm47xx_wdt_info = {
|
|
||||||
+ .identity = DRV_NAME,
|
|
||||||
+ .options = WDIOF_SETTIMEOUT |
|
|
||||||
+ WDIOF_KEEPALIVEPING |
|
|
||||||
+ WDIOF_MAGICCLOSE,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static long bcm47xx_wdt_ioctl(struct file *file,
|
|
||||||
+ unsigned int cmd, unsigned long arg)
|
|
||||||
+{
|
|
||||||
+ void __user *argp = (void __user *)arg;
|
|
||||||
+ int __user *p = argp;
|
|
||||||
+ int new_value, retval = -EINVAL;;
|
|
||||||
+
|
|
||||||
+ switch (cmd) {
|
|
||||||
+ case WDIOC_GETSUPPORT:
|
|
||||||
+ return copy_to_user(argp, &bcm47xx_wdt_info,
|
|
||||||
+ sizeof(bcm47xx_wdt_info)) ? -EFAULT : 0;
|
|
||||||
+
|
|
||||||
+ case WDIOC_GETSTATUS:
|
|
||||||
+ case WDIOC_GETBOOTSTATUS:
|
|
||||||
+ return put_user(0, p);
|
|
||||||
+
|
|
||||||
+ case WDIOC_SETOPTIONS:
|
|
||||||
+ if (get_user(new_value, p))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+
|
|
||||||
+ if (new_value & WDIOS_DISABLECARD) {
|
|
||||||
+ bcm47xx_wdt_stop();
|
|
||||||
+ retval = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (new_value & WDIOS_ENABLECARD) {
|
|
||||||
+ bcm47xx_wdt_start();
|
|
||||||
+ retval = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return retval;
|
|
||||||
+
|
|
||||||
+ case WDIOC_KEEPALIVE:
|
|
||||||
+ bcm47xx_wdt_pet();
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ case WDIOC_SETTIMEOUT:
|
|
||||||
+ if (get_user(new_value, p))
|
|
||||||
+ return -EFAULT;
|
|
||||||
+
|
|
||||||
+ if (bcm47xx_wdt_settimeout(new_value))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ bcm47xx_wdt_pet();
|
|
||||||
+
|
|
||||||
+ case WDIOC_GETTIMEOUT:
|
|
||||||
+ return put_user(wdt_time, p);
|
|
||||||
+
|
|
||||||
+ default:
|
|
||||||
+ return -ENOTTY;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int bcm47xx_wdt_notify_sys(struct notifier_block *this,
|
|
||||||
+ unsigned long code, void *unused)
|
|
||||||
+{
|
|
||||||
+ if (code == SYS_DOWN || code == SYS_HALT)
|
|
||||||
+ bcm47xx_wdt_stop();
|
|
||||||
+ return NOTIFY_DONE;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static const struct file_operations bcm47xx_wdt_fops = {
|
|
||||||
+ .owner = THIS_MODULE,
|
|
||||||
+ .llseek = no_llseek,
|
|
||||||
+ .unlocked_ioctl = bcm47xx_wdt_ioctl,
|
|
||||||
+ .open = bcm47xx_wdt_open,
|
|
||||||
+ .release = bcm47xx_wdt_release,
|
|
||||||
+ .write = bcm47xx_wdt_write,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct miscdevice bcm47xx_wdt_miscdev = {
|
|
||||||
+ .minor = WATCHDOG_MINOR,
|
|
||||||
+ .name = "watchdog",
|
|
||||||
+ .fops = &bcm47xx_wdt_fops,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static struct notifier_block bcm47xx_wdt_notifier = {
|
|
||||||
+ .notifier_call = bcm47xx_wdt_notify_sys,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int __init bcm47xx_wdt_init(void)
|
|
||||||
+{
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ if (bcm47xx_wdt_hw_stop() < 0)
|
|
||||||
+ return -ENODEV;
|
|
||||||
+
|
|
||||||
+ setup_timer(&wdt_timer, bcm47xx_timer_tick, 0L);
|
|
||||||
+
|
|
||||||
+ if (bcm47xx_wdt_settimeout(wdt_time)) {
|
|
||||||
+ bcm47xx_wdt_settimeout(WDT_DEFAULT_TIME);
|
|
||||||
+ printk(KERN_INFO DRV_NAME
|
|
||||||
+ ": wdt_time value must be 1 <= wdt_time <= 256, using %d\n",
|
|
||||||
+ wdt_time);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ ret = register_reboot_notifier(&bcm47xx_wdt_notifier);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ ret = misc_register(&bcm47xx_wdt_miscdev);
|
|
||||||
+ if (ret) {
|
|
||||||
+ unregister_reboot_notifier(&bcm47xx_wdt_notifier);
|
|
||||||
+ return ret;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ printk(KERN_INFO "BCM47xx Watchdog Timer enabled (%d seconds%s)\n",
|
|
||||||
+ wdt_time, nowayout ? ", nowayout" : "");
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void __exit bcm47xx_wdt_exit(void)
|
|
||||||
+{
|
|
||||||
+ if (!nowayout)
|
|
||||||
+ bcm47xx_wdt_stop();
|
|
||||||
+
|
|
||||||
+ misc_deregister(&bcm47xx_wdt_miscdev);
|
|
||||||
+
|
|
||||||
+ unregister_reboot_notifier(&bcm47xx_wdt_notifier);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+module_init(bcm47xx_wdt_init);
|
|
||||||
+module_exit(bcm47xx_wdt_exit);
|
|
||||||
+
|
|
||||||
+MODULE_AUTHOR("Aleksandar Radovanovic");
|
|
||||||
+MODULE_DESCRIPTION("Watchdog driver for Broadcom BCM47xx");
|
|
||||||
+MODULE_LICENSE("GPL");
|
|
||||||
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
|
|
@ -1,183 +0,0 @@
|
||||||
the current ssb irq setup (in ssb_mipscore_init) have some problem :
|
|
||||||
it configure some device on some irq without checking that the irq is not taken by an other device.
|
|
||||||
|
|
||||||
For example in my case PCI host is on irq 0 and IPSEC on irq 3.
|
|
||||||
The current code :
|
|
||||||
- store in dev->irq that IPSEC irq is 3+2
|
|
||||||
- do a set_irq 0->3 on PCI host
|
|
||||||
|
|
||||||
But now IPSEC irq is not routed anymore to the mips code and dev->irq is wrong. This cause problem described in [1].
|
|
||||||
|
|
||||||
This patch try to solve the problem by making set_irq configure the device we want to take the irq on the shared irq0.
|
|
||||||
The previous example become :
|
|
||||||
- store in dev->irq that IPSEC irq is 3+2
|
|
||||||
- do a set_irq 0->3 on PCI host :
|
|
||||||
- irq 3 is already taken by IPSEC. do a set_irq 3->0 on IPSEC
|
|
||||||
|
|
||||||
|
|
||||||
I also added some code to print the irq configuration before and after irq setup to allow easier debugging. And I add extra checking in ssb_mips_irq to report device without irq or device with not routed irq.
|
|
||||||
|
|
||||||
|
|
||||||
[1] http://www.danm.de/files/src/bcm5365p/REPORTED_DEVICES
|
|
||||||
|
|
||||||
Signed-off-by: Matthieu CASTET <castet.matthieu@free.fr>
|
|
||||||
--- a/drivers/ssb/driver_mipscore.c
|
|
||||||
+++ b/drivers/ssb/driver_mipscore.c
|
|
||||||
@@ -49,29 +49,54 @@ static const u32 ipsflag_irq_shift[] = {
|
|
||||||
|
|
||||||
static inline u32 ssb_irqflag(struct ssb_device *dev)
|
|
||||||
{
|
|
||||||
- return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
|
|
||||||
+ u32 tpsflag = ssb_read32(dev, SSB_TPSFLAG);
|
|
||||||
+ if (tpsflag)
|
|
||||||
+ return ssb_read32(dev, SSB_TPSFLAG) & SSB_TPSFLAG_BPFLAG;
|
|
||||||
+ else
|
|
||||||
+ /* not irq supported */
|
|
||||||
+ return 0x3f;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct ssb_device *find_device(struct ssb_device *rdev, int irqflag)
|
|
||||||
+{
|
|
||||||
+ struct ssb_bus *bus = rdev->bus;
|
|
||||||
+ int i;
|
|
||||||
+ for (i = 0; i < bus->nr_devices; i++) {
|
|
||||||
+ struct ssb_device *dev;
|
|
||||||
+ dev = &(bus->devices[i]);
|
|
||||||
+ if (ssb_irqflag(dev) == irqflag)
|
|
||||||
+ return dev;
|
|
||||||
+ }
|
|
||||||
+ return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the MIPS IRQ assignment for a specified device.
|
|
||||||
* If unassigned, 0 is returned.
|
|
||||||
+ * If disabled, 5 is returned.
|
|
||||||
+ * If not supported, 6 is returned.
|
|
||||||
*/
|
|
||||||
unsigned int ssb_mips_irq(struct ssb_device *dev)
|
|
||||||
{
|
|
||||||
struct ssb_bus *bus = dev->bus;
|
|
||||||
+ struct ssb_device *mdev = bus->mipscore.dev;
|
|
||||||
u32 irqflag;
|
|
||||||
u32 ipsflag;
|
|
||||||
u32 tmp;
|
|
||||||
unsigned int irq;
|
|
||||||
|
|
||||||
irqflag = ssb_irqflag(dev);
|
|
||||||
+ if (irqflag == 0x3f)
|
|
||||||
+ return 6;
|
|
||||||
ipsflag = ssb_read32(bus->mipscore.dev, SSB_IPSFLAG);
|
|
||||||
for (irq = 1; irq <= 4; irq++) {
|
|
||||||
tmp = ((ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq]);
|
|
||||||
if (tmp == irqflag)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
- if (irq == 5)
|
|
||||||
- irq = 0;
|
|
||||||
+ if (irq == 5) {
|
|
||||||
+ if ((1 << irqflag) & ssb_read32(mdev, SSB_INTVEC))
|
|
||||||
+ irq = 0;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return irq;
|
|
||||||
}
|
|
||||||
@@ -97,25 +122,56 @@ static void set_irq(struct ssb_device *d
|
|
||||||
struct ssb_device *mdev = bus->mipscore.dev;
|
|
||||||
u32 irqflag = ssb_irqflag(dev);
|
|
||||||
|
|
||||||
+ BUG_ON(oldirq == 6);
|
|
||||||
+
|
|
||||||
dev->irq = irq + 2;
|
|
||||||
|
|
||||||
- ssb_dprintk(KERN_INFO PFX
|
|
||||||
- "set_irq: core 0x%04x, irq %d => %d\n",
|
|
||||||
- dev->id.coreid, oldirq, irq);
|
|
||||||
/* clear the old irq */
|
|
||||||
if (oldirq == 0)
|
|
||||||
ssb_write32(mdev, SSB_INTVEC, (~(1 << irqflag) & ssb_read32(mdev, SSB_INTVEC)));
|
|
||||||
- else
|
|
||||||
+ else if (oldirq != 5)
|
|
||||||
clear_irq(bus, oldirq);
|
|
||||||
|
|
||||||
/* assign the new one */
|
|
||||||
if (irq == 0) {
|
|
||||||
ssb_write32(mdev, SSB_INTVEC, ((1 << irqflag) | ssb_read32(mdev, SSB_INTVEC)));
|
|
||||||
} else {
|
|
||||||
+ u32 ipsflag = ssb_read32(mdev, SSB_IPSFLAG);
|
|
||||||
+ if ((ipsflag & ipsflag_irq_mask[irq]) != ipsflag_irq_mask[irq]) {
|
|
||||||
+ u32 oldipsflag = (ipsflag & ipsflag_irq_mask[irq]) >> ipsflag_irq_shift[irq];
|
|
||||||
+ struct ssb_device *olddev = find_device(dev, oldipsflag);
|
|
||||||
+ if (olddev)
|
|
||||||
+ set_irq(olddev, 0);
|
|
||||||
+ }
|
|
||||||
irqflag <<= ipsflag_irq_shift[irq];
|
|
||||||
- irqflag |= (ssb_read32(mdev, SSB_IPSFLAG) & ~ipsflag_irq_mask[irq]);
|
|
||||||
+ irqflag |= (ipsflag & ~ipsflag_irq_mask[irq]);
|
|
||||||
ssb_write32(mdev, SSB_IPSFLAG, irqflag);
|
|
||||||
}
|
|
||||||
+ ssb_dprintk(KERN_INFO PFX
|
|
||||||
+ "set_irq: core 0x%04x, irq %d => %d\n",
|
|
||||||
+ dev->id.coreid, oldirq+2, irq+2);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void print_irq(struct ssb_device *dev, unsigned int irq)
|
|
||||||
+{
|
|
||||||
+ int i;
|
|
||||||
+ static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
|
|
||||||
+ ssb_dprintk(KERN_INFO PFX
|
|
||||||
+ "core 0x%04x, irq :", dev->id.coreid);
|
|
||||||
+ for (i = 0; i <= 6; i++) {
|
|
||||||
+ ssb_dprintk(" %s%s", irq_name[i], i==irq?"*":" ");
|
|
||||||
+ }
|
|
||||||
+ ssb_dprintk("\n");
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void dump_irq(struct ssb_bus *bus)
|
|
||||||
+{
|
|
||||||
+ int i;
|
|
||||||
+ for (i = 0; i < bus->nr_devices; i++) {
|
|
||||||
+ struct ssb_device *dev;
|
|
||||||
+ dev = &(bus->devices[i]);
|
|
||||||
+ print_irq(dev, ssb_mips_irq(dev));
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
static void ssb_mips_serial_init(struct ssb_mipscore *mcore)
|
|
||||||
@@ -197,18 +253,26 @@ void ssb_mipscore_init(struct ssb_mipsco
|
|
||||||
else if (bus->chipco.dev)
|
|
||||||
ssb_chipco_timing_init(&bus->chipco, ns);
|
|
||||||
|
|
||||||
+ dump_irq(bus);
|
|
||||||
/* Assign IRQs to all cores on the bus, start with irq line 2, because serial usually takes 1 */
|
|
||||||
for (irq = 2, i = 0; i < bus->nr_devices; i++) {
|
|
||||||
+ int mips_irq;
|
|
||||||
dev = &(bus->devices[i]);
|
|
||||||
- dev->irq = ssb_mips_irq(dev) + 2;
|
|
||||||
+ mips_irq = ssb_mips_irq(dev);
|
|
||||||
+ if (mips_irq > 4)
|
|
||||||
+ dev->irq = 0;
|
|
||||||
+ else
|
|
||||||
+ dev->irq = mips_irq + 2;
|
|
||||||
+ if (dev->irq > 5)
|
|
||||||
+ continue;
|
|
||||||
switch (dev->id.coreid) {
|
|
||||||
case SSB_DEV_USB11_HOST:
|
|
||||||
/* shouldn't need a separate irq line for non-4710, most of them have a proper
|
|
||||||
* external usb controller on the pci */
|
|
||||||
if ((bus->chip_id == 0x4710) && (irq <= 4)) {
|
|
||||||
set_irq(dev, irq++);
|
|
||||||
- break;
|
|
||||||
}
|
|
||||||
+ break;
|
|
||||||
/* fallthrough */
|
|
||||||
case SSB_DEV_PCI:
|
|
||||||
case SSB_DEV_ETHERNET:
|
|
||||||
@@ -222,6 +286,8 @@ void ssb_mipscore_init(struct ssb_mipsco
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ ssb_dprintk(KERN_INFO PFX "after irq reconfiguration\n");
|
|
||||||
+ dump_irq(bus);
|
|
||||||
|
|
||||||
ssb_mips_serial_init(mcore);
|
|
||||||
ssb_mips_flash_detect(mcore);
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/arch/mips/Kconfig
|
|
||||||
+++ b/arch/mips/Kconfig
|
|
||||||
@@ -56,7 +56,6 @@ config BCM47XX
|
|
||||||
select SSB_B43_PCI_BRIDGE if PCI
|
|
||||||
select SSB_PCICORE_HOSTMODE if PCI
|
|
||||||
select GENERIC_GPIO
|
|
||||||
- select SYS_HAS_EARLY_PRINTK
|
|
||||||
select CFE
|
|
||||||
help
|
|
||||||
Support for BCM47XX based boards
|
|
|
@ -1,135 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/r4kcache.h
|
|
||||||
+++ b/arch/mips/include/asm/r4kcache.h
|
|
||||||
@@ -20,10 +20,25 @@
|
|
||||||
#ifdef CONFIG_BCM47XX
|
|
||||||
#include <asm/paccess.h>
|
|
||||||
#include <linux/ssb/ssb.h>
|
|
||||||
-#define BCM4710_DUMMY_RREG() ((void) *((u8 *) KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)))
|
|
||||||
+#define BCM4710_DUMMY_RREG() bcm4710_dummy_rreg()
|
|
||||||
+
|
|
||||||
+static inline unsigned long bcm4710_dummy_rreg(void) {
|
|
||||||
+ return (*(volatile unsigned long *)(KSEG1ADDR(SSB_ENUM_BASE + SSB_IMSTATE)));
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define BCM4710_FILL_TLB(addr) bcm4710_fill_tlb((void*)(addr))
|
|
||||||
+
|
|
||||||
+static inline unsigned long bcm4710_fill_tlb(void *addr) {
|
|
||||||
+ return (*(unsigned long *)addr);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define BCM4710_PROTECTED_FILL_TLB(addr) bcm4710_protected_fill_tlb((void*)(addr))
|
|
||||||
+
|
|
||||||
+static inline void bcm4710_protected_fill_tlb(void *addr) {
|
|
||||||
+ unsigned long x;
|
|
||||||
+ get_dbe(x, (unsigned long *)addr);;
|
|
||||||
+}
|
|
||||||
|
|
||||||
-#define BCM4710_FILL_TLB(addr) (*(volatile unsigned long *)(addr))
|
|
||||||
-#define BCM4710_PROTECTED_FILL_TLB(addr) ({ unsigned long x; get_dbe(x, (volatile unsigned long *)(addr)); })
|
|
||||||
#else
|
|
||||||
#define BCM4710_DUMMY_RREG()
|
|
||||||
|
|
||||||
--- a/arch/mips/mm/tlbex.c
|
|
||||||
+++ b/arch/mips/mm/tlbex.c
|
|
||||||
@@ -548,6 +548,9 @@ build_get_pgde32(u32 **p, unsigned int t
|
|
||||||
#endif
|
|
||||||
uasm_i_addu(p, ptr, tmp, ptr);
|
|
||||||
#else
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ uasm_i_nop(p);
|
|
||||||
+#endif
|
|
||||||
UASM_i_LA_mostly(p, ptr, pgdc);
|
|
||||||
#endif
|
|
||||||
uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */
|
|
||||||
@@ -678,12 +681,12 @@ static void __cpuinit build_r4000_tlb_re
|
|
||||||
/* No need for uasm_i_nop */
|
|
||||||
}
|
|
||||||
|
|
||||||
-#ifdef CONFIG_BCM47XX
|
|
||||||
- uasm_i_nop(&p);
|
|
||||||
-#endif
|
|
||||||
#ifdef CONFIG_64BIT
|
|
||||||
build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */
|
|
||||||
#else
|
|
||||||
+# ifdef CONFIG_BCM47XX
|
|
||||||
+ uasm_i_nop(&p);
|
|
||||||
+# endif
|
|
||||||
build_get_pgde32(&p, K0, K1); /* get pgd in K1 */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -691,6 +694,9 @@ static void __cpuinit build_r4000_tlb_re
|
|
||||||
build_update_entries(&p, K0, K1);
|
|
||||||
build_tlb_write_entry(&p, &l, &r, tlb_random);
|
|
||||||
uasm_l_leave(&l, p);
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ uasm_i_nop(&p);
|
|
||||||
+#endif
|
|
||||||
uasm_i_eret(&p); /* return from trap */
|
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
|
||||||
@@ -1088,12 +1094,12 @@ build_r4000_tlbchange_handler_head(u32 *
|
|
||||||
struct uasm_reloc **r, unsigned int pte,
|
|
||||||
unsigned int ptr)
|
|
||||||
{
|
|
||||||
-#ifdef CONFIG_BCM47XX
|
|
||||||
- uasm_i_nop(p);
|
|
||||||
-#endif
|
|
||||||
#ifdef CONFIG_64BIT
|
|
||||||
build_get_pmde64(p, l, r, pte, ptr); /* get pmd in ptr */
|
|
||||||
#else
|
|
||||||
+# ifdef CONFIG_BCM47XX
|
|
||||||
+ uasm_i_nop(p);
|
|
||||||
+# endif
|
|
||||||
build_get_pgde32(p, pte, ptr); /* get pgd in ptr */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1121,6 +1127,9 @@ build_r4000_tlbchange_handler_tail(u32 *
|
|
||||||
build_update_entries(p, tmp, ptr);
|
|
||||||
build_tlb_write_entry(p, l, r, tlb_indexed);
|
|
||||||
uasm_l_leave(l, *p);
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ uasm_i_nop(p);
|
|
||||||
+#endif
|
|
||||||
uasm_i_eret(p); /* return from trap */
|
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
|
||||||
--- a/arch/mips/kernel/genex.S
|
|
||||||
+++ b/arch/mips/kernel/genex.S
|
|
||||||
@@ -22,6 +22,19 @@
|
|
||||||
#include <asm/page.h>
|
|
||||||
#include <asm/thread_info.h>
|
|
||||||
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+# ifdef eret
|
|
||||||
+# undef eret
|
|
||||||
+# endif
|
|
||||||
+# define eret \
|
|
||||||
+ .set push; \
|
|
||||||
+ .set noreorder; \
|
|
||||||
+ nop; \
|
|
||||||
+ nop; \
|
|
||||||
+ eret; \
|
|
||||||
+ .set pop;
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#define PANIC_PIC(msg) \
|
|
||||||
.set push; \
|
|
||||||
.set reorder; \
|
|
||||||
@@ -54,7 +67,6 @@ NESTED(except_vec3_generic, 0, sp)
|
|
||||||
.set noat
|
|
||||||
#ifdef CONFIG_BCM47XX
|
|
||||||
nop
|
|
||||||
- nop
|
|
||||||
#endif
|
|
||||||
#if R5432_CP0_INTERRUPT_WAR
|
|
||||||
mfc0 k0, CP0_INDEX
|
|
||||||
@@ -79,6 +91,9 @@ NESTED(except_vec3_r4000, 0, sp)
|
|
||||||
.set push
|
|
||||||
.set mips3
|
|
||||||
.set noat
|
|
||||||
+#ifdef CONFIG_BCM47XX
|
|
||||||
+ nop
|
|
||||||
+#endif
|
|
||||||
mfc0 k1, CP0_CAUSE
|
|
||||||
li k0, 31<<2
|
|
||||||
andi k1, k1, 0x7c
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,365 +0,0 @@
|
||||||
/*
|
|
||||||
* LED Morse Trigger
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 Gabor Juhos <juhosg at openwrt.org>
|
|
||||||
*
|
|
||||||
* This file was based on: drivers/led/ledtrig-timer.c
|
|
||||||
* Copyright 2005-2006 Openedhand Ltd.
|
|
||||||
* Author: Richard Purdie <rpurdie@openedhand.com>
|
|
||||||
*
|
|
||||||
* also based on the patch '[PATCH] 2.5.59 morse code panics' posted
|
|
||||||
* in the LKML by Tomas Szepe at Thu, 30 Jan 2003
|
|
||||||
* Copyright (C) 2002 Andrew Rodland <arodland@noln.com>
|
|
||||||
* Copyright (C) 2003 Tomas Szepe <szepe@pinerecords.com>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/version.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/jiffies.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/sysdev.h>
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/ctype.h>
|
|
||||||
#include <linux/leds.h>
|
|
||||||
|
|
||||||
#include "leds.h"
|
|
||||||
|
|
||||||
#define MORSE_DELAY_BASE (HZ/2)
|
|
||||||
|
|
||||||
#define MORSE_STATE_BLINK_START 0
|
|
||||||
#define MORSE_STATE_BLINK_STOP 1
|
|
||||||
|
|
||||||
#define MORSE_DIT_LEN 1
|
|
||||||
#define MORSE_DAH_LEN 3
|
|
||||||
#define MORSE_SPACE_LEN 7
|
|
||||||
|
|
||||||
struct morse_trig_data {
|
|
||||||
unsigned long delay;
|
|
||||||
char *msg;
|
|
||||||
|
|
||||||
unsigned char morse;
|
|
||||||
unsigned char state;
|
|
||||||
char *msgpos;
|
|
||||||
struct timer_list timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
const unsigned char morsetable[] = {
|
|
||||||
0122, 0, 0310, 0, 0, 0163, /* "#$%&' */
|
|
||||||
055, 0155, 0, 0, 0163, 0141, 0152, 0051, /* ()*+,-./ */
|
|
||||||
077, 076, 074, 070, 060, 040, 041, 043, 047, 057, /* 0-9 */
|
|
||||||
0107, 0125, 0, 0061, 0, 0114, 0, /* :;<=>?@ */
|
|
||||||
006, 021, 025, 011, 002, 024, 013, 020, 004, /* A-I */
|
|
||||||
036, 015, 022, 007, 005, 017, 026, 033, 012, /* J-R */
|
|
||||||
010, 003, 014, 030, 016, 031, 035, 023, /* S-Z */
|
|
||||||
0, 0, 0, 0, 0154 /* [\]^_ */
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline unsigned char tomorse(char c) {
|
|
||||||
if (c >= 'a' && c <= 'z')
|
|
||||||
c = c - 'a' + 'A';
|
|
||||||
if (c >= '"' && c <= '_') {
|
|
||||||
return morsetable[c - '"'];
|
|
||||||
} else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned long dit_len(struct morse_trig_data *morse_data)
|
|
||||||
{
|
|
||||||
return MORSE_DIT_LEN*morse_data->delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned long dah_len(struct morse_trig_data *morse_data)
|
|
||||||
{
|
|
||||||
return MORSE_DAH_LEN*morse_data->delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline unsigned long space_len(struct morse_trig_data *morse_data)
|
|
||||||
{
|
|
||||||
return MORSE_SPACE_LEN*morse_data->delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void morse_timer_function(unsigned long data)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = (struct led_classdev *)data;
|
|
||||||
struct morse_trig_data *morse_data = led_cdev->trigger_data;
|
|
||||||
unsigned long brightness = LED_OFF;
|
|
||||||
unsigned long delay = 0;
|
|
||||||
|
|
||||||
if (!morse_data->msg)
|
|
||||||
goto set_led;
|
|
||||||
|
|
||||||
switch (morse_data->state) {
|
|
||||||
case MORSE_STATE_BLINK_START:
|
|
||||||
/* Starting a new blink. We have a valid code in morse. */
|
|
||||||
delay = (morse_data->morse & 001) ? dah_len(morse_data):
|
|
||||||
dit_len(morse_data);
|
|
||||||
brightness = LED_FULL;
|
|
||||||
morse_data->state = MORSE_STATE_BLINK_STOP;
|
|
||||||
morse_data->morse >>= 1;
|
|
||||||
break;
|
|
||||||
case MORSE_STATE_BLINK_STOP:
|
|
||||||
/* Coming off of a blink. */
|
|
||||||
morse_data->state = MORSE_STATE_BLINK_START;
|
|
||||||
|
|
||||||
if (morse_data->morse > 1) {
|
|
||||||
/* Not done yet, just a one-dit pause. */
|
|
||||||
delay = dit_len(morse_data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a new char, figure out how much space. */
|
|
||||||
/* First time through */
|
|
||||||
if (!morse_data->msgpos)
|
|
||||||
morse_data->msgpos = (char *)morse_data->msg;
|
|
||||||
|
|
||||||
if (!*morse_data->msgpos) {
|
|
||||||
/* Repeating */
|
|
||||||
morse_data->msgpos = (char *)morse_data->msg;
|
|
||||||
delay = space_len(morse_data);
|
|
||||||
} else {
|
|
||||||
/* Inter-letter space */
|
|
||||||
delay = dah_len(morse_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(morse_data->morse = tomorse(*morse_data->msgpos))) {
|
|
||||||
delay = space_len(morse_data);
|
|
||||||
/* And get us back here */
|
|
||||||
morse_data->state = MORSE_STATE_BLINK_STOP;
|
|
||||||
}
|
|
||||||
morse_data->msgpos++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod_timer(&morse_data->timer, jiffies + msecs_to_jiffies(delay));
|
|
||||||
|
|
||||||
set_led:
|
|
||||||
led_set_brightness(led_cdev, brightness);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t _morse_delay_show(struct led_classdev *led_cdev, char *buf)
|
|
||||||
{
|
|
||||||
struct morse_trig_data *morse_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
sprintf(buf, "%lu\n", morse_data->delay);
|
|
||||||
|
|
||||||
return strlen(buf) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t _morse_delay_store(struct led_classdev *led_cdev,
|
|
||||||
const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
struct morse_trig_data *morse_data = led_cdev->trigger_data;
|
|
||||||
char *after;
|
|
||||||
unsigned long state = simple_strtoul(buf, &after, 10);
|
|
||||||
size_t count = after - buf;
|
|
||||||
int ret = -EINVAL;
|
|
||||||
|
|
||||||
if (*after && isspace(*after))
|
|
||||||
count++;
|
|
||||||
|
|
||||||
if (count == size) {
|
|
||||||
morse_data->delay = state;
|
|
||||||
mod_timer(&morse_data->timer, jiffies + 1);
|
|
||||||
ret = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t _morse_msg_show(struct led_classdev *led_cdev, char *buf)
|
|
||||||
{
|
|
||||||
struct morse_trig_data *morse_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
if (!morse_data->msg)
|
|
||||||
sprintf(buf, "<none>\n");
|
|
||||||
else
|
|
||||||
sprintf(buf, "%s\n", morse_data->msg);
|
|
||||||
|
|
||||||
return strlen(buf) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t _morse_msg_store(struct led_classdev *led_cdev,
|
|
||||||
const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
struct morse_trig_data *morse_data = led_cdev->trigger_data;
|
|
||||||
char *m;
|
|
||||||
|
|
||||||
m = kmalloc(size, GFP_KERNEL);
|
|
||||||
if (!m)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
memcpy(m,buf,size);
|
|
||||||
m[size]='\0';
|
|
||||||
|
|
||||||
if (morse_data->msg)
|
|
||||||
kfree(morse_data->msg);
|
|
||||||
|
|
||||||
morse_data->msg = m;
|
|
||||||
morse_data->msgpos = NULL;
|
|
||||||
morse_data->state = MORSE_STATE_BLINK_STOP;
|
|
||||||
|
|
||||||
mod_timer(&morse_data->timer, jiffies + 1);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
|
|
||||||
static ssize_t morse_delay_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
return _morse_delay_show(led_cdev, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t morse_delay_store(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
return _morse_delay_store(led_cdev, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t morse_msg_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
return _morse_msg_show(led_cdev, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t morse_msg_store(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
|
|
||||||
return _morse_msg_store(led_cdev, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store);
|
|
||||||
static DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store);
|
|
||||||
|
|
||||||
#define led_device_create_file(leddev, attr) \
|
|
||||||
device_create_file(leddev->dev, &dev_attr_ ## attr)
|
|
||||||
#define led_device_remove_file(leddev, attr) \
|
|
||||||
device_remove_file(leddev->dev, &dev_attr_ ## attr)
|
|
||||||
|
|
||||||
#else
|
|
||||||
static ssize_t morse_delay_show(struct class_device *dev, char *buf)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = class_get_devdata(dev);
|
|
||||||
|
|
||||||
return _morse_delay_show(led_cdev, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t morse_delay_store(struct class_device *dev, const char *buf,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = class_get_devdata(dev);
|
|
||||||
|
|
||||||
return _morse_delay_store(led_cdev, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t morse_msg_show(struct class_device *dev, char *buf)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = class_get_devdata(dev);
|
|
||||||
|
|
||||||
return _morse_msg_show(led_cdev, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t morse_msg_store(struct class_device *dev, const char *buf,
|
|
||||||
size_t size)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = class_get_devdata(dev);
|
|
||||||
|
|
||||||
return _morse_msg_store(led_cdev, buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static CLASS_DEVICE_ATTR(delay, 0644, morse_delay_show, morse_delay_store);
|
|
||||||
static CLASS_DEVICE_ATTR(message, 0644, morse_msg_show, morse_msg_store);
|
|
||||||
|
|
||||||
#define led_device_create_file(leddev, attr) \
|
|
||||||
class_device_create_file(leddev->class_dev, &class_device_attr_ ## attr)
|
|
||||||
#define led_device_remove_file(leddev, attr) \
|
|
||||||
class_device_remove_file(leddev->class_dev, &class_device_attr_ ## attr)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void morse_trig_activate(struct led_classdev *led_cdev)
|
|
||||||
{
|
|
||||||
struct morse_trig_data *morse_data;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
morse_data = kzalloc(sizeof(*morse_data), GFP_KERNEL);
|
|
||||||
if (!morse_data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
morse_data->delay = MORSE_DELAY_BASE;
|
|
||||||
init_timer(&morse_data->timer);
|
|
||||||
morse_data->timer.function = morse_timer_function;
|
|
||||||
morse_data->timer.data = (unsigned long)led_cdev;
|
|
||||||
|
|
||||||
rc = led_device_create_file(led_cdev, delay);
|
|
||||||
if (rc) goto err;
|
|
||||||
|
|
||||||
rc = led_device_create_file(led_cdev, message);
|
|
||||||
if (rc) goto err_delay;
|
|
||||||
|
|
||||||
led_cdev->trigger_data = morse_data;
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
err_delay:
|
|
||||||
led_device_remove_file(led_cdev, delay);
|
|
||||||
err:
|
|
||||||
kfree(morse_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void morse_trig_deactivate(struct led_classdev *led_cdev)
|
|
||||||
{
|
|
||||||
struct morse_trig_data *morse_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
if (!morse_data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
led_device_remove_file(led_cdev, message);
|
|
||||||
led_device_remove_file(led_cdev, delay);
|
|
||||||
|
|
||||||
del_timer_sync(&morse_data->timer);
|
|
||||||
if (morse_data->msg)
|
|
||||||
kfree(morse_data->msg);
|
|
||||||
|
|
||||||
kfree(morse_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct led_trigger morse_led_trigger = {
|
|
||||||
.name = "morse",
|
|
||||||
.activate = morse_trig_activate,
|
|
||||||
.deactivate = morse_trig_deactivate,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init morse_trig_init(void)
|
|
||||||
{
|
|
||||||
return led_trigger_register(&morse_led_trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit morse_trig_exit(void)
|
|
||||||
{
|
|
||||||
led_trigger_unregister(&morse_led_trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(morse_trig_init);
|
|
||||||
module_exit(morse_trig_exit);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Gabor Juhos <juhosg at openwrt.org>");
|
|
||||||
MODULE_DESCRIPTION("Morse LED trigger");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
|
@ -1,451 +0,0 @@
|
||||||
/*
|
|
||||||
* LED Kernel Netdev Trigger
|
|
||||||
*
|
|
||||||
* Toggles the LED to reflect the link and traffic state of a named net device
|
|
||||||
*
|
|
||||||
* Copyright 2007 Oliver Jowett <oliver@opencloud.com>
|
|
||||||
*
|
|
||||||
* Derived from ledtrig-timer.c which is:
|
|
||||||
* Copyright 2005-2006 Openedhand Ltd.
|
|
||||||
* Author: Richard Purdie <rpurdie@openedhand.com>
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/jiffies.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/spinlock.h>
|
|
||||||
#include <linux/device.h>
|
|
||||||
#include <linux/sysdev.h>
|
|
||||||
#include <linux/netdevice.h>
|
|
||||||
#include <linux/timer.h>
|
|
||||||
#include <linux/ctype.h>
|
|
||||||
#include <linux/leds.h>
|
|
||||||
#include <linux/version.h>
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
|
||||||
#include <net/net_namespace.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "leds.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Configurable sysfs attributes:
|
|
||||||
*
|
|
||||||
* device_name - network device name to monitor
|
|
||||||
*
|
|
||||||
* interval - duration of LED blink, in milliseconds
|
|
||||||
*
|
|
||||||
* mode - either "none" (LED is off) or a space separated list of one or more of:
|
|
||||||
* link: LED's normal state reflects whether the link is up (has carrier) or not
|
|
||||||
* tx: LED blinks on transmitted data
|
|
||||||
* rx: LED blinks on receive data
|
|
||||||
*
|
|
||||||
* Some suggestions:
|
|
||||||
*
|
|
||||||
* Simple link status LED:
|
|
||||||
* $ echo netdev >someled/trigger
|
|
||||||
* $ echo eth0 >someled/device_name
|
|
||||||
* $ echo link >someled/mode
|
|
||||||
*
|
|
||||||
* Ethernet-style link/activity LED:
|
|
||||||
* $ echo netdev >someled/trigger
|
|
||||||
* $ echo eth0 >someled/device_name
|
|
||||||
* $ echo "link tx rx" >someled/mode
|
|
||||||
*
|
|
||||||
* Modem-style tx/rx LEDs:
|
|
||||||
* $ echo netdev >led1/trigger
|
|
||||||
* $ echo ppp0 >led1/device_name
|
|
||||||
* $ echo tx >led1/mode
|
|
||||||
* $ echo netdev >led2/trigger
|
|
||||||
* $ echo ppp0 >led2/device_name
|
|
||||||
* $ echo rx >led2/mode
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define MODE_LINK 1
|
|
||||||
#define MODE_TX 2
|
|
||||||
#define MODE_RX 4
|
|
||||||
|
|
||||||
struct led_netdev_data {
|
|
||||||
rwlock_t lock;
|
|
||||||
|
|
||||||
struct timer_list timer;
|
|
||||||
struct notifier_block notifier;
|
|
||||||
|
|
||||||
struct led_classdev *led_cdev;
|
|
||||||
struct net_device *net_dev;
|
|
||||||
|
|
||||||
char device_name[IFNAMSIZ];
|
|
||||||
unsigned interval;
|
|
||||||
unsigned mode;
|
|
||||||
unsigned link_up;
|
|
||||||
unsigned last_activity;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void set_baseline_state(struct led_netdev_data *trigger_data)
|
|
||||||
{
|
|
||||||
if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up)
|
|
||||||
led_set_brightness(trigger_data->led_cdev, LED_FULL);
|
|
||||||
else
|
|
||||||
led_set_brightness(trigger_data->led_cdev, LED_OFF);
|
|
||||||
|
|
||||||
if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && trigger_data->link_up)
|
|
||||||
mod_timer(&trigger_data->timer, jiffies + trigger_data->interval);
|
|
||||||
else
|
|
||||||
del_timer(&trigger_data->timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t led_device_name_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
read_lock(&trigger_data->lock);
|
|
||||||
sprintf(buf, "%s\n", trigger_data->device_name);
|
|
||||||
read_unlock(&trigger_data->lock);
|
|
||||||
|
|
||||||
return strlen(buf) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
|
|
||||||
extern struct net init_net;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static ssize_t led_device_name_store(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
if (size < 0 || size >= IFNAMSIZ)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
write_lock(&trigger_data->lock);
|
|
||||||
|
|
||||||
strcpy(trigger_data->device_name, buf);
|
|
||||||
if (size > 0 && trigger_data->device_name[size-1] == '\n')
|
|
||||||
trigger_data->device_name[size-1] = 0;
|
|
||||||
|
|
||||||
if (trigger_data->device_name[0] != 0) {
|
|
||||||
/* check for existing device to update from */
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
|
|
||||||
trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name);
|
|
||||||
#else
|
|
||||||
trigger_data->net_dev = dev_get_by_name(trigger_data->device_name);
|
|
||||||
#endif
|
|
||||||
if (trigger_data->net_dev != NULL)
|
|
||||||
trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0;
|
|
||||||
set_baseline_state(trigger_data); /* updates LEDs, may start timers */
|
|
||||||
}
|
|
||||||
|
|
||||||
write_unlock(&trigger_data->lock);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(device_name, 0644, led_device_name_show, led_device_name_store);
|
|
||||||
|
|
||||||
static ssize_t led_mode_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
read_lock(&trigger_data->lock);
|
|
||||||
|
|
||||||
if (trigger_data->mode == 0) {
|
|
||||||
strcpy(buf, "none\n");
|
|
||||||
} else {
|
|
||||||
if (trigger_data->mode & MODE_LINK)
|
|
||||||
strcat(buf, "link ");
|
|
||||||
if (trigger_data->mode & MODE_TX)
|
|
||||||
strcat(buf, "tx ");
|
|
||||||
if (trigger_data->mode & MODE_RX)
|
|
||||||
strcat(buf, "rx ");
|
|
||||||
strcat(buf, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
read_unlock(&trigger_data->lock);
|
|
||||||
|
|
||||||
return strlen(buf)+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t led_mode_store(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
|
|
||||||
char copybuf[1024];
|
|
||||||
int new_mode = -1;
|
|
||||||
char *p, *token;
|
|
||||||
|
|
||||||
/* take a copy since we don't want to trash the inbound buffer when using strsep */
|
|
||||||
strncpy(copybuf, buf, sizeof(copybuf));
|
|
||||||
copybuf[1023] = 0;
|
|
||||||
p = copybuf;
|
|
||||||
|
|
||||||
while ((token = strsep(&p, " \t\n")) != NULL) {
|
|
||||||
if (!*token)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (new_mode == -1)
|
|
||||||
new_mode = 0;
|
|
||||||
|
|
||||||
if (!strcmp(token, "none"))
|
|
||||||
new_mode = 0;
|
|
||||||
else if (!strcmp(token, "tx"))
|
|
||||||
new_mode |= MODE_TX;
|
|
||||||
else if (!strcmp(token, "rx"))
|
|
||||||
new_mode |= MODE_RX;
|
|
||||||
else if (!strcmp(token, "link"))
|
|
||||||
new_mode |= MODE_LINK;
|
|
||||||
else
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_mode == -1)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
write_lock(&trigger_data->lock);
|
|
||||||
trigger_data->mode = new_mode;
|
|
||||||
set_baseline_state(trigger_data);
|
|
||||||
write_unlock(&trigger_data->lock);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store);
|
|
||||||
|
|
||||||
static ssize_t led_interval_show(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
read_lock(&trigger_data->lock);
|
|
||||||
sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval));
|
|
||||||
read_unlock(&trigger_data->lock);
|
|
||||||
|
|
||||||
return strlen(buf) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t led_interval_store(struct device *dev,
|
|
||||||
struct device_attribute *attr, const char *buf, size_t size)
|
|
||||||
{
|
|
||||||
struct led_classdev *led_cdev = dev_get_drvdata(dev);
|
|
||||||
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
|
|
||||||
int ret = -EINVAL;
|
|
||||||
char *after;
|
|
||||||
unsigned long value = simple_strtoul(buf, &after, 10);
|
|
||||||
size_t count = after - buf;
|
|
||||||
|
|
||||||
if (*after && isspace(*after))
|
|
||||||
count++;
|
|
||||||
|
|
||||||
/* impose some basic bounds on the timer interval */
|
|
||||||
if (count == size && value >= 5 && value <= 10000) {
|
|
||||||
write_lock(&trigger_data->lock);
|
|
||||||
trigger_data->interval = msecs_to_jiffies(value);
|
|
||||||
set_baseline_state(trigger_data); // resets timer
|
|
||||||
write_unlock(&trigger_data->lock);
|
|
||||||
ret = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store);
|
|
||||||
|
|
||||||
static int netdev_trig_notify(struct notifier_block *nb,
|
|
||||||
unsigned long evt,
|
|
||||||
void *dv)
|
|
||||||
{
|
|
||||||
struct net_device *dev = dv;
|
|
||||||
struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier);
|
|
||||||
|
|
||||||
if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
|
|
||||||
write_lock(&trigger_data->lock);
|
|
||||||
|
|
||||||
if (strcmp(dev->name, trigger_data->device_name))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (evt == NETDEV_REGISTER) {
|
|
||||||
if (trigger_data->net_dev != NULL)
|
|
||||||
dev_put(trigger_data->net_dev);
|
|
||||||
dev_hold(dev);
|
|
||||||
trigger_data->net_dev = dev;
|
|
||||||
trigger_data->link_up = 0;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) {
|
|
||||||
dev_put(trigger_data->net_dev);
|
|
||||||
trigger_data->net_dev = NULL;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* UP / DOWN / CHANGE */
|
|
||||||
|
|
||||||
trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev));
|
|
||||||
set_baseline_state(trigger_data);
|
|
||||||
|
|
||||||
done:
|
|
||||||
write_unlock(&trigger_data->lock);
|
|
||||||
return NOTIFY_DONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* here's the real work! */
|
|
||||||
static void netdev_trig_timer(unsigned long arg)
|
|
||||||
{
|
|
||||||
struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg;
|
|
||||||
struct net_device_stats *dev_stats;
|
|
||||||
unsigned new_activity;
|
|
||||||
|
|
||||||
write_lock(&trigger_data->lock);
|
|
||||||
|
|
||||||
if (!trigger_data->link_up || !trigger_data->net_dev || (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) {
|
|
||||||
/* we don't need to do timer work, just reflect link state. */
|
|
||||||
led_set_brightness(trigger_data->led_cdev, ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ? LED_FULL : LED_OFF);
|
|
||||||
goto no_restart;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_stats = trigger_data->net_dev->get_stats(trigger_data->net_dev);
|
|
||||||
new_activity =
|
|
||||||
((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) +
|
|
||||||
((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0);
|
|
||||||
|
|
||||||
if (trigger_data->mode & MODE_LINK) {
|
|
||||||
/* base state is ON (link present) */
|
|
||||||
/* if there's no link, we don't get this far and the LED is off */
|
|
||||||
|
|
||||||
/* OFF -> ON always */
|
|
||||||
/* ON -> OFF on activity */
|
|
||||||
if (trigger_data->led_cdev->brightness == LED_OFF) {
|
|
||||||
led_set_brightness(trigger_data->led_cdev, LED_FULL);
|
|
||||||
} else if (trigger_data->last_activity != new_activity) {
|
|
||||||
led_set_brightness(trigger_data->led_cdev, LED_OFF);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* base state is OFF */
|
|
||||||
/* ON -> OFF always */
|
|
||||||
/* OFF -> ON on activity */
|
|
||||||
if (trigger_data->led_cdev->brightness == LED_FULL) {
|
|
||||||
led_set_brightness(trigger_data->led_cdev, LED_OFF);
|
|
||||||
} else if (trigger_data->last_activity != new_activity) {
|
|
||||||
led_set_brightness(trigger_data->led_cdev, LED_FULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trigger_data->last_activity = new_activity;
|
|
||||||
mod_timer(&trigger_data->timer, jiffies + trigger_data->interval);
|
|
||||||
|
|
||||||
no_restart:
|
|
||||||
write_unlock(&trigger_data->lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netdev_trig_activate(struct led_classdev *led_cdev)
|
|
||||||
{
|
|
||||||
struct led_netdev_data *trigger_data;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
|
|
||||||
if (!trigger_data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
rwlock_init(&trigger_data->lock);
|
|
||||||
|
|
||||||
trigger_data->notifier.notifier_call = netdev_trig_notify;
|
|
||||||
trigger_data->notifier.priority = 10;
|
|
||||||
|
|
||||||
setup_timer(&trigger_data->timer, netdev_trig_timer, (unsigned long) trigger_data);
|
|
||||||
|
|
||||||
trigger_data->led_cdev = led_cdev;
|
|
||||||
trigger_data->net_dev = NULL;
|
|
||||||
trigger_data->device_name[0] = 0;
|
|
||||||
|
|
||||||
trigger_data->mode = 0;
|
|
||||||
trigger_data->interval = msecs_to_jiffies(50);
|
|
||||||
trigger_data->link_up = 0;
|
|
||||||
trigger_data->last_activity = 0;
|
|
||||||
|
|
||||||
led_cdev->trigger_data = trigger_data;
|
|
||||||
|
|
||||||
rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
|
|
||||||
if (rc)
|
|
||||||
goto err_out;
|
|
||||||
rc = device_create_file(led_cdev->dev, &dev_attr_mode);
|
|
||||||
if (rc)
|
|
||||||
goto err_out_device_name;
|
|
||||||
rc = device_create_file(led_cdev->dev, &dev_attr_interval);
|
|
||||||
if (rc)
|
|
||||||
goto err_out_mode;
|
|
||||||
|
|
||||||
register_netdevice_notifier(&trigger_data->notifier);
|
|
||||||
return;
|
|
||||||
|
|
||||||
err_out_mode:
|
|
||||||
device_remove_file(led_cdev->dev, &dev_attr_mode);
|
|
||||||
err_out_device_name:
|
|
||||||
device_remove_file(led_cdev->dev, &dev_attr_device_name);
|
|
||||||
err_out:
|
|
||||||
led_cdev->trigger_data = NULL;
|
|
||||||
kfree(trigger_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void netdev_trig_deactivate(struct led_classdev *led_cdev)
|
|
||||||
{
|
|
||||||
struct led_netdev_data *trigger_data = led_cdev->trigger_data;
|
|
||||||
|
|
||||||
if (trigger_data) {
|
|
||||||
unregister_netdevice_notifier(&trigger_data->notifier);
|
|
||||||
|
|
||||||
device_remove_file(led_cdev->dev, &dev_attr_device_name);
|
|
||||||
device_remove_file(led_cdev->dev, &dev_attr_mode);
|
|
||||||
device_remove_file(led_cdev->dev, &dev_attr_interval);
|
|
||||||
|
|
||||||
write_lock(&trigger_data->lock);
|
|
||||||
|
|
||||||
if (trigger_data->net_dev) {
|
|
||||||
dev_put(trigger_data->net_dev);
|
|
||||||
trigger_data->net_dev = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_unlock(&trigger_data->lock);
|
|
||||||
|
|
||||||
del_timer_sync(&trigger_data->timer);
|
|
||||||
|
|
||||||
kfree(trigger_data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct led_trigger netdev_led_trigger = {
|
|
||||||
.name = "netdev",
|
|
||||||
.activate = netdev_trig_activate,
|
|
||||||
.deactivate = netdev_trig_deactivate,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int __init netdev_trig_init(void)
|
|
||||||
{
|
|
||||||
return led_trigger_register(&netdev_led_trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void __exit netdev_trig_exit(void)
|
|
||||||
{
|
|
||||||
led_trigger_unregister(&netdev_led_trigger);
|
|
||||||
}
|
|
||||||
|
|
||||||
module_init(netdev_trig_init);
|
|
||||||
module_exit(netdev_trig_exit);
|
|
||||||
|
|
||||||
MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
|
|
||||||
MODULE_DESCRIPTION("Netdev LED trigger");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,780 +0,0 @@
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/linux/LzmaDecode.h
|
|
||||||
@@ -0,0 +1,100 @@
|
|
||||||
+/*
|
|
||||||
+ LzmaDecode.h
|
|
||||||
+ LZMA Decoder interface
|
|
||||||
+
|
|
||||||
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
|
|
||||||
+ http://www.7-zip.org/
|
|
||||||
+
|
|
||||||
+ LZMA SDK is licensed under two licenses:
|
|
||||||
+ 1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
+ 2) Common Public License (CPL)
|
|
||||||
+ It means that you can select one of these two licenses and
|
|
||||||
+ follow rules of that license.
|
|
||||||
+
|
|
||||||
+ SPECIAL EXCEPTION:
|
|
||||||
+ Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
+ statically or dynamically link your code (or bind by name) to the
|
|
||||||
+ interfaces of this file without subjecting your linked code to the
|
|
||||||
+ terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
+ to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
+*/
|
|
||||||
+
|
|
||||||
+#ifndef __LZMADECODE_H
|
|
||||||
+#define __LZMADECODE_H
|
|
||||||
+
|
|
||||||
+/* #define _LZMA_IN_CB */
|
|
||||||
+/* Use callback for input data */
|
|
||||||
+
|
|
||||||
+/* #define _LZMA_OUT_READ */
|
|
||||||
+/* Use read function for output data */
|
|
||||||
+
|
|
||||||
+/* #define _LZMA_PROB32 */
|
|
||||||
+/* It can increase speed on some 32-bit CPUs,
|
|
||||||
+ but memory usage will be doubled in that case */
|
|
||||||
+
|
|
||||||
+/* #define _LZMA_LOC_OPT */
|
|
||||||
+/* Enable local speed optimizations inside code */
|
|
||||||
+
|
|
||||||
+#ifndef UInt32
|
|
||||||
+#ifdef _LZMA_UINT32_IS_ULONG
|
|
||||||
+#define UInt32 unsigned long
|
|
||||||
+#else
|
|
||||||
+#define UInt32 unsigned int
|
|
||||||
+#endif
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifdef _LZMA_PROB32
|
|
||||||
+#define CProb UInt32
|
|
||||||
+#else
|
|
||||||
+#define CProb unsigned short
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#define LZMA_RESULT_OK 0
|
|
||||||
+#define LZMA_RESULT_DATA_ERROR 1
|
|
||||||
+#define LZMA_RESULT_NOT_ENOUGH_MEM 2
|
|
||||||
+
|
|
||||||
+#ifdef _LZMA_IN_CB
|
|
||||||
+typedef struct _ILzmaInCallback
|
|
||||||
+{
|
|
||||||
+ int (*Read)(void *object, unsigned char **buffer, UInt32 *bufferSize);
|
|
||||||
+} ILzmaInCallback;
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#define LZMA_BASE_SIZE 1846
|
|
||||||
+#define LZMA_LIT_SIZE 768
|
|
||||||
+
|
|
||||||
+/*
|
|
||||||
+bufferSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(CProb)
|
|
||||||
+bufferSize += 100 in case of _LZMA_OUT_READ
|
|
||||||
+by default CProb is unsigned short,
|
|
||||||
+but if specify _LZMA_PROB_32, CProb will be UInt32(unsigned int)
|
|
||||||
+*/
|
|
||||||
+
|
|
||||||
+#ifdef _LZMA_OUT_READ
|
|
||||||
+int LzmaDecoderInit(
|
|
||||||
+ unsigned char *buffer, UInt32 bufferSize,
|
|
||||||
+ int lc, int lp, int pb,
|
|
||||||
+ unsigned char *dictionary, UInt32 dictionarySize,
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ ILzmaInCallback *inCallback
|
|
||||||
+ #else
|
|
||||||
+ unsigned char *inStream, UInt32 inSize
|
|
||||||
+ #endif
|
|
||||||
+);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+int LzmaDecode(
|
|
||||||
+ unsigned char *buffer,
|
|
||||||
+ #ifndef _LZMA_OUT_READ
|
|
||||||
+ UInt32 bufferSize,
|
|
||||||
+ int lc, int lp, int pb,
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ ILzmaInCallback *inCallback,
|
|
||||||
+ #else
|
|
||||||
+ unsigned char *inStream, UInt32 inSize,
|
|
||||||
+ #endif
|
|
||||||
+ #endif
|
|
||||||
+ unsigned char *outStream, UInt32 outSize,
|
|
||||||
+ UInt32 *outSizeProcessed);
|
|
||||||
+
|
|
||||||
+#endif
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/lib/LzmaDecode.c
|
|
||||||
@@ -0,0 +1,663 @@
|
|
||||||
+/*
|
|
||||||
+ LzmaDecode.c
|
|
||||||
+ LZMA Decoder
|
|
||||||
+
|
|
||||||
+ LZMA SDK 4.05 Copyright (c) 1999-2004 Igor Pavlov (2004-08-25)
|
|
||||||
+ http://www.7-zip.org/
|
|
||||||
+
|
|
||||||
+ LZMA SDK is licensed under two licenses:
|
|
||||||
+ 1) GNU Lesser General Public License (GNU LGPL)
|
|
||||||
+ 2) Common Public License (CPL)
|
|
||||||
+ It means that you can select one of these two licenses and
|
|
||||||
+ follow rules of that license.
|
|
||||||
+
|
|
||||||
+ SPECIAL EXCEPTION:
|
|
||||||
+ Igor Pavlov, as the author of this code, expressly permits you to
|
|
||||||
+ statically or dynamically link your code (or bind by name) to the
|
|
||||||
+ interfaces of this file without subjecting your linked code to the
|
|
||||||
+ terms of the CPL or GNU LGPL. Any modifications or additions
|
|
||||||
+ to this file, however, are subject to the LGPL or CPL terms.
|
|
||||||
+*/
|
|
||||||
+
|
|
||||||
+#include <linux/LzmaDecode.h>
|
|
||||||
+
|
|
||||||
+#ifndef Byte
|
|
||||||
+#define Byte unsigned char
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#define kNumTopBits 24
|
|
||||||
+#define kTopValue ((UInt32)1 << kNumTopBits)
|
|
||||||
+
|
|
||||||
+#define kNumBitModelTotalBits 11
|
|
||||||
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
|
||||||
+#define kNumMoveBits 5
|
|
||||||
+
|
|
||||||
+typedef struct _CRangeDecoder
|
|
||||||
+{
|
|
||||||
+ Byte *Buffer;
|
|
||||||
+ Byte *BufferLim;
|
|
||||||
+ UInt32 Range;
|
|
||||||
+ UInt32 Code;
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ ILzmaInCallback *InCallback;
|
|
||||||
+ int Result;
|
|
||||||
+ #endif
|
|
||||||
+ int ExtraBytes;
|
|
||||||
+} CRangeDecoder;
|
|
||||||
+
|
|
||||||
+Byte RangeDecoderReadByte(CRangeDecoder *rd)
|
|
||||||
+{
|
|
||||||
+ if (rd->Buffer == rd->BufferLim)
|
|
||||||
+ {
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ UInt32 size;
|
|
||||||
+ rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
|
|
||||||
+ rd->BufferLim = rd->Buffer + size;
|
|
||||||
+ if (size == 0)
|
|
||||||
+ #endif
|
|
||||||
+ {
|
|
||||||
+ rd->ExtraBytes = 1;
|
|
||||||
+ return 0xFF;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ return (*rd->Buffer++);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* #define ReadByte (*rd->Buffer++) */
|
|
||||||
+#define ReadByte (RangeDecoderReadByte(rd))
|
|
||||||
+
|
|
||||||
+void RangeDecoderInit(CRangeDecoder *rd,
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ ILzmaInCallback *inCallback
|
|
||||||
+ #else
|
|
||||||
+ Byte *stream, UInt32 bufferSize
|
|
||||||
+ #endif
|
|
||||||
+ )
|
|
||||||
+{
|
|
||||||
+ int i;
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ rd->InCallback = inCallback;
|
|
||||||
+ rd->Buffer = rd->BufferLim = 0;
|
|
||||||
+ #else
|
|
||||||
+ rd->Buffer = stream;
|
|
||||||
+ rd->BufferLim = stream + bufferSize;
|
|
||||||
+ #endif
|
|
||||||
+ rd->ExtraBytes = 0;
|
|
||||||
+ rd->Code = 0;
|
|
||||||
+ rd->Range = (0xFFFFFFFF);
|
|
||||||
+ for(i = 0; i < 5; i++)
|
|
||||||
+ rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
|
|
||||||
+#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
|
|
||||||
+#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
|
|
||||||
+
|
|
||||||
+UInt32 RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
|
|
||||||
+{
|
|
||||||
+ RC_INIT_VAR
|
|
||||||
+ UInt32 result = 0;
|
|
||||||
+ int i;
|
|
||||||
+ for (i = numTotalBits; i > 0; i--)
|
|
||||||
+ {
|
|
||||||
+ /* UInt32 t; */
|
|
||||||
+ range >>= 1;
|
|
||||||
+
|
|
||||||
+ result <<= 1;
|
|
||||||
+ if (code >= range)
|
|
||||||
+ {
|
|
||||||
+ code -= range;
|
|
||||||
+ result |= 1;
|
|
||||||
+ }
|
|
||||||
+ /*
|
|
||||||
+ t = (code - range) >> 31;
|
|
||||||
+ t &= 1;
|
|
||||||
+ code -= range & (t - 1);
|
|
||||||
+ result = (result + result) | (1 - t);
|
|
||||||
+ */
|
|
||||||
+ RC_NORMALIZE
|
|
||||||
+ }
|
|
||||||
+ RC_FLUSH_VAR
|
|
||||||
+ return result;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
|
|
||||||
+{
|
|
||||||
+ UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
|
|
||||||
+ if (rd->Code < bound)
|
|
||||||
+ {
|
|
||||||
+ rd->Range = bound;
|
|
||||||
+ *prob += (kBitModelTotal - *prob) >> kNumMoveBits;
|
|
||||||
+ if (rd->Range < kTopValue)
|
|
||||||
+ {
|
|
||||||
+ rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
+ rd->Range <<= 8;
|
|
||||||
+ }
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ rd->Range -= bound;
|
|
||||||
+ rd->Code -= bound;
|
|
||||||
+ *prob -= (*prob) >> kNumMoveBits;
|
|
||||||
+ if (rd->Range < kTopValue)
|
|
||||||
+ {
|
|
||||||
+ rd->Code = (rd->Code << 8) | ReadByte;
|
|
||||||
+ rd->Range <<= 8;
|
|
||||||
+ }
|
|
||||||
+ return 1;
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define RC_GET_BIT2(prob, mi, A0, A1) \
|
|
||||||
+ UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
|
|
||||||
+ if (code < bound) \
|
|
||||||
+ { A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
|
|
||||||
+ else \
|
|
||||||
+ { A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
|
|
||||||
+ RC_NORMALIZE
|
|
||||||
+
|
|
||||||
+#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
|
|
||||||
+
|
|
||||||
+int RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
|
||||||
+{
|
|
||||||
+ int mi = 1;
|
|
||||||
+ int i;
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_INIT_VAR
|
|
||||||
+ #endif
|
|
||||||
+ for(i = numLevels; i > 0; i--)
|
|
||||||
+ {
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ CProb *prob = probs + mi;
|
|
||||||
+ RC_GET_BIT(prob, mi)
|
|
||||||
+ #else
|
|
||||||
+ mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
|
|
||||||
+ #endif
|
|
||||||
+ }
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_FLUSH_VAR
|
|
||||||
+ #endif
|
|
||||||
+ return mi - (1 << numLevels);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
|
|
||||||
+{
|
|
||||||
+ int mi = 1;
|
|
||||||
+ int i;
|
|
||||||
+ int symbol = 0;
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_INIT_VAR
|
|
||||||
+ #endif
|
|
||||||
+ for(i = 0; i < numLevels; i++)
|
|
||||||
+ {
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ CProb *prob = probs + mi;
|
|
||||||
+ RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
|
|
||||||
+ #else
|
|
||||||
+ int bit = RangeDecoderBitDecode(probs + mi, rd);
|
|
||||||
+ mi = mi + mi + bit;
|
|
||||||
+ symbol |= (bit << i);
|
|
||||||
+ #endif
|
|
||||||
+ }
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_FLUSH_VAR
|
|
||||||
+ #endif
|
|
||||||
+ return symbol;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+Byte LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
|
|
||||||
+{
|
|
||||||
+ int symbol = 1;
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_INIT_VAR
|
|
||||||
+ #endif
|
|
||||||
+ do
|
|
||||||
+ {
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ CProb *prob = probs + symbol;
|
|
||||||
+ RC_GET_BIT(prob, symbol)
|
|
||||||
+ #else
|
|
||||||
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
|
||||||
+ #endif
|
|
||||||
+ }
|
|
||||||
+ while (symbol < 0x100);
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_FLUSH_VAR
|
|
||||||
+ #endif
|
|
||||||
+ return symbol;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+Byte LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
|
|
||||||
+{
|
|
||||||
+ int symbol = 1;
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_INIT_VAR
|
|
||||||
+ #endif
|
|
||||||
+ do
|
|
||||||
+ {
|
|
||||||
+ int bit;
|
|
||||||
+ int matchBit = (matchByte >> 7) & 1;
|
|
||||||
+ matchByte <<= 1;
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ {
|
|
||||||
+ CProb *prob = probs + ((1 + matchBit) << 8) + symbol;
|
|
||||||
+ RC_GET_BIT2(prob, symbol, bit = 0, bit = 1)
|
|
||||||
+ }
|
|
||||||
+ #else
|
|
||||||
+ bit = RangeDecoderBitDecode(probs + ((1 + matchBit) << 8) + symbol, rd);
|
|
||||||
+ symbol = (symbol << 1) | bit;
|
|
||||||
+ #endif
|
|
||||||
+ if (matchBit != bit)
|
|
||||||
+ {
|
|
||||||
+ while (symbol < 0x100)
|
|
||||||
+ {
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ CProb *prob = probs + symbol;
|
|
||||||
+ RC_GET_BIT(prob, symbol)
|
|
||||||
+ #else
|
|
||||||
+ symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
|
|
||||||
+ #endif
|
|
||||||
+ }
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ while (symbol < 0x100);
|
|
||||||
+ #ifdef _LZMA_LOC_OPT
|
|
||||||
+ RC_FLUSH_VAR
|
|
||||||
+ #endif
|
|
||||||
+ return symbol;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define kNumPosBitsMax 4
|
|
||||||
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
|
|
||||||
+
|
|
||||||
+#define kLenNumLowBits 3
|
|
||||||
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
|
|
||||||
+#define kLenNumMidBits 3
|
|
||||||
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
|
|
||||||
+#define kLenNumHighBits 8
|
|
||||||
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
|
|
||||||
+
|
|
||||||
+#define LenChoice 0
|
|
||||||
+#define LenChoice2 (LenChoice + 1)
|
|
||||||
+#define LenLow (LenChoice2 + 1)
|
|
||||||
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
|
|
||||||
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
|
|
||||||
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
|
|
||||||
+
|
|
||||||
+int LzmaLenDecode(CProb *p, CRangeDecoder *rd, int posState)
|
|
||||||
+{
|
|
||||||
+ if(RangeDecoderBitDecode(p + LenChoice, rd) == 0)
|
|
||||||
+ return RangeDecoderBitTreeDecode(p + LenLow +
|
|
||||||
+ (posState << kLenNumLowBits), kLenNumLowBits, rd);
|
|
||||||
+ if(RangeDecoderBitDecode(p + LenChoice2, rd) == 0)
|
|
||||||
+ return kLenNumLowSymbols + RangeDecoderBitTreeDecode(p + LenMid +
|
|
||||||
+ (posState << kLenNumMidBits), kLenNumMidBits, rd);
|
|
||||||
+ return kLenNumLowSymbols + kLenNumMidSymbols +
|
|
||||||
+ RangeDecoderBitTreeDecode(p + LenHigh, kLenNumHighBits, rd);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#define kNumStates 12
|
|
||||||
+
|
|
||||||
+#define kStartPosModelIndex 4
|
|
||||||
+#define kEndPosModelIndex 14
|
|
||||||
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
|
|
||||||
+
|
|
||||||
+#define kNumPosSlotBits 6
|
|
||||||
+#define kNumLenToPosStates 4
|
|
||||||
+
|
|
||||||
+#define kNumAlignBits 4
|
|
||||||
+#define kAlignTableSize (1 << kNumAlignBits)
|
|
||||||
+
|
|
||||||
+#define kMatchMinLen 2
|
|
||||||
+
|
|
||||||
+#define IsMatch 0
|
|
||||||
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
|
|
||||||
+#define IsRepG0 (IsRep + kNumStates)
|
|
||||||
+#define IsRepG1 (IsRepG0 + kNumStates)
|
|
||||||
+#define IsRepG2 (IsRepG1 + kNumStates)
|
|
||||||
+#define IsRep0Long (IsRepG2 + kNumStates)
|
|
||||||
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
|
|
||||||
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
|
|
||||||
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
|
|
||||||
+#define LenCoder (Align + kAlignTableSize)
|
|
||||||
+#define RepLenCoder (LenCoder + kNumLenProbs)
|
|
||||||
+#define Literal (RepLenCoder + kNumLenProbs)
|
|
||||||
+
|
|
||||||
+#if Literal != LZMA_BASE_SIZE
|
|
||||||
+StopCompilingDueBUG
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifdef _LZMA_OUT_READ
|
|
||||||
+
|
|
||||||
+typedef struct _LzmaVarState
|
|
||||||
+{
|
|
||||||
+ CRangeDecoder RangeDecoder;
|
|
||||||
+ Byte *Dictionary;
|
|
||||||
+ UInt32 DictionarySize;
|
|
||||||
+ UInt32 DictionaryPos;
|
|
||||||
+ UInt32 GlobalPos;
|
|
||||||
+ UInt32 Reps[4];
|
|
||||||
+ int lc;
|
|
||||||
+ int lp;
|
|
||||||
+ int pb;
|
|
||||||
+ int State;
|
|
||||||
+ int PreviousIsMatch;
|
|
||||||
+ int RemainLen;
|
|
||||||
+} LzmaVarState;
|
|
||||||
+
|
|
||||||
+int LzmaDecoderInit(
|
|
||||||
+ unsigned char *buffer, UInt32 bufferSize,
|
|
||||||
+ int lc, int lp, int pb,
|
|
||||||
+ unsigned char *dictionary, UInt32 dictionarySize,
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ ILzmaInCallback *inCallback
|
|
||||||
+ #else
|
|
||||||
+ unsigned char *inStream, UInt32 inSize
|
|
||||||
+ #endif
|
|
||||||
+ )
|
|
||||||
+{
|
|
||||||
+ LzmaVarState *vs = (LzmaVarState *)buffer;
|
|
||||||
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
|
|
||||||
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
|
|
||||||
+ UInt32 i;
|
|
||||||
+ if (bufferSize < numProbs * sizeof(CProb) + sizeof(LzmaVarState))
|
|
||||||
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
|
|
||||||
+ vs->Dictionary = dictionary;
|
|
||||||
+ vs->DictionarySize = dictionarySize;
|
|
||||||
+ vs->DictionaryPos = 0;
|
|
||||||
+ vs->GlobalPos = 0;
|
|
||||||
+ vs->Reps[0] = vs->Reps[1] = vs->Reps[2] = vs->Reps[3] = 1;
|
|
||||||
+ vs->lc = lc;
|
|
||||||
+ vs->lp = lp;
|
|
||||||
+ vs->pb = pb;
|
|
||||||
+ vs->State = 0;
|
|
||||||
+ vs->PreviousIsMatch = 0;
|
|
||||||
+ vs->RemainLen = 0;
|
|
||||||
+ dictionary[dictionarySize - 1] = 0;
|
|
||||||
+ for (i = 0; i < numProbs; i++)
|
|
||||||
+ p[i] = kBitModelTotal >> 1;
|
|
||||||
+ RangeDecoderInit(&vs->RangeDecoder,
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ inCallback
|
|
||||||
+ #else
|
|
||||||
+ inStream, inSize
|
|
||||||
+ #endif
|
|
||||||
+ );
|
|
||||||
+ return LZMA_RESULT_OK;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int LzmaDecode(unsigned char *buffer,
|
|
||||||
+ unsigned char *outStream, UInt32 outSize,
|
|
||||||
+ UInt32 *outSizeProcessed)
|
|
||||||
+{
|
|
||||||
+ LzmaVarState *vs = (LzmaVarState *)buffer;
|
|
||||||
+ CProb *p = (CProb *)(buffer + sizeof(LzmaVarState));
|
|
||||||
+ CRangeDecoder rd = vs->RangeDecoder;
|
|
||||||
+ int state = vs->State;
|
|
||||||
+ int previousIsMatch = vs->PreviousIsMatch;
|
|
||||||
+ Byte previousByte;
|
|
||||||
+ UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3];
|
|
||||||
+ UInt32 nowPos = 0;
|
|
||||||
+ UInt32 posStateMask = (1 << (vs->pb)) - 1;
|
|
||||||
+ UInt32 literalPosMask = (1 << (vs->lp)) - 1;
|
|
||||||
+ int lc = vs->lc;
|
|
||||||
+ int len = vs->RemainLen;
|
|
||||||
+ UInt32 globalPos = vs->GlobalPos;
|
|
||||||
+
|
|
||||||
+ Byte *dictionary = vs->Dictionary;
|
|
||||||
+ UInt32 dictionarySize = vs->DictionarySize;
|
|
||||||
+ UInt32 dictionaryPos = vs->DictionaryPos;
|
|
||||||
+
|
|
||||||
+ if (len == -1)
|
|
||||||
+ {
|
|
||||||
+ *outSizeProcessed = 0;
|
|
||||||
+ return LZMA_RESULT_OK;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ while(len > 0 && nowPos < outSize)
|
|
||||||
+ {
|
|
||||||
+ UInt32 pos = dictionaryPos - rep0;
|
|
||||||
+ if (pos >= dictionarySize)
|
|
||||||
+ pos += dictionarySize;
|
|
||||||
+ outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos];
|
|
||||||
+ if (++dictionaryPos == dictionarySize)
|
|
||||||
+ dictionaryPos = 0;
|
|
||||||
+ len--;
|
|
||||||
+ }
|
|
||||||
+ if (dictionaryPos == 0)
|
|
||||||
+ previousByte = dictionary[dictionarySize - 1];
|
|
||||||
+ else
|
|
||||||
+ previousByte = dictionary[dictionaryPos - 1];
|
|
||||||
+#else
|
|
||||||
+
|
|
||||||
+int LzmaDecode(
|
|
||||||
+ Byte *buffer, UInt32 bufferSize,
|
|
||||||
+ int lc, int lp, int pb,
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ ILzmaInCallback *inCallback,
|
|
||||||
+ #else
|
|
||||||
+ unsigned char *inStream, UInt32 inSize,
|
|
||||||
+ #endif
|
|
||||||
+ unsigned char *outStream, UInt32 outSize,
|
|
||||||
+ UInt32 *outSizeProcessed)
|
|
||||||
+{
|
|
||||||
+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + lp));
|
|
||||||
+ CProb *p = (CProb *)buffer;
|
|
||||||
+ CRangeDecoder rd;
|
|
||||||
+ UInt32 i;
|
|
||||||
+ int state = 0;
|
|
||||||
+ int previousIsMatch = 0;
|
|
||||||
+ Byte previousByte = 0;
|
|
||||||
+ UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
|
|
||||||
+ UInt32 nowPos = 0;
|
|
||||||
+ UInt32 posStateMask = (1 << pb) - 1;
|
|
||||||
+ UInt32 literalPosMask = (1 << lp) - 1;
|
|
||||||
+ int len = 0;
|
|
||||||
+ if (bufferSize < numProbs * sizeof(CProb))
|
|
||||||
+ return LZMA_RESULT_NOT_ENOUGH_MEM;
|
|
||||||
+ for (i = 0; i < numProbs; i++)
|
|
||||||
+ p[i] = kBitModelTotal >> 1;
|
|
||||||
+ RangeDecoderInit(&rd,
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ inCallback
|
|
||||||
+ #else
|
|
||||||
+ inStream, inSize
|
|
||||||
+ #endif
|
|
||||||
+ );
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ *outSizeProcessed = 0;
|
|
||||||
+ while(nowPos < outSize)
|
|
||||||
+ {
|
|
||||||
+ int posState = (int)(
|
|
||||||
+ (nowPos
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ + globalPos
|
|
||||||
+ #endif
|
|
||||||
+ )
|
|
||||||
+ & posStateMask);
|
|
||||||
+ #ifdef _LZMA_IN_CB
|
|
||||||
+ if (rd.Result != LZMA_RESULT_OK)
|
|
||||||
+ return rd.Result;
|
|
||||||
+ #endif
|
|
||||||
+ if (rd.ExtraBytes != 0)
|
|
||||||
+ return LZMA_RESULT_DATA_ERROR;
|
|
||||||
+ if (RangeDecoderBitDecode(p + IsMatch + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
|
||||||
+ {
|
|
||||||
+ CProb *probs = p + Literal + (LZMA_LIT_SIZE *
|
|
||||||
+ (((
|
|
||||||
+ (nowPos
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ + globalPos
|
|
||||||
+ #endif
|
|
||||||
+ )
|
|
||||||
+ & literalPosMask) << lc) + (previousByte >> (8 - lc))));
|
|
||||||
+
|
|
||||||
+ if (state < 4) state = 0;
|
|
||||||
+ else if (state < 10) state -= 3;
|
|
||||||
+ else state -= 6;
|
|
||||||
+ if (previousIsMatch)
|
|
||||||
+ {
|
|
||||||
+ Byte matchByte;
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ UInt32 pos = dictionaryPos - rep0;
|
|
||||||
+ if (pos >= dictionarySize)
|
|
||||||
+ pos += dictionarySize;
|
|
||||||
+ matchByte = dictionary[pos];
|
|
||||||
+ #else
|
|
||||||
+ matchByte = outStream[nowPos - rep0];
|
|
||||||
+ #endif
|
|
||||||
+ previousByte = LzmaLiteralDecodeMatch(probs, &rd, matchByte);
|
|
||||||
+ previousIsMatch = 0;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ previousByte = LzmaLiteralDecode(probs, &rd);
|
|
||||||
+ outStream[nowPos++] = previousByte;
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ dictionary[dictionaryPos] = previousByte;
|
|
||||||
+ if (++dictionaryPos == dictionarySize)
|
|
||||||
+ dictionaryPos = 0;
|
|
||||||
+ #endif
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ previousIsMatch = 1;
|
|
||||||
+ if (RangeDecoderBitDecode(p + IsRep + state, &rd) == 1)
|
|
||||||
+ {
|
|
||||||
+ if (RangeDecoderBitDecode(p + IsRepG0 + state, &rd) == 0)
|
|
||||||
+ {
|
|
||||||
+ if (RangeDecoderBitDecode(p + IsRep0Long + (state << kNumPosBitsMax) + posState, &rd) == 0)
|
|
||||||
+ {
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ UInt32 pos;
|
|
||||||
+ #endif
|
|
||||||
+ if (
|
|
||||||
+ (nowPos
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ + globalPos
|
|
||||||
+ #endif
|
|
||||||
+ )
|
|
||||||
+ == 0)
|
|
||||||
+ return LZMA_RESULT_DATA_ERROR;
|
|
||||||
+ state = state < 7 ? 9 : 11;
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ pos = dictionaryPos - rep0;
|
|
||||||
+ if (pos >= dictionarySize)
|
|
||||||
+ pos += dictionarySize;
|
|
||||||
+ previousByte = dictionary[pos];
|
|
||||||
+ dictionary[dictionaryPos] = previousByte;
|
|
||||||
+ if (++dictionaryPos == dictionarySize)
|
|
||||||
+ dictionaryPos = 0;
|
|
||||||
+ #else
|
|
||||||
+ previousByte = outStream[nowPos - rep0];
|
|
||||||
+ #endif
|
|
||||||
+ outStream[nowPos++] = previousByte;
|
|
||||||
+ continue;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ UInt32 distance;
|
|
||||||
+ if(RangeDecoderBitDecode(p + IsRepG1 + state, &rd) == 0)
|
|
||||||
+ distance = rep1;
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ if(RangeDecoderBitDecode(p + IsRepG2 + state, &rd) == 0)
|
|
||||||
+ distance = rep2;
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ distance = rep3;
|
|
||||||
+ rep3 = rep2;
|
|
||||||
+ }
|
|
||||||
+ rep2 = rep1;
|
|
||||||
+ }
|
|
||||||
+ rep1 = rep0;
|
|
||||||
+ rep0 = distance;
|
|
||||||
+ }
|
|
||||||
+ len = LzmaLenDecode(p + RepLenCoder, &rd, posState);
|
|
||||||
+ state = state < 7 ? 8 : 11;
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ int posSlot;
|
|
||||||
+ rep3 = rep2;
|
|
||||||
+ rep2 = rep1;
|
|
||||||
+ rep1 = rep0;
|
|
||||||
+ state = state < 7 ? 7 : 10;
|
|
||||||
+ len = LzmaLenDecode(p + LenCoder, &rd, posState);
|
|
||||||
+ posSlot = RangeDecoderBitTreeDecode(p + PosSlot +
|
|
||||||
+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
|
|
||||||
+ kNumPosSlotBits), kNumPosSlotBits, &rd);
|
|
||||||
+ if (posSlot >= kStartPosModelIndex)
|
|
||||||
+ {
|
|
||||||
+ int numDirectBits = ((posSlot >> 1) - 1);
|
|
||||||
+ rep0 = ((2 | ((UInt32)posSlot & 1)) << numDirectBits);
|
|
||||||
+ if (posSlot < kEndPosModelIndex)
|
|
||||||
+ {
|
|
||||||
+ rep0 += RangeDecoderReverseBitTreeDecode(
|
|
||||||
+ p + SpecPos + rep0 - posSlot - 1, numDirectBits, &rd);
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ {
|
|
||||||
+ rep0 += RangeDecoderDecodeDirectBits(&rd,
|
|
||||||
+ numDirectBits - kNumAlignBits) << kNumAlignBits;
|
|
||||||
+ rep0 += RangeDecoderReverseBitTreeDecode(p + Align, kNumAlignBits, &rd);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ else
|
|
||||||
+ rep0 = posSlot;
|
|
||||||
+ rep0++;
|
|
||||||
+ }
|
|
||||||
+ if (rep0 == (UInt32)(0))
|
|
||||||
+ {
|
|
||||||
+ /* it's for stream version */
|
|
||||||
+ len = -1;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ if (rep0 > nowPos
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ + globalPos
|
|
||||||
+ #endif
|
|
||||||
+ )
|
|
||||||
+ {
|
|
||||||
+ return LZMA_RESULT_DATA_ERROR;
|
|
||||||
+ }
|
|
||||||
+ len += kMatchMinLen;
|
|
||||||
+ do
|
|
||||||
+ {
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ UInt32 pos = dictionaryPos - rep0;
|
|
||||||
+ if (pos >= dictionarySize)
|
|
||||||
+ pos += dictionarySize;
|
|
||||||
+ previousByte = dictionary[pos];
|
|
||||||
+ dictionary[dictionaryPos] = previousByte;
|
|
||||||
+ if (++dictionaryPos == dictionarySize)
|
|
||||||
+ dictionaryPos = 0;
|
|
||||||
+ #else
|
|
||||||
+ previousByte = outStream[nowPos - rep0];
|
|
||||||
+ #endif
|
|
||||||
+ outStream[nowPos++] = previousByte;
|
|
||||||
+ len--;
|
|
||||||
+ }
|
|
||||||
+ while(len > 0 && nowPos < outSize);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ #ifdef _LZMA_OUT_READ
|
|
||||||
+ vs->RangeDecoder = rd;
|
|
||||||
+ vs->DictionaryPos = dictionaryPos;
|
|
||||||
+ vs->GlobalPos = globalPos + nowPos;
|
|
||||||
+ vs->Reps[0] = rep0;
|
|
||||||
+ vs->Reps[1] = rep1;
|
|
||||||
+ vs->Reps[2] = rep2;
|
|
||||||
+ vs->Reps[3] = rep3;
|
|
||||||
+ vs->State = state;
|
|
||||||
+ vs->PreviousIsMatch = previousIsMatch;
|
|
||||||
+ vs->RemainLen = len;
|
|
||||||
+ #endif
|
|
||||||
+
|
|
||||||
+ *outSizeProcessed = nowPos;
|
|
||||||
+ return LZMA_RESULT_OK;
|
|
||||||
+}
|
|
||||||
--- a/lib/Makefile
|
|
||||||
+++ b/lib/Makefile
|
|
||||||
@@ -20,7 +20,7 @@ lib-y += kobject.o kref.o klist.o
|
|
||||||
|
|
||||||
obj-y += bcd.o div64.o sort.o parser.o halfmd4.o debug_locks.o random32.o \
|
|
||||||
bust_spinlocks.o hexdump.o kasprintf.o bitmap.o scatterlist.o \
|
|
||||||
- string_helpers.o
|
|
||||||
+ string_helpers.o LzmaDecode.o
|
|
||||||
|
|
||||||
ifeq ($(CONFIG_DEBUG_KOBJECT),y)
|
|
||||||
CFLAGS_kobject.o += -DDEBUG
|
|
|
@ -1,107 +0,0 @@
|
||||||
--- a/fs/squashfs/inode.c
|
|
||||||
+++ b/fs/squashfs/inode.c
|
|
||||||
@@ -4,6 +4,9 @@
|
|
||||||
* Copyright (c) 2002, 2003, 2004, 2005, 2006
|
|
||||||
* Phillip Lougher <phillip@lougher.org.uk>
|
|
||||||
*
|
|
||||||
+ * LZMA decompressor support added by Oleg I. Vdovikin
|
|
||||||
+ * Copyright (c) 2005 Oleg I.Vdovikin <oleg@cs.msu.su>
|
|
||||||
+ *
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* as published by the Free Software Foundation; either version 2,
|
|
||||||
@@ -21,6 +24,7 @@
|
|
||||||
* inode.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#define SQUASHFS_LZMA
|
|
||||||
#include <linux/types.h>
|
|
||||||
#include <linux/squashfs_fs.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
@@ -44,6 +48,19 @@
|
|
||||||
|
|
||||||
#include "squashfs.h"
|
|
||||||
|
|
||||||
+#ifdef SQUASHFS_LZMA
|
|
||||||
+#include <linux/LzmaDecode.h>
|
|
||||||
+
|
|
||||||
+/* default LZMA settings, should be in sync with mksquashfs */
|
|
||||||
+#define LZMA_LC 3
|
|
||||||
+#define LZMA_LP 0
|
|
||||||
+#define LZMA_PB 2
|
|
||||||
+
|
|
||||||
+#define LZMA_WORKSPACE_SIZE ((LZMA_BASE_SIZE + \
|
|
||||||
+ (LZMA_LIT_SIZE << (LZMA_LC + LZMA_LP))) * sizeof(CProb))
|
|
||||||
+
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
static void squashfs_put_super(struct super_block *);
|
|
||||||
static int squashfs_statfs(struct dentry *, struct kstatfs *);
|
|
||||||
static int squashfs_symlink_readpage(struct file *file, struct page *page);
|
|
||||||
@@ -64,7 +81,11 @@ static int squashfs_get_sb(struct file_s
|
|
||||||
const char *, void *, struct vfsmount *);
|
|
||||||
|
|
||||||
|
|
||||||
+#ifdef SQUASHFS_LZMA
|
|
||||||
+static unsigned char lzma_workspace[LZMA_WORKSPACE_SIZE];
|
|
||||||
+#else
|
|
||||||
static z_stream stream;
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
static struct file_system_type squashfs_fs_type = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
@@ -249,6 +270,15 @@ SQSH_EXTERN unsigned int squashfs_read_d
|
|
||||||
if (compressed) {
|
|
||||||
int zlib_err;
|
|
||||||
|
|
||||||
+#ifdef SQUASHFS_LZMA
|
|
||||||
+ if ((zlib_err = LzmaDecode(lzma_workspace,
|
|
||||||
+ LZMA_WORKSPACE_SIZE, LZMA_LC, LZMA_LP, LZMA_PB,
|
|
||||||
+ c_buffer, c_byte, buffer, msblk->read_size, &bytes)) != LZMA_RESULT_OK)
|
|
||||||
+ {
|
|
||||||
+ ERROR("lzma returned unexpected result 0x%x\n", zlib_err);
|
|
||||||
+ bytes = 0;
|
|
||||||
+ }
|
|
||||||
+#else
|
|
||||||
stream.next_in = c_buffer;
|
|
||||||
stream.avail_in = c_byte;
|
|
||||||
stream.next_out = buffer;
|
|
||||||
@@ -263,7 +293,7 @@ SQSH_EXTERN unsigned int squashfs_read_d
|
|
||||||
bytes = 0;
|
|
||||||
} else
|
|
||||||
bytes = stream.total_out;
|
|
||||||
-
|
|
||||||
+#endif
|
|
||||||
up(&msblk->read_data_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2045,15 +2075,19 @@ static int __init init_squashfs_fs(void)
|
|
||||||
printk(KERN_INFO "squashfs: version 3.0 (2006/03/15) "
|
|
||||||
"Phillip Lougher\n");
|
|
||||||
|
|
||||||
+#ifndef SQUASHFS_LZMA
|
|
||||||
if (!(stream.workspace = vmalloc(zlib_inflate_workspacesize()))) {
|
|
||||||
ERROR("Failed to allocate zlib workspace\n");
|
|
||||||
destroy_inodecache();
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
if ((err = register_filesystem(&squashfs_fs_type))) {
|
|
||||||
+#ifndef SQUASHFS_LZMA
|
|
||||||
vfree(stream.workspace);
|
|
||||||
+#endif
|
|
||||||
destroy_inodecache();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -2064,7 +2098,9 @@ out:
|
|
||||||
|
|
||||||
static void __exit exit_squashfs_fs(void)
|
|
||||||
{
|
|
||||||
+#ifndef SQUASHFS_LZMA
|
|
||||||
vfree(stream.workspace);
|
|
||||||
+#endif
|
|
||||||
unregister_filesystem(&squashfs_fs_type);
|
|
||||||
destroy_inodecache();
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -512,7 +512,7 @@ all: vmlinux
|
|
||||||
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
|
|
||||||
KBUILD_CFLAGS += -Os
|
|
||||||
else
|
|
||||||
-KBUILD_CFLAGS += -O2
|
|
||||||
+KBUILD_CFLAGS += -O2 -fno-reorder-blocks -fno-tree-ch
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(srctree)/arch/$(SRCARCH)/Makefile
|
|
||||||
@@ -549,6 +549,9 @@ endif
|
|
||||||
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
|
|
||||||
CHECKFLAGS += $(NOSTDINC_FLAGS)
|
|
||||||
|
|
||||||
+# improve gcc optimization
|
|
||||||
+CFLAGS += $(call cc-option,-funit-at-a-time,)
|
|
||||||
+
|
|
||||||
# warn about C99 declaration after statement
|
|
||||||
KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,)
|
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
--- a/fs/squashfs/inode.c
|
|
||||||
+++ b/fs/squashfs/inode.c
|
|
||||||
@@ -33,6 +33,7 @@
|
|
||||||
#include <linux/fs.h>
|
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
#include <linux/slab.h>
|
|
||||||
+#include <linux/exportfs.h>
|
|
||||||
#include <linux/squashfs_fs_sb.h>
|
|
||||||
#include <linux/squashfs_fs_i.h>
|
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
@@ -43,8 +44,8 @@
|
|
||||||
#include <linux/zlib.h>
|
|
||||||
#include <linux/blkdev.h>
|
|
||||||
#include <linux/vmalloc.h>
|
|
||||||
+#include <linux/semaphore.h>
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
-#include <asm/semaphore.h>
|
|
||||||
|
|
||||||
#include "squashfs.h"
|
|
||||||
|
|
||||||
@@ -2125,7 +2126,7 @@ static void squashfs_destroy_inode(struc
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags)
|
|
||||||
+static void init_once(void *foo)
|
|
||||||
{
|
|
||||||
struct squashfs_inode_info *ei = foo;
|
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/arch/mips/include/asm/system.h
|
|
||||||
+++ b/arch/mips/include/asm/system.h
|
|
||||||
@@ -187,7 +187,7 @@ extern __u64 __xchg_u64_unsupported_on_3
|
|
||||||
if something tries to do an invalid xchg(). */
|
|
||||||
extern void __xchg_called_with_bad_pointer(void);
|
|
||||||
|
|
||||||
-static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
|
||||||
+static __always_inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
|
|
||||||
{
|
|
||||||
switch (size) {
|
|
||||||
case 4:
|
|
|
@ -1,36 +0,0 @@
|
||||||
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
|
|
||||||
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
|
|
||||||
@@ -51,6 +51,7 @@
|
|
||||||
#define SST49LF040B 0x0050
|
|
||||||
#define SST49LF008A 0x005a
|
|
||||||
#define AT49BV6416 0x00d6
|
|
||||||
+#define MANUFACTURER_SAMSUNG 0x00ec
|
|
||||||
|
|
||||||
static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *);
|
|
||||||
static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *);
|
|
||||||
@@ -365,12 +366,19 @@ struct mtd_info *cfi_cmdset_0002(struct
|
|
||||||
|
|
||||||
if (extp->MajorVersion != '1' ||
|
|
||||||
(extp->MinorVersion < '0' || extp->MinorVersion > '4')) {
|
|
||||||
- printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
|
||||||
- "version %c.%c.\n", extp->MajorVersion,
|
|
||||||
- extp->MinorVersion);
|
|
||||||
- kfree(extp);
|
|
||||||
- kfree(mtd);
|
|
||||||
- return NULL;
|
|
||||||
+ if (cfi->mfr == MANUFACTURER_SAMSUNG &&
|
|
||||||
+ (extp->MajorVersion == '3' && extp->MinorVersion == '3')) {
|
|
||||||
+ printk(KERN_NOTICE " Newer Samsung flash detected, "
|
|
||||||
+ "should be compatibile with Amd/Fujitsu.\n");
|
|
||||||
+ }
|
|
||||||
+ else {
|
|
||||||
+ printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query "
|
|
||||||
+ "version %c.%c.\n", extp->MajorVersion,
|
|
||||||
+ extp->MinorVersion);
|
|
||||||
+ kfree(extp);
|
|
||||||
+ kfree(mtd);
|
|
||||||
+ return NULL;
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Install our own private info structure */
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/fs/squashfs/inode.c
|
|
||||||
+++ b/fs/squashfs/inode.c
|
|
||||||
@@ -1179,7 +1179,7 @@ failure:
|
|
||||||
|
|
||||||
static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf)
|
|
||||||
{
|
|
||||||
- struct squashfs_sb_info *msblk = dentry->d_inode->i_sb->s_fs_info;
|
|
||||||
+ struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info;
|
|
||||||
struct squashfs_super_block *sblk = &msblk->sblk;
|
|
||||||
|
|
||||||
TRACE("Entered squashfs_statfs\n");
|
|
|
@ -1,19 +0,0 @@
|
||||||
--- a/fs/squashfs/Makefile
|
|
||||||
+++ b/fs/squashfs/Makefile
|
|
||||||
@@ -4,4 +4,3 @@
|
|
||||||
|
|
||||||
obj-$(CONFIG_SQUASHFS) += squashfs.o
|
|
||||||
squashfs-y += inode.o
|
|
||||||
-squashfs-y += squashfs2_0.o
|
|
||||||
--- a/fs/squashfs/squashfs.h
|
|
||||||
+++ b/fs/squashfs/squashfs.h
|
|
||||||
@@ -24,6 +24,9 @@
|
|
||||||
#ifdef CONFIG_SQUASHFS_1_0_COMPATIBILITY
|
|
||||||
#undef CONFIG_SQUASHFS_1_0_COMPATIBILITY
|
|
||||||
#endif
|
|
||||||
+#ifdef CONFIG_SQUASHFS_2_0_COMPATIBILITY
|
|
||||||
+#undef CONFIG_SQUASHFS_2_0_COMPATIBILITY
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
#ifdef SQUASHFS_TRACE
|
|
||||||
#define TRACE(s, args...) printk(KERN_NOTICE "SQUASHFS: "s, ## args)
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/arch/mips/kernel/head.S
|
|
||||||
+++ b/arch/mips/kernel/head.S
|
|
||||||
@@ -121,6 +121,8 @@
|
|
||||||
#endif
|
|
||||||
.endm
|
|
||||||
|
|
||||||
+ j kernel_entry
|
|
||||||
+ nop
|
|
||||||
#ifndef CONFIG_NO_EXCEPT_FILL
|
|
||||||
/*
|
|
||||||
* Reserved space for exception handlers.
|
|
|
@ -1,157 +0,0 @@
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/asm-mips/mips_machine.h
|
|
||||||
@@ -0,0 +1,47 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
+ *
|
|
||||||
+ * 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.
|
|
||||||
+ *
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef __ASM_MIPS_MACHINE_H
|
|
||||||
+#define __ASM_MIPS_MACHINE_H
|
|
||||||
+
|
|
||||||
+#include <linux/init.h>
|
|
||||||
+#include <linux/list.h>
|
|
||||||
+
|
|
||||||
+#define MIPS_MACHINE_NAME_LEN 64
|
|
||||||
+
|
|
||||||
+struct mips_machine {
|
|
||||||
+ unsigned long mach_type;
|
|
||||||
+ void (*mach_setup)(void);
|
|
||||||
+ unsigned char mach_name[MIPS_MACHINE_NAME_LEN];
|
|
||||||
+ struct list_head list;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+void mips_machine_register(struct mips_machine *) __init;
|
|
||||||
+void mips_machine_setup(unsigned long machtype) __init;
|
|
||||||
+
|
|
||||||
+extern unsigned char mips_machine_name[MIPS_MACHINE_NAME_LEN];
|
|
||||||
+
|
|
||||||
+#define MIPS_MACHINE(_type, _name, _setup) \
|
|
||||||
+static struct mips_machine machine_##_type __initdata = \
|
|
||||||
+{ \
|
|
||||||
+ .mach_type = _type, \
|
|
||||||
+ .mach_name = _name, \
|
|
||||||
+ .mach_setup = _setup, \
|
|
||||||
+}; \
|
|
||||||
+ \
|
|
||||||
+static int __init register_machine_##_type(void) \
|
|
||||||
+{ \
|
|
||||||
+ mips_machine_register(&machine_##_type); \
|
|
||||||
+ return 0; \
|
|
||||||
+} \
|
|
||||||
+ \
|
|
||||||
+pure_initcall(register_machine_##_type)
|
|
||||||
+
|
|
||||||
+#endif /* __ASM_MIPS_MACHINE_H */
|
|
||||||
+
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/arch/mips/kernel/mips_machine.c
|
|
||||||
@@ -0,0 +1,58 @@
|
|
||||||
+/*
|
|
||||||
+ * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
+ *
|
|
||||||
+ * 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.
|
|
||||||
+ *
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <asm/mips_machine.h>
|
|
||||||
+#include <asm/bootinfo.h>
|
|
||||||
+
|
|
||||||
+static struct list_head mips_machines __initdata =
|
|
||||||
+ LIST_HEAD_INIT(mips_machines);
|
|
||||||
+
|
|
||||||
+unsigned char mips_machine_name[MIPS_MACHINE_NAME_LEN] = "Unknown";
|
|
||||||
+
|
|
||||||
+static struct mips_machine * __init mips_machine_find(unsigned long machtype)
|
|
||||||
+{
|
|
||||||
+ struct list_head *this;
|
|
||||||
+
|
|
||||||
+ list_for_each(this, &mips_machines) {
|
|
||||||
+ struct mips_machine *mach;
|
|
||||||
+
|
|
||||||
+ mach = list_entry(this, struct mips_machine, list);
|
|
||||||
+ if (mach->mach_type == machtype)
|
|
||||||
+ return mach;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void __init mips_machine_register(struct mips_machine *mach)
|
|
||||||
+{
|
|
||||||
+ list_add_tail(&mach->list, &mips_machines);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+void __init mips_machine_setup(unsigned long machtype)
|
|
||||||
+{
|
|
||||||
+ struct mips_machine *mach;
|
|
||||||
+
|
|
||||||
+ mach = mips_machine_find(machtype);
|
|
||||||
+ if (!mach) {
|
|
||||||
+ printk(KERN_ALERT "MIPS: no machine registered for "
|
|
||||||
+ "machtype %lu\n", machtype);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (mach->mach_name[0])
|
|
||||||
+ strncpy(mips_machine_name, mach->mach_name,
|
|
||||||
+ MIPS_MACHINE_NAME_LEN);
|
|
||||||
+
|
|
||||||
+ printk(KERN_INFO "MIPS: machine is %s\n", mips_machine_name);
|
|
||||||
+
|
|
||||||
+ if (mach->mach_setup)
|
|
||||||
+ mach->mach_setup();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
--- a/arch/mips/kernel/Makefile
|
|
||||||
+++ b/arch/mips/kernel/Makefile
|
|
||||||
@@ -84,6 +84,7 @@ obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o
|
|
||||||
|
|
||||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
|
||||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
|
||||||
+obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o
|
|
||||||
|
|
||||||
CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
|
|
||||||
|
|
||||||
--- a/arch/mips/Kconfig
|
|
||||||
+++ b/arch/mips/Kconfig
|
|
||||||
@@ -763,6 +763,9 @@ config MIPS_DISABLE_OBSOLETE_IDE
|
|
||||||
config SYNC_R4K
|
|
||||||
bool
|
|
||||||
|
|
||||||
+config MIPS_MACHINE
|
|
||||||
+ def_bool n
|
|
||||||
+
|
|
||||||
config NO_IOPORT
|
|
||||||
def_bool n
|
|
||||||
|
|
||||||
--- a/arch/mips/kernel/proc.c
|
|
||||||
+++ b/arch/mips/kernel/proc.c
|
|
||||||
@@ -14,6 +14,7 @@
|
|
||||||
#include <asm/cpu-features.h>
|
|
||||||
#include <asm/mipsregs.h>
|
|
||||||
#include <asm/processor.h>
|
|
||||||
+#include <asm/mips_machine.h>
|
|
||||||
|
|
||||||
unsigned int vced_count, vcei_count;
|
|
||||||
|
|
||||||
@@ -33,8 +34,12 @@ static int show_cpuinfo(struct seq_file
|
|
||||||
/*
|
|
||||||
* For the first processor also print the system type
|
|
||||||
*/
|
|
||||||
- if (n == 0)
|
|
||||||
+ if (n == 0) {
|
|
||||||
seq_printf(m, "system type\t\t: %s\n", get_system_type());
|
|
||||||
+#ifdef CONFIG_MIPS_MACHINE
|
|
||||||
+ seq_printf(m, "machine\t\t\t: %s\n", mips_machine_name);
|
|
||||||
+#endif
|
|
||||||
+ }
|
|
||||||
|
|
||||||
seq_printf(m, "processor\t\t: %ld\n", n);
|
|
||||||
sprintf(fmt, "cpu model\t\t: %%s V%%d.%%d%s\n",
|
|
|
@ -1,28 +0,0 @@
|
||||||
--- a/arch/mips/Kconfig
|
|
||||||
+++ b/arch/mips/Kconfig
|
|
||||||
@@ -766,6 +766,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
|
|
||||||
@@ -143,6 +143,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,171 +0,0 @@
|
||||||
From: Ralf Baechle <ralf@linux-mips.org>
|
|
||||||
Date: Thu, 30 Apr 2009 16:14:56 +0000 (+0200)
|
|
||||||
Subject: MIPS: Rewrite <asm/div64.h> to work with gcc 4.4.0.
|
|
||||||
X-Git-Url: http://www.linux-mips.org/git?p=linux.git;a=commitdiff_plain;h=a1b68289997030df64cba8478d5767fe10e42a58
|
|
||||||
|
|
||||||
MIPS: Rewrite <asm/div64.h> to work with gcc 4.4.0.
|
|
||||||
|
|
||||||
The inline assembler used on 32-bit kernels was using the "h" constraint
|
|
||||||
which was considered dangerous and removed for gcc 4.4.0.
|
|
||||||
|
|
||||||
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
|
|
||||||
---
|
|
||||||
|
|
||||||
--- a/arch/mips/include/asm/div64.h
|
|
||||||
+++ b/arch/mips/include/asm/div64.h
|
|
||||||
@@ -6,105 +6,63 @@
|
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
-#ifndef _ASM_DIV64_H
|
|
||||||
-#define _ASM_DIV64_H
|
|
||||||
+#ifndef __ASM_DIV64_H
|
|
||||||
+#define __ASM_DIV64_H
|
|
||||||
|
|
||||||
-#include <linux/types.h>
|
|
||||||
+#include <asm-generic/div64.h>
|
|
||||||
|
|
||||||
-#if (_MIPS_SZLONG == 32)
|
|
||||||
+#if BITS_PER_LONG == 64
|
|
||||||
|
|
||||||
-#include <asm/compiler.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* No traps on overflows for any of these...
|
|
||||||
*/
|
|
||||||
|
|
||||||
-#define do_div64_32(res, high, low, base) ({ \
|
|
||||||
- unsigned long __quot32, __mod32; \
|
|
||||||
- unsigned long __cf, __tmp, __tmp2, __i; \
|
|
||||||
- \
|
|
||||||
- __asm__(".set push\n\t" \
|
|
||||||
- ".set noat\n\t" \
|
|
||||||
- ".set noreorder\n\t" \
|
|
||||||
- "move %2, $0\n\t" \
|
|
||||||
- "move %3, $0\n\t" \
|
|
||||||
- "b 1f\n\t" \
|
|
||||||
- " li %4, 0x21\n" \
|
|
||||||
- "0:\n\t" \
|
|
||||||
- "sll $1, %0, 0x1\n\t" \
|
|
||||||
- "srl %3, %0, 0x1f\n\t" \
|
|
||||||
- "or %0, $1, %5\n\t" \
|
|
||||||
- "sll %1, %1, 0x1\n\t" \
|
|
||||||
- "sll %2, %2, 0x1\n" \
|
|
||||||
- "1:\n\t" \
|
|
||||||
- "bnez %3, 2f\n\t" \
|
|
||||||
- " sltu %5, %0, %z6\n\t" \
|
|
||||||
- "bnez %5, 3f\n" \
|
|
||||||
- "2:\n\t" \
|
|
||||||
- " addiu %4, %4, -1\n\t" \
|
|
||||||
- "subu %0, %0, %z6\n\t" \
|
|
||||||
- "addiu %2, %2, 1\n" \
|
|
||||||
- "3:\n\t" \
|
|
||||||
- "bnez %4, 0b\n\t" \
|
|
||||||
- " srl %5, %1, 0x1f\n\t" \
|
|
||||||
- ".set pop" \
|
|
||||||
- : "=&r" (__mod32), "=&r" (__tmp), \
|
|
||||||
- "=&r" (__quot32), "=&r" (__cf), \
|
|
||||||
- "=&r" (__i), "=&r" (__tmp2) \
|
|
||||||
- : "Jr" (base), "0" (high), "1" (low)); \
|
|
||||||
- \
|
|
||||||
- (res) = __quot32; \
|
|
||||||
- __mod32; })
|
|
||||||
-
|
|
||||||
-#define do_div(n, base) ({ \
|
|
||||||
- unsigned long long __quot; \
|
|
||||||
- unsigned long __mod; \
|
|
||||||
- unsigned long long __div; \
|
|
||||||
- unsigned long __upper, __low, __high, __base; \
|
|
||||||
- \
|
|
||||||
- __div = (n); \
|
|
||||||
- __base = (base); \
|
|
||||||
- \
|
|
||||||
- __high = __div >> 32; \
|
|
||||||
- __low = __div; \
|
|
||||||
- __upper = __high; \
|
|
||||||
- \
|
|
||||||
- if (__high) \
|
|
||||||
- __asm__("divu $0, %z2, %z3" \
|
|
||||||
- : "=h" (__upper), "=l" (__high) \
|
|
||||||
- : "Jr" (__high), "Jr" (__base) \
|
|
||||||
- : GCC_REG_ACCUM); \
|
|
||||||
- \
|
|
||||||
- __mod = do_div64_32(__low, __upper, __low, __base); \
|
|
||||||
- \
|
|
||||||
- __quot = __high; \
|
|
||||||
- __quot = __quot << 32 | __low; \
|
|
||||||
- (n) = __quot; \
|
|
||||||
- __mod; })
|
|
||||||
-
|
|
||||||
-#endif /* (_MIPS_SZLONG == 32) */
|
|
||||||
-
|
|
||||||
-#if (_MIPS_SZLONG == 64)
|
|
||||||
-
|
|
||||||
-/*
|
|
||||||
- * Hey, we're already 64-bit, no
|
|
||||||
- * need to play games..
|
|
||||||
- */
|
|
||||||
-#define do_div(n, base) ({ \
|
|
||||||
- unsigned long __quot; \
|
|
||||||
- unsigned int __mod; \
|
|
||||||
- unsigned long __div; \
|
|
||||||
- unsigned int __base; \
|
|
||||||
- \
|
|
||||||
- __div = (n); \
|
|
||||||
- __base = (base); \
|
|
||||||
- \
|
|
||||||
- __mod = __div % __base; \
|
|
||||||
- __quot = __div / __base; \
|
|
||||||
- \
|
|
||||||
- (n) = __quot; \
|
|
||||||
- __mod; })
|
|
||||||
+#define __div64_32(n, base) \
|
|
||||||
+({ \
|
|
||||||
+ unsigned long __cf, __tmp, __tmp2, __i; \
|
|
||||||
+ unsigned long __quot32, __mod32; \
|
|
||||||
+ unsigned long __high, __low; \
|
|
||||||
+ unsigned long long __n; \
|
|
||||||
+ \
|
|
||||||
+ __high = *__n >> 32; \
|
|
||||||
+ __low = __n; \
|
|
||||||
+ __asm__( \
|
|
||||||
+ " .set push \n" \
|
|
||||||
+ " .set noat \n" \
|
|
||||||
+ " .set noreorder \n" \
|
|
||||||
+ " move %2, $0 \n" \
|
|
||||||
+ " move %3, $0 \n" \
|
|
||||||
+ " b 1f \n" \
|
|
||||||
+ " li %4, 0x21 \n" \
|
|
||||||
+ "0: \n" \
|
|
||||||
+ " sll $1, %0, 0x1 \n" \
|
|
||||||
+ " srl %3, %0, 0x1f \n" \
|
|
||||||
+ " or %0, $1, %5 \n" \
|
|
||||||
+ " sll %1, %1, 0x1 \n" \
|
|
||||||
+ " sll %2, %2, 0x1 \n" \
|
|
||||||
+ "1: \n" \
|
|
||||||
+ " bnez %3, 2f \n" \
|
|
||||||
+ " sltu %5, %0, %z6 \n" \
|
|
||||||
+ " bnez %5, 3f \n" \
|
|
||||||
+ "2: \n" \
|
|
||||||
+ " addiu %4, %4, -1 \n" \
|
|
||||||
+ " subu %0, %0, %z6 \n" \
|
|
||||||
+ " addiu %2, %2, 1 \n" \
|
|
||||||
+ "3: \n" \
|
|
||||||
+ " bnez %4, 0b\n\t" \
|
|
||||||
+ " srl %5, %1, 0x1f\n\t" \
|
|
||||||
+ " .set pop" \
|
|
||||||
+ : "=&r" (__mod32), "=&r" (__tmp), \
|
|
||||||
+ "=&r" (__quot32), "=&r" (__cf), \
|
|
||||||
+ "=&r" (__i), "=&r" (__tmp2) \
|
|
||||||
+ : "Jr" (base), "0" (__high), "1" (__low)); \
|
|
||||||
+ \
|
|
||||||
+ (__n) = __quot32; \
|
|
||||||
+ __mod32; \
|
|
||||||
+})
|
|
||||||
|
|
||||||
-#endif /* (_MIPS_SZLONG == 64) */
|
|
||||||
+#endif /* BITS_PER_LONG == 64 */
|
|
||||||
|
|
||||||
-#endif /* _ASM_DIV64_H */
|
|
||||||
+#endif /* __ASM_DIV64_H */
|
|
|
@ -1,152 +0,0 @@
|
||||||
From: Wu Zhangjin <wuzj@lemote.com>
|
|
||||||
|
|
||||||
the gcc 4.4 support for MIPS mostly refer to this PATCH:
|
|
||||||
http://www.nabble.com/-PATCH--MIPS:-Handle-removal-of-%27h%27-constraint-in-GCC-4.4-td22192768.html
|
|
||||||
but have been tuned a little.
|
|
||||||
|
|
||||||
because only gcc 4.4 have loongson-specific support, so, we need to
|
|
||||||
choose the suitable -march argument for gcc <= 4.3 and gcc >= 4.4, and
|
|
||||||
we also need to consider use -march=loongson2e and -march=loongson2f for
|
|
||||||
loongson2e and loongson2f respectively. this is handled by adding two
|
|
||||||
new kernel options: CPU_LOONGSON2E and CPU_LOONGSON2F(thanks for the
|
|
||||||
solutin provided by ZhangLe).
|
|
||||||
|
|
||||||
I have tested it on FuLoong(2f) in 32bit and 64bit with gcc-4.4 and
|
|
||||||
gcc-4.3. so, basically, it works.
|
|
||||||
|
|
||||||
Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
|
|
||||||
---
|
|
||||||
arch/mips/Makefile | 9 +++++-
|
|
||||||
arch/mips/include/asm/compiler.h | 10 ++++++
|
|
||||||
arch/mips/include/asm/delay.h | 58 +++++++++++++++++++++++++------------
|
|
||||||
3 files changed, 57 insertions(+), 20 deletions(-)
|
|
||||||
|
|
||||||
--- a/arch/mips/Makefile
|
|
||||||
+++ b/arch/mips/Makefile
|
|
||||||
@@ -119,7 +119,14 @@ cflags-$(CONFIG_CPU_R4300) += -march=r43
|
|
||||||
cflags-$(CONFIG_CPU_VR41XX) += -march=r4100 -Wa,--trap
|
|
||||||
cflags-$(CONFIG_CPU_R4X00) += -march=r4600 -Wa,--trap
|
|
||||||
cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
|
|
||||||
-cflags-$(CONFIG_CPU_LOONGSON2) += -march=r4600 -Wa,--trap
|
|
||||||
+
|
|
||||||
+# only gcc >= 4.4 have the loongson-specific support
|
|
||||||
+cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap
|
|
||||||
+cflags-$(CONFIG_CPU_LOONGSON2E) += $(shell if [ $(call cc-version) -lt 0440 ] ; then \
|
|
||||||
+ echo $(call cc-option,-march=r4600); else echo $(call cc-option,-march=loongson2e); fi ;)
|
|
||||||
+cflags-$(CONFIG_CPU_LOONGSON2F) += $(shell if [ $(call cc-version) -lt 0440 ] ; then \
|
|
||||||
+ echo $(call cc-option,-march=r4600); else echo $(call cc-option,-march=loongson2f); fi ;)
|
|
||||||
+
|
|
||||||
cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
|
|
||||||
-Wa,-mips32 -Wa,--trap
|
|
||||||
cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
|
|
||||||
--- a/arch/mips/include/asm/compiler.h
|
|
||||||
+++ b/arch/mips/include/asm/compiler.h
|
|
||||||
@@ -1,5 +1,6 @@
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2004, 2007 Maciej W. Rozycki
|
|
||||||
+ * Copyright (C) 2009 Wu Zhangjin, wuzj@lemote.com
|
|
||||||
*
|
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
|
||||||
* License. See the file "COPYING" in the main directory of this archive
|
|
||||||
@@ -16,4 +17,13 @@
|
|
||||||
#define GCC_REG_ACCUM "accum"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
|
|
||||||
+#define GCC_NO_H_CONSTRAINT
|
|
||||||
+#ifdef CONFIG_64BIT
|
|
||||||
+typedef unsigned int uintx_t __attribute__((mode(TI)));
|
|
||||||
+#else
|
|
||||||
+typedef u64 uintx_t;
|
|
||||||
+#endif
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#endif /* _ASM_COMPILER_H */
|
|
||||||
--- a/arch/mips/include/asm/delay.h
|
|
||||||
+++ b/arch/mips/include/asm/delay.h
|
|
||||||
@@ -7,6 +7,7 @@
|
|
||||||
* Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
|
|
||||||
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
|
||||||
* Copyright (C) 2007 Maciej W. Rozycki
|
|
||||||
+ * Copyright (C) 2009 Wu Zhangjin, wuzj@lemote.com
|
|
||||||
*/
|
|
||||||
#ifndef _ASM_DELAY_H
|
|
||||||
#define _ASM_DELAY_H
|
|
||||||
@@ -48,6 +49,43 @@ static inline void __delay(unsigned long
|
|
||||||
: "0" (loops), "r" (1));
|
|
||||||
}
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * convert usecs to loops
|
|
||||||
+ *
|
|
||||||
+ * handle removal of 'h' constraint in GCC 4.4
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#ifndef GCC_NO_H_CONSTRAINT /* gcc <= 4.3 */
|
|
||||||
+static inline unsigned long __usecs_to_loops(unsigned long usecs,
|
|
||||||
+ unsigned long lpj)
|
|
||||||
+{
|
|
||||||
+ unsigned long hi, lo;
|
|
||||||
+
|
|
||||||
+ if (sizeof(long) == 4)
|
|
||||||
+ __asm__("multu\t%2, %3"
|
|
||||||
+ : "=h" (usecs), "=l" (lo)
|
|
||||||
+ : "r" (usecs), "r" (lpj)
|
|
||||||
+ : GCC_REG_ACCUM);
|
|
||||||
+ else if (sizeof(long) == 8 && !R4000_WAR)
|
|
||||||
+ __asm__("dmultu\t%2, %3"
|
|
||||||
+ : "=h" (usecs), "=l" (lo)
|
|
||||||
+ : "r" (usecs), "r" (lpj)
|
|
||||||
+ : GCC_REG_ACCUM);
|
|
||||||
+ else if (sizeof(long) == 8 && R4000_WAR)
|
|
||||||
+ __asm__("dmultu\t%3, %4\n\tmfhi\t%0"
|
|
||||||
+ : "=r" (usecs), "=h" (hi), "=l" (lo)
|
|
||||||
+ : "r" (usecs), "r" (lpj)
|
|
||||||
+ : GCC_REG_ACCUM);
|
|
||||||
+
|
|
||||||
+ return usecs;
|
|
||||||
+}
|
|
||||||
+#else /* GCC_NO_H_CONSTRAINT, gcc >= 4.4 */
|
|
||||||
+static inline unsigned long __usecs_to_loops(unsigned long usecs,
|
|
||||||
+ unsigned long lpj)
|
|
||||||
+{
|
|
||||||
+ return ((uintx_t)usecs * lpj) >> BITS_PER_LONG;
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Division by multiplication: you don't have to worry about
|
|
||||||
@@ -62,8 +100,6 @@ static inline void __delay(unsigned long
|
|
||||||
|
|
||||||
static inline void __udelay(unsigned long usecs, unsigned long lpj)
|
|
||||||
{
|
|
||||||
- unsigned long hi, lo;
|
|
||||||
-
|
|
||||||
/*
|
|
||||||
* The rates of 128 is rounded wrongly by the catchall case
|
|
||||||
* for 64-bit. Excessive precission? Probably ...
|
|
||||||
@@ -77,23 +113,7 @@ static inline void __udelay(unsigned lon
|
|
||||||
0x80000000ULL) >> 32);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
- if (sizeof(long) == 4)
|
|
||||||
- __asm__("multu\t%2, %3"
|
|
||||||
- : "=h" (usecs), "=l" (lo)
|
|
||||||
- : "r" (usecs), "r" (lpj)
|
|
||||||
- : GCC_REG_ACCUM);
|
|
||||||
- else if (sizeof(long) == 8 && !R4000_WAR)
|
|
||||||
- __asm__("dmultu\t%2, %3"
|
|
||||||
- : "=h" (usecs), "=l" (lo)
|
|
||||||
- : "r" (usecs), "r" (lpj)
|
|
||||||
- : GCC_REG_ACCUM);
|
|
||||||
- else if (sizeof(long) == 8 && R4000_WAR)
|
|
||||||
- __asm__("dmultu\t%3, %4\n\tmfhi\t%0"
|
|
||||||
- : "=r" (usecs), "=h" (hi), "=l" (lo)
|
|
||||||
- : "r" (usecs), "r" (lpj)
|
|
||||||
- : GCC_REG_ACCUM);
|
|
||||||
-
|
|
||||||
- __delay(usecs);
|
|
||||||
+ __delay(__usecs_to_loops(usecs, lpj));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val
|
|
|
@ -1,155 +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
|
|
||||||
@@ -751,6 +751,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,12 +2,14 @@
|
|
||||||
# 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 dsemul.o cp1emu.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
|
|
||||||
|
|
||||||
EXTRA_CFLAGS += -Werror
|
|
||||||
--- a/arch/mips/math-emu/cp1emu.c
|
|
||||||
+++ b/arch/mips/math-emu/cp1emu.c
|
|
||||||
@@ -56,6 +56,12 @@
|
|
||||||
#endif
|
|
||||||
#define __mips 4
|
|
||||||
|
|
||||||
+/* Further private data for which no space exists in mips_fpu_struct */
|
|
||||||
+
|
|
||||||
+struct mips_fpu_emulator_stats fpuemustats;
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
|
||||||
+
|
|
||||||
/* Function which emulates a floating point instruction. */
|
|
||||||
|
|
||||||
static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
|
|
||||||
@@ -66,10 +72,6 @@ static int fpux_emu(struct pt_regs *,
|
|
||||||
struct mips_fpu_struct *, mips_instruction);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-/* Further private data for which no space exists in mips_fpu_struct */
|
|
||||||
-
|
|
||||||
-struct mips_fpu_emulator_stats fpuemustats;
|
|
||||||
-
|
|
||||||
/* Control registers */
|
|
||||||
|
|
||||||
#define FPCREG_RID 0 /* $0 = revision id */
|
|
||||||
@@ -1273,6 +1275,13 @@ int fpu_emulator_cop1Handler(struct pt_r
|
|
||||||
|
|
||||||
return sig;
|
|
||||||
}
|
|
||||||
+#else
|
|
||||||
+int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
|
||||||
+ int has_fpu)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
|
||||||
|
|
||||||
#ifdef CONFIG_DEBUG_FS
|
|
||||||
extern struct dentry *mips_debugfs_dir;
|
|
||||||
--- a/arch/mips/math-emu/dsemul.c
|
|
||||||
+++ b/arch/mips/math-emu/dsemul.c
|
|
||||||
@@ -109,6 +109,7 @@ int mips_dsemul(struct pt_regs *regs, mi
|
|
||||||
return SIGILL; /* force out of emulation loop */
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef CONFIG_MIPS_FPU_EMU
|
|
||||||
int do_dsemulret(struct pt_regs *xcp)
|
|
||||||
{
|
|
||||||
struct emuframe __user *fr;
|
|
||||||
@@ -165,3 +166,9 @@ int do_dsemulret(struct pt_regs *xcp)
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
+#else
|
|
||||||
+int do_dsemulret(struct pt_regs *xcp)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
|
||||||
--- 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;
|
|
||||||
@@ -112,4 +113,36 @@ int fpu_emulator_restore_context32(struc
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
-#endif
|
|
||||||
+#endif /* CONFIG_64BIT */
|
|
||||||
+#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;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int fpu_emulator_save_context32(struct sigcontext32 __user *sc)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int fpu_emulator_restore_context32(struct sigcontext32 __user *sc)
|
|
||||||
+{
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_64BIT
|
|
||||||
+#endif /* CONFIG_64BIT */
|
|
||||||
+#endif /* CONFIG_MIPS_FPU_EMU */
|
|
|
@ -1,42 +0,0 @@
|
||||||
From 819b4bda18d62b52d04789c4a8d4fc3fbf9ce242 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
Date: Mon, 13 Jul 2009 10:46:49 +0200
|
|
||||||
Subject: [PATCH] MIPS: fix loading of modules with unresolved weak symbols
|
|
||||||
|
|
||||||
Loading of modules with unresolved weak symbols fails on MIPS
|
|
||||||
since '88173507e4fc1e7ecd111b0565e8cba0cb7dae6d'.
|
|
||||||
|
|
||||||
Modules: handle symbols that have a zero value
|
|
||||||
|
|
||||||
The module subsystem cannot handle symbols that are zero. If symbols
|
|
||||||
are present that have a zero value then the module resolver prints out a
|
|
||||||
message that these symbols are unresolved.
|
|
||||||
|
|
||||||
We have to use IS_ERR_VALUE() to check that a symbol has been resolved
|
|
||||||
or not.
|
|
||||||
|
|
||||||
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
|
||||||
---
|
|
||||||
arch/mips/kernel/module.c | 4 ++--
|
|
||||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
|
||||||
|
|
||||||
--- a/arch/mips/kernel/module.c
|
|
||||||
+++ b/arch/mips/kernel/module.c
|
|
||||||
@@ -303,7 +303,7 @@ int apply_relocate(Elf_Shdr *sechdrs, co
|
|
||||||
/* This is the symbol it is referring to */
|
|
||||||
sym = (Elf_Sym *)sechdrs[symindex].sh_addr
|
|
||||||
+ ELF_MIPS_R_SYM(rel[i]);
|
|
||||||
- if (!sym->st_value) {
|
|
||||||
+ if (IS_ERR_VALUE(sym->st_value)) {
|
|
||||||
/* Ignore unresolved weak symbol */
|
|
||||||
if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
|
|
||||||
continue;
|
|
||||||
@@ -343,7 +343,7 @@ int apply_relocate_add(Elf_Shdr *sechdrs
|
|
||||||
/* This is the symbol it is referring to */
|
|
||||||
sym = (Elf_Sym *)sechdrs[symindex].sh_addr
|
|
||||||
+ ELF_MIPS_R_SYM(rel[i]);
|
|
||||||
- if (!sym->st_value) {
|
|
||||||
+ if (IS_ERR_VALUE(sym->st_value)) {
|
|
||||||
/* Ignore unresolved weak symbol */
|
|
||||||
if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
|
|
||||||
continue;
|
|
|
@ -1,326 +0,0 @@
|
||||||
--- a/arch/mips/Makefile
|
|
||||||
+++ b/arch/mips/Makefile
|
|
||||||
@@ -82,7 +82,7 @@ all-$(CONFIG_BOOT_ELF64) := $(vmlinux-64
|
|
||||||
cflags-y += -G 0 -mno-abicalls -fno-pic -pipe
|
|
||||||
cflags-y += -msoft-float
|
|
||||||
LDFLAGS_vmlinux += -G 0 -static -n -nostdlib
|
|
||||||
-MODFLAGS += -mlong-calls
|
|
||||||
+MODFLAGS += -mno-long-calls
|
|
||||||
|
|
||||||
cflags-y += -ffreestanding
|
|
||||||
|
|
||||||
--- a/arch/mips/include/asm/module.h
|
|
||||||
+++ b/arch/mips/include/asm/module.h
|
|
||||||
@@ -9,6 +9,11 @@ struct mod_arch_specific {
|
|
||||||
struct list_head dbe_list;
|
|
||||||
const struct exception_table_entry *dbe_start;
|
|
||||||
const struct exception_table_entry *dbe_end;
|
|
||||||
+
|
|
||||||
+ void *plt_tbl;
|
|
||||||
+ unsigned int core_plt_offset;
|
|
||||||
+ unsigned int core_plt_size;
|
|
||||||
+ unsigned int init_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,6 +43,114 @@ static struct mips_hi16 *mips_hi16_list;
|
|
||||||
static LIST_HEAD(dbe_list);
|
|
||||||
static DEFINE_SPINLOCK(dbe_lock);
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * 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 Elf32_Ehdr *hdr, const Elf32_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;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+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);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+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
|
|
||||||
@@ -58,16 +166,41 @@ void *module_alloc(unsigned long size)
|
|
||||||
|
|
||||||
return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
|
|
||||||
#else
|
|
||||||
+ void *ptr;
|
|
||||||
+
|
|
||||||
if (size == 0)
|
|
||||||
return NULL;
|
|
||||||
- return vmalloc(size);
|
|
||||||
+
|
|
||||||
+ 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)
|
|
||||||
+{
|
|
||||||
+ return (KSEGX(ptr) == KSEG0);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* Free memory returned from module_alloc */
|
|
||||||
void module_free(struct module *mod, void *module_region)
|
|
||||||
{
|
|
||||||
- vfree(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);
|
|
||||||
+ }
|
|
||||||
/* FIXME: If module_region == mod->init_region, trim exception
|
|
||||||
table entries. */
|
|
||||||
}
|
|
||||||
@@ -75,6 +208,24 @@ void module_free(struct module *mod, voi
|
|
||||||
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;
|
|
||||||
+
|
|
||||||
+ 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);
|
|
||||||
+
|
|
||||||
+ mod->arch.core_plt_offset = 0;
|
|
||||||
+ mod->arch.core_plt_size = core_size;
|
|
||||||
+ mod->arch.init_plt_offset = core_size;
|
|
||||||
+ mod->arch.plt_tbl = kmalloc(core_size + init_size, GFP_KERNEL);
|
|
||||||
+ if (!mod->arch.plt_tbl)
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -97,27 +248,41 @@ static int apply_r_mips_32_rela(struct m
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
|
|
||||||
+static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
|
|
||||||
+ void *start, Elf_Addr v)
|
|
||||||
{
|
|
||||||
- if (v % 4) {
|
|
||||||
- printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
|
|
||||||
- return -ENOEXEC;
|
|
||||||
- }
|
|
||||||
+ unsigned *tramp = start + *plt_offset;
|
|
||||||
|
|
||||||
- if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
|
|
||||||
- printk(KERN_ERR
|
|
||||||
- "module %s: relocation overflow\n",
|
|
||||||
- me->name);
|
|
||||||
- return -ENOEXEC;
|
|
||||||
- }
|
|
||||||
+ *plt_offset += 4 * sizeof(int);
|
|
||||||
+
|
|
||||||
+ /* adjust carry for addiu */
|
|
||||||
+ if (v & 0x00008000)
|
|
||||||
+ v += 0x10000;
|
|
||||||
|
|
||||||
- *location = (*location & ~0x03ffffff) |
|
|
||||||
- ((*location + (v >> 2)) & 0x03ffffff);
|
|
||||||
+ 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 (location >= me->module_core &&
|
|
||||||
+ location < me->module_core + me->core_size)
|
|
||||||
+ return add_plt_entry_to(&me->arch.core_plt_offset,
|
|
||||||
+ me->arch.plt_tbl, v);
|
|
||||||
+
|
|
||||||
+ if (location >= me->module_init &&
|
|
||||||
+ location < me->module_init + me->init_size)
|
|
||||||
+ return add_plt_entry_to(&me->arch.init_plt_offset,
|
|
||||||
+ me->arch.plt_tbl, v);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
-static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
|
|
||||||
+static int set_r_mips_26(struct module *me, u32 *location, u32 ofs, Elf_Addr v)
|
|
||||||
{
|
|
||||||
if (v % 4) {
|
|
||||||
printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
|
|
||||||
@@ -125,17 +290,31 @@ static int apply_r_mips_26_rela(struct m
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
|
|
||||||
- printk(KERN_ERR
|
|
||||||
+ v = add_plt_entry(me, location, v + (ofs << 2));
|
|
||||||
+ if (!v) {
|
|
||||||
+ printk(KERN_ERR
|
|
||||||
"module %s: relocation overflow\n",
|
|
||||||
me->name);
|
|
||||||
- return -ENOEXEC;
|
|
||||||
+ return -ENOEXEC;
|
|
||||||
+ }
|
|
||||||
+ ofs = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
- *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
|
|
||||||
+ *location = (*location & ~0x03ffffff) | ((ofs + (v >> 2)) & 0x03ffffff);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
|
|
||||||
+{
|
|
||||||
+ return set_r_mips_26(me, location, *location & 0x03ffffff, v);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
|
|
||||||
+{
|
|
||||||
+ return set_r_mips_26(me, location, 0, v);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
|
|
||||||
{
|
|
||||||
struct mips_hi16 *n;
|
|
||||||
@@ -400,11 +579,23 @@ 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.core_plt_offset == 0 &&
|
|
||||||
+ me->arch.init_plt_offset == me->arch.core_plt_size &&
|
|
||||||
+ is_phys_addr(me->module_core)) {
|
|
||||||
+ kfree(me->arch.plt_tbl);
|
|
||||||
+ me->arch.plt_tbl = NULL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void module_arch_cleanup(struct module *mod)
|
|
||||||
{
|
|
||||||
+ if (mod->arch.plt_tbl)
|
|
||||||
+ kfree(mod->arch.plt_tbl);
|
|
||||||
spin_lock_irq(&dbe_lock);
|
|
||||||
list_del(&mod->arch.dbe_list);
|
|
||||||
spin_unlock_irq(&dbe_lock);
|
|
|
@ -1,191 +0,0 @@
|
||||||
--- a/include/asm-generic/vmlinux.lds.h
|
|
||||||
+++ b/include/asm-generic/vmlinux.lds.h
|
|
||||||
@@ -2,6 +2,27 @@
|
|
||||||
#define LOAD_OFFSET 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#ifndef SYMTAB_KEEP_STR
|
|
||||||
+#define SYMTAB_KEEP_STR *(__ksymtab_strings.*)
|
|
||||||
+#define SYMTAB_DISCARD_STR
|
|
||||||
+#else
|
|
||||||
+#define SYMTAB_DISCARD_STR *(__ksymtab_strings.*)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifndef SYMTAB_KEEP
|
|
||||||
+#define SYMTAB_KEEP *(__ksymtab.*)
|
|
||||||
+#define SYMTAB_DISCARD
|
|
||||||
+#else
|
|
||||||
+#define SYMTAB_DISCARD *(__ksymtab.*)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+#ifndef SYMTAB_KEEP_GPL
|
|
||||||
+#define SYMTAB_KEEP_GPL *(__ksymtab_gpl.*)
|
|
||||||
+#define SYMTAB_DISCARD_GPL
|
|
||||||
+#else
|
|
||||||
+#define SYMTAB_DISCARD_GPL *(__ksymtab_gpl.*)
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#ifndef VMLINUX_SYMBOL
|
|
||||||
#define VMLINUX_SYMBOL(_sym_) _sym_
|
|
||||||
#endif
|
|
||||||
@@ -124,35 +145,35 @@
|
|
||||||
/* Kernel symbol table: Normal symbols */ \
|
|
||||||
__ksymtab : AT(ADDR(__ksymtab) - LOAD_OFFSET) { \
|
|
||||||
VMLINUX_SYMBOL(__start___ksymtab) = .; \
|
|
||||||
- *(__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) = .; \
|
|
||||||
- *(__ksymtab_gpl) \
|
|
||||||
+ SYMTAB_KEEP_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) = .; \
|
|
||||||
- *(__ksymtab_unused) \
|
|
||||||
+ *(__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) = .; \
|
|
||||||
- *(__ksymtab_unused_gpl) \
|
|
||||||
+ *(__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) = .; \
|
|
||||||
- *(__ksymtab_gpl_future) \
|
|
||||||
+ *(__ksymtab_gpl_future.*) \
|
|
||||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl_future) = .; \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
@@ -193,7 +214,13 @@
|
|
||||||
\
|
|
||||||
/* Kernel symbol table: strings */ \
|
|
||||||
__ksymtab_strings : AT(ADDR(__ksymtab_strings) - LOAD_OFFSET) { \
|
|
||||||
- *(__ksymtab_strings) \
|
|
||||||
+ SYMTAB_KEEP_STR \
|
|
||||||
+ } \
|
|
||||||
+ \
|
|
||||||
+ /DISCARD/ : { \
|
|
||||||
+ SYMTAB_DISCARD \
|
|
||||||
+ SYMTAB_DISCARD_GPL \
|
|
||||||
+ SYMTAB_DISCARD_STR \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
/* __*init sections */ \
|
|
||||||
--- a/include/linux/module.h
|
|
||||||
+++ b/include/linux/module.h
|
|
||||||
@@ -187,16 +187,24 @@ void *__symbol_get_gpl(const char *symbo
|
|
||||||
#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))) \
|
|
||||||
= MODULE_SYMBOL_PREFIX #sym; \
|
|
||||||
static const struct kernel_symbol __ksymtab_##sym \
|
|
||||||
__used \
|
|
||||||
- __attribute__((section("__ksymtab" sec), unused)) \
|
|
||||||
+ __attribute__((section("__ksymtab" sec \
|
|
||||||
+ __EXPORT_SUFFIX(sym)), unused)) \
|
|
||||||
= { (unsigned long)&sym, __kstrtab_##sym }
|
|
||||||
|
|
||||||
#define EXPORT_SYMBOL(sym) \
|
|
||||||
--- a/Makefile
|
|
||||||
+++ b/Makefile
|
|
||||||
@@ -963,7 +963,7 @@ prepare: prepare0
|
|
||||||
# Leave this as default for preprocessing vmlinux.lds.S, which is now
|
|
||||||
# done in arch/$(ARCH)/kernel/Makefile
|
|
||||||
|
|
||||||
-export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH)
|
|
||||||
+export CPPFLAGS_vmlinux.lds += -P -C -U$(ARCH) $(EXTRA_LDSFLAGS)
|
|
||||||
|
|
||||||
# The asm symlink changes when $(ARCH) changes.
|
|
||||||
# Detect this and ask user to run make mrproper
|
|
||||||
--- a/arch/powerpc/kernel/vmlinux.lds.S
|
|
||||||
+++ b/arch/powerpc/kernel/vmlinux.lds.S
|
|
||||||
@@ -37,12 +37,6 @@ jiffies = jiffies_64 + 4;
|
|
||||||
#endif
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
- /* Sections to be discarded. */
|
|
||||||
- /DISCARD/ : {
|
|
||||||
- *(.exitcall.exit)
|
|
||||||
- EXIT_DATA
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
. = KERNELBASE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -290,6 +284,12 @@ SECTIONS
|
|
||||||
__bss_stop = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /* Sections to be discarded. */
|
|
||||||
+ /DISCARD/ : {
|
|
||||||
+ *(.exitcall.exit)
|
|
||||||
+ EXIT_DATA
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
. = ALIGN(PAGE_SIZE);
|
|
||||||
_end = . ;
|
|
||||||
PROVIDE32 (end = .);
|
|
||||||
--- a/arch/arm/kernel/vmlinux.lds.S
|
|
||||||
+++ b/arch/arm/kernel/vmlinux.lds.S
|
|
||||||
@@ -76,16 +76,6 @@ SECTIONS
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
- /DISCARD/ : { /* Exit code and data */
|
|
||||||
- EXIT_TEXT
|
|
||||||
- EXIT_DATA
|
|
||||||
- *(.exitcall.exit)
|
|
||||||
-#ifndef CONFIG_MMU
|
|
||||||
- *(.fixup)
|
|
||||||
- *(__ex_table)
|
|
||||||
-#endif
|
|
||||||
- }
|
|
||||||
-
|
|
||||||
.text : { /* Real text segment */
|
|
||||||
_text = .; /* Text and read-only data */
|
|
||||||
__exception_text_start = .;
|
|
||||||
@@ -173,6 +163,17 @@ SECTIONS
|
|
||||||
*(COMMON)
|
|
||||||
_end = .;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+ /DISCARD/ : { /* Exit code and data */
|
|
||||||
+ EXIT_TEXT
|
|
||||||
+ EXIT_DATA
|
|
||||||
+ *(.exitcall.exit)
|
|
||||||
+#ifndef CONFIG_MMU
|
|
||||||
+ *(.fixup)
|
|
||||||
+ *(__ex_table)
|
|
||||||
+#endif
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* Stabs debugging sections. */
|
|
||||||
.stab 0 : { *(.stab) }
|
|
||||||
.stabstr 0 : { *(.stabstr) }
|
|
|
@ -1,13 +0,0 @@
|
||||||
--- a/arch/arm/kernel/module.c
|
|
||||||
+++ b/arch/arm/kernel/module.c
|
|
||||||
@@ -101,6 +101,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,43 +0,0 @@
|
||||||
--- a/drivers/pci/Kconfig
|
|
||||||
+++ b/drivers/pci/Kconfig
|
|
||||||
@@ -42,6 +42,12 @@ config PCI_DEBUG
|
|
||||||
|
|
||||||
When in doubt, say N.
|
|
||||||
|
|
||||||
+config PCI_DISABLE_COMMON_QUIRKS
|
|
||||||
+ bool "PCI disable common quirks"
|
|
||||||
+ depends on PCI
|
|
||||||
+ help
|
|
||||||
+ If you don't know what to do here, say N.
|
|
||||||
+
|
|
||||||
config HT_IRQ
|
|
||||||
bool "Interrupts on hypertransport devices"
|
|
||||||
default y
|
|
||||||
--- a/drivers/pci/quirks.c
|
|
||||||
+++ b/drivers/pci/quirks.c
|
|
||||||
@@ -34,6 +34,7 @@ int pcie_mch_quirk;
|
|
||||||
EXPORT_SYMBOL(pcie_mch_quirk);
|
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_QUIRKS
|
|
||||||
+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
|
|
||||||
/* The Mellanox Tavor device gives false positive parity errors
|
|
||||||
* Mark this device with a broken_parity_status, to allow
|
|
||||||
* PCI scanning code to "skip" this now blacklisted device.
|
|
||||||
@@ -1580,7 +1581,9 @@ static void __devinit fixup_rev1_53c810(
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
|
|
||||||
+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
|
|
||||||
|
|
||||||
+#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS
|
|
||||||
/* Enable 1k I/O space granularity on the Intel P64H2 */
|
|
||||||
static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev)
|
|
||||||
{
|
|
||||||
@@ -1972,6 +1975,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AT
|
|
||||||
quirk_msi_intx_disable_bug);
|
|
||||||
|
|
||||||
#endif /* CONFIG_PCI_MSI */
|
|
||||||
+#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */
|
|
||||||
|
|
||||||
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
|
|
||||||
{
|
|
|
@ -1,110 +0,0 @@
|
||||||
--- a/drivers/mtd/devices/block2mtd.c
|
|
||||||
+++ b/drivers/mtd/devices/block2mtd.c
|
|
||||||
@@ -14,6 +14,7 @@
|
|
||||||
#include <linux/list.h>
|
|
||||||
#include <linux/init.h>
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
+#include <linux/mtd/partitions.h>
|
|
||||||
#include <linux/buffer_head.h>
|
|
||||||
#include <linux/mutex.h>
|
|
||||||
#include <linux/mount.h>
|
|
||||||
@@ -232,10 +233,11 @@ 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)
|
|
||||||
{
|
|
||||||
struct block_device *bdev;
|
|
||||||
struct block2mtd_dev *dev;
|
|
||||||
+ struct mtd_partition *part;
|
|
||||||
char *name;
|
|
||||||
|
|
||||||
if (!devname)
|
|
||||||
@@ -273,17 +275,17 @@ static struct block2mtd_dev *add_device(
|
|
||||||
|
|
||||||
mutex_init(&dev->write_mutex);
|
|
||||||
|
|
||||||
- /* Setup the MTD structure */
|
|
||||||
- /* make the name contain the block device in */
|
|
||||||
- name = kmalloc(sizeof("block2mtd: ") + strlen(devname) + 1,
|
|
||||||
- GFP_KERNEL);
|
|
||||||
+ if (!mtdname)
|
|
||||||
+ mtdname = devname;
|
|
||||||
+
|
|
||||||
+ name = kmalloc(strlen(mtdname) + 1, GFP_KERNEL);
|
|
||||||
if (!name)
|
|
||||||
goto devinit_err;
|
|
||||||
|
|
||||||
- sprintf(name, "block2mtd: %s", devname);
|
|
||||||
+ 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.type = MTD_RAM;
|
|
||||||
@@ -296,14 +298,17 @@ static struct block2mtd_dev *add_device(
|
|
||||||
dev->mtd.priv = dev;
|
|
||||||
dev->mtd.owner = THIS_MODULE;
|
|
||||||
|
|
||||||
- if (add_mtd_device(&dev->mtd)) {
|
|
||||||
+ part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
|
||||||
+ part->name = dev->mtd.name;
|
|
||||||
+ part->offset = 0;
|
|
||||||
+ part->size = dev->mtd.size;
|
|
||||||
+ if (add_mtd_partitions(&dev->mtd, part, 1)) {
|
|
||||||
/* Device didnt get added, so free the entry */
|
|
||||||
goto devinit_err;
|
|
||||||
}
|
|
||||||
list_add(&dev->list, &blkmtd_device_list);
|
|
||||||
INFO("mtd%d: [%s] erase_size = %dKiB [%d]", 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:
|
|
||||||
@@ -376,9 +381,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;
|
|
||||||
@@ -389,7 +394,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)
|
|
||||||
@@ -408,8 +413,10 @@ static int block2mtd_setup2(const char *
|
|
||||||
parse_err("illegal erase size");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ if (token[2] && (strlen(token[2]) + 1 > 80))
|
|
||||||
+ parse_err("mtd device name too long");
|
|
||||||
|
|
||||||
- add_device(name, erase_size);
|
|
||||||
+ add_device(name, erase_size, token[2]);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -443,7 +450,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,624 +0,0 @@
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -45,6 +45,16 @@ config MTD_PARTITIONS
|
|
||||||
devices. Partitioning on NFTL 'devices' is a different - that's the
|
|
||||||
'normal' form of partitioning used on a block device.
|
|
||||||
|
|
||||||
+config MTD_ROOTFS_ROOT_DEV
|
|
||||||
+ bool "Automatically set 'rootfs' partition to be root filesystem"
|
|
||||||
+ depends on MTD_PARTITIONS
|
|
||||||
+ default y
|
|
||||||
+
|
|
||||||
+config MTD_ROOTFS_SPLIT
|
|
||||||
+ bool "Automatically split 'rootfs' partition for squashfs"
|
|
||||||
+ depends on MTD_PARTITIONS
|
|
||||||
+ default y
|
|
||||||
+
|
|
||||||
config MTD_REDBOOT_PARTS
|
|
||||||
tristate "RedBoot partition table parsing"
|
|
||||||
depends on MTD_PARTITIONS
|
|
||||||
--- a/drivers/mtd/mtdpart.c
|
|
||||||
+++ b/drivers/mtd/mtdpart.c
|
|
||||||
@@ -18,6 +18,8 @@
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/mtd/partitions.h>
|
|
||||||
#include <linux/mtd/compatmac.h>
|
|
||||||
+#include <linux/squashfs_fs.h>
|
|
||||||
+#include <linux/root_dev.h>
|
|
||||||
|
|
||||||
/* Our partition linked list */
|
|
||||||
static LIST_HEAD(mtd_partitions);
|
|
||||||
@@ -37,7 +39,7 @@ struct mtd_part {
|
|
||||||
* the pointer to that structure with this macro.
|
|
||||||
*/
|
|
||||||
#define PART(x) ((struct mtd_part *)(x))
|
|
||||||
-
|
|
||||||
+#define IS_PART(mtd) (mtd->read == part_read)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* MTD methods which simply translate the effective address and pass through
|
|
||||||
@@ -489,6 +491,147 @@ out_register:
|
|
||||||
return slave;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
|
||||||
+#define ROOTFS_SPLIT_NAME "rootfs_data"
|
|
||||||
+#define ROOTFS_REMOVED_NAME "<removed>"
|
|
||||||
+static int split_squashfs(struct mtd_info *master, int offset, int *split_offset)
|
|
||||||
+{
|
|
||||||
+ struct squashfs_super_block sb;
|
|
||||||
+ int len, ret;
|
|
||||||
+
|
|
||||||
+ ret = master->read(master, offset, sizeof(sb), &len, (void *) &sb);
|
|
||||||
+ if (ret || (len != sizeof(sb))) {
|
|
||||||
+ printk(KERN_ALERT "split_squashfs: error occured while reading "
|
|
||||||
+ "from \"%s\"\n", master->name);
|
|
||||||
+ return -EINVAL;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (sb.s_magic != SQUASHFS_MAGIC) {
|
|
||||||
+ printk(KERN_ALERT "split_squashfs: no squashfs found in \"%s\"\n",
|
|
||||||
+ master->name);
|
|
||||||
+ *split_offset = 0;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (sb.bytes_used <= 0) {
|
|
||||||
+ printk(KERN_ALERT "split_squashfs: squashfs is empty in \"%s\"\n",
|
|
||||||
+ master->name);
|
|
||||||
+ *split_offset = 0;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ len = (u32) sb.bytes_used;
|
|
||||||
+ len += (offset & 0x000fffff);
|
|
||||||
+ len += (master->erasesize - 1);
|
|
||||||
+ len &= ~(master->erasesize - 1);
|
|
||||||
+ len -= (offset & 0x000fffff);
|
|
||||||
+ *split_offset = offset + len;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int split_rootfs_data(struct mtd_info *master, struct mtd_info *rpart, const struct mtd_partition *part,
|
|
||||||
+ int index)
|
|
||||||
+{
|
|
||||||
+ struct mtd_partition *dpart;
|
|
||||||
+ struct mtd_part *slave = NULL;
|
|
||||||
+ int split_offset = 0;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ ret = split_squashfs(master, part->offset, &split_offset);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ if (split_offset <= 0)
|
|
||||||
+ return 0;
|
|
||||||
+
|
|
||||||
+ dpart = kmalloc(sizeof(*part)+sizeof(ROOTFS_SPLIT_NAME)+1, GFP_KERNEL);
|
|
||||||
+ if (dpart == NULL) {
|
|
||||||
+ printk(KERN_INFO "split_squashfs: no memory for partition \"%s\"\n",
|
|
||||||
+ ROOTFS_SPLIT_NAME);
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ memcpy(dpart, part, sizeof(*part));
|
|
||||||
+ dpart->name = (unsigned char *)&dpart[1];
|
|
||||||
+ strcpy(dpart->name, ROOTFS_SPLIT_NAME);
|
|
||||||
+
|
|
||||||
+ dpart->size -= split_offset - dpart->offset;
|
|
||||||
+ dpart->offset = split_offset;
|
|
||||||
+
|
|
||||||
+ if (dpart == NULL)
|
|
||||||
+ return 1;
|
|
||||||
+
|
|
||||||
+ printk(KERN_INFO "mtd: partition \"%s\" created automatically, ofs=%X, len=%X \n",
|
|
||||||
+ ROOTFS_SPLIT_NAME, dpart->offset, dpart->size);
|
|
||||||
+
|
|
||||||
+ slave = add_one_partition(master, dpart, index, split_offset);
|
|
||||||
+ if (!slave) {
|
|
||||||
+ kfree(dpart);
|
|
||||||
+ return -ENOMEM;
|
|
||||||
+ }
|
|
||||||
+ rpart->split = &slave->mtd;
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int refresh_rootfs_split(struct mtd_info *mtd)
|
|
||||||
+{
|
|
||||||
+ struct mtd_partition tpart;
|
|
||||||
+ struct mtd_part *part;
|
|
||||||
+ char *name;
|
|
||||||
+ int index = 0;
|
|
||||||
+ int offset, size;
|
|
||||||
+ int ret;
|
|
||||||
+
|
|
||||||
+ part = PART(mtd);
|
|
||||||
+
|
|
||||||
+ /* check for the new squashfs offset first */
|
|
||||||
+ ret = split_squashfs(part->master, part->offset, &offset);
|
|
||||||
+ if (ret)
|
|
||||||
+ return ret;
|
|
||||||
+
|
|
||||||
+ if ((offset > 0) && !mtd->split) {
|
|
||||||
+ printk(KERN_INFO "%s: creating new split partition for \"%s\"\n", __func__, mtd->name);
|
|
||||||
+ /* if we don't have a rootfs split partition, create a new one */
|
|
||||||
+ tpart.name = (char *) mtd->name;
|
|
||||||
+ tpart.size = mtd->size;
|
|
||||||
+ tpart.offset = part->offset;
|
|
||||||
+
|
|
||||||
+ /* find the index of the last partition */
|
|
||||||
+ if (!list_empty(&mtd_partitions))
|
|
||||||
+ index = list_first_entry(&mtd_partitions, struct mtd_part, list)->index + 1;
|
|
||||||
+
|
|
||||||
+ return split_rootfs_data(part->master, &part->mtd, &tpart, index);
|
|
||||||
+ } else if ((offset > 0) && mtd->split) {
|
|
||||||
+ /* update the offsets of the existing partition */
|
|
||||||
+ size = mtd->size + part->offset - offset;
|
|
||||||
+
|
|
||||||
+ part = PART(mtd->split);
|
|
||||||
+ part->offset = offset;
|
|
||||||
+ part->mtd.size = size;
|
|
||||||
+ printk(KERN_INFO "%s: %s partition \"" ROOTFS_SPLIT_NAME "\", offset: 0x%06x (0x%06x)\n",
|
|
||||||
+ __func__, (!strcmp(part->mtd.name, ROOTFS_SPLIT_NAME) ? "updating" : "creating"),
|
|
||||||
+ part->offset, part->mtd.size);
|
|
||||||
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
|
|
||||||
+ strcpy(name, ROOTFS_SPLIT_NAME);
|
|
||||||
+ part->mtd.name = name;
|
|
||||||
+ } else if ((offset <= 0) && mtd->split) {
|
|
||||||
+ printk(KERN_INFO "%s: removing partition \"%s\"\n", __func__, mtd->split->name);
|
|
||||||
+
|
|
||||||
+ /* mark existing partition as removed */
|
|
||||||
+ part = PART(mtd->split);
|
|
||||||
+ name = kmalloc(sizeof(ROOTFS_SPLIT_NAME) + 1, GFP_KERNEL);
|
|
||||||
+ strcpy(name, ROOTFS_REMOVED_NAME);
|
|
||||||
+ part->mtd.name = name;
|
|
||||||
+ part->offset = 0;
|
|
||||||
+ part->mtd.size = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+#endif /* CONFIG_MTD_ROOTFS_SPLIT */
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
@@ -502,14 +645,29 @@ int add_mtd_partitions(struct mtd_info *
|
|
||||||
{
|
|
||||||
struct mtd_part *slave;
|
|
||||||
u_int32_t cur_offset = 0;
|
|
||||||
- int i;
|
|
||||||
+ int i, j, ret;
|
|
||||||
|
|
||||||
printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
|
|
||||||
|
|
||||||
- for (i = 0; i < nbparts; i++) {
|
|
||||||
- slave = add_one_partition(master, parts + i, i, cur_offset);
|
|
||||||
+ for (i = 0, j = 0; i < nbparts; i++) {
|
|
||||||
+ slave = add_one_partition(master, parts + i, j++, cur_offset);
|
|
||||||
if (!slave)
|
|
||||||
return -ENOMEM;
|
|
||||||
+
|
|
||||||
+ if (!strcmp(parts[i].name, "rootfs") && slave->registered) {
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
|
|
||||||
+ if (ROOT_DEV == 0) {
|
|
||||||
+ printk(KERN_NOTICE "mtd: partition \"rootfs\" "
|
|
||||||
+ "set to be root filesystem\n");
|
|
||||||
+ ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, slave->mtd.index);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
|
||||||
+ ret = split_rootfs_data(master, &slave->mtd, &parts[i], j);
|
|
||||||
+ if (ret == 0)
|
|
||||||
+ j++;
|
|
||||||
+#endif
|
|
||||||
+ }
|
|
||||||
cur_offset = slave->offset + slave->mtd.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -517,6 +675,32 @@ int add_mtd_partitions(struct mtd_info *
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(add_mtd_partitions);
|
|
||||||
|
|
||||||
+int refresh_mtd_partitions(struct mtd_info *mtd)
|
|
||||||
+{
|
|
||||||
+ int ret = 0;
|
|
||||||
+
|
|
||||||
+ if (IS_PART(mtd)) {
|
|
||||||
+ struct mtd_part *part;
|
|
||||||
+ struct mtd_info *master;
|
|
||||||
+
|
|
||||||
+ part = PART(mtd);
|
|
||||||
+ master = part->master;
|
|
||||||
+ if (master->refresh_device)
|
|
||||||
+ ret = master->refresh_device(master);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (!ret && mtd->refresh_device)
|
|
||||||
+ ret = mtd->refresh_device(mtd);
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_MTD_ROOTFS_SPLIT
|
|
||||||
+ if (!ret && IS_PART(mtd) && !strcmp(mtd->name, "rootfs"))
|
|
||||||
+ refresh_rootfs_split(mtd);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+EXPORT_SYMBOL_GPL(refresh_mtd_partitions);
|
|
||||||
+
|
|
||||||
static DEFINE_SPINLOCK(part_parser_lock);
|
|
||||||
static LIST_HEAD(part_parsers);
|
|
||||||
|
|
||||||
--- a/drivers/mtd/devices/block2mtd.c
|
|
||||||
+++ b/drivers/mtd/devices/block2mtd.c
|
|
||||||
@@ -29,6 +29,8 @@ struct block2mtd_dev {
|
|
||||||
struct block_device *blkdev;
|
|
||||||
struct mtd_info mtd;
|
|
||||||
struct mutex write_mutex;
|
|
||||||
+ rwlock_t bdev_mutex;
|
|
||||||
+ char devname[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -81,6 +83,12 @@ static int block2mtd_erase(struct mtd_in
|
|
||||||
size_t len = instr->len;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
+ read_lock(&dev->bdev_mutex);
|
|
||||||
+ if (!dev->blkdev) {
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
instr->state = MTD_ERASING;
|
|
||||||
mutex_lock(&dev->write_mutex);
|
|
||||||
err = _block2mtd_erase(dev, from, len);
|
|
||||||
@@ -93,6 +101,10 @@ static int block2mtd_erase(struct mtd_in
|
|
||||||
|
|
||||||
instr->state = MTD_ERASE_DONE;
|
|
||||||
mtd_erase_callback(instr);
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
+
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -104,10 +116,14 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
struct page *page;
|
|
||||||
int index = from >> PAGE_SHIFT;
|
|
||||||
int offset = from & (PAGE_SIZE-1);
|
|
||||||
- int cpylen;
|
|
||||||
+ int cpylen, err = 0;
|
|
||||||
+
|
|
||||||
+ read_lock(&dev->bdev_mutex);
|
|
||||||
+ if (!dev->blkdev || (from > mtd->size)) {
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- if (from > mtd->size)
|
|
||||||
- return -EINVAL;
|
|
||||||
if (from + len > mtd->size)
|
|
||||||
len = mtd->size - from;
|
|
||||||
|
|
||||||
@@ -122,10 +138,14 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
len = len - cpylen;
|
|
||||||
|
|
||||||
page = page_read(dev->blkdev->bd_inode->i_mapping, index);
|
|
||||||
- if (!page)
|
|
||||||
- return -ENOMEM;
|
|
||||||
- if (IS_ERR(page))
|
|
||||||
- return PTR_ERR(page);
|
|
||||||
+ if (!page) {
|
|
||||||
+ err = -ENOMEM;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+ if (IS_ERR(page)) {
|
|
||||||
+ err = PTR_ERR(page);
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
memcpy(buf, page_address(page) + offset, cpylen);
|
|
||||||
page_cache_release(page);
|
|
||||||
@@ -136,7 +156,10 @@ static int block2mtd_read(struct mtd_inf
|
|
||||||
offset = 0;
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
- return 0;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
+ return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -188,12 +211,22 @@ static int block2mtd_write(struct mtd_in
|
|
||||||
size_t *retlen, const u_char *buf)
|
|
||||||
{
|
|
||||||
struct block2mtd_dev *dev = mtd->priv;
|
|
||||||
- int err;
|
|
||||||
+ int err = 0;
|
|
||||||
+
|
|
||||||
+ read_lock(&dev->bdev_mutex);
|
|
||||||
+ if (!dev->blkdev) {
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if (!len)
|
|
||||||
- return 0;
|
|
||||||
- if (to >= mtd->size)
|
|
||||||
- return -ENOSPC;
|
|
||||||
+ goto done;
|
|
||||||
+
|
|
||||||
+ if (to >= mtd->size) {
|
|
||||||
+ err = -ENOSPC;
|
|
||||||
+ goto done;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (to + len > mtd->size)
|
|
||||||
len = mtd->size - to;
|
|
||||||
|
|
||||||
@@ -202,6 +235,9 @@ static int block2mtd_write(struct mtd_in
|
|
||||||
mutex_unlock(&dev->write_mutex);
|
|
||||||
if (err > 0)
|
|
||||||
err = 0;
|
|
||||||
+
|
|
||||||
+done:
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -210,52 +246,29 @@ static int block2mtd_write(struct mtd_in
|
|
||||||
static void block2mtd_sync(struct mtd_info *mtd)
|
|
||||||
{
|
|
||||||
struct block2mtd_dev *dev = mtd->priv;
|
|
||||||
- sync_blockdev(dev->blkdev);
|
|
||||||
- return;
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
-
|
|
||||||
-static void block2mtd_free_device(struct block2mtd_dev *dev)
|
|
||||||
-{
|
|
||||||
- if (!dev)
|
|
||||||
- return;
|
|
||||||
-
|
|
||||||
- kfree(dev->mtd.name);
|
|
||||||
|
|
||||||
- if (dev->blkdev) {
|
|
||||||
- invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
|
|
||||||
- 0, -1);
|
|
||||||
- close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
|
|
||||||
- }
|
|
||||||
+ read_lock(&dev->bdev_mutex);
|
|
||||||
+ if (dev->blkdev)
|
|
||||||
+ sync_blockdev(dev->blkdev);
|
|
||||||
+ read_unlock(&dev->bdev_mutex);
|
|
||||||
|
|
||||||
- kfree(dev);
|
|
||||||
+ return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-/* FIXME: ensure that mtd->size % erase_size == 0 */
|
|
||||||
-static struct block2mtd_dev *add_device(char *devname, int erase_size, const char *mtdname)
|
|
||||||
+static int _open_bdev(struct block2mtd_dev *dev)
|
|
||||||
{
|
|
||||||
struct block_device *bdev;
|
|
||||||
- struct block2mtd_dev *dev;
|
|
||||||
- struct mtd_partition *part;
|
|
||||||
- char *name;
|
|
||||||
-
|
|
||||||
- if (!devname)
|
|
||||||
- return NULL;
|
|
||||||
-
|
|
||||||
- dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
|
|
||||||
- if (!dev)
|
|
||||||
- return NULL;
|
|
||||||
|
|
||||||
/* Get a handle on the device */
|
|
||||||
- bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, NULL);
|
|
||||||
+ bdev = open_bdev_exclusive(dev->devname, FMODE_READ|FMODE_WRITE, NULL);
|
|
||||||
#ifndef MODULE
|
|
||||||
if (IS_ERR(bdev)) {
|
|
||||||
|
|
||||||
/* We might not have rootfs mounted at this point. Try
|
|
||||||
to resolve the device name by other means. */
|
|
||||||
|
|
||||||
- dev_t devt = name_to_dev_t(devname);
|
|
||||||
+ dev_t devt = name_to_dev_t(dev->devname);
|
|
||||||
if (devt) {
|
|
||||||
bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
|
||||||
}
|
|
||||||
@@ -263,17 +276,97 @@ static struct block2mtd_dev *add_device(
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (IS_ERR(bdev)) {
|
|
||||||
- ERROR("error: cannot open device %s", devname);
|
|
||||||
- goto devinit_err;
|
|
||||||
+ ERROR("error: cannot open device %s", dev->devname);
|
|
||||||
+ return 1;
|
|
||||||
}
|
|
||||||
dev->blkdev = bdev;
|
|
||||||
|
|
||||||
if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
|
|
||||||
ERROR("attempting to use an MTD device as a block device");
|
|
||||||
- goto devinit_err;
|
|
||||||
+ return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void _close_bdev(struct block2mtd_dev *dev)
|
|
||||||
+{
|
|
||||||
+ struct block_device *bdev;
|
|
||||||
+
|
|
||||||
+ if (!dev->blkdev)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ bdev = dev->blkdev;
|
|
||||||
+ invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping, 0, -1);
|
|
||||||
+ close_bdev_exclusive(dev->blkdev, FMODE_READ|FMODE_WRITE);
|
|
||||||
+ dev->blkdev = NULL;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void block2mtd_free_device(struct block2mtd_dev *dev)
|
|
||||||
+{
|
|
||||||
+ if (!dev)
|
|
||||||
+ return;
|
|
||||||
+
|
|
||||||
+ kfree(dev->mtd.name);
|
|
||||||
+ _close_bdev(dev);
|
|
||||||
+ kfree(dev);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int block2mtd_refresh(struct mtd_info *mtd)
|
|
||||||
+{
|
|
||||||
+ struct block2mtd_dev *dev = mtd->priv;
|
|
||||||
+ struct block_device *bdev;
|
|
||||||
+ dev_t devt;
|
|
||||||
+ int err = 0;
|
|
||||||
+
|
|
||||||
+ /* no other mtd function can run at this point */
|
|
||||||
+ write_lock(&dev->bdev_mutex);
|
|
||||||
+
|
|
||||||
+ /* get the device number for the whole disk */
|
|
||||||
+ devt = MKDEV(MAJOR(dev->blkdev->bd_dev), 0);
|
|
||||||
+
|
|
||||||
+ /* close the old block device */
|
|
||||||
+ _close_bdev(dev);
|
|
||||||
+
|
|
||||||
+ /* open the whole disk, issue a partition rescan, then */
|
|
||||||
+ bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
|
|
||||||
+ if (!bdev || !bdev->bd_disk)
|
|
||||||
+ err = -EINVAL;
|
|
||||||
+ else {
|
|
||||||
+ err = rescan_partitions(bdev->bd_disk, bdev);
|
|
||||||
+ }
|
|
||||||
+ if (bdev)
|
|
||||||
+ close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE);
|
|
||||||
+
|
|
||||||
+ /* try to open the partition block device again */
|
|
||||||
+ _open_bdev(dev);
|
|
||||||
+ write_unlock(&dev->bdev_mutex);
|
|
||||||
+
|
|
||||||
+ return err;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* FIXME: ensure that mtd->size % erase_size == 0 */
|
|
||||||
+static struct block2mtd_dev *add_device(char *devname, int erase_size, char *mtdname)
|
|
||||||
+{
|
|
||||||
+ struct block2mtd_dev *dev;
|
|
||||||
+ struct mtd_partition *part;
|
|
||||||
+ char *name;
|
|
||||||
+
|
|
||||||
+ if (!devname)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ dev = kzalloc(sizeof(struct block2mtd_dev) + strlen(devname) + 1, GFP_KERNEL);
|
|
||||||
+ if (!dev)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ strcpy(dev->devname, devname);
|
|
||||||
+
|
|
||||||
+ if (_open_bdev(dev))
|
|
||||||
+ goto devinit_err;
|
|
||||||
+
|
|
||||||
mutex_init(&dev->write_mutex);
|
|
||||||
+ rwlock_init(&dev->bdev_mutex);
|
|
||||||
|
|
||||||
if (!mtdname)
|
|
||||||
mtdname = devname;
|
|
||||||
@@ -297,6 +390,7 @@ static struct block2mtd_dev *add_device(
|
|
||||||
dev->mtd.read = block2mtd_read;
|
|
||||||
dev->mtd.priv = dev;
|
|
||||||
dev->mtd.owner = THIS_MODULE;
|
|
||||||
+ dev->mtd.refresh_device = block2mtd_refresh;
|
|
||||||
|
|
||||||
part = kzalloc(sizeof(struct mtd_partition), GFP_KERNEL);
|
|
||||||
part->name = dev->mtd.name;
|
|
||||||
--- a/drivers/mtd/mtdchar.c
|
|
||||||
+++ b/drivers/mtd/mtdchar.c
|
|
||||||
@@ -16,6 +16,7 @@
|
|
||||||
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/mtd/compatmac.h>
|
|
||||||
+#include <linux/mtd/partitions.h>
|
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
|
||||||
|
|
||||||
@@ -769,6 +770,13 @@ static int mtd_ioctl(struct inode *inode
|
|
||||||
file->f_pos = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
+#ifdef CONFIG_MTD_PARTITIONS
|
|
||||||
+ case MTDREFRESH:
|
|
||||||
+ {
|
|
||||||
+ ret = refresh_mtd_partitions(mtd);
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
ret = -ENOTTY;
|
|
||||||
--- a/include/linux/mtd/mtd.h
|
|
||||||
+++ b/include/linux/mtd/mtd.h
|
|
||||||
@@ -98,6 +98,7 @@ struct mtd_oob_ops {
|
|
||||||
uint8_t *oobbuf;
|
|
||||||
};
|
|
||||||
|
|
||||||
+struct mtd_info;
|
|
||||||
struct mtd_info {
|
|
||||||
u_char type;
|
|
||||||
u_int32_t flags;
|
|
||||||
@@ -213,6 +214,9 @@ struct mtd_info {
|
|
||||||
struct module *owner;
|
|
||||||
int usecount;
|
|
||||||
|
|
||||||
+ int (*refresh_device)(struct mtd_info *mtd);
|
|
||||||
+ struct mtd_info *split;
|
|
||||||
+
|
|
||||||
/* If the driver is something smart, like UBI, it may need to maintain
|
|
||||||
* its own reference counting. The below functions are only for driver.
|
|
||||||
* The driver may register its callbacks. These callbacks are not
|
|
||||||
--- a/include/linux/mtd/partitions.h
|
|
||||||
+++ b/include/linux/mtd/partitions.h
|
|
||||||
@@ -34,6 +34,7 @@
|
|
||||||
* erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
|
|
||||||
*/
|
|
||||||
|
|
||||||
+struct mtd_partition;
|
|
||||||
struct mtd_partition {
|
|
||||||
char *name; /* identifier string */
|
|
||||||
u_int32_t size; /* partition size */
|
|
||||||
@@ -41,6 +42,7 @@ struct mtd_partition {
|
|
||||||
u_int32_t mask_flags; /* master MTD flags to mask out for this partition */
|
|
||||||
struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
|
|
||||||
struct mtd_info **mtdp; /* pointer to store the MTD object */
|
|
||||||
+ int (*refresh_partition)(struct mtd_info *);
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MTDPART_OFS_NXTBLK (-2)
|
|
||||||
@@ -50,6 +52,7 @@ struct mtd_partition {
|
|
||||||
|
|
||||||
int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
|
|
||||||
int del_mtd_partitions(struct mtd_info *);
|
|
||||||
+int refresh_mtd_partitions(struct mtd_info *);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Functions dealing with the various ways of partitioning the space
|
|
||||||
--- a/include/mtd/mtd-abi.h
|
|
||||||
+++ b/include/mtd/mtd-abi.h
|
|
||||||
@@ -93,6 +93,7 @@ struct otp_info {
|
|
||||||
#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout)
|
|
||||||
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
|
|
||||||
#define MTDFILEMODE _IO('M', 19)
|
|
||||||
+#define MTDREFRESH _IO('M', 23)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Obsolete legacy interface. Keep it in order not to break userspace
|
|
|
@ -1,30 +0,0 @@
|
||||||
--- a/drivers/mtd/redboot.c
|
|
||||||
+++ b/drivers/mtd/redboot.c
|
|
||||||
@@ -249,14 +249,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,60 +0,0 @@
|
||||||
--- a/drivers/mtd/redboot.c
|
|
||||||
+++ b/drivers/mtd/redboot.c
|
|
||||||
@@ -11,6 +11,8 @@
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/mtd/partitions.h>
|
|
||||||
|
|
||||||
+#define BOARD_CONFIG_PART "boardconfig"
|
|
||||||
+
|
|
||||||
struct fis_image_desc {
|
|
||||||
unsigned char name[16]; // Null terminated name
|
|
||||||
uint32_t flash_base; // Address within FLASH of image
|
|
||||||
@@ -41,6 +43,7 @@ static int parse_redboot_partitions(stru
|
|
||||||
struct mtd_partition **pparts,
|
|
||||||
unsigned long fis_origin)
|
|
||||||
{
|
|
||||||
+ unsigned long max_offset = 0;
|
|
||||||
int nrparts = 0;
|
|
||||||
struct fis_image_desc *buf;
|
|
||||||
struct mtd_partition *parts;
|
|
||||||
@@ -209,14 +212,14 @@ static int parse_redboot_partitions(stru
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
- parts = kzalloc(sizeof(*parts)*nrparts + nulllen + namelen, GFP_KERNEL);
|
|
||||||
+ parts = kzalloc(sizeof(*parts) * (nrparts + 1) + nulllen + namelen + sizeof(BOARD_CONFIG_PART), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!parts) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- nullname = (char *)&parts[nrparts];
|
|
||||||
+ nullname = (char *)&parts[nrparts + 1];
|
|
||||||
#ifdef CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED
|
|
||||||
if (nulllen > 0) {
|
|
||||||
strcpy(nullname, nullstring);
|
|
||||||
@@ -235,6 +238,8 @@ static int parse_redboot_partitions(stru
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for ( ; i<nrparts; i++) {
|
|
||||||
+ if(max_offset < buf[i].flash_base + buf[i].size)
|
|
||||||
+ max_offset = buf[i].flash_base + buf[i].size;
|
|
||||||
parts[i].size = fl->img->size;
|
|
||||||
parts[i].offset = fl->img->flash_base;
|
|
||||||
parts[i].name = names;
|
|
||||||
@@ -268,6 +273,14 @@ static int parse_redboot_partitions(stru
|
|
||||||
fl = fl->next;
|
|
||||||
kfree(tmp_fl);
|
|
||||||
}
|
|
||||||
+ if(master->size - max_offset >= master->erasesize)
|
|
||||||
+ {
|
|
||||||
+ parts[nrparts].size = master->size - max_offset;
|
|
||||||
+ parts[nrparts].offset = max_offset;
|
|
||||||
+ parts[nrparts].name = names;
|
|
||||||
+ strcpy(names, BOARD_CONFIG_PART);
|
|
||||||
+ nrparts++;
|
|
||||||
+ }
|
|
||||||
ret = nrparts;
|
|
||||||
*pparts = parts;
|
|
||||||
out:
|
|
|
@ -1,32 +0,0 @@
|
||||||
--- a/include/linux/mtd/nand.h
|
|
||||||
+++ b/include/linux/mtd/nand.h
|
|
||||||
@@ -579,6 +579,7 @@ struct platform_nand_chip {
|
|
||||||
int chip_delay;
|
|
||||||
unsigned int options;
|
|
||||||
const char **part_probe_types;
|
|
||||||
+ int (*chip_fixup)(struct mtd_info *mtd);
|
|
||||||
void *priv;
|
|
||||||
};
|
|
||||||
|
|
||||||
--- a/drivers/mtd/nand/plat_nand.c
|
|
||||||
+++ b/drivers/mtd/nand/plat_nand.c
|
|
||||||
@@ -71,7 +71,18 @@ static int __init plat_nand_probe(struct
|
|
||||||
platform_set_drvdata(pdev, data);
|
|
||||||
|
|
||||||
/* Scan to find existance of the device */
|
|
||||||
- if (nand_scan(&data->mtd, 1)) {
|
|
||||||
+ if (nand_scan_ident(&data->mtd, 1)) {
|
|
||||||
+ res = -ENXIO;
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (pdata->chip.chip_fixup) {
|
|
||||||
+ res = pdata->chip.chip_fixup(&data->mtd);
|
|
||||||
+ if (res)
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (nand_scan_tail(&data->mtd)) {
|
|
||||||
res = -ENXIO;
|
|
||||||
goto out;
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
--- a/drivers/mtd/Kconfig
|
|
||||||
+++ b/drivers/mtd/Kconfig
|
|
||||||
@@ -172,6 +172,22 @@ config MTD_AR7_PARTS
|
|
||||||
---help---
|
|
||||||
TI AR7 partitioning support
|
|
||||||
|
|
||||||
+config MTD_MYLOADER_PARTS
|
|
||||||
+ tristate "MyLoader partition parsing"
|
|
||||||
+ depends on MTD_PARTITIONS && (ADM5120 || ATHEROS || ATHEROS_AR71XX)
|
|
||||||
+ ---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"
|
|
||||||
|
|
||||||
config MTD_CHAR
|
|
||||||
--- a/drivers/mtd/Makefile
|
|
||||||
+++ b/drivers/mtd/Makefile
|
|
||||||
@@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdli
|
|
||||||
obj-$(CONFIG_MTD_AFS_PARTS) += afs.o
|
|
||||||
obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o
|
|
||||||
obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o
|
|
||||||
+obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o
|
|
||||||
|
|
||||||
# 'Users' - code which presents functionality to userspace.
|
|
||||||
obj-$(CONFIG_MTD_CHAR) += mtdchar.o
|
|
|
@ -1,11 +0,0 @@
|
||||||
--- a/drivers/mtd/myloader.c
|
|
||||||
+++ b/drivers/mtd/myloader.c
|
|
||||||
@@ -19,7 +19,7 @@
|
|
||||||
#include <linux/vmalloc.h>
|
|
||||||
#include <linux/mtd/mtd.h>
|
|
||||||
#include <linux/mtd/partitions.h>
|
|
||||||
-#include <linux/byteorder/generic.h>
|
|
||||||
+#include <linux/byteorder.h>
|
|
||||||
#include <linux/myloader.h>
|
|
||||||
|
|
||||||
#define BLOCK_LEN_MIN 0x10000
|
|
|
@ -1,12 +0,0 @@
|
||||||
--- a/drivers/mtd/nand/nand_ecc.c
|
|
||||||
+++ b/drivers/mtd/nand/nand_ecc.c
|
|
||||||
@@ -492,8 +492,7 @@ int nand_correct_data(struct mtd_info *m
|
|
||||||
if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
|
|
||||||
return 1; /* error in ecc data; no action needed */
|
|
||||||
|
|
||||||
- printk(KERN_ERR "uncorrectable error : ");
|
|
||||||
- return -1;
|
|
||||||
+ return -EBADMSG;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL(nand_correct_data);
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,108 +0,0 @@
|
||||||
--- a/include/linux/netfilter/xt_layer7.h
|
|
||||||
+++ b/include/linux/netfilter/xt_layer7.h
|
|
||||||
@@ -8,6 +8,7 @@ struct xt_layer7_info {
|
|
||||||
char protocol[MAX_PROTOCOL_LEN];
|
|
||||||
char pattern[MAX_PATTERN_LEN];
|
|
||||||
u_int8_t invert;
|
|
||||||
+ u_int8_t pkt;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* _XT_LAYER7_H */
|
|
||||||
--- a/net/netfilter/xt_layer7.c
|
|
||||||
+++ b/net/netfilter/xt_layer7.c
|
|
||||||
@@ -314,33 +314,35 @@ static int match_no_append(struct nf_con
|
|
||||||
}
|
|
||||||
|
|
||||||
/* add the new app data to the conntrack. Return number of bytes added. */
|
|
||||||
-static int add_data(struct nf_conn * master_conntrack,
|
|
||||||
- char * app_data, int appdatalen)
|
|
||||||
+static int add_datastr(char *target, int offset, char *app_data, int len)
|
|
||||||
{
|
|
||||||
int length = 0, i;
|
|
||||||
- int oldlength = master_conntrack->layer7.app_data_len;
|
|
||||||
-
|
|
||||||
- /* This is a fix for a race condition by Deti Fliegl. However, I'm not
|
|
||||||
- clear on whether the race condition exists or whether this really
|
|
||||||
- fixes it. I might just be being dense... Anyway, if it's not really
|
|
||||||
- a fix, all it does is waste a very small amount of time. */
|
|
||||||
- if(!master_conntrack->layer7.app_data) return 0;
|
|
||||||
+ if (!target) return 0;
|
|
||||||
|
|
||||||
/* Strip nulls. Make everything lower case (our regex lib doesn't
|
|
||||||
do case insensitivity). Add it to the end of the current data. */
|
|
||||||
- for(i = 0; i < maxdatalen-oldlength-1 &&
|
|
||||||
- i < appdatalen; i++) {
|
|
||||||
+ for(i = 0; i < maxdatalen-offset-1 && i < len; i++) {
|
|
||||||
if(app_data[i] != '\0') {
|
|
||||||
/* the kernel version of tolower mungs 'upper ascii' */
|
|
||||||
- master_conntrack->layer7.app_data[length+oldlength] =
|
|
||||||
+ target[length+offset] =
|
|
||||||
isascii(app_data[i])?
|
|
||||||
tolower(app_data[i]) : app_data[i];
|
|
||||||
length++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+ target[length+offset] = '\0';
|
|
||||||
+
|
|
||||||
+ return length;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* add the new app data to the conntrack. Return number of bytes added. */
|
|
||||||
+static int add_data(struct nf_conn * master_conntrack,
|
|
||||||
+ char * app_data, int appdatalen)
|
|
||||||
+{
|
|
||||||
+ int length;
|
|
||||||
|
|
||||||
- master_conntrack->layer7.app_data[length+oldlength] = '\0';
|
|
||||||
- master_conntrack->layer7.app_data_len = length + oldlength;
|
|
||||||
+ length = add_datastr(master_conntrack->layer7.app_data, master_conntrack->layer7.app_data_len, app_data, appdatalen);
|
|
||||||
+ master_conntrack->layer7.app_data_len += length;
|
|
||||||
|
|
||||||
return length;
|
|
||||||
}
|
|
||||||
@@ -438,7 +440,7 @@ match(const struct sk_buff *skbin,
|
|
||||||
|
|
||||||
enum ip_conntrack_info master_ctinfo, ctinfo;
|
|
||||||
struct nf_conn *master_conntrack, *conntrack;
|
|
||||||
- unsigned char * app_data;
|
|
||||||
+ unsigned char *app_data, *tmp_data;
|
|
||||||
unsigned int pattern_result, appdatalen;
|
|
||||||
regexp * comppattern;
|
|
||||||
|
|
||||||
@@ -466,8 +468,8 @@ match(const struct sk_buff *skbin,
|
|
||||||
master_conntrack = master_ct(master_conntrack);
|
|
||||||
|
|
||||||
/* if we've classified it or seen too many packets */
|
|
||||||
- if(total_acct_packets(master_conntrack) > num_packets ||
|
|
||||||
- master_conntrack->layer7.app_proto) {
|
|
||||||
+ if(!info->pkt && (total_acct_packets(master_conntrack) > num_packets ||
|
|
||||||
+ master_conntrack->layer7.app_proto)) {
|
|
||||||
|
|
||||||
pattern_result = match_no_append(conntrack, master_conntrack,
|
|
||||||
ctinfo, master_ctinfo, info);
|
|
||||||
@@ -500,6 +502,25 @@ match(const struct sk_buff *skbin,
|
|
||||||
/* the return value gets checked later, when we're ready to use it */
|
|
||||||
comppattern = compile_and_cache(info->pattern, info->protocol);
|
|
||||||
|
|
||||||
+ if (info->pkt) {
|
|
||||||
+ tmp_data = kmalloc(maxdatalen, GFP_ATOMIC);
|
|
||||||
+ if(!tmp_data){
|
|
||||||
+ if (net_ratelimit())
|
|
||||||
+ printk(KERN_ERR "layer7: out of memory in match, bailing.\n");
|
|
||||||
+ return info->invert;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ tmp_data[0] = '\0';
|
|
||||||
+ add_datastr(tmp_data, 0, app_data, appdatalen);
|
|
||||||
+ pattern_result = ((comppattern && regexec(comppattern, tmp_data)) ? 1 : 0);
|
|
||||||
+
|
|
||||||
+ kfree(tmp_data);
|
|
||||||
+ tmp_data = NULL;
|
|
||||||
+ spin_unlock_bh(&l7_lock);
|
|
||||||
+
|
|
||||||
+ return (pattern_result ^ info->invert);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* On the first packet of a connection, allocate space for app data */
|
|
||||||
if(total_acct_packets(master_conntrack) == 1 && !skb->cb[0] &&
|
|
||||||
!master_conntrack->layer7.app_data){
|
|
|
@ -1,119 +0,0 @@
|
||||||
--- a/include/linux/netfilter_ipv4/ip_tables.h
|
|
||||||
+++ b/include/linux/netfilter_ipv4/ip_tables.h
|
|
||||||
@@ -62,6 +62,7 @@ struct ipt_ip {
|
|
||||||
#define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */
|
|
||||||
#define IPT_F_GOTO 0x02 /* Set if jump is a goto */
|
|
||||||
#define IPT_F_MASK 0x03 /* All possible flag bits mask. */
|
|
||||||
+#define IPT_F_NO_DEF_MATCH 0x80 /* Internal: no default match rules present */
|
|
||||||
|
|
||||||
/* Values for "inv" field in struct ipt_ip. */
|
|
||||||
#define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */
|
|
||||||
--- a/net/ipv4/netfilter/ip_tables.c
|
|
||||||
+++ b/net/ipv4/netfilter/ip_tables.c
|
|
||||||
@@ -88,6 +88,9 @@ ip_packet_match(const struct iphdr *ip,
|
|
||||||
|
|
||||||
#define FWINV(bool, invflg) ((bool) ^ !!(ipinfo->invflags & (invflg)))
|
|
||||||
|
|
||||||
+ if (ipinfo->flags & IPT_F_NO_DEF_MATCH)
|
|
||||||
+ return true;
|
|
||||||
+
|
|
||||||
if (FWINV((ip->saddr&ipinfo->smsk.s_addr) != ipinfo->src.s_addr,
|
|
||||||
IPT_INV_SRCIP)
|
|
||||||
|| FWINV((ip->daddr&ipinfo->dmsk.s_addr) != ipinfo->dst.s_addr,
|
|
||||||
@@ -151,13 +154,35 @@ ip_packet_match(const struct iphdr *ip,
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#undef FWINV
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
-ip_checkentry(const struct ipt_ip *ip)
|
|
||||||
+ip_checkentry(struct ipt_ip *ip)
|
|
||||||
{
|
|
||||||
- if (ip->flags & ~IPT_F_MASK) {
|
|
||||||
+#define FWINV(bool, invflg) ((bool) || (ip->invflags & (invflg)))
|
|
||||||
+
|
|
||||||
+ if (FWINV(ip->smsk.s_addr, IPT_INV_SRCIP) ||
|
|
||||||
+ FWINV(ip->dmsk.s_addr, IPT_INV_DSTIP))
|
|
||||||
+ goto has_match_rules;
|
|
||||||
+
|
|
||||||
+ if (FWINV(!!((const unsigned long *)ip->iniface_mask)[0],
|
|
||||||
+ IPT_INV_VIA_IN) ||
|
|
||||||
+ FWINV(!!((const unsigned long *)ip->outiface_mask)[0],
|
|
||||||
+ IPT_INV_VIA_OUT))
|
|
||||||
+ goto has_match_rules;
|
|
||||||
+
|
|
||||||
+ if (FWINV(ip->proto, IPT_INV_PROTO))
|
|
||||||
+ goto has_match_rules;
|
|
||||||
+
|
|
||||||
+ if (FWINV(ip->flags&IPT_F_FRAG, IPT_INV_FRAG))
|
|
||||||
+ goto has_match_rules;
|
|
||||||
+
|
|
||||||
+ ip->flags |= IPT_F_NO_DEF_MATCH;
|
|
||||||
+
|
|
||||||
+has_match_rules:
|
|
||||||
+ if (ip->flags & ~(IPT_F_MASK|IPT_F_NO_DEF_MATCH)) {
|
|
||||||
duprintf("Unknown flag bits set: %08X\n",
|
|
||||||
ip->flags & ~IPT_F_MASK);
|
|
||||||
return false;
|
|
||||||
@@ -167,6 +192,8 @@ ip_checkentry(const struct ipt_ip *ip)
|
|
||||||
ip->invflags & ~IPT_INV_MASK);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
+#undef FWINV
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -214,7 +241,6 @@ unconditional(const struct ipt_ip *ip)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
-#undef FWINV
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
|
|
||||||
@@ -332,8 +358,27 @@ ipt_do_table(struct sk_buff *skb,
|
|
||||||
struct xt_match_param mtpar;
|
|
||||||
struct xt_target_param tgpar;
|
|
||||||
|
|
||||||
- /* Initialization */
|
|
||||||
ip = ip_hdr(skb);
|
|
||||||
+
|
|
||||||
+ read_lock_bh(&table->lock);
|
|
||||||
+ IP_NF_ASSERT(table->valid_hooks & (1 << hook));
|
|
||||||
+ private = table->private;
|
|
||||||
+ table_base = (void *)private->entries[smp_processor_id()];
|
|
||||||
+ e = get_entry(table_base, private->hook_entry[hook]);
|
|
||||||
+ if (e->target_offset <= sizeof(struct ipt_entry) &&
|
|
||||||
+ (e->ip.flags & IPT_F_NO_DEF_MATCH)) {
|
|
||||||
+ struct ipt_entry_target *t = ipt_get_target(e);
|
|
||||||
+ if (!t->u.kernel.target->target) {
|
|
||||||
+ int v = ((struct ipt_standard_target *)t)->verdict;
|
|
||||||
+ if ((v < 0) && (v != IPT_RETURN)) {
|
|
||||||
+ ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);
|
|
||||||
+ read_unlock_bh(&table->lock);
|
|
||||||
+ return (unsigned)(-v) - 1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /* Initialization */
|
|
||||||
datalen = skb->len - ip->ihl * 4;
|
|
||||||
indev = in ? in->name : nulldevname;
|
|
||||||
outdev = out ? out->name : nulldevname;
|
|
||||||
@@ -351,12 +396,6 @@ ipt_do_table(struct sk_buff *skb,
|
|
||||||
mtpar.family = tgpar.family = NFPROTO_IPV4;
|
|
||||||
tgpar.hooknum = hook;
|
|
||||||
|
|
||||||
- read_lock_bh(&table->lock);
|
|
||||||
- IP_NF_ASSERT(table->valid_hooks & (1 << hook));
|
|
||||||
- private = table->private;
|
|
||||||
- table_base = (void *)private->entries[smp_processor_id()];
|
|
||||||
- e = get_entry(table_base, private->hook_entry[hook]);
|
|
||||||
-
|
|
||||||
/* For return from builtin chain */
|
|
||||||
back = get_entry(table_base, private->underflow[hook]);
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,18 +0,0 @@
|
||||||
--- a/net/netfilter/Kconfig
|
|
||||||
+++ b/net/netfilter/Kconfig
|
|
||||||
@@ -160,7 +160,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
|
|
||||||
@@ -467,7 +466,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
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,797 +0,0 @@
|
||||||
--- a/include/linux/pkt_sched.h
|
|
||||||
+++ b/include/linux/pkt_sched.h
|
|
||||||
@@ -180,8 +180,37 @@ struct tc_sfq_xstats
|
|
||||||
*
|
|
||||||
* The only reason for this is efficiency, it is possible
|
|
||||||
* to change these parameters in compile time.
|
|
||||||
+ *
|
|
||||||
+ * If you need to play with these values, use esfq instead.
|
|
||||||
*/
|
|
||||||
|
|
||||||
+/* ESFQ section */
|
|
||||||
+
|
|
||||||
+enum
|
|
||||||
+{
|
|
||||||
+ /* traditional */
|
|
||||||
+ TCA_SFQ_HASH_CLASSIC,
|
|
||||||
+ TCA_SFQ_HASH_DST,
|
|
||||||
+ TCA_SFQ_HASH_SRC,
|
|
||||||
+ TCA_SFQ_HASH_FWMARK,
|
|
||||||
+ /* conntrack */
|
|
||||||
+ TCA_SFQ_HASH_CTORIGDST,
|
|
||||||
+ TCA_SFQ_HASH_CTORIGSRC,
|
|
||||||
+ TCA_SFQ_HASH_CTREPLDST,
|
|
||||||
+ TCA_SFQ_HASH_CTREPLSRC,
|
|
||||||
+ TCA_SFQ_HASH_CTNATCHG,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct tc_esfq_qopt
|
|
||||||
+{
|
|
||||||
+ unsigned quantum; /* Bytes per round allocated to flow */
|
|
||||||
+ int perturb_period; /* Period of hash perturbation */
|
|
||||||
+ __u32 limit; /* Maximal packets in queue */
|
|
||||||
+ unsigned divisor; /* Hash divisor */
|
|
||||||
+ unsigned flows; /* Maximal number of flows */
|
|
||||||
+ unsigned hash_kind; /* Hash function to use for flow identification */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
/* RED section */
|
|
||||||
|
|
||||||
enum
|
|
||||||
--- a/net/sched/Kconfig
|
|
||||||
+++ b/net/sched/Kconfig
|
|
||||||
@@ -137,6 +137,37 @@ config NET_SCH_SFQ
|
|
||||||
To compile this code as a module, choose M here: the
|
|
||||||
module will be called sch_sfq.
|
|
||||||
|
|
||||||
+config NET_SCH_ESFQ
|
|
||||||
+ tristate "Enhanced Stochastic Fairness Queueing (ESFQ)"
|
|
||||||
+ ---help---
|
|
||||||
+ Say Y here if you want to use the Enhanced Stochastic Fairness
|
|
||||||
+ Queueing (ESFQ) packet scheduling algorithm for some of your network
|
|
||||||
+ devices or as a leaf discipline for a classful qdisc such as HTB or
|
|
||||||
+ CBQ (see the top of <file:net/sched/sch_esfq.c> for details and
|
|
||||||
+ references to the SFQ algorithm).
|
|
||||||
+
|
|
||||||
+ This is an enchanced SFQ version which allows you to control some
|
|
||||||
+ hardcoded values in the SFQ scheduler.
|
|
||||||
+
|
|
||||||
+ ESFQ also adds control of the hash function used to identify packet
|
|
||||||
+ flows. The original SFQ discipline hashes by connection; ESFQ add
|
|
||||||
+ several other hashing methods, such as by src IP or by dst IP, which
|
|
||||||
+ can be more fair to users in some networking situations.
|
|
||||||
+
|
|
||||||
+ To compile this code as a module, choose M here: the
|
|
||||||
+ module will be called sch_esfq.
|
|
||||||
+
|
|
||||||
+config NET_SCH_ESFQ_NFCT
|
|
||||||
+ bool "Connection Tracking Hash Types"
|
|
||||||
+ depends on NET_SCH_ESFQ && NF_CONNTRACK
|
|
||||||
+ ---help---
|
|
||||||
+ Say Y here to enable support for hashing based on netfilter connection
|
|
||||||
+ tracking information. This is useful for a router that is also using
|
|
||||||
+ NAT to connect privately-addressed hosts to the Internet. If you want
|
|
||||||
+ to provide fair distribution of upstream bandwidth, ESFQ must use
|
|
||||||
+ connection tracking information, since all outgoing packets will share
|
|
||||||
+ the same source address.
|
|
||||||
+
|
|
||||||
config NET_SCH_TEQL
|
|
||||||
tristate "True Link Equalizer (TEQL)"
|
|
||||||
---help---
|
|
||||||
--- a/net/sched/Makefile
|
|
||||||
+++ b/net/sched/Makefile
|
|
||||||
@@ -24,6 +24,7 @@ obj-$(CONFIG_NET_SCH_GRED) += sch_gred.o
|
|
||||||
obj-$(CONFIG_NET_SCH_INGRESS) += sch_ingress.o
|
|
||||||
obj-$(CONFIG_NET_SCH_DSMARK) += sch_dsmark.o
|
|
||||||
obj-$(CONFIG_NET_SCH_SFQ) += sch_sfq.o
|
|
||||||
+obj-$(CONFIG_NET_SCH_ESFQ) += sch_esfq.o
|
|
||||||
obj-$(CONFIG_NET_SCH_TBF) += sch_tbf.o
|
|
||||||
obj-$(CONFIG_NET_SCH_TEQL) += sch_teql.o
|
|
||||||
obj-$(CONFIG_NET_SCH_PRIO) += sch_prio.o
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/net/sched/sch_esfq.c
|
|
||||||
@@ -0,0 +1,704 @@
|
|
||||||
+/*
|
|
||||||
+ * net/sched/sch_esfq.c Extended Stochastic Fairness Queueing discipline.
|
|
||||||
+ *
|
|
||||||
+ * This program is free software; you can redistribute it and/or
|
|
||||||
+ * modify it under the terms of the GNU General Public License
|
|
||||||
+ * as published by the Free Software Foundation; either version
|
|
||||||
+ * 2 of the License, or (at your option) any later version.
|
|
||||||
+ *
|
|
||||||
+ * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
|
|
||||||
+ *
|
|
||||||
+ * Changes: Alexander Atanasov, <alex@ssi.bg>
|
|
||||||
+ * Added dynamic depth,limit,divisor,hash_kind options.
|
|
||||||
+ * Added dst and src hashes.
|
|
||||||
+ *
|
|
||||||
+ * Alexander Clouter, <alex@digriz.org.uk>
|
|
||||||
+ * Ported ESFQ to Linux 2.6.
|
|
||||||
+ *
|
|
||||||
+ * Corey Hickey, <bugfood-c@fatooh.org>
|
|
||||||
+ * Maintenance of the Linux 2.6 port.
|
|
||||||
+ * Added fwmark hash (thanks to Robert Kurjata).
|
|
||||||
+ * Added usage of jhash.
|
|
||||||
+ * Added conntrack support.
|
|
||||||
+ * Added ctnatchg hash (thanks to Ben Pfountz).
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
+#include <linux/module.h>
|
|
||||||
+#include <asm/uaccess.h>
|
|
||||||
+#include <asm/system.h>
|
|
||||||
+#include <linux/bitops.h>
|
|
||||||
+#include <linux/types.h>
|
|
||||||
+#include <linux/kernel.h>
|
|
||||||
+#include <linux/jiffies.h>
|
|
||||||
+#include <linux/string.h>
|
|
||||||
+#include <linux/mm.h>
|
|
||||||
+#include <linux/socket.h>
|
|
||||||
+#include <linux/sockios.h>
|
|
||||||
+#include <linux/in.h>
|
|
||||||
+#include <linux/errno.h>
|
|
||||||
+#include <linux/interrupt.h>
|
|
||||||
+#include <linux/if_ether.h>
|
|
||||||
+#include <linux/inet.h>
|
|
||||||
+#include <linux/netdevice.h>
|
|
||||||
+#include <linux/etherdevice.h>
|
|
||||||
+#include <linux/notifier.h>
|
|
||||||
+#include <linux/init.h>
|
|
||||||
+#include <net/ip.h>
|
|
||||||
+#include <linux/ipv6.h>
|
|
||||||
+#include <net/route.h>
|
|
||||||
+#include <linux/skbuff.h>
|
|
||||||
+#include <net/sock.h>
|
|
||||||
+#include <net/pkt_sched.h>
|
|
||||||
+#include <linux/jhash.h>
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+#include <net/netfilter/nf_conntrack.h>
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+/* Stochastic Fairness Queuing algorithm.
|
|
||||||
+ For more comments look at sch_sfq.c.
|
|
||||||
+ The difference is that you can change limit, depth,
|
|
||||||
+ hash table size and choose alternate hash types.
|
|
||||||
+
|
|
||||||
+ classic: same as in sch_sfq.c
|
|
||||||
+ dst: destination IP address
|
|
||||||
+ src: source IP address
|
|
||||||
+ fwmark: netfilter mark value
|
|
||||||
+ ctorigdst: original destination IP address
|
|
||||||
+ ctorigsrc: original source IP address
|
|
||||||
+ ctrepldst: reply destination IP address
|
|
||||||
+ ctreplsrc: reply source IP
|
|
||||||
+
|
|
||||||
+*/
|
|
||||||
+
|
|
||||||
+#define ESFQ_HEAD 0
|
|
||||||
+#define ESFQ_TAIL 1
|
|
||||||
+
|
|
||||||
+/* This type should contain at least SFQ_DEPTH*2 values */
|
|
||||||
+typedef unsigned int esfq_index;
|
|
||||||
+
|
|
||||||
+struct esfq_head
|
|
||||||
+{
|
|
||||||
+ esfq_index next;
|
|
||||||
+ esfq_index prev;
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+struct esfq_sched_data
|
|
||||||
+{
|
|
||||||
+/* Parameters */
|
|
||||||
+ int perturb_period;
|
|
||||||
+ unsigned quantum; /* Allotment per round: MUST BE >= MTU */
|
|
||||||
+ int limit;
|
|
||||||
+ unsigned depth;
|
|
||||||
+ unsigned hash_divisor;
|
|
||||||
+ unsigned hash_kind;
|
|
||||||
+/* Variables */
|
|
||||||
+ struct timer_list perturb_timer;
|
|
||||||
+ int perturbation;
|
|
||||||
+ esfq_index tail; /* Index of current slot in round */
|
|
||||||
+ esfq_index max_depth; /* Maximal depth */
|
|
||||||
+
|
|
||||||
+ esfq_index *ht; /* Hash table */
|
|
||||||
+ esfq_index *next; /* Active slots link */
|
|
||||||
+ short *allot; /* Current allotment per slot */
|
|
||||||
+ unsigned short *hash; /* Hash value indexed by slots */
|
|
||||||
+ struct sk_buff_head *qs; /* Slot queue */
|
|
||||||
+ struct esfq_head *dep; /* Linked list of slots, indexed by depth */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+/* This contains the info we will hash. */
|
|
||||||
+struct esfq_packet_info
|
|
||||||
+{
|
|
||||||
+ u32 proto; /* protocol or port */
|
|
||||||
+ u32 src; /* source from packet header */
|
|
||||||
+ u32 dst; /* destination from packet header */
|
|
||||||
+ u32 ctorigsrc; /* original source from conntrack */
|
|
||||||
+ u32 ctorigdst; /* original destination from conntrack */
|
|
||||||
+ u32 ctreplsrc; /* reply source from conntrack */
|
|
||||||
+ u32 ctrepldst; /* reply destination from conntrack */
|
|
||||||
+ u32 mark; /* netfilter mark (fwmark) */
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static __inline__ unsigned esfq_jhash_1word(struct esfq_sched_data *q,u32 a)
|
|
||||||
+{
|
|
||||||
+ return jhash_1word(a, q->perturbation) & (q->hash_divisor-1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static __inline__ unsigned esfq_jhash_2words(struct esfq_sched_data *q, u32 a, u32 b)
|
|
||||||
+{
|
|
||||||
+ return jhash_2words(a, b, q->perturbation) & (q->hash_divisor-1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static __inline__ unsigned esfq_jhash_3words(struct esfq_sched_data *q, u32 a, u32 b, u32 c)
|
|
||||||
+{
|
|
||||||
+ return jhash_3words(a, b, c, q->perturbation) & (q->hash_divisor-1);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static unsigned esfq_hash(struct esfq_sched_data *q, struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ struct esfq_packet_info info;
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ enum ip_conntrack_info ctinfo;
|
|
||||||
+ struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ switch (skb->protocol) {
|
|
||||||
+ case __constant_htons(ETH_P_IP):
|
|
||||||
+ {
|
|
||||||
+ struct iphdr *iph = ip_hdr(skb);
|
|
||||||
+ info.dst = iph->daddr;
|
|
||||||
+ info.src = iph->saddr;
|
|
||||||
+ if (!(iph->frag_off&htons(IP_MF|IP_OFFSET)) &&
|
|
||||||
+ (iph->protocol == IPPROTO_TCP ||
|
|
||||||
+ iph->protocol == IPPROTO_UDP ||
|
|
||||||
+ iph->protocol == IPPROTO_SCTP ||
|
|
||||||
+ iph->protocol == IPPROTO_DCCP ||
|
|
||||||
+ iph->protocol == IPPROTO_ESP))
|
|
||||||
+ info.proto = *(((u32*)iph) + iph->ihl);
|
|
||||||
+ else
|
|
||||||
+ info.proto = iph->protocol;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ case __constant_htons(ETH_P_IPV6):
|
|
||||||
+ {
|
|
||||||
+ struct ipv6hdr *iph = ipv6_hdr(skb);
|
|
||||||
+ /* Hash ipv6 addresses into a u32. This isn't ideal,
|
|
||||||
+ * but the code is simple. */
|
|
||||||
+ info.dst = jhash2(iph->daddr.s6_addr32, 4, q->perturbation);
|
|
||||||
+ info.src = jhash2(iph->saddr.s6_addr32, 4, q->perturbation);
|
|
||||||
+ if (iph->nexthdr == IPPROTO_TCP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_UDP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_SCTP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_DCCP ||
|
|
||||||
+ iph->nexthdr == IPPROTO_ESP)
|
|
||||||
+ info.proto = *(u32*)&iph[1];
|
|
||||||
+ else
|
|
||||||
+ info.proto = iph->nexthdr;
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
+ default:
|
|
||||||
+ info.dst = (u32)(unsigned long)skb->dst;
|
|
||||||
+ info.src = (u32)(unsigned long)skb->sk;
|
|
||||||
+ info.proto = skb->protocol;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ info.mark = skb->mark;
|
|
||||||
+
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ /* defaults if there is no conntrack info */
|
|
||||||
+ info.ctorigsrc = info.src;
|
|
||||||
+ info.ctorigdst = info.dst;
|
|
||||||
+ info.ctreplsrc = info.dst;
|
|
||||||
+ info.ctrepldst = info.src;
|
|
||||||
+ /* collect conntrack info */
|
|
||||||
+ if (ct && ct != &nf_conntrack_untracked) {
|
|
||||||
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
|
|
||||||
+ info.ctorigsrc = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
|
|
||||||
+ info.ctorigdst = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip;
|
|
||||||
+ info.ctreplsrc = ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip;
|
|
||||||
+ info.ctrepldst = ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip;
|
|
||||||
+ }
|
|
||||||
+ else if (skb->protocol == __constant_htons(ETH_P_IPV6)) {
|
|
||||||
+ /* Again, hash ipv6 addresses into a single u32. */
|
|
||||||
+ info.ctorigsrc = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip6, 4, q->perturbation);
|
|
||||||
+ info.ctorigdst = jhash2(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3.ip6, 4, q->perturbation);
|
|
||||||
+ info.ctreplsrc = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6, 4, q->perturbation);
|
|
||||||
+ info.ctrepldst = jhash2(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6, 4, q->perturbation);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
+ switch(q->hash_kind) {
|
|
||||||
+ case TCA_SFQ_HASH_CLASSIC:
|
|
||||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
|
||||||
+ case TCA_SFQ_HASH_DST:
|
|
||||||
+ return esfq_jhash_1word(q, info.dst);
|
|
||||||
+ case TCA_SFQ_HASH_SRC:
|
|
||||||
+ return esfq_jhash_1word(q, info.src);
|
|
||||||
+ case TCA_SFQ_HASH_FWMARK:
|
|
||||||
+ return esfq_jhash_1word(q, info.mark);
|
|
||||||
+#ifdef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctorigdst);
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctrepldst);
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
|
||||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
|
||||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
|
||||||
+ {
|
|
||||||
+ if (info.ctorigdst == info.ctreplsrc)
|
|
||||||
+ return esfq_jhash_1word(q, info.ctorigsrc);
|
|
||||||
+ return esfq_jhash_1word(q, info.ctreplsrc);
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ default:
|
|
||||||
+ if (net_ratelimit())
|
|
||||||
+ printk(KERN_WARNING "ESFQ: Unknown hash method. Falling back to classic.\n");
|
|
||||||
+ }
|
|
||||||
+ return esfq_jhash_3words(q, info.dst, info.src, info.proto);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void esfq_link(struct esfq_sched_data *q, esfq_index x)
|
|
||||||
+{
|
|
||||||
+ esfq_index p, n;
|
|
||||||
+ int d = q->qs[x].qlen + q->depth;
|
|
||||||
+
|
|
||||||
+ p = d;
|
|
||||||
+ n = q->dep[d].next;
|
|
||||||
+ q->dep[x].next = n;
|
|
||||||
+ q->dep[x].prev = p;
|
|
||||||
+ q->dep[p].next = q->dep[n].prev = x;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void esfq_dec(struct esfq_sched_data *q, esfq_index x)
|
|
||||||
+{
|
|
||||||
+ esfq_index p, n;
|
|
||||||
+
|
|
||||||
+ n = q->dep[x].next;
|
|
||||||
+ p = q->dep[x].prev;
|
|
||||||
+ q->dep[p].next = n;
|
|
||||||
+ q->dep[n].prev = p;
|
|
||||||
+
|
|
||||||
+ if (n == p && q->max_depth == q->qs[x].qlen + 1)
|
|
||||||
+ q->max_depth--;
|
|
||||||
+
|
|
||||||
+ esfq_link(q, x);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline void esfq_inc(struct esfq_sched_data *q, esfq_index x)
|
|
||||||
+{
|
|
||||||
+ esfq_index p, n;
|
|
||||||
+ int d;
|
|
||||||
+
|
|
||||||
+ n = q->dep[x].next;
|
|
||||||
+ p = q->dep[x].prev;
|
|
||||||
+ q->dep[p].next = n;
|
|
||||||
+ q->dep[n].prev = p;
|
|
||||||
+ d = q->qs[x].qlen;
|
|
||||||
+ if (q->max_depth < d)
|
|
||||||
+ q->max_depth = d;
|
|
||||||
+
|
|
||||||
+ esfq_link(q, x);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static unsigned int esfq_drop(struct Qdisc *sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_index d = q->max_depth;
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+ unsigned int len;
|
|
||||||
+
|
|
||||||
+ /* Queue is full! Find the longest slot and
|
|
||||||
+ drop a packet from it */
|
|
||||||
+
|
|
||||||
+ if (d > 1) {
|
|
||||||
+ esfq_index x = q->dep[d+q->depth].next;
|
|
||||||
+ skb = q->qs[x].prev;
|
|
||||||
+ len = skb->len;
|
|
||||||
+ __skb_unlink(skb, &q->qs[x]);
|
|
||||||
+ kfree_skb(skb);
|
|
||||||
+ esfq_dec(q, x);
|
|
||||||
+ sch->q.qlen--;
|
|
||||||
+ sch->qstats.drops++;
|
|
||||||
+ sch->qstats.backlog -= len;
|
|
||||||
+ return len;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (d == 1) {
|
|
||||||
+ /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
|
|
||||||
+ d = q->next[q->tail];
|
|
||||||
+ q->next[q->tail] = q->next[d];
|
|
||||||
+ q->allot[q->next[d]] += q->quantum;
|
|
||||||
+ skb = q->qs[d].prev;
|
|
||||||
+ len = skb->len;
|
|
||||||
+ __skb_unlink(skb, &q->qs[d]);
|
|
||||||
+ kfree_skb(skb);
|
|
||||||
+ esfq_dec(q, d);
|
|
||||||
+ sch->q.qlen--;
|
|
||||||
+ q->ht[q->hash[d]] = q->depth;
|
|
||||||
+ sch->qstats.drops++;
|
|
||||||
+ sch->qstats.backlog -= len;
|
|
||||||
+ return len;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_q_enqueue(struct sk_buff *skb, struct esfq_sched_data *q, unsigned int end)
|
|
||||||
+{
|
|
||||||
+ unsigned hash = esfq_hash(q, skb);
|
|
||||||
+ unsigned depth = q->depth;
|
|
||||||
+ esfq_index x;
|
|
||||||
+
|
|
||||||
+ x = q->ht[hash];
|
|
||||||
+ if (x == depth) {
|
|
||||||
+ q->ht[hash] = x = q->dep[depth].next;
|
|
||||||
+ q->hash[x] = hash;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ if (end == ESFQ_TAIL)
|
|
||||||
+ __skb_queue_tail(&q->qs[x], skb);
|
|
||||||
+ else
|
|
||||||
+ __skb_queue_head(&q->qs[x], skb);
|
|
||||||
+
|
|
||||||
+ esfq_inc(q, x);
|
|
||||||
+ if (q->qs[x].qlen == 1) { /* The flow is new */
|
|
||||||
+ if (q->tail == depth) { /* It is the first flow */
|
|
||||||
+ q->tail = x;
|
|
||||||
+ q->next[x] = x;
|
|
||||||
+ q->allot[x] = q->quantum;
|
|
||||||
+ } else {
|
|
||||||
+ q->next[x] = q->next[q->tail];
|
|
||||||
+ q->next[q->tail] = x;
|
|
||||||
+ q->tail = x;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_enqueue(struct sk_buff *skb, struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_q_enqueue(skb, q, ESFQ_TAIL);
|
|
||||||
+ sch->qstats.backlog += skb->len;
|
|
||||||
+ if (++sch->q.qlen < q->limit-1) {
|
|
||||||
+ sch->bstats.bytes += skb->len;
|
|
||||||
+ sch->bstats.packets++;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ sch->qstats.drops++;
|
|
||||||
+ esfq_drop(sch);
|
|
||||||
+ return NET_XMIT_CN;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static int esfq_requeue(struct sk_buff *skb, struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_q_enqueue(skb, q, ESFQ_HEAD);
|
|
||||||
+ sch->qstats.backlog += skb->len;
|
|
||||||
+ if (++sch->q.qlen < q->limit - 1) {
|
|
||||||
+ sch->qstats.requeues++;
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ sch->qstats.drops++;
|
|
||||||
+ esfq_drop(sch);
|
|
||||||
+ return NET_XMIT_CN;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct sk_buff *esfq_q_dequeue(struct esfq_sched_data *q)
|
|
||||||
+{
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+ unsigned depth = q->depth;
|
|
||||||
+ esfq_index a, old_a;
|
|
||||||
+
|
|
||||||
+ /* No active slots */
|
|
||||||
+ if (q->tail == depth)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ a = old_a = q->next[q->tail];
|
|
||||||
+
|
|
||||||
+ /* Grab packet */
|
|
||||||
+ skb = __skb_dequeue(&q->qs[a]);
|
|
||||||
+ esfq_dec(q, a);
|
|
||||||
+
|
|
||||||
+ /* Is the slot empty? */
|
|
||||||
+ if (q->qs[a].qlen == 0) {
|
|
||||||
+ q->ht[q->hash[a]] = depth;
|
|
||||||
+ a = q->next[a];
|
|
||||||
+ if (a == old_a) {
|
|
||||||
+ q->tail = depth;
|
|
||||||
+ return skb;
|
|
||||||
+ }
|
|
||||||
+ q->next[q->tail] = a;
|
|
||||||
+ q->allot[a] += q->quantum;
|
|
||||||
+ } else if ((q->allot[a] -= skb->len) <= 0) {
|
|
||||||
+ q->tail = a;
|
|
||||||
+ a = q->next[a];
|
|
||||||
+ q->allot[a] += q->quantum;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return skb;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct sk_buff *esfq_dequeue(struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+
|
|
||||||
+ skb = esfq_q_dequeue(q);
|
|
||||||
+ if (skb == NULL)
|
|
||||||
+ return NULL;
|
|
||||||
+ sch->q.qlen--;
|
|
||||||
+ sch->qstats.backlog -= skb->len;
|
|
||||||
+ return skb;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_q_destroy(struct esfq_sched_data *q)
|
|
||||||
+{
|
|
||||||
+ del_timer(&q->perturb_timer);
|
|
||||||
+ if(q->ht)
|
|
||||||
+ kfree(q->ht);
|
|
||||||
+ if(q->dep)
|
|
||||||
+ kfree(q->dep);
|
|
||||||
+ if(q->next)
|
|
||||||
+ kfree(q->next);
|
|
||||||
+ if(q->allot)
|
|
||||||
+ kfree(q->allot);
|
|
||||||
+ if(q->hash)
|
|
||||||
+ kfree(q->hash);
|
|
||||||
+ if(q->qs)
|
|
||||||
+ kfree(q->qs);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_destroy(struct Qdisc *sch)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ esfq_q_destroy(q);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+static void esfq_reset(struct Qdisc* sch)
|
|
||||||
+{
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+
|
|
||||||
+ while ((skb = esfq_dequeue(sch)) != NULL)
|
|
||||||
+ kfree_skb(skb);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static void esfq_perturbation(unsigned long arg)
|
|
||||||
+{
|
|
||||||
+ struct Qdisc *sch = (struct Qdisc*)arg;
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+
|
|
||||||
+ q->perturbation = net_random()&0x1F;
|
|
||||||
+
|
|
||||||
+ if (q->perturb_period) {
|
|
||||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
|
||||||
+ add_timer(&q->perturb_timer);
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static unsigned int esfq_check_hash(unsigned int kind)
|
|
||||||
+{
|
|
||||||
+ switch (kind) {
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGDST:
|
|
||||||
+ case TCA_SFQ_HASH_CTORIGSRC:
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLDST:
|
|
||||||
+ case TCA_SFQ_HASH_CTREPLSRC:
|
|
||||||
+ case TCA_SFQ_HASH_CTNATCHG:
|
|
||||||
+#ifndef CONFIG_NET_SCH_ESFQ_NFCT
|
|
||||||
+ {
|
|
||||||
+ if (net_ratelimit())
|
|
||||||
+ printk(KERN_WARNING "ESFQ: Conntrack hash types disabled in kernel config. Falling back to classic.\n");
|
|
||||||
+ return TCA_SFQ_HASH_CLASSIC;
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
+ case TCA_SFQ_HASH_CLASSIC:
|
|
||||||
+ case TCA_SFQ_HASH_DST:
|
|
||||||
+ case TCA_SFQ_HASH_SRC:
|
|
||||||
+ case TCA_SFQ_HASH_FWMARK:
|
|
||||||
+ return kind;
|
|
||||||
+ default:
|
|
||||||
+ {
|
|
||||||
+ if (net_ratelimit())
|
|
||||||
+ printk(KERN_WARNING "ESFQ: Unknown hash type. Falling back to classic.\n");
|
|
||||||
+ return TCA_SFQ_HASH_CLASSIC;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_q_init(struct esfq_sched_data *q, struct rtattr *opt)
|
|
||||||
+{
|
|
||||||
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
|
|
||||||
+ esfq_index p = ~0U/2;
|
|
||||||
+ int i;
|
|
||||||
+
|
|
||||||
+ if (opt && opt->rta_len < RTA_LENGTH(sizeof(*ctl)))
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ q->perturbation = 0;
|
|
||||||
+ q->hash_kind = TCA_SFQ_HASH_CLASSIC;
|
|
||||||
+ q->max_depth = 0;
|
|
||||||
+ if (opt == NULL) {
|
|
||||||
+ q->perturb_period = 0;
|
|
||||||
+ q->hash_divisor = 1024;
|
|
||||||
+ q->tail = q->limit = q->depth = 128;
|
|
||||||
+
|
|
||||||
+ } else {
|
|
||||||
+ struct tc_esfq_qopt *ctl = RTA_DATA(opt);
|
|
||||||
+ if (ctl->quantum)
|
|
||||||
+ q->quantum = ctl->quantum;
|
|
||||||
+ q->perturb_period = ctl->perturb_period*HZ;
|
|
||||||
+ q->hash_divisor = ctl->divisor ? : 1024;
|
|
||||||
+ q->tail = q->limit = q->depth = ctl->flows ? : 128;
|
|
||||||
+
|
|
||||||
+ if ( q->depth > p - 1 )
|
|
||||||
+ return -EINVAL;
|
|
||||||
+
|
|
||||||
+ if (ctl->limit)
|
|
||||||
+ q->limit = min_t(u32, ctl->limit, q->depth);
|
|
||||||
+
|
|
||||||
+ if (ctl->hash_kind) {
|
|
||||||
+ q->hash_kind = esfq_check_hash(ctl->hash_kind);
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ q->ht = kmalloc(q->hash_divisor*sizeof(esfq_index), GFP_KERNEL);
|
|
||||||
+ if (!q->ht)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->dep = kmalloc((1+q->depth*2)*sizeof(struct esfq_head), GFP_KERNEL);
|
|
||||||
+ if (!q->dep)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->next = kmalloc(q->depth*sizeof(esfq_index), GFP_KERNEL);
|
|
||||||
+ if (!q->next)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->allot = kmalloc(q->depth*sizeof(short), GFP_KERNEL);
|
|
||||||
+ if (!q->allot)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->hash = kmalloc(q->depth*sizeof(unsigned short), GFP_KERNEL);
|
|
||||||
+ if (!q->hash)
|
|
||||||
+ goto err_case;
|
|
||||||
+ q->qs = kmalloc(q->depth*sizeof(struct sk_buff_head), GFP_KERNEL);
|
|
||||||
+ if (!q->qs)
|
|
||||||
+ goto err_case;
|
|
||||||
+
|
|
||||||
+ for (i=0; i< q->hash_divisor; i++)
|
|
||||||
+ q->ht[i] = q->depth;
|
|
||||||
+ for (i=0; i<q->depth; i++) {
|
|
||||||
+ skb_queue_head_init(&q->qs[i]);
|
|
||||||
+ q->dep[i+q->depth].next = i+q->depth;
|
|
||||||
+ q->dep[i+q->depth].prev = i+q->depth;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ for (i=0; i<q->depth; i++)
|
|
||||||
+ esfq_link(q, i);
|
|
||||||
+ return 0;
|
|
||||||
+err_case:
|
|
||||||
+ esfq_q_destroy(q);
|
|
||||||
+ return -ENOBUFS;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_init(struct Qdisc *sch, struct rtattr *opt)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ q->quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
|
||||||
+ if ((err = esfq_q_init(q, opt)))
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ init_timer(&q->perturb_timer);
|
|
||||||
+ q->perturb_timer.data = (unsigned long)sch;
|
|
||||||
+ q->perturb_timer.function = esfq_perturbation;
|
|
||||||
+ if (q->perturb_period) {
|
|
||||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
|
||||||
+ add_timer(&q->perturb_timer);
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_change(struct Qdisc *sch, struct rtattr *opt)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ struct esfq_sched_data new;
|
|
||||||
+ struct sk_buff *skb;
|
|
||||||
+ int err;
|
|
||||||
+
|
|
||||||
+ /* set up new queue */
|
|
||||||
+ memset(&new, 0, sizeof(struct esfq_sched_data));
|
|
||||||
+ new.quantum = psched_mtu(qdisc_dev(sch)); /* default */
|
|
||||||
+ if ((err = esfq_q_init(&new, opt)))
|
|
||||||
+ return err;
|
|
||||||
+
|
|
||||||
+ /* copy all packets from the old queue to the new queue */
|
|
||||||
+ sch_tree_lock(sch);
|
|
||||||
+ while ((skb = esfq_q_dequeue(q)) != NULL)
|
|
||||||
+ esfq_q_enqueue(skb, &new, ESFQ_TAIL);
|
|
||||||
+
|
|
||||||
+ /* clean up the old queue */
|
|
||||||
+ esfq_q_destroy(q);
|
|
||||||
+
|
|
||||||
+ /* copy elements of the new queue into the old queue */
|
|
||||||
+ q->perturb_period = new.perturb_period;
|
|
||||||
+ q->quantum = new.quantum;
|
|
||||||
+ q->limit = new.limit;
|
|
||||||
+ q->depth = new.depth;
|
|
||||||
+ q->hash_divisor = new.hash_divisor;
|
|
||||||
+ q->hash_kind = new.hash_kind;
|
|
||||||
+ q->tail = new.tail;
|
|
||||||
+ q->max_depth = new.max_depth;
|
|
||||||
+ q->ht = new.ht;
|
|
||||||
+ q->dep = new.dep;
|
|
||||||
+ q->next = new.next;
|
|
||||||
+ q->allot = new.allot;
|
|
||||||
+ q->hash = new.hash;
|
|
||||||
+ q->qs = new.qs;
|
|
||||||
+
|
|
||||||
+ /* finish up */
|
|
||||||
+ if (q->perturb_period) {
|
|
||||||
+ q->perturb_timer.expires = jiffies + q->perturb_period;
|
|
||||||
+ add_timer(&q->perturb_timer);
|
|
||||||
+ } else {
|
|
||||||
+ q->perturbation = 0;
|
|
||||||
+ }
|
|
||||||
+ sch_tree_unlock(sch);
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int esfq_dump(struct Qdisc *sch, struct sk_buff *skb)
|
|
||||||
+{
|
|
||||||
+ struct esfq_sched_data *q = qdisc_priv(sch);
|
|
||||||
+ unsigned char *b = skb->tail;
|
|
||||||
+ struct tc_esfq_qopt opt;
|
|
||||||
+
|
|
||||||
+ opt.quantum = q->quantum;
|
|
||||||
+ opt.perturb_period = q->perturb_period/HZ;
|
|
||||||
+
|
|
||||||
+ opt.limit = q->limit;
|
|
||||||
+ opt.divisor = q->hash_divisor;
|
|
||||||
+ opt.flows = q->depth;
|
|
||||||
+ opt.hash_kind = q->hash_kind;
|
|
||||||
+
|
|
||||||
+ RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt);
|
|
||||||
+
|
|
||||||
+ return skb->len;
|
|
||||||
+
|
|
||||||
+rtattr_failure:
|
|
||||||
+ skb_trim(skb, b - skb->data);
|
|
||||||
+ return -1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static struct Qdisc_ops esfq_qdisc_ops =
|
|
||||||
+{
|
|
||||||
+ .next = NULL,
|
|
||||||
+ .cl_ops = NULL,
|
|
||||||
+ .id = "esfq",
|
|
||||||
+ .priv_size = sizeof(struct esfq_sched_data),
|
|
||||||
+ .enqueue = esfq_enqueue,
|
|
||||||
+ .dequeue = esfq_dequeue,
|
|
||||||
+ .requeue = esfq_requeue,
|
|
||||||
+ .drop = esfq_drop,
|
|
||||||
+ .init = esfq_init,
|
|
||||||
+ .reset = esfq_reset,
|
|
||||||
+ .destroy = esfq_destroy,
|
|
||||||
+ .change = esfq_change,
|
|
||||||
+ .dump = esfq_dump,
|
|
||||||
+ .owner = THIS_MODULE,
|
|
||||||
+};
|
|
||||||
+
|
|
||||||
+static int __init esfq_module_init(void)
|
|
||||||
+{
|
|
||||||
+ return register_qdisc(&esfq_qdisc_ops);
|
|
||||||
+}
|
|
||||||
+static void __exit esfq_module_exit(void)
|
|
||||||
+{
|
|
||||||
+ unregister_qdisc(&esfq_qdisc_ops);
|
|
||||||
+}
|
|
||||||
+module_init(esfq_module_init)
|
|
||||||
+module_exit(esfq_module_exit)
|
|
||||||
+MODULE_LICENSE("GPL");
|
|
|
@ -1,227 +0,0 @@
|
||||||
--- a/include/linux/jhash.h
|
|
||||||
+++ b/include/linux/jhash.h
|
|
||||||
@@ -3,80 +3,95 @@
|
|
||||||
|
|
||||||
/* jhash.h: Jenkins hash support.
|
|
||||||
*
|
|
||||||
- * Copyright (C) 1996 Bob Jenkins (bob_jenkins@burtleburtle.net)
|
|
||||||
+ * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
|
|
||||||
*
|
|
||||||
* http://burtleburtle.net/bob/hash/
|
|
||||||
*
|
|
||||||
* These are the credits from Bob's sources:
|
|
||||||
*
|
|
||||||
- * lookup2.c, by Bob Jenkins, December 1996, Public Domain.
|
|
||||||
- * hash(), hash2(), hash3, and mix() are externally useful functions.
|
|
||||||
- * Routines to test the hash are included if SELF_TEST is defined.
|
|
||||||
- * You can use this free for any purpose. It has no warranty.
|
|
||||||
+ * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
|
|
||||||
*
|
|
||||||
- * Copyright (C) 2003 David S. Miller (davem@redhat.com)
|
|
||||||
+ * These are functions for producing 32-bit hashes for hash table lookup.
|
|
||||||
+ * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
|
|
||||||
+ * are externally useful functions. Routines to test the hash are included
|
|
||||||
+ * if SELF_TEST is defined. You can use this free for any purpose. It's in
|
|
||||||
+ * the public domain. It has no warranty.
|
|
||||||
+ *
|
|
||||||
+ * Copyright (C) 2009 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
|
||||||
*
|
|
||||||
* I've modified Bob's hash to be useful in the Linux kernel, and
|
|
||||||
- * any bugs present are surely my fault. -DaveM
|
|
||||||
+ * any bugs present are my fault. Jozsef
|
|
||||||
*/
|
|
||||||
|
|
||||||
-/* NOTE: Arguments are modified. */
|
|
||||||
-#define __jhash_mix(a, b, c) \
|
|
||||||
+#define __rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
|
|
||||||
+
|
|
||||||
+/* __jhash_mix - mix 3 32-bit values reversibly. */
|
|
||||||
+#define __jhash_mix(a,b,c) \
|
|
||||||
+{ \
|
|
||||||
+ a -= c; a ^= __rot(c, 4); c += b; \
|
|
||||||
+ b -= a; b ^= __rot(a, 6); a += c; \
|
|
||||||
+ c -= b; c ^= __rot(b, 8); b += a; \
|
|
||||||
+ a -= c; a ^= __rot(c,16); c += b; \
|
|
||||||
+ b -= a; b ^= __rot(a,19); a += c; \
|
|
||||||
+ c -= b; c ^= __rot(b, 4); b += a; \
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
|
|
||||||
+#define __jhash_final(a,b,c) \
|
|
||||||
{ \
|
|
||||||
- a -= b; a -= c; a ^= (c>>13); \
|
|
||||||
- b -= c; b -= a; b ^= (a<<8); \
|
|
||||||
- c -= a; c -= b; c ^= (b>>13); \
|
|
||||||
- a -= b; a -= c; a ^= (c>>12); \
|
|
||||||
- b -= c; b -= a; b ^= (a<<16); \
|
|
||||||
- c -= a; c -= b; c ^= (b>>5); \
|
|
||||||
- a -= b; a -= c; a ^= (c>>3); \
|
|
||||||
- b -= c; b -= a; b ^= (a<<10); \
|
|
||||||
- c -= a; c -= b; c ^= (b>>15); \
|
|
||||||
+ c ^= b; c -= __rot(b,14); \
|
|
||||||
+ a ^= c; a -= __rot(c,11); \
|
|
||||||
+ b ^= a; b -= __rot(a,25); \
|
|
||||||
+ c ^= b; c -= __rot(b,16); \
|
|
||||||
+ a ^= c; a -= __rot(c,4); \
|
|
||||||
+ b ^= a; b -= __rot(a,14); \
|
|
||||||
+ c ^= b; c -= __rot(b,24); \
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* The golden ration: an arbitrary value */
|
|
||||||
-#define JHASH_GOLDEN_RATIO 0x9e3779b9
|
|
||||||
+/* An arbitrary initial parameter */
|
|
||||||
+#define JHASH_GOLDEN_RATIO 0xdeadbeef
|
|
||||||
|
|
||||||
/* The most generic version, hashes an arbitrary sequence
|
|
||||||
* of bytes. No alignment or length assumptions are made about
|
|
||||||
- * the input key.
|
|
||||||
+ * the input key. The result depends on endianness.
|
|
||||||
*/
|
|
||||||
static inline u32 jhash(const void *key, u32 length, u32 initval)
|
|
||||||
{
|
|
||||||
- u32 a, b, c, len;
|
|
||||||
+ u32 a,b,c;
|
|
||||||
const u8 *k = key;
|
|
||||||
|
|
||||||
- len = length;
|
|
||||||
- a = b = JHASH_GOLDEN_RATIO;
|
|
||||||
- c = initval;
|
|
||||||
-
|
|
||||||
- while (len >= 12) {
|
|
||||||
- a += (k[0] +((u32)k[1]<<8) +((u32)k[2]<<16) +((u32)k[3]<<24));
|
|
||||||
- b += (k[4] +((u32)k[5]<<8) +((u32)k[6]<<16) +((u32)k[7]<<24));
|
|
||||||
- c += (k[8] +((u32)k[9]<<8) +((u32)k[10]<<16)+((u32)k[11]<<24));
|
|
||||||
-
|
|
||||||
- __jhash_mix(a,b,c);
|
|
||||||
+ /* Set up the internal state */
|
|
||||||
+ a = b = c = JHASH_GOLDEN_RATIO + length + initval;
|
|
||||||
|
|
||||||
+ /* all but the last block: affect some 32 bits of (a,b,c) */
|
|
||||||
+ while (length > 12) {
|
|
||||||
+ a += (k[0] + ((u32)k[1]<<8) + ((u32)k[2]<<16) + ((u32)k[3]<<24));
|
|
||||||
+ b += (k[4] + ((u32)k[5]<<8) + ((u32)k[6]<<16) + ((u32)k[7]<<24));
|
|
||||||
+ c += (k[8] + ((u32)k[9]<<8) + ((u32)k[10]<<16) + ((u32)k[11]<<24));
|
|
||||||
+ __jhash_mix(a, b, c);
|
|
||||||
+ length -= 12;
|
|
||||||
k += 12;
|
|
||||||
- len -= 12;
|
|
||||||
}
|
|
||||||
|
|
||||||
- c += length;
|
|
||||||
- switch (len) {
|
|
||||||
- case 11: c += ((u32)k[10]<<24);
|
|
||||||
- case 10: c += ((u32)k[9]<<16);
|
|
||||||
- case 9 : c += ((u32)k[8]<<8);
|
|
||||||
- case 8 : b += ((u32)k[7]<<24);
|
|
||||||
- case 7 : b += ((u32)k[6]<<16);
|
|
||||||
- case 6 : b += ((u32)k[5]<<8);
|
|
||||||
+ /* last block: affect all 32 bits of (c) */
|
|
||||||
+ /* all the case statements fall through */
|
|
||||||
+ switch (length) {
|
|
||||||
+ case 12: c += (u32)k[11]<<24;
|
|
||||||
+ case 11: c += (u32)k[10]<<16;
|
|
||||||
+ case 10: c += (u32)k[9]<<8;
|
|
||||||
+ case 9 : c += k[8];
|
|
||||||
+ case 8 : b += (u32)k[7]<<24;
|
|
||||||
+ case 7 : b += (u32)k[6]<<16;
|
|
||||||
+ case 6 : b += (u32)k[5]<<8;
|
|
||||||
case 5 : b += k[4];
|
|
||||||
- case 4 : a += ((u32)k[3]<<24);
|
|
||||||
- case 3 : a += ((u32)k[2]<<16);
|
|
||||||
- case 2 : a += ((u32)k[1]<<8);
|
|
||||||
+ case 4 : a += (u32)k[3]<<24;
|
|
||||||
+ case 3 : a += (u32)k[2]<<16;
|
|
||||||
+ case 2 : a += (u32)k[1]<<8;
|
|
||||||
case 1 : a += k[0];
|
|
||||||
- };
|
|
||||||
-
|
|
||||||
- __jhash_mix(a,b,c);
|
|
||||||
+ __jhash_final(a, b, c);
|
|
||||||
+ case 0 :
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
@@ -86,58 +101,57 @@ static inline u32 jhash(const void *key,
|
|
||||||
*/
|
|
||||||
static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
|
|
||||||
{
|
|
||||||
- u32 a, b, c, len;
|
|
||||||
+ u32 a, b, c;
|
|
||||||
|
|
||||||
- a = b = JHASH_GOLDEN_RATIO;
|
|
||||||
- c = initval;
|
|
||||||
- len = length;
|
|
||||||
+ /* Set up the internal state */
|
|
||||||
+ a = b = c = JHASH_GOLDEN_RATIO + (length<<2) + initval;
|
|
||||||
|
|
||||||
- while (len >= 3) {
|
|
||||||
+ /* handle most of the key */
|
|
||||||
+ while (length > 3) {
|
|
||||||
a += k[0];
|
|
||||||
b += k[1];
|
|
||||||
c += k[2];
|
|
||||||
__jhash_mix(a, b, c);
|
|
||||||
- k += 3; len -= 3;
|
|
||||||
+ length -= 3;
|
|
||||||
+ k += 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
- c += length * 4;
|
|
||||||
-
|
|
||||||
- switch (len) {
|
|
||||||
- case 2 : b += k[1];
|
|
||||||
- case 1 : a += k[0];
|
|
||||||
- };
|
|
||||||
-
|
|
||||||
- __jhash_mix(a,b,c);
|
|
||||||
+ /* handle the last 3 u32's */
|
|
||||||
+ /* all the case statements fall through */
|
|
||||||
+ switch (length) {
|
|
||||||
+ case 3: c += k[2];
|
|
||||||
+ case 2: b += k[1];
|
|
||||||
+ case 1: a += k[0];
|
|
||||||
+ __jhash_final(a, b, c);
|
|
||||||
+ case 0: /* case 0: nothing left to add */
|
|
||||||
+ break;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
-
|
|
||||||
/* A special ultra-optimized versions that knows they are hashing exactly
|
|
||||||
* 3, 2 or 1 word(s).
|
|
||||||
- *
|
|
||||||
- * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally
|
|
||||||
- * done at the end is not done here.
|
|
||||||
*/
|
|
||||||
static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
|
|
||||||
{
|
|
||||||
- a += JHASH_GOLDEN_RATIO;
|
|
||||||
- b += JHASH_GOLDEN_RATIO;
|
|
||||||
- c += initval;
|
|
||||||
+ a += JHASH_GOLDEN_RATIO + initval;
|
|
||||||
+ b += JHASH_GOLDEN_RATIO + initval;
|
|
||||||
+ c += JHASH_GOLDEN_RATIO + initval;
|
|
||||||
|
|
||||||
- __jhash_mix(a, b, c);
|
|
||||||
+ __jhash_final(a, b, c);
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
|
|
||||||
{
|
|
||||||
- return jhash_3words(a, b, 0, initval);
|
|
||||||
+ return jhash_3words(0, a, b, initval);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u32 jhash_1word(u32 a, u32 initval)
|
|
||||||
{
|
|
||||||
- return jhash_3words(a, 0, 0, initval);
|
|
||||||
+ return jhash_3words(0, 0, a, initval);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* _LINUX_JHASH_H */
|
|
|
@ -1,12 +0,0 @@
|
||||||
--- a/arch/mips/Makefile
|
|
||||||
+++ b/arch/mips/Makefile
|
|
||||||
@@ -593,6 +593,9 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/
|
|
||||||
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/
|
|
||||||
core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/
|
|
||||||
|
|
||||||
+# temporary until string.h is fixed
|
|
||||||
+cflags-y += -ffreestanding
|
|
||||||
+
|
|
||||||
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
|
|
||||||
drivers-$(CONFIG_PCI) += arch/mips/pci/
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
--- a/include/linux/slab.h
|
|
||||||
+++ b/include/linux/slab.h
|
|
||||||
@@ -115,8 +115,8 @@ int kmem_ptr_validate(struct kmem_cache
|
|
||||||
* to do various tricks to work around compiler limitations in order to
|
|
||||||
* ensure proper constant folding.
|
|
||||||
*/
|
|
||||||
-#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 25 ? \
|
|
||||||
- (MAX_ORDER + PAGE_SHIFT - 1) : 25)
|
|
||||||
+#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT - 1) <= 17 ? \
|
|
||||||
+ (MAX_ORDER + PAGE_SHIFT - 1) : 17)
|
|
||||||
|
|
||||||
#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_HIGH)
|
|
||||||
#define KMALLOC_MAX_ORDER (KMALLOC_SHIFT_HIGH - PAGE_SHIFT)
|
|
|
@ -1,132 +0,0 @@
|
||||||
--- a/fs/jffs2/build.c
|
|
||||||
+++ b/fs/jffs2/build.c
|
|
||||||
@@ -111,6 +111,17 @@ static int jffs2_build_filesystem(struct
|
|
||||||
dbg_fsbuild("scanned flash completely\n");
|
|
||||||
jffs2_dbg_dump_block_lists_nolock(c);
|
|
||||||
|
|
||||||
+ if (c->flags & (1 << 7)) {
|
|
||||||
+ printk("%s(): unlocking the mtd device... ", __func__);
|
|
||||||
+ if (c->mtd->unlock)
|
|
||||||
+ c->mtd->unlock(c->mtd, 0, c->mtd->size);
|
|
||||||
+ printk("done.\n");
|
|
||||||
+
|
|
||||||
+ printk("%s(): erasing all blocks after the end marker... ", __func__);
|
|
||||||
+ jffs2_erase_pending_blocks(c, -1);
|
|
||||||
+ printk("done.\n");
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
dbg_fsbuild("pass 1 starting\n");
|
|
||||||
c->flags |= JFFS2_SB_FLAG_BUILDING;
|
|
||||||
/* Now scan the directory tree, increasing nlink according to every dirent found. */
|
|
||||||
--- a/fs/jffs2/scan.c
|
|
||||||
+++ b/fs/jffs2/scan.c
|
|
||||||
@@ -72,7 +72,7 @@ static int file_dirty(struct jffs2_sb_in
|
|
||||||
return ret;
|
|
||||||
if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size)))
|
|
||||||
return ret;
|
|
||||||
- /* Turned wasted size into dirty, since we apparently
|
|
||||||
+ /* Turned wasted size into dirty, since we apparently
|
|
||||||
think it's recoverable now. */
|
|
||||||
jeb->dirty_size += jeb->wasted_size;
|
|
||||||
c->dirty_size += jeb->wasted_size;
|
|
||||||
@@ -144,8 +144,11 @@ int jffs2_scan_medium(struct jffs2_sb_in
|
|
||||||
/* reset summary info for next eraseblock scan */
|
|
||||||
jffs2_sum_reset_collected(s);
|
|
||||||
|
|
||||||
- ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
|
||||||
- buf_size, s);
|
|
||||||
+ if (c->flags & (1 << 7))
|
|
||||||
+ ret = BLK_STATE_ALLFF;
|
|
||||||
+ else
|
|
||||||
+ ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset),
|
|
||||||
+ buf_size, s);
|
|
||||||
|
|
||||||
if (ret < 0)
|
|
||||||
goto out;
|
|
||||||
@@ -400,7 +403,7 @@ static int jffs2_scan_xref_node(struct j
|
|
||||||
if (!ref)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
- /* BEFORE jffs2_build_xattr_subsystem() called,
|
|
||||||
+ /* BEFORE jffs2_build_xattr_subsystem() called,
|
|
||||||
* and AFTER xattr_ref is marked as a dead xref,
|
|
||||||
* ref->xid is used to store 32bit xid, xd is not used
|
|
||||||
* ref->ino is used to store 32bit inode-number, ic is not used
|
|
||||||
@@ -473,7 +476,7 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
struct jffs2_sum_marker *sm;
|
|
||||||
void *sumptr = NULL;
|
|
||||||
uint32_t sumlen;
|
|
||||||
-
|
|
||||||
+
|
|
||||||
if (!buf_size) {
|
|
||||||
/* XIP case. Just look, point at the summary if it's there */
|
|
||||||
sm = (void *)buf + c->sector_size - sizeof(*sm);
|
|
||||||
@@ -489,9 +492,9 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
buf_len = sizeof(*sm);
|
|
||||||
|
|
||||||
/* Read as much as we want into the _end_ of the preallocated buffer */
|
|
||||||
- err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
|
|
||||||
+ err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len,
|
|
||||||
jeb->offset + c->sector_size - buf_len,
|
|
||||||
- buf_len);
|
|
||||||
+ buf_len);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
@@ -510,9 +513,9 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
}
|
|
||||||
if (buf_len < sumlen) {
|
|
||||||
/* Need to read more so that the entire summary node is present */
|
|
||||||
- err = jffs2_fill_scan_buf(c, sumptr,
|
|
||||||
+ err = jffs2_fill_scan_buf(c, sumptr,
|
|
||||||
jeb->offset + c->sector_size - sumlen,
|
|
||||||
- sumlen - buf_len);
|
|
||||||
+ sumlen - buf_len);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
@@ -525,7 +528,7 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
|
|
||||||
if (buf_size && sumlen > buf_size)
|
|
||||||
kfree(sumptr);
|
|
||||||
- /* If it returns with a real error, bail.
|
|
||||||
+ /* If it returns with a real error, bail.
|
|
||||||
If it returns positive, that's a block classification
|
|
||||||
(i.e. BLK_STATE_xxx) so return that too.
|
|
||||||
If it returns zero, fall through to full scan. */
|
|
||||||
@@ -546,6 +549,17 @@ static int jffs2_scan_eraseblock (struct
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ if ((buf[0] == 0xde) &&
|
|
||||||
+ (buf[1] == 0xad) &&
|
|
||||||
+ (buf[2] == 0xc0) &&
|
|
||||||
+ (buf[3] == 0xde)) {
|
|
||||||
+ /* end of filesystem. erase everything after this point */
|
|
||||||
+ printk("%s(): End of filesystem marker found at 0x%x\n", __func__, jeb->offset);
|
|
||||||
+ c->flags |= (1 << 7);
|
|
||||||
+
|
|
||||||
+ return BLK_STATE_ALLFF;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* We temporarily use 'ofs' as a pointer into the buffer/jeb */
|
|
||||||
ofs = 0;
|
|
||||||
|
|
||||||
@@ -671,7 +685,7 @@ scan_more:
|
|
||||||
scan_end = buf_len;
|
|
||||||
goto more_empty;
|
|
||||||
}
|
|
||||||
-
|
|
||||||
+
|
|
||||||
/* See how much more there is to read in this eraseblock... */
|
|
||||||
buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs);
|
|
||||||
if (!buf_len) {
|
|
||||||
@@ -907,7 +921,7 @@ scan_more:
|
|
||||||
|
|
||||||
D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n",
|
|
||||||
jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size));
|
|
||||||
-
|
|
||||||
+
|
|
||||||
/* mark_node_obsolete can add to wasted !! */
|
|
||||||
if (jeb->wasted_size) {
|
|
||||||
jeb->dirty_size += jeb->wasted_size;
|
|
|
@ -1,56 +0,0 @@
|
||||||
--- a/include/linux/skbuff.h
|
|
||||||
+++ b/include/linux/skbuff.h
|
|
||||||
@@ -1270,11 +1270,18 @@ static inline int skb_network_offset(con
|
|
||||||
*
|
|
||||||
* Various parts of the networking layer expect at least 16 bytes of
|
|
||||||
* headroom, you should not reduce this.
|
|
||||||
+ *
|
|
||||||
+ * This has been changed to 64 to acommodate for routing between ethernet
|
|
||||||
+ * and wireless, but only for new allocations
|
|
||||||
*/
|
|
||||||
#ifndef NET_SKB_PAD
|
|
||||||
#define NET_SKB_PAD 16
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#ifndef NET_SKB_PAD_ALLOC
|
|
||||||
+#define NET_SKB_PAD_ALLOC 64
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
|
|
||||||
|
|
||||||
static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
|
|
||||||
@@ -1364,9 +1371,9 @@ static inline void __skb_queue_purge(str
|
|
||||||
static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
|
|
||||||
gfp_t gfp_mask)
|
|
||||||
{
|
|
||||||
- struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD, gfp_mask);
|
|
||||||
+ struct sk_buff *skb = alloc_skb(length + NET_SKB_PAD_ALLOC, gfp_mask);
|
|
||||||
if (likely(skb))
|
|
||||||
- skb_reserve(skb, NET_SKB_PAD);
|
|
||||||
+ skb_reserve(skb, NET_SKB_PAD_ALLOC);
|
|
||||||
return skb;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1439,7 +1446,7 @@ static inline int __skb_cow(struct sk_bu
|
|
||||||
delta = headroom - skb_headroom(skb);
|
|
||||||
|
|
||||||
if (delta || cloned)
|
|
||||||
- return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0,
|
|
||||||
+ return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD_ALLOC), 0,
|
|
||||||
GFP_ATOMIC);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
--- a/net/core/skbuff.c
|
|
||||||
+++ b/net/core/skbuff.c
|
|
||||||
@@ -320,9 +320,9 @@ struct sk_buff *__netdev_alloc_skb(struc
|
|
||||||
int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1;
|
|
||||||
struct sk_buff *skb;
|
|
||||||
|
|
||||||
- skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask, 0, node);
|
|
||||||
+ skb = __alloc_skb(length + NET_SKB_PAD_ALLOC, gfp_mask, 0, node);
|
|
||||||
if (likely(skb)) {
|
|
||||||
- skb_reserve(skb, NET_SKB_PAD);
|
|
||||||
+ skb_reserve(skb, NET_SKB_PAD_ALLOC);
|
|
||||||
skb->dev = dev;
|
|
||||||
}
|
|
||||||
return skb;
|
|
|
@ -1,9 +0,0 @@
|
||||||
--- /dev/null
|
|
||||||
+++ b/include/asm-powerpc/segment.h
|
|
||||||
@@ -0,0 +1,6 @@
|
|
||||||
+#ifndef _ASM_SEGMENT_H
|
|
||||||
+#define _ASM_SEGMENT_H
|
|
||||||
+
|
|
||||||
+/* Only here because we have some old header files that expect it.. */
|
|
||||||
+
|
|
||||||
+#endif /* _ASM_SEGMENT_H */
|
|
|
@ -1,42 +0,0 @@
|
||||||
--- a/drivers/net/r8169.c
|
|
||||||
+++ b/drivers/net/r8169.c
|
|
||||||
@@ -1862,7 +1862,7 @@ static const struct rtl_cfg_info {
|
|
||||||
.hw_start = rtl_hw_start_8169,
|
|
||||||
.region = 1,
|
|
||||||
.align = 0,
|
|
||||||
- .intr_event = SYSErr | LinkChg | RxOverflow |
|
|
||||||
+ .intr_event = LinkChg | RxOverflow |
|
|
||||||
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
|
||||||
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
|
|
||||||
.features = RTL_FEATURE_GMII
|
|
||||||
@@ -1871,7 +1871,7 @@ static const struct rtl_cfg_info {
|
|
||||||
.hw_start = rtl_hw_start_8168,
|
|
||||||
.region = 2,
|
|
||||||
.align = 8,
|
|
||||||
- .intr_event = SYSErr | LinkChg | RxOverflow |
|
|
||||||
+ .intr_event = LinkChg | RxOverflow |
|
|
||||||
TxErr | TxOK | RxOK | RxErr,
|
|
||||||
.napi_event = TxErr | TxOK | RxOK | RxOverflow,
|
|
||||||
.features = RTL_FEATURE_GMII | RTL_FEATURE_MSI
|
|
||||||
@@ -1880,7 +1880,7 @@ static const struct rtl_cfg_info {
|
|
||||||
.hw_start = rtl_hw_start_8101,
|
|
||||||
.region = 2,
|
|
||||||
.align = 8,
|
|
||||||
- .intr_event = SYSErr | LinkChg | RxOverflow | PCSTimeout |
|
|
||||||
+ .intr_event = LinkChg | RxOverflow | PCSTimeout |
|
|
||||||
RxFIFOOver | TxErr | TxOK | RxOK | RxErr,
|
|
||||||
.napi_event = RxFIFOOver | TxErr | TxOK | RxOK | RxOverflow,
|
|
||||||
.features = RTL_FEATURE_MSI
|
|
||||||
@@ -3555,10 +3555,12 @@ static irqreturn_t rtl8169_interrupt(int
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
+#if 0
|
|
||||||
if (unlikely(status & SYSErr)) {
|
|
||||||
rtl8169_pcierr_interrupt(dev);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
if (status & LinkChg)
|
|
||||||
rtl8169_check_link_status(dev, tp, ioaddr);
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,143 +0,0 @@
|
||||||
--- a/fs/mini_fo/main.c
|
|
||||||
+++ b/fs/mini_fo/main.c
|
|
||||||
@@ -79,6 +79,7 @@ mini_fo_tri_interpose(dentry_t *hidden_d
|
|
||||||
* of the new inode's fields
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
|
|
||||||
/*
|
|
||||||
* original: inode = iget(sb, hidden_inode->i_ino);
|
|
||||||
*/
|
|
||||||
@@ -87,6 +88,13 @@ mini_fo_tri_interpose(dentry_t *hidden_d
|
|
||||||
err = -EACCES; /* should be impossible??? */
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
+#else
|
|
||||||
+ inode = mini_fo_iget(sb, iunique(sb, 25));
|
|
||||||
+ if (IS_ERR(inode)) {
|
|
||||||
+ err = PTR_ERR(inode);
|
|
||||||
+ goto out;
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* interpose the inode if not already interposed
|
|
||||||
@@ -184,9 +192,9 @@ mini_fo_parse_options(super_block_t *sb,
|
|
||||||
hidden_root = ERR_PTR(err);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
- hidden_root = nd.dentry;
|
|
||||||
- stopd(sb)->base_dir_dentry = nd.dentry;
|
|
||||||
- stopd(sb)->hidden_mnt = nd.mnt;
|
|
||||||
+ hidden_root = nd_get_dentry(&nd);
|
|
||||||
+ stopd(sb)->base_dir_dentry = nd_get_dentry(&nd);
|
|
||||||
+ stopd(sb)->hidden_mnt = nd_get_mnt(&nd);
|
|
||||||
|
|
||||||
} else if(!strncmp("sto=", options, 4)) {
|
|
||||||
/* parse the storage dir */
|
|
||||||
@@ -204,9 +212,9 @@ mini_fo_parse_options(super_block_t *sb,
|
|
||||||
hidden_root2 = ERR_PTR(err);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
- hidden_root2 = nd2.dentry;
|
|
||||||
- stopd(sb)->storage_dir_dentry = nd2.dentry;
|
|
||||||
- stopd(sb)->hidden_mnt2 = nd2.mnt;
|
|
||||||
+ hidden_root2 = nd_get_dentry(&nd2);
|
|
||||||
+ stopd(sb)->storage_dir_dentry = nd_get_dentry(&nd2);
|
|
||||||
+ stopd(sb)->hidden_mnt2 = nd_get_mnt(&nd2);
|
|
||||||
stohs2(sb) = hidden_root2->d_sb;
|
|
||||||
|
|
||||||
/* validate storage dir, this is done in
|
|
||||||
--- a/fs/mini_fo/mini_fo.h
|
|
||||||
+++ b/fs/mini_fo/mini_fo.h
|
|
||||||
@@ -302,6 +302,10 @@ extern int mini_fo_tri_interpose(dentry_
|
|
||||||
extern int mini_fo_cp_cont(dentry_t *tgt_dentry, struct vfsmount *tgt_mnt,
|
|
||||||
dentry_t *src_dentry, struct vfsmount *src_mnt);
|
|
||||||
|
|
||||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
|
||||||
+extern struct inode *mini_fo_iget(struct super_block *sb, unsigned long ino);
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
|
|
||||||
extern int mini_fo_create(inode_t *dir, dentry_t *dentry, int mode, struct nameidata *nd);
|
|
||||||
|
|
||||||
@@ -501,6 +505,29 @@ static inline void double_unlock(struct
|
|
||||||
#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) */
|
|
||||||
#endif /* __KERNEL__ */
|
|
||||||
|
|
||||||
+
|
|
||||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
|
||||||
+static inline dentry_t *nd_get_dentry(struct nameidata *nd)
|
|
||||||
+{
|
|
||||||
+ return (nd->path.dentry);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline struct vfsmount *nd_get_mnt(struct nameidata *nd)
|
|
||||||
+{
|
|
||||||
+ return (nd->path.mnt);
|
|
||||||
+}
|
|
||||||
+#else
|
|
||||||
+static inline dentry_t *nd_get_dentry(struct nameidata *nd)
|
|
||||||
+{
|
|
||||||
+ return (nd->dentry);
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static inline struct vfsmount *nd_get_mnt(struct nameidata *nd)
|
|
||||||
+{
|
|
||||||
+ return (nd->mnt);
|
|
||||||
+}
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Definitions for user and kernel code
|
|
||||||
*/
|
|
||||||
--- a/fs/mini_fo/super.c
|
|
||||||
+++ b/fs/mini_fo/super.c
|
|
||||||
@@ -262,10 +262,31 @@ mini_fo_umount_begin(super_block_t *sb)
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25)
|
|
||||||
+struct inode *
|
|
||||||
+mini_fo_iget(struct super_block *sb, unsigned long ino)
|
|
||||||
+{
|
|
||||||
+ struct inode *inode;
|
|
||||||
+
|
|
||||||
+ inode = iget_locked(sb, ino);
|
|
||||||
+ if (!inode)
|
|
||||||
+ return ERR_PTR(-ENOMEM);
|
|
||||||
+
|
|
||||||
+ if (!(inode->i_state & I_NEW))
|
|
||||||
+ return inode;
|
|
||||||
+
|
|
||||||
+ mini_fo_read_inode(inode);
|
|
||||||
+
|
|
||||||
+ unlock_new_inode(inode);
|
|
||||||
+ return inode;
|
|
||||||
+}
|
|
||||||
+#endif /* if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) */
|
|
||||||
|
|
||||||
struct super_operations mini_fo_sops =
|
|
||||||
{
|
|
||||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
|
|
||||||
read_inode: mini_fo_read_inode,
|
|
||||||
+#endif
|
|
||||||
#if defined(FIST_DEBUG) || defined(FIST_FILTER_SCA)
|
|
||||||
write_inode: mini_fo_write_inode,
|
|
||||||
#endif /* defined(FIST_DEBUG) || defined(FIST_FILTER_SCA) */
|
|
||||||
--- a/fs/mini_fo/aux.c
|
|
||||||
+++ b/fs/mini_fo/aux.c
|
|
||||||
@@ -164,11 +164,11 @@ dentry_t *bpath_walk(super_block_t *sb,
|
|
||||||
err = vfs_path_lookup(mnt->mnt_root, mnt, bpath+1, 0, &nd);
|
|
||||||
|
|
||||||
/* validate */
|
|
||||||
- if (err || !nd.dentry || !nd.dentry->d_inode) {
|
|
||||||
+ if (err || !nd_get_dentry(&nd) || !nd_get_dentry(&nd)->d_inode) {
|
|
||||||
printk(KERN_CRIT "mini_fo: bpath_walk: path_walk failed.\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
- return nd.dentry;
|
|
||||||
+ return nd_get_dentry(&nd);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue