/* * Driver for generic MPU-401 boards (UART mode only) * Copyright (c) by Jaroslav Kysela * Copyright (c) 2004 by Castet Matthieu * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include #include #include #include #include #include #include #include MODULE_AUTHOR("Jaroslav Kysela "); MODULE_DESCRIPTION("MPU-401 UART"); MODULE_LICENSE("GPL"); static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */ #ifdef CONFIG_PNP static bool pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; #endif static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */ static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */ static bool uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for MPU-401 device."); module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for MPU-401 device."); module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable MPU-401 device."); #ifdef CONFIG_PNP module_param_array(pnp, bool, NULL, 0444); MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device."); #endif module_param_array(port, long, NULL, 0444); MODULE_PARM_DESC(port, "Port # for MPU-401 device."); module_param_array(irq, int, NULL, 0444); MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device."); module_param_array(uart_enter, bool, NULL, 0444); MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open."); static struct platform_device *platform_devices[SNDRV_CARDS]; static int pnp_registered; static unsigned int snd_mpu401_devices; static int snd_mpu401_create(struct device *devptr, int dev, struct snd_card **rcard) { struct snd_card *card; int err; if (!uart_enter[dev]) snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n"); *rcard = NULL; err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE, 0, &card); if (err < 0) return err; strcpy(card->driver, "MPU-401 UART"); strcpy(card->shortname, card->driver); sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]); if (irq[dev] >= 0) { sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]); } else { strcat(card->longname, "polled"); } err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0, irq[dev], NULL); if (err < 0) { printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]); goto _err; } *rcard = card; return 0; _err: snd_card_free(card); return err; } static int snd_mpu401_probe(struct platform_device *devptr) { int dev = devptr->id; int err; struct snd_card *card; if (port[dev] == SNDRV_AUTO_PORT) { snd_printk(KERN_ERR "specify port\n"); return -EINVAL; } if (irq[dev] == SNDRV_AUTO_IRQ) { snd_printk(KERN_ERR "specify or disable IRQ\n"); return -EINVAL; } err = snd_mpu401_create(&devptr->dev, dev, &card); if (err < 0) return err; if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } platform_set_drvdata(devptr, card); return 0; } static int snd_mpu401_remove(struct platform_device *devptr) { snd_card_free(platform_get_drvdata(devptr)); return 0; } #define SND_MPU401_DRIVER "snd_mpu401" static struct platform_driver snd_mpu401_driver = { .probe = snd_mpu401_probe, .remove = snd_mpu401_remove, .driver = { .name = SND_MPU401_DRIVER, }, }; #ifdef CONFIG_PNP #define IO_EXTENT 2 static struct pnp_device_id snd_mpu401_pnpids[] = { { .id = "PNPb006" }, { .id = "" } }; MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); static int snd_mpu401_pnp(int dev, struct pnp_dev *device, const struct pnp_device_id *id) { if (!pnp_port_valid(device, 0) || pnp_port_flags(device, 0) & IORESOURCE_DISABLED) { snd_printk(KERN_ERR "no PnP port\n"); return -ENODEV; } if (pnp_port_len(device, 0) < IO_EXTENT) { snd_printk(KERN_ERR "PnP port length is %llu, expected %d\n", (unsigned long long)pnp_port_len(device, 0), IO_EXTENT); return -ENODEV; } port[dev] = pnp_port_start(device, 0); if (!pnp_irq_valid(device, 0) || pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) { snd_printk(KERN_WARNING "no PnP irq, using polling\n"); irq[dev] = -1; } else { irq[dev] = pnp_irq(device, 0); } return 0; } static int snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) { static int dev; struct snd_card *card; int err; for ( ; dev < SNDRV_CARDS; ++dev) { if (!enable[dev] || !pnp[dev]) continue; err = snd_mpu401_pnp(dev, pnp_dev, id); if (err < 0) return err; err = snd_mpu401_create(&pnp_dev->dev, dev, &card); if (err < 0) return err; if ((err = snd_card_register(card)) < 0) { snd_card_free(card); return err; } pnp_set_drvdata(pnp_dev, card); snd_mpu401_devices++; ++dev; return 0; } return -ENODEV; } static void snd_mpu401_pnp_remove(struct pnp_dev *dev) { struct snd_card *card = (struct snd_card *) pnp_get_drvdata(dev); snd_card_disconnect(card); snd_card_free_when_closed(card); } static struct pnp_driver snd_mpu401_pnp_driver = { .name = "mpu401", .id_table = snd_mpu401_pnpids, .probe = snd_mpu401_pnp_probe, .remove = snd_mpu401_pnp_remove, }; #else static struct pnp_driver snd_mpu401_pnp_driver; #endif static void snd_mpu401_unregister_all(void) { int i; if (pnp_registered) pnp_unregister_driver(&snd_mpu401_pnp_driver); for (i = 0; i < ARRAY_SIZE(platform_devices); ++i) platform_device_unregister(platform_devices[i]); platform_driver_unregister(&snd_mpu401_driver); } static int __init alsa_card_mpu401_init(void) { int i, err; if ((err = platform_driver_register(&snd_mpu401_driver)) < 0) return err; for (i = 0; i < SNDRV_CARDS; i++) { struct platform_device *device; if (! enable[i]) continue; #ifdef CONFIG_PNP if (pnp[i]) continue; #endif device = platform_device_register_simple(SND_MPU401_DRIVER, i, NULL, 0); if (IS_ERR(device)) continue; if (!platform_get_drvdata(device)) { platform_device_unregister(device); continue; } platform_devices[i] = device; snd_mpu401_devices++; } err = pnp_register_driver(&snd_mpu401_pnp_driver); if (!err) pnp_registered = 1; if (!snd_mpu401_devices) { #ifdef MODULE printk(KERN_ERR "MPU-401 device not found or device busy\n"); #endif snd_mpu401_unregister_all(); return -ENODEV; } return 0; } static void __exit alsa_card_mpu401_exit(void) { snd_mpu401_unregister_all(); } module_init(alsa_card_mpu401_init) module_exit(alsa_card_mpu401_exit) 2017-02-12netfilter: nfnetlink: allow to check for generation IDPablo Neira Ayuso1-4/+27 This patch allows userspace to specify the generation ID that has been used to build an incremental batch update. If userspace specifies the generation ID in the batch message as attribute, then nfnetlink compares it to the current generation ID so you make sure that you work against the right baseline. Otherwise, bail out with ERESTART so userspace knows that its changeset is stale and needs to respin. Userspace can do this transparently at the cost of taking slightly more time to refresh caches and rework the changeset. This check is optional, if there is no NFNL_BATCH_GENID attribute in the batch begin message, then no check is performed. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-12netfilter: nfnetlink: add nfnetlink_rcv_skb_batch()Pablo Neira Ayuso1-23/+28 Add new nfnetlink_rcv_skb_batch() to wrap initial nfnetlink batch handling. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-12netfilter: nfnetlink: get rid of u_intX_t typesPablo Neira Ayuso1-8/+8 Use uX types instead. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-12netfilter: nf_ct_expect: nf_ct_expect_insert() returns voidGao Feng1-5/+3 Because nf_ct_expect_insert() always succeeds now, its return value can be just void instead of int. And remove code that checks for its return value. Signed-off-by: Gao Feng <fgao@ikuai8.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-12netfilter: nf_ct_sip: Use mod_timer_pending()Gao Feng1-7/+5 timer_del() followed by timer_add() can be replaced by mod_timer_pending(). Signed-off-by: Gao Feng <fgao@ikuai8.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> 2017-02-11net_sched: fix error recovery at qdisc creationEric Dumazet5-23/+19 Dmitry reported uses after free in qdisc code [1] The problem here is that ops->init() can return an error. qdisc_create_dflt() then call ops->destroy(), while qdisc_create() does _not_ call it. Four qdisc chose to call their own ops->destroy(), assuming their caller would not. This patch makes sure qdisc_create() calls ops->destroy() and fixes the four qdisc to avoid double free. [1] BUG: KASAN: use-after-free in mq_destroy+0x242/0x290 net/sched/sch_mq.c:33 at addr ffff8801d415d440 Read of size 8 by task syz-executor2/5030 CPU: 0 PID: 5030 Comm: syz-executor2 Not tainted 4.3.5-smp-DEV #119 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 0000000000000046 ffff8801b435b870 ffffffff81bbbed4 ffff8801db000400 ffff8801d415d440 ffff8801d415dc40 ffff8801c4988510 ffff8801b435b898 ffffffff816682b1 ffff8801b435b928 ffff8801d415d440 ffff8801c49880c0 Call Trace: [<ffffffff81bbbed4>] __dump_stack lib/dump_stack.c:15 [inline] [<ffffffff81bbbed4>] dump_stack+0x6c/0x98 lib/dump_stack.c:51 [<ffffffff816682b1>] kasan_object_err+0x21/0x70 mm/kasan/report.c:158 [<ffffffff81668524>] print_address_description mm/kasan/report.c:196 [inline] [<ffffffff81668524>] kasan_report_error+0x1b4/0x4b0 mm/kasan/report.c:285 [<ffffffff81668953>] kasan_report mm/kasan/report.c:305 [inline] [<ffffffff81668953>] __asan_report_load8_noabort+0x43/0x50 mm/kasan/report.c:326 [<ffffffff82527b02>] mq_destroy+0x242/0x290 net/sched/sch_mq.c:33 [<ffffffff82524bdd>] qdisc_destroy+0x12d/0x290 net/sched/sch_generic.c:953 [<ffffffff82524e30>] qdisc_create_dflt+0xf0/0x120 net/sched/sch_generic.c:848 [<ffffffff8252550d>] attach_default_qdiscs net/sched/sch_generic.c:1029 [inline] [<ffffffff8252550d>] dev_activate+0x6ad/0x880 net/sched/sch_generic.c:1064 [<ffffffff824b1db1>] __dev_open+0x221/0x320 net/core/dev.c:1403 [<ffffffff824b24ce>] __dev_change_flags+0x15e/0x3e0 net/core/dev.c:6858 [<ffffffff824b27de>] dev_change_flags+0x8e/0x140 net/core/dev.c:6926 [<ffffffff824f5bf6>] dev_ifsioc+0x446/0x890 net/core/dev_ioctl.c:260 [<ffffffff824f61fa>] dev_ioctl+0x1ba/0xb80 net/core/dev_ioctl.c:546 [<ffffffff82430509>] sock_do_ioctl+0x99/0xb0 net/socket.c:879 [<ffffffff82430d30>] sock_ioctl+0x2a0/0x390 net/socket.c:958 [<ffffffff816f3b68>] vfs_ioctl fs/ioctl.c:44 [inline] [<ffffffff816f3b68>] do_vfs_ioctl+0x8a8/0xe50 fs/ioctl.c:611 [<ffffffff816f41a4>] SYSC_ioctl fs/ioctl.c:626 [inline] [<ffffffff816f41a4>] SyS_ioctl+0x94/0xc0 fs/ioctl.c:617 [<ffffffff8123e357>] entry_SYSCALL_64_fastpath+0x12/0x17 Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> 2017-02-11net: rename dst_neigh_output back to neigh_outputJulian Anastasov2-2/+2 After the dst->pending_confirm flag was removed, we do not need anymore to provide dst arg to dst_neigh_output. So, rename it to neigh_output as before commit 5110effee8fd ("net: Do delayed neigh confirmation."). Signed-off-by: Julian Anastasov <ja@ssi.bg> Signed-off-by: David S. Miller <davem@davemloft.net> 2017-02-11Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/netDavid S. Miller