diff options
Diffstat (limited to 'drivers/char')
25 files changed, 752 insertions, 438 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index a043107da2af..3ec0766ed5e9 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -328,7 +328,8 @@ config JS_RTC config GEN_RTC tristate "Generic /dev/rtc emulation" - depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN && !UML + depends on RTC!=y + depends on ALPHA || M68K || MN10300 || PARISC || PPC || X86 ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you diff --git a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c index 09f17eb73486..0f64d149c98d 100644 --- a/drivers/char/agp/frontend.c +++ b/drivers/char/agp/frontend.c @@ -156,7 +156,7 @@ static pgprot_t agp_convert_mmap_flags(int prot) { unsigned long prot_bits; - prot_bits = calc_vm_prot_bits(prot) | VM_SHARED; + prot_bits = calc_vm_prot_bits(prot, 0) | VM_SHARED; return vm_get_page_prot(prot_bits); } diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index 05755441250c..fdced547ad59 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -10,7 +10,6 @@ #include <linux/delay.h> #include <linux/vmalloc.h> #include <asm/uninorth.h> -#include <asm/pci-bridge.h> #include <asm/prom.h> #include <asm/pmac_feature.h> #include "agp.h" diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index ff00331bff49..67ee8b08ab53 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -77,7 +77,7 @@ config HW_RANDOM_ATMEL config HW_RANDOM_BCM63XX tristate "Broadcom BCM63xx Random Number Generator support" - depends on BCM63XX + depends on BCM63XX || BMIPS_GENERIC default HW_RANDOM ---help--- This driver provides kernel-side support for the Random Number @@ -382,6 +382,19 @@ config HW_RANDOM_STM32 If unsure, say N. +config HW_RANDOM_PIC32 + tristate "Microchip PIC32 Random Number Generator support" + depends on HW_RANDOM && MACH_PIC32 + default y + ---help--- + This driver provides kernel-side support for the Random Number + Generator hardware found on a PIC32. + + To compile this driver as a module, choose M here. the + module will be called pic32-rng. + + If unsure, say Y. + endif # HW_RANDOM config UML_RANDOM diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 5ad397635128..f5a6fa7690e7 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -33,3 +33,4 @@ obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o +obj-$(CONFIG_HW_RANDOM_PIC32) += pic32-rng.o diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c index 4b31f1387f37..ca9c40309757 100644 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ b/drivers/char/hw_random/bcm63xx-rng.c @@ -79,10 +79,8 @@ static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) static int bcm63xx_rng_probe(struct platform_device *pdev) { struct resource *r; - struct clk *clk; int ret; struct bcm63xx_rng_priv *priv; - struct hwrng *rng; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -132,10 +130,19 @@ static int bcm63xx_rng_probe(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id bcm63xx_rng_of_match[] = { + { .compatible = "brcm,bcm6368-rng", }, + {}, +}; +MODULE_DEVICE_TABLE(of, bcm63xx_rng_of_match); +#endif + static struct platform_driver bcm63xx_rng_driver = { .probe = bcm63xx_rng_probe, .driver = { .name = "bcm63xx-rng", + .of_match_table = of_match_ptr(bcm63xx_rng_of_match), }, }; diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c index 30cf4623184f..ada081232528 100644 --- a/drivers/char/hw_random/exynos-rng.c +++ b/drivers/char/hw_random/exynos-rng.c @@ -144,8 +144,7 @@ static int exynos_rng_probe(struct platform_device *pdev) return devm_hwrng_register(&pdev->dev, &exynos_rng->rng); } -#ifdef CONFIG_PM -static int exynos_rng_runtime_suspend(struct device *dev) +static int __maybe_unused exynos_rng_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); @@ -155,7 +154,7 @@ static int exynos_rng_runtime_suspend(struct device *dev) return 0; } -static int exynos_rng_runtime_resume(struct device *dev) +static int __maybe_unused exynos_rng_runtime_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); @@ -163,12 +162,12 @@ static int exynos_rng_runtime_resume(struct device *dev) return clk_prepare_enable(exynos_rng->clk); } -static int exynos_rng_suspend(struct device *dev) +static int __maybe_unused exynos_rng_suspend(struct device *dev) { return pm_runtime_force_suspend(dev); } -static int exynos_rng_resume(struct device *dev) +static int __maybe_unused exynos_rng_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); @@ -180,7 +179,6 @@ static int exynos_rng_resume(struct device *dev) return exynos_rng_configure(exynos_rng); } -#endif static const struct dev_pm_ops exynos_rng_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(exynos_rng_suspend, exynos_rng_resume) diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 843d6f6aee7a..3b06c1d6cfb2 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c @@ -743,6 +743,16 @@ static const struct of_device_id n2rng_match[] = { .compatible = "SUNW,kt-rng", .data = (void *) 1, }, + { + .name = "random-number-generator", + .compatible = "ORCL,m4-rng", + .data = (void *) 1, + }, + { + .name = "random-number-generator", + .compatible = "ORCL,m7-rng", + .data = (void *) 1, + }, {}, }; MODULE_DEVICE_TABLE(of, n2rng_match); diff --git a/drivers/char/hw_random/pic32-rng.c b/drivers/char/hw_random/pic32-rng.c new file mode 100644 index 000000000000..108897bea2d0 --- /dev/null +++ b/drivers/char/hw_random/pic32-rng.c @@ -0,0 +1,155 @@ +/* + * PIC32 RNG driver + * + * Joshua Henderson <joshua.henderson@microchip.com> + * Copyright (C) 2016 Microchip Technology Inc. All rights reserved. + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/err.h> +#include <linux/hw_random.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#define RNGCON 0x04 +#define TRNGEN BIT(8) +#define PRNGEN BIT(9) +#define PRNGCONT BIT(10) +#define TRNGMOD BIT(11) +#define SEEDLOAD BIT(12) +#define RNGPOLY1 0x08 +#define RNGPOLY2 0x0C +#define RNGNUMGEN1 0x10 +#define RNGNUMGEN2 0x14 +#define RNGSEED1 0x18 +#define RNGSEED2 0x1C +#define RNGRCNT 0x20 +#define RCNT_MASK 0x7F + +struct pic32_rng { + void __iomem *base; + struct hwrng rng; + struct clk *clk; +}; + +/* + * The TRNG can generate up to 24Mbps. This is a timeout that should be safe + * enough given the instructions in the loop and that the TRNG may not always + * be at maximum rate. + */ +#define RNG_TIMEOUT 500 + +static int pic32_rng_read(struct hwrng *rng, void *buf, size_t max, + bool wait) +{ + struct pic32_rng *priv = container_of(rng, struct pic32_rng, rng); + u64 *data = buf; + u32 t; + unsigned int timeout = RNG_TIMEOUT; + + if (max < 8) + return 0; + + do { + t = readl(priv->base + RNGRCNT) & RCNT_MASK; + if (t == 64) { + /* TRNG value comes through the seed registers */ + *data = ((u64)readl(priv->base + RNGSEED2) << 32) + + readl(priv->base + RNGSEED1); + return 8; + } + } while (wait && --timeout); + + return -EIO; +} + +static int pic32_rng_probe(struct platform_device *pdev) +{ + struct pic32_rng *priv; + struct resource *res; + u32 v; + int ret; + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + priv->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->clk)) + return PTR_ERR(priv->clk); + + ret = clk_prepare_enable(priv->clk); + if (ret) + return ret; + + /* enable TRNG in enhanced mode */ + v = TRNGEN | TRNGMOD; + writel(v, priv->base + RNGCON); + + priv->rng.name = pdev->name; + priv->rng.read = pic32_rng_read; + + ret = hwrng_register(&priv->rng); + if (ret) + goto err_register; + + platform_set_drvdata(pdev, priv); + + return 0; + +err_register: + clk_disable_unprepare(priv->clk); + return ret; +} + +static int pic32_rng_remove(struct platform_device *pdev) +{ + struct pic32_rng *rng = platform_get_drvdata(pdev); + + hwrng_unregister(&rng->rng); + writel(0, rng->base + RNGCON); + clk_disable_unprepare(rng->clk); + return 0; +} + +static const struct of_device_id pic32_rng_of_match[] = { + { .compatible = "microchip,pic32mzda-rng", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, pic32_rng_of_match); + +static struct platform_driver pic32_rng_driver = { + .probe = pic32_rng_probe, + .remove = pic32_rng_remove, + .driver = { + .name = "pic32-rng", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pic32_rng_of_match), + }, +}; + +module_platform_driver(pic32_rng_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Joshua Henderson <joshua.henderson@microchip.com>"); +MODULE_DESCRIPTION("Microchip PIC32 RNG Driver"); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 7fddd8696211..1e25b5205724 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -849,7 +849,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, smi_inc_stat(smi_info, complete_transactions); handle_transaction_done(smi_info); - si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); + goto restart; } else if (si_sm_result == SI_SM_HOSED) { smi_inc_stat(smi_info, hosed_count); @@ -866,7 +866,7 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, */ return_hosed_msg(smi_info, IPMI_ERR_UNSPECIFIED); } - si_sm_result = smi_info->handlers->event(smi_info->si_sm, 0); + goto restart; } /* @@ -1363,12 +1363,12 @@ MODULE_PARM_DESC(trydmi, "Setting this to zero will disable the" " default scan of the interfaces identified via DMI"); #endif module_param_named(tryplatform, si_tryplatform, bool, 0); -MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" +MODULE_PARM_DESC(tryplatform, "Setting this to zero will disable the" " default scan of the interfaces identified via platform" " interfaces like openfirmware"); #ifdef CONFIG_PCI module_param_named(trypci, si_trypci, bool, 0); -MODULE_PARM_DESC(tryacpi, "Setting this to zero will disable the" +MODULE_PARM_DESC(trypci, "Setting this to zero will disable the" " default scan of the interfaces identified via pci"); #endif module_param_named(trydefaults, si_trydefaults, bool, 0); @@ -2690,6 +2690,9 @@ static int acpi_ipmi_probe(struct platform_device *dev) unsigned long long tmp; int rv = -EINVAL; + if (!si_tryacpi) + return 0; + handle = ACPI_HANDLE(&dev->dev); if (!handle) return -ENODEV; diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c index 5f1c3d08ba65..8b3be8b92573 100644 --- a/drivers/char/ipmi/ipmi_ssif.c +++ b/drivers/char/ipmi/ipmi_ssif.c @@ -920,23 +920,18 @@ static void msg_written_handler(struct ssif_info *ssif_info, int result, msg_done_handler(ssif_info, -EIO, NULL, 0); } } else { + /* Ready to request the result. */ unsigned long oflags, *flags; - bool got_alert; ssif_inc_stat(ssif_info, sent_messages); ssif_inc_stat(ssif_info, sent_messages_parts); flags = ipmi_ssif_lock_cond(ssif_info, &oflags); - got_alert = ssif_info->got_alert; - if (got_alert) { + if (ssif_info->got_alert) { + /* The result is already ready, just start it. */ ssif_info->got_alert = false; - ssif_info->waiting_alert = false; - } - - if (got_alert) { ipmi_ssif_unlock_cond(ssif_info, flags); - /* The alert already happened, try now. */ - retry_timeout((unsigned long) ssif_info); + start_get(ssif_info); } else { /* Wait a jiffie then request the next message */ ssif_info->waiting_alert = true; diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 4f6f94c43412..71025c2f6bbb 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -695,7 +695,7 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) offset += file->f_pos; case SEEK_SET: /* to avoid userland mistaking f_pos=-9 as -EBADF=-9 */ - if (IS_ERR_VALUE((unsigned long long)offset)) { + if ((unsigned long long)offset >= -MAX_ERRNO) { ret = -EOVERFLOW; break; } diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 01292328a456..678fa97e41fb 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -496,12 +496,12 @@ static void pc_set_checksum(void) #ifdef CONFIG_PROC_FS -static char *floppy_types[] = { +static const char * const floppy_types[] = { "none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M", "3.5'' 2.88M", "3.5'' 2.88M" }; -static char *gfx_types[] = { +static const char * const gfx_types[] = { "EGA, VGA, ... (with BIOS)", "CGA (40 cols)", "CGA (80 cols)", @@ -602,7 +602,7 @@ static void atari_set_checksum(void) static struct { unsigned char val; - char *name; + const char *name; } boot_prefs[] = { { 0x80, "TOS" }, { 0x40, "ASV" }, @@ -611,7 +611,7 @@ static struct { { 0x00, "unspecified" } }; -static char *languages[] = { +static const char * const languages[] = { "English (US)", "German", "French", @@ -623,7 +623,7 @@ static char *languages[] = { "Swiss (German)" }; -static char *dateformat[] = { +static const char * const dateformat[] = { "MM%cDD%cYY", "DD%cMM%cYY", "YY%cMM%cDD", @@ -634,7 +634,7 @@ static char *dateformat[] = { "7 (undefined)" }; -static char *colors[] = { +static const char * const colors[] = { "2", "4", "16", "256", "65536", "??", "??", "??" }; diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 76c490fa0511..0e184426db98 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -129,10 +129,9 @@ static void button_consume_callbacks (int bpcount) static void button_sequence_finished (unsigned long parameters) { -#ifdef CONFIG_NWBUTTON_REBOOT /* Reboot using button is enabled */ - if (button_press_count == reboot_count) + if (IS_ENABLED(CONFIG_NWBUTTON_REBOOT) && + button_press_count == reboot_count) kill_cad_pid(SIGINT, 1); /* Ask init to reboot us */ -#endif /* CONFIG_NWBUTTON_REBOOT */ button_consume_callbacks (button_press_count); bcount = sprintf (button_output_buffer, "%d\n", button_press_count); button_press_count = 0; /* Reset the button press counter */ diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 45df4bf914f8..22c27652e46a 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -1349,7 +1349,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) /* TODO:disable interrupts instead of reset to preserve signal states */ reset_device(info); - if (!tty || tty->termios.c_cflag & HUPCL) { + if (!tty || C_HUPCL(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); set_signals(info); } @@ -1390,7 +1390,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); get_signals(info); - if (info->netcount || (tty && (tty->termios.c_cflag & CREAD))) + if (info->netcount || (tty && C_CREAD(tty))) rx_start(info); spin_unlock_irqrestore(&info->lock, flags); @@ -1733,7 +1733,7 @@ static void mgslpc_throttle(struct tty_struct * tty) if (I_IXOFF(tty)) mgslpc_send_xchar(tty, STOP_CHAR(tty)); - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals &= ~SerialSignal_RTS; set_signals(info); @@ -1762,7 +1762,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty) mgslpc_send_xchar(tty, START_CHAR(tty)); } - if (tty->termios.c_cflag & CRTSCTS) { + if (C_CRTSCTS(tty)) { spin_lock_irqsave(&info->lock, flags); info->serial_signals |= SerialSignal_RTS; set_signals(info); @@ -2306,8 +2306,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term mgslpc_change_params(info, tty); /* Handle transition to B0 status */ - if (old_termios->c_cflag & CBAUD && - !(tty->termios.c_cflag & CBAUD)) { + if ((old_termios->c_cflag & CBAUD) && !C_BAUD(tty)) { info->serial_signals &= ~(SerialSignal_RTS | SerialSignal_DTR); spin_lock_irqsave(&info->lock, flags); set_signals(info); @@ -2315,21 +2314,17 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term } /* Handle transition away from B0 status */ - if (!(old_termios->c_cflag & CBAUD) && - tty->termios.c_cflag & CBAUD) { + if (!(old_termios->c_cflag & CBAUD) && C_BAUD(tty)) { info->serial_signals |= SerialSignal_DTR; - if (!(tty->termios.c_cflag & CRTSCTS) || - !test_bit(TTY_THROTTLED, &tty->flags)) { + if (!C_CRTSCTS(tty) || !test_bit(TTY_THROTTLED, &tty->flags)) info->serial_signals |= SerialSignal_RTS; - } spin_lock_irqsave(&info->lock, flags); set_signals(info); spin_unlock_irqrestore(&info->lock, flags); } /* Handle turning off CRTSCTS */ - if (old_termios->c_cflag & CRTSCTS && - !(tty->termios.c_cflag & CRTSCTS)) { + if (old_termios->c_cflag & CRTSCTS && !C_CRTSCTS(tty)) { tty->hw_stopped = 0; tx_release(tty); } diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index ae0b42b66e55..d23368874710 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -69,12 +69,13 @@ #include <linux/ppdev.h> #include <linux/mutex.h> #include <linux/uaccess.h> +#include <linux/compat.h> #define PP_VERSION "ppdev: user-space parallel port driver" #define CHRDEV "ppdev" struct pp_struct { - struct pardevice * pdev; + struct pardevice *pdev; wait_queue_head_t irq_wait; atomic_t irqc; unsigned int flags; @@ -98,18 +99,26 @@ struct pp_struct { #define ROUND_UP(x,y) (((x)+(y)-1)/(y)) static DEFINE_MUTEX(pp_do_mutex); -static inline void pp_enable_irq (struct pp_struct *pp) + +/* define fixed sized ioctl cmd for y2038 migration */ +#define PPGETTIME32 _IOR(PP_IOCTL, 0x95, s32[2]) +#define PPSETTIME32 _IOW(PP_IOCTL, 0x96, s32[2]) +#define PPGETTIME64 _IOR(PP_IOCTL, 0x95, s64[2]) +#define PPSETTIME64 _IOW(PP_IOCTL, 0x96, s64[2]) + +static inline void pp_enable_irq(struct pp_struct *pp) { struct parport *port = pp->pdev->port; - port->ops->enable_irq (port); + + port->ops->enable_irq(port); } -static ssize_t pp_read (struct file * file, char __user * buf, size_t count, - loff_t * ppos) +static ssize_t pp_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; - char * kbuffer; + char *kbuffer; ssize_t bytes_read = 0; struct parport *pport; int mode; @@ -125,16 +134,15 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, return 0; kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL); - if (!kbuffer) { + if (!kbuffer) return -ENOMEM; - } pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - parport_set_timeout (pp->pdev, - (file->f_flags & O_NONBLOCK) ? - PARPORT_INACTIVITY_O_NONBLOCK : - pp->default_inactivity); + parport_set_timeout(pp->pdev, + (file->f_flags & O_NONBLOCK) ? + PARPORT_INACTIVITY_O_NONBLOCK : + pp->default_inactivity); while (bytes_read == 0) { ssize_t need = min_t(unsigned long, count, PP_BUFFER_SIZE); @@ -144,20 +152,17 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, int flags = 0; size_t (*fn)(struct parport *, void *, size_t, int); - if (pp->flags & PP_W91284PIC) { + if (pp->flags & PP_W91284PIC) flags |= PARPORT_W91284PIC; - } - if (pp->flags & PP_FASTREAD) { + if (pp->flags & PP_FASTREAD) flags |= PARPORT_EPP_FAST; - } - if (pport->ieee1284.mode & IEEE1284_ADDR) { + if (pport->ieee1284.mode & IEEE1284_ADDR) fn = pport->ops->epp_read_addr; - } else { + else fn = pport->ops->epp_read_data; - } bytes_read = (*fn)(pport, kbuffer, need, flags); } else { - bytes_read = parport_read (pport, kbuffer, need); + bytes_read = parport_read(pport, kbuffer, need); } if (bytes_read != 0) @@ -168,7 +173,7 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, break; } - if (signal_pending (current)) { + if (signal_pending(current)) { bytes_read = -ERESTARTSYS; break; } @@ -176,22 +181,22 @@ static ssize_t pp_read (struct file * file, char __user * buf, size_t count, cond_resched(); } - parport_set_timeout (pp->pdev, pp->default_inactivity); + parport_set_timeout(pp->pdev, pp->default_inactivity); - if (bytes_read > 0 && copy_to_user (buf, kbuffer, bytes_read)) + if (bytes_read > 0 && copy_to_user(buf, kbuffer, bytes_read)) bytes_read = -EFAULT; - kfree (kbuffer); - pp_enable_irq (pp); + kfree(kbuffer); + pp_enable_irq(pp); return bytes_read; } -static ssize_t pp_write (struct file * file, const char __user * buf, - size_t count, loff_t * ppos) +static ssize_t pp_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; - char * kbuffer; + char *kbuffer; ssize_t bytes_written = 0; ssize_t wrote; int mode; @@ -204,21 +209,21 @@ static ssize_t pp_write (struct file * file, const char __user * buf, } kbuffer = kmalloc(min_t(size_t, count, PP_BUFFER_SIZE), GFP_KERNEL); - if (!kbuffer) { + if (!kbuffer) return -ENOMEM; - } + pport = pp->pdev->port; mode = pport->ieee1284.mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR); - parport_set_timeout (pp->pdev, - (file->f_flags & O_NONBLOCK) ? - PARPORT_INACTIVITY_O_NONBLOCK : - pp->default_inactivity); + parport_set_timeout(pp->pdev, + (file->f_flags & O_NONBLOCK) ? + PARPORT_INACTIVITY_O_NONBLOCK : + pp->default_inactivity); while (bytes_written < count) { ssize_t n = min_t(unsigned long, count - bytes_written, PP_BUFFER_SIZE); - if (copy_from_user (kbuffer, buf + bytes_written, n)) { + if (copy_from_user(kbuffer, buf + bytes_written, n)) { bytes_written = -EFAULT; break; } @@ -226,20 +231,19 @@ static ssize_t pp_write (struct file * file, const char __user * buf, if ((pp->flags & PP_FASTWRITE) && (mode == IEEE1284_MODE_EPP)) { /* do a fast EPP write */ if (pport->ieee1284.mode & IEEE1284_ADDR) { - wrote = pport->ops->epp_write_addr (pport, + wrote = pport->ops->epp_write_addr(pport, kbuffer, n, PARPORT_EPP_FAST); } else { - wrote = pport->ops->epp_write_data (pport, + wrote = pport->ops->epp_write_data(pport, kbuffer, n, PARPORT_EPP_FAST); } } else { - wrote = parport_write (pp->pdev->port, kbuffer, n); + wrote = parport_write(pp->pdev->port, kbuffer, n); } if (wrote <= 0) { - if (!bytes_written) { + if (!bytes_written) bytes_written = wrote; - } break; } @@ -251,67 +255,69 @@ static ssize_t pp_write (struct file * file, const char __user * buf, break; } - if (signal_pending (current)) + if (signal_pending(current)) break; cond_resched(); } - parport_set_timeout (pp->pdev, pp->default_inactivity); + parport_set_timeout(pp->pdev, pp->default_inactivity); - kfree (kbuffer); - pp_enable_irq (pp); + kfree(kbuffer); + pp_enable_irq(pp); return bytes_written; } -static void pp_irq (void *private) +static void pp_irq(void *private) { struct pp_struct *pp = private; if (pp->irqresponse) { - parport_write_control (pp->pdev->port, pp->irqctl); + parport_write_control(pp->pdev->port, pp->irqctl); pp->irqresponse = 0; } - atomic_inc (&pp->irqc); - wake_up_interruptible (&pp->irq_wait); + atomic_inc(&pp->irqc); + wake_up_interruptible(&pp->irq_wait); } -static int register_device (int minor, struct pp_struct *pp) +static int register_device(int minor, struct pp_struct *pp) { struct parport *port; - struct pardevice * pdev = NULL; + struct pardevice *pdev = NULL; char *name; - int fl; + struct pardev_cb ppdev_cb; name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor); if (name == NULL) return -ENOMEM; - port = parport_find_number (minor); + port = parport_find_number(minor); if (!port) { - printk (KERN_WARNING "%s: no associated port!\n", name); - kfree (name); + printk(KERN_WARNING "%s: no associated port!\n", name); + kfree(name); return -ENXIO; } - fl = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; - pdev = parport_register_device (port, name, NULL, - NULL, pp_irq, fl, pp); - parport_put_port (port); + memset(&ppdev_cb, 0, sizeof(ppdev_cb)); + ppdev_cb.irq_func = pp_irq; + ppdev_cb.flags = (pp->flags & PP_EXCL) ? PARPORT_FLAG_EXCL : 0; + ppdev_cb.private = pp; + pdev = parport_register_dev_model(port, name, &ppdev_cb, minor); + parport_put_port(port); if (!pdev) { - printk (KERN_WARNING "%s: failed to register device!\n", name); - kfree (name); + printk(KERN_WARNING "%s: failed to register device!\n", name); + kfree(name); return -ENXIO; } pp->pdev = pdev; - pr_debug("%s: registered pardevice\n", name); + dev_dbg(&pdev->dev, "registered pardevice\n"); return 0; } -static enum ieee1284_phase init_phase (int mode) +static enum ieee1284_phase init_phase(int mode) { switch (mode & ~(IEEE1284_DEVICEID | IEEE1284_ADDR)) { @@ -322,11 +328,27 @@ static enum ieee1284_phase init_phase (int mode) return IEEE1284_PH_FWD_IDLE; } +static int pp_set_timeout(struct pardevice *pdev, long tv_sec, int tv_usec) +{ + long to_jiffies; + + if ((tv_sec < 0) || (tv_usec < 0)) + return -EINVAL; + + to_jiffies = usecs_to_jiffies(tv_usec); + to_jiffies += tv_sec * HZ; + if (to_jiffies <= 0) + return -EINVAL; + + pdev->timeout = to_jiffies; + return 0; +} + static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned int minor = iminor(file_inode(file)); struct pp_struct *pp = file->private_data; - struct parport * port; + struct parport *port; void __user *argp = (void __user *)arg; /* First handle the cases that don't take arguments. */ @@ -337,19 +359,19 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int ret; if (pp->flags & PP_CLAIMED) { - pr_debug(CHRDEV "%x: you've already got it!\n", minor); + dev_dbg(&pp->pdev->dev, "you've already got it!\n"); return -EINVAL; } /* Deferred device registration. */ if (!pp->pdev) { - int err = register_device (minor, pp); - if (err) { + int err = register_device(minor, pp); + + if (err) return err; - } } - ret = parport_claim_or_block (pp->pdev); + ret = parport_claim_or_block(pp->pdev); if (ret < 0) return ret; @@ -357,7 +379,7 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) /* For interrupt-reporting to work, we need to be * informed of each interrupt. */ - pp_enable_irq (pp); + pp_enable_irq(pp); /* We may need to fix up the state machine. */ info = &pp->pdev->port->ieee1284; @@ -365,15 +387,15 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pp->saved_state.phase = info->phase; info->mode = pp->state.mode; info->phase = pp->state.phase; - pp->default_inactivity = parport_set_timeout (pp->pdev, 0); - parport_set_timeout (pp->pdev, pp->default_inactivity); + pp->default_inactivity = parport_set_timeout(pp->pdev, 0); + parport_set_timeout(pp->pdev, pp->default_inactivity); return 0; } case PPEXCL: if (pp->pdev) { - pr_debug(CHRDEV "%x: too late for PPEXCL; " - "already registered\n", minor); + dev_dbg(&pp->pdev->dev, + "too late for PPEXCL; already registered\n"); if (pp->flags & PP_EXCL) /* But it's not really an error. */ return 0; @@ -388,11 +410,12 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PPSETMODE: { int mode; - if (copy_from_user (&mode, argp, sizeof (mode))) + + if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; /* FIXME: validate mode */ pp->state.mode = mode; - pp->state.phase = init_phase (mode); + pp->state.phase = init_phase(mode); if (pp->flags & PP_CLAIMED) { pp->pdev->port->ieee1284.mode = mode; @@ -405,28 +428,27 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int mode; - if (pp->flags & PP_CLAIMED) { + if (pp->flags & PP_CLAIMED) mode = pp->pdev->port->ieee1284.mode; - } else { + else mode = pp->state.mode; - } - if (copy_to_user (argp, &mode, sizeof (mode))) { + + if (copy_to_user(argp, &mode, sizeof(mode))) return -EFAULT; - } return 0; } case PPSETPHASE: { int phase; - if (copy_from_user (&phase, argp, sizeof (phase))) { + + if (copy_from_user(&phase, argp, sizeof(phase))) return -EFAULT; - } + /* FIXME: validate phase */ pp->state.phase = phase; - if (pp->flags & PP_CLAIMED) { + if (pp->flags & PP_CLAIMED) pp->pdev->port->ieee1284.phase = phase; - } return 0; } @@ -434,38 +456,34 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int phase; - if (pp->flags & PP_CLAIMED) { + if (pp->flags & PP_CLAIMED) phase = pp->pdev->port->ieee1284.phase; - } else { + else phase = pp->state.phase; - } - if (copy_to_user (argp, &phase, sizeof (phase))) { + if (copy_to_user(argp, &phase, sizeof(phase))) return -EFAULT; - } return 0; } case PPGETMODES: { unsigned int modes; - port = parport_find_number (minor); + port = parport_find_number(minor); if (!port) return -ENODEV; modes = port->modes; parport_put_port(port); - if (copy_to_user (argp, &modes, sizeof (modes))) { + if (copy_to_user(argp, &modes, sizeof(modes))) return -EFAULT; - } return 0; } case PPSETFLAGS: { int uflags; - if (copy_from_user (&uflags, argp, sizeof (uflags))) { + if (copy_from_user(&uflags, argp, sizeof(uflags))) return -EFAULT; - } pp->flags &= ~PP_FLAGMASK; pp->flags |= (uflags & PP_FLAGMASK); return 0; @@ -475,9 +493,8 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int uflags; uflags = pp->flags & PP_FLAGMASK; - if (copy_to_user (argp, &uflags, sizeof (uflags))) { + if (copy_to_user(argp, &uflags, sizeof(uflags))) return -EFAULT; - } return 0; } } /* end switch() */ @@ -495,27 +512,28 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) unsigned char reg; unsigned char mask; int mode; + s32 time32[2]; + s64 time64[2]; + struct timespec64 ts; int ret; - struct timeval par_timeout; - long to_jiffies; case PPRSTATUS: - reg = parport_read_status (port); - if (copy_to_user (argp, ®, sizeof (reg))) + reg = parport_read_status(port); + if (copy_to_user(argp, ®, sizeof(reg))) return -EFAULT; return 0; case PPRDATA: - reg = parport_read_data (port); - if (copy_to_user (argp, ®, sizeof (reg))) + reg = parport_read_data(port); + if (copy_to_user(argp, ®, sizeof(reg))) return -EFAULT; return 0; case PPRCONTROL: - reg = parport_read_control (port); - if (copy_to_user (argp, ®, sizeof (reg))) + reg = parport_read_control(port); + if (copy_to_user(argp, ®, sizeof(reg))) return -EFAULT; return 0; case PPYIELD: - parport_yield_blocking (pp->pdev); + parport_yield_blocking(pp->pdev); return 0; case PPRELEASE: @@ -525,45 +543,45 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) pp->state.phase = info->phase; info->mode = pp->saved_state.mode; info->phase = pp->saved_state.phase; - parport_release (pp->pdev); + parport_release(pp->pdev); pp->flags &= ~PP_CLAIMED; return 0; case PPWCONTROL: - if (copy_from_user (®, argp, sizeof (reg))) + if (copy_from_user(®, argp, sizeof(reg))) return -EFAULT; - parport_write_control (port, reg); + parport_write_control(port, reg); return 0; case PPWDATA: - if (copy_from_user (®, argp, sizeof (reg))) + if (copy_from_user(®, argp, sizeof(reg))) return -EFAULT; - parport_write_data (port, reg); + parport_write_data(port, reg); return 0; case PPFCONTROL: - if (copy_from_user (&mask, argp, - sizeof (mask))) + if (copy_from_user(&mask, argp, + sizeof(mask))) return -EFAULT; - if (copy_from_user (®, 1 + (unsigned char __user *) arg, - sizeof (reg))) + if (copy_from_user(®, 1 + (unsigned char __user *) arg, + sizeof(reg))) return -EFAULT; - parport_frob_control (port, mask, reg); + parport_frob_control(port, mask, reg); return 0; case PPDATADIR: - if (copy_from_user (&mode, argp, sizeof (mode))) + if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; if (mode) - port->ops->data_reverse (port); + port->ops->data_reverse(port); else - port->ops->data_forward (port); + port->ops->data_forward(port); return 0; case PPNEGOT: - if (copy_from_user (&mode, argp, sizeof (mode))) + if (copy_from_user(&mode, argp, sizeof(mode))) return -EFAULT; - switch ((ret = parport_negotiate (port, mode))) { + switch ((ret = parport_negotiate(port, mode))) { case 0: break; case -1: /* handshake failed, peripheral not IEEE 1284 */ ret = -EIO; @@ -572,11 +590,11 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ret = -ENXIO; break; } - pp_enable_irq (pp); + pp_enable_irq(pp); return ret; case PPWCTLONIRQ: - if (copy_from_user (®, argp, sizeof (reg))) + if (copy_from_user(®, argp, sizeof(reg))) return -EFAULT; /* Remember what to set the control lines to, for next @@ -586,39 +604,50 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; case PPCLRIRQ: - ret = atomic_read (&pp->irqc); - if (copy_to_user (argp, &ret, sizeof (ret))) + ret = atomic_read(&pp->irqc); + if (copy_to_user(argp, &ret, sizeof(ret))) return -EFAULT; - atomic_sub (ret, &pp->irqc); + atomic_sub(ret, &pp->irqc); return 0; - case PPSETTIME: - if (copy_from_user (&par_timeout, argp, sizeof(struct timeval))) { + case PPSETTIME32: + if (copy_from_user(time32, argp, sizeof(time32))) return -EFAULT; - } - /* Convert to jiffies, place in pp->pdev->timeout */ - if ((par_timeout.tv_sec < 0) || (par_timeout.tv_usec < 0)) { - return -EINVAL; - } - to_jiffies = ROUND_UP(par_timeout.tv_usec, 1000000/HZ); - to_jiffies += par_timeout.tv_sec * (long)HZ; - if (to_jiffies <= 0) { + + return pp_set_timeout(pp->pdev, time32[0], time32[1]); + + case PPSETTIME64: + if (copy_from_user(time64, argp, sizeof(time64))) + return -EFAULT; + + return pp_set_timeout(pp->pdev, time64[0], time64[1]); + + case PPGETTIME32: + jiffies_to_timespec64(pp->pdev->timeout, &ts); + time32[0] = ts.tv_sec; + time32[1] = ts.tv_nsec / NSEC_PER_USEC; + if ((time32[0] < 0) || (time32[1] < 0)) return -EINVAL; - } - pp->pdev->timeout = to_jiffies; + + if (copy_to_user(argp, time32, sizeof(time32))) + return -EFAULT; + return 0; - case PPGETTIME: - to_jiffies = pp->pdev->timeout; - memset(&par_timeout, 0, sizeof(par_timeout)); - par_timeout.tv_sec = to_jiffies / HZ; - par_timeout.tv_usec = (to_jiffies % (long)HZ) * (1000000/HZ); - if (copy_to_user (argp, &par_timeout, sizeof(struct timeval))) + case PPGETTIME64: + jiffies_to_timespec64(pp->pdev->timeout, &ts); + time64[0] = ts.tv_sec; + time64[1] = ts.tv_nsec / NSEC_PER_USEC; + if ((time64[0] < 0) || (time64[1] < 0)) + return -EINVAL; + + if (copy_to_user(argp, time64, sizeof(time64))) return -EFAULT; + return 0; default: - pr_debug(CHRDEV "%x: What? (cmd=0x%x)\n", minor, cmd); + dev_dbg(&pp->pdev->dev, "What? (cmd=0x%x)\n", cmd); return -EINVAL; } @@ -629,13 +658,22 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { long ret; + mutex_lock(&pp_do_mutex); ret = pp_do_ioctl(file, cmd, arg); mutex_unlock(&pp_do_mutex); return ret; } -static int pp_open (struct inode * inode, struct file * file) +#ifdef CONFIG_COMPAT +static long pp_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return pp_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + +static int pp_open(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); struct pp_struct *pp; @@ -643,16 +681,16 @@ static int pp_open (struct inode * inode, struct file * file) if (minor >= PARPORT_MAX) return -ENXIO; - pp = kmalloc (sizeof (struct pp_struct), GFP_KERNEL); + pp = kmalloc(sizeof(struct pp_struct), GFP_KERNEL); if (!pp) return -ENOMEM; pp->state.mode = IEEE1284_MODE_COMPAT; - pp->state.phase = init_phase (pp->state.mode); + pp->state.phase = init_phase(pp->state.mode); pp->flags = 0; pp->irqresponse = 0; - atomic_set (&pp->irqc, 0); - init_waitqueue_head (&pp->irq_wait); + atomic_set(&pp->irqc, 0); + init_waitqueue_head(&pp->irq_wait); /* Defer the actual device registration until the first claim. * That way, we know whether or not the driver wants to have @@ -664,7 +702,7 @@ static int pp_open (struct inode * inode, struct file * file) return 0; } -static int pp_release (struct inode * inode, struct file * file) +static int pp_release(struct inode *inode, struct file *file) { unsigned int minor = iminor(inode); struct pp_struct *pp = file->private_data; @@ -673,10 +711,10 @@ static int pp_release (struct inode * inode, struct file * file) compat_negot = 0; if (!(pp->flags & PP_CLAIMED) && pp->pdev && (pp->state.mode != IEEE1284_MODE_COMPAT)) { - struct ieee1284_info *info; + struct ieee1284_info *info; /* parport released, but not in compatibility mode */ - parport_claim_or_block (pp->pdev); + parport_claim_or_block(pp->pdev); pp->flags |= PP_CLAIMED; info = &pp->pdev->port->ieee1284; pp->saved_state.mode = info->mode; @@ -689,9 +727,9 @@ static int pp_release (struct inode * inode, struct file * file) compat_negot = 2; } if (compat_negot) { - parport_negotiate (pp->pdev->port, IEEE1284_MODE_COMPAT); - pr_debug(CHRDEV "%x: negotiated back to compatibility " - "mode because user-space forgot\n", minor); + parport_negotiate(pp->pdev->port, IEEE1284_MODE_COMPAT); + dev_dbg(&pp->pdev->dev, + "negotiated back to compatibility mode because user-space forgot\n"); } if (pp->flags & PP_CLAIMED) { @@ -702,7 +740,7 @@ static int pp_release (struct inode * inode, struct file * file) pp->state.phase = info->phase; info->mode = pp->saved_state.mode; info->phase = pp->saved_state.phase; - parport_release (pp->pdev); + parport_release(pp->pdev); if (compat_negot != 1) { pr_debug(CHRDEV "%x: released pardevice " "because user-space forgot\n", minor); @@ -711,25 +749,26 @@ static int pp_release (struct inode * inode, struct file * file) if (pp->pdev) { const char *name = pp->pdev->name; - parport_unregister_device (pp->pdev); - kfree (name); + + parport_unregister_device(pp->pdev); + kfree(name); pp->pdev = NULL; pr_debug(CHRDEV "%x: unregistered pardevice\n", minor); } - kfree (pp); + kfree(pp); return 0; } /* No kernel lock held - fine */ -static unsigned int pp_poll (struct file * file, poll_table * wait) +static unsigned int pp_poll(struct file *file, poll_table *wait) { struct pp_struct *pp = file->private_data; unsigned int mask = 0; - poll_wait (file, &pp->irq_wait, wait); - if (atomic_read (&pp->irqc)) + poll_wait(file, &pp->irq_wait, wait); + if (atomic_read(&pp->irqc)) mask |= POLLIN | POLLRDNORM; return mask; @@ -744,6 +783,9 @@ static const struct file_operations pp_fops = { .write = pp_write, .poll = pp_poll, .unlocked_ioctl = pp_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = pp_compat_ioctl, +#endif .open = pp_open, .release = pp_release, }; @@ -759,19 +801,32 @@ static void pp_detach(struct parport *port) device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number)); } +static int pp_probe(struct pardevice *par_dev) +{ + struct device_driver *drv = par_dev->dev.driver; + int len = strlen(drv->name); + + if (strncmp(par_dev->name, drv->name, len)) + return -ENODEV; + + return 0; +} + static struct parport_driver pp_driver = { .name = CHRDEV, - .attach = pp_attach, + .probe = pp_probe, + .match_port = pp_attach, .detach = pp_detach, + .devmodel = true, }; -static int __init ppdev_init (void) +static int __init ppdev_init(void) { int err = 0; - if (register_chrdev (PP_MAJOR, CHRDEV, &pp_fops)) { - printk (KERN_WARNING CHRDEV ": unable to get major %d\n", - PP_MAJOR); + if (register_chrdev(PP_MAJOR, CHRDEV, &pp_fops)) { + printk(KERN_WARNING CHRDEV ": unable to get major %d\n", + PP_MAJOR); return -EIO; } ppdev_class = class_create(THIS_MODULE, CHRDEV); @@ -781,11 +836,11 @@ static int __init ppdev_init (void) } err = parport_register_driver(&pp_driver); if (err < 0) { - printk (KERN_WARNING CHRDEV ": unable to register with parport\n"); + printk(KERN_WARNING CHRDEV ": unable to register with parport\n"); goto out_class; } - printk (KERN_INFO PP_VERSION "\n"); + printk(KERN_INFO PP_VERSION "\n"); goto out; out_class: @@ -796,12 +851,12 @@ out: return err; } -static void __exit ppdev_cleanup (void) +static void __exit ppdev_cleanup(void) { /* Clean up all parport stuff */ parport_unregister_driver(&pp_driver); class_destroy(ppdev_class); - unregister_chrdev (PP_MAJOR, CHRDEV); + unregister_chrdev(PP_MAJOR, CHRDEV); } module_init(ppdev_init); diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 9b9809b709a5..e83b2adc014a 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -334,10 +334,8 @@ static int __init raw_init(void) cdev_init(&raw_cdev, &raw_fops); ret = cdev_add(&raw_cdev, dev, max_raw_minors); - if (ret) { + if (ret) goto error_region; - } - raw_class = class_create(THIS_MODULE, "raw"); if (IS_ERR(raw_class)) { printk(KERN_ERR "Error creating raw class.\n"); diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 45cc39aabeee..274dd0123237 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -88,6 +88,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, const struct tpm_class_ops *ops) { struct tpm_chip *chip; + int rc; chip = kzalloc(sizeof(*chip), GFP_KERNEL); if (chip == NULL) @@ -136,11 +137,17 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, chip->cdev.owner = chip->pdev->driver->owner; chip->cdev.kobj.parent = &chip->dev.kobj; + rc = devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev); + if (rc) { + put_device(&chip->dev); + return ERR_PTR(rc); + } + return chip; } EXPORT_SYMBOL_GPL(tpmm_chip_alloc); -static int tpm_dev_add_device(struct tpm_chip *chip) +static int tpm_add_char_device(struct tpm_chip *chip) { int rc; @@ -151,7 +158,6 @@ static int tpm_dev_add_device(struct tpm_chip *chip) chip->devname, MAJOR(chip->dev.devt), MINOR(chip->dev.devt), rc); - device_unregister(&chip->dev); return rc; } @@ -162,16 +168,17 @@ static int tpm_dev_add_device(struct tpm_chip *chip) chip->devname, MAJOR(chip->dev.devt), MINOR(chip->dev.devt), rc); + cdev_del(&chip->cdev); return rc; } return rc; } -static void tpm_dev_del_device(struct tpm_chip *chip) +static void tpm_del_char_device(struct tpm_chip *chip) { cdev_del(&chip->cdev); - device_unregister(&chip->dev); + device_del(&chip->dev); } static int tpm1_chip_register(struct tpm_chip *chip) @@ -222,7 +229,7 @@ int tpm_chip_register(struct tpm_chip *chip) tpm_add_ppi(chip); - rc = tpm_dev_add_device(chip); + rc = tpm_add_char_device(chip); if (rc) goto out_err; @@ -274,6 +281,6 @@ void tpm_chip_unregister(struct tpm_chip *chip) sysfs_remove_link(&chip->pdev->kobj, "ppi"); tpm1_chip_unregister(chip); - tpm_dev_del_device(chip); + tpm_del_char_device(chip); } EXPORT_SYMBOL_GPL(tpm_chip_unregister); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 542a80cbfd9c..28b477e8da6a 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -128,13 +128,6 @@ enum tpm2_startup_types { TPM2_SU_STATE = 0x0001, }; -enum tpm2_start_method { - TPM2_START_ACPI = 2, - TPM2_START_FIFO = 6, - TPM2_START_CRB = 7, - TPM2_START_CRB_WITH_ACPI = 8, -}; - struct tpm_chip; struct tpm_vendor_specific { diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 45a634016f95..b28e4da3d2cf 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -20,7 +20,11 @@ #include <keys/trusted-type.h> enum tpm2_object_attributes { - TPM2_ATTR_USER_WITH_AUTH = BIT(6), + TPM2_OA_USER_WITH_AUTH = BIT(6), +}; + +enum tpm2_session_attributes { + TPM2_SA_CONTINUE_SESSION = BIT(0), }; struct tpm2_startup_in { @@ -478,22 +482,18 @@ int tpm2_seal_trusted(struct tpm_chip *chip, tpm_buf_append_u8(&buf, payload->migratable); /* public */ - if (options->policydigest) - tpm_buf_append_u16(&buf, 14 + options->digest_len); - else - tpm_buf_append_u16(&buf, 14); - + tpm_buf_append_u16(&buf, 14 + options->policydigest_len); tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); tpm_buf_append_u16(&buf, hash); /* policy */ - if (options->policydigest) { + if (options->policydigest_len) { tpm_buf_append_u32(&buf, 0); - tpm_buf_append_u16(&buf, options->digest_len); + tpm_buf_append_u16(&buf, options->policydigest_len); tpm_buf_append(&buf, options->policydigest, - options->digest_len); + options->policydigest_len); } else { - tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH); + tpm_buf_append_u32(&buf, TPM2_OA_USER_WITH_AUTH); tpm_buf_append_u16(&buf, 0); } @@ -631,7 +631,7 @@ static int tpm2_unseal(struct tpm_chip *chip, options->policyhandle ? options->policyhandle : TPM2_RS_PW, NULL /* nonce */, 0, - 0 /* session_attributes */, + TPM2_SA_CONTINUE_SESSION, options->blobauth /* hmac */, TPM_DIGEST_SIZE); diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 8342cf51ffdc..a12b31940344 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -34,14 +34,6 @@ enum crb_defaults { CRB_ACPI_START_INDEX = 1, }; -struct acpi_tpm2 { - struct acpi_table_header hdr; - u16 platform_class; - u16 reserved; - u64 control_area_pa; - u32 start_method; -} __packed; - enum crb_ca_request { CRB_CA_REQ_GO_IDLE = BIT(0), CRB_CA_REQ_CMD_READY = BIT(1), @@ -85,6 +77,8 @@ enum crb_flags { struct crb_priv { unsigned int flags; + struct resource res; + void __iomem *iobase; struct crb_control_area __iomem *cca; u8 __iomem *cmd; u8 __iomem *rsp; @@ -97,7 +91,7 @@ static u8 crb_status(struct tpm_chip *chip) struct crb_priv *priv = chip->vendor.priv; u8 sts = 0; - if ((le32_to_cpu(ioread32(&priv->cca->start)) & CRB_START_INVOKE) != + if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) != CRB_START_INVOKE) sts |= CRB_STS_COMPLETE; @@ -113,7 +107,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) if (count < 6) return -EIO; - if (le32_to_cpu(ioread32(&priv->cca->sts)) & CRB_CA_STS_ERROR) + if (ioread32(&priv->cca->sts) & CRB_CA_STS_ERROR) return -EIO; memcpy_fromio(buf, priv->rsp, 6); @@ -149,11 +143,11 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) struct crb_priv *priv = chip->vendor.priv; int rc = 0; - if (len > le32_to_cpu(ioread32(&priv->cca->cmd_size))) { + if (len > ioread32(&priv->cca->cmd_size)) { dev_err(&chip->dev, "invalid command count value %x %zx\n", (unsigned int) len, - (size_t) le32_to_cpu(ioread32(&priv->cca->cmd_size))); + (size_t) ioread32(&priv->cca->cmd_size)); return -E2BIG; } @@ -189,7 +183,7 @@ static void crb_cancel(struct tpm_chip *chip) static bool crb_req_canceled(struct tpm_chip *chip, u8 status) { struct crb_priv *priv = chip->vendor.priv; - u32 cancel = le32_to_cpu(ioread32(&priv->cca->cancel)); + u32 cancel = ioread32(&priv->cca->cancel); return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE; } @@ -204,97 +198,145 @@ static const struct tpm_class_ops tpm_crb = { .req_complete_val = CRB_STS_COMPLETE, }; -static int crb_acpi_add(struct acpi_device *device) +static int crb_init(struct acpi_device *device, struct crb_priv *priv) { struct tpm_chip *chip; - struct acpi_tpm2 *buf; + int rc; + + chip = tpmm_chip_alloc(&device->dev, &tpm_crb); + if (IS_ERR(chip)) + return PTR_ERR(chip); + + chip->vendor.priv = priv; + chip->acpi_dev_handle = device->handle; + chip->flags = TPM_CHIP_FLAG_TPM2; + + rc = tpm_get_timeouts(chip); + if (rc) + return rc; + + rc = tpm2_do_selftest(chip); + if (rc) + return rc; + + return tpm_chip_register(chip); +} + +static int crb_check_resource(struct acpi_resource *ares, void *data) +{ + struct crb_priv *priv = data; + struct resource res; + + if (acpi_dev_resource_memory(ares, &res)) { + priv->res = res; + priv->res.name = NULL; + } + + return 1; +} + +static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv, + u64 start, u32 size) +{ + struct resource new_res = { + .start = start, + .end = start + size - 1, + .flags = IORESOURCE_MEM, + }; + + /* Detect a 64 bit address on a 32 bit system */ + if (start != new_res.start) + return ERR_PTR(-EINVAL); + + if (!resource_contains(&priv->res, &new_res)) + return devm_ioremap_resource(dev, &new_res); + + return priv->iobase + (new_res.start - priv->res.start); +} + +static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, + struct acpi_table_tpm2 *buf) +{ + struct list_head resources; + struct device *dev = &device->dev; + u64 pa; + int ret; + + INIT_LIST_HEAD(&resources); + ret = acpi_dev_get_resources(device, &resources, crb_check_resource, + priv); + if (ret < 0) + return ret; + acpi_dev_free_resource_list(&resources); + + if (resource_type(&priv->res) != IORESOURCE_MEM) { + dev_err(dev, + FW_BUG "TPM2 ACPI table does not define a memory resource\n"); + return -EINVAL; + } + + priv->iobase = devm_ioremap_resource(dev, &priv->res); + if (IS_ERR(priv->iobase)) + return PTR_ERR(priv->iobase); + + priv->cca = crb_map_res(dev, priv, buf->control_address, 0x1000); + if (IS_ERR(priv->cca)) + return PTR_ERR(priv->cca); + + pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) | + (u64) ioread32(&priv->cca->cmd_pa_low); + priv->cmd = crb_map_res(dev, priv, pa, ioread32(&priv->cca->cmd_size)); + if (IS_ERR(priv->cmd)) + return PTR_ERR(priv->cmd); + + memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); + pa = le64_to_cpu(pa); + priv->rsp = crb_map_res(dev, priv, pa, ioread32(&priv->cca->rsp_size)); + return PTR_ERR_OR_ZERO(priv->rsp); +} + +static int crb_acpi_add(struct acpi_device *device) +{ + struct acpi_table_tpm2 *buf; struct crb_priv *priv; struct device *dev = &device->dev; acpi_status status; u32 sm; - u64 pa; int rc; status = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **) &buf); - if (ACPI_FAILURE(status)) { - dev_err(dev, "failed to get TPM2 ACPI table\n"); - return -ENODEV; + if (ACPI_FAILURE(status) || buf->header.length < sizeof(*buf)) { + dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n"); + return -EINVAL; } /* Should the FIFO driver handle this? */ - if (buf->start_method == TPM2_START_FIFO) + sm = buf->start_method; + if (sm == ACPI_TPM2_MEMORY_MAPPED) return -ENODEV; - chip = tpmm_chip_alloc(dev, &tpm_crb); - if (IS_ERR(chip)) - return PTR_ERR(chip); - - chip->flags = TPM_CHIP_FLAG_TPM2; - - if (buf->hdr.length < sizeof(struct acpi_tpm2)) { - dev_err(dev, "TPM2 ACPI table has wrong size"); - return -EINVAL; - } - - priv = (struct crb_priv *) devm_kzalloc(dev, sizeof(struct crb_priv), - GFP_KERNEL); - if (!priv) { - dev_err(dev, "failed to devm_kzalloc for private data\n"); + priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL); + if (!priv) return -ENOMEM; - } - - sm = le32_to_cpu(buf->start_method); /* The reason for the extra quirk is that the PTT in 4th Gen Core CPUs * report only ACPI start but in practice seems to require both * ACPI start and CRB start. */ - if (sm == TPM2_START_CRB || sm == TPM2_START_FIFO || + if (sm == ACPI_TPM2_COMMAND_BUFFER || sm == ACPI_TPM2_MEMORY_MAPPED || !strcmp(acpi_device_hid(device), "MSFT0101")) priv->flags |= CRB_FL_CRB_START; - if (sm == TPM2_START_ACPI || sm == TPM2_START_CRB_WITH_ACPI) + if (sm == ACPI_TPM2_START_METHOD || + sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) priv->flags |= CRB_FL_ACPI_START; - priv->cca = (struct crb_control_area __iomem *) - devm_ioremap_nocache(dev, buf->control_area_pa, 0x1000); - if (!priv->cca) { - dev_err(dev, "ioremap of the control area failed\n"); - return -ENOMEM; - } - - pa = ((u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_high)) << 32) | - (u64) le32_to_cpu(ioread32(&priv->cca->cmd_pa_low)); - priv->cmd = devm_ioremap_nocache(dev, pa, - ioread32(&priv->cca->cmd_size)); - if (!priv->cmd) { - dev_err(dev, "ioremap of the command buffer failed\n"); - return -ENOMEM; - } - - memcpy_fromio(&pa, &priv->cca->rsp_pa, 8); - pa = le64_to_cpu(pa); - priv->rsp = devm_ioremap_nocache(dev, pa, - ioread32(&priv->cca->rsp_size)); - if (!priv->rsp) { - dev_err(dev, "ioremap of the response buffer failed\n"); - return -ENOMEM; - } - - chip->vendor.priv = priv; - - rc = tpm_get_timeouts(chip); + rc = crb_map_io(device, priv, buf); if (rc) return rc; - chip->acpi_dev_handle = device->handle; - - rc = tpm2_do_selftest(chip); - if (rc) - return rc; - - return tpm_chip_register(chip); + return crb_init(device, priv); } static int crb_acpi_remove(struct acpi_device *device) @@ -302,11 +344,11 @@ static int crb_acpi_remove(struct acpi_device *device) struct device *dev = &device->dev; struct tpm_chip *chip = dev_get_drvdata(dev); - tpm_chip_unregister(chip); - if (chip->flags & TPM_CHIP_FLAG_TPM2) tpm2_shutdown(chip, TPM2_SU_CLEAR); + tpm_chip_unregister(chip); + return 0; } diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c index bd72fb04225e..4e6940acf639 100644 --- a/drivers/char/tpm/tpm_eventlog.c +++ b/drivers/char/tpm/tpm_eventlog.c @@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) { struct tcpa_event *event = v; struct tcpa_event temp_event; - char *tempPtr; + char *temp_ptr; int i; memcpy(&temp_event, event, sizeof(struct tcpa_event)); @@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) temp_event.event_type = do_endian_conversion(event->event_type); temp_event.event_size = do_endian_conversion(event->event_size); - tempPtr = (char *)&temp_event; + temp_ptr = (char *) &temp_event; - for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++) - seq_putc(m, tempPtr[i]); + for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++) + seq_putc(m, temp_ptr[i]); + + temp_ptr = (char *) v; + + for (i = (sizeof(struct tcpa_event) - 1); + i < (sizeof(struct tcpa_event) + temp_event.event_size); i++) + seq_putc(m, temp_ptr[i]); return 0; diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 8a3509cb10da..a507006728e0 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -28,7 +28,6 @@ #include <linux/wait.h> #include <linux/acpi.h> #include <linux/freezer.h> -#include <acpi/actbl2.h> #include "tpm.h" enum tis_access { @@ -60,22 +59,18 @@ enum tis_int_flags { }; enum tis_defaults { - TIS_MEM_BASE = 0xFED40000, TIS_MEM_LEN = 0x5000, TIS_SHORT_TIMEOUT = 750, /* ms */ TIS_LONG_TIMEOUT = 2000, /* 2 sec */ }; struct tpm_info { - unsigned long start; - unsigned long len; - unsigned int irq; -}; - -static struct tpm_info tis_default_info = { - .start = TIS_MEM_BASE, - .len = TIS_MEM_LEN, - .irq = 0, + struct resource res; + /* irq > 0 means: use irq $irq; + * irq = 0 means: autoprobe for an irq; + * irq = -1 means: no irq support + */ + int irq; }; /* Some timeout values are needed before it is known whether the chip is @@ -118,39 +113,11 @@ static inline int is_itpm(struct acpi_device *dev) { return has_hid(dev, "INTC0102"); } - -static inline int is_fifo(struct acpi_device *dev) -{ - struct acpi_table_tpm2 *tbl; - acpi_status st; - - /* TPM 1.2 FIFO */ - if (!has_hid(dev, "MSFT0101")) - return 1; - - st = acpi_get_table(ACPI_SIG_TPM2, 1, - (struct acpi_table_header **) &tbl); - if (ACPI_FAILURE(st)) { - dev_err(&dev->dev, "failed to get TPM2 ACPI table\n"); - return 0; - } - - if (le32_to_cpu(tbl->start_method) != TPM2_START_FIFO) - return 0; - - /* TPM 2.0 FIFO */ - return 1; -} #else static inline int is_itpm(struct acpi_device *dev) { return 0; } - -static inline int is_fifo(struct acpi_device *dev) -{ - return 1; -} #endif /* Before we attempt to access the TPM we must see that the valid bit is set. @@ -716,9 +683,9 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, chip->acpi_dev_handle = acpi_dev_handle; #endif - chip->vendor.iobase = devm_ioremap(dev, tpm_info->start, tpm_info->len); - if (!chip->vendor.iobase) - return -EIO; + chip->vendor.iobase = devm_ioremap_resource(dev, &tpm_info->res); + if (IS_ERR(chip->vendor.iobase)) + return PTR_ERR(chip->vendor.iobase); /* Maximum timeouts */ chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX; @@ -807,7 +774,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info, /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); - if (interrupts) { + if (interrupts && tpm_info->irq != -1) { if (tpm_info->irq) { tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED, tpm_info->irq); @@ -893,29 +860,29 @@ static int tpm_tis_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); -#ifdef CONFIG_PNP static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, - const struct pnp_device_id *pnp_id) + const struct pnp_device_id *pnp_id) { - struct tpm_info tpm_info = tis_default_info; + struct tpm_info tpm_info = {}; acpi_handle acpi_dev_handle = NULL; + struct resource *res; - tpm_info.start = pnp_mem_start(pnp_dev, 0); - tpm_info.len = pnp_mem_len(pnp_dev, 0); + res = pnp_get_resource(pnp_dev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + tpm_info.res = *res; if (pnp_irq_valid(pnp_dev, 0)) tpm_info.irq = pnp_irq(pnp_dev, 0); else - interrupts = false; + tpm_info.irq = -1; -#ifdef CONFIG_ACPI if (pnp_acpi_device(pnp_dev)) { if (is_itpm(pnp_acpi_device(pnp_dev))) itpm = true; - acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; + acpi_dev_handle = ACPI_HANDLE(&pnp_dev->dev); } -#endif return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle); } @@ -956,7 +923,6 @@ static struct pnp_driver tis_pnp_driver = { module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); -#endif #ifdef CONFIG_ACPI static int tpm_check_resource(struct acpi_resource *ares, void *data) @@ -964,11 +930,11 @@ static int tpm_check_resource(struct acpi_resource *ares, void *data) struct tpm_info *tpm_info = (struct tpm_info *) data; struct resource res; - if (acpi_dev_resource_interrupt(ares, 0, &res)) { + if (acpi_dev_resource_interrupt(ares, 0, &res)) tpm_info->irq = res.start; - } else if (acpi_dev_resource_memory(ares, &res)) { - tpm_info->start = res.start; - tpm_info->len = resource_size(&res); + else if (acpi_dev_resource_memory(ares, &res)) { + tpm_info->res = res; + tpm_info->res.name = NULL; } return 1; @@ -976,14 +942,25 @@ static int tpm_check_resource(struct acpi_resource *ares, void *data) static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) { + struct acpi_table_tpm2 *tbl; + acpi_status st; struct list_head resources; - struct tpm_info tpm_info = tis_default_info; + struct tpm_info tpm_info = {}; int ret; - if (!is_fifo(acpi_dev)) + st = acpi_get_table(ACPI_SIG_TPM2, 1, + (struct acpi_table_header **) &tbl); + if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) { + dev_err(&acpi_dev->dev, + FW_BUG "failed to get TPM2 ACPI table\n"); + return -EINVAL; + } + + if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED) return -ENODEV; INIT_LIST_HEAD(&resources); + tpm_info.irq = -1; ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource, &tpm_info); if (ret < 0) @@ -991,8 +968,11 @@ static int tpm_tis_acpi_init(struct acpi_device *acpi_dev) acpi_dev_free_resource_list(&resources); - if (!tpm_info.irq) - interrupts = false; + if (resource_type(&tpm_info.res) != IORESOURCE_MEM) { + dev_err(&acpi_dev->dev, + FW_BUG "TPM2 ACPI table does not define a memory resource\n"); + return -EINVAL; + } if (is_itpm(acpi_dev)) itpm = true; @@ -1031,80 +1011,135 @@ static struct acpi_driver tis_acpi_driver = { }; #endif +static struct platform_device *force_pdev; + +static int tpm_tis_plat_probe(struct platform_device *pdev) +{ + struct tpm_info tpm_info = {}; + struct resource *res; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "no memory resource defined\n"); + return -ENODEV; + } + tpm_info.res = *res; + + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (res) { + tpm_info.irq = res->start; + } else { + if (pdev == force_pdev) + tpm_info.irq = -1; + else + /* When forcing auto probe the IRQ */ + tpm_info.irq = 0; + } + + return tpm_tis_init(&pdev->dev, &tpm_info, NULL); +} + +static int tpm_tis_plat_remove(struct platform_device *pdev) +{ + struct tpm_chip *chip = dev_get_drvdata(&pdev->dev); + + tpm_chip_unregister(chip); + tpm_tis_remove(chip); + + return 0; +} + static struct platform_driver tis_drv = { + .probe = tpm_tis_plat_probe, + .remove = tpm_tis_plat_remove, .driver = { .name = "tpm_tis", .pm = &tpm_tis_pm, }, }; -static struct platform_device *pdev; - static bool force; +#ifdef CONFIG_X86 module_param(force, bool, 0444); MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); +#endif + +static int tpm_tis_force_device(void) +{ + struct platform_device *pdev; + static const struct resource x86_resources[] = { + { + .start = 0xFED40000, + .end = 0xFED40000 + TIS_MEM_LEN - 1, + .flags = IORESOURCE_MEM, + }, + }; + + if (!force) + return 0; + + /* The driver core will match the name tpm_tis of the device to + * the tpm_tis platform driver and complete the setup via + * tpm_tis_plat_probe + */ + pdev = platform_device_register_simple("tpm_tis", -1, x86_resources, + ARRAY_SIZE(x86_resources)); + if (IS_ERR(pdev)) + return PTR_ERR(pdev); + force_pdev = pdev; + + return 0; +} + static int __init init_tis(void) { int rc; -#ifdef CONFIG_PNP - if (!force) { - rc = pnp_register_driver(&tis_pnp_driver); - if (rc) - return rc; - } -#endif + + rc = tpm_tis_force_device(); + if (rc) + goto err_force; + + rc = platform_driver_register(&tis_drv); + if (rc) + goto err_platform; + #ifdef CONFIG_ACPI - if (!force) { - rc = acpi_bus_register_driver(&tis_acpi_driver); - if (rc) { -#ifdef CONFIG_PNP - pnp_unregister_driver(&tis_pnp_driver); -#endif - return rc; - } - } + rc = acpi_bus_register_driver(&tis_acpi_driver); + if (rc) + goto err_acpi; #endif - if (!force) - return 0; - rc = platform_driver_register(&tis_drv); - if (rc < 0) - return rc; - pdev = platform_device_register_simple("tpm_tis", -1, NULL, 0); - if (IS_ERR(pdev)) { - rc = PTR_ERR(pdev); - goto err_dev; + if (IS_ENABLED(CONFIG_PNP)) { + rc = pnp_register_driver(&tis_pnp_driver); + if (rc) + goto err_pnp; } - rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL); - if (rc) - goto err_init; + return 0; -err_init: - platform_device_unregister(pdev); -err_dev: - platform_driver_unregister(&tis_drv); + +err_pnp: +#ifdef CONFIG_ACPI + acpi_bus_unregister_driver(&tis_acpi_driver); +err_acpi: +#endif + platform_device_unregister(force_pdev); +err_platform: + if (force_pdev) + platform_device_unregister(force_pdev); +err_force: return rc; } static void __exit cleanup_tis(void) { - struct tpm_chip *chip; -#if defined(CONFIG_PNP) || defined(CONFIG_ACPI) - if (!force) { + pnp_unregister_driver(&tis_pnp_driver); #ifdef CONFIG_ACPI - acpi_bus_unregister_driver(&tis_acpi_driver); -#endif -#ifdef CONFIG_PNP - pnp_unregister_driver(&tis_pnp_driver); + acpi_bus_unregister_driver(&tis_acpi_driver); #endif - return; - } -#endif - chip = dev_get_drvdata(&pdev->dev); - tpm_chip_unregister(chip); - tpm_tis_remove(chip); - platform_device_unregister(pdev); platform_driver_unregister(&tis_drv); + + if (force_pdev) + platform_device_unregister(force_pdev); } module_init(init_tis); diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index a15ce4ef39cd..b098d2d0b7c4 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -171,7 +171,7 @@ static const struct tty_operations ttyprintk_ops = { .ioctl = tpk_ioctl, }; -static struct tty_port_operations null_ops = { }; +static const struct tty_port_operations null_ops = { }; static struct tty_driver *ttyprintk_driver; diff --git a/drivers/char/xillybus/xillybus_core.c b/drivers/char/xillybus/xillybus_core.c index 77d6c127e691..dcd19f3f182e 100644 --- a/drivers/char/xillybus/xillybus_core.c +++ b/drivers/char/xillybus/xillybus_core.c @@ -509,7 +509,7 @@ static int xilly_setupchannels(struct xilly_endpoint *ep, channel->log2_element_size = ((format > 2) ? 2 : format); - bytebufsize = channel->rd_buf_size = bufsize * + bytebufsize = bufsize * (1 << channel->log2_element_size); buffers = devm_kcalloc(dev, bufnum, @@ -523,6 +523,7 @@ static int xilly_setupchannels(struct xilly_endpoint *ep, if (!is_writebuf) { channel->num_rd_buffers = bufnum; + channel->rd_buf_size = bytebufsize; channel->rd_allow_partial = allowpartial; channel->rd_synchronous = synchronous; channel->rd_exclusive_open = exclusive_open; @@ -533,6 +534,7 @@ static int xilly_setupchannels(struct xilly_endpoint *ep, bufnum, bytebufsize); } else if (channelnum > 0) { channel->num_wr_buffers = bufnum; + channel->wr_buf_size = bytebufsize; channel->seekable = seekable; channel->wr_supports_nonempty = supports_nonempty; |