diff options
Diffstat (limited to 'drivers/char')
88 files changed, 2455 insertions, 4125 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 650e6b4..caff851 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -8,7 +8,7 @@ config VT bool "Virtual terminal" if EMBEDDED depends on !S390 select INPUT - default y if !VIOCONS + default y ---help--- If you say Y here, you will get support for terminal devices with display and keyboard devices. These are called "virtual" because you @@ -36,6 +36,14 @@ config VT If unsure, say Y, or else you won't be able to do much with your new shiny Linux system :-) +config CONSOLE_TRANSLATIONS + depends on VT + default y + bool "Enable character translations in console" if EMBEDDED + ---help--- + This enables support for font mapping and Unicode translation + on virtual consoles. + config VT_CONSOLE bool "Support for console on virtual terminal" if EMBEDDED depends on VT @@ -300,16 +308,6 @@ config SPECIALIX and compile this driver as kernel loadable module which will be called specialix. -config SPECIALIX_RTSCTS - bool "Specialix DTR/RTS pin is RTS" - depends on SPECIALIX - help - The Specialix IO8+ card can only support either RTS or DTR. If you - say N here, the driver will use the pin as "DTR" when the tty is in - software handshake mode. If you say Y here or hardware handshake is - on, it will always be RTS. Read the file - <file:Documentation/specialix.txt> for more information. - config SX tristate "Specialix SX (and SI) card support" depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) @@ -588,11 +586,14 @@ config HVC_DRIVER It will automatically be selected if one of the back-end console drivers is selected. +config HVC_IRQ + bool config HVC_CONSOLE bool "pSeries Hypervisor Virtual Console support" depends on PPC_PSERIES select HVC_DRIVER + select HVC_IRQ help pSeries machines when partitioned support a hypervisor virtual console. This driver allows each pSeries partition to have a console @@ -603,6 +604,7 @@ config HVC_ISERIES depends on PPC_ISERIES default y select HVC_DRIVER + select HVC_IRQ help iSeries machines support a hypervisor virtual console. @@ -624,13 +626,18 @@ config HVC_XEN bool "Xen Hypervisor Console support" depends on XEN select HVC_DRIVER + select HVC_IRQ default y help Xen virtual console device driver config VIRTIO_CONSOLE - bool + tristate "Virtio console" + depends on VIRTIO select HVC_DRIVER + help + Virtio console for use with lguest and other hypervisors. + config HVCS tristate "IBM Hypervisor Virtual Console Server support" @@ -867,13 +874,6 @@ config DS1302 endif # RTC_LIB -config COBALT_LCD - bool "Support for Cobalt LCD" - depends on MIPS_COBALT - help - This option enables support for the LCD display and buttons found - on Cobalt systems through a misc device. - config DTLK tristate "Double Talk PC internal speech card support" depends on ISA diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 0e0d12a..6850f6d 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -7,13 +7,13 @@ # FONTMAPFILE = cp437.uni -obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o +obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o obj-$(CONFIG_LEGACY_PTYS) += pty.o obj-$(CONFIG_UNIX98_PTYS) += pty.o obj-y += misc.o -obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o consolemap.o \ - consolemap_deftbl.o selection.o keyboard.o +obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o +obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o obj-$(CONFIG_AUDIT) += tty_audit.o obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o @@ -48,13 +48,13 @@ obj-$(CONFIG_HVC_ISERIES) += hvc_iseries.o obj-$(CONFIG_HVC_RTAS) += hvc_rtas.o obj-$(CONFIG_HVC_BEAT) += hvc_beat.o obj-$(CONFIG_HVC_DRIVER) += hvc_console.o +obj-$(CONFIG_HVC_IRQ) += hvc_irq.o obj-$(CONFIG_HVC_XEN) += hvc_xen.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o obj-$(CONFIG_MSPEC) += mspec.o obj-$(CONFIG_MMTIMER) += mmtimer.o -obj-$(CONFIG_VIOCONS) += viocons.o obj-$(CONFIG_VIOTAPE) += viotape.o obj-$(CONFIG_HVCS) += hvcs.o obj-$(CONFIG_IBM_BSR) += bsr.o @@ -63,7 +63,6 @@ obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o obj-$(CONFIG_BFIN_OTP) += bfin-otp.o obj-$(CONFIG_PRINTER) += lp.o -obj-$(CONFIG_TIPAR) += tipar.o obj-$(CONFIG_APM_EMULATION) += apm-emulation.o @@ -88,7 +87,6 @@ obj-$(CONFIG_TOSHIBA) += toshiba.o obj-$(CONFIG_I8K) += i8k.o obj-$(CONFIG_DS1620) += ds1620.o obj-$(CONFIG_HW_RANDOM) += hw_random/ -obj-$(CONFIG_COBALT_LCD) += lcd.o obj-$(CONFIG_PPDEV) += ppdev.o obj-$(CONFIG_NWBUTTON) += nwbutton.o obj-$(CONFIG_NWFLASH) += nwflash.o diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 81e14be..4bada0e 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -148,6 +148,9 @@ struct agp_bridge_data { char minor_version; struct list_head list; u32 apbase_config; + /* list of agp_memory mapped to the aperture */ + struct list_head mapped_list; + spinlock_t mapped_lock; }; #define KB(x) ((x) * 1024) diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 1ffb381..31dcd91 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -110,7 +110,8 @@ static int ali_configure(void) nlvm_addr+= agp_bridge->gart_bus_addr; nlvm_addr|=(agp_bridge->gart_bus_addr>>12); - printk(KERN_INFO PFX "nlvm top &base = %8x\n",nlvm_addr); + dev_info(&agp_bridge->dev->dev, "nlvm top &base = %8x\n", + nlvm_addr); } #endif @@ -315,8 +316,8 @@ static int __devinit agp_ali_probe(struct pci_dev *pdev, goto found; } - printk(KERN_ERR PFX "Unsupported ALi chipset (device id: %04x)\n", - pdev->device); + dev_err(&pdev->dev, "unsupported ALi chipset [%04x/%04x])\n", + pdev->vendor, pdev->device); return -ENODEV; @@ -361,8 +362,7 @@ found: bridge->driver = &ali_generic_bridge; } - printk(KERN_INFO PFX "Detected ALi %s chipset\n", - devs[j].chipset_name); + dev_info(&pdev->dev, "ALi %s chipset\n", devs[j].chipset_name); /* Fill in the mode register */ pci_read_config_dword(pdev, diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 39a0718..e280531 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -419,8 +419,8 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, return -ENODEV; j = ent - agp_amdk7_pci_table; - printk(KERN_INFO PFX "Detected AMD %s chipset\n", - amd_agp_device_ids[j].chipset_name); + dev_info(&pdev->dev, "AMD %s chipset\n", + amd_agp_device_ids[j].chipset_name); bridge = agp_alloc_bridge(); if (!bridge) @@ -442,7 +442,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, while (!cap_ptr) { gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard); if (!gfxcard) { - printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n"); + dev_info(&pdev->dev, "no AGP VGA controller\n"); return -ENODEV; } cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP); @@ -453,7 +453,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, (if necessary at all). */ if (gfxcard->vendor == PCI_VENDOR_ID_NVIDIA) { agp_bridge->flags |= AGP_ERRATA_1X; - printk (KERN_INFO PFX "AMD 751 chipset with NVidia GeForce detected. Forcing to 1X due to errata.\n"); + dev_info(&pdev->dev, "AMD 751 chipset with NVidia GeForce; forcing 1X due to errata\n"); } pci_dev_put(gfxcard); } @@ -469,7 +469,7 @@ static int __devinit agp_amdk7_probe(struct pci_dev *pdev, agp_bridge->flags = AGP_ERRATA_FASTWRITES; agp_bridge->flags |= AGP_ERRATA_SBA; agp_bridge->flags |= AGP_ERRATA_1X; - printk (KERN_INFO PFX "AMD 761 chipset with errata detected - disabling AGP fast writes & SBA and forcing to 1X.\n"); + dev_info(&pdev->dev, "AMD 761 chipset with errata; disabling AGP fast writes & SBA and forcing to 1X\n"); } } diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 481ffe8..7495c52 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -34,6 +34,7 @@ static struct resource *aperture_resource; static int __initdata agp_try_unsupported = 1; +static int agp_bridges_found; static void amd64_tlbflush(struct agp_memory *temp) { @@ -293,12 +294,13 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, * so let double check that order, and lets trust the AMD NB settings */ if (order >=0 && aper + (32ULL<<(20 + order)) > 0x100000000ULL) { - printk(KERN_INFO "Aperture size %u MB is not right, using settings from NB\n", - 32 << order); + dev_info(&agp->dev, "aperture size %u MB is not right, using settings from NB\n", + 32 << order); order = nb_order; } - printk(KERN_INFO PFX "Aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); + dev_info(&agp->dev, "aperture from AGP @ %Lx size %u MB\n", + aper, 32 << order); if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order)) return -1; @@ -319,10 +321,10 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) for (i = 0; i < num_k8_northbridges; i++) { struct pci_dev *dev = k8_northbridges[i]; if (fix_northbridge(dev, pdev, cap_ptr) < 0) { - printk(KERN_ERR PFX "No usable aperture found.\n"); + dev_err(&dev->dev, "no usable aperture found\n"); #ifdef __x86_64__ /* should port this to i386 */ - printk(KERN_ERR PFX "Consider rebooting with iommu=memaper=2 to get a good aperture.\n"); + dev_err(&dev->dev, "consider rebooting with iommu=memaper=2 to get a good aperture\n"); #endif return -1; } @@ -345,14 +347,14 @@ static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data default: revstring="??"; break; } - printk (KERN_INFO PFX "Detected AMD 8151 AGP Bridge rev %s\n", revstring); + dev_info(&pdev->dev, "AMD 8151 AGP Bridge rev %s\n", revstring); /* * Work around errata. * Chips before B2 stepping incorrectly reporting v3.5 */ if (pdev->revision < 0x13) { - printk (KERN_INFO PFX "Correcting AGP revision (reports 3.5, is really 3.0)\n"); + dev_info(&pdev->dev, "correcting AGP revision (reports 3.5, is really 3.0)\n"); bridge->major_version = 3; bridge->minor_version = 0; } @@ -375,11 +377,11 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) struct pci_dev *dev1; int i; unsigned size = amd64_fetch_size(); - printk(KERN_INFO "Setting up ULi AGP.\n"); + + dev_info(&pdev->dev, "setting up ULi AGP\n"); dev1 = pci_get_slot (pdev->bus,PCI_DEVFN(0,0)); if (dev1 == NULL) { - printk(KERN_INFO PFX "Detected a ULi chipset, " - "but could not fine the secondary device.\n"); + dev_info(&pdev->dev, "can't find ULi secondary device\n"); return -ENODEV; } @@ -388,7 +390,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) break; if (i == ARRAY_SIZE(uli_sizes)) { - printk(KERN_INFO PFX "No ULi size found for %d\n", size); + dev_info(&pdev->dev, "no ULi size found for %d\n", size); return -ENODEV; } @@ -433,13 +435,11 @@ static int nforce3_agp_init(struct pci_dev *pdev) int i; unsigned size = amd64_fetch_size(); - printk(KERN_INFO PFX "Setting up Nforce3 AGP.\n"); + dev_info(&pdev->dev, "setting up Nforce3 AGP\n"); dev1 = pci_get_slot(pdev->bus, PCI_DEVFN(11, 0)); if (dev1 == NULL) { - printk(KERN_INFO PFX "agpgart: Detected an NVIDIA " - "nForce3 chipset, but could not find " - "the secondary device.\n"); + dev_info(&pdev->dev, "can't find Nforce3 secondary device\n"); return -ENODEV; } @@ -448,7 +448,7 @@ static int nforce3_agp_init(struct pci_dev *pdev) break; if (i == ARRAY_SIZE(nforce3_sizes)) { - printk(KERN_INFO PFX "No NForce3 size found for %d\n", size); + dev_info(&pdev->dev, "no NForce3 size found for %d\n", size); return -ENODEV; } @@ -462,7 +462,7 @@ static int nforce3_agp_init(struct pci_dev *pdev) /* if x86-64 aperture base is beyond 4G, exit here */ if ( (apbase & 0x7fff) >> (32 - 25) ) { - printk(KERN_INFO PFX "aperture base > 4G\n"); + dev_info(&pdev->dev, "aperture base > 4G\n"); return -ENODEV; } @@ -489,6 +489,7 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, { struct agp_bridge_data *bridge; u8 cap_ptr; + int err; cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); if (!cap_ptr) @@ -504,7 +505,8 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, pdev->device == PCI_DEVICE_ID_AMD_8151_0) { amd8151_init(pdev, bridge); } else { - printk(KERN_INFO PFX "Detected AGP bridge %x\n", pdev->devfn); + dev_info(&pdev->dev, "AGP bridge [%04x/%04x]\n", + pdev->vendor, pdev->device); } bridge->driver = &amd_8151_driver; @@ -536,7 +538,12 @@ static int __devinit agp_amd64_probe(struct pci_dev *pdev, } pci_set_drvdata(pdev, bridge); - return agp_add_bridge(bridge); + err = agp_add_bridge(bridge); + if (err < 0) + return err; + + agp_bridges_found++; + return 0; } static void __devexit agp_amd64_remove(struct pci_dev *pdev) @@ -713,7 +720,11 @@ int __init agp_amd64_init(void) if (agp_off) return -EINVAL; - if (pci_register_driver(&agp_amd64_pci_driver) < 0) { + err = pci_register_driver(&agp_amd64_pci_driver); + if (err < 0) + return err; + + if (agp_bridges_found == 0) { struct pci_dev *dev; if (!agp_try_unsupported && !agp_try_unsupported_boot) { printk(KERN_INFO PFX "No supported AGP bridge found.\n"); diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 3a4566c..6ecbcaf 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c @@ -486,8 +486,8 @@ static int __devinit agp_ati_probe(struct pci_dev *pdev, goto found; } - printk(KERN_ERR PFX - "Unsupported Ati chipset (device id: %04x)\n", pdev->device); + dev_err(&pdev->dev, "unsupported Ati chipset [%04x/%04x])\n", + pdev->vendor, pdev->device); return -ENODEV; found: @@ -500,8 +500,7 @@ found: bridge->driver = &ati_generic_bridge; - printk(KERN_INFO PFX "Detected Ati %s chipset\n", - devs[j].chipset_name); + dev_info(&pdev->dev, "Ati %s chipset\n", devs[j].chipset_name); /* Fill in the mode register */ pci_read_config_dword(pdev, diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 1ec8710..3a3cc03 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -144,7 +144,8 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) void *addr = bridge->driver->agp_alloc_page(bridge); if (!addr) { - printk(KERN_ERR PFX "unable to get memory for scratch page.\n"); + dev_err(&bridge->dev->dev, + "can't get memory for scratch page\n"); return -ENOMEM; } @@ -155,13 +156,13 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) size_value = bridge->driver->fetch_size(); if (size_value == 0) { - printk(KERN_ERR PFX "unable to determine aperture size.\n"); + dev_err(&bridge->dev->dev, "can't determine aperture size\n"); rc = -EINVAL; goto err_out; } if (bridge->driver->create_gatt_table(bridge)) { - printk(KERN_ERR PFX - "unable to get memory for graphics translation table.\n"); + dev_err(&bridge->dev->dev, + "can't get memory for graphics translation table\n"); rc = -ENOMEM; goto err_out; } @@ -169,7 +170,8 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) bridge->key_list = vmalloc(PAGE_SIZE * 4); if (bridge->key_list == NULL) { - printk(KERN_ERR PFX "error allocating memory for key lists.\n"); + dev_err(&bridge->dev->dev, + "can't allocate memory for key lists\n"); rc = -ENOMEM; goto err_out; } @@ -179,10 +181,12 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) memset(bridge->key_list, 0, PAGE_SIZE * 4); if (bridge->driver->configure()) { - printk(KERN_ERR PFX "error configuring host chipset.\n"); + dev_err(&bridge->dev->dev, "error configuring host chipset\n"); rc = -EINVAL; goto err_out; } + INIT_LIST_HEAD(&bridge->mapped_list); + spin_lock_init(&bridge->mapped_lock); return 0; @@ -269,25 +273,27 @@ int agp_add_bridge(struct agp_bridge_data *bridge) /* Grab reference on the chipset driver. */ if (!try_module_get(bridge->driver->owner)) { - printk (KERN_INFO PFX "Couldn't lock chipset driver.\n"); + dev_info(&bridge->dev->dev, "can't lock chipset driver\n"); return -EINVAL; } error = agp_backend_initialize(bridge); if (error) { - printk (KERN_INFO PFX "agp_backend_initialize() failed.\n"); + dev_info(&bridge->dev->dev, + "agp_backend_initialize() failed\n"); goto err_out; } if (list_empty(&agp_bridges)) { error = agp_frontend_initialize(); if (error) { - printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n"); + dev_info(&bridge->dev->dev, + "agp_frontend_initialize() failed\n"); goto frontend_err; } - printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n", - bridge->driver->fetch_size(), bridge->gart_bus_addr); + dev_info(&bridge->dev->dev, "AGP aperture is %dM @ 0x%lx\n", + bridge->driver->fetch_size(), bridge->gart_bus_addr); } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index eaa1a35..118dbde 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -429,6 +429,10 @@ int agp_bind_memory(struct agp_memory *curr, off_t pg_start) curr->is_bound = true; curr->pg_start = pg_start; + spin_lock(&agp_bridge->mapped_lock); + list_add(&curr->mapped_list, &agp_bridge->mapped_list); + spin_unlock(&agp_bridge->mapped_lock); + return 0; } EXPORT_SYMBOL(agp_bind_memory); @@ -461,10 +465,34 @@ int agp_unbind_memory(struct agp_memory *curr) curr->is_bound = false; curr->pg_start = 0; + spin_lock(&curr->bridge->mapped_lock); + list_del(&curr->mapped_list); + spin_unlock(&curr->bridge->mapped_lock); return 0; } EXPORT_SYMBOL(agp_unbind_memory); +/** + * agp_rebind_emmory - Rewrite the entire GATT, useful on resume + */ +int agp_rebind_memory(void) +{ + struct agp_memory *curr; + int ret_val = 0; + + spin_lock(&agp_bridge->mapped_lock); + list_for_each_entry(curr, &agp_bridge->mapped_list, mapped_list) { + ret_val = curr->bridge->driver->insert_memory(curr, + curr->pg_start, + curr->type); + if (ret_val != 0) + break; + } + spin_unlock(&agp_bridge->mapped_lock); + return ret_val; +} +EXPORT_SYMBOL(agp_rebind_memory); + /* End - Routines for handling swapping of agp_memory into the GATT */ @@ -771,8 +799,8 @@ void agp_device_command(u32 bridge_agpstat, bool agp_v3) if (!agp) continue; - printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n", - agp_v3 ? 3 : 2, pci_name(device), mode); + dev_info(&device->dev, "putting AGP V%d device into %dx mode\n", + agp_v3 ? 3 : 2, mode); pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat); } } @@ -800,10 +828,8 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) get_agp_version(agp_bridge); - printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", - agp_bridge->major_version, - agp_bridge->minor_version, - pci_name(agp_bridge->dev)); + dev_info(&agp_bridge->dev->dev, "AGP %d.%d bridge\n", + agp_bridge->major_version, agp_bridge->minor_version); pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat); @@ -832,8 +858,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) pci_write_config_dword(bridge->dev, bridge->capndx+AGPCTRL, temp); - printk(KERN_INFO PFX "Device is in legacy mode," - " falling back to 2.x\n"); + dev_info(&bridge->dev->dev, "bridge is in legacy mode, falling back to 2.x\n"); } } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index df70264..016fdf0 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -32,8 +32,8 @@ #define PCI_DEVICE_ID_INTEL_Q35_IG 0x29B2 #define PCI_DEVICE_ID_INTEL_Q33_HB 0x29D0 #define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2 -#define PCI_DEVICE_ID_INTEL_IGD_HB 0x2A40 -#define PCI_DEVICE_ID_INTEL_IGD_IG 0x2A42 +#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40 +#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42 #define PCI_DEVICE_ID_INTEL_IGD_E_HB 0x2E00 #define PCI_DEVICE_ID_INTEL_IGD_E_IG 0x2E02 #define PCI_DEVICE_ID_INTEL_Q45_HB 0x2E10 @@ -55,7 +55,7 @@ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GM_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965GME_HB || \ - agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_HB) + agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_GM45_HB) #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ @@ -161,7 +161,7 @@ static int intel_i810_fetch_size(void) values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes); if ((smram_miscc & I810_GMS) == I810_GMS_DISABLE) { - printk(KERN_WARNING PFX "i810 is disabled\n"); + dev_warn(&agp_bridge->dev->dev, "i810 is disabled\n"); return 0; } if ((smram_miscc & I810_GFX_MEM_WIN_SIZE) == I810_GFX_MEM_WIN_32M) { @@ -193,7 +193,8 @@ static int intel_i810_configure(void) intel_private.registers = ioremap(temp, 128 * 4096); if (!intel_private.registers) { - printk(KERN_ERR PFX "Unable to remap memory.\n"); + dev_err(&intel_private.pcidev->dev, + "can't remap memory\n"); return -ENOMEM; } } @@ -201,7 +202,8 @@ static int intel_i810_configure(void) if ((readl(intel_private.registers+I810_DRAM_CTL) & I810_DRAM_ROW_0) == I810_DRAM_ROW_0_SDRAM) { /* This will need to be dynamically assigned */ - printk(KERN_INFO PFX "detected 4MB dedicated video ram.\n"); + dev_info(&intel_private.pcidev->dev, + "detected 4MB dedicated video ram\n"); intel_private.num_dcache_entries = 1024; } pci_read_config_dword(intel_private.pcidev, I810_GMADDR, &temp); @@ -500,8 +502,8 @@ static void intel_i830_init_gtt_entries(void) size = 1024 + 512; break; default: - printk(KERN_INFO PFX "Unknown page table size, " - "assuming 512KB\n"); + dev_info(&intel_private.pcidev->dev, + "unknown page table size, assuming 512KB\n"); size = 512; } size += 4; /* add in BIOS popup space */ @@ -515,8 +517,8 @@ static void intel_i830_init_gtt_entries(void) size = 2048; break; default: - printk(KERN_INFO PFX "Unknown page table size 0x%x, " - "assuming 512KB\n", + dev_info(&agp_bridge->dev->dev, + "unknown page table size 0x%x, assuming 512KB\n", (gmch_ctrl & G33_PGETBL_SIZE_MASK)); size = 512; } @@ -627,11 +629,11 @@ static void intel_i830_init_gtt_entries(void) } } if (gtt_entries > 0) - printk(KERN_INFO PFX "Detected %dK %s memory.\n", + dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", gtt_entries / KB(1), local ? "local" : "stolen"); else - printk(KERN_INFO PFX - "No pre-allocated video memory detected.\n"); + dev_info(&agp_bridge->dev->dev, + "no pre-allocated video memory detected\n"); gtt_entries /= KB(4); intel_private.gtt_entries = gtt_entries; @@ -801,10 +803,12 @@ static int intel_i830_insert_entries(struct agp_memory *mem, off_t pg_start, num_entries = A_SIZE_FIX(temp)->num_entries; if (pg_start < intel_private.gtt_entries) { - printk(KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n", - pg_start, intel_private.gtt_entries); + dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, + "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", + pg_start, intel_private.gtt_entries); - printk(KERN_INFO PFX "Trying to insert into local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to insert into local/stolen memory\n"); goto out_err; } @@ -851,7 +855,8 @@ static int intel_i830_remove_entries(struct agp_memory *mem, off_t pg_start, return 0; if (pg_start < intel_private.gtt_entries) { - printk(KERN_INFO PFX "Trying to disable local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to disable local/stolen memory\n"); return -EINVAL; } @@ -957,7 +962,7 @@ static void intel_i9xx_setup_flush(void) if (intel_private.ifp_resource.start) { intel_private.i9xx_flush_page = ioremap_nocache(intel_private.ifp_resource.start, PAGE_SIZE); if (!intel_private.i9xx_flush_page) - printk(KERN_INFO "unable to ioremap flush page - no chipset flushing"); + dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing"); } } @@ -1028,10 +1033,12 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start, num_entries = A_SIZE_FIX(temp)->num_entries; if (pg_start < intel_private.gtt_entries) { - printk(KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_private.gtt_entries == 0x%.8x\n", - pg_start, intel_private.gtt_entries); + dev_printk(KERN_DEBUG, &intel_private.pcidev->dev, + "pg_start == 0x%.8lx, intel_private.gtt_entries == 0x%.8x\n", + pg_start, intel_private.gtt_entries); - printk(KERN_INFO PFX "Trying to insert into local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to insert into local/stolen memory\n"); goto out_err; } @@ -1078,7 +1085,8 @@ static int intel_i915_remove_entries(struct agp_memory *mem, off_t pg_start, return 0; if (pg_start < intel_private.gtt_entries) { - printk(KERN_INFO PFX "Trying to disable local/stolen memory\n"); + dev_info(&intel_private.pcidev->dev, + "trying to disable local/stolen memory\n"); return -EINVAL; } @@ -1182,7 +1190,7 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge, static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size) { switch (agp_bridge->dev->device) { - case PCI_DEVICE_ID_INTEL_IGD_HB: + case PCI_DEVICE_ID_INTEL_GM45_HB: case PCI_DEVICE_ID_INTEL_IGD_E_HB: case PCI_DEVICE_ID_INTEL_Q45_HB: case PCI_DEVICE_ID_INTEL_G45_HB: @@ -1379,7 +1387,7 @@ static int intel_815_configure(void) /* the Intel 815 chipset spec. says that bits 29-31 in the * ATTBASE register are reserved -> try not to write them */ if (agp_bridge->gatt_bus_addr & INTEL_815_ATTBASE_MASK) { - printk(KERN_EMERG PFX "gatt bus addr too high"); + dev_emerg(&agp_bridge->dev->dev, "gatt bus addr too high"); return -EINVAL; } @@ -2117,8 +2125,8 @@ static const struct intel_driver_description { NULL, &intel_g33_driver }, { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", NULL, &intel_g33_driver }, - { PCI_DEVICE_ID_INTEL_IGD_HB, PCI_DEVICE_ID_INTEL_IGD_IG, 0, - "Intel Integrated Graphics Device", NULL, &intel_i965_driver }, + { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, + "Mobile Intel? GM45 Express", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, "Intel Integrated Graphics Device", NULL, &intel_i965_driver }, { PCI_DEVICE_ID_INTEL_Q45_HB, PCI_DEVICE_ID_INTEL_Q45_IG, 0, @@ -2163,8 +2171,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, if (intel_agp_chipsets[i].name == NULL) { if (cap_ptr) - printk(KERN_WARNING PFX "Unsupported Intel chipset" - "(device id: %04x)\n", pdev->device); + dev_warn(&pdev->dev, "unsupported Intel chipset [%04x/%04x]\n", + pdev->vendor, pdev->device); agp_put_bridge(bridge); return -ENODEV; } @@ -2172,9 +2180,8 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, if (bridge->driver == NULL) { /* bridge has no AGP and no IGD detected */ if (cap_ptr) - printk(KERN_WARNING PFX "Failed to find bridge device " - "(chip_id: %04x)\n", - intel_agp_chipsets[i].gmch_chip_id); + dev_warn(&pdev->dev, "can't find bridge device (chip_id: %04x)\n", + intel_agp_chipsets[i].gmch_chip_id); agp_put_bridge(bridge); return -ENODEV; } @@ -2183,8 +2190,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, bridge->capndx = cap_ptr; bridge->dev_private_data = &intel_private; - printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", - intel_agp_chipsets[i].name); + dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name); /* * The following fixes the case where the BIOS has "forgotten" to @@ -2194,7 +2200,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, r = &pdev->resource[0]; if (!r->start && r->end) { if (pci_assign_resource(pdev, 0)) { - printk(KERN_ERR PFX "could not assign resource 0\n"); + dev_err(&pdev->dev, "can't assign resource 0\n"); agp_put_bridge(bridge); return -ENODEV; } @@ -2206,7 +2212,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, * 20030610 - hamish@zot.org */ if (pci_enable_device(pdev)) { - printk(KERN_ERR PFX "Unable to Enable PCI device\n"); + dev_err(&pdev->dev, "can't enable PCI device\n"); agp_put_bridge(bridge); return -ENODEV; } @@ -2238,6 +2244,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev) static int agp_intel_resume(struct pci_dev *pdev) { struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + int ret_val; pci_restore_state(pdev); @@ -2265,6 +2272,10 @@ static int agp_intel_resume(struct pci_dev *pdev) else if (bridge->driver == &intel_i965_driver) intel_i915_configure(); + ret_val = agp_rebind_memory(); + if (ret_val != 0) + return ret_val; + return 0; } #endif @@ -2315,7 +2326,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_G33_HB), ID(PCI_DEVICE_ID_INTEL_Q35_HB), ID(PCI_DEVICE_ID_INTEL_Q33_HB), - ID(PCI_DEVICE_ID_INTEL_IGD_HB), + ID(PCI_DEVICE_ID_INTEL_GM45_HB), ID(PCI_DEVICE_ID_INTEL_IGD_E_HB), ID(PCI_DEVICE_ID_INTEL_Q45_HB), ID(PCI_DEVICE_ID_INTEL_G45_HB), diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c index 3f9ccde..c73385c 100644 --- a/drivers/char/agp/isoch.c +++ b/drivers/char/agp/isoch.c @@ -153,7 +153,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, /* Check if this configuration has any chance of working */ if (tot_bw > target.maxbw) { - printk(KERN_ERR PFX "isochronous bandwidth required " + dev_err(&td->dev, "isochronous bandwidth required " "by AGP 3.0 devices exceeds that which is supported by " "the AGP 3.0 bridge!\n"); ret = -ENODEV; @@ -188,7 +188,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, /* Exit if the minimal ISOCH_N allocation among the masters is more * than the target can handle. */ if (tot_n > target.n) { - printk(KERN_ERR PFX "number of isochronous " + dev_err(&td->dev, "number of isochronous " "transactions per period required by AGP 3.0 devices " "exceeds that which is supported by the AGP 3.0 " "bridge!\n"); @@ -229,7 +229,7 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge, /* Exit if the minimal RQ needs of the masters exceeds what the target * can provide. */ if (tot_rq > rq_isoch) { - printk(KERN_ERR PFX "number of request queue slots " + dev_err(&td->dev, "number of request queue slots " "required by the isochronous bandwidth requested by " "AGP 3.0 devices exceeds the number provided by the " "AGP 3.0 bridge!\n"); @@ -359,8 +359,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) case 0x0001: /* Unclassified device */ /* Don't know what this is, but log it for investigation. */ if (mcapndx != 0) { - printk (KERN_INFO PFX "Wacky, found unclassified AGP device. %x:%x\n", - dev->vendor, dev->device); + dev_info(&td->dev, "wacky, found unclassified AGP device %s [%04x/%04x]\n", + pci_name(dev), + dev->vendor, dev->device); } continue; @@ -407,17 +408,18 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) } if (mcapndx == 0) { - printk(KERN_ERR PFX "woah! Non-AGP device " - "found on the secondary bus of an AGP 3.5 bridge!\n"); + dev_err(&td->dev, "woah! Non-AGP device %s on " + "secondary bus of AGP 3.5 bridge!\n", + pci_name(dev)); ret = -ENODEV; goto free_and_exit; } mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; if (mmajor < 3) { - printk(KERN_ERR PFX "woah! AGP 2.0 device " - "found on the secondary bus of an AGP 3.5 " - "bridge operating with AGP 3.0 electricals!\n"); + dev_err(&td->dev, "woah! AGP 2.0 device %s on " + "secondary bus of AGP 3.5 bridge operating " + "with AGP 3.0 electricals!\n", pci_name(dev)); ret = -ENODEV; goto free_and_exit; } @@ -427,10 +429,10 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) pci_read_config_dword(dev, cur->capndx+AGPSTAT, &mstatus); if (((mstatus >> 3) & 0x1) == 0) { - printk(KERN_ERR PFX "woah! AGP 3.x device " - "not operating in AGP 3.x mode found on the " - "secondary bus of an AGP 3.5 bridge operating " - "with AGP 3.0 electricals!\n"); + dev_err(&td->dev, "woah! AGP 3.x device %s not " + "operating in AGP 3.x mode on secondary bus " + "of AGP 3.5 bridge operating with AGP 3.0 " + "electricals!\n", pci_name(dev)); ret = -ENODEV; goto free_and_exit; } @@ -444,9 +446,9 @@ int agp_3_5_enable(struct agp_bridge_data *bridge) if (isoch) { ret = agp_3_5_isochronous_node_enable(bridge, dev_list, ndevs); if (ret) { - printk(KERN_INFO PFX "Something bad happened setting " - "up isochronous xfers. Falling back to " - "non-isochronous xfer mode.\n"); + dev_info(&td->dev, "something bad happened setting " + "up isochronous xfers; falling back to " + "non-isochronous xfer mode\n"); } else { goto free_and_exit; } @@ -466,4 +468,3 @@ free_and_exit: get_out: return ret; } - diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index b679184..2587ef9 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c @@ -79,10 +79,8 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) u32 command; int rate; - printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n", - agp_bridge->major_version, - agp_bridge->minor_version, - pci_name(agp_bridge->dev)); + dev_info(&agp_bridge->dev->dev, "AGP %d.%d bridge\n", + agp_bridge->major_version, agp_bridge->minor_version); pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command); command = agp_collect_device_status(bridge, mode, command); @@ -94,8 +92,8 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) if (!agp) continue; - printk(KERN_INFO PFX "Putting AGP V3 device at %s into %dx mode\n", - pci_name(device), rate); + dev_info(&agp_bridge->dev->dev, "putting AGP V3 device at %s into %dx mode\n", + pci_name(device), rate); pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command); @@ -105,7 +103,7 @@ static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode) * cannot be configured */ if (device->device == bridge->dev->device) { - printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n"); + dev_info(&agp_bridge->dev->dev, "SiS delay workaround: giving bridge time to recover\n"); msleep(10); } } @@ -190,7 +188,8 @@ static int __devinit agp_sis_probe(struct pci_dev *pdev, return -ENODEV; - printk(KERN_INFO PFX "Detected SiS chipset - id:%i\n", pdev->device); + dev_info(&pdev->dev, "SiS chipset [%04x/%04x]\n", + pdev->vendor, pdev->device); bridge = agp_alloc_bridge(); if (!bridge) return -ENOMEM; @@ -242,7 +241,7 @@ static struct pci_device_id agp_sis_pci_table[] = { .class = (PCI_CLASS_BRIDGE_HOST << 8), .class_mask = ~0, .vendor = PCI_VENDOR_ID_SI, - .device = PCI_DEVICE_ID_SI_5591_AGP, + .device = PCI_DEVICE_ID_SI_5591, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 0e054c1..2fb27fe 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c @@ -241,7 +241,8 @@ static void serverworks_tlbflush(struct agp_memory *temp) while (readb(serverworks_private.registers+SVWRKS_POSTFLUSH) == 1) { cpu_relax(); if (time_after(jiffies, timeout)) { - printk(KERN_ERR PFX "TLB post flush took more than 3 seconds\n"); + dev_err(&serverworks_private.svrwrks_dev->dev, + "TLB post flush took more than 3 seconds\n"); break; } } @@ -251,7 +252,8 @@ static void serverworks_tlbflush(struct agp_memory *temp) while (readl(serverworks_private.registers+SVWRKS_DIRFLUSH) == 1) { cpu_relax(); if (time_after(jiffies, timeout)) { - printk(KERN_ERR PFX "TLB Dir flush took more than 3 seconds\n"); + dev_err(&serverworks_private.svrwrks_dev->dev, + "TLB Dir flush took more than 3 seconds\n"); break; } } @@ -271,7 +273,7 @@ static int serverworks_configure(void) temp = (temp & PCI_BASE_ADDRESS_MEM_MASK); serverworks_private.registers = (volatile u8 __iomem *) ioremap(temp, 4096); if (!serverworks_private.registers) { - printk (KERN_ERR PFX "Unable to ioremap() memory.\n"); + dev_err(&agp_bridge->dev->dev, "can't ioremap(%#x)\n", temp); return -ENOMEM; } @@ -451,7 +453,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, switch (pdev->device) { case 0x0006: - printk (KERN_ERR PFX "ServerWorks CNB20HE is unsupported due to lack of documentation.\n"); + dev_err(&pdev->dev, "ServerWorks CNB20HE is unsupported due to lack of documentation\n"); return -ENODEV; case PCI_DEVICE_ID_SERVERWORKS_HE: @@ -461,8 +463,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, default: if (cap_ptr) - printk(KERN_ERR PFX "Unsupported Serverworks chipset " - "(device id: %04x)\n", pdev->device); + dev_err(&pdev->dev, "unsupported Serverworks chipset " + "[%04x/%04x]\n", pdev->vendor, pdev->device); return -ENODEV; } @@ -470,8 +472,7 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, bridge_dev = pci_get_bus_and_slot((unsigned int)pdev->bus->number, PCI_DEVFN(0, 1)); if (!bridge_dev) { - printk(KERN_INFO PFX "Detected a Serverworks chipset " - "but could not find the secondary device.\n"); + dev_info(&pdev->dev, "can't find secondary device\n"); return -ENODEV; } @@ -482,8 +483,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, if (temp & PCI_BASE_ADDRESS_MEM_TYPE_64) { pci_read_config_dword(pdev, SVWRKS_APSIZE + 4, &temp2); if (temp2 != 0) { - printk(KERN_INFO PFX "Detected 64 bit aperture address, " - "but top bits are not zero. Disabling agp\n"); + dev_info(&pdev->dev, "64 bit aperture address, " + "but top bits are not zero; disabling AGP\n"); return -ENODEV; } serverworks_private.mm_addr_ofs = 0x18; @@ -495,8 +496,8 @@ static int __devinit agp_serverworks_probe(struct pci_dev *pdev, pci_read_config_dword(pdev, serverworks_private.mm_addr_ofs + 4, &temp2); if (temp2 != 0) { - printk(KERN_INFO PFX "Detected 64 bit MMIO address, " - "but top bits are not zero. Disabling agp\n"); + dev_info(&pdev->dev, "64 bit MMIO address, but top " + "bits are not zero; disabling AGP\n"); return -ENODEV; } } diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index d2fa3cf..eef7270 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c @@ -46,8 +46,8 @@ static int uninorth_fetch_size(void) break; if (i == agp_bridge->driver->num_aperture_sizes) { - printk(KERN_ERR PFX "Invalid aperture size, using" - " default\n"); + dev_err(&agp_bridge->dev->dev, "invalid aperture size, " + "using default\n"); size = 0; aperture = NULL; } @@ -108,8 +108,8 @@ static int uninorth_configure(void) current_size = A_SIZE_32(agp_bridge->current_size); - printk(KERN_INFO PFX "configuring for size idx: %d\n", - current_size->size_value); + dev_info(&agp_bridge->dev->dev, "configuring for size idx: %d\n", + current_size->size_value); /* aperture size and gatt addr */ pci_write_config_dword(agp_bridge->dev, @@ -197,8 +197,9 @@ static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type) gp = (u32 *) &agp_bridge->gatt_table[pg_start]; for (i = 0; i < mem->page_count; ++i) { if (gp[i]) { - printk("u3_insert_memory: entry 0x%x occupied (%x)\n", - i, gp[i]); + dev_info(&agp_bridge->dev->dev, + "u3_insert_memory: entry 0x%x occupied (%x)\n", + i, gp[i]); return -EBUSY; } } @@ -276,8 +277,8 @@ static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode) &scratch); } while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000); if ((scratch & PCI_AGP_COMMAND_AGP) == 0) - printk(KERN_ERR PFX "failed to write UniNorth AGP" - " command register\n"); + dev_err(&bridge->dev->dev, "can't write UniNorth AGP " + "command register\n"); if (uninorth_rev >= 0x30) { /* This is an AGP V3 */ @@ -330,8 +331,8 @@ static int agp_uninorth_suspend(struct pci_dev *pdev) pci_read_config_dword(device, agp + PCI_AGP_COMMAND, &cmd); if (!(cmd & PCI_AGP_COMMAND_AGP)) continue; - printk("uninorth-agp: disabling AGP on device %s\n", - pci_name(device)); + dev_info(&pdev->dev, "disabling AGP on device %s\n", + pci_name(device)); cmd &= ~PCI_AGP_COMMAND_AGP; pci_write_config_dword(device, agp + PCI_AGP_COMMAND, cmd); } @@ -341,8 +342,7 @@ static int agp_uninorth_suspend(struct pci_dev *pdev) pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd); bridge->dev_private_data = (void *)(long)cmd; if (cmd & PCI_AGP_COMMAND_AGP) { - printk("uninorth-agp: disabling AGP on bridge %s\n", - pci_name(pdev)); + dev_info(&pdev->dev, "disabling AGP on bridge\n"); cmd &= ~PCI_AGP_COMMAND_AGP; pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND, cmd); } @@ -591,14 +591,14 @@ static int __devinit agp_uninorth_probe(struct pci_dev *pdev, /* probe for known chipsets */ for (j = 0; devs[j].chipset_name != NULL; ++j) { if (pdev->device == devs[j].device_id) { - printk(KERN_INFO PFX "Detected Apple %s chipset\n", - devs[j].chipset_name); + dev_info(&pdev->dev, "Apple %s chipset\n", + devs[j].chipset_name); goto found; } } - printk(KERN_ERR PFX "Unsupported Apple chipset (device id: %04x).\n", - pdev->device); + dev_err(&pdev->dev, "unsupported Apple chipset [%04x/%04x]\n", + pdev->vendor, pdev->device); return -ENODEV; found: diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 37457e5..6e763e3 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1248,13 +1248,13 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, /* * rs_break() --- routine which turns the break handling on or off */ -static void rs_break(struct tty_struct *tty, int break_state) +static int rs_break(struct tty_struct *tty, int break_state) { struct async_struct * info = (struct async_struct *)tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "rs_break")) - return; + return -EINVAL; local_irq_save(flags); if (break_state == -1) @@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state) custom.adkcon = AC_UARTBRK; mb(); local_irq_restore(flags); + return 0; } diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index e991dc8..fe6d774 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, /* * cy_break() --- routine which turns the break handling on or off */ -static void cy_break(struct tty_struct *tty, int break_state) +static int cy_break(struct tty_struct *tty, int break_state) { struct cyclades_port *info = tty->driver_data; struct cyclades_card *card; unsigned long flags; + int retval = 0; if (serial_paranoia_check(info, tty->name, "cy_break")) - return; + return -EINVAL; card = info->card; @@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state) } } } else { - int retval; - if (break_state == -1) { retval = cyz_issue_cmd(card, info->line - card->first_line, @@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state) } } spin_unlock_irqrestore(&card->card_lock, flags); + return retval; } /* cy_break */ static int get_mon_info(struct cyclades_port *info, diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index fada6dd..c5e67a6 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c @@ -20,10 +20,11 @@ #include <linux/miscdevice.h> #include <linux/delay.h> #include <linux/bcd.h> +#include <linux/smp_lock.h> +#include <linux/uaccess.h> +#include <linux/io.h> -#include <asm/uaccess.h> #include <asm/system.h> -#include <asm/io.h> #include <asm/rtc.h> #if defined(CONFIG_M32R) #include <asm/m32r.h> @@ -153,9 +154,7 @@ static unsigned char days_in_mo[] = /* ioctl that supports RTC_RD_TIME and RTC_SET_TIME (read and set time/date). */ -static int -rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { unsigned long flags; @@ -165,7 +164,9 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, struct rtc_time rtc_tm; memset(&rtc_tm, 0, sizeof (struct rtc_time)); + lock_kernel(); get_rtc_time(&rtc_tm); + unlock_kernel(); if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time))) return -EFAULT; return 0; @@ -217,6 +218,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, BIN_TO_BCD(mon); BIN_TO_BCD(yrs); + lock_kernel(); local_irq_save(flags); CMOS_WRITE(yrs, RTC_YEAR); CMOS_WRITE(mon, RTC_MONTH); @@ -225,6 +227,7 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, CMOS_WRITE(min, RTC_MINUTES); CMOS_WRITE(sec, RTC_SECONDS); local_irq_restore(flags); + unlock_kernel(); /* Notice that at this point, the RTC is updated but * the kernel is still running with the old time. @@ -244,8 +247,10 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if(copy_from_user(&tcs_val, (int*)arg, sizeof(int))) return -EFAULT; + lock_kernel(); tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F); ds1302_writereg(RTC_TRICKLECHARGER, tcs_val); + unlock_kernel(); return 0; } default: @@ -282,7 +287,7 @@ get_rtc_status(char *buf) static const struct file_operations rtc_fops = { .owner = THIS_MODULE, - .ioctl = rtc_ioctl, + .unlocked_ioctl = rtc_ioctl, }; /* Probe for the chip by writing something to its RAM and try reading it back. */ diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 34275c6..74e9cd8 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c @@ -10,7 +10,7 @@ #include <linux/init.h> #include <linux/smp_lock.h> -#include <asm/hardware.h> +#include <mach/hardware.h> #include <asm/mach-types.h> #include <asm/uaccess.h> #include <asm/therm.h> diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c index b9a30c3..ca7c72a 100644 --- a/drivers/char/dsp56k.c +++ b/drivers/char/dsp56k.c @@ -36,10 +36,10 @@ #include <linux/smp_lock.h> #include <linux/firmware.h> #include <linux/platform_device.h> +#include <linux/uaccess.h> /* For put_user and get_user */ #include <asm/atarihw.h> #include <asm/traps.h> -#include <asm/uaccess.h> /* For put_user and get_user */ #include <asm/dsp56k.h> @@ -303,10 +303,10 @@ static ssize_t dsp56k_write(struct file *file, const char __user *buf, size_t co } } -static int dsp56k_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static long dsp56k_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { - int dev = iminor(inode) & 0x0f; + int dev = iminor(file->f_path.dentry->d_inode) & 0x0f; void __user *argp = (void __user *)arg; switch(dev) @@ -331,8 +331,9 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, if (len > DSP56K_MAX_BINARY_LENGTH) { return -EINVAL; } - + lock_kernel(); r = dsp56k_upload(bin, len); + unlock_kernel(); if (r < 0) { return r; } @@ -342,12 +343,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, case DSP56K_SET_TX_WSIZE: if (arg > 4 || arg < 1) return -EINVAL; + lock_kernel(); dsp56k.tx_wsize = (int) arg; + unlock_kernel(); break; case DSP56K_SET_RX_WSIZE: if (arg > 4 || arg < 1) return -EINVAL; + lock_kernel(); dsp56k.rx_wsize = (int) arg; + unlock_kernel(); break; case DSP56K_HOST_FLAGS: { @@ -359,6 +364,7 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, if(get_user(out, &hf->out) < 0) return -EFAULT; + lock_kernel(); if ((dir & 0x1) && (out & 0x1)) dsp56k_host_interface.icr |= DSP56K_ICR_HF0; else if (dir & 0x1) @@ -373,14 +379,16 @@ static int dsp56k_ioctl(struct inode *inode, struct file *file, if (dsp56k_host_interface.icr & DSP56K_ICR_HF1) status |= 0x2; if (dsp56k_host_interface.isr & DSP56K_ISR_HF2) status |= 0x4; if (dsp56k_host_interface.isr & DSP56K_ISR_HF3) status |= 0x8; - + unlock_kernel(); return put_user(status, &hf->status); } case DSP56K_HOST_CMD: if (arg > 31 || arg < 0) return -EINVAL; + lock_kernel(); dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) | DSP56K_CVR_HC); + unlock_kernel(); break; default: return -EINVAL; @@ -472,7 +480,7 @@ static const struct file_operations dsp56k_fops = { .owner = THIS_MODULE, .read = dsp56k_read, .write = dsp56k_write, - .ioctl = dsp56k_ioctl, + .unlocked_ioctl = dsp56k_ioctl, .open = dsp56k_open, .release = dsp56k_release, }; @@ -500,7 +508,8 @@ static int __init dsp56k_init_driver(void) err = PTR_ERR(dsp56k_class); goto out_chrdev; } - device_create(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), "dsp56k"); + device_create_drvdata(dsp56k_class, NULL, MKDEV(DSP56K_MAJOR, 0), + NULL, "dsp56k"); printk(banner); goto out; diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index d57ca3e..34d15d5 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c @@ -37,8 +37,8 @@ #include <linux/rtc.h> #include <linux/proc_fs.h> #include <linux/efi.h> +#include <linux/uaccess.h> -#include <asm/uaccess.h> #include <asm/system.h> #define EFI_RTC_VERSION "0.4" @@ -51,8 +51,8 @@ static DEFINE_SPINLOCK(efi_rtc_lock); -static int efi_rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static long efi_rtc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg); #define is_leap(year) \ ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) @@ -146,9 +146,8 @@ convert_from_efi_time(efi_time_t *eft, struct rtc_time *wtime) } } -static int -efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long efi_rtc_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) { efi_status_t status; @@ -175,13 +174,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return -EINVAL; case RTC_RD_TIME: - + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); status = efi.get_time(&eft, &cap); spin_unlock_irqrestore(&efi_rtc_lock,flags); - + unlock_kernel(); if (status != EFI_SUCCESS) { /* should never happen */ printk(KERN_ERR "efitime: can't read time\n"); @@ -203,11 +202,13 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, convert_to_efi_time(&wtime, &eft); + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); status = efi.set_time(&eft); spin_unlock_irqrestore(&efi_rtc_lock,flags); + unlock_kernel(); return status == EFI_SUCCESS ? 0 : -EINVAL; @@ -223,6 +224,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, convert_to_efi_time(&wtime, &eft); + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); /* * XXX Fixme: @@ -233,16 +235,19 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, status = efi.set_wakeup_time((efi_bool_t)enabled, &eft); spin_unlock_irqrestore(&efi_rtc_lock,flags); + unlock_kernel(); return status == EFI_SUCCESS ? 0 : -EINVAL; case RTC_WKALM_RD: + lock_kernel(); spin_lock_irqsave(&efi_rtc_lock, flags); status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft); spin_unlock_irqrestore(&efi_rtc_lock,flags); + unlock_kernel(); if (status != EFI_SUCCESS) return -EINVAL; @@ -256,7 +261,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return copy_to_user(&ewp->time, &wtime, sizeof(struct rtc_time)) ? -EFAULT : 0; } - return -EINVAL; + return -ENOTTY; } /* @@ -265,8 +270,7 @@ efi_rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, * up things on a close. */ -static int -efi_rtc_open(struct inode *inode, struct file *file) +static int efi_rtc_open(struct inode *inode, struct file *file) { /* * nothing special to do here @@ -277,8 +281,7 @@ efi_rtc_open(struct inode *inode, struct file *file) return 0; } -static int -efi_rtc_close(struct inode *inode, struct file *file) +static int efi_rtc_close(struct inode *inode, struct file *file) { return 0; } @@ -289,13 +292,12 @@ efi_rtc_close(struct inode *inode, struct file *file) static const struct file_operations efi_rtc_fops = { .owner = THIS_MODULE, - .ioctl = efi_rtc_ioctl, + .unlocked_ioctl = efi_rtc_ioctl, .open = efi_rtc_open, .release = efi_rtc_close, }; -static struct miscdevice efi_rtc_dev= -{ +static struct miscdevice efi_rtc_dev= { EFI_RTC_MINOR, "efirtc", &efi_rtc_fops diff --git a/drivers/char/epca.c b/drivers/char/epca.c index ac9995f..456e4ed 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -184,9 +184,8 @@ static void pc_stop(struct tty_struct *); static void pc_start(struct tty_struct *); static void pc_throttle(struct tty_struct *tty); static void pc_unthrottle(struct tty_struct *tty); -static void digi_send_break(struct channel *ch, int msec); +static int pc_send_break(struct tty_struct *tty, int msec); static void setup_empty_event(struct tty_struct *tty, struct channel *ch); -static void epca_setup(char *, int *); static int pc_write(struct tty_struct *, const unsigned char *, int); static int pc_init(void); @@ -1040,6 +1039,7 @@ static const struct tty_operations pc_ops = { .throttle = pc_throttle, .unthrottle = pc_unthrottle, .hangup = pc_hangup, + .break_ctl = pc_send_break }; static int info_open(struct tty_struct *tty, struct file *filp) @@ -1132,7 +1132,7 @@ static int __init pc_init(void) pc_driver->init_termios.c_lflag = 0; pc_driver->init_termios.c_ispeed = 9600; pc_driver->init_termios.c_ospeed = 9600; - pc_driver->flags = TTY_DRIVER_REAL_RAW; + pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; tty_set_operations(pc_driver, &pc_ops); pc_info->owner = THIS_MODULE; @@ -2177,7 +2177,6 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { digiflow_t dflow; - int retval; unsigned long flags; unsigned int mflag, mstat; unsigned char startc, stopc; @@ -2189,37 +2188,7 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, bc = ch->brdchan; else return -EINVAL; - /* - * For POSIX compliance we need to add more ioctls. See tty_ioctl.c in - * /usr/src/linux/drivers/char for a good example. In particular think - * about adding TCSETAF, TCSETAW, TCSETA, TCSETSF, TCSETSW, TCSETS. - */ switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - /* Setup an event to indicate when the transmit - buffer empties */ - spin_lock_irqsave(&epca_lock, flags); - setup_empty_event(tty, ch); - spin_unlock_irqrestore(&epca_lock, flags); - tty_wait_until_sent(tty, 0); - if (!arg) - digi_send_break(ch, HZ / 4); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - /* Setup an event to indicate when the transmit buffer - empties */ - spin_lock_irqsave(&epca_lock, flags); - setup_empty_event(tty, ch); - spin_unlock_irqrestore(&epca_lock, flags); - tty_wait_until_sent(tty, 0); - digi_send_break(ch, arg ? arg*(HZ/10) : HZ/4); - return 0; case TIOCMODG: mflag = pc_tiocmget(tty, file); if (put_user(mflag, (unsigned long __user *)argp)) @@ -2505,10 +2474,14 @@ static void pc_unthrottle(struct tty_struct *tty) } } -static void digi_send_break(struct channel *ch, int msec) +static int pc_send_break(struct tty_struct *tty, int msec) { + struct channel *ch = (struct channel *) tty->driver_data; unsigned long flags; + if (msec == -1) + return -EOPNOTSUPP; + spin_lock_irqsave(&epca_lock, flags); globalwinon(ch); /* @@ -2521,6 +2494,7 @@ static void digi_send_break(struct channel *ch, int msec) fepcmd(ch, SENDBREAK, msec, 0, 10, 0); memoff(ch); spin_unlock_irqrestore(&epca_lock, flags); + return 0; } /* Caller MUST hold the lock */ @@ -2538,7 +2512,8 @@ static void setup_empty_event(struct tty_struct *tty, struct channel *ch) memoff(ch); } -static void epca_setup(char *str, int *ints) +#ifndef MODULE +static void __init epca_setup(char *str, int *ints) { struct board_info board; int index, loop, last; @@ -2792,6 +2767,17 @@ static void epca_setup(char *str, int *ints) num_cards++; } +static int __init epca_real_setup(char *str) +{ + int ints[11]; + + epca_setup(get_options(str, 11, ints), ints); + return 1; +} + +__setup("digiepca", epca_real_setup); +#endif + enum epic_board_types { brd_xr = 0, brd_xem, diff --git a/drivers/char/esp.c b/drivers/char/esp.c index 2eaf09f..7f077c0 100644 --- a/drivers/char/esp.c +++ b/drivers/char/esp.c @@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file, /* * rs_break() --- routine which turns the break handling on or off */ -static void esp_break(struct tty_struct *tty, int break_state) +static int esp_break(struct tty_struct *tty, int break_state) { struct esp_struct *info = tty->driver_data; unsigned long flags; if (serial_paranoia_check(info, tty->name, "esp_break")) - return; + return -EINVAL; if (break_state == -1) { spin_lock_irqsave(&info->lock, flags); @@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state) serial_out(info, UART_ESI_CMD2, 0x00); spin_unlock_irqrestore(&info->lock, flags); } + return 0; } static int rs_ioctl(struct tty_struct *tty, struct file *file, diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index fb0a85a..b3f5dbc 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -623,6 +623,7 @@ static inline int hpet_tpcheck(struct hpet_task *tp) return -ENXIO; } +#if 0 int hpet_unregister(struct hpet_task *tp) { struct hpet_dev *devp; @@ -652,6 +653,7 @@ int hpet_unregister(struct hpet_task *tp) return 0; } +#endif /* 0 */ static ctl_table hpet_table[] = { { diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index 2f9759d..fd64137 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c @@ -27,7 +27,6 @@ #include <linux/init.h> #include <linux/kbd_kern.h> #include <linux/kernel.h> -#include <linux/kref.h> #include <linux/kthread.h> #include <linux/list.h> #include <linux/module.h> @@ -75,23 +74,6 @@ static int hvc_init(void); static int sysrq_pressed; #endif -struct hvc_struct { - spinlock_t lock; - int index; - struct tty_struct *tty; - unsigned int count; - int do_wakeup; - char *outbuf; - int outbuf_size; - int n_outbuf; - uint32_t vtermno; - struct hv_ops *ops; - int irq_requested; - int irq; - struct list_head next; - struct kref kref; /* ref count & hvc_struct lifetime */ -}; - /* dynamic list of hvc_struct instances */ static LIST_HEAD(hvc_structs); @@ -298,27 +280,15 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops) return 0; } +EXPORT_SYMBOL_GPL(hvc_instantiate); /* Wake the sleeping khvcd */ -static void hvc_kick(void) +void hvc_kick(void) { hvc_kicked = 1; wake_up_process(hvc_task); } - -static int hvc_poll(struct hvc_struct *hp); - -/* - * NOTE: This API isn't used if the console adapter doesn't support interrupts. - * In this case the console is poll driven. - */ -static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) -{ - /* if hvc_poll request a repoll, then kick the hvcd thread */ - if (hvc_poll(dev_instance)) - hvc_kick(); - return IRQ_HANDLED; -} +EXPORT_SYMBOL_GPL(hvc_kick); static void hvc_unthrottle(struct tty_struct *tty) { @@ -333,7 +303,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) { struct hvc_struct *hp; unsigned long flags; - int irq = 0; int rc = 0; /* Auto increments kref reference if found. */ @@ -352,18 +321,14 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) tty->low_latency = 1; /* Makes flushes to ldisc synchronous. */ hp->tty = tty; - /* Save for request_irq outside of spin_lock. */ - irq = hp->irq; - if (irq) - hp->irq_requested = 1; spin_unlock_irqrestore(&hp->lock, flags); - /* check error, fallback to non-irq */ - if (irq) - rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp); + + if (hp->ops->notifier_add) + rc = hp->ops->notifier_add(hp, hp->data); /* - * If the request_irq() fails and we return an error. The tty layer + * If the notifier fails we return an error. The tty layer * will call hvc_close() after a failed open but we don't want to clean * up there so we'll clean up here and clear out the previously set * tty fields and return the kref reference. @@ -371,7 +336,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) if (rc) { spin_lock_irqsave(&hp->lock, flags); hp->tty = NULL; - hp->irq_requested = 0; spin_unlock_irqrestore(&hp->lock, flags); tty->driver_data = NULL; kref_put(&hp->kref, destroy_hvc_struct); @@ -386,7 +350,6 @@ static int hvc_open(struct tty_struct *tty, struct file * filp) static void hvc_close(struct tty_struct *tty, struct file * filp) { struct hvc_struct *hp; - int irq = 0; unsigned long flags; if (tty_hung_up_p(filp)) @@ -404,9 +367,8 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) spin_lock_irqsave(&hp->lock, flags); if (--hp->count == 0) { - if (hp->irq_requested) - irq = hp->irq; - hp->irq_requested = 0; + if (hp->ops->notifier_del) + hp->ops->notifier_del(hp, hp->data); /* We are done with the tty pointer now. */ hp->tty = NULL; @@ -418,10 +380,6 @@ static void hvc_close(struct tty_struct *tty, struct file * filp) * waking periodically to check chars_in_buffer(). */ tty_wait_until_sent(tty, HVC_CLOSE_WAIT); - - if (irq) - free_irq(irq, hp); - } else { if (hp->count < 0) printk(KERN_ERR "hvc_close %X: oops, count is %d\n", @@ -436,7 +394,6 @@ static void hvc_hangup(struct tty_struct *tty) { struct hvc_struct *hp = tty->driver_data; unsigned long flags; - int irq = 0; int temp_open_count; if (!hp) @@ -458,13 +415,12 @@ static void hvc_hangup(struct tty_struct *tty) hp->count = 0; hp->n_outbuf = 0; hp->tty = NULL; - if (hp->irq_requested) - /* Saved for use outside of spin_lock. */ - irq = hp->irq; - hp->irq_requested = 0; + + if (hp->ops->notifier_del) + hp->ops->notifier_del(hp, hp->data); + spin_unlock_irqrestore(&hp->lock, flags); - if (irq) - free_irq(irq, hp); + while(temp_open_count) { --temp_open_count; kref_put(&hp->kref, destroy_hvc_struct); @@ -575,7 +531,7 @@ static u32 timeout = MIN_TIMEOUT; #define HVC_POLL_READ 0x00000001 #define HVC_POLL_WRITE 0x00000002 -static int hvc_poll(struct hvc_struct *hp) +int hvc_poll(struct hvc_struct *hp) { struct tty_struct *tty; int i, n, poll_mask = 0; @@ -602,10 +558,10 @@ static int hvc_poll(struct hvc_struct *hp) if (test_bit(TTY_THROTTLED, &tty->flags)) goto throttled; - /* If we aren't interrupt driven and aren't throttled, we always + /* If we aren't notifier driven and aren't throttled, we always * request a reschedule */ - if (hp->irq == 0) + if (!hp->irq_requested) poll_mask |= HVC_POLL_READ; /* Read data if any */ @@ -674,6 +630,7 @@ static int hvc_poll(struct hvc_struct *hp) return poll_mask; } +EXPORT_SYMBOL_GPL(hvc_poll); /* * This kthread is either polling or interrupt driven. This is determined by @@ -733,7 +690,7 @@ static const struct tty_operations hvc_ops = { .chars_in_buffer = hvc_chars_in_buffer, }; -struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, +struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int data, struct hv_ops *ops, int outbuf_size) { struct hvc_struct *hp; @@ -754,7 +711,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, memset(hp, 0x00, sizeof(*hp)); hp->vtermno = vtermno; - hp->irq = irq; + hp->data = data; hp->ops = ops; hp->outbuf_size = outbuf_size; hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))]; @@ -784,6 +741,7 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq, return hp; } +EXPORT_SYMBOL_GPL(hvc_alloc); int __devexit hvc_remove(struct hvc_struct *hp) { diff --git a/drivers/char/hvc_console.h b/drivers/char/hvc_console.h index 42ffb17..9790201 100644 --- a/drivers/char/hvc_console.h +++ b/drivers/char/hvc_console.h @@ -6,7 +6,7 @@ * Ryan S. Arnold <rsa@us.ibm.com> * * hvc_console header information: - * moved here from include/asm-powerpc/hvconsole.h + * moved here from arch/powerpc/include/asm/hvconsole.h * and drivers/char/hvc_console.c * * This program is free software; you can redistribute it and/or modify @@ -26,6 +26,7 @@ #ifndef HVC_CONSOLE_H #define HVC_CONSOLE_H +#include <linux/kref.h> /* * This is the max number of console adapters that can/will be found as @@ -42,24 +43,50 @@ */ #define HVC_ALLOC_TTY_ADAPTERS 8 +struct hvc_struct { + spinlock_t lock; + int index; + struct tty_struct *tty; + unsigned int count; + int do_wakeup; + char *outbuf; + int outbuf_size; + int n_outbuf; + uint32_t vtermno; + struct hv_ops *ops; + int irq_requested; + int data; + struct list_head next; + struct kref kref; /* ref count & hvc_struct lifetime */ +}; /* implemented by a low level driver */ struct hv_ops { int (*get_chars)(uint32_t vtermno, char *buf, int count); int (*put_chars)(uint32_t vtermno, const char *buf, int count); -}; -struct hvc_struct; + /* Callbacks for notification. Called in open and close */ + int (*notifier_add)(struct hvc_struct *hp, int irq); + void (*notifier_del)(struct hvc_struct *hp, int irq); +}; /* Register a vterm and a slot index for use as a console (console_init) */ extern int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops); /* register a vterm for hvc tty operation (module_init or hotplug add) */ -extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq, +extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int data, struct hv_ops *ops, int outbuf_size); -/* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ +/* remove a vterm from hvc tty operation (module_exit or hotplug remove) */ extern int __devexit hvc_remove(struct hvc_struct *hp); +/* data available */ +int hvc_poll(struct hvc_struct *hp); +void hvc_kick(void); + +/* default notifier for irq based notification */ +extern int notifier_add_irq(struct hvc_struct *hp, int data); +extern void notifier_del_irq(struct hvc_struct *hp, int data); + #if defined(CONFIG_XMON) && defined(CONFIG_SMP) #include <asm/xmon.h> diff --git a/drivers/char/hvc_irq.c b/drivers/char/hvc_irq.c new file mode 100644 index 0000000..73a59cd --- /dev/null +++ b/drivers/char/hvc_irq.c @@ -0,0 +1,44 @@ +/* + * Copyright IBM Corp. 2001,2008 + * + * This file contains the IRQ specific code for hvc_console + * + */ + +#include <linux/interrupt.h> + +#include "hvc_console.h" + +static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance) +{ + /* if hvc_poll request a repoll, then kick the hvcd thread */ + if (hvc_poll(dev_instance)) + hvc_kick(); + return IRQ_HANDLED; +} + +/* + * For IRQ based systems these callbacks can be used + */ +int notifier_add_irq(struct hvc_struct *hp, int irq) +{ + int rc; + + if (!irq) { + hp->irq_requested = 0; + return 0; + } + rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, + "hvc_console", hp); + if (!rc) + hp->irq_requested = 1; + return rc; +} + +void notifier_del_irq(struct hvc_struct *hp, int irq) +{ + if (!irq) + return; + free_irq(irq, hp); + hp->irq_requested = 0; +} diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index a08f8f9..b71c610 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c @@ -200,6 +200,8 @@ done: static struct hv_ops hvc_get_put_ops = { .get_chars = get_chars, .put_chars = put_chars, + .notifier_add = notifier_add_irq, + .notifier_del = notifier_del_irq, }; static int __devinit hvc_vio_probe(struct vio_dev *vdev, diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c index 79711aa..93f3840 100644 --- a/drivers/char/hvc_vio.c +++ b/drivers/char/hvc_vio.c @@ -80,6 +80,8 @@ static int filtered_get_chars(uint32_t vtermno, char *buf, int count) static struct hv_ops hvc_get_put_ops = { .get_chars = filtered_get_chars, .put_chars = hvc_put_chars, + .notifier_add = notifier_add_irq, + .notifier_del = notifier_del_irq, }; static int __devinit hvc_vio_probe(struct vio_dev *vdev, diff --git a/drivers/char/hvc_xen.c b/drivers/char/hvc_xen.c index db2ae42..6b70aa6 100644 --- a/drivers/char/hvc_xen.c +++ b/drivers/char/hvc_xen.c @@ -100,6 +100,8 @@ static int read_console(uint32_t vtermno, char *buf, int len) static struct hv_ops hvc_ops = { .get_chars = read_console, .put_chars = write_console, + .notifier_add = notifier_add_irq, + .notifier_del = notifier_del_irq, }; static int __init xen_init(void) diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 786d518..473d9b1 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -114,7 +114,7 @@ * the hvcs_final_close() function in order to get it out of the spinlock. * Rearranged hvcs_close(). Cleaned up some printks and did some housekeeping * on the changelog. Removed local CLC_LENGTH and used HVCS_CLC_LENGTH from - * include/asm-powerpc/hvcserver.h + * arch/powerepc/include/asm/hvcserver.h * * 1.3.2 -> 1.3.3 Replaced yield() in hvcs_close() with tty_wait_until_sent() to * prevent possible lockup with realtime scheduling as similarily pointed out by diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c index 27fdc08..8a2fce0 100644 --- a/drivers/char/hw_random/intel-rng.c +++ b/drivers/char/hw_random/intel-rng.c @@ -241,7 +241,7 @@ static int __init intel_rng_hw_init(void *_intel_rng_hw) struct intel_rng_hw *intel_rng_hw = _intel_rng_hw; u8 mfc, dvc; - /* interrupts disabled in stop_machine_run call */ + /* interrupts disabled in stop_machine call */ if (!(intel_rng_hw->fwh_dec_en1_val & FWH_F8_EN_MASK)) pci_write_config_byte(intel_rng_hw->dev, @@ -365,10 +365,10 @@ static int __init mod_init(void) * location with the Read ID command, all activity on the system * must be stopped until the state is back to normal. * - * Use stop_machine_run because IPIs can be blocked by disabling + * Use stop_machine because IPIs can be blocked by disabling * interrupts. */ - err = stop_machine_run(intel_rng_hw_init, intel_rng_hw, NR_CPUS); + err = stop_machine(intel_rng_hw_init, intel_rng_hw, NULL); pci_dev_put(dev); iounmap(intel_rng_hw->mem); kfree(intel_rng_hw); diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c index bab43ca..263567f 100644 --- a/drivers/char/hw_random/ixp4xx-rng.c +++ b/drivers/char/hw_random/ixp4xx-rng.c @@ -23,7 +23,7 @@ #include <linux/hw_random.h> #include <asm/io.h> -#include <asm/hardware.h> +#include <mach/hardware.h> static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer) diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index 5dc7440..689f9dc 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c @@ -203,7 +203,7 @@ static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *); static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *); static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *); -static int ip2_ipl_ioctl(struct inode *, struct file *, UINT, ULONG); +static long ip2_ipl_ioctl(struct file *, UINT, ULONG); static int ip2_ipl_open(struct inode *, struct file *); static int DumpTraceBuffer(char __user *, int); @@ -236,7 +236,7 @@ static const struct file_operations ip2_ipl = { .owner = THIS_MODULE, .read = ip2_ipl_read, .write = ip2_ipl_write, - .ioctl = ip2_ipl_ioctl, + .unlocked_ioctl = ip2_ipl_ioctl, .open = ip2_ipl_open, }; @@ -718,12 +718,12 @@ ip2_loadmain(int *iop, int *irqp) } if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { - device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i), - "ipl%d", i); - device_create(ip2_class, NULL, - MKDEV(IP2_IPL_MAJOR, 4 * i + 1), - "stat%d", i); + device_create_drvdata(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i), + NULL, "ipl%d", i); + device_create_drvdata(ip2_class, NULL, + MKDEV(IP2_IPL_MAJOR, 4 * i + 1), + NULL, "stat%d", i); for ( box = 0; box < ABS_MAX_BOXES; ++box ) { @@ -2845,10 +2845,10 @@ ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t /* */ /* */ /******************************************************************************/ -static int -ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) +static long +ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg ) { - unsigned int iplminor = iminor(pInode); + unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode); int rc = 0; void __user *argp = (void __user *)arg; ULONG __user *pIndex = argp; @@ -2859,6 +2859,8 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg ); #endif + lock_kernel(); + switch ( iplminor ) { case 0: // IPL device rc = -EINVAL; @@ -2919,6 +2921,7 @@ ip2_ipl_ioctl ( struct inode *pInode, struct file *pFile, UINT cmd, ULONG arg ) rc = -ENODEV; break; } + unlock_kernel(); return rc; } diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index c11a404..64e1c16 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -871,7 +871,7 @@ static void ipmi_new_smi(int if_num, struct device *device) entry->dev = dev; mutex_lock(®_list_mutex); - device_create(ipmi_class, device, dev, "ipmi%d", if_num); + device_create_drvdata(ipmi_class, device, dev, NULL, "ipmi%d", if_num); list_add(&entry->link, ®_list); mutex_unlock(®_list_mutex); } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 1926883..f52931e 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -66,8 +66,8 @@ #include <linux/ctype.h> #ifdef CONFIG_PPC_OF -#include <asm/of_device.h> -#include <asm/of_platform.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> #endif #define PFX "ipmi_si: " diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index d4281df..8f7cc19 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c @@ -1181,14 +1181,17 @@ static int isicom_chars_in_buffer(struct tty_struct *tty) } /* ioctl et all */ -static inline void isicom_send_break(struct isi_port *port, - unsigned long length) +static int isicom_send_break(struct tty_struct *tty, int length) { + struct isi_port *port = tty->driver_data; struct isi_board *card = port->card; unsigned long base = card->base; + if (length == -1) + return -EOPNOTSUPP; + if (!lock_card(card)) - return; + return -EINVAL; outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base); outw((length & 0xff) << 8 | 0x00, base); @@ -1196,6 +1199,7 @@ static inline void isicom_send_break(struct isi_port *port, InterruptTheCard(base); unlock_card(card); + return 0; } static int isicom_tiocmget(struct tty_struct *tty, struct file *file) @@ -1305,28 +1309,11 @@ static int isicom_ioctl(struct tty_struct *tty, struct file *filp, { struct isi_port *port = tty->driver_data; void __user *argp = (void __user *)arg; - int retval; if (isicom_paranoia_check(port, tty->name, "isicom_ioctl")) return -ENODEV; switch (cmd) { - case TCSBRK: - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - isicom_send_break(port, HZ/4); - return 0; - - case TCSBRKP: - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4); - return 0; case TIOCGSERIAL: return isicom_get_serial_info(port, argp); @@ -1459,6 +1446,7 @@ static const struct tty_operations isicom_ops = { .flush_buffer = isicom_flush_buffer, .tiocmget = isicom_tiocmget, .tiocmset = isicom_tiocmset, + .break_ctl = isicom_send_break, }; static int __devinit reset_card(struct pci_dev *pdev, @@ -1832,7 +1820,7 @@ static int __init isicom_init(void) isicom_normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; isicom_normal->flags = TTY_DRIVER_REAL_RAW | - TTY_DRIVER_DYNAMIC_DEV; + TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK; tty_set_operations(isicom_normal, &isicom_ops); retval = tty_register_driver(isicom_normal); diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index 7930fba..843a2af 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c @@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty); static void stli_stop(struct tty_struct *tty); static void stli_start(struct tty_struct *tty); static void stli_flushbuffer(struct tty_struct *tty); -static void stli_breakctl(struct tty_struct *tty, int state); +static int stli_breakctl(struct tty_struct *tty, int state); static void stli_waituntilsent(struct tty_struct *tty, int timeout); static void stli_sendxchar(struct tty_struct *tty, char ch); static void stli_hangup(struct tty_struct *tty); @@ -925,8 +925,7 @@ static void stli_close(struct tty_struct *tty, struct file *filp) clear_bit(ST_TXBUSY, &portp->state); clear_bit(ST_RXSTOP, &portp->state); set_bit(TTY_IO_ERROR, &tty->flags); - if (tty->ldisc.ops->flush_buffer) - (tty->ldisc.ops->flush_buffer)(tty); + tty_ldisc_flush(tty); set_bit(ST_DOFLUSHRX, &portp->state); stli_flushbuffer(tty); @@ -1909,7 +1908,7 @@ static void stli_flushbuffer(struct tty_struct *tty) /*****************************************************************************/ -static void stli_breakctl(struct tty_struct *tty, int state) +static int stli_breakctl(struct tty_struct *tty, int state) { struct stlibrd *brdp; struct stliport *portp; @@ -1917,15 +1916,16 @@ static void stli_breakctl(struct tty_struct *tty, int state) portp = tty->driver_data; if (portp == NULL) - return; + return -EINVAL; if (portp->brdnr >= stli_nrbrds) - return; + return -EINVAL; brdp = stli_brds[portp->brdnr]; if (brdp == NULL) - return; + return -EINVAL; arg = (state == -1) ? BREAKON : BREAKOFF; stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); + return 0; } /*****************************************************************************/ @@ -4599,8 +4599,9 @@ static int __init istallion_module_init(void) istallion_class = class_create(THIS_MODULE, "staliomem"); for (i = 0; i < 4; i++) - device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), - "staliomem%d", i); + device_create_drvdata(istallion_class, NULL, + MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); return 0; err_deinit: diff --git a/drivers/char/lcd.c b/drivers/char/lcd.c deleted file mode 100644 index 1c29b20..0000000 --- a/drivers/char/lcd.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * LCD, LED and Button interface for Cobalt - * - * 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) 1996, 1997 by Andrew Bose - * - * Linux kernel version history: - * March 2001: Ported from 2.0.34 by Liam Davies - * - */ -#include <linux/types.h> -#include <linux/errno.h> -#include <linux/miscdevice.h> -#include <linux/slab.h> -#include <linux/ioport.h> -#include <linux/fcntl.h> -#include <linux/mc146818rtc.h> -#include <linux/netdevice.h> -#include <linux/sched.h> -#include <linux/smp_lock.h> -#include <linux/delay.h> - -#include <asm/io.h> -#include <asm/uaccess.h> -#include <asm/system.h> - -#include "lcd.h" - -static int lcd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); - -static unsigned int lcd_present = 1; - -/* used in arch/mips/cobalt/reset.c */ -int led_state = 0; - -#if defined(CONFIG_TULIP) && 0 - -#define MAX_INTERFACES 8 -static linkcheck_func_t linkcheck_callbacks[MAX_INTERFACES]; -static void *linkcheck_cookies[MAX_INTERFACES]; - -int lcd_register_linkcheck_func(int iface_num, void *func, void *cookie) -{ - if (iface_num < 0 || - iface_num >= MAX_INTERFACES || - linkcheck_callbacks[iface_num] != NULL) - return -1; - linkcheck_callbacks[iface_num] = (linkcheck_func_t) func; - linkcheck_cookies[iface_num] = cookie; - return 0; -} -#endif - -static int lcd_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct lcd_display button_display; - unsigned long address, a; - - switch (cmd) { - case LCD_On: - udelay(150); - BusyCheck(); - LCDWriteInst(0x0F); - break; - - case LCD_Off: - udelay(150); - BusyCheck(); - LCDWriteInst(0x08); - break; - - case LCD_Reset: - udelay(150); - LCDWriteInst(0x3F); - udelay(150); - LCDWriteInst(0x3F); - udelay(150); - LCDWriteInst(0x3F); - udelay(150); - LCDWriteInst(0x3F); - udelay(150); - LCDWriteInst(0x01); - udelay(150); - LCDWriteInst(0x06); - break; - - case LCD_Clear: - udelay(150); - BusyCheck(); - LCDWriteInst(0x01); - break; - - case LCD_Cursor_Left: - udelay(150); - BusyCheck(); - LCDWriteInst(0x10); - break; - - case LCD_Cursor_Right: - udelay(150); - BusyCheck(); - LCDWriteInst(0x14); - break; - - case LCD_Cursor_Off: - udelay(150); - BusyCheck(); - LCDWriteInst(0x0C); - break; - - case LCD_Cursor_On: - udelay(150); - BusyCheck(); - LCDWriteInst(0x0F); - break; - - case LCD_Blink_Off: - udelay(150); - BusyCheck(); - LCDWriteInst(0x0E); - break; - - case LCD_Get_Cursor_Pos:{ - struct lcd_display display; - - udelay(150); - BusyCheck(); - display.cursor_address = (LCDReadInst); - display.cursor_address = - (display.cursor_address & 0x07F); - if (copy_to_user - ((struct lcd_display *) arg, &display, - sizeof(struct lcd_display))) - return -EFAULT; - - break; - } - - - case LCD_Set_Cursor_Pos:{ - struct lcd_display display; - - if (copy_from_user - (&display, (struct lcd_display *) arg, - sizeof(struct lcd_display))) - return -EFAULT; - - a = (display.cursor_address | kLCD_Addr); - - udelay(150); - BusyCheck(); - LCDWriteInst(a); - - break; - } - - case LCD_Get_Cursor:{ - struct lcd_display display; - - udelay(150); - BusyCheck(); - display.character = LCDReadData; - - if (copy_to_user - ((struct lcd_display *) arg, &display, - sizeof(struct lcd_display))) - return -EFAULT; - udelay(150); - BusyCheck(); - LCDWriteInst(0x10); - - break; - } - - case LCD_Set_Cursor:{ - struct lcd_display display; - - if (copy_from_user - (&display, (struct lcd_display *) arg, - sizeof(struct lcd_display))) - return -EFAULT; - - udelay(150); - BusyCheck(); - LCDWriteData(display.character); - udelay(150); - BusyCheck(); - LCDWriteInst(0x10); - - break; - } - - - case LCD_Disp_Left: - udelay(150); - BusyCheck(); - LCDWriteInst(0x18); - break; - - case LCD_Disp_Right: - udelay(150); - BusyCheck(); - LCDWriteInst(0x1C); - break; - - case LCD_Home: - udelay(150); - BusyCheck(); - LCDWriteInst(0x02); - break; - - case LCD_Write:{ - struct lcd_display display; - unsigned int index; - - - if (copy_from_user - (&display, (struct lcd_display *) arg, - sizeof(struct lcd_display))) - return -EFAULT; - - udelay(150); - BusyCheck(); - LCDWriteInst(0x80); - udelay(150); - BusyCheck(); - - for (index = 0; index < (display.size1); index++) { - udelay(150); - BusyCheck(); - LCDWriteData(display.line1[index]); - BusyCheck(); - } - - udelay(150); - BusyCheck(); - LCDWriteInst(0xC0); - udelay(150); - BusyCheck(); - for (index = 0; index < (display.size2); index++) { - udelay(150); - BusyCheck(); - LCDWriteData(display.line2[index]); - } - - break; - } - - case LCD_Read:{ - struct lcd_display display; - - BusyCheck(); - for (address = kDD_R00; address <= kDD_R01; - address++) { - a = (address | kLCD_Addr); - - udelay(150); - BusyCheck(); - LCDWriteInst(a); - udelay(150); - BusyCheck(); - display.line1[address] = LCDReadData; - } - - display.line1[0x27] = '\0'; - - for (address = kDD_R10; address <= kDD_R11; - address++) { - a = (address | kLCD_Addr); - - udelay(150); - BusyCheck(); - LCDWriteInst(a); - - udelay(150); - BusyCheck(); - display.line2[address - 0x40] = - LCDReadData; - } - - display.line2[0x27] = '\0'; - - if (copy_to_user - ((struct lcd_display *) arg, &display, - sizeof(struct lcd_display))) - return -EFAULT; - break; - } - -// set all GPIO leds to led_display.leds - - case LED_Set:{ - struct lcd_display led_display; - - - if (copy_from_user - (&led_display, (struct lcd_display *) arg, - sizeof(struct lcd_display))) - return -EFAULT; - - led_state = led_display.leds; - LEDSet(led_state); - - break; - } - - -// set only bit led_display.leds - - case LED_Bit_Set:{ - unsigned int i; - int bit = 1; - struct lcd_display led_display; - - - if (copy_from_user - (&led_display, (struct lcd_display *) arg, - sizeof(struct lcd_display))) - return -EFAULT; - - for (i = 0; i < (int) led_display.leds; i++) { - bit = 2 * bit; - } - - led_state = led_state | bit; - LEDSet(led_state); - break; - } - -// clear only bit led_display.leds - - case LED_Bit_Clear:{ - unsigned int i; - int bit = 1; - struct lcd_display led_display; - - - if (copy_from_user - (&led_display, (struct lcd_display *) arg, - sizeof(struct lcd_display))) - return -EFAULT; - - for (i = 0; i < (int) led_display.leds; i++) { - bit = 2 * bit; - } - - led_state = led_state & ~bit; - LEDSet(led_state); - break; - } - - - case BUTTON_Read:{ - button_display.buttons = GPIRead; - if (copy_to_user - ((struct lcd_display *) arg, &button_display, - sizeof(struct lcd_display))) - return -EFAULT; - break; - } - - case LINK_Check:{ - button_display.buttons = - *((volatile unsigned long *) (0xB0100060)); - if (copy_to_user - ((struct lcd_display *) arg, &button_display, - sizeof(struct lcd_display))) - return -EFAULT; - break; - } - - case LINK_Check_2:{ - int iface_num; - - /* panel-utils should pass in the desired interface status is wanted for - * in "buttons" of the structure. We will set this to non-zero if the - * link is in fact up for the requested interface. --DaveM - */ - if (copy_from_user - (&button_display, (struct lcd_display *) arg, - sizeof(button_display))) - return -EFAULT; - iface_num = button_display.buttons; -#if defined(CONFIG_TULIP) && 0 - if (iface_num >= 0 && - iface_num < MAX_INTERFACES && - linkcheck_callbacks[iface_num] != NULL) { - button_display.buttons = - linkcheck_callbacks[iface_num] - (linkcheck_cookies[iface_num]); - } else -#endif - button_display.buttons = 0; - - if (__copy_to_user - ((struct lcd_display *) arg, &button_display, - sizeof(struct lcd_display))) - return -EFAULT; - break; - } - - default: - return -EINVAL; - - } - - return 0; - -} - -static int lcd_open(struct inode *inode, struct file *file) -{ - cycle_kernel_lock(); - - if (!lcd_present) - return -ENXIO; - else - return 0; -} - -/* Only RESET or NEXT counts as button pressed */ - -static inline int button_pressed(void) -{ - unsigned long buttons = GPIRead; - - if ((buttons == BUTTON_Next) || (buttons == BUTTON_Next_B) - || (buttons == BUTTON_Reset_B)) - return buttons; - return 0; -} - -/* LED daemon sits on this and we wake him up once a key is pressed. */ - -static int lcd_waiters = 0; - -static ssize_t lcd_read(struct file *file, char *buf, - size_t count, loff_t *ofs) -{ - long buttons_now; - - if (lcd_waiters > 0) - return -EINVAL; - - lcd_waiters++; - while (((buttons_now = (long) button_pressed()) == 0) && - !(signal_pending(current))) { - msleep_interruptible(2000); - } - lcd_waiters--; - - if (signal_pending(current)) - return -ERESTARTSYS; - return buttons_now; -} - -/* - * The various file operations we support. - */ - -static const struct file_operations lcd_fops = { - .read = lcd_read, - .ioctl = lcd_ioctl, - .open = lcd_open, -}; - -static struct miscdevice lcd_dev = { - MISC_DYNAMIC_MINOR, - "lcd", - &lcd_fops -}; - -static int lcd_init(void) -{ - int ret; - unsigned long data; - - pr_info("%s\n", LCD_DRIVER); - ret = misc_register(&lcd_dev); - if (ret) { - printk(KERN_WARNING LCD "Unable to register misc device.\n"); - return ret; - } - - /* Check region? Naaah! Just snarf it up. */ -/* request_region(RTC_PORT(0), RTC_IO_EXTENT, "lcd");*/ - - udelay(150); - data = LCDReadData; - if ((data & 0x000000FF) == (0x00)) { - lcd_present = 0; - pr_info(LCD "LCD Not Present\n"); - } else { - lcd_present = 1; - WRITE_GAL(kGal_DevBank2PReg, kGal_DevBank2Cfg); - WRITE_GAL(kGal_DevBank3PReg, kGal_DevBank3Cfg); - } - - return 0; -} - -static void __exit lcd_exit(void) -{ - misc_deregister(&lcd_dev); -} - -module_init(lcd_init); -module_exit(lcd_exit); - -MODULE_AUTHOR("Andrew Bose"); -MODULE_LICENSE("GPL"); diff --git a/drivers/char/lcd.h b/drivers/char/lcd.h deleted file mode 100644 index 290b3ff..0000000 --- a/drivers/char/lcd.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * LED, LCD and Button panel driver for Cobalt - * - * 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) 1996, 1997 by Andrew Bose - * - * Linux kernel version history: - * March 2001: Ported from 2.0.34 by Liam Davies - * - */ - -// function headers - -#define LCD_CHARS_PER_LINE 40 -#define MAX_IDLE_TIME 120 - -struct lcd_display { - unsigned buttons; - int size1; - int size2; - unsigned char line1[LCD_CHARS_PER_LINE]; - unsigned char line2[LCD_CHARS_PER_LINE]; - unsigned char cursor_address; - unsigned char character; - unsigned char leds; - unsigned char *RomImage; -}; - - - -#define LCD_DRIVER "Cobalt LCD Driver v2.10" - -#define LCD "lcd: " - -#define kLCD_IR 0x0F000000 -#define kLCD_DR 0x0F000010 -#define kGPI 0x0D000000 -#define kLED 0x0C000000 - -#define kDD_R00 0x00 -#define kDD_R01 0x27 -#define kDD_R10 0x40 -#define kDD_R11 0x67 - -#define kLCD_Addr 0x00000080 - -#define LCDTimeoutValue 0xfff - - -// Macros - -#define LCDWriteData(x) outl((x << 24), kLCD_DR) -#define LCDWriteInst(x) outl((x << 24), kLCD_IR) - -#define LCDReadData (inl(kLCD_DR) >> 24) -#define LCDReadInst (inl(kLCD_IR) >> 24) - -#define GPIRead (inl(kGPI) >> 24) - -#define LEDSet(x) outb((char)x, kLED) - -#define WRITE_GAL(x,y) outl(y, 0x04000000 | (x)) -#define BusyCheck() while ((LCDReadInst & 0x80) == 0x80) - - - -/* - * Function command codes for io_ctl. - */ -#define LCD_On 1 -#define LCD_Off 2 -#define LCD_Clear 3 -#define LCD_Reset 4 -#define LCD_Cursor_Left 5 -#define LCD_Cursor_Right 6 -#define LCD_Disp_Left 7 -#define LCD_Disp_Right 8 -#define LCD_Get_Cursor 9 -#define LCD_Set_Cursor 10 -#define LCD_Home 11 -#define LCD_Read 12 -#define LCD_Write 13 -#define LCD_Cursor_Off 14 -#define LCD_Cursor_On 15 -#define LCD_Get_Cursor_Pos 16 -#define LCD_Set_Cursor_Pos 17 -#define LCD_Blink_Off 18 - -#define LED_Set 40 -#define LED_Bit_Set 41 -#define LED_Bit_Clear 42 - - -// Button defs -#define BUTTON_Read 50 - - -// Ethernet LINK check hackaroo -#define LINK_Check 90 -#define LINK_Check_2 91 - -// Button patterns _B - single layer lcd boards - -#define BUTTON_NONE 0x3F -#define BUTTON_NONE_B 0xFE - -#define BUTTON_Left 0x3B -#define BUTTON_Left_B 0xFA - -#define BUTTON_Right 0x37 -#define BUTTON_Right_B 0xDE - -#define BUTTON_Up 0x2F -#define BUTTON_Up_B 0xF6 - -#define BUTTON_Down 0x1F -#define BUTTON_Down_B 0xEE - -#define BUTTON_Next 0x3D -#define BUTTON_Next_B 0x7E - -#define BUTTON_Enter 0x3E -#define BUTTON_Enter_B 0xBE - -#define BUTTON_Reset_B 0xFC - - -// debounce constants - -#define BUTTON_SENSE 160000 -#define BUTTON_DEBOUNCE 5000 - - -// Galileo register stuff - -#define kGal_DevBank2Cfg 0x1466DB33 -#define kGal_DevBank2PReg 0x464 -#define kGal_DevBank3Cfg 0x146FDFFB -#define kGal_DevBank3PReg 0x468 - -// Network - -#define kIPADDR 1 -#define kNETMASK 2 -#define kGATEWAY 3 -#define kDNS 4 - -#define kClassA 5 -#define kClassB 6 -#define kClassC 7 - diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 71abb4c..3f2719b 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c @@ -813,7 +813,8 @@ static int lp_register(int nr, struct parport *port) if (reset) lp_reset(nr); - device_create(lp_class, port->dev, MKDEV(LP_MAJOR, nr), "lp%d", nr); + device_create_drvdata(lp_class, port->dev, MKDEV(LP_MAJOR, nr), NULL, + "lp%d", nr); printk(KERN_INFO "lp%d: using %s (%s).\n", nr, port->name, (port->irq == PARPORT_IRQ_NONE)?"polling":"interrupt-driven"); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index b6772d6..672b08e 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -327,7 +327,10 @@ static void mmap_mem_close(struct vm_area_struct *vma) static struct vm_operations_struct mmap_mem_ops = { .open = mmap_mem_open, - .close = mmap_mem_close + .close = mmap_mem_close, +#ifdef CONFIG_HAVE_IOREMAP_PROT + .access = generic_access_phys +#endif }; static int mmap_mem(struct file * file, struct vm_area_struct * vma) @@ -989,9 +992,9 @@ static int __init chr_dev_init(void) mem_class = class_create(THIS_MODULE, "mem"); for (i = 0; i < ARRAY_SIZE(devlist); i++) - device_create(mem_class, NULL, - MKDEV(MEM_MAJOR, devlist[i].minor), - devlist[i].name); + device_create_drvdata(mem_class, NULL, + MKDEV(MEM_MAJOR, devlist[i].minor), + NULL, devlist[i].name); return 0; } diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 6e1563c..999aa77 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c @@ -217,8 +217,8 @@ int misc_register(struct miscdevice * misc) misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7); dev = MKDEV(MISC_MAJOR, misc->minor); - misc->this_device = device_create(misc_class, misc->parent, dev, - "%s", misc->name); + misc->this_device = device_create_drvdata(misc_class, misc->parent, + dev, NULL, "%s", misc->name); if (IS_ERR(misc->this_device)) { err = PTR_ERR(misc->this_device); goto out; diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 2bba250..d3d7864e 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c @@ -374,12 +374,13 @@ copy: return ret; } -static void moxa_break_ctl(struct tty_struct *tty, int state) +static int moxa_break_ctl(struct tty_struct *tty, int state) { struct moxa_port *port = tty->driver_data; moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, Magic_code); + return 0; } static const struct tty_operations moxa_ops = { diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index fe2a95b..30f095a 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -193,25 +193,23 @@ mspec_close(struct vm_area_struct *vma) } /* - * mspec_nopfn + * mspec_fault * * Creates a mspec page and maps it to user space. */ -static unsigned long -mspec_nopfn(struct vm_area_struct *vma, unsigned long address) +static int +mspec_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { unsigned long paddr, maddr; unsigned long pfn; - int index; + pgoff_t index = vmf->pgoff; struct vma_data *vdata = vma->vm_private_data; - BUG_ON(address < vdata->vm_start || address >= vdata->vm_end); - index = (address - vdata->vm_start) >> PAGE_SHIFT; maddr = (volatile unsigned long) vdata->maddr[index]; if (maddr == 0) { maddr = uncached_alloc_page(numa_node_id(), 1); if (maddr == 0) - return NOPFN_OOM; + return VM_FAULT_OOM; spin_lock(&vdata->lock); if (vdata->maddr[index] == 0) { @@ -231,13 +229,20 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address) pfn = paddr >> PAGE_SHIFT; - return pfn; + /* + * vm_insert_pfn can fail with -EBUSY, but in that case it will + * be because another thread has installed the pte first, so it + * is no problem. + */ + vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); + + return VM_FAULT_NOPAGE; } static struct vm_operations_struct mspec_vm_ops = { .open = mspec_open, .close = mspec_close, - .nopfn = mspec_nopfn + .fault = mspec_fault, }; /* diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 50243fc..4f8d67f 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c @@ -86,8 +86,8 @@ module_param(mwave_uart_io, int, 0); static int mwave_open(struct inode *inode, struct file *file); static int mwave_close(struct inode *inode, struct file *file); -static int mwave_ioctl(struct inode *inode, struct file *filp, - unsigned int iocmd, unsigned long ioarg); +static long mwave_ioctl(struct file *filp, unsigned int iocmd, + unsigned long ioarg); MWAVE_DEVICE_DATA mwave_s_mdd; @@ -119,16 +119,16 @@ static int mwave_close(struct inode *inode, struct file *file) return retval; } -static int mwave_ioctl(struct inode *inode, struct file *file, - unsigned int iocmd, unsigned long ioarg) +static long mwave_ioctl(struct file *file, unsigned int iocmd, + unsigned long ioarg) { unsigned int retval = 0; pMWAVE_DEVICE_DATA pDrvData = &mwave_s_mdd; void __user *arg = (void __user *)ioarg; - PRINTK_5(TRACE_MWAVE, - "mwavedd::mwave_ioctl, entry inode %p file %p cmd %x arg %x\n", - inode, file, iocmd, (int) ioarg); + PRINTK_4(TRACE_MWAVE, + "mwavedd::mwave_ioctl, entry file %p cmd %x arg %x\n", + file, iocmd, (int) ioarg); switch (iocmd) { @@ -136,7 +136,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RESET" " calling tp3780I_ResetDSP\n"); + lock_kernel(); retval = tp3780I_ResetDSP(&pDrvData->rBDData); + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RESET" " retval %x from tp3780I_ResetDSP\n", @@ -147,7 +149,9 @@ static int mwave_ioctl(struct inode *inode, struct file *file, PRINTK_1(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RUN" " calling tp3780I_StartDSP\n"); + lock_kernel(); retval = tp3780I_StartDSP(&pDrvData->rBDData); + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_RUN" " retval %x from tp3780I_StartDSP\n", @@ -161,8 +165,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, "mwavedd::mwave_ioctl," " IOCTL_MW_DSP_ABILITIES calling" " tp3780I_QueryAbilities\n"); + lock_kernel(); retval = tp3780I_QueryAbilities(&pDrvData->rBDData, &rAbilities); + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES" " retval %x from tp3780I_QueryAbilities\n", @@ -193,11 +199,13 @@ static int mwave_ioctl(struct inode *inode, struct file *file, "mwavedd::mwave_ioctl IOCTL_MW_READ_DATA," " size %lx, ioarg %lx pusBuffer %p\n", rReadData.ulDataLength, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, pusBuffer, rReadData.ulDataLength, rReadData.usDspAddress); + unlock_kernel(); } break; @@ -215,10 +223,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " size %lx, ioarg %lx pusBuffer %p\n", rReadData.ulDataLength / 2, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, pusBuffer, rReadData.ulDataLength / 2, rReadData.usDspAddress); + unlock_kernel(); } break; @@ -236,10 +246,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " size %lx, ioarg %lx pusBuffer %p\n", rWriteData.ulDataLength, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData, iocmd, pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress); + unlock_kernel(); } break; @@ -257,10 +269,12 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " size %lx, ioarg %lx pusBuffer %p\n", rWriteData.ulDataLength, ioarg, pusBuffer); + lock_kernel(); retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData, iocmd, pusBuffer, rWriteData.ulDataLength, rWriteData.usDspAddress); + unlock_kernel(); } break; @@ -281,8 +295,10 @@ static int mwave_ioctl(struct inode *inode, struct file *file, ipcnum); return -EINVAL; } + lock_kernel(); pDrvData->IPCs[ipcnum].bIsHere = FALSE; pDrvData->IPCs[ipcnum].bIsEnabled = TRUE; + unlock_kernel(); PRINTK_2(TRACE_MWAVE, "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC" @@ -307,6 +323,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, return -EINVAL; } + lock_kernel(); if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { DECLARE_WAITQUEUE(wait, current); @@ -347,6 +364,7 @@ static int mwave_ioctl(struct inode *inode, struct file *file, " processing\n", ipcnum); } + unlock_kernel(); } break; @@ -365,19 +383,18 @@ static int mwave_ioctl(struct inode *inode, struct file *file, ipcnum); return -EINVAL; } + lock_kernel(); if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) { pDrvData->IPCs[ipcnum].bIsEnabled = FALSE; if (pDrvData->IPCs[ipcnum].bIsHere == TRUE) { wake_up_interruptible(&pDrvData->IPCs[ipcnum].ipc_wait_queue); } } + unlock_kernel(); } break; default: - PRINTK_ERROR(KERN_ERR_MWAVE "mwavedd::mwave_ioctl:" - " Error: Unrecognized iocmd %x\n", - iocmd); return -ENOTTY; break; } /* switch */ @@ -460,7 +477,7 @@ static const struct file_operations mwave_fops = { .owner = THIS_MODULE, .read = mwave_read, .write = mwave_write, - .ioctl = mwave_ioctl, + .unlocked_ioctl = mwave_ioctl, .open = mwave_open, .release = mwave_close }; diff --git a/drivers/char/mwave/mwavedd.h b/drivers/char/mwave/mwavedd.h index 8eca61e..7e0d530 100644 --- a/drivers/char/mwave/mwavedd.h +++ b/drivers/char/mwave/mwavedd.h @@ -147,4 +147,6 @@ typedef struct _MWAVE_DEVICE_DATA { } MWAVE_DEVICE_DATA, *pMWAVE_DEVICE_DATA; +extern MWAVE_DEVICE_DATA mwave_s_mdd; + #endif diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index f282976..c689697 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c @@ -57,8 +57,6 @@ #include "3780i.h" #include "mwavepub.h" -extern MWAVE_DEVICE_DATA mwave_s_mdd; - static unsigned short s_ausThinkpadIrqToField[16] = { 0xFFFF, 0xFFFF, 0xFFFF, 0x0001, 0x0002, 0x0003, 0xFFFF, 0x0004, 0xFFFF, 0xFFFF, 0x0005, 0x0006, 0xFFFF, 0xFFFF, 0xFFFF, 0x0007 }; diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 6307e30..b638403 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -16,7 +16,6 @@ * Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox * <alan@redhat.com>. The original 1.8 code is available on www.moxa.com. * - Fixed x86_64 cleanness - * - Fixed sleep with spinlock held in mxser_send_break */ #include <linux/module.h> @@ -47,20 +46,14 @@ #include "mxser.h" -#define MXSER_VERSION "2.0.3" /* 1.11 */ +#define MXSER_VERSION "2.0.4" /* 1.12 */ #define MXSERMAJOR 174 -#define MXSERCUMAJOR 175 #define MXSER_BOARDS 4 /* Max. boards */ #define MXSER_PORTS_PER_BOARD 8 /* Max. ports per board */ #define MXSER_PORTS (MXSER_BOARDS * MXSER_PORTS_PER_BOARD) #define MXSER_ISR_PASS_LIMIT 100 -#define MXSER_ERR_IOADDR -1 -#define MXSER_ERR_IRQ -2 -#define MXSER_ERR_IRQ_CONFLIT -3 -#define MXSER_ERR_VECTOR -4 - /*CheckIsMoxaMust return value*/ #define MOXA_OTHER_UART 0x00 #define MOXA_MUST_MU150_HWID 0x01 @@ -71,12 +64,13 @@ #define UART_MCR_AFE 0x20 #define UART_LSR_SPECIAL 0x1E +#define PCI_DEVICE_ID_POS104UL 0x1044 #define PCI_DEVICE_ID_CB108 0x1080 +#define PCI_DEVICE_ID_CP102UF 0x1023 #define PCI_DEVICE_ID_CB114 0x1142 #define PCI_DEVICE_ID_CP114UL 0x1143 #define PCI_DEVICE_ID_CB134I 0x1341 #define PCI_DEVICE_ID_CP138U 0x1380 -#define PCI_DEVICE_ID_POS104UL 0x1044 #define C168_ASIC_ID 1 @@ -142,7 +136,8 @@ static const struct mxser_cardinfo mxser_cards[] = { { "CB-134I series", 4, }, { "CP-138U series", 8, }, { "POS-104UL series", 4, }, - { "CP-114UL series", 4, } + { "CP-114UL series", 4, }, +/*30*/ { "CP-102UF series", 2, } }; /* driver_data correspond to the lines in the structure above @@ -172,18 +167,20 @@ static struct pci_device_id mxser_pcibrds[] = { { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U), .driver_data = 27 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 }, { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 }, + { PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 }, { } }; MODULE_DEVICE_TABLE(pci, mxser_pcibrds); -static int ioaddr[MXSER_BOARDS] = { 0, 0, 0, 0 }; +static unsigned long ioaddr[MXSER_BOARDS]; static int ttymajor = MXSERMAJOR; /* Variables for insmod */ MODULE_AUTHOR("Casper Yang"); MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver"); -module_param_array(ioaddr, int, NULL, 0); +module_param_array(ioaddr, ulong, NULL, 0); +MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board"); module_param(ttymajor, int, 0); MODULE_LICENSE("GPL"); @@ -193,7 +190,6 @@ struct mxser_log { unsigned long txcnt[MXSER_PORTS]; }; - struct mxser_mon { unsigned long rxcnt; unsigned long txcnt; @@ -284,19 +280,9 @@ struct mxser_mstatus { int dcd; }; -static struct mxser_mstatus GMStatus[MXSER_PORTS]; - -static int mxserBoardCAP[MXSER_BOARDS] = { - 0, 0, 0, 0 - /* 0x180, 0x280, 0x200, 0x320 */ -}; - static struct mxser_board mxser_boards[MXSER_BOARDS]; static struct tty_driver *mxvar_sdriver; static struct mxser_log mxvar_log; -static int mxvar_diagflag; -static unsigned char mxser_msr[MXSER_PORTS + 1]; -static struct mxser_mon_ext mon_data_ext; static int mxser_set_baud_method[MXSER_PORTS + 1]; static void mxser_enable_must_enchance_mode(unsigned long baseio) @@ -540,6 +526,7 @@ static void process_txrx_fifo(struct mxser_port *info) static unsigned char mxser_get_msr(int baseaddr, int mode, int port) { + static unsigned char mxser_msr[MXSER_PORTS + 1]; unsigned char status = 0; status = inb(baseaddr + UART_MSR); @@ -1316,13 +1303,9 @@ static void mxser_flush_chars(struct tty_struct *tty) struct mxser_port *info = tty->driver_data; unsigned long flags; - if (info->xmit_cnt <= 0 || - tty->stopped || - !info->port.xmit_buf || - (tty->hw_stopped && - (info->type != PORT_16550A) && - (!info->board->chip_flag) - )) + if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf || + (tty->hw_stopped && info->type != PORT_16550A && + !info->board->chip_flag)) return; spin_lock_irqsave(&info->slock, flags); @@ -1340,9 +1323,7 @@ static int mxser_write_room(struct tty_struct *tty) int ret; ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1; - if (ret < 0) - ret = 0; - return ret; + return ret < 0 ? 0 : ret; } static int mxser_chars_in_buffer(struct tty_struct *tty) @@ -1414,7 +1395,6 @@ static int mxser_set_serial_info(struct mxser_port *info, info->port.closing_wait = new_serial.closing_wait * HZ / 100; info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0; - info->port.tty->low_latency = 0; if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST && (new_serial.baud_base != info->baud_base || new_serial.custom_divisor != @@ -1464,27 +1444,6 @@ static int mxser_get_lsr_info(struct mxser_port *info, return put_user(result, value); } -/* - * This routine sends a break character out the serial port. - */ -static void mxser_send_break(struct mxser_port *info, int duration) -{ - unsigned long flags; - - if (!info->ioaddr) - return; - set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irqsave(&info->slock, flags); - outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC, - info->ioaddr + UART_LCR); - spin_unlock_irqrestore(&info->slock, flags); - schedule_timeout(duration); - spin_lock_irqsave(&info->slock, flags); - outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, - info->ioaddr + UART_LCR); - spin_unlock_irqrestore(&info->slock, flags); -} - static int mxser_tiocmget(struct tty_struct *tty, struct file *file) { struct mxser_port *info = tty->driver_data; @@ -1653,6 +1612,10 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) switch (cmd) { case MOXA_GET_MAJOR: + if (printk_ratelimit()) + printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl " + "%x (GET_MAJOR), fix your userspace\n", + current->comm, cmd); return put_user(ttymajor, (int __user *)argp); case MOXA_CHKPORTENABLE: @@ -1670,62 +1633,60 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) ret = -EFAULT; unlock_kernel(); return ret; - case MOXA_GETMSTATUS: + case MOXA_GETMSTATUS: { + struct mxser_mstatus ms, __user *msu = argp; lock_kernel(); for (i = 0; i < MXSER_BOARDS; i++) for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { port = &mxser_boards[i].ports[j]; + memset(&ms, 0, sizeof(ms)); - GMStatus[i].ri = 0; - if (!port->ioaddr) { - GMStatus[i].dcd = 0; - GMStatus[i].dsr = 0; - GMStatus[i].cts = 0; - continue; - } + if (!port->ioaddr) + goto copy; if (!port->port.tty || !port->port.tty->termios) - GMStatus[i].cflag = - port->normal_termios.c_cflag; + ms.cflag = port->normal_termios.c_cflag; else - GMStatus[i].cflag = - port->port.tty->termios->c_cflag; + ms.cflag = port->port.tty->termios->c_cflag; status = inb(port->ioaddr + UART_MSR); - if (status & 0x80 /*UART_MSR_DCD */ ) - GMStatus[i].dcd = 1; - else - GMStatus[i].dcd = 0; - - if (status & 0x20 /*UART_MSR_DSR */ ) - GMStatus[i].dsr = 1; - else - GMStatus[i].dsr = 0; - - - if (status & 0x10 /*UART_MSR_CTS */ ) - GMStatus[i].cts = 1; - else - GMStatus[i].cts = 0; + if (status & UART_MSR_DCD) + ms.dcd = 1; + if (status & UART_MSR_DSR) + ms.dsr = 1; + if (status & UART_MSR_CTS) + ms.cts = 1; + copy: + if (copy_to_user(msu, &ms, sizeof(ms))) { + unlock_kernel(); + return -EFAULT; + } + msu++; } unlock_kernel(); - if (copy_to_user(argp, GMStatus, - sizeof(struct mxser_mstatus) * MXSER_PORTS)) - return -EFAULT; return 0; + } case MOXA_ASPP_MON_EXT: { - int p, shiftbit; - unsigned long opmode; - unsigned cflag, iflag; + struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */ + unsigned int cflag, iflag, p; + u8 opmode; + + me = kzalloc(sizeof(*me), GFP_KERNEL); + if (!me) + return -ENOMEM; lock_kernel(); - for (i = 0; i < MXSER_BOARDS; i++) { - for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) { + for (i = 0, p = 0; i < MXSER_BOARDS; i++) { + for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) { + if (p >= ARRAY_SIZE(me->rx_cnt)) { + i = MXSER_BOARDS; + break; + } port = &mxser_boards[i].ports[j]; if (!port->ioaddr) continue; - status = mxser_get_msr(port->ioaddr, 0, i); + status = mxser_get_msr(port->ioaddr, 0, p); if (status & UART_MSR_TERI) port->icount.rng++; @@ -1737,16 +1698,13 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) port->icount.cts++; port->mon_data.modem_status = status; - mon_data_ext.rx_cnt[i] = port->mon_data.rxcnt; - mon_data_ext.tx_cnt[i] = port->mon_data.txcnt; - mon_data_ext.up_rxcnt[i] = - port->mon_data.up_rxcnt; - mon_data_ext.up_txcnt[i] = - port->mon_data.up_txcnt; - mon_data_ext.modem_status[i] = + me->rx_cnt[p] = port->mon_data.rxcnt; + me->tx_cnt[p] = port->mon_data.txcnt; + me->up_rxcnt[p] = port->mon_data.up_rxcnt; + me->up_txcnt[p] = port->mon_data.up_txcnt; + me->modem_status[p] = port->mon_data.modem_status; - mon_data_ext.baudrate[i] = - tty_get_baud_rate(port->port.tty); + me->baudrate[p] = tty_get_baud_rate(port->port.tty); if (!port->port.tty || !port->port.tty->termios) { cflag = port->normal_termios.c_cflag; @@ -1756,40 +1714,31 @@ static int mxser_ioctl_special(unsigned int cmd, void __user *argp) iflag = port->port.tty->termios->c_iflag; } - mon_data_ext.databits[i] = cflag & CSIZE; - - mon_data_ext.stopbits[i] = cflag & CSTOPB; - - mon_data_ext.parity[i] = - cflag & (PARENB | PARODD | CMSPAR); - - mon_data_ext.flowctrl[i] = 0x00; + me->databits[p] = cflag & CSIZE; + me->stopbits[p] = cflag & CSTOPB; + me->parity[p] = cflag & (PARENB | PARODD | + CMSPAR); if (cflag & CRTSCTS) - mon_data_ext.flowctrl[i] |= 0x03; + me->flowctrl[p] |= 0x03; if (iflag & (IXON | IXOFF)) - mon_data_ext.flowctrl[i] |= 0x0C; + me->flowctrl[p] |= 0x0C; if (port->type == PORT_16550A) - mon_data_ext.fifo[i] = 1; - else - mon_data_ext.fifo[i] = 0; + me->fifo[p] = 1; - p = i % 4; - shiftbit = p * 2; - opmode = inb(port->opmode_ioaddr) >> shiftbit; + opmode = inb(port->opmode_ioaddr) >> + ((p % 4) * 2); opmode &= OP_MODE_MASK; - - mon_data_ext.iftype[i] = opmode; - + me->iftype[p] = opmode; } } unlock_kernel(); - if (copy_to_user(argp, &mon_data_ext, - sizeof(mon_data_ext))) - return -EFAULT; - return 0; + if (copy_to_user(argp, me, sizeof(*me))) + ret = -EFAULT; + kfree(me); + return ret; } default: return -ENOIOCTLCMD; @@ -1823,7 +1772,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, { struct mxser_port *info = tty->driver_data; struct async_icount cnow; - struct serial_icounter_struct __user *p_cuser; unsigned long flags; void __user *argp = (void __user *)arg; int retval; @@ -1872,21 +1820,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, return -EIO; switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - mxser_send_break(info, HZ / 4); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - mxser_send_break(info, arg ? arg * (HZ / 10) : HZ / 4); - return 0; case TIOCGSERIAL: lock_kernel(); retval = mxser_get_serial_info(info, argp); @@ -1918,30 +1851,26 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file, * NB: both 1->0 and 0->1 transitions are counted except for * RI where only 0->1 is counted. */ - case TIOCGICOUNT: + case TIOCGICOUNT: { + struct serial_icounter_struct icnt = { 0 }; spin_lock_irqsave(&info->slock, flags); cnow = info->icount; spin_unlock_irqrestore(&info->slock, flags); - p_cuser = argp; - if (put_user(cnow.frame, &p_cuser->frame)) - return -EFAULT; - if (put_user(cnow.brk, &p_cuser->brk)) - return -EFAULT; - if (put_user(cnow.overrun, &p_cuser->overrun)) - return -EFAULT; - if (put_user(cnow.buf_overrun, &p_cuser->buf_overrun)) - return -EFAULT; - if (put_user(cnow.parity, &p_cuser->parity)) - return -EFAULT; - if (put_user(cnow.rx, &p_cuser->rx)) - return -EFAULT; - if (put_user(cnow.tx, &p_cuser->tx)) - return -EFAULT; - put_user(cnow.cts, &p_cuser->cts); - put_user(cnow.dsr, &p_cuser->dsr); - put_user(cnow.rng, &p_cuser->rng); - put_user(cnow.dcd, &p_cuser->dcd); - return 0; + + icnt.frame = cnow.frame; + icnt.brk = cnow.brk; + icnt.overrun = cnow.overrun; + icnt.buf_overrun = cnow.buf_overrun; + icnt.parity = cnow.parity; + icnt.rx = cnow.rx; + icnt.tx = cnow.tx; + icnt.cts = cnow.cts; + icnt.dsr = cnow.dsr; + icnt.rng = cnow.rng; + icnt.dcd = cnow.dcd; + + return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0; + } case MOXA_HighSpeedOn: return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); case MOXA_SDS_RSTICOUNTER: @@ -2219,7 +2148,7 @@ static void mxser_hangup(struct tty_struct *tty) /* * mxser_rs_break() --- routine which turns the break handling on or off */ -static void mxser_rs_break(struct tty_struct *tty, int break_state) +static int mxser_rs_break(struct tty_struct *tty, int break_state) { struct mxser_port *info = tty->driver_data; unsigned long flags; @@ -2232,6 +2161,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state) outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, info->ioaddr + UART_LCR); spin_unlock_irqrestore(&info->slock, flags); + return 0; } static void mxser_receive_chars(struct mxser_port *port, int *status) @@ -2536,7 +2466,8 @@ static int __devinit mxser_initbrd(struct mxser_board *brd, unsigned int i; int retval; - printk(KERN_INFO "max. baud rate = %d bps.\n", brd->ports[0].max_baud); + printk(KERN_INFO "mxser: max. baud rate = %d bps\n", + brd->ports[0].max_baud); for (i = 0; i < brd->info->nports; i++) { info = &brd->ports[i]; @@ -2619,28 +2550,32 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) irq = regs[9] & 0xF000; irq = irq | (irq >> 4); if (irq != (regs[9] & 0xFF00)) - return MXSER_ERR_IRQ_CONFLIT; + goto err_irqconflict; } else if (brd->info->nports == 4) { irq = regs[9] & 0xF000; irq = irq | (irq >> 4); irq = irq | (irq >> 8); if (irq != regs[9]) - return MXSER_ERR_IRQ_CONFLIT; + goto err_irqconflict; } else if (brd->info->nports == 8) { irq = regs[9] & 0xF000; irq = irq | (irq >> 4); irq = irq | (irq >> 8); if ((irq != regs[9]) || (irq != regs[10])) - return MXSER_ERR_IRQ_CONFLIT; + goto err_irqconflict; } - if (!irq) - return MXSER_ERR_IRQ; + if (!irq) { + printk(KERN_ERR "mxser: interrupt number unset\n"); + return -EIO; + } brd->irq = ((int)(irq & 0xF000) >> 12); for (i = 0; i < 8; i++) brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8; - if ((regs[12] & 0x80) == 0) - return MXSER_ERR_VECTOR; + if ((regs[12] & 0x80) == 0) { + printk(KERN_ERR "mxser: invalid interrupt vector\n"); + return -EIO; + } brd->vector = (int)regs[11]; /* interrupt vector */ if (id == 1) brd->vector_mask = 0x00FF; @@ -2667,13 +2602,26 @@ static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd) else brd->uart_type = PORT_16450; if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports, - "mxser(IO)")) - return MXSER_ERR_IOADDR; + "mxser(IO)")) { + printk(KERN_ERR "mxser: can't request ports I/O region: " + "0x%.8lx-0x%.8lx\n", + brd->ports[0].ioaddr, brd->ports[0].ioaddr + + 8 * brd->info->nports - 1); + return -EIO; + } if (!request_region(brd->vector, 1, "mxser(vector)")) { release_region(brd->ports[0].ioaddr, 8 * brd->info->nports); - return MXSER_ERR_VECTOR; + printk(KERN_ERR "mxser: can't request interrupt vector region: " + "0x%.8lx-0x%.8lx\n", + brd->ports[0].ioaddr, brd->ports[0].ioaddr + + 8 * brd->info->nports - 1); + return -EIO; } return brd->info->nports; + +err_irqconflict: + printk(KERN_ERR "mxser: invalid interrupt number\n"); + return -EIO; } static int __devinit mxser_probe(struct pci_dev *pdev, @@ -2690,20 +2638,20 @@ static int __devinit mxser_probe(struct pci_dev *pdev, break; if (i >= MXSER_BOARDS) { - printk(KERN_ERR "Too many Smartio/Industio family boards found " - "(maximum %d), board not configured\n", MXSER_BOARDS); + dev_err(&pdev->dev, "too many boards found (maximum %d), board " + "not configured\n", MXSER_BOARDS); goto err; } brd = &mxser_boards[i]; brd->idx = i * MXSER_PORTS_PER_BOARD; - printk(KERN_INFO "Found MOXA %s board (BusNo=%d, DevNo=%d)\n", + dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n", mxser_cards[ent->driver_data].name, pdev->bus->number, PCI_SLOT(pdev->devfn)); retval = pci_enable_device(pdev); if (retval) { - printk(KERN_ERR "Moxa SmartI/O PCI enable fail !\n"); + dev_err(&pdev->dev, "PCI enable failed\n"); goto err; } @@ -2805,11 +2753,8 @@ static struct pci_driver mxser_driver = { static int __init mxser_module_init(void) { struct mxser_board *brd; - unsigned long cap; - unsigned int i, m, isaloop; - int retval, b; - - pr_debug("Loading module mxser ...\n"); + unsigned int b, i, m; + int retval; mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1); if (!mxvar_sdriver) @@ -2839,74 +2784,43 @@ static int __init mxser_module_init(void) goto err_put; } - mxvar_diagflag = 0; - - m = 0; /* Start finding ISA boards here */ - for (isaloop = 0; isaloop < 2; isaloop++) - for (b = 0; b < MXSER_BOARDS && m < MXSER_BOARDS; b++) { - if (!isaloop) - cap = mxserBoardCAP[b]; /* predefined */ - else - cap = ioaddr[b]; /* module param */ + for (m = 0, b = 0; b < MXSER_BOARDS; b++) { + if (!ioaddr[b]) + continue; + + brd = &mxser_boards[m]; + retval = mxser_get_ISA_conf(!ioaddr[b], brd); + if (retval <= 0) { + brd->info = NULL; + continue; + } - if (!cap) - continue; + printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n", + brd->info->name, ioaddr[b]); - brd = &mxser_boards[m]; - retval = mxser_get_ISA_conf(cap, brd); - - if (retval != 0) - printk(KERN_INFO "Found MOXA %s board " - "(CAP=0x%x)\n", - brd->info->name, ioaddr[b]); - - if (retval <= 0) { - if (retval == MXSER_ERR_IRQ) - printk(KERN_ERR "Invalid interrupt " - "number, board not " - "configured\n"); - else if (retval == MXSER_ERR_IRQ_CONFLIT) - printk(KERN_ERR "Invalid interrupt " - "number, board not " - "configured\n"); - else if (retval == MXSER_ERR_VECTOR) - printk(KERN_ERR "Invalid interrupt " - "vector, board not " - "configured\n"); - else if (retval == MXSER_ERR_IOADDR) - printk(KERN_ERR "Invalid I/O address, " - "board not configured\n"); - - brd->info = NULL; - continue; - } - - /* mxser_initbrd will hook ISR. */ - if (mxser_initbrd(brd, NULL) < 0) { - brd->info = NULL; - continue; - } + /* mxser_initbrd will hook ISR. */ + if (mxser_initbrd(brd, NULL) < 0) { + brd->info = NULL; + continue; + } - brd->idx = m * MXSER_PORTS_PER_BOARD; - for (i = 0; i < brd->info->nports; i++) - tty_register_device(mxvar_sdriver, brd->idx + i, - NULL); + brd->idx = m * MXSER_PORTS_PER_BOARD; + for (i = 0; i < brd->info->nports; i++) + tty_register_device(mxvar_sdriver, brd->idx + i, NULL); - m++; - } + m++; + } retval = pci_register_driver(&mxser_driver); if (retval) { - printk(KERN_ERR "Can't register pci driver\n"); + printk(KERN_ERR "mxser: can't register pci driver\n"); if (!m) { retval = -ENODEV; goto err_unr; } /* else: we have some ISA cards under control */ } - pr_debug("Done.\n"); - return 0; err_unr: tty_unregister_driver(mxvar_sdriver); @@ -2919,8 +2833,6 @@ static void __exit mxser_module_exit(void) { unsigned int i, j; - pr_debug("Unloading module mxser ...\n"); - pci_unregister_driver(&mxser_driver); for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */ @@ -2934,8 +2846,6 @@ static void __exit mxser_module_exit(void) for (i = 0; i < MXSER_BOARDS; i++) if (mxser_boards[i].info != NULL) mxser_release_res(&mxser_boards[i], NULL, 1); - - pr_debug("Done.\n"); } module_init(mxser_module_init); diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index ed4e033..69ec639 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -677,6 +677,10 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, /* Allocate transmit buffer */ /* sleep until transmit buffer available */ while (!(tbuf = n_hdlc_buf_get(&n_hdlc->tx_free_buf_list))) { + if (file->f_flags & O_NONBLOCK) { + error = -EAGAIN; + break; + } schedule(); n_hdlc = tty2n_hdlc (tty); diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index a22662b..39f6357 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c @@ -107,7 +107,6 @@ #include <linux/init.h> #include <linux/proc_fs.h> #include <linux/spinlock.h> -#include <linux/smp_lock.h> #include <asm/io.h> #include <asm/uaccess.h> diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index ba012c2..006be92 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -122,35 +122,20 @@ static int flash_ioctl(struct inode *inodep, struct file *filep, unsigned int cm static ssize_t flash_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { - unsigned long p = *ppos; - unsigned int count = size; - int ret = 0; + ssize_t ret; if (flashdebug) - printk(KERN_DEBUG "flash_read: flash_read: offset=0x%lX, " - "buffer=%p, count=0x%X.\n", p, buf, count); - - if (count) - ret = -ENXIO; + printk(KERN_DEBUG "flash_read: flash_read: offset=0x%llx, " + "buffer=%p, count=0x%zx.\n", *ppos, buf, size); + /* + * We now lock against reads and writes. --rmk + */ + if (mutex_lock_interruptible(&nwflash_mutex)) + return -ERESTARTSYS; - if (p < gbFlashSize) { - if (count > gbFlashSize - p) - count = gbFlashSize - p; + ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize); + mutex_unlock(&nwflash_mutex); - /* - * We now lock against reads and writes. --rmk - */ - if (mutex_lock_interruptible(&nwflash_mutex)) - return -ERESTARTSYS; - - ret = copy_to_user(buf, (void *)(FLASH_BASE + p), count); - if (ret == 0) { - ret = count; - *ppos += count; - } else - ret = -EFAULT; - mutex_unlock(&nwflash_mutex); - } return ret; } diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index e4a4fbd..f070ae7 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -1896,7 +1896,7 @@ static int cm4000_probe(struct pcmcia_device *link) return ret; } - device_create(cmm_class, NULL, MKDEV(major, i), "cmm%d", i); + device_create_drvdata(cmm_class, NULL, MKDEV(major, i), NULL, "cmm%d", i); return 0; } diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index 6181f8a..0b5934b 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -653,7 +653,8 @@ static int reader_probe(struct pcmcia_device *link) return ret; } - device_create(cmx_class, NULL, MKDEV(major, i), "cmx%d", i); + device_create_drvdata(cmx_class, NULL, MKDEV(major, i), NULL, + "cmx%d", i); return 0; } diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index 929101e..4c1820c 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c @@ -30,11 +30,11 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw); static void handle_received_SETUP_packet(struct ipw_hardware *ipw, unsigned int address, - unsigned char *data, int len, + const unsigned char *data, int len, int is_last); static void ipwireless_setup_timer(unsigned long data); static void handle_received_CTRL_packet(struct ipw_hardware *hw, - unsigned int channel_idx, unsigned char *data, int len); + unsigned int channel_idx, const unsigned char *data, int len); /*#define TIMING_DIAGNOSTICS*/ @@ -79,8 +79,7 @@ static void report_timing(void) timing_stats.last_report_time = jiffies; if (!first) printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": %u us elapsed - read %lu bytes in %u us, " - "wrote %lu bytes in %u us\n", + ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n", jiffies_to_usecs(since), timing_stats.read_bytes, jiffies_to_usecs(timing_stats.read_time), @@ -133,29 +132,17 @@ enum { #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 struct nl_first_packet_header { -#if defined(__BIG_ENDIAN_BITFIELD) - unsigned char packet_rank:2; - unsigned char address:3; - unsigned char protocol:3; -#else unsigned char protocol:3; unsigned char address:3; unsigned char packet_rank:2; -#endif unsigned char length_lsb; unsigned char length_msb; }; struct nl_packet_header { -#if defined(__BIG_ENDIAN_BITFIELD) - unsigned char packet_rank:2; - unsigned char address:3; - unsigned char protocol:3; -#else unsigned char protocol:3; unsigned char address:3; unsigned char packet_rank:2; -#endif }; /* Value of 'packet_rank' above */ @@ -227,15 +214,12 @@ struct MEMINFREG { unsigned short memreg_tx_new; /* TX2 (new) Register (R/W) */ }; -#define IODMADPR 0x00 /* DMA Data Port Register (R/W) */ - #define CARD_PRESENT_VALUE (0xBEEFCAFEUL) #define MEMTX_TX 0x0001 #define MEMRX_RX 0x0001 #define MEMRX_RX_DONE 0x0001 #define MEMRX_PCINTACKK 0x0001 -#define MEMRX_MEMSPURIOUSINT 0x0001 #define NL_NUM_OF_PRIORITIES 3 #define NL_NUM_OF_PROTOCOLS 3 @@ -245,7 +229,7 @@ struct ipw_hardware { unsigned int base_port; short hw_version; unsigned short ll_mtu; - spinlock_t spinlock; + spinlock_t lock; int initializing; int init_loops; @@ -386,26 +370,52 @@ static void dump_data_bytes(const char *type, const unsigned char *data, length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); } -static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, +static void swap_packet_bitfield_to_le(unsigned char *data) +{ +#ifdef __BIG_ENDIAN_BITFIELD + unsigned char tmp = *data, ret = 0; + + /* + * transform bits from aa.bbb.ccc to ccc.bbb.aa + */ + ret |= tmp & 0xc0 >> 6; + ret |= tmp & 0x38 >> 1; + ret |= tmp & 0x07 << 5; + *data = ret & 0xff; +#endif +} + +static void swap_packet_bitfield_from_le(unsigned char *data) +{ +#ifdef __BIG_ENDIAN_BITFIELD + unsigned char tmp = *data, ret = 0; + + /* + * transform bits from ccc.bbb.aa to aa.bbb.ccc + */ + ret |= tmp & 0xe0 >> 5; + ret |= tmp & 0x1c << 1; + ret |= tmp & 0x03 << 6; + *data = ret & 0xff; +#endif +} + +static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data, unsigned length) { - int i; + unsigned i; unsigned long flags; start_timing(); - - if (length == 0) - return 0; - - if (length > hw->ll_mtu) - return -1; + BUG_ON(length > hw->ll_mtu); if (ipwireless_debug) dump_data_bytes("send", data, length); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->tx_ready = 0; + swap_packet_bitfield_to_le(data); if (hw->hw_version == HW_VERSION_1) { outw((unsigned short) length, hw->base_port + IODWR); @@ -414,7 +424,7 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, unsigned short d = data[i]; __le16 raw_data; - if (likely(i + 1 < length)) + if (i + 1 < length) d |= data[i + 1] << 8; raw_data = cpu_to_le16(d); outw(raw_data, hw->base_port + IODWR); @@ -422,32 +432,30 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, outw(DCR_TXDONE, hw->base_port + IODCR); } else if (hw->hw_version == HW_VERSION_2) { - outw((unsigned short) length, hw->base_port + IODMADPR); + outw((unsigned short) length, hw->base_port); for (i = 0; i < length; i += 2) { unsigned short d = data[i]; __le16 raw_data; - if ((i + 1 < length)) + if (i + 1 < length) d |= data[i + 1] << 8; raw_data = cpu_to_le16(d); - outw(raw_data, hw->base_port + IODMADPR); + outw(raw_data, hw->base_port); } while ((i & 3) != 2) { - outw((unsigned short) 0xDEAD, hw->base_port + IODMADPR); + outw((unsigned short) 0xDEAD, hw->base_port); i += 2; } writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx); } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); end_write_timing(length); - - return 0; } -static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) +static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) { unsigned short fragment_data_len; unsigned short data_left = packet->length - packet->offset; @@ -462,6 +470,10 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) if (data_left < fragment_data_len) fragment_data_len = data_left; + /* + * hdr_first is now in machine bitfield order, which will be swapped + * to le just before it goes to hw + */ pkt.hdr_first.protocol = packet->protocol; pkt.hdr_first.address = packet->dest_addr; pkt.hdr_first.packet_rank = 0; @@ -493,25 +505,23 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) */ unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); list_add(&packet->queue, &hw->tx_queue[0]); hw->tx_queued++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } else { if (packet->packet_callback) packet->packet_callback(packet->callback_data, packet->length); kfree(packet); } - - return 0; } static void ipw_setup_hardware(struct ipw_hardware *hw) { unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); if (hw->hw_version == HW_VERSION_1) { /* Reset RX FIFO */ outw(DCR_RXRESET, hw->base_port + IODCR); @@ -530,7 +540,7 @@ static void ipw_setup_hardware(struct ipw_hardware *hw) csr |= 1; writew(csr, &hw->memregs_CCR->reg_config_and_status); } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } /* @@ -549,28 +559,23 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, if (!packet) { unsigned long flags; - /* - * If this is the first fragment, then we will need to fetch a - * packet to put it in. - */ - spin_lock_irqsave(&hw->spinlock, flags); - /* If we have one in our pool, then pull it out. */ + spin_lock_irqsave(&hw->lock, flags); if (!list_empty(&hw->rx_pool)) { packet = list_first_entry(&hw->rx_pool, struct ipw_rx_packet, queue); - list_del(&packet->queue); hw->rx_pool_size--; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); + list_del(&packet->queue); } else { - /* Otherwise allocate a new one. */ - static int min_capacity = 256; + const int min_capacity = + ipwireless_ppp_mru(hw->network) + 2; int new_capacity; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); new_capacity = - minimum_free_space > min_capacity - ? minimum_free_space - : min_capacity; + (minimum_free_space > min_capacity + ? minimum_free_space + : min_capacity); packet = kmalloc(sizeof(struct ipw_rx_packet) + new_capacity, GFP_ATOMIC); if (!packet) @@ -580,10 +585,6 @@ static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw, packet->length = 0; } - /* - * If this packet does not have sufficient capacity for the data we - * want to add, then make it bigger. - */ if (packet->length + minimum_free_space > packet->capacity) { struct ipw_rx_packet *old_packet = packet; @@ -610,13 +611,15 @@ static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet) kfree(packet); else { hw->rx_pool_size++; - list_add_tail(&packet->queue, &hw->rx_pool); + list_add(&packet->queue, &hw->rx_pool); } } static void queue_received_packet(struct ipw_hardware *hw, - unsigned int protocol, unsigned int address, - unsigned char *data, int length, int is_last) + unsigned int protocol, + unsigned int address, + const unsigned char *data, int length, + int is_last) { unsigned int channel_idx = address - 1; struct ipw_rx_packet *packet = NULL; @@ -658,9 +661,9 @@ static void queue_received_packet(struct ipw_hardware *hw, packet = *assem; *assem = NULL; /* Count queued DATA bytes only */ - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_bytes_queued += packet->length; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } } else { /* If it's a CTRL packet, don't assemble, just queue it. */ @@ -682,13 +685,13 @@ static void queue_received_packet(struct ipw_hardware *hw, * network layer. */ if (packet) { - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); list_add_tail(&packet->queue, &hw->rx_queue); /* Block reception of incoming packets if queue is full. */ hw->blocking_rx = - hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE; + (hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE); - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); schedule_work(&hw->work_rx); } } @@ -702,7 +705,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) container_of(work_rx, struct ipw_hardware, work_rx); unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); while (!list_empty(&hw->rx_queue)) { struct ipw_rx_packet *packet = list_first_entry(&hw->rx_queue, @@ -720,7 +723,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) if (packet->protocol == TL_PROTOCOLID_COM_DATA) { if (hw->network != NULL) { /* If the network hasn't been disconnected. */ - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); /* * This must run unlocked due to tty processing * and mutex locking @@ -731,7 +734,7 @@ static void ipw_receive_data_work(struct work_struct *work_rx) (unsigned char *)packet + sizeof(struct ipw_rx_packet), packet->length); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); } /* Count queued DATA bytes only */ hw->rx_bytes_queued -= packet->length; @@ -755,15 +758,15 @@ static void ipw_receive_data_work(struct work_struct *work_rx) if (hw->shutting_down) break; } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } static void handle_received_CTRL_packet(struct ipw_hardware *hw, unsigned int channel_idx, - unsigned char *data, int len) + const unsigned char *data, int len) { - struct ipw_control_packet_body *body = - (struct ipw_control_packet_body *) data; + const struct ipw_control_packet_body *body = + (const struct ipw_control_packet_body *) data; unsigned int changed_mask; if (len != sizeof(struct ipw_control_packet_body)) { @@ -805,13 +808,13 @@ static void handle_received_CTRL_packet(struct ipw_hardware *hw, } static void handle_received_packet(struct ipw_hardware *hw, - union nl_packet *packet, + const union nl_packet *packet, unsigned short len) { unsigned int protocol = packet->hdr.protocol; unsigned int address = packet->hdr.address; unsigned int header_length; - unsigned char *data; + const unsigned char *data; unsigned int data_len; int is_last = packet->hdr.packet_rank & NL_LAST_PACKET; @@ -850,7 +853,7 @@ static void acknowledge_data_read(struct ipw_hardware *hw) static void do_receive_packet(struct ipw_hardware *hw) { unsigned len; - unsigned int i; + unsigned i; unsigned char pkt[LL_MTU_MAX]; start_timing(); @@ -859,8 +862,7 @@ static void do_receive_packet(struct ipw_hardware *hw) len = inw(hw->base_port + IODRR); if (len > hw->ll_mtu) { printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": received a packet of %u bytes - " - "longer than the MTU!\n", len); + ": received a packet of %u bytes - longer than the MTU!\n", len); outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR); return; } @@ -873,18 +875,17 @@ static void do_receive_packet(struct ipw_hardware *hw) pkt[i + 1] = (unsigned char) (data >> 8); } } else { - len = inw(hw->base_port + IODMADPR); + len = inw(hw->base_port); if (len > hw->ll_mtu) { printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": received a packet of %u bytes - " - "longer than the MTU!\n", len); + ": received a packet of %u bytes - longer than the MTU!\n", len); writew(MEMRX_PCINTACKK, &hw->memory_info_regs->memreg_pc_interrupt_ack); return; } for (i = 0; i < len; i += 2) { - __le16 raw_data = inw(hw->base_port + IODMADPR); + __le16 raw_data = inw(hw->base_port); unsigned short data = le16_to_cpu(raw_data); pkt[i] = (unsigned char) data; @@ -892,13 +893,15 @@ static void do_receive_packet(struct ipw_hardware *hw) } while ((i & 3) != 2) { - inw(hw->base_port + IODMADPR); + inw(hw->base_port); i += 2; } } acknowledge_data_read(hw); + swap_packet_bitfield_from_le(pkt); + if (ipwireless_debug) dump_data_bytes("recv", pkt, len); @@ -916,8 +919,7 @@ static int get_current_packet_priority(struct ipw_hardware *hw) * until setup is complete. */ return (hw->to_setup || hw->initializing - ? PRIO_SETUP + 1 : - NL_NUM_OF_PRIORITIES); + ? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES); } /* @@ -928,17 +930,17 @@ static int get_packets_from_hw(struct ipw_hardware *hw) int received = 0; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); while (hw->rx_ready && !hw->blocking_rx) { received = 1; hw->rx_ready--; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); do_receive_packet(hw); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return received; } @@ -954,7 +956,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) int more_to_send = 0; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); if (hw->tx_queued && hw->tx_ready) { int priority; struct ipw_tx_packet *packet = NULL; @@ -975,17 +977,17 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) } if (!packet) { hw->tx_queued = 0; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return 0; } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); /* Send */ do_send_packet(hw, packet); /* Check if more to send */ - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); for (priority = 0; priority < priority_limit; priority++) if (!list_empty(&hw->tx_queue[priority])) { more_to_send = 1; @@ -995,7 +997,7 @@ static int send_pending_packet(struct ipw_hardware *hw, int priority_limit) if (!more_to_send) hw->tx_queued = 0; } - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return more_to_send; } @@ -1008,9 +1010,9 @@ static void ipwireless_do_tasklet(unsigned long hw_) struct ipw_hardware *hw = (struct ipw_hardware *) hw_; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); if (hw->shutting_down) { - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); return; } @@ -1019,7 +1021,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) * Initial setup data sent to hardware */ hw->to_setup = 2; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); ipw_setup_hardware(hw); ipw_send_setup_packet(hw); @@ -1030,7 +1032,7 @@ static void ipwireless_do_tasklet(unsigned long hw_) int priority_limit = get_current_packet_priority(hw); int again; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); do { again = send_pending_packet(hw, priority_limit); @@ -1068,16 +1070,16 @@ static irqreturn_t ipwireless_handle_v1_interrupt(int irq, /* Transmit complete. */ if (irqn & IR_TXINTR) { ack |= IR_TXINTR; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } /* Received data */ if (irqn & IR_RXINTR) { ack |= IR_RXINTR; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_ready++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } if (ack != 0) { outw(ack, hw->base_port + IOIR); @@ -1128,9 +1130,8 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, } else { return IRQ_NONE; } - } else { + } else return IRQ_NONE; - } } /* @@ -1149,9 +1150,9 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, if (hw->serial_number_detected) { if (memtx_serial != hw->last_memtx_serial) { hw->last_memtx_serial = memtx_serial; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_ready++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); rx = 1; } else /* Ignore 'Timer Recovery' duplicates. */ @@ -1166,18 +1167,18 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": memreg_tx serial num detected\n"); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->rx_ready++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); } rx = 1; } } if (memrxdone & MEMRX_RX_DONE) { writew(0, &hw->memory_info_regs->memreg_rx_done); - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); tx = 1; } if (tx) @@ -1195,8 +1196,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, ": spurious interrupt - new_tx mode\n"); else { printk(KERN_WARNING IPWIRELESS_PCCARD_NAME - ": no valid memreg_tx value - " - "switching to the old memreg_tx\n"); + ": no valid memreg_tx value - switching to the old memreg_tx\n"); hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old; try_mem_tx_old = 1; @@ -1211,7 +1211,7 @@ static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq, return IRQ_HANDLED; } -irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t ipwireless_interrupt(int irq, void *dev_id) { struct ipw_hardware *hw = dev_id; @@ -1226,9 +1226,9 @@ static void flush_packets_to_hw(struct ipw_hardware *hw) int priority_limit; unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); priority_limit = get_current_packet_priority(hw); - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); while (send_pending_packet(hw, priority_limit)); } @@ -1238,10 +1238,10 @@ static void send_packet(struct ipw_hardware *hw, int priority, { unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); list_add_tail(&packet->queue, &hw->tx_queue[priority]); hw->tx_queued++; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); flush_packets_to_hw(hw); } @@ -1291,21 +1291,20 @@ static void *alloc_ctrl_packet(int header_size, } int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, - unsigned char *data, unsigned int length, + const unsigned char *data, unsigned int length, void (*callback) (void *cb, unsigned int length), void *callback_data) { struct ipw_tx_packet *packet; - packet = alloc_data_packet(length, - (unsigned char) (channel_idx + 1), - TL_PROTOCOLID_COM_DATA); + packet = alloc_data_packet(length, (channel_idx + 1), + TL_PROTOCOLID_COM_DATA); if (!packet) return -ENOMEM; packet->packet_callback = callback; packet->callback_data = callback_data; - memcpy((unsigned char *) packet + - sizeof(struct ipw_tx_packet), data, length); + memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data, + length); send_packet(hw, PRIO_DATA, packet); return 0; @@ -1321,12 +1320,11 @@ static int set_control_line(struct ipw_hardware *hw, int prio, protocolid = TL_PROTOCOLID_SETUP; packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet), - (unsigned char) (channel_idx + 1), - protocolid, line); + (channel_idx + 1), protocolid, line); if (!packet) return -ENOMEM; packet->header.length = sizeof(struct ipw_control_packet_body); - packet->body.value = (unsigned char) (state == 0 ? 0 : 1); + packet->body.value = (state == 0 ? 0 : 1); send_packet(hw, prio, &packet->header); return 0; } @@ -1504,8 +1502,7 @@ static void handle_setup_get_version_rsp(struct ipw_hardware *hw, if (vers_no == TL_SETUP_VERSION) __handle_setup_get_version_rsp(hw); else - printk(KERN_ERR - IPWIRELESS_PCCARD_NAME + printk(KERN_ERR IPWIRELESS_PCCARD_NAME ": invalid hardware version no %u\n", (unsigned int) vers_no); } @@ -1528,10 +1525,10 @@ static void ipw_send_setup_packet(struct ipw_hardware *hw) static void handle_received_SETUP_packet(struct ipw_hardware *hw, unsigned int address, - unsigned char *data, int len, + const unsigned char *data, int len, int is_last) { - union ipw_setup_rx_msg *rx_msg = (union ipw_setup_rx_msg *) data; + const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data; if (address != ADDR_SETUP_PROT) { printk(KERN_INFO IPWIRELESS_PCCARD_NAME @@ -1629,7 +1626,7 @@ struct ipw_hardware *ipwireless_hardware_create(void) INIT_LIST_HEAD(&hw->rx_queue); INIT_LIST_HEAD(&hw->rx_pool); - spin_lock_init(&hw->spinlock); + spin_lock_init(&hw->lock); tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw); INIT_WORK(&hw->work_rx, ipw_receive_data_work); setup_timer(&hw->setup_timer, ipwireless_setup_timer, @@ -1651,8 +1648,8 @@ void ipwireless_init_hardware_v1(struct ipw_hardware *hw, enable_irq(hw->irq); } hw->base_port = base_port; - hw->hw_version = is_v2_card ? HW_VERSION_2 : HW_VERSION_1; - hw->ll_mtu = hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2; + hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1); + hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2); hw->memregs_CCR = (struct MEMCCR __iomem *) ((unsigned short __iomem *) attr_memory + 0x200); hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory; @@ -1695,10 +1692,10 @@ static void ipwireless_setup_timer(unsigned long data) if (is_card_present(hw)) { unsigned long flags; - spin_lock_irqsave(&hw->spinlock, flags); + spin_lock_irqsave(&hw->lock, flags); hw->to_setup = 1; hw->tx_ready = 1; - spin_unlock_irqrestore(&hw->spinlock, flags); + spin_unlock_irqrestore(&hw->lock, flags); tasklet_schedule(&hw->tasklet); } diff --git a/drivers/char/pcmcia/ipwireless/hardware.h b/drivers/char/pcmcia/ipwireless/hardware.h index 19ce5eb..90a8590 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.h +++ b/drivers/char/pcmcia/ipwireless/hardware.h @@ -34,14 +34,14 @@ struct ipw_network; struct ipw_hardware *ipwireless_hardware_create(void); void ipwireless_hardware_free(struct ipw_hardware *hw); -irqreturn_t ipwireless_interrupt(int irq, void *dev_id, struct pt_regs *regs); +irqreturn_t ipwireless_interrupt(int irq, void *dev_id); int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx, int state); int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx, int state); int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx, - unsigned char *data, + const unsigned char *data, unsigned int length, void (*packet_sent_callback) (void *cb, unsigned int length), diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c index cc7dcea..5eca7a9 100644 --- a/drivers/char/pcmcia/ipwireless/main.c +++ b/drivers/char/pcmcia/ipwireless/main.c @@ -49,7 +49,7 @@ static void ipwireless_detach(struct pcmcia_device *link); /* Debug mode: more verbose, print sent/recv bytes */ int ipwireless_debug; int ipwireless_loopback; -int ipwireless_out_queue = 1; +int ipwireless_out_queue = 10; module_param_named(debug, ipwireless_debug, int, 0); module_param_named(loopback, ipwireless_loopback, int, 0); @@ -57,7 +57,7 @@ module_param_named(out_queue, ipwireless_out_queue, int, 0); MODULE_PARM_DESC(debug, "switch on debug messages [0]"); MODULE_PARM_DESC(loopback, "debug: enable ras_raw channel [0]"); -MODULE_PARM_DESC(out_queue, "debug: set size of outgoing queue [1]"); +MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]"); /* Executes in process context. */ static void signalled_reboot_work(struct work_struct *work_reboot) @@ -88,8 +88,6 @@ static int config_ipwireless(struct ipw_dev *ipw) unsigned short buf[64]; cisparse_t parse; unsigned short cor_value; - win_req_t request_attr_memory; - win_req_t request_common_memory; memreq_t memreq_attr_memory; memreq_t memreq_common_memory; @@ -188,6 +186,9 @@ static int config_ipwireless(struct ipw_dev *ipw) goto exit0; } + request_region(link->io.BasePort1, link->io.NumPorts1, + IPWIRELESS_PCCARD_NAME); + /* memory settings */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; @@ -214,16 +215,16 @@ static int config_ipwireless(struct ipw_dev *ipw) } if (parse.cftable_entry.mem.nwin > 0) { - request_common_memory.Attributes = + ipw->request_common_memory.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE; - request_common_memory.Base = + ipw->request_common_memory.Base = parse.cftable_entry.mem.win[0].host_addr; - request_common_memory.Size = parse.cftable_entry.mem.win[0].len; - if (request_common_memory.Size < 0x1000) - request_common_memory.Size = 0x1000; - request_common_memory.AccessSpeed = 0; + ipw->request_common_memory.Size = parse.cftable_entry.mem.win[0].len; + if (ipw->request_common_memory.Size < 0x1000) + ipw->request_common_memory.Size = 0x1000; + ipw->request_common_memory.AccessSpeed = 0; - ret = pcmcia_request_window(&link, &request_common_memory, + ret = pcmcia_request_window(&link, &ipw->request_common_memory, &ipw->handle_common_memory); if (ret != CS_SUCCESS) { @@ -246,16 +247,18 @@ static int config_ipwireless(struct ipw_dev *ipw) ipw->is_v2_card = parse.cftable_entry.mem.win[0].len == 0x100; - ipw->common_memory = ioremap(request_common_memory.Base, - request_common_memory.Size); + ipw->common_memory = ioremap(ipw->request_common_memory.Base, + ipw->request_common_memory.Size); + request_mem_region(ipw->request_common_memory.Base, + ipw->request_common_memory.Size, IPWIRELESS_PCCARD_NAME); - request_attr_memory.Attributes = + ipw->request_attr_memory.Attributes = WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE; - request_attr_memory.Base = 0; - request_attr_memory.Size = 0; /* this used to be 0x1000 */ - request_attr_memory.AccessSpeed = 0; + ipw->request_attr_memory.Base = 0; + ipw->request_attr_memory.Size = 0; /* this used to be 0x1000 */ + ipw->request_attr_memory.AccessSpeed = 0; - ret = pcmcia_request_window(&link, &request_attr_memory, + ret = pcmcia_request_window(&link, &ipw->request_attr_memory, &ipw->handle_attr_memory); if (ret != CS_SUCCESS) { @@ -274,8 +277,10 @@ static int config_ipwireless(struct ipw_dev *ipw) goto exit2; } - ipw->attr_memory = ioremap(request_attr_memory.Base, - request_attr_memory.Size); + ipw->attr_memory = ioremap(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size); + request_mem_region(ipw->request_attr_memory.Base, ipw->request_attr_memory.Size, + IPWIRELESS_PCCARD_NAME); } INIT_WORK(&ipw->work_reboot, signalled_reboot_work); @@ -311,14 +316,13 @@ static int config_ipwireless(struct ipw_dev *ipw) (unsigned int) link->irq.AssignedIRQ); if (ipw->attr_memory && ipw->common_memory) printk(KERN_INFO IPWIRELESS_PCCARD_NAME - ": attr memory 0x%08lx-0x%08lx, " - "common memory 0x%08lx-0x%08lx\n", - request_attr_memory.Base, - request_attr_memory.Base - + request_attr_memory.Size - 1, - request_common_memory.Base, - request_common_memory.Base - + request_common_memory.Size - 1); + ": attr memory 0x%08lx-0x%08lx, common memory 0x%08lx-0x%08lx\n", + ipw->request_attr_memory.Base, + ipw->request_attr_memory.Base + + ipw->request_attr_memory.Size - 1, + ipw->request_common_memory.Base, + ipw->request_common_memory.Base + + ipw->request_common_memory.Size - 1); ipw->network = ipwireless_network_create(ipw->hardware); if (!ipw->network) @@ -350,12 +354,16 @@ exit4: pcmcia_disable_device(link); exit3: if (ipw->attr_memory) { + release_mem_region(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size); iounmap(ipw->attr_memory); pcmcia_release_window(ipw->handle_attr_memory); pcmcia_disable_device(link); } exit2: if (ipw->common_memory) { + release_mem_region(ipw->request_common_memory.Base, + ipw->request_common_memory.Size); iounmap(ipw->common_memory); pcmcia_release_window(ipw->handle_common_memory); } @@ -367,19 +375,25 @@ exit0: static void release_ipwireless(struct ipw_dev *ipw) { - struct pcmcia_device *link = ipw->link; - - pcmcia_disable_device(link); + pcmcia_disable_device(ipw->link); - if (ipw->common_memory) + if (ipw->common_memory) { + release_mem_region(ipw->request_common_memory.Base, + ipw->request_common_memory.Size); iounmap(ipw->common_memory); - if (ipw->attr_memory) + } + if (ipw->attr_memory) { + release_mem_region(ipw->request_attr_memory.Base, + ipw->request_attr_memory.Size); iounmap(ipw->attr_memory); + } if (ipw->common_memory) pcmcia_release_window(ipw->handle_common_memory); if (ipw->attr_memory) pcmcia_release_window(ipw->handle_attr_memory); - pcmcia_disable_device(link); + + /* Break the link with Card Services */ + pcmcia_disable_device(ipw->link); } /* @@ -437,10 +451,6 @@ static void ipwireless_detach(struct pcmcia_device *link) release_ipwireless(ipw); - /* Break the link with Card Services */ - if (link) - pcmcia_disable_device(link); - if (ipw->tty != NULL) ipwireless_tty_free(ipw->tty); if (ipw->network != NULL) diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h index 1bfdcc8..0e0363a 100644 --- a/drivers/char/pcmcia/ipwireless/main.h +++ b/drivers/char/pcmcia/ipwireless/main.h @@ -45,10 +45,15 @@ struct ipw_tty; struct ipw_dev { struct pcmcia_device *link; int is_v2_card; + window_handle_t handle_attr_memory; void __iomem *attr_memory; + win_req_t request_attr_memory; + window_handle_t handle_common_memory; void __iomem *common_memory; + win_req_t request_common_memory; + dev_node_t nodes[2]; /* Reference to attribute memory, containing CIS data */ void *attribute_memory; diff --git a/drivers/char/pcmcia/ipwireless/network.c b/drivers/char/pcmcia/ipwireless/network.c index fe914d3..590762a 100644 --- a/drivers/char/pcmcia/ipwireless/network.c +++ b/drivers/char/pcmcia/ipwireless/network.c @@ -29,7 +29,6 @@ #include "main.h" #include "tty.h" -#define MAX_OUTGOING_PACKETS_QUEUED ipwireless_out_queue #define MAX_ASSOCIATED_TTYS 2 #define SC_RCV_BITS (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP) @@ -46,7 +45,7 @@ struct ipw_network { /* Number of packets queued up in hardware module. */ int outgoing_packets_queued; /* Spinlock to avoid interrupts during shutdown */ - spinlock_t spinlock; + spinlock_t lock; struct mutex close_lock; /* PPP ioctl data, not actually used anywere */ @@ -68,20 +67,20 @@ static void notify_packet_sent(void *callback_data, unsigned int packet_length) struct ipw_network *network = callback_data; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); network->outgoing_packets_queued--; if (network->ppp_channel != NULL) { if (network->ppp_blocked) { network->ppp_blocked = 0; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); ppp_output_wakeup(network->ppp_channel); if (ipwireless_debug) - printk(KERN_INFO IPWIRELESS_PCCARD_NAME + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp unblocked\n"); } else - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); } else - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); } /* @@ -93,8 +92,8 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, struct ipw_network *network = ppp_channel->private; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); - if (network->outgoing_packets_queued < MAX_OUTGOING_PACKETS_QUEUED) { + spin_lock_irqsave(&network->lock, flags); + if (network->outgoing_packets_queued < ipwireless_out_queue) { unsigned char *buf; static unsigned char header[] = { PPP_ALLSTATIONS, /* 0xff */ @@ -103,7 +102,7 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, int ret; network->outgoing_packets_queued++; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); /* * If we have the requested amount of headroom in the skb we @@ -144,7 +143,9 @@ static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel, * needs to be unblocked once we are ready to send. */ network->ppp_blocked = 1; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); + if (ipwireless_debug) + printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n"); return 0; } } @@ -249,11 +250,11 @@ static void do_go_online(struct work_struct *work_go_online) work_go_online); unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (!network->ppp_channel) { struct ppp_channel *channel; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL); if (!channel) { printk(KERN_ERR IPWIRELESS_PCCARD_NAME @@ -273,10 +274,10 @@ static void do_go_online(struct work_struct *work_go_online) network->xaccm[3] = 0x60000000U; network->raccm = ~0U; ppp_register_channel(channel); - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); network->ppp_channel = channel; } - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); } static void do_go_offline(struct work_struct *work_go_offline) @@ -287,16 +288,16 @@ static void do_go_offline(struct work_struct *work_go_offline) unsigned long flags; mutex_lock(&network->close_lock); - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) { struct ppp_channel *channel = network->ppp_channel; network->ppp_channel = NULL; - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); mutex_unlock(&network->close_lock); ppp_unregister_channel(channel); } else { - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); mutex_unlock(&network->close_lock); } } @@ -381,18 +382,18 @@ void ipwireless_network_packet_received(struct ipw_network *network, * the PPP layer. */ mutex_lock(&network->close_lock); - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) { struct sk_buff *skb; - spin_unlock_irqrestore(&network->spinlock, + spin_unlock_irqrestore(&network->lock, flags); /* Send the data to the ppp_generic module. */ skb = ipw_packet_received_skb(data, length); ppp_input(network->ppp_channel, skb); } else - spin_unlock_irqrestore(&network->spinlock, + spin_unlock_irqrestore(&network->lock, flags); mutex_unlock(&network->close_lock); } @@ -410,7 +411,7 @@ struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw) if (!network) return NULL; - spin_lock_init(&network->spinlock); + spin_lock_init(&network->lock); mutex_init(&network->close_lock); network->hardware = hw; @@ -478,10 +479,10 @@ int ipwireless_ppp_channel_index(struct ipw_network *network) int ret = -1; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) ret = ppp_channel_index(network->ppp_channel); - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); return ret; } @@ -491,10 +492,15 @@ int ipwireless_ppp_unit_number(struct ipw_network *network) int ret = -1; unsigned long flags; - spin_lock_irqsave(&network->spinlock, flags); + spin_lock_irqsave(&network->lock, flags); if (network->ppp_channel != NULL) ret = ppp_unit_number(network->ppp_channel); - spin_unlock_irqrestore(&network->spinlock, flags); + spin_unlock_irqrestore(&network->lock, flags); return ret; } + +int ipwireless_ppp_mru(const struct ipw_network *network) +{ + return network->mru; +} diff --git a/drivers/char/pcmcia/ipwireless/network.h b/drivers/char/pcmcia/ipwireless/network.h index ccacd26..561f765 100644 --- a/drivers/char/pcmcia/ipwireless/network.h +++ b/drivers/char/pcmcia/ipwireless/network.h @@ -48,5 +48,6 @@ void ipwireless_ppp_open(struct ipw_network *net); void ipwireless_ppp_close(struct ipw_network *net); int ipwireless_ppp_channel_index(struct ipw_network *net); int ipwireless_ppp_unit_number(struct ipw_network *net); +int ipwireless_ppp_mru(const struct ipw_network *net); #endif diff --git a/drivers/char/pcmcia/ipwireless/tty.c b/drivers/char/pcmcia/ipwireless/tty.c index 42f3815..b141450 100644 --- a/drivers/char/pcmcia/ipwireless/tty.c +++ b/drivers/char/pcmcia/ipwireless/tty.c @@ -259,7 +259,7 @@ static int ipw_write(struct tty_struct *linux_tty, } ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS, - (unsigned char *) buf, count, + buf, count, ipw_write_packet_sent_callback, tty); if (ret == -1) { mutex_unlock(&tty->ipw_tty_mutex); diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index b694d43..c240562 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c @@ -232,7 +232,6 @@ typedef struct _mgslpc_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -459,13 +458,11 @@ static int ttymajor=0; static int debug_level = 0; static int maxframe[MAX_DEVICE_COUNT] = {0,}; -static int dosyncppp[MAX_DEVICE_COUNT] = {1,1,1,1}; module_param(break_on_load, bool, 0); module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); MODULE_LICENSE("GPL"); @@ -2230,7 +2227,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file, * Arguments: tty pointer to tty instance data * break_state -1=set break condition, 0=clear */ -static void mgslpc_break(struct tty_struct *tty, int break_state) +static int mgslpc_break(struct tty_struct *tty, int break_state) { MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; unsigned long flags; @@ -2240,7 +2237,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state) __FILE__,__LINE__, info->device_name, break_state); if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break")) - return; + return -EINVAL; spin_lock_irqsave(&info->lock,flags); if (break_state == -1) @@ -2248,6 +2245,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state) else clear_reg_bits(info, CHA+DAFO, BIT6); spin_unlock_irqrestore(&info->lock,flags); + return 0; } /* Service an IOCTL request @@ -2914,7 +2912,6 @@ static void mgslpc_add_device(MGSLPC_INFO *info) if (info->line < MAX_DEVICE_COUNT) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } mgslpc_device_count++; diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index f6e6aca..bee39fd 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c @@ -67,7 +67,7 @@ #include <linux/major.h> #include <linux/ppdev.h> #include <linux/smp_lock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #define PP_VERSION "ppdev: user-space parallel port driver" #define CHRDEV "ppdev" @@ -328,10 +328,9 @@ static enum ieee1284_phase init_phase (int mode) return IEEE1284_PH_FWD_IDLE; } -static int pp_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) +static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - unsigned int minor = iminor(inode); + unsigned int minor = iminor(file->f_path.dentry->d_inode); struct pp_struct *pp = file->private_data; struct parport * port; void __user *argp = (void __user *)arg; @@ -634,6 +633,15 @@ static int pp_ioctl(struct inode *inode, struct file *file, return 0; } +static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + long ret; + lock_kernel(); + ret = pp_do_ioctl(file, cmd, arg); + unlock_kernel(); + return ret; +} + static int pp_open (struct inode * inode, struct file * file) { unsigned int minor = iminor(inode); @@ -745,15 +753,16 @@ static const struct file_operations pp_fops = { .read = pp_read, .write = pp_write, .poll = pp_poll, - .ioctl = pp_ioctl, + .unlocked_ioctl = pp_ioctl, .open = pp_open, .release = pp_release, }; static void pp_attach(struct parport *port) { - device_create(ppdev_class, port->dev, MKDEV(PP_MAJOR, port->number), - "parport%d", port->number); + device_create_drvdata(ppdev_class, port->dev, + MKDEV(PP_MAJOR, port->number), + NULL, "parport%d", port->number); } static void pp_detach(struct parport *port) diff --git a/drivers/char/random.c b/drivers/char/random.c index 0cf98bd..e0d0e37 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -236,6 +236,7 @@ #include <linux/fs.h> #include <linux/genhd.h> #include <linux/interrupt.h> +#include <linux/mm.h> #include <linux/spinlock.h> #include <linux/percpu.h> #include <linux/cryptohash.h> diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 505fcbe..47b8cf2 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -131,8 +131,8 @@ raw_ioctl(struct inode *inode, struct file *filp, static void bind_device(struct raw_config_request *rq) { device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor)); - device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), - "raw%d", rq->raw_minor); + device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), + NULL, "raw%d", rq->raw_minor); } /* @@ -283,7 +283,8 @@ static int __init raw_init(void) ret = PTR_ERR(raw_class); goto error_region; } - device_create(raw_class, NULL, MKDEV(RAW_MAJOR, 0), "rawctl"); + device_create_drvdata(raw_class, NULL, MKDEV(RAW_MAJOR, 0), NULL, + "rawctl"); return 0; diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c index 0cdfee1..a8f68a3 100644 --- a/drivers/char/rio/rio_linux.c +++ b/drivers/char/rio/rio_linux.c @@ -179,7 +179,7 @@ static int rio_set_real_termios(void *ptr); static void rio_hungup(void *ptr); static void rio_close(void *ptr); static int rio_chars_in_buffer(void *ptr); -static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); static int rio_init_drivers(void); static void my_hd(void *addr, int len); @@ -240,7 +240,7 @@ static struct real_driver rio_real_driver = { static const struct file_operations rio_fw_fops = { .owner = THIS_MODULE, - .ioctl = rio_fw_ioctl, + .unlocked_ioctl = rio_fw_ioctl, }; static struct miscdevice rio_fw_device = { @@ -560,13 +560,15 @@ static void rio_close(void *ptr) -static int rio_fw_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) +static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int rc = 0; func_enter(); /* The "dev" argument isn't used. */ + lock_kernel(); rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN)); + unlock_kernel(); func_exit(); return rc; diff --git a/drivers/char/riscom8.c b/drivers/char/riscom8.c index 724b2b2..2c6c8f3 100644 --- a/drivers/char/riscom8.c +++ b/drivers/char/riscom8.c @@ -1250,11 +1250,15 @@ static int rc_tiocmset(struct tty_struct *tty, struct file *file, return 0; } -static void rc_send_break(struct riscom_port *port, unsigned long length) +static int rc_send_break(struct tty_struct *tty, int length) { + struct riscom_port *port = (struct riscom_port *)tty->driver_data; struct riscom_board *bp = port_Board(port); unsigned long flags; + if (length == 0 || length == -1) + return -EOPNOTSUPP; + spin_lock_irqsave(&riscom_lock, flags); port->break_length = RISCOM_TPS / HZ * length; @@ -1268,6 +1272,7 @@ static void rc_send_break(struct riscom_port *port, unsigned long length) rc_wait_CCR(bp); spin_unlock_irqrestore(&riscom_lock, flags); + return 0; } static int rc_set_serial_info(struct riscom_port *port, @@ -1342,27 +1347,12 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp, { struct riscom_port *port = (struct riscom_port *)tty->driver_data; void __user *argp = (void __user *)arg; - int retval = 0; + int retval; if (rc_paranoia_check(port, tty->name, "rc_ioctl")) return -ENODEV; switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - if (!arg) - rc_send_break(port, HZ/4); /* 1/4 second */ - break; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - rc_send_break(port, arg ? arg*(HZ/10) : HZ/4); - break; case TIOCGSERIAL: lock_kernel(); retval = rc_get_serial_info(port, argp); @@ -1517,6 +1507,7 @@ static const struct tty_operations riscom_ops = { .hangup = rc_hangup, .tiocmget = rc_tiocmget, .tiocmset = rc_tiocmset, + .break_ctl = rc_send_break, }; static int __init rc_init_drivers(void) @@ -1538,7 +1529,7 @@ static int __init rc_init_drivers(void) B9600 | CS8 | CREAD | HUPCL | CLOCAL; riscom_driver->init_termios.c_ispeed = 9600; riscom_driver->init_termios.c_ospeed = 9600; - riscom_driver->flags = TTY_DRIVER_REAL_RAW; + riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK; tty_set_operations(riscom_driver, &riscom_ops); error = tty_register_driver(riscom_driver); if (error != 0) { diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index e670eae..584d791 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c @@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty, } } -static void rp_break(struct tty_struct *tty, int break_state) +static int rp_break(struct tty_struct *tty, int break_state) { struct r_port *info = (struct r_port *) tty->driver_data; unsigned long flags; if (rocket_paranoia_check(info, "rp_break")) - return; + return -EINVAL; spin_lock_irqsave(&info->slock, flags); if (break_state == -1) @@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state) else sClrBreak(&info->channel); spin_unlock_irqrestore(&info->slock, flags); + return 0; } /* diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index fa92a8a..f53d4d0 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -78,9 +78,9 @@ #include <linux/wait.h> #include <linux/bcd.h> #include <linux/delay.h> +#include <linux/uaccess.h> #include <asm/current.h> -#include <asm/uaccess.h> #include <asm/system.h> #ifdef CONFIG_X86 @@ -120,8 +120,6 @@ static irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id) return 0; } #endif -#else -extern irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id); #endif /* @@ -144,8 +142,8 @@ static DEFINE_TIMER(rtc_irq_timer, rtc_dropped_irq, 0, 0); static ssize_t rtc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos); -static int rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg); +static void rtc_get_rtc_time(struct rtc_time *rtc_tm); #ifdef RTC_IRQ static unsigned int rtc_poll(struct file *file, poll_table *wait); @@ -237,7 +235,7 @@ static inline unsigned char rtc_is_updating(void) * (See ./arch/XXXX/kernel/time.c for the set_rtc_mmss() function.) */ -irqreturn_t rtc_interrupt(int irq, void *dev_id) +static irqreturn_t rtc_interrupt(int irq, void *dev_id) { /* * Can be an alarm interrupt, update complete interrupt, @@ -719,10 +717,13 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) &wtime, sizeof wtime) ? -EFAULT : 0; } -static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, - unsigned long arg) +static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - return rtc_do_ioctl(cmd, arg, 0); + long ret; + lock_kernel(); + ret = rtc_do_ioctl(cmd, arg, 0); + unlock_kernel(); + return ret; } /* @@ -915,7 +916,7 @@ static const struct file_operations rtc_fops = { #ifdef RTC_IRQ .poll = rtc_poll, #endif - .ioctl = rtc_ioctl, + .unlocked_ioctl = rtc_ioctl, .open = rtc_open, .release = rtc_release, .fasync = rtc_fasync, @@ -1302,7 +1303,7 @@ static int rtc_proc_open(struct inode *inode, struct file *file) } #endif -void rtc_get_rtc_time(struct rtc_time *rtc_tm) +static void rtc_get_rtc_time(struct rtc_time *rtc_tm) { unsigned long uip_watchdog = jiffies, flags; unsigned char ctrl; diff --git a/drivers/char/ser_a2232.c b/drivers/char/ser_a2232.c index 4ba3aec..7b0c352 100644 --- a/drivers/char/ser_a2232.c +++ b/drivers/char/ser_a2232.c @@ -192,7 +192,7 @@ static inline void a2232_receive_char(struct a2232_port *port, int ch, int err) Maybe one could implement a more efficient version by not only transferring one character at a time. */ - struct tty_struct *tty = port->gs.tty; + struct tty_struct *tty = port->gs.port.tty; #if 0 switch(err) { @@ -226,7 +226,7 @@ static void a2232_disable_tx_interrupts(void *ptr) /* Does this here really have to be? */ local_irq_save(flags); - port->gs.flags &= ~GS_TX_INTEN; + port->gs.port.flags &= ~GS_TX_INTEN; local_irq_restore(flags); } @@ -242,7 +242,7 @@ static void a2232_enable_tx_interrupts(void *ptr) /* Does this here really have to be? */ local_irq_save(flags); - port->gs.flags |= GS_TX_INTEN; + port->gs.port.flags |= GS_TX_INTEN; local_irq_restore(flags); } @@ -276,9 +276,9 @@ static void a2232_shutdown_port(void *ptr) local_irq_save(flags); - port->gs.flags &= ~GS_ACTIVE; + port->gs.port.flags &= ~GS_ACTIVE; - if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { + if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { /* Set DTR and RTS to Low, flush output. The NetBSD driver "msc.c" does it this way. */ stat->Command = ( (stat->Command & ~A2232CMD_CMask) | @@ -309,7 +309,7 @@ static int a2232_set_real_termios(void *ptr) volatile struct a2232status *status; volatile struct a2232memory *mem; - if (!port->gs.tty || !port->gs.tty->termios) return 0; + if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; status = a2232stat(port->which_a2232, port->which_port_on_a2232); mem = a2232mem(port->which_a2232); @@ -345,7 +345,7 @@ static int a2232_set_real_termios(void *ptr) } a2232_param |= rate; - cflag = port->gs.tty->termios->c_cflag; + cflag = port->gs.port.tty->termios->c_cflag; // get character size chsize = cflag & CSIZE; @@ -382,7 +382,7 @@ static int a2232_set_real_termios(void *ptr) the conventional way of inserting START/STOP characters by hand in throttle()/unthrottle(). */ - softflow = !!( port->gs.tty->termios->c_iflag & IXOFF ); + softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF ); // get Parity (Enabled/Disabled? If Enabled, Odd or Even?) parity = cflag & (PARENB | PARODD); @@ -400,9 +400,9 @@ static int a2232_set_real_termios(void *ptr) /* Hmm. Maybe an own a2232_port structure member would be cleaner? */ if (cflag & CLOCAL) - port->gs.flags &= ~ASYNC_CHECK_CD; + port->gs.port.flags &= ~ASYNC_CHECK_CD; else - port->gs.flags |= ASYNC_CHECK_CD; + port->gs.port.flags |= ASYNC_CHECK_CD; /* Now we have all parameters and can go to set them: */ @@ -482,18 +482,18 @@ static int a2232_open(struct tty_struct * tty, struct file * filp) port = &a2232_ports[line]; tty->driver_data = port; - port->gs.tty = tty; - port->gs.count++; + port->gs.port.tty = tty; + port->gs.port.count++; retval = gs_init_port(&port->gs); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } - port->gs.flags |= GS_ACTIVE; + port->gs.port.flags |= GS_ACTIVE; retval = gs_block_til_ready(port, filp); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } @@ -522,7 +522,7 @@ int ch, err, n, p; for (p = 0; p < NUMLINES; p++){ /* for every port on this board */ err = 0; port = &a2232_ports[n*NUMLINES+p]; - if ( port->gs.flags & GS_ACTIVE ){ /* if the port is used */ + if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */ status = a2232stat(n,p); @@ -577,8 +577,8 @@ int ch, err, n, p; obuf = mem->OutBuf[p]; bufpos = status->OutHead; while ( (port->gs.xmit_cnt > 0) && - (!port->gs.tty->stopped) && - (!port->gs.tty->hw_stopped) ){ /* While there are chars to transmit */ + (!port->gs.port.tty->stopped) && + (!port->gs.port.tty->hw_stopped) ){ /* While there are chars to transmit */ if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */ ch = port->gs.xmit_buf[port->gs.xmit_tail]; /* get the next char to transmit */ port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */ @@ -592,8 +592,8 @@ int ch, err, n, p; status->OutHead = bufpos; /* WakeUp if output buffer runs low */ - if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) { - tty_wakeup(port->gs.tty); + if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) { + tty_wakeup(port->gs.port.tty); } } // if the port is used } // for every port on the board @@ -613,16 +613,16 @@ int ch, err, n, p; struct a2232_port *port = &a2232_ports[n*7+p]; port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */ - if (!(port->gs.flags & ASYNC_CHECK_CD)) + if (!(port->gs.port.flags & ASYNC_CHECK_CD)) ; /* Don't report DCD changes */ else if (port->cd_status) { // if DCD on: DCD went UP! /* Are we blocking in open?*/ - wake_up_interruptible(&port->gs.open_wait); + wake_up_interruptible(&port->gs.port.open_wait); } else { // if DCD off: DCD went DOWN! - if (port->gs.tty) - tty_hangup (port->gs.tty); + if (port->gs.port.tty) + tty_hangup (port->gs.port.tty); } } // if CD changed for this port @@ -655,8 +655,8 @@ static void a2232_init_portstructs(void) #ifdef NEW_WRITE_LOCKING mutex_init(&(port->gs.port_write_mutex)); #endif - init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); + init_waitqueue_head(&port->gs.port.open_wait); + init_waitqueue_head(&port->gs.port.close_wait); } } diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c index 0b799ac..3ce60df 100644 --- a/drivers/char/snsc.c +++ b/drivers/char/snsc.c @@ -444,7 +444,8 @@ scdrv_init(void) continue; } - device_create(snsc_class, NULL, dev, "%s", devname); + device_create_drvdata(snsc_class, NULL, dev, NULL, + "%s", devname); ia64_sn_irtr_intr_enable(scd->scd_nasid, 0 /*ignored */ , diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 037dc47..242fd46 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -77,7 +77,7 @@ #include <linux/module.h> -#include <asm/io.h> +#include <linux/io.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/ioport.h> @@ -92,7 +92,7 @@ #include <linux/delay.h> #include <linux/pci.h> #include <linux/init.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "specialix_io8.h" #include "cd1865.h" @@ -110,9 +110,10 @@ static int sx_debug; static int sx_rxfifo = SPECIALIX_RXFIFO; +static int sx_rtscts; #ifdef DEBUG -#define dprintk(f, str...) if (sx_debug & f) printk (str) +#define dprintk(f, str...) if (sx_debug & f) printk(str) #else #define dprintk(f, str...) /* nothing */ #endif @@ -131,10 +132,8 @@ static int sx_rxfifo = SPECIALIX_RXFIFO; #define SX_DEBUG_FIFO 0x0800 -#define func_enter() dprintk (SX_DEBUG_FLOW, "io8: enter %s\n",__func__) -#define func_exit() dprintk (SX_DEBUG_FLOW, "io8: exit %s\n", __func__) - -#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1) +#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__) +#define func_exit() dprintk(SX_DEBUG_FLOW, "io8: exit %s\n", __func__) /* Configurable options: */ @@ -142,17 +141,6 @@ static int sx_rxfifo = SPECIALIX_RXFIFO; /* Am I paranoid or not ? ;-) */ #define SPECIALIX_PARANOIA_CHECK -/* Do I trust the IRQ from the card? (enabeling it doesn't seem to help) - When the IRQ routine leaves the chip in a state that is keeps on - requiring attention, the timer doesn't help either. */ -#undef SPECIALIX_TIMER - -#ifdef SPECIALIX_TIMER -static int sx_poll = HZ; -#endif - - - /* * The following defines are mostly for testing purposes. But if you need * some nice reporting in your syslog, you can define them also. @@ -162,16 +150,6 @@ static int sx_poll = HZ; -#ifdef CONFIG_SPECIALIX_RTSCTS -#define SX_CRTSCTS(bla) 1 -#else -#define SX_CRTSCTS(tty) C_CRTSCTS(tty) -#endif - - -/* Used to be outb (0xff, 0x80); */ -#define short_pause() udelay (1) - #define SPECIALIX_LEGAL_FLAGS \ (ASYNC_HUP_NOTIFY | ASYNC_SAK | ASYNC_SPLIT_TERMIOS | \ @@ -190,21 +168,14 @@ static struct specialix_board sx_board[SX_NBOARD] = { static struct specialix_port sx_port[SX_NBOARD * SX_NPORT]; -#ifdef SPECIALIX_TIMER -static struct timer_list missed_irq_timer; -static irqreturn_t sx_interrupt(int irq, void * dev_id); -#endif - - - -static inline int sx_paranoia_check(struct specialix_port const * port, +static int sx_paranoia_check(struct specialix_port const *port, char *name, const char *routine) { #ifdef SPECIALIX_PARANOIA_CHECK - static const char *badmagic = - KERN_ERR "sx: Warning: bad specialix port magic number for device %s in %s\n"; - static const char *badinfo = - KERN_ERR "sx: Warning: null specialix port for device %s in %s\n"; + static const char *badmagic = KERN_ERR + "sx: Warning: bad specialix port magic number for device %s in %s\n"; + static const char *badinfo = KERN_ERR + "sx: Warning: null specialix port for device %s in %s\n"; if (!port) { printk(badinfo, name, routine); @@ -226,66 +197,69 @@ static inline int sx_paranoia_check(struct specialix_port const * port, */ /* Get board number from pointer */ -static inline int board_No (struct specialix_board * bp) +static inline int board_No(struct specialix_board *bp) { return bp - sx_board; } /* Get port number from pointer */ -static inline int port_No (struct specialix_port const * port) +static inline int port_No(struct specialix_port const *port) { return SX_PORT(port - sx_port); } /* Get pointer to board from pointer to port */ -static inline struct specialix_board * port_Board(struct specialix_port const * port) +static inline struct specialix_board *port_Board( + struct specialix_port const *port) { return &sx_board[SX_BOARD(port - sx_port)]; } /* Input Byte from CL CD186x register */ -static inline unsigned char sx_in(struct specialix_board * bp, unsigned short reg) +static inline unsigned char sx_in(struct specialix_board *bp, + unsigned short reg) { bp->reg = reg | 0x80; - outb (reg | 0x80, bp->base + SX_ADDR_REG); - return inb (bp->base + SX_DATA_REG); + outb(reg | 0x80, bp->base + SX_ADDR_REG); + return inb(bp->base + SX_DATA_REG); } /* Output Byte to CL CD186x register */ -static inline void sx_out(struct specialix_board * bp, unsigned short reg, +static inline void sx_out(struct specialix_board *bp, unsigned short reg, unsigned char val) { bp->reg = reg | 0x80; - outb (reg | 0x80, bp->base + SX_ADDR_REG); - outb (val, bp->base + SX_DATA_REG); + outb(reg | 0x80, bp->base + SX_ADDR_REG); + outb(val, bp->base + SX_DATA_REG); } /* Input Byte from CL CD186x register */ -static inline unsigned char sx_in_off(struct specialix_board * bp, unsigned short reg) +static inline unsigned char sx_in_off(struct specialix_board *bp, + unsigned short reg) { bp->reg = reg; - outb (reg, bp->base + SX_ADDR_REG); - return inb (bp->base + SX_DATA_REG); + outb(reg, bp->base + SX_ADDR_REG); + return inb(bp->base + SX_DATA_REG); } /* Output Byte to CL CD186x register */ -static inline void sx_out_off(struct specialix_board * bp, unsigned short reg, - unsigned char val) +static inline void sx_out_off(struct specialix_board *bp, + unsigned short reg, unsigned char val) { bp->reg = reg; - outb (reg, bp->base + SX_ADDR_REG); - outb (val, bp->base + SX_DATA_REG); + outb(reg, bp->base + SX_ADDR_REG); + outb(val, bp->base + SX_DATA_REG); } /* Wait for Channel Command Register ready */ -static inline void sx_wait_CCR(struct specialix_board * bp) +static void sx_wait_CCR(struct specialix_board *bp) { unsigned long delay, flags; unsigned char ccr; @@ -296,7 +270,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) spin_unlock_irqrestore(&bp->lock, flags); if (!ccr) return; - udelay (1); + udelay(1); } printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); @@ -304,7 +278,7 @@ static inline void sx_wait_CCR(struct specialix_board * bp) /* Wait for Channel Command Register ready */ -static inline void sx_wait_CCR_off(struct specialix_board * bp) +static void sx_wait_CCR_off(struct specialix_board *bp) { unsigned long delay; unsigned char crr; @@ -316,7 +290,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) spin_unlock_irqrestore(&bp->lock, flags); if (!crr) return; - udelay (1); + udelay(1); } printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp)); @@ -327,7 +301,7 @@ static inline void sx_wait_CCR_off(struct specialix_board * bp) * specialix IO8+ IO range functions. */ -static inline int sx_request_io_range(struct specialix_board * bp) +static int sx_request_io_range(struct specialix_board *bp) { return request_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE, @@ -335,15 +309,15 @@ static inline int sx_request_io_range(struct specialix_board * bp) } -static inline void sx_release_io_range(struct specialix_board * bp) +static void sx_release_io_range(struct specialix_board *bp) { - release_region(bp->base, - bp->flags&SX_BOARD_IS_PCI?SX_PCI_IO_SPACE:SX_IO_SPACE); + release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ? + SX_PCI_IO_SPACE : SX_IO_SPACE); } /* Set the IRQ using the RTS lines that run to the PAL on the board.... */ -static int sx_set_irq ( struct specialix_board *bp) +static int sx_set_irq(struct specialix_board *bp) { int virq; int i; @@ -353,15 +327,24 @@ static int sx_set_irq ( struct specialix_board *bp) return 1; switch (bp->irq) { /* In the same order as in the docs... */ - case 15: virq = 0;break; - case 12: virq = 1;break; - case 11: virq = 2;break; - case 9: virq = 3;break; - default: printk (KERN_ERR "Speclialix: cannot set irq to %d.\n", bp->irq); - return 0; + case 15: + virq = 0; + break; + case 12: + virq = 1; + break; + case 11: + virq = 2; + break; + case 9: + virq = 3; + break; + default:printk(KERN_ERR + "Speclialix: cannot set irq to %d.\n", bp->irq); + return 0; } spin_lock_irqsave(&bp->lock, flags); - for (i=0;i<2;i++) { + for (i = 0; i < 2; i++) { sx_out(bp, CD186x_CAR, i); sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0); } @@ -371,7 +354,7 @@ static int sx_set_irq ( struct specialix_board *bp) /* Reset and setup CD186x chip */ -static int sx_init_CD186x(struct specialix_board * bp) +static int sx_init_CD186x(struct specialix_board *bp) { unsigned long flags; int scaler; @@ -390,7 +373,7 @@ static int sx_init_CD186x(struct specialix_board * bp) sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT); /* Prio for transmitter intr */ sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT); /* Prio for receiver intr */ /* Set RegAckEn */ - sx_out_off(bp, CD186x_SRCR, sx_in (bp, CD186x_SRCR) | SRCR_REGACKEN); + sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN); /* Setting up prescaler. We need 4 ticks per 1 ms */ scaler = SX_OSCFREQ/SPECIALIX_TPS; @@ -399,9 +382,9 @@ static int sx_init_CD186x(struct specialix_board * bp) sx_out_off(bp, CD186x_PPRL, scaler & 0xff); spin_unlock_irqrestore(&bp->lock, flags); - if (!sx_set_irq (bp)) { + if (!sx_set_irq(bp)) { /* Figure out how to pass this along... */ - printk (KERN_ERR "Cannot set irq to %d.\n", bp->irq); + printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq); rv = 0; } @@ -410,16 +393,16 @@ static int sx_init_CD186x(struct specialix_board * bp) } -static int read_cross_byte (struct specialix_board *bp, int reg, int bit) +static int read_cross_byte(struct specialix_board *bp, int reg, int bit) { int i; int t; unsigned long flags; spin_lock_irqsave(&bp->lock, flags); - for (i=0, t=0;i<8;i++) { - sx_out_off (bp, CD186x_CAR, i); - if (sx_in_off (bp, reg) & bit) + for (i = 0, t = 0; i < 8; i++) { + sx_out_off(bp, CD186x_CAR, i); + if (sx_in_off(bp, reg) & bit) t |= 1 << i; } spin_unlock_irqrestore(&bp->lock, flags); @@ -428,37 +411,10 @@ static int read_cross_byte (struct specialix_board *bp, int reg, int bit) } -#ifdef SPECIALIX_TIMER -void missed_irq (unsigned long data) -{ - unsigned char irq; - unsigned long flags; - struct specialix_board *bp = (struct specialix_board *)data; - - spin_lock_irqsave(&bp->lock, flags); - irq = sx_in ((struct specialix_board *)data, CD186x_SRSR) & - (SRSR_RREQint | - SRSR_TREQint | - SRSR_MREQint); - spin_unlock_irqrestore(&bp->lock, flags); - if (irq) { - printk (KERN_INFO "Missed interrupt... Calling int from timer. \n"); - sx_interrupt (-1, bp); - } - mod_timer(&missed_irq_timer, jiffies + sx_poll); -} -#endif - - - /* Main probing routine, also sets irq. */ static int sx_probe(struct specialix_board *bp) { unsigned char val1, val2; -#if 0 - int irqs = 0; - int retries; -#endif int rev; int chip; @@ -471,17 +427,18 @@ static int sx_probe(struct specialix_board *bp) /* Are the I/O ports here ? */ sx_out_off(bp, CD186x_PPRL, 0x5a); - short_pause (); + udelay(1); val1 = sx_in_off(bp, CD186x_PPRL); sx_out_off(bp, CD186x_PPRL, 0xa5); - short_pause (); + udelay(1); val2 = sx_in_off(bp, CD186x_PPRL); - if ((val1 != 0x5a) || (val2 != 0xa5)) { - printk(KERN_INFO "sx%d: specialix IO8+ Board at 0x%03x not found.\n", - board_No(bp), bp->base); + if (val1 != 0x5a || val2 != 0xa5) { + printk(KERN_INFO + "sx%d: specialix IO8+ Board at 0x%03x not found.\n", + board_No(bp), bp->base); sx_release_io_range(bp); func_exit(); return 1; @@ -489,10 +446,11 @@ static int sx_probe(struct specialix_board *bp) /* Check the DSR lines that Specialix uses as board identification */ - val1 = read_cross_byte (bp, CD186x_MSVR, MSVR_DSR); - val2 = read_cross_byte (bp, CD186x_MSVR, MSVR_RTS); - dprintk (SX_DEBUG_INIT, "sx%d: DSR lines are: %02x, rts lines are: %02x\n", - board_No(bp), val1, val2); + val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR); + val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS); + dprintk(SX_DEBUG_INIT, + "sx%d: DSR lines are: %02x, rts lines are: %02x\n", + board_No(bp), val1, val2); /* They managed to switch the bit order between the docs and the IO8+ card. The new PCI card now conforms to old docs. @@ -500,7 +458,8 @@ static int sx_probe(struct specialix_board *bp) old card. */ val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2; if (val1 != val2) { - printk(KERN_INFO "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", + printk(KERN_INFO + "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n", board_No(bp), val2, bp->base, val1); sx_release_io_range(bp); func_exit(); @@ -508,47 +467,6 @@ static int sx_probe(struct specialix_board *bp) } -#if 0 - /* It's time to find IRQ for this board */ - for (retries = 0; retries < 5 && irqs <= 0; retries++) { - irqs = probe_irq_on(); - sx_init_CD186x(bp); /* Reset CD186x chip */ - sx_out(bp, CD186x_CAR, 2); /* Select port 2 */ - sx_wait_CCR(bp); - sx_out(bp, CD186x_CCR, CCR_TXEN); /* Enable transmitter */ - sx_out(bp, CD186x_IER, IER_TXRDY); /* Enable tx empty intr */ - msleep(50); - irqs = probe_irq_off(irqs); - - dprintk (SX_DEBUG_INIT, "SRSR = %02x, ", sx_in(bp, CD186x_SRSR)); - dprintk (SX_DEBUG_INIT, "TRAR = %02x, ", sx_in(bp, CD186x_TRAR)); - dprintk (SX_DEBUG_INIT, "GIVR = %02x, ", sx_in(bp, CD186x_GIVR)); - dprintk (SX_DEBUG_INIT, "GICR = %02x, ", sx_in(bp, CD186x_GICR)); - dprintk (SX_DEBUG_INIT, "\n"); - - /* Reset CD186x again */ - if (!sx_init_CD186x(bp)) { - /* Hmmm. This is dead code anyway. */ - } - - dprintk (SX_DEBUG_INIT "val1 = %02x, val2 = %02x, val3 = %02x.\n", - val1, val2, val3); - - } - -#if 0 - if (irqs <= 0) { - printk(KERN_ERR "sx%d: Can't find IRQ for specialix IO8+ board at 0x%03x.\n", - board_No(bp), bp->base); - sx_release_io_range(bp); - func_exit(); - return 1; - } -#endif - printk (KERN_INFO "Started with irq=%d, but now have irq=%d.\n", bp->irq, irqs); - if (irqs > 0) - bp->irq = irqs; -#endif /* Reset CD186x again */ if (!sx_init_CD186x(bp)) { sx_release_io_range(bp); @@ -560,7 +478,7 @@ static int sx_probe(struct specialix_board *bp) bp->flags |= SX_BOARD_PRESENT; /* Chip revcode pkgtype - GFRCR SRCR bit 7 + GFRCR SRCR bit 7 CD180 rev B 0x81 0 CD180 rev C 0x82 0 CD1864 rev A 0x82 1 @@ -570,24 +488,32 @@ static int sx_probe(struct specialix_board *bp) */ switch (sx_in_off(bp, CD186x_GFRCR)) { - case 0x82:chip = 1864;rev='A';break; - case 0x83:chip = 1865;rev='A';break; - case 0x84:chip = 1865;rev='B';break; - case 0x85:chip = 1865;rev='C';break; /* Does not exist at this time */ - default:chip=-1;rev='x'; + case 0x82: + chip = 1864; + rev = 'A'; + break; + case 0x83: + chip = 1865; + rev = 'A'; + break; + case 0x84: + chip = 1865; + rev = 'B'; + break; + case 0x85: + chip = 1865; + rev = 'C'; + break; /* Does not exist at this time */ + default: + chip = -1; + rev = 'x'; } - dprintk (SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR) ); - -#ifdef SPECIALIX_TIMER - setup_timer(&missed_irq_timer, missed_irq, (unsigned long)bp); - mod_timer(&missed_irq_timer, jiffies + sx_poll); -#endif + dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR)); - printk(KERN_INFO"sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", - board_No(bp), - bp->base, bp->irq, - chip, rev); + printk(KERN_INFO + "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n", + board_No(bp), bp->base, bp->irq, chip, rev); func_exit(); return 0; @@ -598,20 +524,22 @@ static int sx_probe(struct specialix_board *bp) * Interrupt processing routines. * */ -static inline struct specialix_port * sx_get_port(struct specialix_board * bp, - unsigned char const * what) +static struct specialix_port *sx_get_port(struct specialix_board *bp, + unsigned char const *what) { unsigned char channel; - struct specialix_port * port = NULL; + struct specialix_port *port = NULL; channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF; - dprintk (SX_DEBUG_CHAN, "channel: %d\n", channel); + dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel); if (channel < CD186x_NCH) { port = &sx_port[board_No(bp) * SX_NPORT + channel]; - dprintk (SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",board_No(bp) * SX_NPORT + channel, port, port->port.flags & ASYNC_INITIALIZED); + dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n", + board_No(bp) * SX_NPORT + channel, port, + port->port.flags & ASYNC_INITIALIZED); if (port->port.flags & ASYNC_INITIALIZED) { - dprintk (SX_DEBUG_CHAN, "port: %d %p\n", channel, port); + dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port); func_exit(); return port; } @@ -622,7 +550,7 @@ static inline struct specialix_port * sx_get_port(struct specialix_board * bp, } -static inline void sx_receive_exc(struct specialix_board * bp) +static void sx_receive_exc(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; @@ -633,7 +561,7 @@ static inline void sx_receive_exc(struct specialix_board * bp) port = sx_get_port(bp, "Receive"); if (!port) { - dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); + dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); func_exit(); return; } @@ -641,19 +569,21 @@ static inline void sx_receive_exc(struct specialix_board * bp) status = sx_in(bp, CD186x_RCSR); - dprintk (SX_DEBUG_RX, "status: 0x%x\n", status); + dprintk(SX_DEBUG_RX, "status: 0x%x\n", status); if (status & RCSR_OE) { port->overrun++; - dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Overrun. Total %ld overruns.\n", - board_No(bp), port_No(port), port->overrun); + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: Overrun. Total %ld overruns.\n", + board_No(bp), port_No(port), port->overrun); } status &= port->mark_mask; /* This flip buffer check needs to be below the reading of the status register to reset the chip's IRQ.... */ if (tty_buffer_request_room(tty, 1) == 0) { - dprintk(SX_DEBUG_FIFO, "sx%d: port %d: Working around flip buffer overflow.\n", - board_No(bp), port_No(port)); + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: Working around flip buffer overflow.\n", + board_No(bp), port_No(port)); func_exit(); return; } @@ -664,8 +594,9 @@ static inline void sx_receive_exc(struct specialix_board * bp) return; } if (status & RCSR_TOUT) { - printk(KERN_INFO "sx%d: port %d: Receiver timeout. Hardware problems ?\n", - board_No(bp), port_No(port)); + printk(KERN_INFO + "sx%d: port %d: Receiver timeout. Hardware problems ?\n", + board_No(bp), port_No(port)); func_exit(); return; @@ -688,13 +619,13 @@ static inline void sx_receive_exc(struct specialix_board * bp) else flag = TTY_NORMAL; - if(tty_insert_flip_char(tty, ch, flag)) + if (tty_insert_flip_char(tty, ch, flag)) tty_flip_buffer_push(tty); func_exit(); } -static inline void sx_receive(struct specialix_board * bp) +static void sx_receive(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; @@ -702,15 +633,16 @@ static inline void sx_receive(struct specialix_board * bp) func_enter(); - if (!(port = sx_get_port(bp, "Receive"))) { - dprintk (SX_DEBUG_RX, "Hmm, couldn't find port.\n"); + port = sx_get_port(bp, "Receive"); + if (port == NULL) { + dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n"); func_exit(); return; } tty = port->port.tty; count = sx_in(bp, CD186x_RDCR); - dprintk (SX_DEBUG_RX, "port: %p: count: %d\n", port, count); + dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count); port->hits[count > 8 ? 9 : count]++; tty_buffer_request_room(tty, count); @@ -722,18 +654,19 @@ static inline void sx_receive(struct specialix_board * bp) } -static inline void sx_transmit(struct specialix_board * bp) +static void sx_transmit(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; unsigned char count; func_enter(); - if (!(port = sx_get_port(bp, "Transmit"))) { + port = sx_get_port(bp, "Transmit"); + if (port == NULL) { func_exit(); return; } - dprintk (SX_DEBUG_TX, "port: %p\n", port); + dprintk(SX_DEBUG_TX, "port: %p\n", port); tty = port->port.tty; if (port->IER & IER_TXEMPTY) { @@ -765,7 +698,8 @@ static inline void sx_transmit(struct specialix_board * bp) sx_out(bp, CD186x_TDR, CD186x_C_ESC); sx_out(bp, CD186x_TDR, CD186x_C_DELAY); sx_out(bp, CD186x_TDR, count); - if (!(port->break_length -= count)) + port->break_length -= count; + if (port->break_length == 0) port->break_length--; } else { sx_out(bp, CD186x_TDR, CD186x_C_ESC); @@ -794,36 +728,36 @@ static inline void sx_transmit(struct specialix_board * bp) sx_out(bp, CD186x_IER, port->IER); } if (port->xmit_cnt <= port->wakeup_chars) - tty_wakeup(tty); + tty_wakeup(tty); func_exit(); } -static inline void sx_check_modem(struct specialix_board * bp) +static void sx_check_modem(struct specialix_board *bp) { struct specialix_port *port; struct tty_struct *tty; unsigned char mcr; int msvr_cd; - dprintk (SX_DEBUG_SIGNALS, "Modem intr. "); - if (!(port = sx_get_port(bp, "Modem"))) + dprintk(SX_DEBUG_SIGNALS, "Modem intr. "); + port = sx_get_port(bp, "Modem"); + if (port == NULL) return; tty = port->port.tty; mcr = sx_in(bp, CD186x_MCR); - printk ("mcr = %02x.\n", mcr); if ((mcr & MCR_CDCHG)) { - dprintk (SX_DEBUG_SIGNALS, "CD just changed... "); + dprintk(SX_DEBUG_SIGNALS, "CD just changed... "); msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD; if (msvr_cd) { - dprintk (SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); + dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n"); wake_up_interruptible(&port->port.open_wait); } else { - dprintk (SX_DEBUG_SIGNALS, "Sending HUP.\n"); + dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n"); tty_hangup(tty); } } @@ -874,9 +808,12 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) spin_lock_irqsave(&bp->lock, flags); - dprintk (SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, port_No(sx_get_port(bp, "INT")), SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); + dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__, + port_No(sx_get_port(bp, "INT")), + SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1); if (!(bp->flags & SX_BOARD_ACTIVE)) { - dprintk (SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", bp->irq); + dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n", + bp->irq); spin_unlock_irqrestore(&bp->lock, flags); func_exit(); return IRQ_NONE; @@ -884,10 +821,11 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) saved_reg = bp->reg; - while ((++loop < 16) && (status = (sx_in(bp, CD186x_SRSR) & - (SRSR_RREQint | - SRSR_TREQint | - SRSR_MREQint)))) { + while (++loop < 16) { + status = sx_in(bp, CD186x_SRSR) & + (SRSR_RREQint | SRSR_TREQint | SRSR_MREQint); + if (status == 0) + break; if (status & SRSR_RREQint) { ack = sx_in(bp, CD186x_RRAR); @@ -896,8 +834,9 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) else if (ack == (SX_ID | GIVR_IT_REXC)) sx_receive_exc(bp); else - printk(KERN_ERR "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", - board_No(bp), status, ack); + printk(KERN_ERR + "sx%d: status: 0x%x Bad receive ack 0x%02x.\n", + board_No(bp), status, ack); } else if (status & SRSR_TREQint) { ack = sx_in(bp, CD186x_TRAR); @@ -906,14 +845,16 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) sx_transmit(bp); else printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n", - board_No(bp), status, ack, port_No (sx_get_port (bp, "Int"))); + board_No(bp), status, ack, + port_No(sx_get_port(bp, "Int"))); } else if (status & SRSR_MREQint) { ack = sx_in(bp, CD186x_MRAR); if (ack == (SX_ID | GIVR_IT_MODEM)) sx_check_modem(bp); else - printk(KERN_ERR "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", + printk(KERN_ERR + "sx%d: status: 0x%x Bad modem ack 0x%02x.\n", board_No(bp), status, ack); } @@ -921,7 +862,7 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) sx_out(bp, CD186x_EOIR, 0); /* Mark end of interrupt */ } bp->reg = saved_reg; - outb (bp->reg, bp->base + SX_ADDR_REG); + outb(bp->reg, bp->base + SX_ADDR_REG); spin_unlock_irqrestore(&bp->lock, flags); func_exit(); return IRQ_HANDLED; @@ -932,36 +873,26 @@ static irqreturn_t sx_interrupt(int dummy, void *dev_id) * Routines for open & close processing. */ -static void turn_ints_off (struct specialix_board *bp) +static void turn_ints_off(struct specialix_board *bp) { unsigned long flags; func_enter(); - if (bp->flags & SX_BOARD_IS_PCI) { - /* This was intended for enabeling the interrupt on the - * PCI card. However it seems that it's already enabled - * and as PCI interrupts can be shared, there is no real - * reason to have to turn it off. */ - } - spin_lock_irqsave(&bp->lock, flags); - (void) sx_in_off (bp, 0); /* Turn off interrupts. */ + (void) sx_in_off(bp, 0); /* Turn off interrupts. */ spin_unlock_irqrestore(&bp->lock, flags); func_exit(); } -static void turn_ints_on (struct specialix_board *bp) +static void turn_ints_on(struct specialix_board *bp) { unsigned long flags; func_enter(); - if (bp->flags & SX_BOARD_IS_PCI) { - /* play with the PCI chip. See comment above. */ - } spin_lock_irqsave(&bp->lock, flags); - (void) sx_in (bp, 0); /* Turn ON interrupts. */ + (void) sx_in(bp, 0); /* Turn ON interrupts. */ spin_unlock_irqrestore(&bp->lock, flags); func_exit(); @@ -969,7 +900,7 @@ static void turn_ints_on (struct specialix_board *bp) /* Called with disabled interrupts */ -static inline int sx_setup_board(struct specialix_board * bp) +static int sx_setup_board(struct specialix_board *bp) { int error; @@ -977,14 +908,16 @@ static inline int sx_setup_board(struct specialix_board * bp) return 0; if (bp->flags & SX_BOARD_IS_PCI) - error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); + error = request_irq(bp->irq, sx_interrupt, + IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp); else - error = request_irq(bp->irq, sx_interrupt, IRQF_DISABLED, "specialix IO8+", bp); + error = request_irq(bp->irq, sx_interrupt, + IRQF_DISABLED, "specialix IO8+", bp); if (error) return error; - turn_ints_on (bp); + turn_ints_on(bp); bp->flags |= SX_BOARD_ACTIVE; return 0; @@ -992,7 +925,7 @@ static inline int sx_setup_board(struct specialix_board * bp) /* Called with disabled interrupts */ -static inline void sx_shutdown_board(struct specialix_board *bp) +static void sx_shutdown_board(struct specialix_board *bp) { func_enter(); @@ -1003,22 +936,26 @@ static inline void sx_shutdown_board(struct specialix_board *bp) bp->flags &= ~SX_BOARD_ACTIVE; - dprintk (SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", - bp->irq, board_No (bp)); + dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n", + bp->irq, board_No(bp)); free_irq(bp->irq, bp); - - turn_ints_off (bp); - - + turn_ints_off(bp); func_exit(); } +static unsigned int sx_crtscts(struct tty_struct *tty) +{ + if (sx_rtscts) + return C_CRTSCTS(tty); + return 1; +} /* * Setting up port characteristics. * Must be called with disabled interrupts */ -static void sx_change_speed(struct specialix_board *bp, struct specialix_port *port) +static void sx_change_speed(struct specialix_board *bp, + struct specialix_port *port) { struct tty_struct *tty; unsigned long baud; @@ -1030,7 +967,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p func_enter(); - if (!(tty = port->port.tty) || !tty->termios) { + tty = port->port.tty; + if (!tty || !tty->termios) { func_exit(); return; } @@ -1043,12 +981,12 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p /* The Specialix board doens't implement the RTS lines. They are used to set the IRQ level. Don't touch them. */ - if (SX_CRTSCTS(tty)) + if (sx_crtscts(tty)) port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS); else port->MSVR = (sx_in(bp, CD186x_MSVR) & MSVR_RTS); spin_unlock_irqrestore(&bp->lock, flags); - dprintk (SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); + dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR); baud = tty_get_baud_rate(tty); if (baud == 38400) { @@ -1060,21 +998,19 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p if (!baud) { /* Drop DTR & exit */ - dprintk (SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); - if (!SX_CRTSCTS (tty)) { - port -> MSVR &= ~ MSVR_DTR; + dprintk(SX_DEBUG_TERMIOS, "Dropping DTR... Hmm....\n"); + if (!sx_crtscts(tty)) { + port->MSVR &= ~MSVR_DTR; spin_lock_irqsave(&bp->lock, flags); - sx_out(bp, CD186x_MSVR, port->MSVR ); + sx_out(bp, CD186x_MSVR, port->MSVR); spin_unlock_irqrestore(&bp->lock, flags); - } - else - dprintk (SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); + } else + dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n"); return; } else { /* Set DTR on */ - if (!SX_CRTSCTS (tty)) { - port ->MSVR |= MSVR_DTR; - } + if (!sx_crtscts(tty)) + port->MSVR |= MSVR_DTR; } /* @@ -1083,28 +1019,27 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p /* Set baud rate for port */ tmp = port->custom_divisor ; - if ( tmp ) - printk (KERN_INFO "sx%d: Using custom baud rate divisor %ld. \n" - "This is an untested option, please be carefull.\n", - port_No (port), tmp); + if (tmp) + printk(KERN_INFO + "sx%d: Using custom baud rate divisor %ld. \n" + "This is an untested option, please be careful.\n", + port_No(port), tmp); else - tmp = (((SX_OSCFREQ + baud/2) / baud + - CD186x_TPC/2) / CD186x_TPC); + tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) / + CD186x_TPC); - if ((tmp < 0x10) && time_before(again, jiffies)) { + if (tmp < 0x10 && time_before(again, jiffies)) { again = jiffies + HZ * 60; /* Page 48 of version 2.0 of the CL-CD1865 databook */ if (tmp >= 12) { - printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" - "Performance degradation is possible.\n" - "Read specialix.txt for more info.\n", - port_No (port), tmp); + printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" + "Performance degradation is possible.\n" + "Read specialix.txt for more info.\n", + port_No(port), tmp); } else { - printk (KERN_INFO "sx%d: Baud rate divisor is %ld. \n" - "Warning: overstressing Cirrus chip. " - "This might not work.\n" - "Read specialix.txt for more info.\n", - port_No (port), tmp); + printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n" + "Warning: overstressing Cirrus chip. This might not work.\n" + "Read specialix.txt for more info.\n", port_No(port), tmp); } } spin_lock_irqsave(&bp->lock, flags); @@ -1114,7 +1049,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p sx_out(bp, CD186x_TBPRL, tmp & 0xff); spin_unlock_irqrestore(&bp->lock, flags); if (port->custom_divisor) - baud = (SX_OSCFREQ + port->custom_divisor/2) / port->custom_divisor; + baud = (SX_OSCFREQ + port->custom_divisor/2) / + port->custom_divisor; baud = (baud + 5) / 10; /* Estimated CPS */ /* Two timer ticks seems enough to wakeup something like SLIP driver */ @@ -1129,16 +1065,16 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p sx_out(bp, CD186x_RTPR, tmp); spin_unlock_irqrestore(&bp->lock, flags); switch (C_CSIZE(tty)) { - case CS5: + case CS5: cor1 |= COR1_5BITS; break; - case CS6: + case CS6: cor1 |= COR1_6BITS; break; - case CS7: + case CS7: cor1 |= COR1_7BITS; break; - case CS8: + case CS8: cor1 |= COR1_8BITS; break; } @@ -1175,7 +1111,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD; mcor2 |= MCOR2_DSROD | MCOR2_CTSOD; spin_lock_irqsave(&bp->lock, flags); - tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & (MSVR_CTS|MSVR_DSR)); + tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) & + (MSVR_CTS|MSVR_DSR)); spin_unlock_irqrestore(&bp->lock, flags); #else port->COR2 |= COR2_CTSAE; @@ -1219,7 +1156,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); /* Setting up modem option registers */ - dprintk (SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", mcor1, mcor2); + dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n", + mcor1, mcor2); sx_out(bp, CD186x_MCOR1, mcor1); sx_out(bp, CD186x_MCOR2, mcor2); spin_unlock_irqrestore(&bp->lock, flags); @@ -1238,7 +1176,8 @@ static void sx_change_speed(struct specialix_board *bp, struct specialix_port *p /* Must be called with interrupts enabled */ -static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port) +static int sx_setup_port(struct specialix_board *bp, + struct specialix_port *port) { unsigned long flags; @@ -1253,7 +1192,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port /* We may sleep in get_zeroed_page() */ unsigned long tmp; - if (!(tmp = get_zeroed_page(GFP_KERNEL))) { + tmp = get_zeroed_page(GFP_KERNEL); + if (tmp == 0L) { func_exit(); return -ENOMEM; } @@ -1284,7 +1224,8 @@ static int sx_setup_port(struct specialix_board *bp, struct specialix_port *port /* Must be called with interrupts disabled */ -static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port *port) +static void sx_shutdown_port(struct specialix_board *bp, + struct specialix_port *port) { struct tty_struct *tty; int i; @@ -1298,11 +1239,11 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * } if (sx_debug & SX_DEBUG_FIFO) { - dprintk(SX_DEBUG_FIFO, "sx%d: port %d: %ld overruns, FIFO hits [ ", - board_No(bp), port_No(port), port->overrun); - for (i = 0; i < 10; i++) { + dprintk(SX_DEBUG_FIFO, + "sx%d: port %d: %ld overruns, FIFO hits [ ", + board_No(bp), port_No(port), port->overrun); + for (i = 0; i < 10; i++) dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]); - } dprintk(SX_DEBUG_FIFO, "].\n"); } @@ -1315,7 +1256,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); - if (!(tty = port->port.tty) || C_HUPCL(tty)) { + tty = port->port.tty; + if (tty == NULL || C_HUPCL(tty)) { /* Drop DTR */ sx_out(bp, CD186x_MSVDTR, 0); } @@ -1338,8 +1280,8 @@ static void sx_shutdown_port(struct specialix_board *bp, struct specialix_port * } -static int block_til_ready(struct tty_struct *tty, struct file * filp, - struct specialix_port *port) +static int block_til_ready(struct tty_struct *tty, struct file *filp, + struct specialix_port *port) { DECLARE_WAITQUEUE(wait, current); struct specialix_board *bp = port_Board(port); @@ -1389,23 +1331,22 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, retval = 0; add_wait_queue(&port->port.open_wait, &wait); spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) { + if (!tty_hung_up_p(filp)) port->port.count--; - } spin_unlock_irqrestore(&port->lock, flags); port->port.blocked_open++; while (1) { spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); CD = sx_in(bp, CD186x_MSVR) & MSVR_CD; - if (SX_CRTSCTS (tty)) { + if (sx_crtscts(tty)) { /* Activate RTS */ port->MSVR |= MSVR_DTR; /* WTF? */ - sx_out (bp, CD186x_MSVR, port->MSVR); + sx_out(bp, CD186x_MSVR, port->MSVR); } else { /* Activate DTR */ port->MSVR |= MSVR_DTR; - sx_out (bp, CD186x_MSVR, port->MSVR); + sx_out(bp, CD186x_MSVR, port->MSVR); } spin_unlock_irqrestore(&bp->lock, flags); set_current_state(TASK_INTERRUPTIBLE); @@ -1430,9 +1371,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, set_current_state(TASK_RUNNING); remove_wait_queue(&port->port.open_wait, &wait); spin_lock_irqsave(&port->lock, flags); - if (!tty_hung_up_p(filp)) { + if (!tty_hung_up_p(filp)) port->port.count++; - } port->port.blocked_open--; spin_unlock_irqrestore(&port->lock, flags); if (retval) { @@ -1446,12 +1386,12 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp, } -static int sx_open(struct tty_struct * tty, struct file * filp) +static int sx_open(struct tty_struct *tty, struct file *filp) { int board; int error; - struct specialix_port * port; - struct specialix_board * bp; + struct specialix_port *port; + struct specialix_board *bp; int i; unsigned long flags; @@ -1468,17 +1408,19 @@ static int sx_open(struct tty_struct * tty, struct file * filp) port = sx_port + board * SX_NPORT + SX_PORT(tty->index); port->overrun = 0; for (i = 0; i < 10; i++) - port->hits[i]=0; + port->hits[i] = 0; - dprintk (SX_DEBUG_OPEN, "Board = %d, bp = %p, port = %p, portno = %d.\n", - board, bp, port, SX_PORT(tty->index)); + dprintk(SX_DEBUG_OPEN, + "Board = %d, bp = %p, port = %p, portno = %d.\n", + board, bp, port, SX_PORT(tty->index)); if (sx_paranoia_check(port, tty->name, "sx_open")) { func_enter(); return -ENODEV; } - if ((error = sx_setup_board(bp))) { + error = sx_setup_board(bp); + if (error) { func_exit(); return error; } @@ -1490,12 +1432,14 @@ static int sx_open(struct tty_struct * tty, struct file * filp) port->port.tty = tty; spin_unlock_irqrestore(&bp->lock, flags); - if ((error = sx_setup_port(bp, port))) { + error = sx_setup_port(bp, port); + if (error) { func_enter(); return error; } - if ((error = block_til_ready(tty, filp, port))) { + error = block_til_ready(tty, filp, port); + if (error) { func_enter(); return error; } @@ -1508,7 +1452,7 @@ static void sx_flush_buffer(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; - struct specialix_board * bp; + struct specialix_board *bp; func_enter(); @@ -1526,9 +1470,9 @@ static void sx_flush_buffer(struct tty_struct *tty) func_exit(); } -static void sx_close(struct tty_struct * tty, struct file * filp) +static void sx_close(struct tty_struct *tty, struct file *filp) { - struct specialix_port *port = (struct specialix_port *) tty->driver_data; + struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp; unsigned long flags; unsigned long timeout; @@ -1547,7 +1491,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } bp = port_Board(port); - if ((tty->count == 1) && (port->port.count != 1)) { + if (tty->count == 1 && port->port.count != 1) { printk(KERN_ERR "sx%d: sx_close: bad port count;" " tty->count is 1, port count is %d\n", board_No(bp), port->port.count); @@ -1570,17 +1514,16 @@ static void sx_close(struct tty_struct * tty, struct file * filp) */ tty->closing = 1; spin_unlock_irqrestore(&port->lock, flags); - dprintk (SX_DEBUG_OPEN, "Closing\n"); - if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) { + dprintk(SX_DEBUG_OPEN, "Closing\n"); + if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, port->port.closing_wait); - } /* * At this point we stop accepting input. To do this, we * disable the receive line status interrupts, and tell the * interrupt driver to stop checking the data ready bit in the * line status register. */ - dprintk (SX_DEBUG_OPEN, "Closed\n"); + dprintk(SX_DEBUG_OPEN, "Closed\n"); port->IER &= ~IER_RXD; if (port->port.flags & ASYNC_INITIALIZED) { port->IER &= ~IER_TXRDY; @@ -1595,11 +1538,11 @@ static void sx_close(struct tty_struct * tty, struct file * filp) * important if there is a transmit FIFO! */ timeout = jiffies+HZ; - while(port->IER & IER_TXEMPTY) { - set_current_state (TASK_INTERRUPTIBLE); + while (port->IER & IER_TXEMPTY) { + set_current_state(TASK_INTERRUPTIBLE); msleep_interruptible(jiffies_to_msecs(port->timeout)); if (time_after(jiffies, timeout)) { - printk (KERN_INFO "Timeout waiting for close\n"); + printk(KERN_INFO "Timeout waiting for close\n"); break; } } @@ -1607,13 +1550,15 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } if (--bp->count < 0) { - printk(KERN_ERR "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", - board_No(bp), bp->count, tty->index); + printk(KERN_ERR + "sx%d: sx_shutdown_port: bad board count: %d port: %d\n", + board_No(bp), bp->count, tty->index); bp->count = 0; } if (--port->port.count < 0) { - printk(KERN_ERR "sx%d: sx_close: bad port count for tty%d: %d\n", - board_No(bp), port_No(port), port->port.count); + printk(KERN_ERR + "sx%d: sx_close: bad port count for tty%d: %d\n", + board_No(bp), port_No(port), port->port.count); port->port.count = 0; } @@ -1625,9 +1570,9 @@ static void sx_close(struct tty_struct * tty, struct file * filp) port->port.tty = NULL; spin_unlock_irqrestore(&port->lock, flags); if (port->port.blocked_open) { - if (port->port.close_delay) { - msleep_interruptible(jiffies_to_msecs(port->port.close_delay)); - } + if (port->port.close_delay) + msleep_interruptible( + jiffies_to_msecs(port->port.close_delay)); wake_up_interruptible(&port->port.open_wait); } port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); @@ -1637,8 +1582,8 @@ static void sx_close(struct tty_struct * tty, struct file * filp) } -static int sx_write(struct tty_struct * tty, - const unsigned char *buf, int count) +static int sx_write(struct tty_struct *tty, + const unsigned char *buf, int count) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp; @@ -1690,11 +1635,11 @@ static int sx_write(struct tty_struct * tty, } -static int sx_put_char(struct tty_struct * tty, unsigned char ch) +static int sx_put_char(struct tty_struct *tty, unsigned char ch) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; - struct specialix_board * bp; + struct specialix_board *bp; func_enter(); @@ -1702,7 +1647,7 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) func_exit(); return 0; } - dprintk (SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); + dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf); if (!port->xmit_buf) { func_exit(); return 0; @@ -1710,14 +1655,15 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) bp = port_Board(port); spin_lock_irqsave(&port->lock, flags); - dprintk (SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", port->xmit_cnt, port->xmit_buf); - if ((port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) || (!port->xmit_buf)) { + dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n", + port->xmit_cnt, port->xmit_buf); + if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) { spin_unlock_irqrestore(&port->lock, flags); - dprintk (SX_DEBUG_TX, "Exit size\n"); + dprintk(SX_DEBUG_TX, "Exit size\n"); func_exit(); return 0; } - dprintk (SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); + dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf); port->xmit_buf[port->xmit_head++] = ch; port->xmit_head &= SERIAL_XMIT_SIZE - 1; port->xmit_cnt++; @@ -1728,11 +1674,11 @@ static int sx_put_char(struct tty_struct * tty, unsigned char ch) } -static void sx_flush_chars(struct tty_struct * tty) +static void sx_flush_chars(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; - struct specialix_board * bp = port_Board(port); + struct specialix_board *bp = port_Board(port); func_enter(); @@ -1755,7 +1701,7 @@ static void sx_flush_chars(struct tty_struct * tty) } -static int sx_write_room(struct tty_struct * tty) +static int sx_write_room(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; int ret; @@ -1790,12 +1736,10 @@ static int sx_chars_in_buffer(struct tty_struct *tty) return port->xmit_cnt; } - - static int sx_tiocmget(struct tty_struct *tty, struct file *file) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; - struct specialix_board * bp; + struct specialix_board *bp; unsigned char status; unsigned int result; unsigned long flags; @@ -1808,25 +1752,23 @@ static int sx_tiocmget(struct tty_struct *tty, struct file *file) } bp = port_Board(port); - spin_lock_irqsave (&bp->lock, flags); + spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); status = sx_in(bp, CD186x_MSVR); spin_unlock_irqrestore(&bp->lock, flags); - dprintk (SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", - port_No(port), status, sx_in (bp, CD186x_CAR)); - dprintk (SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); - if (SX_CRTSCTS(port->port.tty)) { - result = /* (status & MSVR_RTS) ? */ TIOCM_DTR /* : 0) */ - | ((status & MSVR_DTR) ? TIOCM_RTS : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n", + port_No(port), status, sx_in(bp, CD186x_CAR)); + dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port); + if (sx_crtscts(port->port.tty)) { + result = TIOCM_DTR | TIOCM_DSR + | ((status & MSVR_DTR) ? TIOCM_RTS : 0) + | ((status & MSVR_CD) ? TIOCM_CAR : 0) + | ((status & MSVR_CTS) ? TIOCM_CTS : 0); } else { - result = /* (status & MSVR_RTS) ? */ TIOCM_RTS /* : 0) */ - | ((status & MSVR_DTR) ? TIOCM_DTR : 0) - | ((status & MSVR_CD) ? TIOCM_CAR : 0) - |/* ((status & MSVR_DSR) ? */ TIOCM_DSR /* : 0) */ - | ((status & MSVR_CTS) ? TIOCM_CTS : 0); + result = TIOCM_RTS | TIOCM_DSR + | ((status & MSVR_DTR) ? TIOCM_DTR : 0) + | ((status & MSVR_CD) ? TIOCM_CAR : 0) + | ((status & MSVR_CTS) ? TIOCM_CTS : 0); } func_exit(); @@ -1852,24 +1794,14 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, bp = port_Board(port); spin_lock_irqsave(&port->lock, flags); - /* if (set & TIOCM_RTS) - port->MSVR |= MSVR_RTS; */ - /* if (set & TIOCM_DTR) - port->MSVR |= MSVR_DTR; */ - - if (SX_CRTSCTS(port->port.tty)) { + if (sx_crtscts(port->port.tty)) { if (set & TIOCM_RTS) port->MSVR |= MSVR_DTR; } else { if (set & TIOCM_DTR) port->MSVR |= MSVR_DTR; } - - /* if (clear & TIOCM_RTS) - port->MSVR &= ~MSVR_RTS; */ - /* if (clear & TIOCM_DTR) - port->MSVR &= ~MSVR_DTR; */ - if (SX_CRTSCTS(port->port.tty)) { + if (sx_crtscts(port->port.tty)) { if (clear & TIOCM_RTS) port->MSVR &= ~MSVR_DTR; } else { @@ -1886,14 +1818,17 @@ static int sx_tiocmset(struct tty_struct *tty, struct file *file, } -static inline void sx_send_break(struct specialix_port * port, unsigned long length) +static int sx_send_break(struct tty_struct *tty, int length) { + struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp = port_Board(port); unsigned long flags; func_enter(); + if (length == 0 || length == -1) + return -EOPNOTSUPP; - spin_lock_irqsave (&port->lock, flags); + spin_lock_irqsave(&port->lock, flags); port->break_length = SPECIALIX_TPS / HZ * length; port->COR2 |= COR2_ETC; port->IER |= IER_TXRDY; @@ -1902,7 +1837,7 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len sx_out(bp, CD186x_COR2, port->COR2); sx_out(bp, CD186x_IER, port->IER); spin_unlock_irqrestore(&bp->lock, flags); - spin_unlock_irqrestore (&port->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); sx_wait_CCR(bp); spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CCR, CCR_CORCHG2); @@ -1910,11 +1845,12 @@ static inline void sx_send_break(struct specialix_port * port, unsigned long len sx_wait_CCR(bp); func_exit(); + return 0; } -static inline int sx_set_serial_info(struct specialix_port * port, - struct serial_struct __user * newinfo) +static int sx_set_serial_info(struct specialix_port *port, + struct serial_struct __user *newinfo) { struct serial_struct tmp; struct specialix_board *bp = port_Board(port); @@ -1943,25 +1879,25 @@ static inline int sx_set_serial_info(struct specialix_port * port, return -EPERM; } port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) | - (tmp.flags & ASYNC_USR_MASK)); + (tmp.flags & ASYNC_USR_MASK)); port->custom_divisor = tmp.custom_divisor; } else { port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) | - (tmp.flags & ASYNC_FLAGS)); + (tmp.flags & ASYNC_FLAGS)); port->port.close_delay = tmp.close_delay; port->port.closing_wait = tmp.closing_wait; port->custom_divisor = tmp.custom_divisor; } - if (change_speed) { + if (change_speed) sx_change_speed(bp, port); - } + func_exit(); unlock_kernel(); return 0; } -static inline int sx_get_serial_info(struct specialix_port * port, +static int sx_get_serial_info(struct specialix_port *port, struct serial_struct __user *retinfo) { struct serial_struct tmp; @@ -1992,11 +1928,10 @@ static inline int sx_get_serial_info(struct specialix_port * port, } -static int sx_ioctl(struct tty_struct * tty, struct file * filp, - unsigned int cmd, unsigned long arg) +static int sx_ioctl(struct tty_struct *tty, struct file *filp, + unsigned int cmd, unsigned long arg) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; - int retval; void __user *argp = (void __user *)arg; func_enter(); @@ -2007,34 +1942,14 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, } switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ - retval = tty_check_change(tty); - if (retval) { - func_exit(); - return retval; - } - tty_wait_until_sent(tty, 0); - if (!arg) - sx_send_break(port, HZ/4); /* 1/4 second */ - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ - retval = tty_check_change(tty); - if (retval) { - func_exit(); - return retval; - } - tty_wait_until_sent(tty, 0); - sx_send_break(port, arg ? arg*(HZ/10) : HZ/4); + case TIOCGSERIAL: func_exit(); - return 0; - case TIOCGSERIAL: - func_exit(); return sx_get_serial_info(port, argp); - case TIOCSSERIAL: - func_exit(); + case TIOCSSERIAL: + func_exit(); return sx_set_serial_info(port, argp); - default: - func_exit(); + default: + func_exit(); return -ENOIOCTLCMD; } func_exit(); @@ -2042,7 +1957,7 @@ static int sx_ioctl(struct tty_struct * tty, struct file * filp, } -static void sx_throttle(struct tty_struct * tty) +static void sx_throttle(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp; @@ -2058,15 +1973,16 @@ static void sx_throttle(struct tty_struct * tty) bp = port_Board(port); /* Use DTR instead of RTS ! */ - if (SX_CRTSCTS (tty)) + if (sx_crtscts(tty)) port->MSVR &= ~MSVR_DTR; else { /* Auch!!! I think the system shouldn't call this then. */ /* Or maybe we're supposed (allowed?) to do our side of hw handshake anyway, even when hardware handshake is off. When you see this in your logs, please report.... */ - printk (KERN_ERR "sx%d: Need to throttle, but can't (hardware hs is off)\n", - port_No (port)); + printk(KERN_ERR + "sx%d: Need to throttle, but can't (hardware hs is off)\n", + port_No(port)); } spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); @@ -2086,7 +2002,7 @@ static void sx_throttle(struct tty_struct * tty) } -static void sx_unthrottle(struct tty_struct * tty) +static void sx_unthrottle(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp; @@ -2103,9 +2019,9 @@ static void sx_unthrottle(struct tty_struct * tty) spin_lock_irqsave(&port->lock, flags); /* XXXX Use DTR INSTEAD???? */ - if (SX_CRTSCTS(tty)) { + if (sx_crtscts(tty)) port->MSVR |= MSVR_DTR; - } /* Else clause: see remark in "sx_throttle"... */ + /* Else clause: see remark in "sx_throttle"... */ spin_lock_irqsave(&bp->lock, flags); sx_out(bp, CD186x_CAR, port_No(port)); spin_unlock_irqrestore(&bp->lock, flags); @@ -2127,7 +2043,7 @@ static void sx_unthrottle(struct tty_struct * tty) } -static void sx_stop(struct tty_struct * tty) +static void sx_stop(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp; @@ -2154,7 +2070,7 @@ static void sx_stop(struct tty_struct * tty) } -static void sx_start(struct tty_struct * tty) +static void sx_start(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp; @@ -2182,7 +2098,7 @@ static void sx_start(struct tty_struct * tty) func_exit(); } -static void sx_hangup(struct tty_struct * tty) +static void sx_hangup(struct tty_struct *tty) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; struct specialix_board *bp; @@ -2201,8 +2117,9 @@ static void sx_hangup(struct tty_struct * tty) spin_lock_irqsave(&port->lock, flags); bp->count -= port->port.count; if (bp->count < 0) { - printk(KERN_ERR "sx%d: sx_hangup: bad board count: %d port: %d\n", - board_No(bp), bp->count, tty->index); + printk(KERN_ERR + "sx%d: sx_hangup: bad board count: %d port: %d\n", + board_No(bp), bp->count, tty->index); bp->count = 0; } port->port.count = 0; @@ -2215,11 +2132,12 @@ static void sx_hangup(struct tty_struct * tty) } -static void sx_set_termios(struct tty_struct * tty, struct ktermios * old_termios) +static void sx_set_termios(struct tty_struct *tty, + struct ktermios *old_termios) { struct specialix_port *port = (struct specialix_port *)tty->driver_data; unsigned long flags; - struct specialix_board * bp; + struct specialix_board *bp; if (sx_paranoia_check(port, tty->name, "sx_set_termios")) return; @@ -2254,6 +2172,7 @@ static const struct tty_operations sx_ops = { .hangup = sx_hangup, .tiocmget = sx_tiocmget, .tiocmset = sx_tiocmset, + .break_ctl = sx_send_break, }; static int sx_init_drivers(void) @@ -2280,13 +2199,16 @@ static int sx_init_drivers(void) B9600 | CS8 | CREAD | HUPCL | CLOCAL; specialix_driver->init_termios.c_ispeed = 9600; specialix_driver->init_termios.c_ospeed = 9600; - specialix_driver->flags = TTY_DRIVER_REAL_RAW; + specialix_driver->flags = TTY_DRIVER_REAL_RAW | + TTY_DRIVER_HARDWARE_BREAK; tty_set_operations(specialix_driver, &sx_ops); - if ((error = tty_register_driver(specialix_driver))) { + error = tty_register_driver(specialix_driver); + if (error) { put_tty_driver(specialix_driver); - printk(KERN_ERR "sx: Couldn't register specialix IO8+ driver, error = %d\n", - error); + printk(KERN_ERR + "sx: Couldn't register specialix IO8+ driver, error = %d\n", + error); func_exit(); return 1; } @@ -2322,11 +2244,11 @@ static int __init specialix_init(void) printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n"); printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n"); -#ifdef CONFIG_SPECIALIX_RTSCTS - printk (KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); -#else - printk (KERN_INFO "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); -#endif + if (sx_rtscts) + printk(KERN_INFO + "sx: DTR/RTS pin is RTS when CRTSCTS is on.\n"); + else + printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n"); for (i = 0; i < SX_NBOARD; i++) spin_lock_init(&sx_board[i].lock); @@ -2344,27 +2266,27 @@ static int __init specialix_init(void) { struct pci_dev *pdev = NULL; - i=0; + i = 0; while (i < SX_NBOARD) { if (sx_board[i].flags & SX_BOARD_PRESENT) { i++; continue; } - pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX, - PCI_DEVICE_ID_SPECIALIX_IO8, - pdev); - if (!pdev) break; + pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, + PCI_DEVICE_ID_SPECIALIX_IO8, pdev); + if (!pdev) + break; if (pci_enable_device(pdev)) continue; sx_board[i].irq = pdev->irq; - sx_board[i].base = pci_resource_start (pdev, 2); + sx_board[i].base = pci_resource_start(pdev, 2); sx_board[i].flags |= SX_BOARD_IS_PCI; if (!sx_probe(&sx_board[i])) - found ++; + found++; } /* May exit pci_get sequence early with lots of boards */ if (pdev != NULL) @@ -2384,16 +2306,13 @@ static int __init specialix_init(void) } static int iobase[SX_NBOARD] = {0,}; - -static int irq [SX_NBOARD] = {0,}; +static int irq[SX_NBOARD] = {0,}; module_param_array(iobase, int, NULL, 0); module_param_array(irq, int, NULL, 0); module_param(sx_debug, int, 0); +module_param(sx_rtscts, int, 0); module_param(sx_rxfifo, int, 0); -#ifdef SPECIALIX_TIMER -module_param(sx_poll, int, 0); -#endif /* * You can setup up to 4 boards. @@ -2411,10 +2330,10 @@ static int __init specialix_init_module(void) func_enter(); if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) { - for(i = 0; i < SX_NBOARD; i++) { + for (i = 0; i < SX_NBOARD; i++) { sx_board[i].base = iobase[i]; sx_board[i].irq = irq[i]; - sx_board[i].count= 0; + sx_board[i].count = 0; } } @@ -2433,10 +2352,6 @@ static void __exit specialix_exit_module(void) for (i = 0; i < SX_NBOARD; i++) if (sx_board[i].flags & SX_BOARD_PRESENT) sx_release_io_range(&sx_board[i]); -#ifdef SPECIALIX_TIMER - del_timer_sync(&missed_irq_timer); -#endif - func_exit(); } diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 0243efb..19db1eb 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c @@ -1025,7 +1025,7 @@ static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count /*****************************************************************************/ -static void stl_putchar(struct tty_struct *tty, unsigned char ch) +static int stl_putchar(struct tty_struct *tty, unsigned char ch) { struct stlport *portp; unsigned int len; @@ -1034,12 +1034,12 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch) pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch); if (tty == NULL) - return; + return -EINVAL; portp = tty->driver_data; if (portp == NULL) - return; + return -EINVAL; if (portp->tx.buf == NULL) - return; + return -EINVAL; head = portp->tx.head; tail = portp->tx.tail; @@ -1053,6 +1053,7 @@ static void stl_putchar(struct tty_struct *tty, unsigned char ch) head = portp->tx.buf; } portp->tx.head = head; + return 0; } /*****************************************************************************/ @@ -1255,7 +1256,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file, static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) { struct stlport *portp; - unsigned int ival; int rc; void __user *argp = (void __user *)arg; @@ -1460,19 +1460,20 @@ static void stl_hangup(struct tty_struct *tty) /*****************************************************************************/ -static void stl_breakctl(struct tty_struct *tty, int state) +static int stl_breakctl(struct tty_struct *tty, int state) { struct stlport *portp; pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state); if (tty == NULL) - return; + return -EINVAL; portp = tty->driver_data; if (portp == NULL) - return; + return -EINVAL; stl_sendbreak(portp, ((state == -1) ? 1 : 2)); + return 0; } /*****************************************************************************/ @@ -4753,8 +4754,8 @@ static int __init stallion_module_init(void) if (IS_ERR(stallion_class)) printk("STALLION: failed to create class\n"); for (i = 0; i < 4; i++) - device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), - "staliomem%d", i); + device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i), + NULL, "staliomem%d", i); return 0; err_unrtty: diff --git a/drivers/char/sx.c b/drivers/char/sx.c index d5cffcd..c385206 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -286,8 +286,8 @@ static void sx_close(void *ptr); static int sx_chars_in_buffer(void *ptr); static int sx_init_board(struct sx_board *board); static int sx_init_portstructs(int nboards, int nports); -static int sx_fw_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +static long sx_fw_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); static int sx_init_drivers(void); static struct tty_driver *sx_driver; @@ -396,7 +396,7 @@ static struct real_driver sx_real_driver = { static const struct file_operations sx_fw_fops = { .owner = THIS_MODULE, - .ioctl = sx_fw_ioctl, + .unlocked_ioctl = sx_fw_ioctl, }; static struct miscdevice sx_fw_device = { @@ -1686,10 +1686,10 @@ static int do_memtest_w(struct sx_board *board, int min, int max) } #endif -static int sx_fw_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static long sx_fw_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) { - int rc = 0; + long rc = 0; int __user *descr = (int __user *)arg; int i; static struct sx_board *board = NULL; @@ -1699,13 +1699,10 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, func_enter(); -#if 0 - /* Removed superuser check: Sysops can use the permissions on the device - file to restrict access. Recommendation: Root only. (root.root 600) */ - if (!capable(CAP_SYS_ADMIN)) { + if (!capable(CAP_SYS_RAWIO)) return -EPERM; - } -#endif + + lock_kernel(); sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); @@ -1720,19 +1717,23 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, for (i = 0; i < SX_NBOARDS; i++) sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags); sx_dprintk(SX_DEBUG_FIRMWARE, "\n"); + unlock_kernel(); return -EIO; } switch (cmd) { case SXIO_SET_BOARD: sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg); + rc = -EIO; if (arg >= SX_NBOARDS) - return -EIO; + break; sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n"); if (!(boards[arg].flags & SX_BOARD_PRESENT)) - return -EIO; + break; sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n"); board = &boards[arg]; + rc = 0; + /* FIXME: And this does ... nothing?? */ break; case SXIO_GET_TYPE: rc = -ENOENT; /* If we manage to miss one, return error. */ @@ -1746,7 +1747,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = SX_TYPE_SI; if (IS_EISA_BOARD(board)) rc = SX_TYPE_SI; - sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %d\n", rc); + sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc); break; case SXIO_DO_RAMTEST: if (sx_initialized) /* Already initialized: better not ramtest the board. */ @@ -1760,19 +1761,26 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = do_memtest(board, 0, 0x7ff8); /* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */ } - sx_dprintk(SX_DEBUG_FIRMWARE, "returning memtest result= %d\n", - rc); + sx_dprintk(SX_DEBUG_FIRMWARE, + "returning memtest result= %ld\n", rc); break; case SXIO_DOWNLOAD: - if (sx_initialized) /* Already initialized */ - return -EEXIST; - if (!sx_reset(board)) - return -EIO; + if (sx_initialized) {/* Already initialized */ + rc = -EEXIST; + break; + } + if (!sx_reset(board)) { + rc = -EIO; + break; + } sx_dprintk(SX_DEBUG_INIT, "reset the board...\n"); tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER); - if (!tmp) - return -ENOMEM; + if (!tmp) { + rc = -ENOMEM; + break; + } + /* FIXME: check returns */ get_user(nbytes, descr++); get_user(offset, descr++); get_user(data, descr++); @@ -1782,7 +1790,8 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, (i + SX_CHUNK_SIZE > nbytes) ? nbytes - i : SX_CHUNK_SIZE)) { kfree(tmp); - return -EFAULT; + rc = -EFAULT; + break; } memcpy_toio(board->base2 + offset + i, tmp, (i + SX_CHUNK_SIZE > nbytes) ? @@ -1798,13 +1807,17 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = sx_nports; break; case SXIO_INIT: - if (sx_initialized) /* Already initialized */ - return -EEXIST; + if (sx_initialized) { /* Already initialized */ + rc = -EEXIST; + break; + } /* This is not allowed until all boards are initialized... */ for (i = 0; i < SX_NBOARDS; i++) { if ((boards[i].flags & SX_BOARD_PRESENT) && - !(boards[i].flags & SX_BOARD_INITIALIZED)) - return -EIO; + !(boards[i].flags & SX_BOARD_INITIALIZED)) { + rc = -EIO; + break; + } } for (i = 0; i < SX_NBOARDS; i++) if (!(boards[i].flags & SX_BOARD_PRESENT)) @@ -1832,15 +1845,15 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, rc = sx_nports; break; default: - printk(KERN_WARNING "Unknown ioctl on firmware device (%x).\n", - cmd); + rc = -ENOTTY; break; } + unlock_kernel(); func_exit(); return rc; } -static void sx_break(struct tty_struct *tty, int flag) +static int sx_break(struct tty_struct *tty, int flag) { struct sx_port *port = tty->driver_data; int rv; @@ -1857,6 +1870,7 @@ static void sx_break(struct tty_struct *tty, int flag) read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); unlock_kernel(); func_exit(); + return 0; } static int sx_tiocmget(struct tty_struct *tty, struct file *file) diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 527d220..500f517 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -304,7 +304,6 @@ struct mgsl_struct { /* generic HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -868,7 +867,6 @@ static int irq[MAX_ISA_DEVICES]; static int dma[MAX_ISA_DEVICES]; static int debug_level; static int maxframe[MAX_TOTAL_DEVICES]; -static int dosyncppp[MAX_TOTAL_DEVICES]; static int txdmabufs[MAX_TOTAL_DEVICES]; static int txholdbufs[MAX_TOTAL_DEVICES]; @@ -879,7 +877,6 @@ module_param_array(irq, int, NULL, 0); module_param_array(dma, int, NULL, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); module_param_array(txdmabufs, int, NULL, 0); module_param_array(txholdbufs, int, NULL, 0); @@ -2897,9 +2894,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file, * * Arguments: tty pointer to tty instance data * break_state -1=set break condition, 0=clear - * Return Value: None + * Return Value: error code */ -static void mgsl_break(struct tty_struct *tty, int break_state) +static int mgsl_break(struct tty_struct *tty, int break_state) { struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; unsigned long flags; @@ -2909,7 +2906,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state) __FILE__,__LINE__, info->device_name, break_state); if (mgsl_paranoia_check(info, tty->name, "mgsl_break")) - return; + return -EINVAL; spin_lock_irqsave(&info->irq_spinlock,flags); if (break_state == -1) @@ -2917,6 +2914,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state) else usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7)); spin_unlock_irqrestore(&info->irq_spinlock,flags); + return 0; } /* end of mgsl_break() */ @@ -4257,7 +4255,6 @@ static void mgsl_add_device( struct mgsl_struct *info ) if (info->line < MAX_TOTAL_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; if (txdmabufs[info->line]) { info->num_tx_dma_buffers = txdmabufs[info->line]; diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 2c3e43b..509c89a 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -128,17 +128,14 @@ static int slgt_device_count; static int ttymajor; static int debug_level; static int maxframe[MAX_DEVICES]; -static int dosyncppp[MAX_DEVICES]; module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned"); MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail"); MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)"); -MODULE_PARM_DESC(dosyncppp, "Enable synchronous net device, 0=disable 1=enable"); /* * tty support and callbacks @@ -165,7 +162,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v static int chars_in_buffer(struct tty_struct *tty); static void throttle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty); -static void set_break(struct tty_struct *tty, int break_state); +static int set_break(struct tty_struct *tty, int break_state); /* * generic HDLC support and callbacks @@ -214,6 +211,7 @@ struct slgt_desc char *buf; /* virtual address of data buffer */ unsigned int pdesc; /* physical address of this descriptor */ dma_addr_t buf_dma_addr; + unsigned short buf_count; }; #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) @@ -302,7 +300,7 @@ struct slgt_info { u32 idle_mode; u32 max_frame_size; /* as set by device config */ - unsigned int raw_rx_size; + unsigned int rbuf_fill_level; unsigned int if_mode; /* device status */ @@ -348,7 +346,6 @@ struct slgt_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC struct net_device *netdev; @@ -466,6 +463,7 @@ static void tx_start(struct slgt_info *info); static void tx_stop(struct slgt_info *info); static void tx_set_idle(struct slgt_info *info); static unsigned int free_tbuf_count(struct slgt_info *info); +static unsigned int tbuf_bytes(struct slgt_info *info); static void reset_tbufs(struct slgt_info *info); static void tdma_reset(struct slgt_info *info); static void tdma_start(struct slgt_info *info); @@ -513,7 +511,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); static int tiocmget(struct tty_struct *tty, struct file *file); static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); -static void set_break(struct tty_struct *tty, int break_state); +static int set_break(struct tty_struct *tty, int break_state); static int get_interface(struct slgt_info *info, int __user *if_mode); static int set_interface(struct slgt_info *info, int if_mode); static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); @@ -849,6 +847,7 @@ static int write(struct tty_struct *tty, int ret = 0; struct slgt_info *info = tty->driver_data; unsigned long flags; + unsigned int bufs_needed; if (sanity_check(info, tty->name, "write")) goto cleanup; @@ -865,25 +864,16 @@ static int write(struct tty_struct *tty, if (!count) goto cleanup; - if (info->params.mode == MGSL_MODE_RAW || - info->params.mode == MGSL_MODE_MONOSYNC || - info->params.mode == MGSL_MODE_BISYNC) { - unsigned int bufs_needed = (count/DMABUFSIZE); - unsigned int bufs_free = free_tbuf_count(info); - if (count % DMABUFSIZE) - ++bufs_needed; - if (bufs_needed > bufs_free) - goto cleanup; - } else { - if (info->tx_active) - goto cleanup; - if (info->tx_count) { - /* send accumulated data from send_char() calls */ - /* as frame and wait before accepting more data. */ - tx_load(info, info->tx_buf, info->tx_count); - goto start; - } + if (!info->tx_active && info->tx_count) { + /* send accumulated data from send_char() */ + tx_load(info, info->tx_buf, info->tx_count); + goto start; } + bufs_needed = (count/DMABUFSIZE); + if (count % DMABUFSIZE) + ++bufs_needed; + if (bufs_needed > free_tbuf_count(info)) + goto cleanup; ret = info->tx_count = count; tx_load(info, buf, count); @@ -1396,10 +1386,12 @@ done: static int chars_in_buffer(struct tty_struct *tty) { struct slgt_info *info = tty->driver_data; + int count; if (sanity_check(info, tty->name, "chars_in_buffer")) return 0; - DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count)); - return info->tx_count; + count = tbuf_bytes(info); + DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); + return count; } /* @@ -1452,14 +1444,14 @@ static void unthrottle(struct tty_struct * tty) * set or clear transmit break condition * break_state -1=set break condition, 0=clear */ -static void set_break(struct tty_struct *tty, int break_state) +static int set_break(struct tty_struct *tty, int break_state) { struct slgt_info *info = tty->driver_data; unsigned short value; unsigned long flags; if (sanity_check(info, tty->name, "set_break")) - return; + return -EINVAL; DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); spin_lock_irqsave(&info->lock,flags); @@ -1470,6 +1462,7 @@ static void set_break(struct tty_struct *tty, int break_state) value &= ~BIT6; wr_reg16(info, TCR, value); spin_unlock_irqrestore(&info->lock,flags); + return 0; } #if SYNCLINK_GENERIC_HDLC @@ -2679,8 +2672,31 @@ static int tx_abort(struct slgt_info *info) static int rx_enable(struct slgt_info *info, int enable) { unsigned long flags; - DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable)); + unsigned int rbuf_fill_level; + DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable)); spin_lock_irqsave(&info->lock,flags); + /* + * enable[31..16] = receive DMA buffer fill level + * 0 = noop (leave fill level unchanged) + * fill level must be multiple of 4 and <= buffer size + */ + rbuf_fill_level = ((unsigned int)enable) >> 16; + if (rbuf_fill_level) { + if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) { + spin_unlock_irqrestore(&info->lock, flags); + return -EINVAL; + } + info->rbuf_fill_level = rbuf_fill_level; + rx_stop(info); /* restart receiver to use new fill level */ + } + + /* + * enable[1..0] = receiver enable command + * 0 = disable + * 1 = enable + * 2 = enable or force hunt mode if already enabled + */ + enable &= 3; if (enable) { if (!info->rx_enabled) rx_start(info); @@ -3385,7 +3401,6 @@ static void add_device(struct slgt_info *info) if (info->line < MAX_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } slgt_device_count++; @@ -3447,7 +3462,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev info->magic = MGSL_MAGIC; INIT_WORK(&info->task, bh_handler); info->max_frame_size = 4096; - info->raw_rx_size = DMABUFSIZE; + info->rbuf_fill_level = DMABUFSIZE; info->port.close_delay = 5*HZ/10; info->port.closing_wait = 30*HZ; init_waitqueue_head(&info->status_event_wait_q); @@ -3934,15 +3949,7 @@ static void tdma_start(struct slgt_info *info) /* set 1st descriptor address */ wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); - switch(info->params.mode) { - case MGSL_MODE_RAW: - case MGSL_MODE_MONOSYNC: - case MGSL_MODE_BISYNC: - wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ - break; - default: - wr_reg32(info, TDCSR, BIT0); /* DMA enable */ - } + wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ } static void tx_stop(struct slgt_info *info) @@ -4145,7 +4152,7 @@ static void sync_mode(struct slgt_info *info) * 01 enable * 00 auto-CTS enable */ - val = 0; + val = BIT2; switch(info->params.mode) { case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; @@ -4418,6 +4425,8 @@ static void msc_set_vcr(struct slgt_info *info) break; } + if (info->if_mode & MGSL_INTERFACE_MSB_FIRST) + val |= BIT4; if (info->signals & SerialSignal_DTR) val |= BIT3; if (info->signals & SerialSignal_RTS) @@ -4456,16 +4465,7 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last while(!done) { /* reset current buffer for reuse */ info->rbufs[i].status = 0; - switch(info->params.mode) { - case MGSL_MODE_RAW: - case MGSL_MODE_MONOSYNC: - case MGSL_MODE_BISYNC: - set_desc_count(info->rbufs[i], info->raw_rx_size); - break; - default: - set_desc_count(info->rbufs[i], DMABUFSIZE); - } - + set_desc_count(info->rbufs[i], info->rbuf_fill_level); if (i == last) done = 1; if (++i == info->rbuf_count) @@ -4572,7 +4572,7 @@ check_again: DBGBH(("%s rx frame status=%04X size=%d\n", info->device_name, status, framesize)); - DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); + DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx"); if (framesize) { if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { @@ -4592,7 +4592,7 @@ check_again: info->icount.rxok++; while(copy_count) { - int partial_count = min(copy_count, DMABUFSIZE); + int partial_count = min_t(int, copy_count, info->rbuf_fill_level); memcpy(p, info->rbufs[i].buf, partial_count); p += partial_count; copy_count -= partial_count; @@ -4684,6 +4684,56 @@ static unsigned int free_tbuf_count(struct slgt_info *info) } /* + * return number of bytes in unsent transmit DMA buffers + * and the serial controller tx FIFO + */ +static unsigned int tbuf_bytes(struct slgt_info *info) +{ + unsigned int total_count = 0; + unsigned int i = info->tbuf_current; + unsigned int reg_value; + unsigned int count; + unsigned int active_buf_count = 0; + + /* + * Add descriptor counts for all tx DMA buffers. + * If count is zero (cleared by DMA controller after read), + * the buffer is complete or is actively being read from. + * + * Record buf_count of last buffer with zero count starting + * from current ring position. buf_count is mirror + * copy of count and is not cleared by serial controller. + * If DMA controller is active, that buffer is actively + * being read so add to total. + */ + do { + count = desc_count(info->tbufs[i]); + if (count) + total_count += count; + else if (!total_count) + active_buf_count = info->tbufs[i].buf_count; + if (++i == info->tbuf_count) + i = 0; + } while (i != info->tbuf_current); + + /* read tx DMA status register */ + reg_value = rd_reg32(info, TDCSR); + + /* if tx DMA active, last zero count buffer is in use */ + if (reg_value & BIT0) + total_count += active_buf_count; + + /* add tx FIFO count = reg_value[15..8] */ + total_count += (reg_value >> 8) & 0xff; + + /* if transmitter active add one byte for shift register */ + if (info->tx_active) + total_count++; + + return total_count; +} + +/* * load transmit DMA buffer(s) with data */ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) @@ -4721,6 +4771,7 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) set_desc_eof(*d, 0); set_desc_count(*d, count); + d->buf_count = count; } info->tbuf_current = i; diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 5768c41..6bdb44f 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c @@ -270,7 +270,6 @@ typedef struct _synclinkmp_info { /* SPPP/Cisco HDLC device parts */ int netcount; - int dosyncppp; spinlock_t netlock; #if SYNCLINK_GENERIC_HDLC @@ -469,13 +468,11 @@ static int ttymajor = 0; */ static int debug_level = 0; static int maxframe[MAX_DEVICES] = {0,}; -static int dosyncppp[MAX_DEVICES] = {0,}; module_param(break_on_load, bool, 0); module_param(ttymajor, int, 0); module_param(debug_level, int, 0); module_param_array(maxframe, int, NULL, 0); -module_param_array(dosyncppp, int, NULL, 0); static char *driver_name = "SyncLink MultiPort driver"; static char *driver_version = "$Revision: 4.38 $"; @@ -527,7 +524,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v static int chars_in_buffer(struct tty_struct *tty); static void throttle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty); -static void set_break(struct tty_struct *tty, int break_state); +static int set_break(struct tty_struct *tty, int break_state); #if SYNCLINK_GENERIC_HDLC #define dev_to_port(D) (dev_to_hdlc(D)->priv) @@ -552,7 +549,7 @@ static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr); static int tiocmget(struct tty_struct *tty, struct file *file); static int tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); -static void set_break(struct tty_struct *tty, int break_state); +static int set_break(struct tty_struct *tty, int break_state); static void add_device(SLMP_INFO *info); static void device_init(int adapter_num, struct pci_dev *pdev); @@ -1587,7 +1584,7 @@ static void unthrottle(struct tty_struct * tty) /* set or clear transmit break condition * break_state -1=set break condition, 0=clear */ -static void set_break(struct tty_struct *tty, int break_state) +static int set_break(struct tty_struct *tty, int break_state) { unsigned char RegValue; SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; @@ -1598,7 +1595,7 @@ static void set_break(struct tty_struct *tty, int break_state) __FILE__,__LINE__, info->device_name, break_state); if (sanity_check(info, tty->name, "set_break")) - return; + return -EINVAL; spin_lock_irqsave(&info->lock,flags); RegValue = read_reg(info, CTL); @@ -1608,6 +1605,7 @@ static void set_break(struct tty_struct *tty, int break_state) RegValue &= ~BIT3; write_reg(info, CTL, RegValue); spin_unlock_irqrestore(&info->lock,flags); + return 0; } #if SYNCLINK_GENERIC_HDLC @@ -3751,7 +3749,6 @@ static void add_device(SLMP_INFO *info) if (info->line < MAX_DEVICES) { if (maxframe[info->line]) info->max_frame_size = maxframe[info->line]; - info->dosyncppp = dosyncppp[info->line]; } synclinkmp_device_count++; diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index e1fc193..ae766d8 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -580,91 +580,133 @@ void tpm_continue_selftest(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_continue_selftest); +#define TPM_INTERNAL_RESULT_SIZE 200 + ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_FLAG; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - rc = transmit_cmd(chip, data, sizeof(data), - "attemtping to determine the permanent state"); - if (rc) + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + "attemtping to determine the permanent enabled state"); + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); + } + + rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_enabled); ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 35)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_FLAG; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - rc = transmit_cmd(chip, data, sizeof(data), - "attemtping to determine the permanent state"); - if (rc) + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + "attemtping to determine the permanent active state"); + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); + } + + rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_active); ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[sizeof(tpm_cap)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the owner state"); - if (rc) + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); + } + + rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_owned); ssize_t tpm_show_temp_deactivated(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[sizeof(tpm_cap)]; + u8 *data; ssize_t rc; struct tpm_chip *chip = dev_get_drvdata(dev); if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_FLAG; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the temporary state"); - if (rc) + if (rc) { + kfree(data); return 0; - return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); + } + + rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); + + kfree(data); + return rc; } EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); @@ -678,7 +720,7 @@ static const u8 pcrread[] = { ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(pcrread)), 30)]; + u8 *data; ssize_t rc; int i, j, num_pcrs; __be32 index; @@ -688,21 +730,27 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the number of PCRS"); - if (rc) + if (rc) { + kfree(data); return 0; + } num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); for (i = 0; i < num_pcrs; i++) { memcpy(data, pcrread, sizeof(pcrread)); index = cpu_to_be32(i); memcpy(data + 10, &index, 4); - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to read a PCR"); if (rc) goto out; @@ -712,6 +760,7 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, str += sprintf(str, "\n"); } out: + kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_pcrs); @@ -795,7 +844,7 @@ static const u8 cap_version[] = { ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, char *buf) { - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + u8 *data; ssize_t rc; char *str = buf; @@ -803,21 +852,27 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the manufacturer"); - if (rc) + if (rc) { + kfree(data); return 0; + } str += sprintf(str, "Manufacturer: 0x%x\n", be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); memcpy(data, cap_version, sizeof(cap_version)); data[CAP_VERSION_IDX] = CAP_VERSION_1_1; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the 1.1 version"); if (rc) goto out; @@ -828,6 +883,7 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, (int) data[17]); out: + kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps); @@ -835,7 +891,7 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); ssize_t tpm_show_caps_1_2(struct device * dev, struct device_attribute * attr, char *buf) { - u8 data[max_t(int, max(ARRAY_SIZE(tpm_cap), ARRAY_SIZE(cap_version)), 30)]; + u8 *data; ssize_t len; char *str = buf; @@ -843,15 +899,20 @@ ssize_t tpm_show_caps_1_2(struct device * dev, if (chip == NULL) return -ENODEV; + data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + memcpy(data, tpm_cap, sizeof(tpm_cap)); data[TPM_CAP_IDX] = TPM_CAP_PROP; data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - if ((len = tpm_transmit(chip, data, sizeof(data))) <= - TPM_ERROR_SIZE) { + len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); + if (len <= TPM_ERROR_SIZE) { dev_dbg(chip->dev, "A TPM error (%d) occurred " "attempting to determine the manufacturer\n", be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); + kfree(data); return 0; } @@ -861,8 +922,8 @@ ssize_t tpm_show_caps_1_2(struct device * dev, memcpy(data, cap_version, sizeof(cap_version)); data[CAP_VERSION_IDX] = CAP_VERSION_1_2; - if ((len = tpm_transmit(chip, data, sizeof(data))) <= - TPM_ERROR_SIZE) { + len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); + if (len <= TPM_ERROR_SIZE) { dev_err(chip->dev, "A TPM error (%d) occurred " "attempting to determine the 1.2 version\n", be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); @@ -874,6 +935,7 @@ ssize_t tpm_show_caps_1_2(struct device * dev, (int) data[19]); out: + kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); @@ -966,7 +1028,7 @@ ssize_t tpm_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - int in_size = size, out_size; + size_t in_size = size, out_size; /* cannot perform a write until the read has cleared either via tpm_read or a user_read_timer timeout */ @@ -1001,7 +1063,7 @@ ssize_t tpm_read(struct file *file, char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - int ret_size; + ssize_t ret_size; del_singleshot_timer_sync(&chip->user_read_timer); flush_scheduled_work(); diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 60a2d26..68f052b 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c @@ -448,7 +448,7 @@ out_free: goto out; } -const struct file_operations tpm_ascii_bios_measurements_ops = { +static const struct file_operations tpm_ascii_bios_measurements_ops = { .open = tpm_ascii_bios_measurements_open, .read = seq_read, .llseek = seq_lseek, @@ -486,7 +486,7 @@ out_free: goto out; } -const struct file_operations tpm_binary_bios_measurements_ops = { +static const struct file_operations tpm_binary_bios_measurements_ops = { .open = tpm_binary_bios_measurements_open, .read = seq_read, .llseek = seq_lseek, diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index c7a977b..ed1879c 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -622,6 +622,7 @@ static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { {"ATM1200", 0}, /* Atmel */ {"IFX0102", 0}, /* Infineon */ {"BCM0101", 0}, /* Broadcom */ + {"BCM0102", 0}, /* Broadcom */ {"NSC1200", 0}, /* National */ {"ICO0102", 0}, /* Intel */ /* Add new here */ diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 82f6a8c..0e6866f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -656,558 +656,6 @@ EXPORT_SYMBOL_GPL(tty_prepare_flip_string_flags); /** - * tty_set_termios_ldisc - set ldisc field - * @tty: tty structure - * @num: line discipline number - * - * This is probably overkill for real world processors but - * they are not on hot paths so a little discipline won't do - * any harm. - * - * Locking: takes termios_mutex - */ - -static void tty_set_termios_ldisc(struct tty_struct *tty, int num) -{ - mutex_lock(&tty->termios_mutex); - tty->termios->c_line = num; - mutex_unlock(&tty->termios_mutex); -} - -/* - * This guards the refcounted line discipline lists. The lock - * must be taken with irqs off because there are hangup path - * callers who will do ldisc lookups and cannot sleep. - */ - -static DEFINE_SPINLOCK(tty_ldisc_lock); -static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); -/* Line disc dispatch table */ -static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; - -/** - * tty_register_ldisc - install a line discipline - * @disc: ldisc number - * @new_ldisc: pointer to the ldisc object - * - * Installs a new line discipline into the kernel. The discipline - * is set up as unreferenced and then made available to the kernel - * from this point onwards. - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - -int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) -{ - unsigned long flags; - int ret = 0; - - if (disc < N_TTY || disc >= NR_LDISCS) - return -EINVAL; - - spin_lock_irqsave(&tty_ldisc_lock, flags); - tty_ldiscs[disc] = new_ldisc; - new_ldisc->num = disc; - new_ldisc->refcount = 0; - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - - return ret; -} -EXPORT_SYMBOL(tty_register_ldisc); - -/** - * tty_unregister_ldisc - unload a line discipline - * @disc: ldisc number - * @new_ldisc: pointer to the ldisc object - * - * Remove a line discipline from the kernel providing it is not - * currently in use. - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - -int tty_unregister_ldisc(int disc) -{ - unsigned long flags; - int ret = 0; - - if (disc < N_TTY || disc >= NR_LDISCS) - return -EINVAL; - - spin_lock_irqsave(&tty_ldisc_lock, flags); - if (tty_ldiscs[disc]->refcount) - ret = -EBUSY; - else - tty_ldiscs[disc] = NULL; - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - - return ret; -} -EXPORT_SYMBOL(tty_unregister_ldisc); - - -/** - * tty_ldisc_try_get - try and reference an ldisc - * @disc: ldisc number - * @ld: tty ldisc structure to complete - * - * Attempt to open and lock a line discipline into place. Return - * the line discipline refcounted and assigned in ld. On an error - * report the error code back - */ - -static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) -{ - unsigned long flags; - struct tty_ldisc_ops *ldops; - int err = -EINVAL; - - spin_lock_irqsave(&tty_ldisc_lock, flags); - ld->ops = NULL; - ldops = tty_ldiscs[disc]; - /* Check the entry is defined */ - if (ldops) { - /* If the module is being unloaded we can't use it */ - if (!try_module_get(ldops->owner)) - err = -EAGAIN; - else { - /* lock it */ - ldops->refcount++; - ld->ops = ldops; - err = 0; - } - } - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - return err; -} - -/** - * tty_ldisc_get - take a reference to an ldisc - * @disc: ldisc number - * @ld: tty line discipline structure to use - * - * Takes a reference to a line discipline. Deals with refcounts and - * module locking counts. Returns NULL if the discipline is not available. - * Returns a pointer to the discipline and bumps the ref count if it is - * available - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - -static int tty_ldisc_get(int disc, struct tty_ldisc *ld) -{ - int err; - - if (disc < N_TTY || disc >= NR_LDISCS) - return -EINVAL; - err = tty_ldisc_try_get(disc, ld); - if (err == -EAGAIN) { - request_module("tty-ldisc-%d", disc); - err = tty_ldisc_try_get(disc, ld); - } - return err; -} - -/** - * tty_ldisc_put - drop ldisc reference - * @disc: ldisc number - * - * Drop a reference to a line discipline. Manage refcounts and - * module usage counts - * - * Locking: - * takes tty_ldisc_lock to guard against ldisc races - */ - -static void tty_ldisc_put(struct tty_ldisc_ops *ld) -{ - unsigned long flags; - int disc = ld->num; - - BUG_ON(disc < N_TTY || disc >= NR_LDISCS); - - spin_lock_irqsave(&tty_ldisc_lock, flags); - ld = tty_ldiscs[disc]; - BUG_ON(ld->refcount == 0); - ld->refcount--; - module_put(ld->owner); - spin_unlock_irqrestore(&tty_ldisc_lock, flags); -} - -static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) -{ - return (*pos < NR_LDISCS) ? pos : NULL; -} - -static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) -{ - (*pos)++; - return (*pos < NR_LDISCS) ? pos : NULL; -} - -static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) -{ -} - -static int tty_ldiscs_seq_show(struct seq_file *m, void *v) -{ - int i = *(loff_t *)v; - struct tty_ldisc ld; - - if (tty_ldisc_get(i, &ld) < 0) - return 0; - seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); - tty_ldisc_put(ld.ops); - return 0; -} - -static const struct seq_operations tty_ldiscs_seq_ops = { - .start = tty_ldiscs_seq_start, - .next = tty_ldiscs_seq_next, - .stop = tty_ldiscs_seq_stop, - .show = tty_ldiscs_seq_show, -}; - -static int proc_tty_ldiscs_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &tty_ldiscs_seq_ops); -} - -const struct file_operations tty_ldiscs_proc_fops = { - .owner = THIS_MODULE, - .open = proc_tty_ldiscs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -/** - * tty_ldisc_assign - set ldisc on a tty - * @tty: tty to assign - * @ld: line discipline - * - * Install an instance of a line discipline into a tty structure. The - * ldisc must have a reference count above zero to ensure it remains/ - * The tty instance refcount starts at zero. - * - * Locking: - * Caller must hold references - */ - -static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) -{ - ld->refcount = 0; - tty->ldisc = *ld; -} - -/** - * tty_ldisc_try - internal helper - * @tty: the tty - * - * Make a single attempt to grab and bump the refcount on - * the tty ldisc. Return 0 on failure or 1 on success. This is - * used to implement both the waiting and non waiting versions - * of tty_ldisc_ref - * - * Locking: takes tty_ldisc_lock - */ - -static int tty_ldisc_try(struct tty_struct *tty) -{ - unsigned long flags; - struct tty_ldisc *ld; - int ret = 0; - - spin_lock_irqsave(&tty_ldisc_lock, flags); - ld = &tty->ldisc; - if (test_bit(TTY_LDISC, &tty->flags)) { - ld->refcount++; - ret = 1; - } - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - return ret; -} - -/** - * tty_ldisc_ref_wait - wait for the tty ldisc - * @tty: tty device - * - * Dereference the line discipline for the terminal and take a - * reference to it. If the line discipline is in flux then - * wait patiently until it changes. - * - * Note: Must not be called from an IRQ/timer context. The caller - * must also be careful not to hold other locks that will deadlock - * against a discipline change, such as an existing ldisc reference - * (which we check for) - * - * Locking: call functions take tty_ldisc_lock - */ - -struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) -{ - /* wait_event is a macro */ - wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); - if (tty->ldisc.refcount == 0) - printk(KERN_ERR "tty_ldisc_ref_wait\n"); - return &tty->ldisc; -} - -EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); - -/** - * tty_ldisc_ref - get the tty ldisc - * @tty: tty device - * - * Dereference the line discipline for the terminal and take a - * reference to it. If the line discipline is in flux then - * return NULL. Can be called from IRQ and timer functions. - * - * Locking: called functions take tty_ldisc_lock - */ - -struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) -{ - if (tty_ldisc_try(tty)) - return &tty->ldisc; - return NULL; -} - -EXPORT_SYMBOL_GPL(tty_ldisc_ref); - -/** - * tty_ldisc_deref - free a tty ldisc reference - * @ld: reference to free up - * - * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May - * be called in IRQ context. - * - * Locking: takes tty_ldisc_lock - */ - -void tty_ldisc_deref(struct tty_ldisc *ld) -{ - unsigned long flags; - - BUG_ON(ld == NULL); - - spin_lock_irqsave(&tty_ldisc_lock, flags); - if (ld->refcount == 0) - printk(KERN_ERR "tty_ldisc_deref: no references.\n"); - else - ld->refcount--; - if (ld->refcount == 0) - wake_up(&tty_ldisc_wait); - spin_unlock_irqrestore(&tty_ldisc_lock, flags); -} - -EXPORT_SYMBOL_GPL(tty_ldisc_deref); - -/** - * tty_ldisc_enable - allow ldisc use - * @tty: terminal to activate ldisc on - * - * Set the TTY_LDISC flag when the line discipline can be called - * again. Do necessary wakeups for existing sleepers. - * - * Note: nobody should set this bit except via this function. Clearing - * directly is allowed. - */ - -static void tty_ldisc_enable(struct tty_struct *tty) -{ - set_bit(TTY_LDISC, &tty->flags); - wake_up(&tty_ldisc_wait); -} - -/** - * tty_ldisc_restore - helper for tty ldisc change - * @tty: tty to recover - * @old: previous ldisc - * - * Restore the previous line discipline or N_TTY when a line discipline - * change fails due to an open error - */ - -static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) -{ - char buf[64]; - struct tty_ldisc new_ldisc; - - /* There is an outstanding reference here so this is safe */ - tty_ldisc_get(old->ops->num, old); - tty_ldisc_assign(tty, old); - tty_set_termios_ldisc(tty, old->ops->num); - if (old->ops->open && (old->ops->open(tty) < 0)) { - tty_ldisc_put(old->ops); - /* This driver is always present */ - if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) - panic("n_tty: get"); - tty_ldisc_assign(tty, &new_ldisc); - tty_set_termios_ldisc(tty, N_TTY); - if (new_ldisc.ops->open) { - int r = new_ldisc.ops->open(tty); - if (r < 0) - panic("Couldn't open N_TTY ldisc for " - "%s --- error %d.", - tty_name(tty, buf), r); - } - } -} - -/** - * tty_set_ldisc - set line discipline - * @tty: the terminal to set - * @ldisc: the line discipline - * - * Set the discipline of a tty line. Must be called from a process - * context. - * - * Locking: takes tty_ldisc_lock. - * called functions take termios_mutex - */ - -static int tty_set_ldisc(struct tty_struct *tty, int ldisc) -{ - int retval; - struct tty_ldisc o_ldisc, new_ldisc; - int work; - unsigned long flags; - struct tty_struct *o_tty; - -restart: - /* This is a bit ugly for now but means we can break the 'ldisc - is part of the tty struct' assumption later */ - retval = tty_ldisc_get(ldisc, &new_ldisc); - if (retval) - return retval; - - /* - * Problem: What do we do if this blocks ? - */ - - tty_wait_until_sent(tty, 0); - - if (tty->ldisc.ops->num == ldisc) { - tty_ldisc_put(new_ldisc.ops); - return 0; - } - - /* - * No more input please, we are switching. The new ldisc - * will update this value in the ldisc open function - */ - - tty->receive_room = 0; - - o_ldisc = tty->ldisc; - o_tty = tty->link; - - /* - * Make sure we don't change while someone holds a - * reference to the line discipline. The TTY_LDISC bit - * prevents anyone taking a reference once it is clear. - * We need the lock to avoid racing reference takers. - */ - - spin_lock_irqsave(&tty_ldisc_lock, flags); - if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { - if (tty->ldisc.refcount) { - /* Free the new ldisc we grabbed. Must drop the lock - first. */ - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - tty_ldisc_put(o_ldisc.ops); - /* - * There are several reasons we may be busy, including - * random momentary I/O traffic. We must therefore - * retry. We could distinguish between blocking ops - * and retries if we made tty_ldisc_wait() smarter. - * That is up for discussion. - */ - if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) - return -ERESTARTSYS; - goto restart; - } - if (o_tty && o_tty->ldisc.refcount) { - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - tty_ldisc_put(o_tty->ldisc.ops); - if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) - return -ERESTARTSYS; - goto restart; - } - } - /* - * If the TTY_LDISC bit is set, then we are racing against - * another ldisc change - */ - if (!test_bit(TTY_LDISC, &tty->flags)) { - struct tty_ldisc *ld; - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - tty_ldisc_put(new_ldisc.ops); - ld = tty_ldisc_ref_wait(tty); - tty_ldisc_deref(ld); - goto restart; - } - - clear_bit(TTY_LDISC, &tty->flags); - if (o_tty) - clear_bit(TTY_LDISC, &o_tty->flags); - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - - /* - * From this point on we know nobody has an ldisc - * usage reference, nor can they obtain one until - * we say so later on. - */ - - work = cancel_delayed_work(&tty->buf.work); - /* - * Wait for ->hangup_work and ->buf.work handlers to terminate - * MUST NOT hold locks here. - */ - flush_scheduled_work(); - /* Shutdown the current discipline. */ - if (o_ldisc.ops->close) - (o_ldisc.ops->close)(tty); - - /* Now set up the new line discipline. */ - tty_ldisc_assign(tty, &new_ldisc); - tty_set_termios_ldisc(tty, ldisc); - if (new_ldisc.ops->open) - retval = (new_ldisc.ops->open)(tty); - if (retval < 0) { - tty_ldisc_put(new_ldisc.ops); - tty_ldisc_restore(tty, &o_ldisc); - } - /* At this point we hold a reference to the new ldisc and a - a reference to the old ldisc. If we ended up flipping back - to the existing ldisc we have two references to it */ - - if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) - tty->ops->set_ldisc(tty); - - tty_ldisc_put(o_ldisc.ops); - - /* - * Allow ldisc referencing to occur as soon as the driver - * ldisc callback completes. - */ - - tty_ldisc_enable(tty); - if (o_tty) - tty_ldisc_enable(o_tty); - - /* Restart it in case no characters kick it off. Safe if - already running */ - if (work) - schedule_delayed_work(&tty->buf.work, 1); - return retval; -} - -/** * get_tty_driver - find device of a tty * @dev_t: device identifier * @index: returns the index of the tty @@ -1467,7 +915,7 @@ static void tty_reset_termios(struct tty_struct *tty) * do_tty_hangup - actual handler for hangup events * @work: tty device * -k * This can be called by the "eventd" kernel thread. That is process + * This can be called by the "eventd" kernel thread. That is process * synchronous but doesn't hold any locks, so we need to make sure we * have the appropriate locks for what we're doing. * @@ -1671,19 +1119,6 @@ int tty_hung_up_p(struct file *filp) EXPORT_SYMBOL(tty_hung_up_p); -/** - * is_tty - checker whether file is a TTY - * @filp: file handle that may be a tty - * - * Check if the file handle is a tty handle. - */ - -int is_tty(struct file *filp) -{ - return filp->f_op->read == tty_read - || filp->f_op->read == hung_up_tty_read; -} - static void session_clear_tty(struct pid *session) { struct task_struct *p; @@ -1726,8 +1161,8 @@ void disassociate_ctty(int on_exit) tty = get_current_tty(); if (tty) { tty_pgrp = get_pid(tty->pgrp); - mutex_unlock(&tty_mutex); lock_kernel(); + mutex_unlock(&tty_mutex); /* XXX: here we race, there is nothing protecting tty */ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); @@ -2193,7 +1628,6 @@ static int init_dev(struct tty_driver *driver, int idx, struct ktermios *tp, **tp_loc, *o_tp, **o_tp_loc; struct ktermios *ltp, **ltp_loc, *o_ltp, **o_ltp_loc; int retval = 0; - struct tty_ldisc *ld; /* check whether we're reopening an existing tty */ if (driver->flags & TTY_DRIVER_DEVPTS_MEM) { @@ -2342,25 +1776,12 @@ static int init_dev(struct tty_driver *driver, int idx, * If we fail here just call release_tty to clean up. No need * to decrement the use counts, as release_tty doesn't care. */ - - ld = &tty->ldisc; - if (ld->ops->open) { - retval = (ld->ops->open)(tty); - if (retval) - goto release_mem_out; - } - if (o_tty && o_tty->ldisc.ops->open) { - retval = (o_tty->ldisc.ops->open)(o_tty); - if (retval) { - if (ld->ops->close) - (ld->ops->close)(tty); - goto release_mem_out; - } - tty_ldisc_enable(o_tty); - } - tty_ldisc_enable(tty); - goto success; + retval = tty_ldisc_setup(tty, o_tty); + + if (retval) + goto release_mem_out; + goto success; /* * This fast open can be used if the tty is already open. @@ -2498,12 +1919,10 @@ static void release_tty(struct tty_struct *tty, int idx) static void release_dev(struct file *filp) { struct tty_struct *tty, *o_tty; - struct tty_ldisc ld; int pty_master, tty_closing, o_tty_closing, do_sleep; int devpts; int idx; char buf[64]; - unsigned long flags; tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, @@ -2705,56 +2124,9 @@ static void release_dev(struct file *filp) printk(KERN_DEBUG "freeing tty structure..."); #endif /* - * Prevent flush_to_ldisc() from rescheduling the work for later. Then - * kill any delayed work. As this is the final close it does not - * race with the set_ldisc code path. + * Ask the line discipline code to release its structures */ - clear_bit(TTY_LDISC, &tty->flags); - cancel_delayed_work(&tty->buf.work); - - /* - * Wait for ->hangup_work and ->buf.work handlers to terminate - */ - - flush_scheduled_work(); - - /* - * Wait for any short term users (we know they are just driver - * side waiters as the file is closing so user count on the file - * side is zero. - */ - spin_lock_irqsave(&tty_ldisc_lock, flags); - while (tty->ldisc.refcount) { - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); - spin_lock_irqsave(&tty_ldisc_lock, flags); - } - spin_unlock_irqrestore(&tty_ldisc_lock, flags); - /* - * Shutdown the current line discipline, and reset it to N_TTY. - * - * FIXME: this MUST get fixed for the new reflocking - */ - if (tty->ldisc.ops->close) - (tty->ldisc.ops->close)(tty); - tty_ldisc_put(tty->ldisc.ops); - - /* - * Switch the line discipline back - */ - WARN_ON(tty_ldisc_get(N_TTY, &ld)); - tty_ldisc_assign(tty, &ld); - tty_set_termios_ldisc(tty, N_TTY); - if (o_tty) { - /* FIXME: could o_tty be in setldisc here ? */ - clear_bit(TTY_LDISC, &o_tty->flags); - if (o_tty->ldisc.ops->close) - (o_tty->ldisc.ops->close)(o_tty); - tty_ldisc_put(o_tty->ldisc.ops); - WARN_ON(tty_ldisc_get(N_TTY, &ld)); - tty_ldisc_assign(o_tty, &ld); - tty_set_termios_ldisc(o_tty, N_TTY); - } + tty_ldisc_release(tty, o_tty); /* * The release_tty function takes care of the details of clearing * the slots and preserving the termios structure. @@ -3464,16 +2836,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) static int send_break(struct tty_struct *tty, unsigned int duration) { - if (tty_write_lock(tty, 0) < 0) - return -EINTR; - tty->ops->break_ctl(tty, -1); - if (!signal_pending(current)) - msleep_interruptible(duration); - tty->ops->break_ctl(tty, 0); - tty_write_unlock(tty); - if (signal_pending(current)) - return -EINTR; - return 0; + int retval; + + if (tty->ops->break_ctl == NULL) + return 0; + + if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK) + retval = tty->ops->break_ctl(tty, duration); + else { + /* Do the work ourselves */ + if (tty_write_lock(tty, 0) < 0) + return -EINTR; + retval = tty->ops->break_ctl(tty, -1); + if (retval) + goto out; + if (!signal_pending(current)) + msleep_interruptible(duration); + retval = tty->ops->break_ctl(tty, 0); +out: + tty_write_unlock(tty); + if (signal_pending(current)) + retval = -EINTR; + } + return retval; } /** @@ -3564,36 +2949,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) tty->driver->subtype == PTY_TYPE_MASTER) real_tty = tty->link; - /* - * Break handling by driver - */ - - retval = -EINVAL; - - if (!tty->ops->break_ctl) { - switch (cmd) { - case TIOCSBRK: - case TIOCCBRK: - if (tty->ops->ioctl) - retval = tty->ops->ioctl(tty, file, cmd, arg); - if (retval != -EINVAL && retval != -ENOIOCTLCMD) - printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name); - return retval; - - /* These two ioctl's always return success; even if */ - /* the driver doesn't support them. */ - case TCSBRK: - case TCSBRKP: - if (!tty->ops->ioctl) - return 0; - retval = tty->ops->ioctl(tty, file, cmd, arg); - if (retval != -EINVAL && retval != -ENOIOCTLCMD) - printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name); - if (retval == -ENOIOCTLCMD) - retval = 0; - return retval; - } - } /* * Factor out some common prep work @@ -3615,6 +2970,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } + /* + * Now do the stuff. + */ switch (cmd) { case TIOCSTI: return tiocsti(tty, p); @@ -3658,12 +3016,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) */ case TIOCSBRK: /* Turn break on, unconditionally */ if (tty->ops->break_ctl) - tty->ops->break_ctl(tty, -1); + return tty->ops->break_ctl(tty, -1); return 0; - case TIOCCBRK: /* Turn break off, unconditionally */ if (tty->ops->break_ctl) - tty->ops->break_ctl(tty, 0); + return tty->ops->break_ctl(tty, 0); return 0; case TCSBRK: /* SVID version: non-zero arg --> no break */ /* non-zero arg means wait for all output data @@ -3962,12 +3319,9 @@ EXPORT_SYMBOL(tty_flip_buffer_push); static void initialize_tty_struct(struct tty_struct *tty) { - struct tty_ldisc ld; memset(tty, 0, sizeof(struct tty_struct)); tty->magic = TTY_MAGIC; - if (tty_ldisc_get(N_TTY, &ld) < 0) - panic("n_tty: init_tty"); - tty_ldisc_assign(tty, &ld); + tty_ldisc_init(tty); tty->session = NULL; tty->pgrp = NULL; tty->overrun_time = jiffies; @@ -4045,7 +3399,7 @@ struct device *tty_register_device(struct tty_driver *driver, unsigned index, else tty_line_name(driver, index, name); - return device_create(tty_class, device, dev, name); + return device_create_drvdata(tty_class, device, dev, NULL, name); } /** @@ -4226,7 +3580,6 @@ void proc_clear_tty(struct task_struct *p) p->signal->tty = NULL; spin_unlock_irq(&p->sighand->siglock); } -EXPORT_SYMBOL(proc_clear_tty); /* Called under the sighand lock */ @@ -4280,7 +3633,7 @@ void __init console_init(void) initcall_t *call; /* Setup the default TTY line discipline. */ - (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); + tty_ldisc_begin(); /* * set up the console device so that later boot sequences can @@ -4323,20 +3676,22 @@ static int __init tty_init(void) if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) panic("Couldn't register /dev/tty driver\n"); - device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), "tty"); + device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 0), NULL, + "tty"); cdev_init(&console_cdev, &console_fops); if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) panic("Couldn't register /dev/console driver\n"); - device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), "console"); + device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 1), NULL, + "console"); #ifdef CONFIG_UNIX98_PTYS cdev_init(&ptmx_cdev, &ptmx_fops); if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) || register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) panic("Couldn't register /dev/ptmx driver\n"); - device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), "ptmx"); + device_create_drvdata(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); #endif #ifdef CONFIG_VT @@ -4344,7 +3699,7 @@ static int __init tty_init(void) if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) || register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) panic("Couldn't register /dev/tty0 driver\n"); - device_create(tty_class, NULL, MKDEV(TTY_MAJOR, 0), "tty0"); + device_create_drvdata(tty_class, NULL, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); vty_init(); #endif diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c new file mode 100644 index 0000000..f307f13 --- /dev/null +++ b/drivers/char/tty_ldisc.c @@ -0,0 +1,714 @@ +#include <linux/types.h> +#include <linux/major.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/fcntl.h> +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/tty_flip.h> +#include <linux/devpts_fs.h> +#include <linux/file.h> +#include <linux/fdtable.h> +#include <linux/console.h> +#include <linux/timer.h> +#include <linux/ctype.h> +#include <linux/kd.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/slab.h> +#include <linux/poll.h> +#include <linux/proc_fs.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/smp_lock.h> +#include <linux/device.h> +#include <linux/wait.h> +#include <linux/bitops.h> +#include <linux/delay.h> +#include <linux/seq_file.h> + +#include <linux/uaccess.h> +#include <asm/system.h> + +#include <linux/kbd_kern.h> +#include <linux/vt_kern.h> +#include <linux/selection.h> + +#include <linux/kmod.h> +#include <linux/nsproxy.h> + +/* + * This guards the refcounted line discipline lists. The lock + * must be taken with irqs off because there are hangup path + * callers who will do ldisc lookups and cannot sleep. + */ + +static DEFINE_SPINLOCK(tty_ldisc_lock); +static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); +/* Line disc dispatch table */ +static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]; + +/** + * tty_register_ldisc - install a line discipline + * @disc: ldisc number + * @new_ldisc: pointer to the ldisc object + * + * Installs a new line discipline into the kernel. The discipline + * is set up as unreferenced and then made available to the kernel + * from this point onwards. + * + * Locking: + * takes tty_ldisc_lock to guard against ldisc races + */ + +int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc) +{ + unsigned long flags; + int ret = 0; + + if (disc < N_TTY || disc >= NR_LDISCS) + return -EINVAL; + + spin_lock_irqsave(&tty_ldisc_lock, flags); + tty_ldiscs[disc] = new_ldisc; + new_ldisc->num = disc; + new_ldisc->refcount = 0; + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + + return ret; +} +EXPORT_SYMBOL(tty_register_ldisc); + +/** + * tty_unregister_ldisc - unload a line discipline + * @disc: ldisc number + * @new_ldisc: pointer to the ldisc object + * + * Remove a line discipline from the kernel providing it is not + * currently in use. + * + * Locking: + * takes tty_ldisc_lock to guard against ldisc races + */ + +int tty_unregister_ldisc(int disc) +{ + unsigned long flags; + int ret = 0; + + if (disc < N_TTY || disc >= NR_LDISCS) + return -EINVAL; + + spin_lock_irqsave(&tty_ldisc_lock, flags); + if (tty_ldiscs[disc]->refcount) + ret = -EBUSY; + else + tty_ldiscs[disc] = NULL; + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + + return ret; +} +EXPORT_SYMBOL(tty_unregister_ldisc); + + +/** + * tty_ldisc_try_get - try and reference an ldisc + * @disc: ldisc number + * @ld: tty ldisc structure to complete + * + * Attempt to open and lock a line discipline into place. Return + * the line discipline refcounted and assigned in ld. On an error + * report the error code back + */ + +static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) +{ + unsigned long flags; + struct tty_ldisc_ops *ldops; + int err = -EINVAL; + + spin_lock_irqsave(&tty_ldisc_lock, flags); + ld->ops = NULL; + ldops = tty_ldiscs[disc]; + /* Check the entry is defined */ + if (ldops) { + /* If the module is being unloaded we can't use it */ + if (!try_module_get(ldops->owner)) + err = -EAGAIN; + else { + /* lock it */ + ldops->refcount++; + ld->ops = ldops; + err = 0; + } + } + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + return err; +} + +/** + * tty_ldisc_get - take a reference to an ldisc + * @disc: ldisc number + * @ld: tty line discipline structure to use + * + * Takes a reference to a line discipline. Deals with refcounts and + * module locking counts. Returns NULL if the discipline is not available. + * Returns a pointer to the discipline and bumps the ref count if it is + * available + * + * Locking: + * takes tty_ldisc_lock to guard against ldisc races + */ + +static int tty_ldisc_get(int disc, struct tty_ldisc *ld) +{ + int err; + + if (disc < N_TTY || disc >= NR_LDISCS) + return -EINVAL; + err = tty_ldisc_try_get(disc, ld); + if (err < 0) { + request_module("tty-ldisc-%d", disc); + err = tty_ldisc_try_get(disc, ld); + } + return err; +} + +/** + * tty_ldisc_put - drop ldisc reference + * @disc: ldisc number + * + * Drop a reference to a line discipline. Manage refcounts and + * module usage counts + * + * Locking: + * takes tty_ldisc_lock to guard against ldisc races + */ + +static void tty_ldisc_put(struct tty_ldisc_ops *ld) +{ + unsigned long flags; + int disc = ld->num; + + BUG_ON(disc < N_TTY || disc >= NR_LDISCS); + + spin_lock_irqsave(&tty_ldisc_lock, flags); + ld = tty_ldiscs[disc]; + BUG_ON(ld->refcount == 0); + ld->refcount--; + module_put(ld->owner); + spin_unlock_irqrestore(&tty_ldisc_lock, flags); +} + +static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) +{ + return (*pos < NR_LDISCS) ? pos : NULL; +} + +static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) +{ + (*pos)++; + return (*pos < NR_LDISCS) ? pos : NULL; +} + +static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) +{ +} + +static int tty_ldiscs_seq_show(struct seq_file *m, void *v) +{ + int i = *(loff_t *)v; + struct tty_ldisc ld; + + if (tty_ldisc_get(i, &ld) < 0) + return 0; + seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); + tty_ldisc_put(ld.ops); + return 0; +} + +static const struct seq_operations tty_ldiscs_seq_ops = { + .start = tty_ldiscs_seq_start, + .next = tty_ldiscs_seq_next, + .stop = tty_ldiscs_seq_stop, + .show = tty_ldiscs_seq_show, +}; + +static int proc_tty_ldiscs_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &tty_ldiscs_seq_ops); +} + +const struct file_operations tty_ldiscs_proc_fops = { + .owner = THIS_MODULE, + .open = proc_tty_ldiscs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +/** + * tty_ldisc_assign - set ldisc on a tty + * @tty: tty to assign + * @ld: line discipline + * + * Install an instance of a line discipline into a tty structure. The + * ldisc must have a reference count above zero to ensure it remains/ + * The tty instance refcount starts at zero. + * + * Locking: + * Caller must hold references + */ + +static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) +{ + ld->refcount = 0; + tty->ldisc = *ld; +} + +/** + * tty_ldisc_try - internal helper + * @tty: the tty + * + * Make a single attempt to grab and bump the refcount on + * the tty ldisc. Return 0 on failure or 1 on success. This is + * used to implement both the waiting and non waiting versions + * of tty_ldisc_ref + * + * Locking: takes tty_ldisc_lock + */ + +static int tty_ldisc_try(struct tty_struct *tty) +{ + unsigned long flags; + struct tty_ldisc *ld; + int ret = 0; + + spin_lock_irqsave(&tty_ldisc_lock, flags); + ld = &tty->ldisc; + if (test_bit(TTY_LDISC, &tty->flags)) { + ld->refcount++; + ret = 1; + } + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + return ret; +} + +/** + * tty_ldisc_ref_wait - wait for the tty ldisc + * @tty: tty device + * + * Dereference the line discipline for the terminal and take a + * reference to it. If the line discipline is in flux then + * wait patiently until it changes. + * + * Note: Must not be called from an IRQ/timer context. The caller + * must also be careful not to hold other locks that will deadlock + * against a discipline change, such as an existing ldisc reference + * (which we check for) + * + * Locking: call functions take tty_ldisc_lock + */ + +struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) +{ + /* wait_event is a macro */ + wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); + if (tty->ldisc.refcount == 0) + printk(KERN_ERR "tty_ldisc_ref_wait\n"); + return &tty->ldisc; +} + +EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); + +/** + * tty_ldisc_ref - get the tty ldisc + * @tty: tty device + * + * Dereference the line discipline for the terminal and take a + * reference to it. If the line discipline is in flux then + * return NULL. Can be called from IRQ and timer functions. + * + * Locking: called functions take tty_ldisc_lock + */ + +struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) +{ + if (tty_ldisc_try(tty)) + return &tty->ldisc; + return NULL; +} + +EXPORT_SYMBOL_GPL(tty_ldisc_ref); + +/** + * tty_ldisc_deref - free a tty ldisc reference + * @ld: reference to free up + * + * Undoes the effect of tty_ldisc_ref or tty_ldisc_ref_wait. May + * be called in IRQ context. + * + * Locking: takes tty_ldisc_lock + */ + +void tty_ldisc_deref(struct tty_ldisc *ld) +{ + unsigned long flags; + + BUG_ON(ld == NULL); + + spin_lock_irqsave(&tty_ldisc_lock, flags); + if (ld->refcount == 0) + printk(KERN_ERR "tty_ldisc_deref: no references.\n"); + else + ld->refcount--; + if (ld->refcount == 0) + wake_up(&tty_ldisc_wait); + spin_unlock_irqrestore(&tty_ldisc_lock, flags); +} + +EXPORT_SYMBOL_GPL(tty_ldisc_deref); + +/** + * tty_ldisc_enable - allow ldisc use + * @tty: terminal to activate ldisc on + * + * Set the TTY_LDISC flag when the line discipline can be called + * again. Do necessary wakeups for existing sleepers. + * + * Note: nobody should set this bit except via this function. Clearing + * directly is allowed. + */ + +void tty_ldisc_enable(struct tty_struct *tty) +{ + set_bit(TTY_LDISC, &tty->flags); + wake_up(&tty_ldisc_wait); +} + +/** + * tty_set_termios_ldisc - set ldisc field + * @tty: tty structure + * @num: line discipline number + * + * This is probably overkill for real world processors but + * they are not on hot paths so a little discipline won't do + * any harm. + * + * Locking: takes termios_mutex + */ + +static void tty_set_termios_ldisc(struct tty_struct *tty, int num) +{ + mutex_lock(&tty->termios_mutex); + tty->termios->c_line = num; + mutex_unlock(&tty->termios_mutex); +} + + +/** + * tty_ldisc_restore - helper for tty ldisc change + * @tty: tty to recover + * @old: previous ldisc + * + * Restore the previous line discipline or N_TTY when a line discipline + * change fails due to an open error + */ + +static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) +{ + char buf[64]; + struct tty_ldisc new_ldisc; + + /* There is an outstanding reference here so this is safe */ + tty_ldisc_get(old->ops->num, old); + tty_ldisc_assign(tty, old); + tty_set_termios_ldisc(tty, old->ops->num); + if (old->ops->open && (old->ops->open(tty) < 0)) { + tty_ldisc_put(old->ops); + /* This driver is always present */ + if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) + panic("n_tty: get"); + tty_ldisc_assign(tty, &new_ldisc); + tty_set_termios_ldisc(tty, N_TTY); + if (new_ldisc.ops->open) { + int r = new_ldisc.ops->open(tty); + if (r < 0) + panic("Couldn't open N_TTY ldisc for " + "%s --- error %d.", + tty_name(tty, buf), r); + } + } +} + +/** + * tty_set_ldisc - set line discipline + * @tty: the terminal to set + * @ldisc: the line discipline + * + * Set the discipline of a tty line. Must be called from a process + * context. + * + * Locking: takes tty_ldisc_lock. + * called functions take termios_mutex + */ + +int tty_set_ldisc(struct tty_struct *tty, int ldisc) +{ + int retval; + struct tty_ldisc o_ldisc, new_ldisc; + int work; + unsigned long flags; + struct tty_struct *o_tty; + +restart: + /* This is a bit ugly for now but means we can break the 'ldisc + is part of the tty struct' assumption later */ + retval = tty_ldisc_get(ldisc, &new_ldisc); + if (retval) + return retval; + + /* + * Problem: What do we do if this blocks ? + */ + + tty_wait_until_sent(tty, 0); + + if (tty->ldisc.ops->num == ldisc) { + tty_ldisc_put(new_ldisc.ops); + return 0; + } + + /* + * No more input please, we are switching. The new ldisc + * will update this value in the ldisc open function + */ + + tty->receive_room = 0; + + o_ldisc = tty->ldisc; + o_tty = tty->link; + + /* + * Make sure we don't change while someone holds a + * reference to the line discipline. The TTY_LDISC bit + * prevents anyone taking a reference once it is clear. + * We need the lock to avoid racing reference takers. + */ + + spin_lock_irqsave(&tty_ldisc_lock, flags); + if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { + if (tty->ldisc.refcount) { + /* Free the new ldisc we grabbed. Must drop the lock + first. */ + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + tty_ldisc_put(o_ldisc.ops); + /* + * There are several reasons we may be busy, including + * random momentary I/O traffic. We must therefore + * retry. We could distinguish between blocking ops + * and retries if we made tty_ldisc_wait() smarter. + * That is up for discussion. + */ + if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) + return -ERESTARTSYS; + goto restart; + } + if (o_tty && o_tty->ldisc.refcount) { + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + tty_ldisc_put(o_tty->ldisc.ops); + if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) + return -ERESTARTSYS; + goto restart; + } + } + /* + * If the TTY_LDISC bit is set, then we are racing against + * another ldisc change + */ + if (!test_bit(TTY_LDISC, &tty->flags)) { + struct tty_ldisc *ld; + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + tty_ldisc_put(new_ldisc.ops); + ld = tty_ldisc_ref_wait(tty); + tty_ldisc_deref(ld); + goto restart; + } + + clear_bit(TTY_LDISC, &tty->flags); + if (o_tty) + clear_bit(TTY_LDISC, &o_tty->flags); + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + + /* + * From this point on we know nobody has an ldisc + * usage reference, nor can they obtain one until + * we say so later on. + */ + + work = cancel_delayed_work(&tty->buf.work); + /* + * Wait for ->hangup_work and ->buf.work handlers to terminate + * MUST NOT hold locks here. + */ + flush_scheduled_work(); + /* Shutdown the current discipline. */ + if (o_ldisc.ops->close) + (o_ldisc.ops->close)(tty); + + /* Now set up the new line discipline. */ + tty_ldisc_assign(tty, &new_ldisc); + tty_set_termios_ldisc(tty, ldisc); + if (new_ldisc.ops->open) + retval = (new_ldisc.ops->open)(tty); + if (retval < 0) { + tty_ldisc_put(new_ldisc.ops); + tty_ldisc_restore(tty, &o_ldisc); + } + /* At this point we hold a reference to the new ldisc and a + a reference to the old ldisc. If we ended up flipping back + to the existing ldisc we have two references to it */ + + if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) + tty->ops->set_ldisc(tty); + + tty_ldisc_put(o_ldisc.ops); + + /* + * Allow ldisc referencing to occur as soon as the driver + * ldisc callback completes. + */ + + tty_ldisc_enable(tty); + if (o_tty) + tty_ldisc_enable(o_tty); + + /* Restart it in case no characters kick it off. Safe if + already running */ + if (work) + schedule_delayed_work(&tty->buf.work, 1); + return retval; +} + + +/** + * tty_ldisc_setup - open line discipline + * @tty: tty being shut down + * @o_tty: pair tty for pty/tty pairs + * + * Called during the initial open of a tty/pty pair in order to set up the + * line discplines and bind them to the tty. + */ + +int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) +{ + struct tty_ldisc *ld = &tty->ldisc; + int retval; + + if (ld->ops->open) { + retval = (ld->ops->open)(tty); + if (retval) + return retval; + } + if (o_tty && o_tty->ldisc.ops->open) { + retval = (o_tty->ldisc.ops->open)(o_tty); + if (retval) { + if (ld->ops->close) + (ld->ops->close)(tty); + return retval; + } + tty_ldisc_enable(o_tty); + } + tty_ldisc_enable(tty); + return 0; +} + +/** + * tty_ldisc_release - release line discipline + * @tty: tty being shut down + * @o_tty: pair tty for pty/tty pairs + * + * Called during the final close of a tty/pty pair in order to shut down the + * line discpline layer. + */ + +void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) +{ + unsigned long flags; + struct tty_ldisc ld; + /* + * Prevent flush_to_ldisc() from rescheduling the work for later. Then + * kill any delayed work. As this is the final close it does not + * race with the set_ldisc code path. + */ + clear_bit(TTY_LDISC, &tty->flags); + cancel_delayed_work(&tty->buf.work); + + /* + * Wait for ->hangup_work and ->buf.work handlers to terminate + */ + + flush_scheduled_work(); + + /* + * Wait for any short term users (we know they are just driver + * side waiters as the file is closing so user count on the file + * side is zero. + */ + spin_lock_irqsave(&tty_ldisc_lock, flags); + while (tty->ldisc.refcount) { + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); + spin_lock_irqsave(&tty_ldisc_lock, flags); + } + spin_unlock_irqrestore(&tty_ldisc_lock, flags); + /* + * Shutdown the current line discipline, and reset it to N_TTY. + * + * FIXME: this MUST get fixed for the new reflocking + */ + if (tty->ldisc.ops->close) + (tty->ldisc.ops->close)(tty); + tty_ldisc_put(tty->ldisc.ops); + + /* + * Switch the line discipline back + */ + WARN_ON(tty_ldisc_get(N_TTY, &ld)); + tty_ldisc_assign(tty, &ld); + tty_set_termios_ldisc(tty, N_TTY); + if (o_tty) { + /* FIXME: could o_tty be in setldisc here ? */ + clear_bit(TTY_LDISC, &o_tty->flags); + if (o_tty->ldisc.ops->close) + (o_tty->ldisc.ops->close)(o_tty); + tty_ldisc_put(o_tty->ldisc.ops); + WARN_ON(tty_ldisc_get(N_TTY, &ld)); + tty_ldisc_assign(o_tty, &ld); + tty_set_termios_ldisc(o_tty, N_TTY); + } +} + +/** + * tty_ldisc_init - ldisc setup for new tty + * @tty: tty being allocated + * + * Set up the line discipline objects for a newly allocated tty. Note that + * the tty structure is not completely set up when this call is made. + */ + +void tty_ldisc_init(struct tty_struct *tty) +{ + struct tty_ldisc ld; + if (tty_ldisc_get(N_TTY, &ld) < 0) + panic("n_tty: init_tty"); + tty_ldisc_assign(tty, &ld); +} + +void tty_ldisc_begin(void) +{ + /* Setup the default TTY line discipline. */ + (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY); +} diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index eebfad2..c2ae52d 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -481,10 +481,10 @@ static struct class *vc_class; void vcs_make_sysfs(struct tty_struct *tty) { - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), - "vcs%u", tty->index + 1); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), - "vcsa%u", tty->index + 1); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), + NULL, "vcs%u", tty->index + 1); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), + NULL, "vcsa%u", tty->index + 1); } void vcs_remove_sysfs(struct tty_struct *tty) @@ -499,7 +499,7 @@ int __init vcs_init(void) panic("unable to get major %d for vcs device", VCS_MAJOR); vc_class = class_create(THIS_MODULE, "vc"); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 0), "vcs"); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, 128), "vcsa"); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); + device_create_drvdata(vc_class, NULL, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); return 0; } diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c deleted file mode 100644 index 65fb848..0000000 --- a/drivers/char/viocons.c +++ /dev/null @@ -1,1171 +0,0 @@ -/* -*- linux-c -*- - * - * drivers/char/viocons.c - * - * iSeries Virtual Terminal - * - * Authors: Dave Boutcher <boutcher@us.ibm.com> - * Ryan Arnold <ryanarn@us.ibm.com> - * Colin Devilbiss <devilbis@us.ibm.com> - * Stephen Rothwell - * - * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation - * - * 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) anyu 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 <linux/kernel.h> -#include <linux/proc_fs.h> -#include <linux/errno.h> -#include <linux/vmalloc.h> -#include <linux/mm.h> -#include <linux/console.h> -#include <linux/module.h> -#include <asm/uaccess.h> -#include <linux/init.h> -#include <linux/wait.h> -#include <linux/spinlock.h> -#include <asm/ioctls.h> -#include <linux/kd.h> -#include <linux/tty.h> -#include <linux/tty_flip.h> -#include <linux/sysrq.h> - -#include <asm/firmware.h> -#include <asm/iseries/vio.h> -#include <asm/iseries/hv_lp_event.h> -#include <asm/iseries/hv_call_event.h> -#include <asm/iseries/hv_lp_config.h> -#include <asm/iseries/hv_call.h> - -#ifdef CONFIG_VT -#error You must turn off CONFIG_VT to use CONFIG_VIOCONS -#endif - -#define VIOTTY_MAGIC (0x0DCB) -#define VTTY_PORTS 10 - -#define VIOCONS_KERN_WARN KERN_WARNING "viocons: " -#define VIOCONS_KERN_INFO KERN_INFO "viocons: " - -static DEFINE_SPINLOCK(consolelock); -static DEFINE_SPINLOCK(consoleloglock); - -static int vio_sysrq_pressed; - -#define VIOCHAR_NUM_BUF 16 - -/* - * Our port information. We store a pointer to one entry in the - * tty_driver_data - */ -static struct port_info { - int magic; - struct tty_struct *tty; - HvLpIndex lp; - u8 vcons; - u64 seq; /* sequence number of last HV send */ - u64 ack; /* last ack from HV */ -/* - * When we get writes faster than we can send it to the partition, - * buffer the data here. Note that used is a bit map of used buffers. - * It had better have enough bits to hold VIOCHAR_NUM_BUF the bitops assume - * it is a multiple of unsigned long - */ - unsigned long used; - u8 *buffer[VIOCHAR_NUM_BUF]; - int bufferBytes[VIOCHAR_NUM_BUF]; - int curbuf; - int bufferOverflow; - int overflowMessage; -} port_info[VTTY_PORTS]; - -#define viochar_is_console(pi) ((pi) == &port_info[0]) -#define viochar_port(pi) ((pi) - &port_info[0]) - -static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp); - -static struct tty_driver *viotty_driver; - -static void hvlog(char *fmt, ...) -{ - int i; - unsigned long flags; - va_list args; - static char buf[256]; - - spin_lock_irqsave(&consoleloglock, flags); - va_start(args, fmt); - i = vscnprintf(buf, sizeof(buf) - 1, fmt, args); - va_end(args); - buf[i++] = '\r'; - HvCall_writeLogBuffer(buf, i); - spin_unlock_irqrestore(&consoleloglock, flags); -} - -static void hvlogOutput(const char *buf, int count) -{ - unsigned long flags; - int begin; - int index; - static const char cr = '\r'; - - begin = 0; - spin_lock_irqsave(&consoleloglock, flags); - for (index = 0; index < count; index++) { - if (buf[index] == '\n') { - /* - * Start right after the last '\n' or at the zeroth - * array position and output the number of characters - * including the newline. - */ - HvCall_writeLogBuffer(&buf[begin], index - begin + 1); - begin = index + 1; - HvCall_writeLogBuffer(&cr, 1); - } - } - if ((index - begin) > 0) - HvCall_writeLogBuffer(&buf[begin], index - begin); - spin_unlock_irqrestore(&consoleloglock, flags); -} - -/* - * Make sure we're pointing to a valid port_info structure. Shamelessly - * plagerized from serial.c - */ -static inline int viotty_paranoia_check(struct port_info *pi, - char *name, const char *routine) -{ - static const char *bad_pi_addr = VIOCONS_KERN_WARN - "warning: bad address for port_info struct (%s) in %s\n"; - static const char *badmagic = VIOCONS_KERN_WARN - "warning: bad magic number for port_info struct (%s) in %s\n"; - - if ((pi < &port_info[0]) || (viochar_port(pi) > VTTY_PORTS)) { - printk(bad_pi_addr, name, routine); - return 1; - } - if (pi->magic != VIOTTY_MAGIC) { - printk(badmagic, name, routine); - return 1; - } - return 0; -} - -/* - * Add data to our pending-send buffers. - * - * NOTE: Don't use printk in here because it gets nastily recursive. - * hvlog can be used to log to the hypervisor buffer - */ -static int buffer_add(struct port_info *pi, const char *buf, size_t len) -{ - size_t bleft; - size_t curlen; - const char *curbuf; - int nextbuf; - - curbuf = buf; - bleft = len; - while (bleft > 0) { - /* - * If there is no space left in the current buffer, we have - * filled everything up, so return. If we filled the previous - * buffer we would already have moved to the next one. - */ - if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { - hvlog ("\n\rviocons: No overflow buffer available for memcpy().\n"); - pi->bufferOverflow++; - pi->overflowMessage = 1; - break; - } - - /* - * Turn on the "used" bit for this buffer. If it's already on, - * that's fine. - */ - set_bit(pi->curbuf, &pi->used); - - /* - * See if this buffer has been allocated. If not, allocate it. - */ - if (pi->buffer[pi->curbuf] == NULL) { - pi->buffer[pi->curbuf] = - kmalloc(VIOCHAR_MAX_DATA, GFP_ATOMIC); - if (pi->buffer[pi->curbuf] == NULL) { - hvlog("\n\rviocons: kmalloc failed allocating spaces for buffer %d.", - pi->curbuf); - break; - } - } - - /* Figure out how much we can copy into this buffer. */ - if (bleft < (VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf])) - curlen = bleft; - else - curlen = VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf]; - - /* Copy the data into the buffer. */ - memcpy(pi->buffer[pi->curbuf] + pi->bufferBytes[pi->curbuf], - curbuf, curlen); - - pi->bufferBytes[pi->curbuf] += curlen; - curbuf += curlen; - bleft -= curlen; - - /* - * Now see if we've filled this buffer. If not then - * we'll try to use it again later. If we've filled it - * up then we'll advance the curbuf to the next in the - * circular queue. - */ - if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) { - nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; - /* - * Move to the next buffer if it hasn't been used yet - */ - if (test_bit(nextbuf, &pi->used) == 0) - pi->curbuf = nextbuf; - } - } - return len - bleft; -} - -/* - * Send pending data - * - * NOTE: Don't use printk in here because it gets nastily recursive. - * hvlog can be used to log to the hypervisor buffer - */ -static void send_buffers(struct port_info *pi) -{ - HvLpEvent_Rc hvrc; - int nextbuf; - struct viocharlpevent *viochar; - unsigned long flags; - - spin_lock_irqsave(&consolelock, flags); - - viochar = (struct viocharlpevent *) - vio_get_event_buffer(viomajorsubtype_chario); - - /* Make sure we got a buffer */ - if (viochar == NULL) { - hvlog("\n\rviocons: Can't get viochar buffer in sendBuffers()."); - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - if (pi->used == 0) { - hvlog("\n\rviocons: in sendbuffers(), but no buffers used.\n"); - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - /* - * curbuf points to the buffer we're filling. We want to - * start sending AFTER this one. - */ - nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF; - - /* - * Loop until we find a buffer with the used bit on - */ - while (test_bit(nextbuf, &pi->used) == 0) - nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; - - initDataEvent(viochar, pi->lp); - - /* - * While we have buffers with data, and our send window - * is open, send them - */ - while ((test_bit(nextbuf, &pi->used)) && - ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { - viochar->len = pi->bufferBytes[nextbuf]; - viochar->event.xCorrelationToken = pi->seq++; - viochar->event.xSizeMinus1 = - offsetof(struct viocharlpevent, data) + viochar->len; - - memcpy(viochar->data, pi->buffer[nextbuf], viochar->len); - - hvrc = HvCallEvent_signalLpEvent(&viochar->event); - if (hvrc) { - /* - * MUST unlock the spinlock before doing a printk - */ - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - - printk(VIOCONS_KERN_WARN - "error sending event! return code %d\n", - (int)hvrc); - return; - } - - /* - * clear the used bit, zero the number of bytes in - * this buffer, and move to the next buffer - */ - clear_bit(nextbuf, &pi->used); - pi->bufferBytes[nextbuf] = 0; - nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF; - } - - /* - * If we have emptied all the buffers, start at 0 again. - * this will re-use any allocated buffers - */ - if (pi->used == 0) { - pi->curbuf = 0; - - if (pi->overflowMessage) - pi->overflowMessage = 0; - - if (pi->tty) { - tty_wakeup(pi->tty); - } - } - - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); -} - -/* - * Our internal writer. Gets called both from the console device and - * the tty device. the tty pointer will be NULL if called from the console. - * Return total number of bytes "written". - * - * NOTE: Don't use printk in here because it gets nastily recursive. hvlog - * can be used to log to the hypervisor buffer - */ -static int internal_write(struct port_info *pi, const char *buf, size_t len) -{ - HvLpEvent_Rc hvrc; - size_t bleft; - size_t curlen; - const char *curbuf; - unsigned long flags; - struct viocharlpevent *viochar; - - /* - * Write to the hvlog of inbound data are now done prior to - * calling internal_write() since internal_write() is only called in - * the event that an lp event path is active, which isn't the case for - * logging attempts prior to console initialization. - * - * If there is already data queued for this port, send it prior to - * attempting to send any new data. - */ - if (pi->used) - send_buffers(pi); - - spin_lock_irqsave(&consolelock, flags); - - viochar = vio_get_event_buffer(viomajorsubtype_chario); - if (viochar == NULL) { - spin_unlock_irqrestore(&consolelock, flags); - hvlog("\n\rviocons: Can't get vio buffer in internal_write()."); - return -EAGAIN; - } - initDataEvent(viochar, pi->lp); - - curbuf = buf; - bleft = len; - - while ((bleft > 0) && (pi->used == 0) && - ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) { - if (bleft > VIOCHAR_MAX_DATA) - curlen = VIOCHAR_MAX_DATA; - else - curlen = bleft; - - viochar->event.xCorrelationToken = pi->seq++; - memcpy(viochar->data, curbuf, curlen); - viochar->len = curlen; - viochar->event.xSizeMinus1 = - offsetof(struct viocharlpevent, data) + curlen; - - hvrc = HvCallEvent_signalLpEvent(&viochar->event); - if (hvrc) { - hvlog("viocons: error sending event! %d\n", (int)hvrc); - goto out; - } - curbuf += curlen; - bleft -= curlen; - } - - /* If we didn't send it all, buffer as much of it as we can. */ - if (bleft > 0) - bleft -= buffer_add(pi, curbuf, bleft); -out: - vio_free_event_buffer(viomajorsubtype_chario, viochar); - spin_unlock_irqrestore(&consolelock, flags); - return len - bleft; -} - -static struct port_info *get_port_data(struct tty_struct *tty) -{ - unsigned long flags; - struct port_info *pi; - - spin_lock_irqsave(&consolelock, flags); - if (tty) { - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, - "get_port_data")) { - pi = NULL; - } - } else - /* - * If this is the console device, use the lp from - * the first port entry - */ - pi = &port_info[0]; - spin_unlock_irqrestore(&consolelock, flags); - return pi; -} - -/* - * Initialize the common fields in a charLpEvent - */ -static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp) -{ - struct HvLpEvent *hev = &viochar->event; - - memset(viochar, 0, sizeof(struct viocharlpevent)); - - hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK | - HV_LP_EVENT_INT; - hev->xType = HvLpEvent_Type_VirtualIo; - hev->xSubtype = viomajorsubtype_chario | viochardata; - hev->xSourceLp = HvLpConfig_getLpIndex(); - hev->xTargetLp = lp; - hev->xSizeMinus1 = sizeof(struct viocharlpevent); - hev->xSourceInstanceId = viopath_sourceinst(lp); - hev->xTargetInstanceId = viopath_targetinst(lp); -} - -/* - * early console device write - */ -static void viocons_write_early(struct console *co, const char *s, unsigned count) -{ - hvlogOutput(s, count); -} - -/* - * console device write - */ -static void viocons_write(struct console *co, const char *s, unsigned count) -{ - int index; - int begin; - struct port_info *pi; - - static const char cr = '\r'; - - /* - * Check port data first because the target LP might be valid but - * simply not active, in which case we want to hvlog the output. - */ - pi = get_port_data(NULL); - if (pi == NULL) { - hvlog("\n\rviocons_write: unable to get port data."); - return; - } - - hvlogOutput(s, count); - - if (!viopath_isactive(pi->lp)) - return; - - /* - * Any newline character found will cause a - * carriage return character to be emitted as well. - */ - begin = 0; - for (index = 0; index < count; index++) { - if (s[index] == '\n') { - /* - * Newline found. Print everything up to and - * including the newline - */ - internal_write(pi, &s[begin], index - begin + 1); - begin = index + 1; - /* Emit a carriage return as well */ - internal_write(pi, &cr, 1); - } - } - - /* If any characters left to write, write them now */ - if ((index - begin) > 0) - internal_write(pi, &s[begin], index - begin); -} - -/* - * Work out the device associate with this console - */ -static struct tty_driver *viocons_device(struct console *c, int *index) -{ - *index = c->index; - return viotty_driver; -} - -/* - * console device I/O methods - */ -static struct console viocons_early = { - .name = "viocons", - .write = viocons_write_early, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -static struct console viocons = { - .name = "viocons", - .write = viocons_write, - .device = viocons_device, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -/* - * TTY Open method - */ -static int viotty_open(struct tty_struct *tty, struct file *filp) -{ - int port; - unsigned long flags; - struct port_info *pi; - - port = tty->index; - - if ((port < 0) || (port >= VTTY_PORTS)) - return -ENODEV; - - spin_lock_irqsave(&consolelock, flags); - - pi = &port_info[port]; - /* If some other TTY is already connected here, reject the open */ - if ((pi->tty) && (pi->tty != tty)) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN - "attempt to open device twice from different ttys\n"); - return -EBUSY; - } - tty->driver_data = pi; - pi->tty = tty; - spin_unlock_irqrestore(&consolelock, flags); - - return 0; -} - -/* - * TTY Close method - */ -static void viotty_close(struct tty_struct *tty, struct file *filp) -{ - unsigned long flags; - struct port_info *pi; - - spin_lock_irqsave(&consolelock, flags); - pi = (struct port_info *)tty->driver_data; - - if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_close")) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - if (tty->count == 1) - pi->tty = NULL; - spin_unlock_irqrestore(&consolelock, flags); -} - -/* - * TTY Write method - */ -static int viotty_write(struct tty_struct *tty, const unsigned char *buf, - int count) -{ - struct port_info *pi; - - pi = get_port_data(tty); - if (pi == NULL) { - hvlog("\n\rviotty_write: no port data."); - return -ENODEV; - } - - if (viochar_is_console(pi)) - hvlogOutput(buf, count); - - /* - * If the path to this LP is closed, don't bother doing anything more. - * just dump the data on the floor and return count. For some reason - * some user level programs will attempt to probe available tty's and - * they'll attempt a viotty_write on an invalid port which maps to an - * invalid target lp. If this is the case then ignore the - * viotty_write call and, since the viopath isn't active to this - * partition, return count. - */ - if (!viopath_isactive(pi->lp)) - return count; - - return internal_write(pi, buf, count); -} - -/* - * TTY put_char method - */ -static int viotty_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct port_info *pi; - - pi = get_port_data(tty); - if (pi == NULL) - return 0; - - /* This will append '\r' as well if the char is '\n' */ - if (viochar_is_console(pi)) - hvlogOutput(&ch, 1); - - if (viopath_isactive(pi->lp)) - internal_write(pi, &ch, 1); - return 1; -} - -/* - * TTY write_room method - */ -static int viotty_write_room(struct tty_struct *tty) -{ - int i; - int room = 0; - struct port_info *pi; - unsigned long flags; - - spin_lock_irqsave(&consolelock, flags); - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) { - spin_unlock_irqrestore(&consolelock, flags); - return 0; - } - - /* If no buffers are used, return the max size. */ - if (pi->used == 0) { - spin_unlock_irqrestore(&consolelock, flags); - return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF; - } - - /* - * We retain the spinlock because we want to get an accurate - * count and it can change on us between each operation if we - * don't hold the spinlock. - */ - for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++) - room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]); - spin_unlock_irqrestore(&consolelock, flags); - - if (room > VIOCHAR_MAX_DATA) - room = VIOCHAR_MAX_DATA; - return room; -} - -/* - * TTY chars_in_buffer method - */ -static int viotty_chars_in_buffer(struct tty_struct *tty) -{ - return 0; -} - -static int viotty_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - switch (cmd) { - /* - * the ioctls below read/set the flags usually shown in the leds - * don't use them - they will go away without warning - */ - case KDGETLED: - case KDGKBLED: - return put_user(0, (char *)arg); - - case KDSKBLED: - return 0; - } - /* FIXME: WTF is this being called for ??? */ - lock_kernel(); - ret = n_tty_ioctl(tty, file, cmd, arg); - unlock_kernel(); - return ret; -} - -/* - * Handle an open charLpEvent. Could be either interrupt or ack - */ -static void vioHandleOpenEvent(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - struct port_info *pi; - int reject = 0; - - if (hvlpevent_is_ack(event)) { - if (port >= VTTY_PORTS) - return; - - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - pi = &port_info[port]; - if (event->xRc == HvLpEvent_Rc_Good) { - pi->seq = pi->ack = 0; - /* - * This line allows connections from the primary - * partition but once one is connected from the - * primary partition nothing short of a reboot - * of linux will allow access from the hosting - * partition again without a required iSeries fix. - */ - pi->lp = event->xTargetLp; - } - - spin_unlock_irqrestore(&consolelock, flags); - if (event->xRc != HvLpEvent_Rc_Good) - printk(VIOCONS_KERN_WARN - "handle_open_event: event->xRc == (%d).\n", - event->xRc); - - if (event->xCorrelationToken != 0) { - atomic_t *aptr= (atomic_t *)event->xCorrelationToken; - atomic_set(aptr, 1); - } else - printk(VIOCONS_KERN_WARN - "weird...got open ack without atomic\n"); - return; - } - - /* This had better require an ack, otherwise complain */ - if (!hvlpevent_need_ack(event)) { - printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - /* Make sure this is a good virtual tty */ - if (port >= VTTY_PORTS) { - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - /* - * Flag state here since we can't printk while holding - * a spinlock. - */ - reject = 1; - } else { - pi = &port_info[port]; - if ((pi->lp != HvLpIndexInvalid) && - (pi->lp != event->xSourceLp)) { - /* - * If this is tty is already connected to a different - * partition, fail. - */ - event->xRc = HvLpEvent_Rc_SubtypeError; - cevent->subtype_result_code = viorc_openRejected; - reject = 2; - } else { - pi->lp = event->xSourceLp; - event->xRc = HvLpEvent_Rc_Good; - cevent->subtype_result_code = viorc_good; - pi->seq = pi->ack = 0; - reject = 0; - } - } - - spin_unlock_irqrestore(&consolelock, flags); - - if (reject == 1) - printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n"); - else if (reject == 2) - printk(VIOCONS_KERN_WARN - "open rejected: console in exclusive use by another partition.\n"); - - /* Return the acknowledgement */ - HvCallEvent_ackLpEvent(event); -} - -/* - * Handle a close charLpEvent. This should ONLY be an Interrupt because the - * virtual console should never actually issue a close event to the hypervisor - * because the virtual console never goes away. A close event coming from the - * hypervisor simply means that there are no client consoles connected to the - * virtual console. - * - * Regardless of the number of connections masqueraded on the other side of - * the hypervisor ONLY ONE close event should be called to accompany the ONE - * open event that is called. The close event should ONLY be called when NO - * MORE connections (masqueraded or not) exist on the other side of the - * hypervisor. - */ -static void vioHandleCloseEvent(struct HvLpEvent *event) -{ - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - u8 port = cevent->virtual_device; - - if (hvlpevent_is_int(event)) { - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN - "close message from invalid virtual device.\n"); - return; - } - - /* For closes, just mark the console partition invalid */ - spin_lock_irqsave(&consolelock, flags); - /* Got the lock, don't cause console output */ - - if (port_info[port].lp == event->xSourceLp) - port_info[port].lp = HvLpIndexInvalid; - - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp); - } else - printk(VIOCONS_KERN_WARN - "got unexpected close acknowlegement\n"); -} - -/* - * Handle a config charLpEvent. Could be either interrupt or ack - */ -static void vioHandleConfig(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - - HvCall_writeLogBuffer(cevent->data, cevent->len); - - if (cevent->data[0] == 0x01) - printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n", - cevent->data[1], cevent->data[2], - cevent->data[3], cevent->data[4]); - else - printk(VIOCONS_KERN_WARN "unknown config event\n"); -} - -/* - * Handle a data charLpEvent. - */ -static void vioHandleData(struct HvLpEvent *event) -{ - struct tty_struct *tty; - unsigned long flags; - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - struct port_info *pi; - int index; - int num_pushed; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n", - port); - return; - } - - /* - * Hold the spinlock so that we don't take an interrupt that - * changes tty between the time we fetch the port_info - * pointer and the time we paranoia check. - */ - spin_lock_irqsave(&consolelock, flags); - pi = &port_info[port]; - - /* - * Change 05/01/2003 - Ryan Arnold: If a partition other than - * the current exclusive partition tries to send us data - * events then just drop them on the floor because we don't - * want his stinking data. He isn't authorized to receive - * data because he wasn't the first one to get the console, - * therefore he shouldn't be allowed to send data either. - * This will work without an iSeries fix. - */ - if (pi->lp != event->xSourceLp) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - - tty = pi->tty; - if (tty == NULL) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n", - port); - return; - } - - if (tty->magic != TTY_MAGIC) { - spin_unlock_irqrestore(&consolelock, flags); - printk(VIOCONS_KERN_WARN "tty bad magic\n"); - return; - } - - /* - * Just to be paranoid, make sure the tty points back to this port - */ - pi = (struct port_info *)tty->driver_data; - if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) { - spin_unlock_irqrestore(&consolelock, flags); - return; - } - spin_unlock_irqrestore(&consolelock, flags); - - /* - * Change 07/21/2003 - Ryan Arnold: functionality added to - * support sysrq utilizing ^O as the sysrq key. The sysrq - * functionality will only work if built into the kernel and - * then only if sysrq is enabled through the proc filesystem. - */ - num_pushed = 0; - for (index = 0; index < cevent->len; index++) { - /* - * Will be optimized away if !CONFIG_MAGIC_SYSRQ: - */ - if (sysrq_on()) { - /* 0x0f is the ascii character for ^O */ - if (cevent->data[index] == '\x0f') { - vio_sysrq_pressed = 1; - /* - * continue because we don't want to add - * the sysrq key into the data string. - */ - continue; - } else if (vio_sysrq_pressed) { - handle_sysrq(cevent->data[index], tty); - vio_sysrq_pressed = 0; - /* - * continue because we don't want to add - * the sysrq sequence into the data string. - */ - continue; - } - } - /* - * The sysrq sequence isn't included in this check if - * sysrq is enabled and compiled into the kernel because - * the sequence will never get inserted into the buffer. - * Don't attempt to copy more data into the buffer than we - * have room for because it would fail without indication. - */ - if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) { - printk(VIOCONS_KERN_WARN "input buffer overflow!\n"); - break; - } - num_pushed++; - } - - if (num_pushed) - tty_flip_buffer_push(tty); -} - -/* - * Handle an ack charLpEvent. - */ -static void vioHandleAck(struct HvLpEvent *event) -{ - struct viocharlpevent *cevent = (struct viocharlpevent *)event; - unsigned long flags; - u8 port = cevent->virtual_device; - - if (port >= VTTY_PORTS) { - printk(VIOCONS_KERN_WARN "data on invalid virtual device\n"); - return; - } - - spin_lock_irqsave(&consolelock, flags); - port_info[port].ack = event->xCorrelationToken; - spin_unlock_irqrestore(&consolelock, flags); - - if (port_info[port].used) - send_buffers(&port_info[port]); -} - -/* - * Handle charLpEvents and route to the appropriate routine - */ -static void vioHandleCharEvent(struct HvLpEvent *event) -{ - int charminor; - - if (event == NULL) - return; - - charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK; - switch (charminor) { - case viocharopen: - vioHandleOpenEvent(event); - break; - case viocharclose: - vioHandleCloseEvent(event); - break; - case viochardata: - vioHandleData(event); - break; - case viocharack: - vioHandleAck(event); - break; - case viocharconfig: - vioHandleConfig(event); - break; - default: - if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) { - event->xRc = HvLpEvent_Rc_InvalidSubtype; - HvCallEvent_ackLpEvent(event); - } - } -} - -/* - * Send an open event - */ -static int send_open(HvLpIndex remoteLp, void *sem) -{ - return HvCallEvent_signalLpEventFast(remoteLp, - HvLpEvent_Type_VirtualIo, - viomajorsubtype_chario | viocharopen, - HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck, - viopath_sourceinst(remoteLp), - viopath_targetinst(remoteLp), - (u64)(unsigned long)sem, VIOVERSION << 16, - 0, 0, 0, 0); -} - -static const struct tty_operations serial_ops = { - .open = viotty_open, - .close = viotty_close, - .write = viotty_write, - .put_char = viotty_put_char, - .write_room = viotty_write_room, - .chars_in_buffer = viotty_chars_in_buffer, - .ioctl = viotty_ioctl, -}; - -static int __init viocons_init2(void) -{ - atomic_t wait_flag; - int rc; - - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; - - /* +2 for fudge */ - rc = viopath_open(HvLpConfig_getPrimaryLpIndex(), - viomajorsubtype_chario, VIOCHAR_WINDOW + 2); - if (rc) - printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc); - - if (viopath_hostLp == HvLpIndexInvalid) - vio_set_hostlp(); - - /* - * And if the primary is not the same as the hosting LP, open to the - * hosting lp - */ - if ((viopath_hostLp != HvLpIndexInvalid) && - (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) { - printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n", - viopath_hostLp); - rc = viopath_open(viopath_hostLp, viomajorsubtype_chario, - VIOCHAR_WINDOW + 2); /* +2 for fudge */ - if (rc) - printk(VIOCONS_KERN_WARN - "error opening to partition %d: %d\n", - viopath_hostLp, rc); - } - - if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0) - printk(VIOCONS_KERN_WARN - "error seting handler for console events!\n"); - - /* - * First, try to open the console to the hosting lp. - * Wait on a semaphore for the response. - */ - atomic_set(&wait_flag, 0); - if ((viopath_isactive(viopath_hostLp)) && - (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) { - printk(VIOCONS_KERN_INFO "hosting partition %d\n", - viopath_hostLp); - while (atomic_read(&wait_flag) == 0) - mb(); - atomic_set(&wait_flag, 0); - } - - /* - * If we don't have an active console, try the primary - */ - if ((!viopath_isactive(port_info[0].lp)) && - (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) && - (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag) - == 0)) { - printk(VIOCONS_KERN_INFO "opening console to primary partition\n"); - while (atomic_read(&wait_flag) == 0) - mb(); - } - - /* Initialize the tty_driver structure */ - viotty_driver = alloc_tty_driver(VTTY_PORTS); - viotty_driver->owner = THIS_MODULE; - viotty_driver->driver_name = "vioconsole"; - viotty_driver->name = "tty"; - viotty_driver->name_base = 1; - viotty_driver->major = TTY_MAJOR; - viotty_driver->minor_start = 1; - viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE; - viotty_driver->subtype = 1; - viotty_driver->init_termios = tty_std_termios; - viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; - tty_set_operations(viotty_driver, &serial_ops); - - if (tty_register_driver(viotty_driver)) { - printk(VIOCONS_KERN_WARN "couldn't register console driver\n"); - put_tty_driver(viotty_driver); - viotty_driver = NULL; - } - - unregister_console(&viocons_early); - register_console(&viocons); - - return 0; -} - -static int __init viocons_init(void) -{ - int i; - - if (!firmware_has_feature(FW_FEATURE_ISERIES)) - return -ENODEV; - - printk(VIOCONS_KERN_INFO "registering console\n"); - for (i = 0; i < VTTY_PORTS; i++) { - port_info[i].lp = HvLpIndexInvalid; - port_info[i].magic = VIOTTY_MAGIC; - } - HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437); - add_preferred_console("viocons", 0, NULL); - register_console(&viocons_early); - return 0; -} - -console_initcall(viocons_init); -module_init(viocons_init2); diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index e5da98d..7a70a40 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -886,10 +886,10 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id) state[i].cur_part = 0; for (j = 0; j < MAX_PARTITIONS; ++j) state[i].part_stat_rwi[j] = VIOT_IDLE; - device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), - "iseries!vt%d", i); - device_create(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), - "iseries!nvt%d", i); + device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i), + NULL, "iseries!vt%d", i); + device_create_drvdata(tape_class, NULL, MKDEV(VIOTAPE_MAJOR, i | 0x80), + NULL, "iseries!nvt%d", i); printk(VIOTAPE_KERN_INFO "tape iseries/vt%d is iSeries " "resource %10.10s type %4.4s, model %3.3s\n", i, viotape_unitinfo[i].rsrcname, diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index dc17fe3..d0f4eb6 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -46,6 +46,9 @@ static char *in, *inbuf; /* The operations for our console. */ static struct hv_ops virtio_cons; +/* The hvc device */ +static struct hvc_struct *hvc; + /*D:310 The put_chars() callback is pretty straightforward. * * We turn the characters into a scatter-gather list, add it to the output @@ -134,6 +137,27 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) return hvc_instantiate(0, 0, &virtio_cons); } +/* + * we support only one console, the hvc struct is a global var + * There is no need to do anything + */ +static int notifier_add_vio(struct hvc_struct *hp, int data) +{ + hp->irq_requested = 1; + return 0; +} + +static void notifier_del_vio(struct hvc_struct *hp, int data) +{ + hp->irq_requested = 0; +} + +static void hvc_handle_input(struct virtqueue *vq) +{ + if (hvc_poll(hvc)) + hvc_kick(); +} + /*D:370 Once we're further in boot, we get probed like any other virtio device. * At this stage we set up the output virtqueue. * @@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int)) static int __devinit virtcons_probe(struct virtio_device *dev) { int err; - struct hvc_struct *hvc; vdev = dev; @@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev) /* Find the input queue. */ /* FIXME: This is why we want to wean off hvc: we do nothing * when input comes in. */ - in_vq = vdev->config->find_vq(vdev, 0, NULL); + in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input); if (IS_ERR(in_vq)) { err = PTR_ERR(in_vq); goto free; @@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev) /* Start using the new console output. */ virtio_cons.get_chars = get_chars; virtio_cons.put_chars = put_chars; + virtio_cons.notifier_add = notifier_add_vio; + virtio_cons.notifier_del = notifier_del_vio; /* The first argument of hvc_alloc() is the virtual console number, so - * we use zero. The second argument is the interrupt number; we - * currently leave this as zero: it would be better not to use the - * hvc mechanism and fix this (FIXME!). + * we use zero. The second argument is the parameter for the + * notification mechanism (like irq number). We currently leave this + * as zero, virtqueues have implicit notifications. * * The third argument is a "struct hv_ops" containing the put_chars() - * and get_chars() pointers. The final argument is the output buffer - * size: we can do any size, so we put PAGE_SIZE here. */ + * get_chars(), notifier_add() and notifier_del() pointers. + * The final argument is the output buffer size: we can do any size, + * so we put PAGE_SIZE here. */ hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); if (IS_ERR(hvc)) { err = PTR_ERR(hvc); diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index f17ac04..1718b3c 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data); static irqreturn_t scc_stat_int(int irq, void *data); static irqreturn_t scc_spcond_int(int irq, void *data); static void scc_setsignals(struct scc_port *port, int dtr, int rts); -static void scc_break_ctl(struct tty_struct *tty, int break_state); +static int scc_break_ctl(struct tty_struct *tty, int break_state); static struct tty_driver *scc_driver; @@ -183,8 +183,8 @@ static void scc_init_portstructs(void) #ifdef NEW_WRITE_LOCKING port->gs.port_write_mutex = MUTEX; #endif - init_waitqueue_head(&port->gs.open_wait); - init_waitqueue_head(&port->gs.close_wait); + init_waitqueue_head(&port->gs.port.open_wait); + init_waitqueue_head(&port->gs.port.close_wait); } } @@ -422,7 +422,7 @@ static irqreturn_t scc_rx_int(int irq, void *data) { unsigned char ch; struct scc_port *port = data; - struct tty_struct *tty = port->gs.tty; + struct tty_struct *tty = port->gs.port.tty; SCC_ACCESS_INIT(port); ch = SCCread_NB(RX_DATA_REG); @@ -453,7 +453,7 @@ static irqreturn_t scc_rx_int(int irq, void *data) static irqreturn_t scc_spcond_int(int irq, void *data) { struct scc_port *port = data; - struct tty_struct *tty = port->gs.tty; + struct tty_struct *tty = port->gs.port.tty; unsigned char stat, ch, err; int int_pending_mask = port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX; @@ -500,7 +500,7 @@ static irqreturn_t scc_tx_int(int irq, void *data) struct scc_port *port = data; SCC_ACCESS_INIT(port); - if (!port->gs.tty) { + if (!port->gs.port.tty) { printk(KERN_WARNING "scc_tx_int with NULL tty!\n"); SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); @@ -512,8 +512,9 @@ static irqreturn_t scc_tx_int(int irq, void *data) SCCwrite(TX_DATA_REG, port->x_char); port->x_char = 0; } - else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || - port->gs.tty->hw_stopped) + else if ((port->gs.xmit_cnt <= 0) || + port->gs.port.tty->stopped || + port->gs.port.tty->hw_stopped) break; else { SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]); @@ -522,15 +523,15 @@ static irqreturn_t scc_tx_int(int irq, void *data) break; } } - if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped || - port->gs.tty->hw_stopped) { + if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped || + port->gs.port.tty->hw_stopped) { /* disable tx interrupts */ SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */ - port->gs.flags &= ~GS_TX_INTEN; + port->gs.port.flags &= ~GS_TX_INTEN; } - if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) - tty_wakeup(port->gs.tty); + if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) + tty_wakeup(port->gs.port.tty); SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET); return IRQ_HANDLED; @@ -550,14 +551,14 @@ static irqreturn_t scc_stat_int(int irq, void *data) if (changed & SR_DCD) { port->c_dcd = !!(sr & SR_DCD); - if (!(port->gs.flags & ASYNC_CHECK_CD)) + if (!(port->gs.port.flags & ASYNC_CHECK_CD)) ; /* Don't report DCD changes */ else if (port->c_dcd) { - wake_up_interruptible(&port->gs.open_wait); + wake_up_interruptible(&port->gs.port.open_wait); } else { - if (port->gs.tty) - tty_hangup (port->gs.tty); + if (port->gs.port.tty) + tty_hangup (port->gs.port.tty); } } SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET); @@ -578,7 +579,7 @@ static void scc_disable_tx_interrupts(void *ptr) local_irq_save(flags); SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0); - port->gs.flags &= ~GS_TX_INTEN; + port->gs.port.flags &= ~GS_TX_INTEN; local_irq_restore(flags); } @@ -636,8 +637,8 @@ static void scc_shutdown_port(void *ptr) { struct scc_port *port = ptr; - port->gs.flags &= ~ GS_ACTIVE; - if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) { + port->gs.port.flags &= ~ GS_ACTIVE; + if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) { scc_setsignals (port, 0, 0); } } @@ -652,14 +653,14 @@ static int scc_set_real_termios (void *ptr) struct scc_port *port = ptr; SCC_ACCESS_INIT(port); - if (!port->gs.tty || !port->gs.tty->termios) return 0; + if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0; channel = port->channel; if (channel == CHANNEL_A) return 0; /* Settings controlled by boot PROM */ - cflag = port->gs.tty->termios->c_cflag; + cflag = port->gs.port.tty->termios->c_cflag; baud = port->gs.baud; chsize = (cflag & CSIZE) >> 4; @@ -678,9 +679,9 @@ static int scc_set_real_termios (void *ptr) } if (cflag & CLOCAL) - port->gs.flags &= ~ASYNC_CHECK_CD; + port->gs.port.flags &= ~ASYNC_CHECK_CD; else - port->gs.flags |= ASYNC_CHECK_CD; + port->gs.port.flags |= ASYNC_CHECK_CD; #ifdef CONFIG_MVME147_SCC if (MACH_IS_MVME147) @@ -856,7 +857,7 @@ static int scc_open (struct tty_struct * tty, struct file * filp) { COMMAND_REG, CR_EXTSTAT_RESET }, }; #endif - if (!(port->gs.flags & ASYNC_INITIALIZED)) { + if (!(port->gs.port.flags & ASYNC_INITIALIZED)) { local_irq_save(flags); #if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC) if (MACH_IS_MVME147 || MACH_IS_MVME16x) { @@ -880,18 +881,18 @@ static int scc_open (struct tty_struct * tty, struct file * filp) } tty->driver_data = port; - port->gs.tty = tty; - port->gs.count++; + port->gs.port.tty = tty; + port->gs.port.count++; retval = gs_init_port(&port->gs); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } - port->gs.flags |= GS_ACTIVE; + port->gs.port.flags |= GS_ACTIVE; retval = gs_block_til_ready(port, filp); if (retval) { - port->gs.count--; + port->gs.port.count--; return retval; } @@ -942,7 +943,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file, } -static void scc_break_ctl(struct tty_struct *tty, int break_state) +static int scc_break_ctl(struct tty_struct *tty, int break_state) { struct scc_port *port = (struct scc_port *)tty->driver_data; unsigned long flags; @@ -952,6 +953,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state) SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, break_state ? TCR_SEND_BREAK : 0); local_irq_restore(flags); + return 0; } diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 935f1c2..1bc00c9 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -261,7 +261,7 @@ static void notify_update(struct vc_data *vc) #ifdef VT_BUF_VRAM_ONLY #define DO_UPDATE(vc) 0 #else -#define DO_UPDATE(vc) CON_IS_VISIBLE(vc) +#define DO_UPDATE(vc) (CON_IS_VISIBLE(vc) && !console_blanked) #endif static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed) @@ -916,7 +916,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) ws.ws_col = vc->vc_cols; ws.ws_ypixel = vc->vc_scan_lines; - mutex_lock(&vc->vc_tty->termios_mutex); spin_lock_irq(&vc->vc_tty->ctrl_lock); if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col)) pgrp = get_pid(vc->vc_tty->pgrp); @@ -926,7 +925,6 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines) put_pid(pgrp); } *cws = ws; - mutex_unlock(&vc->vc_tty->termios_mutex); } if (CON_IS_VISIBLE(vc)) @@ -2211,7 +2209,7 @@ rescan_last_byte: c = 0xfffd; tc = c; } else { /* no utf or alternate charset mode */ - tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c]; + tc = vc_translate(vc, c); } param.c = tc; @@ -2749,8 +2747,8 @@ static int con_open(struct tty_struct *tty, struct file *filp) tty->termios->c_iflag |= IUTF8; else tty->termios->c_iflag &= ~IUTF8; - release_console_sem(); vcs_make_sysfs(tty); + release_console_sem(); return ret; } } @@ -2775,8 +2773,8 @@ static void con_close(struct tty_struct *tty, struct file *filp) if (vc) vc->vc_tty = NULL; tty->driver_data = NULL; - release_console_sem(); vcs_remove_sysfs(tty); + release_console_sem(); mutex_unlock(&tty_mutex); /* * tty_mutex is released, but we still hold BKL, so there is @@ -3425,9 +3423,10 @@ int register_con_driver(const struct consw *csw, int first, int last) if (retval) goto err; - con_driver->dev = device_create(vtconsole_class, NULL, - MKDEV(0, con_driver->node), - "vtcon%i", con_driver->node); + con_driver->dev = device_create_drvdata(vtconsole_class, NULL, + MKDEV(0, con_driver->node), + NULL, "vtcon%i", + con_driver->node); if (IS_ERR(con_driver->dev)) { printk(KERN_WARNING "Unable to create device for %s; " @@ -3535,9 +3534,10 @@ static int __init vtconsole_class_init(void) struct con_driver *con = ®istered_con_driver[i]; if (con->con && !con->dev) { - con->dev = device_create(vtconsole_class, NULL, - MKDEV(0, con->node), - "vtcon%i", con->node); + con->dev = device_create_drvdata(vtconsole_class, NULL, + MKDEV(0, con->node), + NULL, "vtcon%i", + con->node); if (IS_ERR(con->dev)) { printk(KERN_WARNING "Unable to create " diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 1e1b81e..8bfee5f 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c @@ -87,7 +87,6 @@ #include <linux/mutex.h> #include <linux/smp_lock.h> #include <linux/sysctl.h> -#include <linux/version.h> #include <linux/fs.h> #include <linux/cdev.h> #include <linux/platform_device.h> @@ -658,8 +657,9 @@ static int __devinit hwicap_setup(struct device *dev, int id, dev_err(dev, "cdev_add() failed\n"); goto failed3; } - /* devfs_mk_cdev(devt, S_IFCHR|S_IRUGO|S_IWUGO, DRIVER_NAME); */ - device_create(icap_class, dev, devt, "%s%d", DRIVER_NAME, id); + + device_create_drvdata(icap_class, dev, devt, NULL, + "%s%d", DRIVER_NAME, id); return 0; /* success */ failed3: |