summaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Kconfig15
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/agp/Kconfig2
-rw-r--r--drivers/char/agp/amd64-agp.c39
-rw-r--r--drivers/char/agp/generic.c4
-rw-r--r--drivers/char/agp/intel-agp.c42
-rw-r--r--drivers/char/agp/intel-agp.h23
-rw-r--r--drivers/char/agp/intel-gtt.c66
-rw-r--r--drivers/char/amiserial.c56
-rw-r--r--drivers/char/apm-emulation.c12
-rw-r--r--drivers/char/applicom.c9
-rw-r--r--drivers/char/bfin-otp.c1
-rw-r--r--drivers/char/briq_panel.c1
-rw-r--r--drivers/char/bsr.c1
-rw-r--r--drivers/char/cs5535_gpio.c3
-rw-r--r--drivers/char/cyclades.c49
-rw-r--r--drivers/char/ds1302.c16
-rw-r--r--drivers/char/ds1620.c9
-rw-r--r--drivers/char/dsp56k.c28
-rw-r--r--drivers/char/dtlk.c9
-rw-r--r--drivers/char/generic_nvram.c7
-rw-r--r--drivers/char/genrtc.c14
-rw-r--r--drivers/char/hangcheck-timer.c2
-rw-r--r--drivers/char/hpet.c98
-rw-r--r--drivers/char/hvc_console.c2
-rw-r--r--drivers/char/hvsi.c2
-rw-r--r--drivers/char/hw_random/core.c1
-rw-r--r--drivers/char/hw_random/n2-drv.c2
-rw-r--r--drivers/char/i8k.c7
-rw-r--r--drivers/char/ip2/ip2main.c85
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c15
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c17
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c9
-rw-r--r--drivers/char/istallion.c1
-rw-r--r--drivers/char/lp.c16
-rw-r--r--drivers/char/mbcs.c8
-rw-r--r--drivers/char/mem.c6
-rw-r--r--drivers/char/misc.c1
-rw-r--r--drivers/char/mmtimer.c8
-rw-r--r--drivers/char/mspec.c9
-rw-r--r--drivers/char/mwave/mwavedd.c47
-rw-r--r--drivers/char/mxser.c109
-rw-r--r--drivers/char/nozomi.c37
-rw-r--r--drivers/char/nvram.c11
-rw-r--r--drivers/char/nwbutton.c1
-rw-r--r--drivers/char/nwflash.c12
-rw-r--r--drivers/char/pc8736x_gpio.c1
-rw-r--r--drivers/char/pcmcia/cm4000_cs.c42
-rw-r--r--drivers/char/pcmcia/cm4040_cs.c47
-rw-r--r--drivers/char/pcmcia/ipwireless/main.c117
-rw-r--r--drivers/char/pcmcia/ipwireless/main.h5
-rw-r--r--drivers/char/pcmcia/ipwireless/tty.h1
-rw-r--r--drivers/char/pcmcia/synclink_cs.c106
-rw-r--r--drivers/char/ppdev.c8
-rw-r--r--drivers/char/pty.c6
-rw-r--r--drivers/char/random.c2
-rw-r--r--drivers/char/raw.c245
-rw-r--r--drivers/char/rio/rio_linux.c8
-rw-r--r--drivers/char/rocket.c1
-rw-r--r--drivers/char/scx200_gpio.c1
-rw-r--r--drivers/char/snsc.c10
-rw-r--r--drivers/char/stallion.c1
-rw-r--r--drivers/char/sx.c1
-rw-r--r--drivers/char/synclink.c73
-rw-r--r--drivers/char/synclink_gt.c59
-rw-r--r--drivers/char/synclinkmp.c61
-rw-r--r--drivers/char/sysrq.c54
-rw-r--r--drivers/char/tb0219.c1
-rw-r--r--drivers/char/tlclk.c7
-rw-r--r--drivers/char/toshiba.c10
-rw-r--r--drivers/char/tpm/tpm.c22
-rw-r--r--drivers/char/tty_io.c163
-rw-r--r--drivers/char/ttyprintk.c225
-rw-r--r--drivers/char/uv_mmtimer.c1
-rw-r--r--drivers/char/vc_screen.c135
-rw-r--r--drivers/char/viotape.c12
-rw-r--r--drivers/char/virtio_console.c263
-rw-r--r--drivers/char/vt.c31
-rw-r--r--drivers/char/vt_ioctl.c16
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c8
80 files changed, 1719 insertions, 937 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3d44ec724c17..43d3395325c5 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -493,6 +493,21 @@ config LEGACY_PTY_COUNT
When not in use, each legacy PTY occupies 12 bytes on 32-bit
architectures and 24 bytes on 64-bit architectures.
+config TTY_PRINTK
+ bool "TTY driver to output user messages via printk"
+ depends on EMBEDDED
+ default n
+ ---help---
+ If you say Y here, the support for writing user messages (i.e.
+ console messages) via printk is available.
+
+ The feature is useful to inline user messages with kernel
+ messages.
+ In order to use this feature, you should output user messages
+ to /dev/ttyprintk or redirect console to this TTY.
+
+ If unsure, say N.
+
config BRIQ_PANEL
tristate 'Total Impact briQ front panel driver'
depends on PPC_CHRP
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index dc9641660605..3a9c01416839 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -12,6 +12,7 @@ obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o t
obj-y += tty_mutex.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
obj-$(CONFIG_UNIX98_PTYS) += pty.o
+obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
obj-y += misc.o
obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o
obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 4b66c69eaf57..5ddf67e76f8b 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -57,7 +57,7 @@ config AGP_AMD
config AGP_AMD64
tristate "AMD Opteron/Athlon64 on-CPU GART support"
- depends on AGP && X86 && K8_NB
+ depends on AGP && X86 && AMD_NB
help
This option gives you AGP support for the GLX component of
X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 70312da4c968..42396df55556 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -15,7 +15,7 @@
#include <linux/mmzone.h>
#include <asm/page.h> /* PAGE_SIZE */
#include <asm/e820.h>
-#include <asm/k8.h>
+#include <asm/amd_nb.h>
#include <asm/gart.h>
#include "agp.h"
@@ -124,7 +124,7 @@ static int amd64_fetch_size(void)
u32 temp;
struct aper_size_info_32 *values;
- dev = k8_northbridges[0];
+ dev = k8_northbridges.nb_misc[0];
if (dev==NULL)
return 0;
@@ -181,10 +181,14 @@ static int amd_8151_configure(void)
unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
int i;
+ if (!k8_northbridges.gart_supported)
+ return 0;
+
/* Configure AGP regs in each x86-64 host bridge. */
- for (i = 0; i < num_k8_northbridges; i++) {
+ for (i = 0; i < k8_northbridges.num; i++) {
agp_bridge->gart_bus_addr =
- amd64_configure(k8_northbridges[i], gatt_bus);
+ amd64_configure(k8_northbridges.nb_misc[i],
+ gatt_bus);
}
k8_flush_garts();
return 0;
@@ -195,11 +199,15 @@ static void amd64_cleanup(void)
{
u32 tmp;
int i;
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
+
+ if (!k8_northbridges.gart_supported)
+ return;
+
+ for (i = 0; i < k8_northbridges.num; i++) {
+ struct pci_dev *dev = k8_northbridges.nb_misc[i];
/* disable gart translation */
pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &tmp);
- tmp &= ~AMD64_GARTEN;
+ tmp &= ~GARTEN;
pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, tmp);
}
}
@@ -313,22 +321,25 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)<<order))
return -1;
- pci_write_config_dword(nb, AMD64_GARTAPERTURECTL, order << 1);
+ gart_set_size_and_enable(nb, order);
pci_write_config_dword(nb, AMD64_GARTAPERTUREBASE, aper >> 25);
return 0;
}
-static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
+static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr)
{
int i;
if (cache_k8_northbridges() < 0)
return -ENODEV;
+ if (!k8_northbridges.gart_supported)
+ return -ENODEV;
+
i = 0;
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
+ for (i = 0; i < k8_northbridges.num; i++) {
+ struct pci_dev *dev = k8_northbridges.nb_misc[i];
if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
dev_err(&dev->dev, "no usable aperture found\n");
#ifdef __x86_64__
@@ -405,7 +416,8 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
}
/* shadow x86-64 registers into ULi registers */
- pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
+ pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+ &httfea);
/* if x86-64 aperture base is beyond 4G, exit here */
if ((httfea & 0x7fff) >> (32 - 25)) {
@@ -472,7 +484,8 @@ static int nforce3_agp_init(struct pci_dev *pdev)
pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
/* shadow x86-64 registers into NVIDIA registers */
- pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase);
+ pci_read_config_dword (k8_northbridges.nb_misc[0], AMD64_GARTAPERTUREBASE,
+ &apbase);
/* if x86-64 aperture base is beyond 4G, exit here */
if ( (apbase & 0x7fff) >> (32 - 25) ) {
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index d2abf5143983..64255cef8a7d 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -984,7 +984,9 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
bridge->driver->cache_flush();
#ifdef CONFIG_X86
- set_memory_uc((unsigned long)table, 1 << page_order);
+ if (set_memory_uc((unsigned long)table, 1 << page_order))
+ printk(KERN_WARNING "Could not set GATT table memory to UC!");
+
bridge->gatt_table = (void *)table;
#else
bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index ddf5def1b0da..cd18493c9527 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -12,6 +12,7 @@
#include <asm/smp.h>
#include "agp.h"
#include "intel-agp.h"
+#include <linux/intel-gtt.h>
#include "intel-gtt.c"
@@ -805,6 +806,8 @@ static const struct intel_driver_description {
"G45/G43", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_B43_HB, PCI_DEVICE_ID_INTEL_B43_IG,
"B43", NULL, &intel_i965_driver },
+ { PCI_DEVICE_ID_INTEL_B43_1_HB, PCI_DEVICE_ID_INTEL_B43_1_IG,
+ "B43", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_G41_HB, PCI_DEVICE_ID_INTEL_G41_IG,
"G41", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG,
@@ -815,9 +818,19 @@ static const struct intel_driver_description {
"HD Graphics", NULL, &intel_i965_driver },
{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
"HD Graphics", NULL, &intel_i965_driver },
- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG,
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG,
+ "Sandybridge", NULL, &intel_gen6_driver },
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG,
+ "Sandybridge", NULL, &intel_gen6_driver },
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG,
+ "Sandybridge", NULL, &intel_gen6_driver },
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG,
+ "Sandybridge", NULL, &intel_gen6_driver },
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG,
"Sandybridge", NULL, &intel_gen6_driver },
- { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG,
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG,
+ "Sandybridge", NULL, &intel_gen6_driver },
+ { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG,
"Sandybridge", NULL, &intel_gen6_driver },
{ 0, 0, NULL, NULL, NULL }
};
@@ -825,7 +838,8 @@ static const struct intel_driver_description {
static int __devinit intel_gmch_probe(struct pci_dev *pdev,
struct agp_bridge_data *bridge)
{
- int i;
+ int i, mask;
+
bridge->driver = NULL;
for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
@@ -845,14 +859,19 @@ static int __devinit intel_gmch_probe(struct pci_dev *pdev,
dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
- if (bridge->driver->mask_memory == intel_i965_mask_memory) {
- if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(36)))
- dev_err(&intel_private.pcidev->dev,
- "set gfx device dma mask 36bit failed!\n");
- else
- pci_set_consistent_dma_mask(intel_private.pcidev,
- DMA_BIT_MASK(36));
- }
+ if (bridge->driver->mask_memory == intel_gen6_mask_memory)
+ mask = 40;
+ else if (bridge->driver->mask_memory == intel_i965_mask_memory)
+ mask = 36;
+ else
+ mask = 32;
+
+ if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
+ dev_err(&intel_private.pcidev->dev,
+ "set gfx device dma mask %d-bit failed!\n", mask);
+ else
+ pci_set_consistent_dma_mask(intel_private.pcidev,
+ DMA_BIT_MASK(mask));
return 1;
}
@@ -1036,6 +1055,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
+ ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB),
{ }
};
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index c05e3e518268..d09b1ab7e8ab 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -1,6 +1,8 @@
/*
* Common Intel AGPGART and GTT definitions.
*/
+#ifndef _INTEL_AGP_H
+#define _INTEL_AGP_H
/* Intel registers */
#define INTEL_APSIZE 0xb4
@@ -184,6 +186,8 @@
#define PCI_DEVICE_ID_INTEL_Q33_IG 0x29D2
#define PCI_DEVICE_ID_INTEL_B43_HB 0x2E40
#define PCI_DEVICE_ID_INTEL_B43_IG 0x2E42
+#define PCI_DEVICE_ID_INTEL_B43_1_HB 0x2E90
+#define PCI_DEVICE_ID_INTEL_B43_1_IG 0x2E92
#define PCI_DEVICE_ID_INTEL_GM45_HB 0x2A40
#define PCI_DEVICE_ID_INTEL_GM45_IG 0x2A42
#define PCI_DEVICE_ID_INTEL_EAGLELAKE_HB 0x2E00
@@ -200,10 +204,16 @@
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062
#define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a
#define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG 0x0102
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104
-#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG 0x0106
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */
+#define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A
/* cover 915 and 945 variants */
#define IS_I915 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_E7221_HB || \
@@ -230,7 +240,8 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_PINEVIEW_HB)
#define IS_SNB (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB || \
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB || \
+ agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB)
#define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_EAGLELAKE_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \
@@ -243,3 +254,5 @@
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB || \
agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB || \
IS_SNB)
+
+#endif
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index d22ffb811bf2..75e0a3497888 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -49,6 +49,26 @@ static struct gatt_mask intel_i810_masks[] =
.type = INTEL_AGP_CACHED_MEMORY}
};
+#define INTEL_AGP_UNCACHED_MEMORY 0
+#define INTEL_AGP_CACHED_MEMORY_LLC 1
+#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT 2
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC 3
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT 4
+
+static struct gatt_mask intel_gen6_masks[] =
+{
+ {.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED,
+ .type = INTEL_AGP_UNCACHED_MEMORY },
+ {.mask = I810_PTE_VALID | GEN6_PTE_LLC,
+ .type = INTEL_AGP_CACHED_MEMORY_LLC },
+ {.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT,
+ .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT },
+ {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC,
+ .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC },
+ {.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT,
+ .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT },
+};
+
static struct _intel_private {
struct pci_dev *pcidev; /* device one */
u8 __iomem *registers;
@@ -178,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
off_t pg_start, int mask_type)
{
int i, j;
- u32 cache_bits = 0;
-
- if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
- {
- cache_bits = GEN6_PTE_LLC_MLC;
- }
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
writel(agp_bridge->driver->mask_memory(agp_bridge,
@@ -317,6 +330,23 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
return 0;
}
+static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge,
+ int type)
+{
+ unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT;
+ unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT;
+
+ if (type_mask == AGP_USER_UNCACHED_MEMORY)
+ return INTEL_AGP_UNCACHED_MEMORY;
+ else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
+ return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT :
+ INTEL_AGP_CACHED_MEMORY_LLC_MLC;
+ else /* set 'normal'/'cached' to LLC by default */
+ return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT :
+ INTEL_AGP_CACHED_MEMORY_LLC;
+}
+
+
static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
int type)
{
@@ -588,8 +618,7 @@ static void intel_i830_init_gtt_entries(void)
gtt_entries = 0;
break;
}
- } else if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
- agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB) {
+ } else if (IS_SNB) {
/*
* SandyBridge has new memory control reg at 0x50.w
*/
@@ -1068,11 +1097,11 @@ static void intel_i9xx_setup_flush(void)
intel_i915_setup_chipset_flush();
}
- if (intel_private.ifp_resource.start) {
+ 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)
- dev_info(&intel_private.pcidev->dev, "can't ioremap flush page - no chipset flushing");
- }
+ if (!intel_private.i9xx_flush_page)
+ dev_err(&intel_private.pcidev->dev,
+ "can't ioremap flush page - no chipset flushing\n");
}
static int intel_i9xx_configure(void)
@@ -1163,7 +1192,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
- if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+ if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
mask_type != INTEL_AGP_CACHED_MEMORY)
goto out_err;
@@ -1333,8 +1362,8 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
dma_addr_t addr, int type)
{
- /* Shift high bits down */
- addr |= (addr >> 28) & 0xff;
+ /* gen6 has bit11-4 for physical addr bit39-32 */
+ addr |= (addr >> 28) & 0xff0;
/* Type checking must be done elsewhere */
return addr | bridge->driver->masks[type].mask;
@@ -1359,6 +1388,7 @@ static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
break;
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB:
case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB:
+ case PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB:
*gtt_offset = MB(2);
pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl);
@@ -1563,7 +1593,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
.fetch_size = intel_i9xx_fetch_size,
.cleanup = intel_i915_cleanup,
.mask_memory = intel_gen6_mask_memory,
- .masks = intel_i810_masks,
+ .masks = intel_gen6_masks,
.agp_enable = intel_i810_agp_enable,
.cache_flush = global_cache_flush,
.create_gatt_table = intel_i965_create_gatt_table,
@@ -1576,7 +1606,7 @@ static const struct agp_bridge_driver intel_gen6_driver = {
.agp_alloc_pages = agp_generic_alloc_pages,
.agp_destroy_page = agp_generic_destroy_page,
.agp_destroy_pages = agp_generic_destroy_pages,
- .agp_type_to_mask_type = intel_i830_type_to_mask_type,
+ .agp_type_to_mask_type = intel_gen6_type_to_mask_type,
.chipset_flush = intel_i915_chipset_flush,
#ifdef USE_PCI_DMA_API
.agp_map_page = intel_agp_map_page,
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a11c8c9ca3d4..b0a70461a12c 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
return 0;
}
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+static int rs_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ struct async_struct *info = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cnow = info->state->icount;
+ local_irq_restore(flags);
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
static int rs_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
}
/* NOTREACHED */
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- local_irq_save(flags);
- cnow = info->state->icount;
- local_irq_restore(flags);
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
-
- if (copy_to_user(argp, &icount, sizeof(icount)))
- return -EFAULT;
- return 0;
case TIOCSERGWILD:
case TIOCSERSWILD:
/* "setserial -W" is called in Debian boot */
@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
.wait_until_sent = rs_wait_until_sent,
.tiocmget = rs_tiocmget,
.tiocmset = rs_tiocmset,
+ .get_icount = rs_get_icount,
.proc_fops = &rs_proc_fops,
};
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c
index 033e1505fca9..3022801669b1 100644
--- a/drivers/char/apm-emulation.c
+++ b/drivers/char/apm-emulation.c
@@ -13,7 +13,7 @@
#include <linux/module.h>
#include <linux/poll.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/miscdevice.h>
@@ -126,6 +126,7 @@ struct apm_user {
/*
* Local variables
*/
+static DEFINE_MUTEX(apm_mutex);
static atomic_t suspend_acks_pending = ATOMIC_INIT(0);
static atomic_t userspace_notification_inhibit = ATOMIC_INIT(0);
static int apm_disabled;
@@ -274,7 +275,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
if (!as->suser || !as->writer)
return -EPERM;
- lock_kernel();
+ mutex_lock(&apm_mutex);
switch (cmd) {
case APM_IOC_SUSPEND:
mutex_lock(&state_lock);
@@ -335,7 +336,7 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg)
mutex_unlock(&state_lock);
break;
}
- unlock_kernel();
+ mutex_unlock(&apm_mutex);
return err;
}
@@ -370,7 +371,7 @@ static int apm_open(struct inode * inode, struct file * filp)
{
struct apm_user *as;
- lock_kernel();
+ mutex_lock(&apm_mutex);
as = kzalloc(sizeof(*as), GFP_KERNEL);
if (as) {
/*
@@ -390,7 +391,7 @@ static int apm_open(struct inode * inode, struct file * filp)
filp->private_data = as;
}
- unlock_kernel();
+ mutex_unlock(&apm_mutex);
return as ? 0 : -ENOMEM;
}
@@ -402,6 +403,7 @@ static const struct file_operations apm_bios_fops = {
.unlocked_ioctl = apm_ioctl,
.open = apm_open,
.release = apm_release,
+ .llseek = noop_llseek,
};
static struct miscdevice apm_device = {
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index f4ae0e0fb631..e7ba774beda6 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -26,7 +26,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <linux/wait.h>
@@ -60,6 +60,7 @@
#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
#endif
+static DEFINE_MUTEX(ac_mutex);
static char *applicom_pci_devnames[] = {
"PCI board",
"PCI2000IBS / PCI2000CAN",
@@ -707,7 +708,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (IS_ERR(adgl))
return PTR_ERR(adgl);
- lock_kernel();
+ mutex_lock(&ac_mutex);
IndexCard = adgl->num_card-1;
if(cmd != 6 && ((IndexCard >= MAX_BOARD) || !apbs[IndexCard].RamIO)) {
@@ -717,7 +718,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
warncount--;
}
kfree(adgl);
- unlock_kernel();
+ mutex_unlock(&ac_mutex);
return -EINVAL;
}
@@ -835,7 +836,7 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
Dummy = readb(apbs[IndexCard].RamIO + VERS);
kfree(adgl);
- unlock_kernel();
+ mutex_unlock(&ac_mutex);
return 0;
}
diff --git a/drivers/char/bfin-otp.c b/drivers/char/bfin-otp.c
index 836d4f0a876f..44660f1c4849 100644
--- a/drivers/char/bfin-otp.c
+++ b/drivers/char/bfin-otp.c
@@ -222,6 +222,7 @@ static const struct file_operations bfin_otp_fops = {
.unlocked_ioctl = bfin_otp_ioctl,
.read = bfin_otp_read,
.write = bfin_otp_write,
+ .llseek = default_llseek,
};
static struct miscdevice bfin_otp_misc_device = {
diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c
index d5fa113afe37..f6718f05dad4 100644
--- a/drivers/char/briq_panel.c
+++ b/drivers/char/briq_panel.c
@@ -186,6 +186,7 @@ static const struct file_operations briq_panel_fops = {
.write = briq_panel_write,
.open = briq_panel_open,
.release = briq_panel_release,
+ .llseek = noop_llseek,
};
static struct miscdevice briq_panel_miscdev = {
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 91917133ae0a..a4a6c2f044b5 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -155,6 +155,7 @@ static const struct file_operations bsr_fops = {
.owner = THIS_MODULE,
.mmap = bsr_mmap,
.open = bsr_open,
+ .llseek = noop_llseek,
};
static void bsr_cleanup_devs(void)
diff --git a/drivers/char/cs5535_gpio.c b/drivers/char/cs5535_gpio.c
index 4d830dc482ef..0cf1e5fad9ab 100644
--- a/drivers/char/cs5535_gpio.c
+++ b/drivers/char/cs5535_gpio.c
@@ -169,7 +169,8 @@ static const struct file_operations cs5535_gpio_fops = {
.owner = THIS_MODULE,
.write = cs5535_gpio_write,
.read = cs5535_gpio_read,
- .open = cs5535_gpio_open
+ .open = cs5535_gpio_open,
+ .llseek = no_llseek,
};
static int __init cs5535_gpio_init(void)
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 27aad9422332..4f152c28f40e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2790,29 +2790,6 @@ cy_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: {
- struct serial_icounter_struct sic = { };
-
- spin_lock_irqsave(&info->card->card_lock, flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->card->card_lock, flags);
-
- sic.cts = cnow.cts;
- sic.dsr = cnow.dsr;
- sic.rng = cnow.rng;
- sic.dcd = cnow.dcd;
- sic.rx = cnow.rx;
- sic.tx = cnow.tx;
- sic.frame = cnow.frame;
- sic.overrun = cnow.overrun;
- sic.parity = cnow.parity;
- sic.brk = cnow.brk;
- sic.buf_overrun = cnow.buf_overrun;
-
- if (copy_to_user(argp, &sic, sizeof(sic)))
- ret_val = -EFAULT;
- break;
- }
default:
ret_val = -ENOIOCTLCMD;
}
@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
return ret_val;
} /* cy_ioctl */
+static int cy_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *sic)
+{
+ struct cyclades_port *info = tty->driver_data;
+ struct cyclades_icount cnow; /* Used to snapshot */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->card->card_lock, flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->card->card_lock, flags);
+
+ sic->cts = cnow.cts;
+ sic->dsr = cnow.dsr;
+ sic->rng = cnow.rng;
+ sic->dcd = cnow.dcd;
+ sic->rx = cnow.rx;
+ sic->tx = cnow.tx;
+ sic->frame = cnow.frame;
+ sic->overrun = cnow.overrun;
+ sic->parity = cnow.parity;
+ sic->brk = cnow.brk;
+ sic->buf_overrun = cnow.buf_overrun;
+ return 0;
+}
+
/*
* This routine allows the tty driver to be notified when
* device's termios settings have changed. Note that a
@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
.wait_until_sent = cy_wait_until_sent,
.tiocmget = cy_tiocmget,
.tiocmset = cy_tiocmset,
+ .get_icount = cy_get_icount,
.proc_fops = &cyclades_proc_fops,
};
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c
index 170693c93c73..ed8303f9890c 100644
--- a/drivers/char/ds1302.c
+++ b/drivers/char/ds1302.c
@@ -20,7 +20,7 @@
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <linux/bcd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/io.h>
@@ -32,6 +32,7 @@
#define RTC_MAJOR_NR 121 /* local major, change later */
+static DEFINE_MUTEX(rtc_mutex);
static const char ds1302_name[] = "ds1302";
/* Send 8 bits. */
@@ -164,9 +165,9 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct rtc_time rtc_tm;
memset(&rtc_tm, 0, sizeof (struct rtc_time));
- lock_kernel();
+ mutex_lock(&rtc_mutex);
get_rtc_time(&rtc_tm);
- unlock_kernel();
+ mutex_unlock(&rtc_mutex);
if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
return -EFAULT;
return 0;
@@ -218,7 +219,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
mon = bin2bcd(mon);
yrs = bin2bcd(yrs);
- lock_kernel();
+ mutex_lock(&rtc_mutex);
local_irq_save(flags);
CMOS_WRITE(yrs, RTC_YEAR);
CMOS_WRITE(mon, RTC_MONTH);
@@ -227,7 +228,7 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
CMOS_WRITE(min, RTC_MINUTES);
CMOS_WRITE(sec, RTC_SECONDS);
local_irq_restore(flags);
- unlock_kernel();
+ mutex_unlock(&rtc_mutex);
/* Notice that at this point, the RTC is updated but
* the kernel is still running with the old time.
@@ -247,10 +248,10 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if(copy_from_user(&tcs_val, (int*)arg, sizeof(int)))
return -EFAULT;
- lock_kernel();
+ mutex_lock(&rtc_mutex);
tcs_val = RTC_TCR_PATTERN | (tcs_val & 0x0F);
ds1302_writereg(RTC_TRICKLECHARGER, tcs_val);
- unlock_kernel();
+ mutex_unlock(&rtc_mutex);
return 0;
}
default:
@@ -288,6 +289,7 @@ get_rtc_status(char *buf)
static const struct file_operations rtc_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = rtc_ioctl,
+ .llseek = noop_llseek,
};
/* 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 dbee8688f75c..aab9605f0b43 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -8,7 +8,7 @@
#include <linux/proc_fs.h>
#include <linux/capability.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
@@ -34,6 +34,7 @@
#define CFG_CPU 2
#define CFG_1SHOT 1
+static DEFINE_MUTEX(ds1620_mutex);
static const char *fan_state[] = { "off", "on", "on (hardwired)" };
/*
@@ -210,7 +211,6 @@ static void ds1620_read_state(struct therm *therm)
static int ds1620_open(struct inode *inode, struct file *file)
{
- cycle_kernel_lock();
return nonseekable_open(inode, file);
}
@@ -321,9 +321,9 @@ ds1620_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int ret;
- lock_kernel();
+ mutex_lock(&ds1620_mutex);
ret = ds1620_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ds1620_mutex);
return ret;
}
@@ -357,6 +357,7 @@ static const struct file_operations ds1620_fops = {
.open = ds1620_open,
.read = ds1620_read,
.unlocked_ioctl = ds1620_unlocked_ioctl,
+ .llseek = no_llseek,
};
static struct miscdevice ds1620_miscdev = {
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 8a1b28a10ef0..052797b32bd3 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -32,7 +32,7 @@
#include <linux/mm.h>
#include <linux/init.h>
#include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
#include <linux/uaccess.h> /* For put_user and get_user */
@@ -94,6 +94,7 @@
} \
}
+static DEFINE_MUTEX(dsp56k_mutex);
static struct dsp56k_device {
unsigned long in_use;
long maxio, timeout;
@@ -330,9 +331,9 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
if (len > DSP56K_MAX_BINARY_LENGTH) {
return -EINVAL;
}
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
r = dsp56k_upload(bin, len);
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
if (r < 0) {
return r;
}
@@ -342,16 +343,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
case DSP56K_SET_TX_WSIZE:
if (arg > 4 || arg < 1)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
dsp56k.tx_wsize = (int) arg;
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
break;
case DSP56K_SET_RX_WSIZE:
if (arg > 4 || arg < 1)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
dsp56k.rx_wsize = (int) arg;
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
break;
case DSP56K_HOST_FLAGS:
{
@@ -363,7 +364,7 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
if(get_user(out, &hf->out) < 0)
return -EFAULT;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
if ((dir & 0x1) && (out & 0x1))
dsp56k_host_interface.icr |= DSP56K_ICR_HF0;
else if (dir & 0x1)
@@ -378,16 +379,16 @@ static long dsp56k_ioctl(struct file *file, unsigned int cmd,
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();
+ mutex_unlock(&dsp56k_mutex);
return put_user(status, &hf->status);
}
case DSP56K_HOST_CMD:
if (arg > 31 || arg < 0)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
dsp56k_host_interface.cvr = (u_char)((arg & DSP56K_CVR_HV_MASK) |
DSP56K_CVR_HC);
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
break;
default:
return -EINVAL;
@@ -427,7 +428,7 @@ static int dsp56k_open(struct inode *inode, struct file *file)
int dev = iminor(inode) & 0x0f;
int ret = 0;
- lock_kernel();
+ mutex_lock(&dsp56k_mutex);
switch(dev)
{
case DSP56K_DEV_56001:
@@ -454,7 +455,7 @@ static int dsp56k_open(struct inode *inode, struct file *file)
ret = -ENODEV;
}
out:
- unlock_kernel();
+ mutex_unlock(&dsp56k_mutex);
return ret;
}
@@ -482,6 +483,7 @@ static const struct file_operations dsp56k_fops = {
.unlocked_ioctl = dsp56k_ioctl,
.open = dsp56k_open,
.release = dsp56k_release,
+ .llseek = noop_llseek,
};
diff --git a/drivers/char/dtlk.c b/drivers/char/dtlk.c
index e3859d4eaead..85156dd0caee 100644
--- a/drivers/char/dtlk.c
+++ b/drivers/char/dtlk.c
@@ -57,7 +57,7 @@
#include <linux/ioport.h> /* for request_region */
#include <linux/delay.h> /* for loops_per_jiffy */
#include <linux/sched.h>
-#include <linux/smp_lock.h> /* cycle_kernel_lock() */
+#include <linux/mutex.h>
#include <asm/io.h> /* for inb_p, outb_p, inb, outb, etc. */
#include <asm/uaccess.h> /* for get_user, etc. */
#include <linux/wait.h> /* for wait_queue */
@@ -73,6 +73,7 @@
#define TRACE_RET ((void) 0)
#endif /* TRACING */
+static DEFINE_MUTEX(dtlk_mutex);
static void dtlk_timer_tick(unsigned long data);
static int dtlk_major;
@@ -105,6 +106,7 @@ static const struct file_operations dtlk_fops =
.unlocked_ioctl = dtlk_ioctl,
.open = dtlk_open,
.release = dtlk_release,
+ .llseek = no_llseek,
};
/* local prototypes */
@@ -275,9 +277,9 @@ static long dtlk_ioctl(struct file *file,
switch (cmd) {
case DTLK_INTERROGATE:
- lock_kernel();
+ mutex_lock(&dtlk_mutex);
sp = dtlk_interrogate();
- unlock_kernel();
+ mutex_unlock(&dtlk_mutex);
if (copy_to_user(argp, sp, sizeof(struct dtlk_settings)))
return -EINVAL;
return 0;
@@ -296,7 +298,6 @@ static int dtlk_open(struct inode *inode, struct file *file)
{
TRACE_TEXT("(dtlk_open");
- cycle_kernel_lock();
nonseekable_open(inode, file);
switch (iminor(inode)) {
case DTLK_MINOR:
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c
index 82b5a88a82d7..0e941b57482e 100644
--- a/drivers/char/generic_nvram.c
+++ b/drivers/char/generic_nvram.c
@@ -19,7 +19,7 @@
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/nvram.h>
#ifdef CONFIG_PPC_PMAC
@@ -28,6 +28,7 @@
#define NVRAM_SIZE 8192
+static DEFINE_MUTEX(nvram_mutex);
static ssize_t nvram_len;
static loff_t nvram_llseek(struct file *file, loff_t offset, int origin)
@@ -120,9 +121,9 @@ static long nvram_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned l
{
int ret;
- lock_kernel();
+ mutex_lock(&nvram_mutex);
ret = nvram_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&nvram_mutex);
return ret;
}
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index b6c2cc167c11..f773a9dd14f3 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -52,7 +52,7 @@
#include <linux/init.h>
#include <linux/poll.h>
#include <linux/proc_fs.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/workqueue.h>
#include <asm/uaccess.h>
@@ -66,6 +66,7 @@
* ioctls.
*/
+static DEFINE_MUTEX(gen_rtc_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait);
/*
@@ -337,9 +338,9 @@ static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
{
int ret;
- lock_kernel();
+ mutex_lock(&gen_rtc_mutex);
ret = gen_rtc_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&gen_rtc_mutex);
return ret;
}
@@ -352,16 +353,16 @@ static long gen_rtc_unlocked_ioctl(struct file *file, unsigned int cmd,
static int gen_rtc_open(struct inode *inode, struct file *file)
{
- lock_kernel();
+ mutex_lock(&gen_rtc_mutex);
if (gen_rtc_status & RTC_IS_OPEN) {
- unlock_kernel();
+ mutex_unlock(&gen_rtc_mutex);
return -EBUSY;
}
gen_rtc_status |= RTC_IS_OPEN;
gen_rtc_irq_data = 0;
irq_active = 0;
- unlock_kernel();
+ mutex_unlock(&gen_rtc_mutex);
return 0;
}
@@ -497,6 +498,7 @@ static const struct file_operations gen_rtc_fops = {
.unlocked_ioctl = gen_rtc_unlocked_ioctl,
.open = gen_rtc_open,
.release = gen_rtc_release,
+ .llseek = noop_llseek,
};
static struct miscdevice rtc_gen_dev =
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index e0249722d25f..f953c96efc86 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -159,7 +159,7 @@ static void hangcheck_fire(unsigned long data)
if (hangcheck_dump_tasks) {
printk(KERN_CRIT "Hangcheck: Task state:\n");
#ifdef CONFIG_MAGIC_SYSRQ
- handle_sysrq('t', NULL);
+ handle_sysrq('t');
#endif /* CONFIG_MAGIC_SYSRQ */
}
if (hangcheck_reboot) {
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index a0a1829d3198..a4eee324eb1e 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -30,6 +30,7 @@
#include <linux/bcd.h>
#include <linux/seq_file.h>
#include <linux/bitops.h>
+#include <linux/compat.h>
#include <linux/clocksource.h>
#include <linux/slab.h>
@@ -67,6 +68,7 @@
#define read_counter(MC) readl(MC)
#endif
+static DEFINE_MUTEX(hpet_mutex); /* replaces BKL */
static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
/* This clocksource driver currently only works on ia64 */
@@ -250,7 +252,7 @@ static int hpet_open(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE)
return -EINVAL;
- lock_kernel();
+ mutex_lock(&hpet_mutex);
spin_lock_irq(&hpet_lock);
for (devp = NULL, hpetp = hpets; hpetp && !devp; hpetp = hpetp->hp_next)
@@ -264,7 +266,7 @@ static int hpet_open(struct inode *inode, struct file *file)
if (!devp) {
spin_unlock_irq(&hpet_lock);
- unlock_kernel();
+ mutex_unlock(&hpet_mutex);
return -EBUSY;
}
@@ -272,7 +274,7 @@ static int hpet_open(struct inode *inode, struct file *file)
devp->hd_irqdata = 0;
devp->hd_flags |= HPET_OPEN;
spin_unlock_irq(&hpet_lock);
- unlock_kernel();
+ mutex_unlock(&hpet_mutex);
hpet_timer_set_irq(devp);
@@ -429,22 +431,6 @@ static int hpet_release(struct inode *inode, struct file *file)
return 0;
}
-static int hpet_ioctl_common(struct hpet_dev *, int, unsigned long, int);
-
-static long hpet_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct hpet_dev *devp;
- int ret;
-
- devp = file->private_data;
- lock_kernel();
- ret = hpet_ioctl_common(devp, cmd, arg, 0);
- unlock_kernel();
-
- return ret;
-}
-
static int hpet_ioctl_ieon(struct hpet_dev *devp)
{
struct hpet_timer __iomem *timer;
@@ -553,7 +539,8 @@ static inline unsigned long hpet_time_div(struct hpets *hpets,
}
static int
-hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
+hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
+ struct hpet_info *info)
{
struct hpet_timer __iomem *timer;
struct hpet __iomem *hpet;
@@ -594,23 +581,15 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
break;
case HPET_INFO:
{
- struct hpet_info info;
-
if (devp->hd_ireqfreq)
- info.hi_ireqfreq =
+ info->hi_ireqfreq =
hpet_time_div(hpetp, devp->hd_ireqfreq);
else
- info.hi_ireqfreq = 0;
- info.hi_flags =
+ info->hi_ireqfreq = 0;
+ info->hi_flags =
readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
- info.hi_hpet = hpetp->hp_which;
- info.hi_timer = devp - hpetp->hp_dev;
- if (kernel)
- memcpy((void *)arg, &info, sizeof(info));
- else
- if (copy_to_user((void __user *)arg, &info,
- sizeof(info)))
- err = -EFAULT;
+ info->hi_hpet = hpetp->hp_which;
+ info->hi_timer = devp - hpetp->hp_dev;
break;
}
case HPET_EPI:
@@ -636,7 +615,7 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
devp->hd_flags &= ~HPET_PERIODIC;
break;
case HPET_IRQFREQ:
- if (!kernel && (arg > hpet_max_freq) &&
+ if ((arg > hpet_max_freq) &&
!capable(CAP_SYS_RESOURCE)) {
err = -EACCES;
break;
@@ -653,12 +632,63 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel)
return err;
}
+static long
+hpet_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct hpet_info info;
+ int err;
+
+ mutex_lock(&hpet_mutex);
+ err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+ mutex_unlock(&hpet_mutex);
+
+ if ((cmd == HPET_INFO) && !err &&
+ (copy_to_user((void __user *)arg, &info, sizeof(info))))
+ err = -EFAULT;
+
+ return err;
+}
+
+#ifdef CONFIG_COMPAT
+struct compat_hpet_info {
+ compat_ulong_t hi_ireqfreq; /* Hz */
+ compat_ulong_t hi_flags; /* information */
+ unsigned short hi_hpet;
+ unsigned short hi_timer;
+};
+
+static long
+hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct hpet_info info;
+ int err;
+
+ mutex_lock(&hpet_mutex);
+ err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
+ mutex_unlock(&hpet_mutex);
+
+ if ((cmd == HPET_INFO) && !err) {
+ struct compat_hpet_info __user *u = compat_ptr(arg);
+ if (put_user(info.hi_ireqfreq, &u->hi_ireqfreq) ||
+ put_user(info.hi_flags, &u->hi_flags) ||
+ put_user(info.hi_hpet, &u->hi_hpet) ||
+ put_user(info.hi_timer, &u->hi_timer))
+ err = -EFAULT;
+ }
+
+ return err;
+}
+#endif
+
static const struct file_operations hpet_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = hpet_read,
.poll = hpet_poll,
.unlocked_ioctl = hpet_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = hpet_compat_ioctl,
+#endif
.open = hpet_open,
.release = hpet_release,
.fasync = hpet_fasync,
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index fa27d1676ee5..3afd62e856eb 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -651,7 +651,7 @@ int hvc_poll(struct hvc_struct *hp)
if (sysrq_pressed)
continue;
} else if (sysrq_pressed) {
- handle_sysrq(buf[i], tty);
+ handle_sysrq(buf[i]);
sysrq_pressed = 0;
continue;
}
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index 1f4b6de65a2d..a2bc885ce60a 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -403,7 +403,7 @@ static void hvsi_insert_chars(struct hvsi_struct *hp, const char *buf, int len)
hp->sysrq = 1;
continue;
} else if (hp->sysrq) {
- handle_sysrq(c, hp->tty);
+ handle_sysrq(c);
hp->sysrq = 0;
continue;
}
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 3d9c61e5acbf..788da05190cc 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -170,6 +170,7 @@ static const struct file_operations rng_chrdev_ops = {
.owner = THIS_MODULE,
.open = rng_dev_open,
.read = rng_dev_read,
+ .llseek = noop_llseek,
};
static struct miscdevice rng_miscdev = {
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index 1acdb2509511..a3f5e381e746 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -387,7 +387,7 @@ static int n2rng_init_control(struct n2rng *np)
static int n2rng_data_read(struct hwrng *rng, u32 *data)
{
- struct n2rng *np = rng->priv;
+ struct n2rng *np = (struct n2rng *) rng->priv;
unsigned long ra = __pa(&np->test_data);
int len;
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index 4cd8b227c11f..3bc0eef88717 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -23,7 +23,7 @@
#include <linux/seq_file.h>
#include <linux/dmi.h>
#include <linux/capability.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -56,6 +56,7 @@
#define I8K_TEMPERATURE_BUG 1
+static DEFINE_MUTEX(i8k_mutex);
static char bios_version[4];
MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
@@ -399,9 +400,9 @@ static long i8k_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&i8k_mutex);
ret = i8k_ioctl_unlocked(fp, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&i8k_mutex);
return ret;
}
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 07f3ea38b582..fcd02baa7d65 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -98,7 +98,7 @@
#include <linux/major.h>
#include <linux/wait.h>
#include <linux/device.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/firmware.h>
#include <linux/platform_device.h>
@@ -138,6 +138,7 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
+static DEFINE_MUTEX(ip2_mutex);
static const struct file_operations ip2mem_proc_fops;
static const struct file_operations ip2_proc_fops;
@@ -183,6 +184,8 @@ static void ip2_hangup(PTTY);
static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
+static int ip2_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount);
static void set_irq(int, int);
static void ip2_interrupt_bh(struct work_struct *work);
@@ -236,6 +239,7 @@ static const struct file_operations ip2_ipl = {
.write = ip2_ipl_write,
.unlocked_ioctl = ip2_ipl_ioctl,
.open = ip2_ipl_open,
+ .llseek = noop_llseek,
};
static unsigned long irq_counter;
@@ -454,6 +458,7 @@ static const struct tty_operations ip2_ops = {
.hangup = ip2_hangup,
.tiocmget = ip2_tiocmget,
.tiocmset = ip2_tiocmset,
+ .get_icount = ip2_get_icount,
.proc_fops = &ip2_proc_fops,
};
@@ -1650,7 +1655,7 @@ ip2_close( PTTY tty, struct file *pFile )
/* disable DSS reporting */
i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
- if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
+ if (tty->termios->c_cflag & HUPCL) {
i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
@@ -2128,7 +2133,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
i2ChanStrPtr pCh = DevTable[tty->index];
i2eBordStrPtr pB;
struct async_icount cprev, cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser;
int rc = 0;
unsigned long flags;
void __user *argp = (void __user *)arg;
@@ -2297,34 +2301,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
break;
/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for RI where
- * only 0->1 is counted. The controller is quite capable of counting
- * both, but this done to preserve compatibility with the standard
- * serial driver.
- */
- case TIOCGICOUNT:
- ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
-
- write_lock_irqsave(&pB->read_fifo_spinlock, flags);
- cnow = pCh->icount;
- write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
- p_cuser = argp;
- rc = put_user(cnow.cts, &p_cuser->cts);
- rc = put_user(cnow.dsr, &p_cuser->dsr);
- rc = put_user(cnow.rng, &p_cuser->rng);
- rc = put_user(cnow.dcd, &p_cuser->dcd);
- rc = put_user(cnow.rx, &p_cuser->rx);
- rc = put_user(cnow.tx, &p_cuser->tx);
- rc = put_user(cnow.frame, &p_cuser->frame);
- rc = put_user(cnow.overrun, &p_cuser->overrun);
- rc = put_user(cnow.parity, &p_cuser->parity);
- rc = put_user(cnow.brk, &p_cuser->brk);
- rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
- break;
-
- /*
* The rest are not supported by this driver. By returning -ENOIOCTLCMD they
* will be passed to the line discipline for it to handle.
*/
@@ -2348,6 +2324,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
return rc;
}
+static int ip2_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ i2ChanStrPtr pCh = DevTable[tty->index];
+ i2eBordStrPtr pB;
+ struct async_icount cnow; /* kernel counter temp */
+ unsigned long flags;
+
+ if ( pCh == NULL )
+ return -ENODEV;
+
+ pB = pCh->pMyBord;
+
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for RI where
+ * only 0->1 is counted. The controller is quite capable of counting
+ * both, but this done to preserve compatibility with the standard
+ * serial driver.
+ */
+
+ write_lock_irqsave(&pB->read_fifo_spinlock, flags);
+ cnow = pCh->icount;
+ write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+ return 0;
+}
+
/******************************************************************************/
/* Function: GetSerialInfo() */
/* Parameters: Pointer to channel structure */
@@ -2897,7 +2913,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
#endif
- lock_kernel();
+ mutex_lock(&ip2_mutex);
switch ( iplminor ) {
case 0: // IPL device
@@ -2930,6 +2946,8 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
if ( pCh )
{
rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
+ if (rc)
+ rc = -EFAULT;
} else {
rc = -ENODEV;
}
@@ -2959,7 +2977,7 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
rc = -ENODEV;
break;
}
- unlock_kernel();
+ mutex_unlock(&ip2_mutex);
return rc;
}
@@ -2980,7 +2998,6 @@ ip2_ipl_open( struct inode *pInode, struct file *pFile )
#ifdef IP2DEBUG_IPL
printk (KERN_DEBUG "IP2IPL: open\n" );
#endif
- cycle_kernel_lock();
return 0;
}
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index d8ec92a38980..1fc8876af1f5 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -44,7 +44,6 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/compat.h>
-#include <linux/smp_lock.h>
struct ipmi_file_private
{
@@ -59,6 +58,7 @@ struct ipmi_file_private
unsigned int default_retry_time_ms;
};
+static DEFINE_MUTEX(ipmi_mutex);
static void file_receive_handler(struct ipmi_recv_msg *msg,
void *handler_data)
{
@@ -102,9 +102,9 @@ static int ipmi_fasync(int fd, struct file *file, int on)
struct ipmi_file_private *priv = file->private_data;
int result;
- lock_kernel(); /* could race against open() otherwise */
+ mutex_lock(&ipmi_mutex); /* could race against open() otherwise */
result = fasync_helper(fd, file, on, &priv->fasync_queue);
- unlock_kernel();
+ mutex_unlock(&ipmi_mutex);
return (result);
}
@@ -125,7 +125,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
if (!priv)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&ipmi_mutex);
priv->file = file;
rv = ipmi_create_user(if_num,
@@ -150,7 +150,7 @@ static int ipmi_open(struct inode *inode, struct file *file)
priv->default_retry_time_ms = 0;
out:
- unlock_kernel();
+ mutex_unlock(&ipmi_mutex);
return rv;
}
@@ -639,9 +639,9 @@ static long ipmi_unlocked_ioctl(struct file *file,
{
int ret;
- lock_kernel();
+ mutex_lock(&ipmi_mutex);
ret = ipmi_ioctl(file, cmd, data);
- unlock_kernel();
+ mutex_unlock(&ipmi_mutex);
return ret;
}
@@ -850,6 +850,7 @@ static const struct file_operations ipmi_fops = {
.release = ipmi_release,
.fasync = ipmi_fasync,
.poll = ipmi_poll,
+ .llseek = noop_llseek,
};
#define DEVICE_NAME "ipmidev"
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 3822b4f49c84..7bd7c45b53ef 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -305,6 +305,9 @@ static int num_force_kipmid;
#ifdef CONFIG_PCI
static int pci_registered;
#endif
+#ifdef CONFIG_ACPI
+static int pnp_registered;
+#endif
#ifdef CONFIG_PPC_OF
static int of_registered;
#endif
@@ -2126,7 +2129,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
{
struct acpi_device *acpi_dev;
struct smi_info *info;
- struct resource *res;
+ struct resource *res, *res_second;
acpi_handle handle;
acpi_status status;
unsigned long long tmp;
@@ -2182,13 +2185,13 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
info->io.addr_data = res->start;
info->io.regspacing = DEFAULT_REGSPACING;
- res = pnp_get_resource(dev,
+ res_second = pnp_get_resource(dev,
(info->io.addr_type == IPMI_IO_ADDR_SPACE) ?
IORESOURCE_IO : IORESOURCE_MEM,
1);
- if (res) {
- if (res->start > info->io.addr_data)
- info->io.regspacing = res->start - info->io.addr_data;
+ if (res_second) {
+ if (res_second->start > info->io.addr_data)
+ info->io.regspacing = res_second->start - info->io.addr_data;
}
info->io.regsize = DEFAULT_REGSPACING;
info->io.regshift = 0;
@@ -3359,6 +3362,7 @@ static __devinit int init_ipmi_si(void)
#ifdef CONFIG_ACPI
pnp_register_driver(&ipmi_pnp_driver);
+ pnp_registered = 1;
#endif
#ifdef CONFIG_DMI
@@ -3526,7 +3530,8 @@ static __exit void cleanup_ipmi_si(void)
pci_unregister_driver(&ipmi_pci_driver);
#endif
#ifdef CONFIG_ACPI
- pnp_unregister_driver(&ipmi_pnp_driver);
+ if (pnp_registered)
+ pnp_unregister_driver(&ipmi_pnp_driver);
#endif
#ifdef CONFIG_PPC_OF
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 654d566ca57c..f4d334f2536e 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -35,7 +35,7 @@
#include <linux/moduleparam.h>
#include <linux/ipmi.h>
#include <linux/ipmi_smi.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/watchdog.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
@@ -149,6 +149,7 @@
#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
#endif
+static DEFINE_MUTEX(ipmi_watchdog_mutex);
static int nowayout = WATCHDOG_NOWAYOUT;
static ipmi_user_t watchdog_user;
@@ -748,9 +749,9 @@ static long ipmi_unlocked_ioctl(struct file *file,
{
int ret;
- lock_kernel();
+ mutex_lock(&ipmi_watchdog_mutex);
ret = ipmi_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&ipmi_watchdog_mutex);
return ret;
}
@@ -844,7 +845,6 @@ static int ipmi_open(struct inode *ino, struct file *filep)
if (test_and_set_bit(0, &ipmi_wdog_open))
return -EBUSY;
- cycle_kernel_lock();
/*
* Don't start the timer now, let it start on the
@@ -909,6 +909,7 @@ static const struct file_operations ipmi_wdog_fops = {
.open = ipmi_open,
.release = ipmi_close,
.fasync = ipmi_fasync,
+ .llseek = no_llseek,
};
static struct miscdevice ipmi_wdog_miscdev = {
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index be28391adb79..667abd23ad6a 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -704,6 +704,7 @@ static const struct file_operations stli_fsiomem = {
.read = stli_memread,
.write = stli_memwrite,
.unlocked_ioctl = stli_memioctl,
+ .llseek = default_llseek,
};
/*****************************************************************************/
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 938a3a273886..97c3edb95ae7 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -126,7 +126,7 @@
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/compat.h>
#include <linux/parport.h>
@@ -140,6 +140,7 @@
/* if you have more than 8 printers, remember to increase LP_NO */
#define LP_NO 8
+static DEFINE_MUTEX(lp_mutex);
static struct lp_struct lp_table[LP_NO];
static unsigned int lp_count = 0;
@@ -493,7 +494,7 @@ static int lp_open(struct inode * inode, struct file * file)
unsigned int minor = iminor(inode);
int ret = 0;
- lock_kernel();
+ mutex_lock(&lp_mutex);
if (minor >= LP_NO) {
ret = -ENXIO;
goto out;
@@ -554,7 +555,7 @@ static int lp_open(struct inode * inode, struct file * file)
lp_release_parport (&lp_table[minor]);
lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
out:
- unlock_kernel();
+ mutex_unlock(&lp_mutex);
return ret;
}
@@ -680,7 +681,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd,
int ret;
minor = iminor(file->f_path.dentry->d_inode);
- lock_kernel();
+ mutex_lock(&lp_mutex);
switch (cmd) {
case LPSETTIMEOUT:
if (copy_from_user(&par_timeout, (void __user *)arg,
@@ -694,7 +695,7 @@ static long lp_ioctl(struct file *file, unsigned int cmd,
ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
break;
}
- unlock_kernel();
+ mutex_unlock(&lp_mutex);
return ret;
}
@@ -709,7 +710,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
int ret;
minor = iminor(file->f_path.dentry->d_inode);
- lock_kernel();
+ mutex_lock(&lp_mutex);
switch (cmd) {
case LPSETTIMEOUT:
tc = compat_ptr(arg);
@@ -730,7 +731,7 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
break;
}
- unlock_kernel();
+ mutex_unlock(&lp_mutex);
return ret;
}
@@ -748,6 +749,7 @@ static const struct file_operations lp_fops = {
#ifdef CONFIG_PARPORT_1284
.read = lp_read,
#endif
+ .llseek = noop_llseek,
};
/* --- support for console on the line printer ----------------- */
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index 83bef4efe376..1aeaaba680d2 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -25,7 +25,6 @@
#include <linux/mm.h>
#include <linux/uio.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/uaccess.h>
@@ -42,6 +41,7 @@
#else
#define DBG(fmt...)
#endif
+static DEFINE_MUTEX(mbcs_mutex);
static int mbcs_major;
static LIST_HEAD(soft_list);
@@ -385,19 +385,19 @@ static int mbcs_open(struct inode *ip, struct file *fp)
struct mbcs_soft *soft;
int minor;
- lock_kernel();
+ mutex_lock(&mbcs_mutex);
minor = iminor(ip);
/* Nothing protects access to this list... */
list_for_each_entry(soft, &soft_list, list) {
if (soft->nasid == minor) {
fp->private_data = soft->cxdev;
- unlock_kernel();
+ mutex_unlock(&mbcs_mutex);
return 0;
}
}
- unlock_kernel();
+ mutex_unlock(&mbcs_mutex);
return -ENODEV;
}
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index a398ecdbd758..e985b1c2730e 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -788,10 +788,11 @@ static const struct file_operations zero_fops = {
/*
* capabilities for /dev/zero
* - permits private mappings, "copies" are taken of the source of zeros
+ * - no writeback happens
*/
static struct backing_dev_info zero_bdi = {
.name = "char/mem",
- .capabilities = BDI_CAP_MAP_COPY,
+ .capabilities = BDI_CAP_MAP_COPY | BDI_CAP_NO_ACCT_AND_WRITEBACK,
};
static const struct file_operations full_fops = {
@@ -804,6 +805,7 @@ static const struct file_operations full_fops = {
static const struct file_operations oldmem_fops = {
.read = read_oldmem,
.open = open_oldmem,
+ .llseek = default_llseek,
};
#endif
@@ -830,6 +832,7 @@ static ssize_t kmsg_write(struct file *file, const char __user *buf,
static const struct file_operations kmsg_fops = {
.write = kmsg_write,
+ .llseek = noop_llseek,
};
static const struct memdev {
@@ -881,6 +884,7 @@ static int memory_open(struct inode *inode, struct file *filp)
static const struct file_operations memory_fops = {
.open = memory_open,
+ .llseek = noop_llseek,
};
static char *mem_devnode(struct device *dev, mode_t *mode)
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index abdafd488980..778273c93242 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -162,6 +162,7 @@ static struct class *misc_class;
static const struct file_operations misc_fops = {
.owner = THIS_MODULE,
.open = misc_open,
+ .llseek = noop_llseek,
};
/**
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
index ea7c99fa978f..c070b53984e4 100644
--- a/drivers/char/mmtimer.c
+++ b/drivers/char/mmtimer.c
@@ -32,7 +32,7 @@
#include <linux/interrupt.h>
#include <linux/time.h>
#include <linux/math64.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
@@ -59,6 +59,7 @@ extern unsigned long sn_rtc_cycles_per_second;
#define rtc_time() (*RTC_COUNTER_ADDR)
+static DEFINE_MUTEX(mmtimer_mutex);
static long mmtimer_ioctl(struct file *file, unsigned int cmd,
unsigned long arg);
static int mmtimer_mmap(struct file *file, struct vm_area_struct *vma);
@@ -72,6 +73,7 @@ static const struct file_operations mmtimer_fops = {
.owner = THIS_MODULE,
.mmap = mmtimer_mmap,
.unlocked_ioctl = mmtimer_ioctl,
+ .llseek = noop_llseek,
};
/*
@@ -371,7 +373,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
{
int ret = 0;
- lock_kernel();
+ mutex_lock(&mmtimer_mutex);
switch (cmd) {
case MMTIMER_GETOFFSET: /* offset of the counter */
@@ -414,7 +416,7 @@ static long mmtimer_ioctl(struct file *file, unsigned int cmd,
ret = -ENOTTY;
break;
}
- unlock_kernel();
+ mutex_unlock(&mmtimer_mutex);
return ret;
}
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index ecb89d798e35..966a95bc974b 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -316,7 +316,8 @@ uncached_mmap(struct file *file, struct vm_area_struct *vma)
static const struct file_operations fetchop_fops = {
.owner = THIS_MODULE,
- .mmap = fetchop_mmap
+ .mmap = fetchop_mmap,
+ .llseek = noop_llseek,
};
static struct miscdevice fetchop_miscdev = {
@@ -327,7 +328,8 @@ static struct miscdevice fetchop_miscdev = {
static const struct file_operations cached_fops = {
.owner = THIS_MODULE,
- .mmap = cached_mmap
+ .mmap = cached_mmap,
+ .llseek = noop_llseek,
};
static struct miscdevice cached_miscdev = {
@@ -338,7 +340,8 @@ static struct miscdevice cached_miscdev = {
static const struct file_operations uncached_fops = {
.owner = THIS_MODULE,
- .mmap = uncached_mmap
+ .mmap = uncached_mmap,
+ .llseek = noop_llseek,
};
static struct miscdevice uncached_miscdev = {
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index a4ec50c95072..1d82d5838f0c 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -56,7 +56,7 @@
#include <linux/serial.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/serial_8250.h>
#include "smapi.h"
@@ -73,6 +73,7 @@ MODULE_LICENSE("GPL");
* checks are made against other devices (ie. superio) for conflicts.
* We'll depend on users using the tpctl utility to do that for now
*/
+static DEFINE_MUTEX(mwave_mutex);
int mwave_debug = 0;
int mwave_3780i_irq = 0;
int mwave_3780i_io = 0;
@@ -101,7 +102,6 @@ static int mwave_open(struct inode *inode, struct file *file)
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_open, exit return retval %x\n", retval);
- cycle_kernel_lock();
return retval;
}
@@ -136,9 +136,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" calling tp3780I_ResetDSP\n");
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ResetDSP(&pDrvData->rBDData);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RESET"
" retval %x from tp3780I_ResetDSP\n",
@@ -149,9 +149,9 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
PRINTK_1(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" calling tp3780I_StartDSP\n");
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_StartDSP(&pDrvData->rBDData);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_RUN"
" retval %x from tp3780I_StartDSP\n",
@@ -165,10 +165,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
"mwavedd::mwave_ioctl,"
" IOCTL_MW_DSP_ABILITIES calling"
" tp3780I_QueryAbilities\n");
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_QueryAbilities(&pDrvData->rBDData,
&rAbilities);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl, IOCTL_MW_DSP_ABILITIES"
" retval %x from tp3780I_QueryAbilities\n",
@@ -199,13 +199,13 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
"mwavedd::mwave_ioctl IOCTL_MW_READ_DATA,"
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength, ioarg, pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd,
pusBuffer,
rReadData.ulDataLength,
rReadData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -223,12 +223,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" size %lx, ioarg %lx pusBuffer %p\n",
rReadData.ulDataLength / 2, ioarg,
pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rReadData.ulDataLength / 2,
rReadData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -246,12 +246,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspDStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -269,12 +269,12 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" size %lx, ioarg %lx pusBuffer %p\n",
rWriteData.ulDataLength, ioarg,
pusBuffer);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
retval = tp3780I_ReadWriteDspIStore(&pDrvData->rBDData,
iocmd, pusBuffer,
rWriteData.ulDataLength,
rWriteData.usDspAddress);
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -295,10 +295,10 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
pDrvData->IPCs[ipcnum].bIsHere = FALSE;
pDrvData->IPCs[ipcnum].bIsEnabled = TRUE;
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
PRINTK_2(TRACE_MWAVE,
"mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
@@ -323,7 +323,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum,
pDrvData->IPCs[ipcnum].usIntCount);
- lock_kernel();
+ mutex_lock(&mwave_mutex);
if (pDrvData->IPCs[ipcnum].bIsEnabled == TRUE) {
DECLARE_WAITQUEUE(wait, current);
@@ -364,7 +364,7 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
" processing\n",
ipcnum);
}
- unlock_kernel();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -383,14 +383,14 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
ipcnum);
return -EINVAL;
}
- lock_kernel();
+ mutex_lock(&mwave_mutex);
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();
+ mutex_unlock(&mwave_mutex);
}
break;
@@ -479,7 +479,8 @@ static const struct file_operations mwave_fops = {
.write = mwave_write,
.unlocked_ioctl = mwave_ioctl,
.open = mwave_open,
- .release = mwave_close
+ .release = mwave_close,
+ .llseek = default_llseek,
};
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 3fc89da856ae..463df27494bd 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0;
}
- if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT &&
+ if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
test_bit(TTY_IO_ERROR, &tty->flags))
return -EIO;
@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return wait_event_interruptible(info->port.delta_msr_wait,
mxser_cflags_changed(info, arg, &cnow));
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT: {
- struct serial_icounter_struct icnt = { 0 };
- spin_lock_irqsave(&info->slock, flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->slock, flags);
-
- 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:
@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
return 0;
}
+ /*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+
+static int mxser_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+
+{
+ struct mxser_port *info = tty->driver_data;
+ struct async_icount cnow;
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->slock, flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->slock, flags);
+
+ icount->frame = cnow.frame;
+ icount->brk = cnow.brk;
+ icount->overrun = cnow.overrun;
+ icount->buf_overrun = cnow.buf_overrun;
+ icount->parity = cnow.parity;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ return 0;
+}
+
static void mxser_stoprx(struct tty_struct *tty)
{
struct mxser_port *info = tty->driver_data;
@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
.wait_until_sent = mxser_wait_until_sent,
.tiocmget = mxser_tiocmget,
.tiocmset = mxser_tiocmset,
+ .get_icount = mxser_get_icount,
};
struct tty_port_operations mxser_port_ops = {
@@ -2339,20 +2347,11 @@ struct tty_port_operations mxser_port_ops = {
* The MOXA Smartio/Industio serial driver boot-time initialization code!
*/
-static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev,
- unsigned int irq)
+static void mxser_release_ISA_res(struct mxser_board *brd)
{
- if (irq)
- free_irq(brd->irq, brd);
- if (pdev != NULL) { /* PCI */
-#ifdef CONFIG_PCI
- pci_release_region(pdev, 2);
- pci_release_region(pdev, 3);
-#endif
- } else {
- release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
- release_region(brd->vector, 1);
- }
+ free_irq(brd->irq, brd);
+ release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
+ release_region(brd->vector, 1);
}
static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2397,13 +2396,11 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
brd);
- if (retval) {
+ if (retval)
printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
"conflict with another device.\n",
brd->info->name, brd->irq);
- /* We hold resources, we need to release them. */
- mxser_release_res(brd, pdev, 0);
- }
+
return retval;
}
@@ -2555,7 +2552,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
ioaddress = pci_resource_start(pdev, 2);
retval = pci_request_region(pdev, 2, "mxser(IO)");
if (retval)
- goto err;
+ goto err_dis;
brd->info = &mxser_cards[ent->driver_data];
for (i = 0; i < brd->info->nports; i++)
@@ -2565,7 +2562,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
ioaddress = pci_resource_start(pdev, 3);
retval = pci_request_region(pdev, 3, "mxser(vector)");
if (retval)
- goto err_relio;
+ goto err_zero;
brd->vector = ioaddress;
/* irq */
@@ -2608,7 +2605,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
/* mxser_initbrd will hook ISR. */
retval = mxser_initbrd(brd, pdev);
if (retval)
- goto err_null;
+ goto err_rel3;
for (i = 0; i < brd->info->nports; i++)
tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
@@ -2616,10 +2613,13 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, brd);
return 0;
-err_relio:
- pci_release_region(pdev, 2);
-err_null:
+err_rel3:
+ pci_release_region(pdev, 3);
+err_zero:
brd->info = NULL;
+ pci_release_region(pdev, 2);
+err_dis:
+ pci_disable_device(pdev);
err:
return retval;
#else
@@ -2629,14 +2629,19 @@ err:
static void __devexit mxser_remove(struct pci_dev *pdev)
{
+#ifdef CONFIG_PCI
struct mxser_board *brd = pci_get_drvdata(pdev);
unsigned int i;
for (i = 0; i < brd->info->nports; i++)
tty_unregister_device(mxvar_sdriver, brd->idx + i);
- mxser_release_res(brd, pdev, 1);
+ free_irq(pdev->irq, brd);
+ pci_release_region(pdev, 2);
+ pci_release_region(pdev, 3);
+ pci_disable_device(pdev);
brd->info = NULL;
+#endif
}
static struct pci_driver mxser_driver = {
@@ -2741,7 +2746,7 @@ 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);
+ mxser_release_ISA_res(&mxser_boards[i]);
}
module_init(mxser_module_init);
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 817169cbb245..dd3f9b1f11b4 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
return ret;
}
-static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp)
+static int ntty_tiocgicount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
{
+ struct port *port = tty->driver_data;
const struct async_icount cnow = port->tty_icount;
- struct serial_icounter_struct icount;
-
- icount.cts = cnow.cts;
- icount.dsr = cnow.dsr;
- icount.rng = cnow.rng;
- icount.dcd = cnow.dcd;
- icount.rx = cnow.rx;
- icount.tx = cnow.tx;
- icount.frame = cnow.frame;
- icount.overrun = cnow.overrun;
- icount.parity = cnow.parity;
- icount.brk = cnow.brk;
- icount.buf_overrun = cnow.buf_overrun;
-
- return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+ return 0;
}
static int ntty_ioctl(struct tty_struct *tty, struct file *file,
@@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file,
rval = wait_event_interruptible(port->tty_wait,
ntty_cflags_changed(port, arg, &cprev));
break;
- } case TIOCGICOUNT:
- rval = ntty_ioctl_tiocgicount(port, argp);
- break;
+ }
default:
DBG1("ERR: 0x%08X, %d", cmd, cmd);
break;
@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
.chars_in_buffer = ntty_chars_in_buffer,
.tiocmget = ntty_tiocmget,
.tiocmset = ntty_tiocmset,
+ .get_icount = ntty_tiocgicount,
.install = ntty_install,
.cleanup = ntty_cleanup,
};
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 66d2917b003f..166f1e7aaa7e 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -109,10 +109,11 @@
#include <linux/spinlock.h>
#include <linux/io.h>
#include <linux/uaccess.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/system.h>
+static DEFINE_MUTEX(nvram_mutex);
static DEFINE_SPINLOCK(nvram_state_lock);
static int nvram_open_cnt; /* #times opened */
static int nvram_open_mode; /* special open modes */
@@ -308,7 +309,7 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- lock_kernel();
+ mutex_lock(&nvram_mutex);
spin_lock_irq(&rtc_lock);
for (i = 0; i < NVRAM_BYTES; ++i)
@@ -316,7 +317,7 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
__nvram_set_checksum();
spin_unlock_irq(&rtc_lock);
- unlock_kernel();
+ mutex_unlock(&nvram_mutex);
return 0;
case NVRAM_SETCKS:
@@ -325,11 +326,11 @@ static long nvram_ioctl(struct file *file, unsigned int cmd,
if (!capable(CAP_SYS_ADMIN))
return -EACCES;
- lock_kernel();
+ mutex_lock(&nvram_mutex);
spin_lock_irq(&rtc_lock);
__nvram_set_checksum();
spin_unlock_irq(&rtc_lock);
- unlock_kernel();
+ mutex_unlock(&nvram_mutex);
return 0;
default:
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 2604246501e4..8994ce32e6c7 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -182,6 +182,7 @@ static int button_read (struct file *filp, char __user *buffer,
static const struct file_operations button_fops = {
.owner = THIS_MODULE,
.read = button_read,
+ .llseek = noop_llseek,
};
/*
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c
index 043a1c7b86be..a12f52400dbc 100644
--- a/drivers/char/nwflash.c
+++ b/drivers/char/nwflash.c
@@ -25,7 +25,6 @@
#include <linux/spinlock.h>
#include <linux/rwsem.h>
#include <linux/init.h>
-#include <linux/smp_lock.h>
#include <linux/mutex.h>
#include <linux/jiffies.h>
@@ -41,6 +40,7 @@
#define NWFLASH_VERSION "6.4"
+static DEFINE_MUTEX(flash_mutex);
static void kick_open(void);
static int get_flash_id(void);
static int erase_block(int nBlock);
@@ -96,7 +96,7 @@ static int get_flash_id(void)
static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
- lock_kernel();
+ mutex_lock(&flash_mutex);
switch (cmd) {
case CMD_WRITE_DISABLE:
gbWriteBase64Enable = 0;
@@ -114,10 +114,10 @@ static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
default:
gbWriteBase64Enable = 0;
gbWriteEnable = 0;
- unlock_kernel();
+ mutex_unlock(&flash_mutex);
return -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&flash_mutex);
return 0;
}
@@ -282,7 +282,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
{
loff_t ret;
- lock_kernel();
+ mutex_lock(&flash_mutex);
if (flashdebug)
printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
(unsigned int) offset, orig);
@@ -317,7 +317,7 @@ static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
default:
ret = -EINVAL;
}
- unlock_kernel();
+ mutex_unlock(&flash_mutex);
return ret;
}
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c
index 8ecbcc174c15..b304ec052501 100644
--- a/drivers/char/pc8736x_gpio.c
+++ b/drivers/char/pc8736x_gpio.c
@@ -234,6 +234,7 @@ static const struct file_operations pc8736x_gpio_fileops = {
.open = pc8736x_gpio_open,
.write = nsc_gpio_write,
.read = nsc_gpio_read,
+ .llseek = no_llseek,
};
static void __init pc8736x_init_shadow(void)
diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c
index ec73d9f6d9ed..6835c23e9a51 100644
--- a/drivers/char/pcmcia/cm4000_cs.c
+++ b/drivers/char/pcmcia/cm4000_cs.c
@@ -30,11 +30,10 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/bitrev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#include <linux/io.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -55,7 +54,7 @@
__func__ , ## args); \
} while (0)
-static char *version = "cm4000_cs.c v2.4.0gm6 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cmm_mutex);
#define T_1SEC (HZ)
#define T_10MSEC msecs_to_jiffies(10)
@@ -1418,7 +1417,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
iminor(inode), ioctl_names[_IOC_NR(cmd)]);
#endif
- lock_kernel();
+ mutex_lock(&cmm_mutex);
rc = -ENODEV;
link = dev_table[iminor(inode)];
if (!pcmcia_dev_present(link)) {
@@ -1626,7 +1625,7 @@ static long cmm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
rc = -ENOTTY;
}
out:
- unlock_kernel();
+ mutex_unlock(&cmm_mutex);
return rc;
}
@@ -1640,7 +1639,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
if (minor >= CM4000_MAX_DEV)
return -ENODEV;
- lock_kernel();
+ mutex_lock(&cmm_mutex);
link = dev_table[minor];
if (link == NULL || !pcmcia_dev_present(link)) {
ret = -ENODEV;
@@ -1685,7 +1684,7 @@ static int cmm_open(struct inode *inode, struct file *filp)
DEBUGP(2, dev, "<- cmm_open\n");
ret = nonseekable_open(inode, filp);
out:
- unlock_kernel();
+ mutex_unlock(&cmm_mutex);
return ret;
}
@@ -1742,20 +1741,8 @@ static void cmm_cm4000_release(struct pcmcia_device * link)
/*==== Interface to PCMCIA Layer =======================================*/
-static int cm4000_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int cm4000_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- if (!cfg->io.nwin)
- return -ENODEV;
-
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
- p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
- p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
return pcmcia_request_io(p_dev);
}
@@ -1763,13 +1750,13 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
{
struct cm4000_dev *dev;
+ link->config_flags |= CONF_AUTO_SET_IO;
+
/* read the config-tuples */
if (pcmcia_loop_config(link, cm4000_config_check, NULL))
goto cs_release;
- link->conf.IntType = 00000002;
-
- if (pcmcia_request_configuration(link, &link->conf))
+ if (pcmcia_enable_device(link))
goto cs_release;
dev = link->priv;
@@ -1829,7 +1816,6 @@ static int cm4000_probe(struct pcmcia_device *link)
dev->p_dev = link;
link->priv = dev;
- link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
init_waitqueue_head(&dev->devq);
@@ -1880,6 +1866,7 @@ static const struct file_operations cm4000_fops = {
.unlocked_ioctl = cmm_ioctl,
.open = cmm_open,
.release= cmm_close,
+ .llseek = no_llseek,
};
static struct pcmcia_device_id cm4000_ids[] = {
@@ -1891,9 +1878,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4000_ids);
static struct pcmcia_driver cm4000_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "cm4000_cs",
- },
+ .name = "cm4000_cs",
.probe = cm4000_probe,
.remove = cm4000_detach,
.suspend = cm4000_suspend,
@@ -1905,8 +1890,6 @@ static int __init cmm_init(void)
{
int rc;
- printk(KERN_INFO "%s\n", version);
-
cmm_class = class_create(THIS_MODULE, "cardman_4000");
if (IS_ERR(cmm_class))
return PTR_ERR(cmm_class);
@@ -1931,7 +1914,6 @@ static int __init cmm_init(void)
static void __exit cmm_exit(void)
{
- printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&cm4000_driver);
unregister_chrdev(major, DEVICE_NAME);
class_destroy(cmm_class);
diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c
index 815cde1d0570..5d8d59e865f4 100644
--- a/drivers/char/pcmcia/cm4040_cs.c
+++ b/drivers/char/pcmcia/cm4040_cs.c
@@ -24,12 +24,11 @@
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/wait.h>
#include <asm/uaccess.h>
#include <asm/io.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ciscode.h>
@@ -49,8 +48,7 @@
__func__ , ## args); \
} while (0)
-static char *version =
-"OMNIKEY CardMan 4040 v1.1.0gm5 - All bugs added by Harald Welte";
+static DEFINE_MUTEX(cm4040_mutex);
#define CCID_DRIVER_BULK_DEFAULT_TIMEOUT (150*HZ)
#define CCID_DRIVER_ASYNC_POWERUP_TIMEOUT (35*HZ)
@@ -444,7 +442,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
if (minor >= CM_MAX_DEV)
return -ENODEV;
- lock_kernel();
+ mutex_lock(&cm4040_mutex);
link = dev_table[minor];
if (link == NULL || !pcmcia_dev_present(link)) {
ret = -ENODEV;
@@ -473,7 +471,7 @@ static int cm4040_open(struct inode *inode, struct file *filp)
DEBUGP(2, dev, "<- cm4040_open (successfully)\n");
ret = nonseekable_open(inode, filp);
out:
- unlock_kernel();
+ mutex_unlock(&cm4040_mutex);
return ret;
}
@@ -516,26 +514,9 @@ static void cm4040_reader_release(struct pcmcia_device *link)
return;
}
-static int cm4040_config_check(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int cm4040_config_check(struct pcmcia_device *p_dev, void *priv_data)
{
- int rc;
- if (!cfg->io.nwin)
- return -ENODEV;
-
- /* Get the IOaddr */
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
- p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
- p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
- rc = pcmcia_request_io(p_dev);
-
- dev_printk(KERN_INFO, &p_dev->dev,
- "pcmcia_request_io returned 0x%x\n", rc);
- return rc;
+ return pcmcia_request_io(p_dev);
}
@@ -544,15 +525,15 @@ static int reader_config(struct pcmcia_device *link, int devno)
struct reader_dev *dev;
int fail_rc;
+ link->config_flags |= CONF_AUTO_SET_IO;
+
if (pcmcia_loop_config(link, cm4040_config_check, NULL))
goto cs_release;
- link->conf.IntType = 00000002;
-
- fail_rc = pcmcia_request_configuration(link, &link->conf);
+ fail_rc = pcmcia_enable_device(link);
if (fail_rc != 0) {
dev_printk(KERN_INFO, &link->dev,
- "pcmcia_request_configuration failed 0x%x\n",
+ "pcmcia_enable_device failed 0x%x\n",
fail_rc);
goto cs_release;
}
@@ -599,7 +580,6 @@ static int reader_probe(struct pcmcia_device *link)
link->priv = dev;
dev->p_dev = link;
- link->conf.IntType = INT_MEMORY_AND_IO;
dev_table[i] = link;
init_waitqueue_head(&dev->devq);
@@ -650,6 +630,7 @@ static const struct file_operations reader_fops = {
.open = cm4040_open,
.release = cm4040_close,
.poll = cm4040_poll,
+ .llseek = no_llseek,
};
static struct pcmcia_device_id cm4040_ids[] = {
@@ -662,9 +643,7 @@ MODULE_DEVICE_TABLE(pcmcia, cm4040_ids);
static struct pcmcia_driver reader_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "cm4040_cs",
- },
+ .name = "cm4040_cs",
.probe = reader_probe,
.remove = reader_detach,
.id_table = cm4040_ids,
@@ -674,7 +653,6 @@ static int __init cm4040_init(void)
{
int rc;
- printk(KERN_INFO "%s\n", version);
cmx_class = class_create(THIS_MODULE, "cardman_4040");
if (IS_ERR(cmx_class))
return PTR_ERR(cmx_class);
@@ -699,7 +677,6 @@ static int __init cm4040_init(void)
static void __exit cm4040_exit(void)
{
- printk(KERN_INFO MODULE_NAME ": unloading\n");
pcmcia_unregister_driver(&reader_driver);
unregister_chrdev(major, DEVICE_NAME);
class_destroy(cmx_class);
diff --git a/drivers/char/pcmcia/ipwireless/main.c b/drivers/char/pcmcia/ipwireless/main.c
index 67bdb05798b1..94b8eb4d691d 100644
--- a/drivers/char/pcmcia/ipwireless/main.c
+++ b/drivers/char/pcmcia/ipwireless/main.c
@@ -32,7 +32,6 @@
#include <pcmcia/device_id.h>
#include <pcmcia/ss.h>
#include <pcmcia/ds.h>
-#include <pcmcia/cs.h>
static struct pcmcia_device_id ipw_ids[] = {
PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
@@ -76,23 +75,18 @@ static void signalled_reboot_callback(void *callback_data)
schedule_work(&ipw->work_reboot);
}
-static int ipwireless_probe(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
{
struct ipw_dev *ipw = priv_data;
struct resource *io_resource;
int ret;
+ p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
/* 0x40 causes it to generate level mode interrupts. */
/* 0x04 enables IREQ pin. */
- p_dev->conf.ConfigIndex = cfg->index | 0x44;
+ p_dev->config_index |= 0x44;
p_dev->io_lines = 16;
ret = pcmcia_request_io(p_dev);
if (ret)
@@ -102,65 +96,49 @@ static int ipwireless_probe(struct pcmcia_device *p_dev,
resource_size(p_dev->resource[0]),
IPWIRELESS_PCCARD_NAME);
- if (cfg->mem.nwin == 0)
- return 0;
-
- ipw->request_common_memory.Attributes =
+ p_dev->resource[2]->flags |=
WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
- ipw->request_common_memory.Base = cfg->mem.win[0].host_addr;
- ipw->request_common_memory.Size = cfg->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(p_dev, &ipw->request_common_memory,
- &ipw->handle_common_memory);
+ ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
if (ret != 0)
goto exit1;
- ret = pcmcia_map_mem_page(p_dev, ipw->handle_common_memory,
- cfg->mem.win[0].card_addr);
-
+ ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
if (ret != 0)
goto exit2;
- ipw->is_v2_card = cfg->mem.win[0].len == 0x100;
+ ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
- 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,
+ ipw->attr_memory = ioremap(p_dev->resource[2]->start,
+ resource_size(p_dev->resource[2]));
+ request_mem_region(p_dev->resource[2]->start,
+ resource_size(p_dev->resource[2]),
IPWIRELESS_PCCARD_NAME);
- ipw->request_attr_memory.Attributes =
- WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM | WIN_ENABLE;
- 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(p_dev, &ipw->request_attr_memory,
- &ipw->handle_attr_memory);
-
+ p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
+ WIN_ENABLE;
+ p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
+ ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
if (ret != 0)
goto exit2;
- ret = pcmcia_map_mem_page(p_dev, ipw->handle_attr_memory, 0);
+ ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
if (ret != 0)
goto exit3;
- 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);
+ ipw->attr_memory = ioremap(p_dev->resource[3]->start,
+ resource_size(p_dev->resource[3]));
+ request_mem_region(p_dev->resource[3]->start,
+ resource_size(p_dev->resource[3]),
+ IPWIRELESS_PCCARD_NAME);
return 0;
exit3:
exit2:
if (ipw->common_memory) {
- release_mem_region(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size);
+ release_mem_region(p_dev->resource[2]->start,
+ resource_size(p_dev->resource[2]));
iounmap(ipw->common_memory);
}
exit1:
@@ -175,14 +153,13 @@ static int config_ipwireless(struct ipw_dev *ipw)
int ret = 0;
ipw->is_v2_card = 0;
+ link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
+ CONF_ENABLE_IRQ;
ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
if (ret != 0)
return ret;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
@@ -201,13 +178,9 @@ static int config_ipwireless(struct ipw_dev *ipw)
(unsigned int) link->irq);
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",
- 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);
+ ": attr memory %pR, common memory %pR\n",
+ link->resource[3],
+ link->resource[2]);
ipw->network = ipwireless_network_create(ipw->hardware);
if (!ipw->network)
@@ -223,25 +196,23 @@ static int config_ipwireless(struct ipw_dev *ipw)
* Do the RequestConfiguration last, because it enables interrupts.
* Then we don't get any interrupts before we're ready for them.
*/
- ret = pcmcia_request_configuration(link, &link->conf);
-
+ ret = pcmcia_enable_device(link);
if (ret != 0)
goto exit;
return 0;
exit:
- 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) {
- release_mem_region(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size);
+ release_mem_region(link->resource[2]->start,
+ resource_size(link->resource[2]));
iounmap(ipw->common_memory);
}
+ if (ipw->attr_memory) {
+ release_mem_region(link->resource[3]->start,
+ resource_size(link->resource[3]));
+ iounmap(ipw->attr_memory);
+ }
pcmcia_disable_device(link);
return -1;
}
@@ -249,13 +220,13 @@ exit:
static void release_ipwireless(struct ipw_dev *ipw)
{
if (ipw->common_memory) {
- release_mem_region(ipw->request_common_memory.Base,
- ipw->request_common_memory.Size);
+ release_mem_region(ipw->link->resource[2]->start,
+ resource_size(ipw->link->resource[2]));
iounmap(ipw->common_memory);
}
if (ipw->attr_memory) {
- release_mem_region(ipw->request_attr_memory.Base,
- ipw->request_attr_memory.Size);
+ release_mem_region(ipw->link->resource[3]->start,
+ resource_size(ipw->link->resource[3]));
iounmap(ipw->attr_memory);
}
pcmcia_disable_device(ipw->link);
@@ -324,7 +295,7 @@ static struct pcmcia_driver me = {
.owner = THIS_MODULE,
.probe = ipwireless_attach,
.remove = ipwireless_detach,
- .drv = { .name = IPWIRELESS_PCCARD_NAME },
+ .name = IPWIRELESS_PCCARD_NAME,
.id_table = ipw_ids
};
@@ -336,9 +307,6 @@ static int __init init_ipwireless(void)
{
int ret;
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
- IPWIRELESS_PCMCIA_VERSION " by " IPWIRELESS_PCMCIA_AUTHOR "\n");
-
ret = ipwireless_tty_init();
if (ret != 0)
return ret;
@@ -355,9 +323,6 @@ static int __init init_ipwireless(void)
*/
static void __exit exit_ipwireless(void)
{
- printk(KERN_INFO IPWIRELESS_PCCARD_NAME " "
- IPWIRELESS_PCMCIA_VERSION " removed\n");
-
pcmcia_unregister_driver(&me);
ipwireless_tty_release();
}
diff --git a/drivers/char/pcmcia/ipwireless/main.h b/drivers/char/pcmcia/ipwireless/main.h
index c207be87b597..f2cbb116bccb 100644
--- a/drivers/char/pcmcia/ipwireless/main.h
+++ b/drivers/char/pcmcia/ipwireless/main.h
@@ -21,7 +21,6 @@
#include <linux/sched.h>
#include <linux/types.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
@@ -45,13 +44,9 @@ 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;
/* Reference to attribute memory, containing CIS data */
void *attribute_memory;
diff --git a/drivers/char/pcmcia/ipwireless/tty.h b/drivers/char/pcmcia/ipwireless/tty.h
index 3e163d4cab15..747b2d637860 100644
--- a/drivers/char/pcmcia/ipwireless/tty.h
+++ b/drivers/char/pcmcia/ipwireless/tty.h
@@ -21,7 +21,6 @@
#include <linux/types.h>
#include <linux/sched.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 9ecd6bef5d3b..bfc10f89d951 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -70,7 +70,6 @@
#include <linux/workqueue.h>
#include <linux/hdlc.h>
-#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/cisreg.h>
#include <pcmcia/ds.h>
@@ -550,9 +549,6 @@ static int mgslpc_probe(struct pcmcia_device *link)
/* Initialize the struct pcmcia_device structure */
- link->conf.Attributes = 0;
- link->conf.IntType = INT_MEMORY_AND_IO;
-
ret = mgslpc_config(link);
if (ret)
return ret;
@@ -565,20 +561,8 @@ static int mgslpc_probe(struct pcmcia_device *link)
/* Card has been inserted.
*/
-static int mgslpc_ioprobe(struct pcmcia_device *p_dev,
- cistpl_cftable_entry_t *cfg,
- cistpl_cftable_entry_t *dflt,
- unsigned int vcc,
- void *priv_data)
+static int mgslpc_ioprobe(struct pcmcia_device *p_dev, void *priv_data)
{
- if (!cfg->io.nwin)
- return -ENODEV;
-
- p_dev->resource[0]->start = cfg->io.win[0].base;
- p_dev->resource[0]->end = cfg->io.win[0].len;
- p_dev->resource[0]->flags |= pcmcia_io_cfg_data_width(cfg->io.flags);
- p_dev->io_lines = cfg->io.flags & CISTPL_IO_LINES_MASK;
-
return pcmcia_request_io(p_dev);
}
@@ -590,32 +574,24 @@ static int mgslpc_config(struct pcmcia_device *link)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_config(0x%p)\n", link);
+ link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
ret = pcmcia_loop_config(link, mgslpc_ioprobe, NULL);
if (ret != 0)
goto failed;
- link->conf.Attributes = CONF_ENABLE_IRQ;
- link->conf.IntType = INT_MEMORY_AND_IO;
- link->conf.ConfigIndex = 8;
- link->conf.Present = PRESENT_OPTION;
+ link->config_index = 8;
+ link->config_regs = PRESENT_OPTION;
ret = pcmcia_request_irq(link, mgslpc_isr);
if (ret)
goto failed;
- ret = pcmcia_request_configuration(link, &link->conf);
+ ret = pcmcia_enable_device(link);
if (ret)
goto failed;
info->io_base = link->resource[0]->start;
info->irq_level = link->irq;
-
- dev_info(&link->dev, "index 0x%02x:",
- link->conf.ConfigIndex);
- if (link->conf.Attributes & CONF_ENABLE_IRQ)
- printk(", irq %d", link->irq);
- if (link->resource[0])
- printk(", io %pR", link->resource[0]);
- printk("\n");
return 0;
failed:
@@ -2215,6 +2191,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
return 0;
}
+static int mgslpc_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+
/* Service an IOCTL request
*
* Arguments:
@@ -2230,11 +2232,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
unsigned int cmd, unsigned long arg)
{
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
- int error;
- struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
void __user *argp = (void __user *)arg;
- unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2244,7 +2242,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -2274,34 +2272,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
return wait_events(info, argp);
case TIOCMIWAIT:
return modem_input_wait(info,(int)arg);
- case TIOCGICOUNT:
- spin_lock_irqsave(&info->lock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->lock,flags);
- p_cuser = argp;
- PUT_USER(error,cnow.cts, &p_cuser->cts);
- if (error) return error;
- PUT_USER(error,cnow.dsr, &p_cuser->dsr);
- if (error) return error;
- PUT_USER(error,cnow.rng, &p_cuser->rng);
- if (error) return error;
- PUT_USER(error,cnow.dcd, &p_cuser->dcd);
- if (error) return error;
- PUT_USER(error,cnow.rx, &p_cuser->rx);
- if (error) return error;
- PUT_USER(error,cnow.tx, &p_cuser->tx);
- if (error) return error;
- PUT_USER(error,cnow.frame, &p_cuser->frame);
- if (error) return error;
- PUT_USER(error,cnow.overrun, &p_cuser->overrun);
- if (error) return error;
- PUT_USER(error,cnow.parity, &p_cuser->parity);
- if (error) return error;
- PUT_USER(error,cnow.brk, &p_cuser->brk);
- if (error) return error;
- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
- if (error) return error;
- return 0;
default:
return -ENOIOCTLCMD;
}
@@ -2797,9 +2767,7 @@ MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids);
static struct pcmcia_driver mgslpc_driver = {
.owner = THIS_MODULE,
- .drv = {
- .name = "synclink_cs",
- },
+ .name = "synclink_cs",
.probe = mgslpc_probe,
.remove = mgslpc_detach,
.id_table = mgslpc_ids,
@@ -2835,8 +2803,6 @@ static void synclink_cs_cleanup(void)
{
int rc;
- printk("Unloading %s: version %s\n", driver_name, driver_version);
-
while(mgslpc_device_list)
mgslpc_remove_device(mgslpc_device_list);
@@ -2859,8 +2825,6 @@ static int __init synclink_cs_init(void)
BREAKPOINT();
}
- printk("%s %s\n", driver_name, driver_version);
-
if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0)
return rc;
@@ -4127,6 +4091,8 @@ static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (cmd != SIOCWANDEV)
return hdlc_ioctl(dev, ifr, cmd);
+ memset(&new_line, 0, size);
+
switch(ifr->ifr_settings.type) {
case IF_GET_IFACE: /* return current sync_serial_settings */
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 02abfddce45a..723152d978a9 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -67,7 +67,7 @@
#include <linux/slab.h>
#include <linux/major.h>
#include <linux/ppdev.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/uaccess.h>
#define PP_VERSION "ppdev: user-space parallel port driver"
@@ -97,6 +97,7 @@ struct pp_struct {
/* ROUND_UP macro from fs/select.c */
#define ROUND_UP(x,y) (((x)+(y)-1)/(y))
+static DEFINE_MUTEX(pp_do_mutex);
static inline void pp_enable_irq (struct pp_struct *pp)
{
struct parport *port = pp->pdev->port;
@@ -630,9 +631,9 @@ static int pp_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
static long pp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long ret;
- lock_kernel();
+ mutex_lock(&pp_do_mutex);
ret = pp_do_ioctl(file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&pp_do_mutex);
return ret;
}
@@ -641,7 +642,6 @@ static int pp_open (struct inode * inode, struct file * file)
unsigned int minor = iminor(inode);
struct pp_struct *pp;
- cycle_kernel_lock();
if (minor >= PARPORT_MAX)
return -ENXIO;
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index ad46eae1f9bb..923a48585501 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -675,8 +675,10 @@ static int ptmx_open(struct inode *inode, struct file *filp)
}
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
- filp->private_data = tty;
- file_move(filp, &tty->tty_files);
+
+ retval = tty_add_file(tty, filp);
+ if (retval)
+ goto out;
retval = devpts_pty_new(inode, tty->link);
if (retval)
diff --git a/drivers/char/random.c b/drivers/char/random.c
index caef35a46890..5a1aa64f4e76 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1165,6 +1165,7 @@ const struct file_operations random_fops = {
.poll = random_poll,
.unlocked_ioctl = random_ioctl,
.fasync = random_fasync,
+ .llseek = noop_llseek,
};
const struct file_operations urandom_fops = {
@@ -1172,6 +1173,7 @@ const struct file_operations urandom_fops = {
.write = random_write,
.unlocked_ioctl = random_ioctl,
.fasync = random_fasync,
+ .llseek = noop_llseek,
};
/***************************************************************
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index b38942f6bf31..bfe25ea9766b 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -19,8 +19,8 @@
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/gfp.h>
+#include <linux/compat.h>
#include <asm/uaccess.h>
@@ -55,7 +55,6 @@ static int raw_open(struct inode *inode, struct file *filp)
return 0;
}
- lock_kernel();
mutex_lock(&raw_mutex);
/*
@@ -82,7 +81,6 @@ static int raw_open(struct inode *inode, struct file *filp)
bdev->bd_inode->i_mapping;
filp->private_data = bdev;
mutex_unlock(&raw_mutex);
- unlock_kernel();
return 0;
out2:
@@ -91,7 +89,6 @@ out1:
blkdev_put(bdev, filp->f_mode);
out:
mutex_unlock(&raw_mutex);
- unlock_kernel();
return err;
}
@@ -125,20 +122,84 @@ static long
raw_ioctl(struct file *filp, unsigned int command, unsigned long arg)
{
struct block_device *bdev = filp->private_data;
- int ret;
+ return blkdev_ioctl(bdev, 0, command, arg);
+}
+
+static int bind_set(int number, u64 major, u64 minor)
+{
+ dev_t dev = MKDEV(major, minor);
+ struct raw_device_data *rawdev;
+ int err = 0;
- lock_kernel();
- ret = blkdev_ioctl(bdev, 0, command, arg);
- unlock_kernel();
+ if (number <= 0 || number >= MAX_RAW_MINORS)
+ return -EINVAL;
- return ret;
+ if (MAJOR(dev) != major || MINOR(dev) != minor)
+ return -EINVAL;
+
+ rawdev = &raw_devices[number];
+
+ /*
+ * This is like making block devices, so demand the
+ * same capability
+ */
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ /*
+ * For now, we don't need to check that the underlying
+ * block device is present or not: we can do that when
+ * the raw device is opened. Just check that the
+ * major/minor numbers make sense.
+ */
+
+ if (MAJOR(dev) == 0 && dev != 0)
+ return -EINVAL;
+
+ mutex_lock(&raw_mutex);
+ if (rawdev->inuse) {
+ mutex_unlock(&raw_mutex);
+ return -EBUSY;
+ }
+ if (rawdev->binding) {
+ bdput(rawdev->binding);
+ module_put(THIS_MODULE);
+ }
+ if (!dev) {
+ /* unbind */
+ rawdev->binding = NULL;
+ device_destroy(raw_class, MKDEV(RAW_MAJOR, number));
+ } else {
+ rawdev->binding = bdget(dev);
+ if (rawdev->binding == NULL) {
+ err = -ENOMEM;
+ } else {
+ dev_t raw = MKDEV(RAW_MAJOR, number);
+ __module_get(THIS_MODULE);
+ device_destroy(raw_class, raw);
+ device_create(raw_class, NULL, raw, NULL,
+ "raw%d", number);
+ }
+ }
+ mutex_unlock(&raw_mutex);
+ return err;
}
-static void bind_device(struct raw_config_request *rq)
+static int bind_get(int number, dev_t *dev)
{
- device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
- device_create(raw_class, NULL, MKDEV(RAW_MAJOR, rq->raw_minor), NULL,
- "raw%d", rq->raw_minor);
+ struct raw_device_data *rawdev;
+ struct block_device *bdev;
+
+ if (number <= 0 || number >= MAX_RAW_MINORS)
+ return -EINVAL;
+
+ rawdev = &raw_devices[number];
+
+ mutex_lock(&raw_mutex);
+ bdev = rawdev->binding;
+ *dev = bdev ? bdev->bd_dev : 0;
+ mutex_unlock(&raw_mutex);
+ return 0;
}
/*
@@ -149,105 +210,78 @@ static long raw_ctl_ioctl(struct file *filp, unsigned int command,
unsigned long arg)
{
struct raw_config_request rq;
- struct raw_device_data *rawdev;
- int err = 0;
+ dev_t dev;
+ int err;
- lock_kernel();
switch (command) {
case RAW_SETBIND:
+ if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+ return -EFAULT;
+
+ return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
case RAW_GETBIND:
+ if (copy_from_user(&rq, (void __user *) arg, sizeof(rq)))
+ return -EFAULT;
- /* First, find out which raw minor we want */
+ err = bind_get(rq.raw_minor, &dev);
+ if (err)
+ return err;
- if (copy_from_user(&rq, (void __user *) arg, sizeof(rq))) {
- err = -EFAULT;
- goto out;
- }
+ rq.block_major = MAJOR(dev);
+ rq.block_minor = MINOR(dev);
- if (rq.raw_minor <= 0 || rq.raw_minor >= MAX_RAW_MINORS) {
- err = -EINVAL;
- goto out;
- }
- rawdev = &raw_devices[rq.raw_minor];
-
- if (command == RAW_SETBIND) {
- dev_t dev;
-
- /*
- * This is like making block devices, so demand the
- * same capability
- */
- if (!capable(CAP_SYS_ADMIN)) {
- err = -EPERM;
- goto out;
- }
-
- /*
- * For now, we don't need to check that the underlying
- * block device is present or not: we can do that when
- * the raw device is opened. Just check that the
- * major/minor numbers make sense.
- */
-
- dev = MKDEV(rq.block_major, rq.block_minor);
- if ((rq.block_major == 0 && rq.block_minor != 0) ||
- MAJOR(dev) != rq.block_major ||
- MINOR(dev) != rq.block_minor) {
- err = -EINVAL;
- goto out;
- }
-
- mutex_lock(&raw_mutex);
- if (rawdev->inuse) {
- mutex_unlock(&raw_mutex);
- err = -EBUSY;
- goto out;
- }
- if (rawdev->binding) {
- bdput(rawdev->binding);
- module_put(THIS_MODULE);
- }
- if (rq.block_major == 0 && rq.block_minor == 0) {
- /* unbind */
- rawdev->binding = NULL;
- device_destroy(raw_class,
- MKDEV(RAW_MAJOR, rq.raw_minor));
- } else {
- rawdev->binding = bdget(dev);
- if (rawdev->binding == NULL)
- err = -ENOMEM;
- else {
- __module_get(THIS_MODULE);
- bind_device(&rq);
- }
- }
- mutex_unlock(&raw_mutex);
- } else {
- struct block_device *bdev;
-
- mutex_lock(&raw_mutex);
- bdev = rawdev->binding;
- if (bdev) {
- rq.block_major = MAJOR(bdev->bd_dev);
- rq.block_minor = MINOR(bdev->bd_dev);
- } else {
- rq.block_major = rq.block_minor = 0;
- }
- mutex_unlock(&raw_mutex);
- if (copy_to_user((void __user *)arg, &rq, sizeof(rq))) {
- err = -EFAULT;
- goto out;
- }
- }
- break;
- default:
- err = -EINVAL;
- break;
+ if (copy_to_user((void __user *)arg, &rq, sizeof(rq)))
+ return -EFAULT;
+
+ return 0;
}
-out:
- unlock_kernel();
- return err;
+
+ return -EINVAL;
+}
+
+#ifdef CONFIG_COMPAT
+struct raw32_config_request {
+ compat_int_t raw_minor;
+ compat_u64 block_major;
+ compat_u64 block_minor;
+};
+
+static long raw_ctl_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct raw32_config_request __user *user_req = compat_ptr(arg);
+ struct raw32_config_request rq;
+ dev_t dev;
+ int err = 0;
+
+ switch (cmd) {
+ case RAW_SETBIND:
+ if (copy_from_user(&rq, user_req, sizeof(rq)))
+ return -EFAULT;
+
+ return bind_set(rq.raw_minor, rq.block_major, rq.block_minor);
+
+ case RAW_GETBIND:
+ if (copy_from_user(&rq, user_req, sizeof(rq)))
+ return -EFAULT;
+
+ err = bind_get(rq.raw_minor, &dev);
+ if (err)
+ return err;
+
+ rq.block_major = MAJOR(dev);
+ rq.block_minor = MINOR(dev);
+
+ if (copy_to_user(user_req, &rq, sizeof(rq)))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ return -EINVAL;
}
+#endif
static const struct file_operations raw_fops = {
.read = do_sync_read,
@@ -258,13 +292,18 @@ static const struct file_operations raw_fops = {
.open = raw_open,
.release = raw_release,
.unlocked_ioctl = raw_ioctl,
+ .llseek = default_llseek,
.owner = THIS_MODULE,
};
static const struct file_operations raw_ctl_fops = {
.unlocked_ioctl = raw_ctl_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = raw_ctl_compat_ioctl,
+#endif
.open = raw_open,
.owner = THIS_MODULE,
+ .llseek = noop_llseek,
};
static struct cdev raw_cdev;
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index d58c2eb07f07..5e33293d24e3 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -44,7 +44,7 @@
#include <linux/delay.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
@@ -122,6 +122,7 @@ more than 512 ports.... */
/* These constants are derived from SCO Source */
+static DEFINE_MUTEX(rio_fw_mutex);
static struct Conf
RIOConf = {
/* locator */ "RIO Config here",
@@ -241,6 +242,7 @@ static struct real_driver rio_real_driver = {
static const struct file_operations rio_fw_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = rio_fw_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice rio_fw_device = {
@@ -566,9 +568,9 @@ static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
func_enter();
/* The "dev" argument isn't used. */
- lock_kernel();
+ mutex_lock(&rio_fw_mutex);
rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
- unlock_kernel();
+ mutex_unlock(&rio_fw_mutex);
func_exit();
return rc;
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 79c3bc69165a..7c79d243acc9 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1244,6 +1244,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
}
info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
configure_r_port(tty, info, NULL);
+ mutex_unlock(&info->port.mutex);
return 0;
}
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index 99e5272e3c53..0bc135b9b16f 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -67,6 +67,7 @@ static const struct file_operations scx200_gpio_fileops = {
.read = nsc_gpio_read,
.open = scx200_gpio_open,
.release = scx200_gpio_release,
+ .llseek = no_llseek,
};
static struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 32b74de18f5f..5816b39ff5a9 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -21,7 +21,7 @@
#include <linux/poll.h>
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <asm/sn/io.h>
#include <asm/sn/sn_sal.h>
#include <asm/sn/module.h>
@@ -34,6 +34,7 @@
#define SCDRV_BUFSZ 2048
#define SCDRV_TIMEOUT 1000
+static DEFINE_MUTEX(scdrv_mutex);
static irqreturn_t
scdrv_interrupt(int irq, void *subch_data)
{
@@ -105,7 +106,7 @@ scdrv_open(struct inode *inode, struct file *file)
file->private_data = sd;
/* hook this subchannel up to the system controller interrupt */
- lock_kernel();
+ mutex_lock(&scdrv_mutex);
rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
IRQF_SHARED | IRQF_DISABLED,
SYSCTL_BASENAME, sd);
@@ -113,10 +114,10 @@ scdrv_open(struct inode *inode, struct file *file)
ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
kfree(sd);
printk("%s: irq request failed (%d)\n", __func__, rv);
- unlock_kernel();
+ mutex_unlock(&scdrv_mutex);
return -EBUSY;
}
- unlock_kernel();
+ mutex_unlock(&scdrv_mutex);
return 0;
}
@@ -357,6 +358,7 @@ static const struct file_operations scdrv_fops = {
.poll = scdrv_poll,
.open = scdrv_open,
.release = scdrv_release,
+ .llseek = noop_llseek,
};
static struct class *snsc_class;
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index f2167f8e5aab..8ef16490810c 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -608,6 +608,7 @@ static unsigned int sc26198_baudtable[] = {
static const struct file_operations stl_fsiomem = {
.owner = THIS_MODULE,
.unlocked_ioctl = stl_memioctl,
+ .llseek = noop_llseek,
};
static struct class *stallion_class;
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index 5b24db4ff7f1..e53f16865397 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -397,6 +397,7 @@ static struct real_driver sx_real_driver = {
static const struct file_operations sx_fw_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = sx_fw_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice sx_fw_device = {
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a2a58004e188..3a6824f12be2 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
} /* end of mgsl_break() */
+/*
+ * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+ * Return: write counters to the user passed counter struct
+ * NB: both 1->0 and 0->1 transitions are counted except for
+ * RI where only 0->1 is counted.
+ */
+static int msgl_get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+
+{
+ struct mgsl_struct * info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+ return 0;
+}
+
/* mgsl_ioctl() Service an IOCTL request
*
* Arguments:
@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
{
- int error;
- struct mgsl_icount cnow; /* kernel counter temps */
void __user *argp = (void __user *)arg;
- struct serial_icounter_struct __user *p_cuser; /* user space */
- unsigned long flags;
switch (cmd) {
case MGSL_IOCGPARAMS:
@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
case TIOCMIWAIT:
return modem_input_wait(info,(int)arg);
- /*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- * RI where only 0->1 is counted.
- */
- case TIOCGICOUNT:
- spin_lock_irqsave(&info->irq_spinlock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
- p_cuser = argp;
- PUT_USER(error,cnow.cts, &p_cuser->cts);
- if (error) return error;
- PUT_USER(error,cnow.dsr, &p_cuser->dsr);
- if (error) return error;
- PUT_USER(error,cnow.rng, &p_cuser->rng);
- if (error) return error;
- PUT_USER(error,cnow.dcd, &p_cuser->dcd);
- if (error) return error;
- PUT_USER(error,cnow.rx, &p_cuser->rx);
- if (error) return error;
- PUT_USER(error,cnow.tx, &p_cuser->tx);
- if (error) return error;
- PUT_USER(error,cnow.frame, &p_cuser->frame);
- if (error) return error;
- PUT_USER(error,cnow.overrun, &p_cuser->overrun);
- if (error) return error;
- PUT_USER(error,cnow.parity, &p_cuser->parity);
- if (error) return error;
- PUT_USER(error,cnow.brk, &p_cuser->brk);
- if (error) return error;
- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
- if (error) return error;
- return 0;
default:
return -ENOIOCTLCMD;
}
@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
.hangup = mgsl_hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
+ .get_icount = msgl_get_icount,
.proc_fops = &mgsl_proc_fops,
};
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index fef80cfcab5c..1746d91205f7 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -691,8 +691,10 @@ static int open(struct tty_struct *tty, struct file *filp)
if (info->port.count == 1) {
/* 1st open on this device, init hardware */
retval = startup(info);
- if (retval < 0)
+ if (retval < 0) {
+ mutex_unlock(&info->port.mutex);
goto cleanup;
+ }
}
mutex_unlock(&info->port.mutex);
retval = block_til_ready(tty, filp, info);
@@ -1030,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct slgt_info *info = tty->driver_data;
- struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
- unsigned long flags;
void __user *argp = (void __user *)arg;
int ret;
@@ -1041,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -1051,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return wait_mgsl_event(info, argp);
case TIOCMIWAIT:
return modem_input_wait(info,(int)arg);
- case TIOCGICOUNT:
- spin_lock_irqsave(&info->lock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->lock,flags);
- p_cuser = argp;
- if (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) ||
- put_user(cnow.rx, &p_cuser->rx) ||
- put_user(cnow.tx, &p_cuser->tx) ||
- put_user(cnow.frame, &p_cuser->frame) ||
- put_user(cnow.overrun, &p_cuser->overrun) ||
- put_user(cnow.parity, &p_cuser->parity) ||
- put_user(cnow.brk, &p_cuser->brk) ||
- put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
- return -EFAULT;
- return 0;
case MGSL_IOCSGPIO:
return set_gpio(info, argp);
case MGSL_IOCGGPIO:
@@ -1115,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return ret;
}
+static int get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+
+{
+ struct slgt_info *info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+
/*
* support for 32 bit ioctl calls on 64 bit systems
*/
@@ -1204,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
case MGSL_IOCSGPIO:
case MGSL_IOCGGPIO:
case MGSL_IOCWAITGPIO:
- case TIOCGICOUNT:
- rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
- break;
-
case MGSL_IOCSTXIDLE:
case MGSL_IOCTXENABLE:
case MGSL_IOCRXENABLE:
@@ -3640,6 +3644,7 @@ static const struct tty_operations ops = {
.hangup = hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
+ .get_icount = get_icount,
.proc_fops = &synclink_gt_proc_fops,
};
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index e56caf7d82aa..2f9eb4b0dec1 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
SLMP_INFO *info = tty->driver_data;
- int error;
- struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct __user *p_cuser; /* user space */
- unsigned long flags;
void __user *argp = (void __user *)arg;
if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
return -ENODEV;
if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+ (cmd != TIOCMIWAIT)) {
if (tty->flags & (1 << TTY_IO_ERROR))
return -EIO;
}
@@ -1310,40 +1306,38 @@ static int 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:
- spin_lock_irqsave(&info->lock,flags);
- cnow = info->icount;
- spin_unlock_irqrestore(&info->lock,flags);
- p_cuser = argp;
- PUT_USER(error,cnow.cts, &p_cuser->cts);
- if (error) return error;
- PUT_USER(error,cnow.dsr, &p_cuser->dsr);
- if (error) return error;
- PUT_USER(error,cnow.rng, &p_cuser->rng);
- if (error) return error;
- PUT_USER(error,cnow.dcd, &p_cuser->dcd);
- if (error) return error;
- PUT_USER(error,cnow.rx, &p_cuser->rx);
- if (error) return error;
- PUT_USER(error,cnow.tx, &p_cuser->tx);
- if (error) return error;
- PUT_USER(error,cnow.frame, &p_cuser->frame);
- if (error) return error;
- PUT_USER(error,cnow.overrun, &p_cuser->overrun);
- if (error) return error;
- PUT_USER(error,cnow.parity, &p_cuser->parity);
- if (error) return error;
- PUT_USER(error,cnow.brk, &p_cuser->brk);
- if (error) return error;
- PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
- if (error) return error;
- return 0;
default:
return -ENOIOCTLCMD;
}
return 0;
}
+static int get_icount(struct tty_struct *tty,
+ struct serial_icounter_struct *icount)
+{
+ SLMP_INFO *info = tty->driver_data;
+ struct mgsl_icount cnow; /* kernel counter temps */
+ unsigned long flags;
+
+ spin_lock_irqsave(&info->lock,flags);
+ cnow = info->icount;
+ spin_unlock_irqrestore(&info->lock,flags);
+
+ icount->cts = cnow.cts;
+ icount->dsr = cnow.dsr;
+ icount->rng = cnow.rng;
+ icount->dcd = cnow.dcd;
+ icount->rx = cnow.rx;
+ icount->tx = cnow.tx;
+ icount->frame = cnow.frame;
+ icount->overrun = cnow.overrun;
+ icount->parity = cnow.parity;
+ icount->brk = cnow.brk;
+ icount->buf_overrun = cnow.buf_overrun;
+
+ return 0;
+}
+
/*
* /proc fs routines....
*/
@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
.hangup = hangup,
.tiocmget = tiocmget,
.tiocmset = tiocmset,
+ .get_icount = get_icount,
.proc_fops = &synclinkmp_proc_fops,
};
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index 878ac0c2cc68..f3019f53e875 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -18,7 +18,6 @@
#include <linux/interrupt.h>
#include <linux/mm.h>
#include <linux/fs.h>
-#include <linux/tty.h>
#include <linux/mount.h>
#include <linux/kdev_t.h>
#include <linux/major.h>
@@ -76,7 +75,7 @@ static int __init sysrq_always_enabled_setup(char *str)
__setup("sysrq_always_enabled", sysrq_always_enabled_setup);
-static void sysrq_handle_loglevel(int key, struct tty_struct *tty)
+static void sysrq_handle_loglevel(int key)
{
int i;
@@ -93,7 +92,7 @@ static struct sysrq_key_op sysrq_loglevel_op = {
};
#ifdef CONFIG_VT
-static void sysrq_handle_SAK(int key, struct tty_struct *tty)
+static void sysrq_handle_SAK(int key)
{
struct work_struct *SAK_work = &vc_cons[fg_console].SAK_work;
schedule_work(SAK_work);
@@ -109,7 +108,7 @@ static struct sysrq_key_op sysrq_SAK_op = {
#endif
#ifdef CONFIG_VT
-static void sysrq_handle_unraw(int key, struct tty_struct *tty)
+static void sysrq_handle_unraw(int key)
{
struct kbd_struct *kbd = &kbd_table[fg_console];
@@ -126,7 +125,7 @@ static struct sysrq_key_op sysrq_unraw_op = {
#define sysrq_unraw_op (*(struct sysrq_key_op *)NULL)
#endif /* CONFIG_VT */
-static void sysrq_handle_crash(int key, struct tty_struct *tty)
+static void sysrq_handle_crash(int key)
{
char *killer = NULL;
@@ -141,7 +140,7 @@ static struct sysrq_key_op sysrq_crash_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-static void sysrq_handle_reboot(int key, struct tty_struct *tty)
+static void sysrq_handle_reboot(int key)
{
lockdep_off();
local_irq_enable();
@@ -154,7 +153,7 @@ static struct sysrq_key_op sysrq_reboot_op = {
.enable_mask = SYSRQ_ENABLE_BOOT,
};
-static void sysrq_handle_sync(int key, struct tty_struct *tty)
+static void sysrq_handle_sync(int key)
{
emergency_sync();
}
@@ -165,7 +164,7 @@ static struct sysrq_key_op sysrq_sync_op = {
.enable_mask = SYSRQ_ENABLE_SYNC,
};
-static void sysrq_handle_show_timers(int key, struct tty_struct *tty)
+static void sysrq_handle_show_timers(int key)
{
sysrq_timer_list_show();
}
@@ -176,7 +175,7 @@ static struct sysrq_key_op sysrq_show_timers_op = {
.action_msg = "Show clockevent devices & pending hrtimers (no others)",
};
-static void sysrq_handle_mountro(int key, struct tty_struct *tty)
+static void sysrq_handle_mountro(int key)
{
emergency_remount();
}
@@ -188,7 +187,7 @@ static struct sysrq_key_op sysrq_mountro_op = {
};
#ifdef CONFIG_LOCKDEP
-static void sysrq_handle_showlocks(int key, struct tty_struct *tty)
+static void sysrq_handle_showlocks(int key)
{
debug_show_all_locks();
}
@@ -226,7 +225,7 @@ static void sysrq_showregs_othercpus(struct work_struct *dummy)
static DECLARE_WORK(sysrq_showallcpus, sysrq_showregs_othercpus);
-static void sysrq_handle_showallcpus(int key, struct tty_struct *tty)
+static void sysrq_handle_showallcpus(int key)
{
/*
* Fall back to the workqueue based printing if the
@@ -252,7 +251,7 @@ static struct sysrq_key_op sysrq_showallcpus_op = {
};
#endif
-static void sysrq_handle_showregs(int key, struct tty_struct *tty)
+static void sysrq_handle_showregs(int key)
{
struct pt_regs *regs = get_irq_regs();
if (regs)
@@ -266,7 +265,7 @@ static struct sysrq_key_op sysrq_showregs_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-static void sysrq_handle_showstate(int key, struct tty_struct *tty)
+static void sysrq_handle_showstate(int key)
{
show_state();
}
@@ -277,7 +276,7 @@ static struct sysrq_key_op sysrq_showstate_op = {
.enable_mask = SYSRQ_ENABLE_DUMP,
};
-static void sysrq_handle_showstate_blocked(int key, struct tty_struct *tty)
+static void sysrq_handle_showstate_blocked(int key)
{
show_state_filter(TASK_UNINTERRUPTIBLE);
}
@@ -291,7 +290,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = {
#ifdef CONFIG_TRACING
#include <linux/ftrace.h>
-static void sysrq_ftrace_dump(int key, struct tty_struct *tty)
+static void sysrq_ftrace_dump(int key)
{
ftrace_dump(DUMP_ALL);
}
@@ -305,7 +304,7 @@ static struct sysrq_key_op sysrq_ftrace_dump_op = {
#define sysrq_ftrace_dump_op (*(struct sysrq_key_op *)NULL)
#endif
-static void sysrq_handle_showmem(int key, struct tty_struct *tty)
+static void sysrq_handle_showmem(int key)
{
show_mem();
}
@@ -330,7 +329,7 @@ static void send_sig_all(int sig)
}
}
-static void sysrq_handle_term(int key, struct tty_struct *tty)
+static void sysrq_handle_term(int key)
{
send_sig_all(SIGTERM);
console_loglevel = 8;
@@ -349,7 +348,7 @@ static void moom_callback(struct work_struct *ignored)
static DECLARE_WORK(moom_work, moom_callback);
-static void sysrq_handle_moom(int key, struct tty_struct *tty)
+static void sysrq_handle_moom(int key)
{
schedule_work(&moom_work);
}
@@ -361,7 +360,7 @@ static struct sysrq_key_op sysrq_moom_op = {
};
#ifdef CONFIG_BLOCK
-static void sysrq_handle_thaw(int key, struct tty_struct *tty)
+static void sysrq_handle_thaw(int key)
{
emergency_thaw_all();
}
@@ -373,7 +372,7 @@ static struct sysrq_key_op sysrq_thaw_op = {
};
#endif
-static void sysrq_handle_kill(int key, struct tty_struct *tty)
+static void sysrq_handle_kill(int key)
{
send_sig_all(SIGKILL);
console_loglevel = 8;
@@ -385,7 +384,7 @@ static struct sysrq_key_op sysrq_kill_op = {
.enable_mask = SYSRQ_ENABLE_SIGNAL,
};
-static void sysrq_handle_unrt(int key, struct tty_struct *tty)
+static void sysrq_handle_unrt(int key)
{
normalize_rt_tasks();
}
@@ -493,7 +492,7 @@ static void __sysrq_put_key_op(int key, struct sysrq_key_op *op_p)
sysrq_key_table[i] = op_p;
}
-void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
+void __handle_sysrq(int key, bool check_mask)
{
struct sysrq_key_op *op_p;
int orig_log_level;
@@ -520,7 +519,7 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
if (!check_mask || sysrq_on_mask(op_p->enable_mask)) {
printk("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
- op_p->handler(key, tty);
+ op_p->handler(key);
} else {
printk("This sysrq operation is disabled.\n");
}
@@ -545,10 +544,10 @@ void __handle_sysrq(int key, struct tty_struct *tty, int check_mask)
spin_unlock_irqrestore(&sysrq_key_table_lock, flags);
}
-void handle_sysrq(int key, struct tty_struct *tty)
+void handle_sysrq(int key)
{
if (sysrq_on())
- __handle_sysrq(key, tty, 1);
+ __handle_sysrq(key, true);
}
EXPORT_SYMBOL(handle_sysrq);
@@ -597,7 +596,7 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
default:
if (sysrq_down && value && value != 2)
- __handle_sysrq(sysrq_xlate[code], NULL, 1);
+ __handle_sysrq(sysrq_xlate[code], true);
break;
}
@@ -765,7 +764,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
if (get_user(c, buf))
return -EFAULT;
- __handle_sysrq(c, NULL, 0);
+ __handle_sysrq(c, false);
}
return count;
@@ -773,6 +772,7 @@ static ssize_t write_sysrq_trigger(struct file *file, const char __user *buf,
static const struct file_operations proc_sysrq_trigger_operations = {
.write = write_sysrq_trigger,
+ .llseek = noop_llseek,
};
static void sysrq_init_procfs(void)
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index cad4eb65f13d..ad264185eb10 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -261,6 +261,7 @@ static const struct file_operations tb0219_fops = {
.write = tanbac_tb0219_write,
.open = tanbac_tb0219_open,
.release = tanbac_tb0219_release,
+ .llseek = no_llseek,
};
static void tb0219_restart(char *command)
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 80ea6bcfffdc..0c964cdcc223 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -37,7 +37,7 @@
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/timer.h>
#include <linux/sysfs.h>
#include <linux/device.h>
@@ -206,7 +206,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
{
int result;
- lock_kernel();
+ mutex_lock(&tlclk_mutex);
if (test_and_set_bit(0, &useflags)) {
result = -EBUSY;
/* this legacy device is always one per system and it doesn't
@@ -229,7 +229,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
inb(TLCLK_REG6); /* Clear interrupt events */
out:
- unlock_kernel();
+ mutex_unlock(&tlclk_mutex);
return result;
}
@@ -267,6 +267,7 @@ static const struct file_operations tlclk_fops = {
.read = tlclk_read,
.open = tlclk_open,
.release = tlclk_release,
+ .llseek = noop_llseek,
};
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index f8bc79f6de34..014c9d90d297 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -68,7 +68,7 @@
#include <linux/stat.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/toshiba.h>
#define TOSH_MINOR_DEV 181
@@ -78,6 +78,7 @@ MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
MODULE_DESCRIPTION("Toshiba laptop SMM driver");
MODULE_SUPPORTED_DEVICE("toshiba");
+static DEFINE_MUTEX(tosh_mutex);
static int tosh_fn;
module_param_named(fn, tosh_fn, int, 0);
MODULE_PARM_DESC(fn, "User specified Fn key detection port");
@@ -95,6 +96,7 @@ static long tosh_ioctl(struct file *, unsigned int,
static const struct file_operations tosh_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = tosh_ioctl,
+ .llseek = noop_llseek,
};
static struct miscdevice tosh_device = {
@@ -274,16 +276,16 @@ static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
return -EINVAL;
/* do we need to emulate the fan ? */
- lock_kernel();
+ mutex_lock(&tosh_mutex);
if (tosh_fan==1) {
if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) {
err = tosh_emulate_fan(&regs);
- unlock_kernel();
+ mutex_unlock(&tosh_mutex);
break;
}
}
err = tosh_smm(&regs);
- unlock_kernel();
+ mutex_unlock(&tosh_mutex);
break;
default:
return -EINVAL;
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 05ad4a17a28f..7c4133582dba 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -47,6 +47,16 @@ enum tpm_duration {
#define TPM_MAX_PROTECTED_ORDINAL 12
#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+/*
+ * Bug workaround - some TPM's don't flush the most
+ * recently changed pcr on suspend, so force the flush
+ * with an extend to the selected _unused_ non-volatile pcr.
+ */
+static int tpm_suspend_pcr;
+module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
+MODULE_PARM_DESC(suspend_pcr,
+ "PCR to use for dummy writes to faciltate flush on suspend.");
+
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
@@ -1077,18 +1087,6 @@ static struct tpm_input_header savestate_header = {
.ordinal = TPM_ORD_SAVESTATE
};
-/* Bug workaround - some TPM's don't flush the most
- * recently changed pcr on suspend, so force the flush
- * with an extend to the selected _unused_ non-volatile pcr.
- */
-static int tpm_suspend_pcr;
-static int __init tpm_suspend_setup(char *str)
-{
- get_option(&str, &tpm_suspend_pcr);
- return 1;
-}
-__setup("tpm_suspend_pcr=", tpm_suspend_setup);
-
/*
* We are about to suspend. Save the TPM state
* so that it can be restored.
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 0350c42375a2..c05c5af5aa04 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -96,6 +96,7 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/seq_file.h>
+#include <linux/serial.h>
#include <linux/uaccess.h>
#include <asm/system.h>
@@ -136,6 +137,9 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
DEFINE_MUTEX(tty_mutex);
EXPORT_SYMBOL(tty_mutex);
+/* Spinlock to protect the tty->tty_files list */
+DEFINE_SPINLOCK(tty_files_lock);
+
static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
ssize_t redirected_tty_write(struct file *, const char __user *,
@@ -180,11 +184,51 @@ struct tty_struct *alloc_tty_struct(void)
void free_tty_struct(struct tty_struct *tty)
{
+ if (tty->dev)
+ put_device(tty->dev);
kfree(tty->write_buf);
tty_buffer_free_all(tty);
kfree(tty);
}
+static inline struct tty_struct *file_tty(struct file *file)
+{
+ return ((struct tty_file_private *)file->private_data)->tty;
+}
+
+/* Associate a new file with the tty structure */
+int tty_add_file(struct tty_struct *tty, struct file *file)
+{
+ struct tty_file_private *priv;
+
+ priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->tty = tty;
+ priv->file = file;
+ file->private_data = priv;
+
+ spin_lock(&tty_files_lock);
+ list_add(&priv->list, &tty->tty_files);
+ spin_unlock(&tty_files_lock);
+
+ return 0;
+}
+
+/* Delete file from its tty */
+void tty_del_file(struct file *file)
+{
+ struct tty_file_private *priv = file->private_data;
+
+ spin_lock(&tty_files_lock);
+ list_del(&priv->list);
+ spin_unlock(&tty_files_lock);
+ file->private_data = NULL;
+ kfree(priv);
+}
+
+
#define TTY_NUMBER(tty) ((tty)->index + (tty)->driver->name_base)
/**
@@ -235,11 +279,11 @@ static int check_tty_count(struct tty_struct *tty, const char *routine)
struct list_head *p;
int count = 0;
- file_list_lock();
+ spin_lock(&tty_files_lock);
list_for_each(p, &tty->tty_files) {
count++;
}
- file_list_unlock();
+ spin_unlock(&tty_files_lock);
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_SLAVE &&
tty->link && tty->link->count)
@@ -317,7 +361,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
if (*stp == '\0')
stp = NULL;
- if (tty_line >= 0 && tty_line <= p->num && p->ops &&
+ if (tty_line >= 0 && tty_line < p->num && p->ops &&
p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) {
res = tty_driver_kref_get(p);
*line = tty_line;
@@ -497,6 +541,7 @@ void __tty_hangup(struct tty_struct *tty)
struct file *cons_filp = NULL;
struct file *filp, *f = NULL;
struct task_struct *p;
+ struct tty_file_private *priv;
int closecount = 0, n;
unsigned long flags;
int refs = 0;
@@ -506,7 +551,7 @@ void __tty_hangup(struct tty_struct *tty)
spin_lock(&redirect_lock);
- if (redirect && redirect->private_data == tty) {
+ if (redirect && file_tty(redirect) == tty) {
f = redirect;
redirect = NULL;
}
@@ -519,9 +564,10 @@ void __tty_hangup(struct tty_struct *tty)
workqueue with the lock held */
check_tty_count(tty, "tty_hangup");
- file_list_lock();
+ spin_lock(&tty_files_lock);
/* This breaks for file handles being sent over AF_UNIX sockets ? */
- list_for_each_entry(filp, &tty->tty_files, f_u.fu_list) {
+ list_for_each_entry(priv, &tty->tty_files, list) {
+ filp = priv->file;
if (filp->f_op->write == redirected_tty_write)
cons_filp = filp;
if (filp->f_op->write != tty_write)
@@ -530,7 +576,7 @@ void __tty_hangup(struct tty_struct *tty)
__tty_fasync(-1, filp, 0); /* can't block */
filp->f_op = &hung_up_tty_fops;
}
- file_list_unlock();
+ spin_unlock(&tty_files_lock);
tty_ldisc_hangup(tty);
@@ -889,12 +935,10 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
loff_t *ppos)
{
int i;
- struct tty_struct *tty;
- struct inode *inode;
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct tty_struct *tty = file_tty(file);
struct tty_ldisc *ld;
- tty = file->private_data;
- inode = file->f_path.dentry->d_inode;
if (tty_paranoia_check(tty, inode, "tty_read"))
return -EIO;
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
@@ -1065,12 +1109,11 @@ void tty_write_message(struct tty_struct *tty, char *msg)
static ssize_t tty_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- struct tty_struct *tty;
struct inode *inode = file->f_path.dentry->d_inode;
+ struct tty_struct *tty = file_tty(file);
+ struct tty_ldisc *ld;
ssize_t ret;
- struct tty_ldisc *ld;
- tty = file->private_data;
if (tty_paranoia_check(tty, inode, "tty_write"))
return -EIO;
if (!tty || !tty->ops->write ||
@@ -1424,9 +1467,9 @@ static void release_one_tty(struct work_struct *work)
tty_driver_kref_put(driver);
module_put(driver->owner);
- file_list_lock();
+ spin_lock(&tty_files_lock);
list_del_init(&tty->tty_files);
- file_list_unlock();
+ spin_unlock(&tty_files_lock);
put_pid(tty->pgrp);
put_pid(tty->session);
@@ -1507,13 +1550,13 @@ static void release_tty(struct tty_struct *tty, int idx)
int tty_release(struct inode *inode, struct file *filp)
{
- struct tty_struct *tty, *o_tty;
+ struct tty_struct *tty = file_tty(filp);
+ struct tty_struct *o_tty;
int pty_master, tty_closing, o_tty_closing, do_sleep;
int devpts;
int idx;
char buf[64];
- tty = filp->private_data;
if (tty_paranoia_check(tty, inode, "tty_release_dev"))
return 0;
@@ -1671,8 +1714,7 @@ int tty_release(struct inode *inode, struct file *filp)
* - do_tty_hangup no longer sees this file descriptor as
* something that needs to be handled for hangups.
*/
- file_kill(filp);
- filp->private_data = NULL;
+ tty_del_file(filp);
/*
* Perform some housekeeping before deciding whether to return.
@@ -1839,8 +1881,12 @@ got_driver:
return PTR_ERR(tty);
}
- filp->private_data = tty;
- file_move(filp, &tty->tty_files);
+ retval = tty_add_file(tty, filp);
+ if (retval) {
+ tty_unlock();
+ return retval;
+ }
+
check_tty_count(tty, "tty_open");
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
@@ -1916,11 +1962,10 @@ got_driver:
static unsigned int tty_poll(struct file *filp, poll_table *wait)
{
- struct tty_struct *tty;
+ struct tty_struct *tty = file_tty(filp);
struct tty_ldisc *ld;
int ret = 0;
- tty = filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll"))
return 0;
@@ -1933,11 +1978,10 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait)
static int __tty_fasync(int fd, struct file *filp, int on)
{
- struct tty_struct *tty;
+ struct tty_struct *tty = file_tty(filp);
unsigned long flags;
int retval = 0;
- tty = filp->private_data;
if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync"))
goto out;
@@ -2468,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
return tty->ops->tiocmset(tty, file, set, clear);
}
+static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
+{
+ int retval = -EINVAL;
+ struct serial_icounter_struct icount;
+ memset(&icount, 0, sizeof(icount));
+ if (tty->ops->get_icount)
+ retval = tty->ops->get_icount(tty, &icount);
+ if (retval != 0)
+ return retval;
+ if (copy_to_user(arg, &icount, sizeof(icount)))
+ return -EFAULT;
+ return 0;
+}
+
struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
{
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2491,13 +2549,13 @@ EXPORT_SYMBOL(tty_pair_get_pty);
*/
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
- struct tty_struct *tty, *real_tty;
+ struct tty_struct *tty = file_tty(file);
+ struct tty_struct *real_tty;
void __user *p = (void __user *)arg;
int retval;
struct tty_ldisc *ld;
struct inode *inode = file->f_dentry->d_inode;
- tty = file->private_data;
if (tty_paranoia_check(tty, inode, "tty_ioctl"))
return -EINVAL;
@@ -2588,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCMBIC:
case TIOCMBIS:
return tty_tiocmset(tty, file, cmd, p);
+ case TIOCGICOUNT:
+ retval = tty_tiocgicount(tty, p);
+ /* For the moment allow fall through to the old method */
+ if (retval != -EINVAL)
+ return retval;
+ break;
case TCFLSH:
switch (arg) {
case TCIFLUSH:
@@ -2619,7 +2683,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
struct inode *inode = file->f_dentry->d_inode;
- struct tty_struct *tty = file->private_data;
+ struct tty_struct *tty = file_tty(file);
struct tty_ldisc *ld;
int retval = -ENOIOCTLCMD;
@@ -2711,7 +2775,7 @@ void __do_SAK(struct tty_struct *tty)
if (!filp)
continue;
if (filp->f_op->read == tty_read &&
- filp->private_data == tty) {
+ file_tty(filp) == tty) {
printk(KERN_NOTICE "SAK: killed process %d"
" (%s): fd#%d opened to the tty\n",
task_pid_nr(p), p->comm, i);
@@ -2749,6 +2813,20 @@ void do_SAK(struct tty_struct *tty)
EXPORT_SYMBOL(do_SAK);
+static int dev_match_devt(struct device *dev, void *data)
+{
+ dev_t *devt = data;
+ return dev->devt == *devt;
+}
+
+/* Must put_device() after it's unused! */
+static struct device *tty_get_device(struct tty_struct *tty)
+{
+ dev_t devt = tty_devnum(tty);
+ return class_find_device(tty_class, NULL, &devt, dev_match_devt);
+}
+
+
/**
* initialize_tty_struct
* @tty: tty to initialize
@@ -2789,6 +2867,7 @@ void initialize_tty_struct(struct tty_struct *tty,
tty->ops = driver->ops;
tty->index = idx;
tty_line_name(driver, idx, tty->name);
+ tty->dev = tty_get_device(tty);
}
/**
@@ -2946,6 +3025,7 @@ int tty_register_driver(struct tty_driver *driver)
int i;
dev_t dev;
void **p = NULL;
+ struct device *d;
if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
@@ -2993,12 +3073,31 @@ int tty_register_driver(struct tty_driver *driver)
mutex_unlock(&tty_mutex);
if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
- for (i = 0; i < driver->num; i++)
- tty_register_device(driver, i, NULL);
+ for (i = 0; i < driver->num; i++) {
+ d = tty_register_device(driver, i, NULL);
+ if (IS_ERR(d)) {
+ error = PTR_ERR(d);
+ goto err;
+ }
+ }
}
proc_tty_register_driver(driver);
driver->flags |= TTY_DRIVER_INSTALLED;
return 0;
+
+err:
+ for (i--; i >= 0; i--)
+ tty_unregister_device(driver, i);
+
+ mutex_lock(&tty_mutex);
+ list_del(&driver->tty_drivers);
+ mutex_unlock(&tty_mutex);
+
+ unregister_chrdev_region(dev, driver->num);
+ driver->ttys = NULL;
+ driver->termios = NULL;
+ kfree(p);
+ return error;
}
EXPORT_SYMBOL(tty_register_driver);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
new file mode 100644
index 000000000000..c40c1612c8a7
--- /dev/null
+++ b/drivers/char/ttyprintk.c
@@ -0,0 +1,225 @@
+/*
+ * linux/drivers/char/ttyprintk.c
+ *
+ * Copyright (C) 2010 Samo Pogacnik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the smems of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+/*
+ * This pseudo device allows user to make printk messages. It is possible
+ * to store "console" messages inline with kernel messages for better analyses
+ * of the boot process, for example.
+ */
+
+#include <linux/device.h>
+#include <linux/serial.h>
+#include <linux/tty.h>
+
+struct ttyprintk_port {
+ struct tty_port port;
+ struct mutex port_write_mutex;
+};
+
+static struct ttyprintk_port tpk_port;
+
+/*
+ * Our simple preformatting supports transparent output of (time-stamped)
+ * printk messages (also suitable for logging service):
+ * - any cr is replaced by nl
+ * - adds a ttyprintk source tag in front of each line
+ * - too long message is fragmeted, with '\'nl between fragments
+ * - TPK_STR_SIZE isn't really the write_room limiting factor, bcause
+ * it is emptied on the fly during preformatting.
+ */
+#define TPK_STR_SIZE 508 /* should be bigger then max expected line length */
+#define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */
+static const char *tpk_tag = "[U] "; /* U for User */
+static int tpk_curr;
+
+static int tpk_printk(const unsigned char *buf, int count)
+{
+ static char tmp[TPK_STR_SIZE + 4];
+ int i = tpk_curr;
+
+ if (buf == NULL) {
+ /* flush tmp[] */
+ if (tpk_curr > 0) {
+ /* non nl or cr terminated message - add nl */
+ tmp[tpk_curr + 0] = '\n';
+ tmp[tpk_curr + 1] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ }
+ return i;
+ }
+
+ for (i = 0; i < count; i++) {
+ tmp[tpk_curr] = buf[i];
+ if (tpk_curr < TPK_STR_SIZE) {
+ switch (buf[i]) {
+ case '\r':
+ /* replace cr with nl */
+ tmp[tpk_curr + 0] = '\n';
+ tmp[tpk_curr + 1] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ if (buf[i + 1] == '\n')
+ i++;
+ break;
+ case '\n':
+ tmp[tpk_curr + 1] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ break;
+ default:
+ tpk_curr++;
+ }
+ } else {
+ /* end of tmp buffer reached: cut the message in two */
+ tmp[tpk_curr + 1] = '\\';
+ tmp[tpk_curr + 2] = '\n';
+ tmp[tpk_curr + 3] = '\0';
+ printk(KERN_INFO "%s%s", tpk_tag, tmp);
+ tpk_curr = 0;
+ }
+ }
+
+ return count;
+}
+
+/*
+ * TTY operations open function.
+ */
+static int tpk_open(struct tty_struct *tty, struct file *filp)
+{
+ tty->driver_data = &tpk_port;
+
+ return tty_port_open(&tpk_port.port, tty, filp);
+}
+
+/*
+ * TTY operations close function.
+ */
+static void tpk_close(struct tty_struct *tty, struct file *filp)
+{
+ struct ttyprintk_port *tpkp = tty->driver_data;
+
+ mutex_lock(&tpkp->port_write_mutex);
+ /* flush tpk_printk buffer */
+ tpk_printk(NULL, 0);
+ mutex_unlock(&tpkp->port_write_mutex);
+
+ tty_port_close(&tpkp->port, tty, filp);
+}
+
+/*
+ * TTY operations write function.
+ */
+static int tpk_write(struct tty_struct *tty,
+ const unsigned char *buf, int count)
+{
+ struct ttyprintk_port *tpkp = tty->driver_data;
+ int ret;
+
+
+ /* exclusive use of tpk_printk within this tty */
+ mutex_lock(&tpkp->port_write_mutex);
+ ret = tpk_printk(buf, count);
+ mutex_unlock(&tpkp->port_write_mutex);
+
+ return ret;
+}
+
+/*
+ * TTY operations write_room function.
+ */
+static int tpk_write_room(struct tty_struct *tty)
+{
+ return TPK_MAX_ROOM;
+}
+
+/*
+ * TTY operations ioctl function.
+ */
+static int tpk_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct ttyprintk_port *tpkp = tty->driver_data;
+
+ if (!tpkp)
+ return -EINVAL;
+
+ switch (cmd) {
+ /* Stop TIOCCONS */
+ case TIOCCONS:
+ return -EOPNOTSUPP;
+ default:
+ return -ENOIOCTLCMD;
+ }
+ return 0;
+}
+
+static const struct tty_operations ttyprintk_ops = {
+ .open = tpk_open,
+ .close = tpk_close,
+ .write = tpk_write,
+ .write_room = tpk_write_room,
+ .ioctl = tpk_ioctl,
+};
+
+struct tty_port_operations null_ops = { };
+
+static struct tty_driver *ttyprintk_driver;
+
+static int __init ttyprintk_init(void)
+{
+ int ret = -ENOMEM;
+ void *rp;
+
+ ttyprintk_driver = alloc_tty_driver(1);
+ if (!ttyprintk_driver)
+ return ret;
+
+ ttyprintk_driver->owner = THIS_MODULE;
+ ttyprintk_driver->driver_name = "ttyprintk";
+ ttyprintk_driver->name = "ttyprintk";
+ ttyprintk_driver->major = TTYAUX_MAJOR;
+ ttyprintk_driver->minor_start = 3;
+ ttyprintk_driver->num = 1;
+ ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
+ ttyprintk_driver->init_termios = tty_std_termios;
+ ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
+ ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
+ tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
+
+ ret = tty_register_driver(ttyprintk_driver);
+ if (ret < 0) {
+ printk(KERN_ERR "Couldn't register ttyprintk driver\n");
+ goto error;
+ }
+
+ /* create our unnumbered device */
+ rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
+ ttyprintk_driver->name);
+ if (IS_ERR(rp)) {
+ printk(KERN_ERR "Couldn't create ttyprintk device\n");
+ ret = PTR_ERR(rp);
+ goto error;
+ }
+
+ tty_port_init(&tpk_port.port);
+ tpk_port.port.ops = &null_ops;
+ mutex_init(&tpk_port.port_write_mutex);
+
+ return 0;
+
+error:
+ put_tty_driver(ttyprintk_driver);
+ ttyprintk_driver = NULL;
+ return ret;
+}
+module_init(ttyprintk_init);
diff --git a/drivers/char/uv_mmtimer.c b/drivers/char/uv_mmtimer.c
index c7072ba14f48..493b47a0d511 100644
--- a/drivers/char/uv_mmtimer.c
+++ b/drivers/char/uv_mmtimer.c
@@ -52,6 +52,7 @@ static const struct file_operations uv_mmtimer_fops = {
.owner = THIS_MODULE,
.mmap = uv_mmtimer_mmap,
.unlocked_ioctl = uv_mmtimer_ioctl,
+ .llseek = noop_llseek,
};
/**
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index bcce46c96b88..273ab44cc91d 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -35,6 +35,12 @@
#include <linux/console.h>
#include <linux/device.h>
#include <linux/smp_lock.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/poll.h>
+#include <linux/signal.h>
+#include <linux/slab.h>
+#include <linux/notifier.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -45,6 +51,86 @@
#undef addr
#define HEADER_SIZE 4
+struct vcs_poll_data {
+ struct notifier_block notifier;
+ unsigned int cons_num;
+ bool seen_last_update;
+ wait_queue_head_t waitq;
+ struct fasync_struct *fasync;
+};
+
+static int
+vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
+{
+ struct vt_notifier_param *param = _param;
+ struct vc_data *vc = param->vc;
+ struct vcs_poll_data *poll =
+ container_of(nb, struct vcs_poll_data, notifier);
+ int currcons = poll->cons_num;
+
+ if (code != VT_UPDATE)
+ return NOTIFY_DONE;
+
+ if (currcons == 0)
+ currcons = fg_console;
+ else
+ currcons--;
+ if (currcons != vc->vc_num)
+ return NOTIFY_DONE;
+
+ poll->seen_last_update = false;
+ wake_up_interruptible(&poll->waitq);
+ kill_fasync(&poll->fasync, SIGIO, POLL_IN);
+ return NOTIFY_OK;
+}
+
+static void
+vcs_poll_data_free(struct vcs_poll_data *poll)
+{
+ unregister_vt_notifier(&poll->notifier);
+ kfree(poll);
+}
+
+static struct vcs_poll_data *
+vcs_poll_data_get(struct file *file)
+{
+ struct vcs_poll_data *poll = file->private_data;
+
+ if (poll)
+ return poll;
+
+ poll = kzalloc(sizeof(*poll), GFP_KERNEL);
+ if (!poll)
+ return NULL;
+ poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
+ init_waitqueue_head(&poll->waitq);
+ poll->notifier.notifier_call = vcs_notifier;
+ if (register_vt_notifier(&poll->notifier) != 0) {
+ kfree(poll);
+ return NULL;
+ }
+
+ /*
+ * This code may be called either through ->poll() or ->fasync().
+ * If we have two threads using the same file descriptor, they could
+ * both enter this function, both notice that the structure hasn't
+ * been allocated yet and go ahead allocating it in parallel, but
+ * only one of them must survive and be shared otherwise we'd leak
+ * memory with a dangling notifier callback.
+ */
+ spin_lock(&file->f_lock);
+ if (!file->private_data) {
+ file->private_data = poll;
+ } else {
+ /* someone else raced ahead of us */
+ vcs_poll_data_free(poll);
+ poll = file->private_data;
+ }
+ spin_unlock(&file->f_lock);
+
+ return poll;
+}
+
static int
vcs_size(struct inode *inode)
{
@@ -102,6 +188,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
struct inode *inode = file->f_path.dentry->d_inode;
unsigned int currcons = iminor(inode);
struct vc_data *vc;
+ struct vcs_poll_data *poll;
long pos;
long viewed, attr, read;
int col, maxcol;
@@ -134,6 +221,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
ret = -EINVAL;
if (pos < 0)
goto unlock_out;
+ poll = file->private_data;
+ if (count && poll)
+ poll->seen_last_update = true;
read = 0;
ret = 0;
while (count) {
@@ -448,6 +538,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
}
*ppos += written;
ret = written;
+ if (written)
+ vcs_scr_updated(vc);
unlock_out:
release_console_sem();
@@ -457,6 +549,37 @@ unlock_out:
return ret;
}
+static unsigned int
+vcs_poll(struct file *file, poll_table *wait)
+{
+ struct vcs_poll_data *poll = vcs_poll_data_get(file);
+ int ret = 0;
+
+ if (poll) {
+ poll_wait(file, &poll->waitq, wait);
+ if (!poll->seen_last_update)
+ ret = POLLIN | POLLRDNORM;
+ }
+ return ret;
+}
+
+static int
+vcs_fasync(int fd, struct file *file, int on)
+{
+ struct vcs_poll_data *poll = file->private_data;
+
+ if (!poll) {
+ /* don't allocate anything if all we want is disable fasync */
+ if (!on)
+ return 0;
+ poll = vcs_poll_data_get(file);
+ if (!poll)
+ return -ENOMEM;
+ }
+
+ return fasync_helper(fd, file, on, &poll->fasync);
+}
+
static int
vcs_open(struct inode *inode, struct file *filp)
{
@@ -470,11 +593,23 @@ vcs_open(struct inode *inode, struct file *filp)
return ret;
}
+static int vcs_release(struct inode *inode, struct file *file)
+{
+ struct vcs_poll_data *poll = file->private_data;
+
+ if (poll)
+ vcs_poll_data_free(poll);
+ return 0;
+}
+
static const struct file_operations vcs_fops = {
.llseek = vcs_lseek,
.read = vcs_read,
.write = vcs_write,
+ .poll = vcs_poll,
+ .fasync = vcs_fasync,
.open = vcs_open,
+ .release = vcs_release,
};
static struct class *vc_class;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 42f7fa442ff8..ad6e64a2912d 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -46,7 +46,7 @@
#include <linux/completion.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
@@ -64,6 +64,7 @@
#define VIOTAPE_KERN_WARN KERN_WARNING "viotape: "
#define VIOTAPE_KERN_INFO KERN_INFO "viotape: "
+static DEFINE_MUTEX(proc_viotape_mutex);
static int viotape_numdev;
/*
@@ -684,9 +685,9 @@ static long viotap_unlocked_ioctl(struct file *file,
{
long rc;
- lock_kernel();
+ mutex_lock(&proc_viotape_mutex);
rc = viotap_ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
- unlock_kernel();
+ mutex_unlock(&proc_viotape_mutex);
return rc;
}
@@ -700,7 +701,7 @@ static int viotap_open(struct inode *inode, struct file *file)
if (op == NULL)
return -ENOMEM;
- lock_kernel();
+ mutex_lock(&proc_viotape_mutex);
get_dev_info(file->f_path.dentry->d_inode, &devi);
/* Note: We currently only support one mode! */
@@ -731,7 +732,7 @@ static int viotap_open(struct inode *inode, struct file *file)
free_op:
free_op_struct(op);
- unlock_kernel();
+ mutex_unlock(&proc_viotape_mutex);
return ret;
}
@@ -804,6 +805,7 @@ const struct file_operations viotap_fops = {
.unlocked_ioctl = viotap_unlocked_ioctl,
.open = viotap_open,
.release = viotap_release,
+ .llseek = noop_llseek,
};
/* Handle interrupt events for tape */
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 942a9826bd23..6c1b676643a9 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -48,6 +48,9 @@ struct ports_driver_data {
/* Used for exporting per-port information to debugfs */
struct dentry *debugfs_dir;
+ /* List of all the devices we're handling */
+ struct list_head portdevs;
+
/* Number of devices this driver is handling */
unsigned int index;
@@ -108,6 +111,9 @@ struct port_buffer {
* ports for that device (vdev->priv).
*/
struct ports_device {
+ /* Next portdev in the list, head is in the pdrvdata struct */
+ struct list_head list;
+
/*
* Workqueue handlers where we process deferred work after
* notification
@@ -178,15 +184,21 @@ struct port {
struct console cons;
/* Each port associates with a separate char device */
- struct cdev cdev;
+ struct cdev *cdev;
struct device *dev;
+ /* Reference-counting to handle port hot-unplugs and file operations */
+ struct kref kref;
+
/* A waitqueue for poll() or blocking read operations */
wait_queue_head_t waitqueue;
/* The 'name' of the port that we expose via sysfs properties */
char *name;
+ /* We can notify apps of host connect / disconnect events via SIGIO */
+ struct fasync_struct *async_queue;
+
/* The 'id' to identify the port with the Host */
u32 id;
@@ -221,6 +233,41 @@ out:
return port;
}
+static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev,
+ dev_t dev)
+{
+ struct port *port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&portdev->ports_lock, flags);
+ list_for_each_entry(port, &portdev->ports, list)
+ if (port->cdev->dev == dev)
+ goto out;
+ port = NULL;
+out:
+ spin_unlock_irqrestore(&portdev->ports_lock, flags);
+
+ return port;
+}
+
+static struct port *find_port_by_devt(dev_t dev)
+{
+ struct ports_device *portdev;
+ struct port *port;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pdrvdata_lock, flags);
+ list_for_each_entry(portdev, &pdrvdata.portdevs, list) {
+ port = find_port_by_devt_in_portdev(portdev, dev);
+ if (port)
+ goto out;
+ }
+ port = NULL;
+out:
+ spin_unlock_irqrestore(&pdrvdata_lock, flags);
+ return port;
+}
+
static struct port *find_port_by_id(struct ports_device *portdev, u32 id)
{
struct port *port;
@@ -410,7 +457,10 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
static ssize_t send_control_msg(struct port *port, unsigned int event,
unsigned int value)
{
- return __send_control_msg(port->portdev, port->id, event, value);
+ /* Did the port get unplugged before userspace closed it? */
+ if (port->portdev)
+ return __send_control_msg(port->portdev, port->id, event, value);
+ return 0;
}
/* Callers must take the port->outvq_lock */
@@ -459,9 +509,12 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
/*
* Wait till the host acknowledges it pushed out the data we
- * sent. This is done for ports in blocking mode or for data
- * from the hvc_console; the tty operations are performed with
- * spinlocks held so we can't sleep here.
+ * sent. This is done for data from the hvc_console; the tty
+ * operations are performed with spinlocks held so we can't
+ * sleep here. An alternative would be to copy the data to a
+ * buffer and relax the spinning requirement. The downside is
+ * we need to kmalloc a GFP_ATOMIC buffer each time the
+ * console driver writes something out.
*/
while (!virtqueue_get_buf(out_vq, &len))
cpu_relax();
@@ -522,6 +575,10 @@ static ssize_t fill_readbuf(struct port *port, char *out_buf, size_t out_count,
/* The condition that must be true for polling to end */
static bool will_read_block(struct port *port)
{
+ if (!port->guest_connected) {
+ /* Port got hot-unplugged. Let's exit. */
+ return false;
+ }
return !port_has_data(port) && port->host_connected;
}
@@ -572,6 +629,9 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
if (ret < 0)
return ret;
}
+ /* Port got hot-unplugged. */
+ if (!port->guest_connected)
+ return -ENODEV;
/*
* We could've received a disconnection message while we were
* waiting for more data.
@@ -596,6 +656,10 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
ssize_t ret;
bool nonblock;
+ /* Userspace could be out to fool us */
+ if (!count)
+ return 0;
+
port = filp->private_data;
nonblock = filp->f_flags & O_NONBLOCK;
@@ -609,6 +673,9 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
if (ret < 0)
return ret;
}
+ /* Port got hot-unplugged. */
+ if (!port->guest_connected)
+ return -ENODEV;
count = min((size_t)(32 * 1024), count);
@@ -622,6 +689,14 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf,
goto free_buf;
}
+ /*
+ * We now ask send_buf() to not spin for generic ports -- we
+ * can re-use the same code path that non-blocking file
+ * descriptors take for blocking file descriptors since the
+ * wait is already done and we're certain the write will go
+ * through to the host.
+ */
+ nonblock = true;
ret = send_buf(port, buf, count, nonblock);
if (nonblock && ret > 0)
@@ -641,8 +716,12 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
port = filp->private_data;
poll_wait(filp, &port->waitqueue, wait);
+ if (!port->guest_connected) {
+ /* Port got unplugged */
+ return POLLHUP;
+ }
ret = 0;
- if (port->inbuf)
+ if (!will_read_block(port))
ret |= POLLIN | POLLRDNORM;
if (!will_write_block(port))
ret |= POLLOUT;
@@ -652,6 +731,8 @@ static unsigned int port_fops_poll(struct file *filp, poll_table *wait)
return ret;
}
+static void remove_port(struct kref *kref);
+
static int port_fops_release(struct inode *inode, struct file *filp)
{
struct port *port;
@@ -672,6 +753,16 @@ static int port_fops_release(struct inode *inode, struct file *filp)
reclaim_consumed_buffers(port);
spin_unlock_irq(&port->outvq_lock);
+ /*
+ * Locks aren't necessary here as a port can't be opened after
+ * unplug, and if a port isn't unplugged, a kref would already
+ * exist for the port. Plus, taking ports_lock here would
+ * create a dependency on other locks taken by functions
+ * inside remove_port if we're the last holder of the port,
+ * creating many problems.
+ */
+ kref_put(&port->kref, remove_port);
+
return 0;
}
@@ -679,22 +770,31 @@ static int port_fops_open(struct inode *inode, struct file *filp)
{
struct cdev *cdev = inode->i_cdev;
struct port *port;
+ int ret;
- port = container_of(cdev, struct port, cdev);
+ port = find_port_by_devt(cdev->dev);
filp->private_data = port;
+ /* Prevent against a port getting hot-unplugged at the same time */
+ spin_lock_irq(&port->portdev->ports_lock);
+ kref_get(&port->kref);
+ spin_unlock_irq(&port->portdev->ports_lock);
+
/*
* Don't allow opening of console port devices -- that's done
* via /dev/hvc
*/
- if (is_console_port(port))
- return -ENXIO;
+ if (is_console_port(port)) {
+ ret = -ENXIO;
+ goto out;
+ }
/* Allow only one process to open a particular port at a time */
spin_lock_irq(&port->inbuf_lock);
if (port->guest_connected) {
spin_unlock_irq(&port->inbuf_lock);
- return -EMFILE;
+ ret = -EMFILE;
+ goto out;
}
port->guest_connected = true;
@@ -709,10 +809,23 @@ static int port_fops_open(struct inode *inode, struct file *filp)
reclaim_consumed_buffers(port);
spin_unlock_irq(&port->outvq_lock);
+ nonseekable_open(inode, filp);
+
/* Notify host of port being opened */
send_control_msg(filp->private_data, VIRTIO_CONSOLE_PORT_OPEN, 1);
return 0;
+out:
+ kref_put(&port->kref, remove_port);
+ return ret;
+}
+
+static int port_fops_fasync(int fd, struct file *filp, int mode)
+{
+ struct port *port;
+
+ port = filp->private_data;
+ return fasync_helper(fd, filp, mode, &port->async_queue);
}
/*
@@ -728,6 +841,8 @@ static const struct file_operations port_fops = {
.write = port_fops_write,
.poll = port_fops_poll,
.release = port_fops_release,
+ .fasync = port_fops_fasync,
+ .llseek = no_llseek,
};
/*
@@ -986,6 +1101,12 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock)
return nr_added_bufs;
}
+static void send_sigio_to_port(struct port *port)
+{
+ if (port->async_queue && port->guest_connected)
+ kill_fasync(&port->async_queue, SIGIO, POLL_OUT);
+}
+
static int add_port(struct ports_device *portdev, u32 id)
{
char debugfs_name[16];
@@ -1000,6 +1121,7 @@ static int add_port(struct ports_device *portdev, u32 id)
err = -ENOMEM;
goto fail;
}
+ kref_init(&port->kref);
port->portdev = portdev;
port->id = id;
@@ -1007,6 +1129,7 @@ static int add_port(struct ports_device *portdev, u32 id)
port->name = NULL;
port->inbuf = NULL;
port->cons.hvc = NULL;
+ port->async_queue = NULL;
port->cons.ws.ws_row = port->cons.ws.ws_col = 0;
@@ -1017,14 +1140,20 @@ static int add_port(struct ports_device *portdev, u32 id)
port->in_vq = portdev->in_vqs[port->id];
port->out_vq = portdev->out_vqs[port->id];
- cdev_init(&port->cdev, &port_fops);
+ port->cdev = cdev_alloc();
+ if (!port->cdev) {
+ dev_err(&port->portdev->vdev->dev, "Error allocating cdev\n");
+ err = -ENOMEM;
+ goto free_port;
+ }
+ port->cdev->ops = &port_fops;
devt = MKDEV(portdev->chr_major, id);
- err = cdev_add(&port->cdev, devt, 1);
+ err = cdev_add(port->cdev, devt, 1);
if (err < 0) {
dev_err(&port->portdev->vdev->dev,
"Error %d adding cdev for port %u\n", err, id);
- goto free_port;
+ goto free_cdev;
}
port->dev = device_create(pdrvdata.class, &port->portdev->vdev->dev,
devt, port, "vport%up%u",
@@ -1089,7 +1218,7 @@ free_inbufs:
free_device:
device_destroy(pdrvdata.class, port->dev->devt);
free_cdev:
- cdev_del(&port->cdev);
+ cdev_del(port->cdev);
free_port:
kfree(port);
fail:
@@ -1098,21 +1227,45 @@ fail:
return err;
}
-/* Remove all port-specific data. */
-static int remove_port(struct port *port)
+/* No users remain, remove all port-specific data. */
+static void remove_port(struct kref *kref)
+{
+ struct port *port;
+
+ port = container_of(kref, struct port, kref);
+
+ sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
+ device_destroy(pdrvdata.class, port->dev->devt);
+ cdev_del(port->cdev);
+
+ kfree(port->name);
+
+ debugfs_remove(port->debugfs_file);
+
+ kfree(port);
+}
+
+/*
+ * Port got unplugged. Remove port from portdev's list and drop the
+ * kref reference. If no userspace has this port opened, it will
+ * result in immediate removal the port.
+ */
+static void unplug_port(struct port *port)
{
struct port_buffer *buf;
+ spin_lock_irq(&port->portdev->ports_lock);
+ list_del(&port->list);
+ spin_unlock_irq(&port->portdev->ports_lock);
+
if (port->guest_connected) {
port->guest_connected = false;
port->host_connected = false;
wake_up_interruptible(&port->waitqueue);
- send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
- }
- spin_lock_irq(&port->portdev->ports_lock);
- list_del(&port->list);
- spin_unlock_irq(&port->portdev->ports_lock);
+ /* Let the app know the port is going down. */
+ send_sigio_to_port(port);
+ }
if (is_console_port(port)) {
spin_lock_irq(&pdrvdata_lock);
@@ -1131,9 +1284,6 @@ static int remove_port(struct port *port)
hvc_remove(port->cons.hvc);
#endif
}
- sysfs_remove_group(&port->dev->kobj, &port_attribute_group);
- device_destroy(pdrvdata.class, port->dev->devt);
- cdev_del(&port->cdev);
/* Remove unused data this port might have received. */
discard_port_data(port);
@@ -1144,12 +1294,19 @@ static int remove_port(struct port *port)
while ((buf = virtqueue_detach_unused_buf(port->in_vq)))
free_buf(buf);
- kfree(port->name);
-
- debugfs_remove(port->debugfs_file);
+ /*
+ * We should just assume the device itself has gone off --
+ * else a close on an open port later will try to send out a
+ * control message.
+ */
+ port->portdev = NULL;
- kfree(port);
- return 0;
+ /*
+ * Locks around here are not necessary - a port can't be
+ * opened after we removed the port struct from ports_list
+ * above.
+ */
+ kref_put(&port->kref, remove_port);
}
/* Any private messages that the Host and Guest want to share */
@@ -1188,7 +1345,7 @@ static void handle_control_message(struct ports_device *portdev,
add_port(portdev, cpkt->id);
break;
case VIRTIO_CONSOLE_PORT_REMOVE:
- remove_port(port);
+ unplug_port(port);
break;
case VIRTIO_CONSOLE_CONSOLE_PORT:
if (!cpkt->value)
@@ -1230,6 +1387,12 @@ static void handle_control_message(struct ports_device *portdev,
spin_lock_irq(&port->outvq_lock);
reclaim_consumed_buffers(port);
spin_unlock_irq(&port->outvq_lock);
+
+ /*
+ * If the guest is connected, it'll be interested in
+ * knowing the host connection state changed.
+ */
+ send_sigio_to_port(port);
break;
case VIRTIO_CONSOLE_PORT_NAME:
/*
@@ -1326,6 +1489,9 @@ static void in_intr(struct virtqueue *vq)
wake_up_interruptible(&port->waitqueue);
+ /* Send a SIGIO indicating new data in case the process asked for it */
+ send_sigio_to_port(port);
+
if (is_console_port(port) && hvc_poll(port->cons.hvc))
hvc_kick();
}
@@ -1562,6 +1728,10 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
add_port(portdev, 0);
}
+ spin_lock_irq(&pdrvdata_lock);
+ list_add_tail(&portdev->list, &pdrvdata.portdevs);
+ spin_unlock_irq(&pdrvdata_lock);
+
__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
VIRTIO_CONSOLE_DEVICE_READY, 1);
return 0;
@@ -1585,23 +1755,41 @@ static void virtcons_remove(struct virtio_device *vdev)
{
struct ports_device *portdev;
struct port *port, *port2;
- struct port_buffer *buf;
- unsigned int len;
portdev = vdev->priv;
+ spin_lock_irq(&pdrvdata_lock);
+ list_del(&portdev->list);
+ spin_unlock_irq(&pdrvdata_lock);
+
+ /* Disable interrupts for vqs */
+ vdev->config->reset(vdev);
+ /* Finish up work that's lined up */
cancel_work_sync(&portdev->control_work);
list_for_each_entry_safe(port, port2, &portdev->ports, list)
- remove_port(port);
+ unplug_port(port);
unregister_chrdev(portdev->chr_major, "virtio-portsdev");
- while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
- free_buf(buf);
+ /*
+ * When yanking out a device, we immediately lose the
+ * (device-side) queues. So there's no point in keeping the
+ * guest side around till we drop our final reference. This
+ * also means that any ports which are in an open state will
+ * have to just stop using the port, as the vqs are going
+ * away.
+ */
+ if (use_multiport(portdev)) {
+ struct port_buffer *buf;
+ unsigned int len;
- while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
- free_buf(buf);
+ while ((buf = virtqueue_get_buf(portdev->c_ivq, &len)))
+ free_buf(buf);
+
+ while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq)))
+ free_buf(buf);
+ }
vdev->config->del_vqs(vdev);
kfree(portdev->in_vqs);
@@ -1648,6 +1836,7 @@ static int __init init(void)
PTR_ERR(pdrvdata.debugfs_dir));
}
INIT_LIST_HEAD(&pdrvdata.consoles);
+ INIT_LIST_HEAD(&pdrvdata.portdevs);
return register_virtio_driver(&virtio_console);
}
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index c734f9b1263a..a8ec48ed14d9 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -194,10 +194,11 @@ static DECLARE_WORK(console_work, console_callback);
int fg_console;
int last_console;
int want_console = -1;
-int saved_fg_console;
-int saved_last_console;
-int saved_want_console;
-int saved_vc_mode;
+static int saved_fg_console;
+static int saved_last_console;
+static int saved_want_console;
+static int saved_vc_mode;
+static int saved_console_blanked;
/*
* For each existing display, we have a pointer to console currently visible
@@ -905,22 +906,16 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
* bottom of buffer
*/
old_origin += (old_rows - new_rows) * old_row_size;
- end = vc->vc_scr_end;
} else {
/*
* Cursor is in no man's land, copy 1/2 screenful
* from the top and bottom of cursor position
*/
old_origin += (vc->vc_y - new_rows/2) * old_row_size;
- end = old_origin + (old_row_size * new_rows);
}
- } else
- /*
- * Cursor near the top, copy contents from the top of buffer
- */
- end = (old_rows > new_rows) ? old_origin +
- (old_row_size * new_rows) :
- vc->vc_scr_end;
+ }
+
+ end = old_origin + old_row_size * min(old_rows, new_rows);
update_attr(vc);
@@ -3074,8 +3069,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last,
old_was_color = vc->vc_can_do_color;
vc->vc_sw->con_deinit(vc);
- if (!vc->vc_origin)
- vc->vc_origin = (unsigned long)vc->vc_screenbuf;
+ vc->vc_origin = (unsigned long)vc->vc_screenbuf;
visual_init(vc, i, 0);
set_origin(vc);
update_attr(vc);
@@ -3449,6 +3443,7 @@ int con_debug_enter(struct vc_data *vc)
saved_last_console = last_console;
saved_want_console = want_console;
saved_vc_mode = vc->vc_mode;
+ saved_console_blanked = console_blanked;
vc->vc_mode = KD_TEXT;
console_blanked = 0;
if (vc->vc_sw->con_debug_enter)
@@ -3492,6 +3487,7 @@ int con_debug_leave(void)
fg_console = saved_fg_console;
last_console = saved_last_console;
want_console = saved_want_console;
+ console_blanked = saved_console_blanked;
vc_cons[fg_console].d->vc_mode = saved_vc_mode;
vc = vc_cons[fg_console].d;
@@ -4186,6 +4182,11 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
}
}
+void vcs_scr_updated(struct vc_data *vc)
+{
+ notify_update(vc);
+}
+
/*
* Visible symbols for modules
*/
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 2bbeaaea46e9..38df8c19e74c 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -533,11 +533,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
case KIOCSOUND:
if (!perm)
goto eperm;
- /* FIXME: This is an old broken API but we need to keep it
- supported and somehow separate the historic advertised
- tick rate from any real one */
+ /*
+ * The use of PIT_TICK_RATE is historic, it used to be
+ * the platform-dependent CLOCK_TICK_RATE between 2.6.12
+ * and 2.6.36, which was a minor but unfortunate ABI
+ * change.
+ */
if (arg)
- arg = CLOCK_TICK_RATE / arg;
+ arg = PIT_TICK_RATE / arg;
kd_mksound(arg, 0);
break;
@@ -553,11 +556,8 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
*/
ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
count = ticks ? (arg & 0xffff) : 0;
- /* FIXME: This is an old broken API but we need to keep it
- supported and somehow separate the historic advertised
- tick rate from any real one */
if (count)
- count = CLOCK_TICK_RATE / count;
+ count = PIT_TICK_RATE / count;
kd_mksound(count, ticks);
break;
}
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 0ed763cd2e77..9f2272e6de1c 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -81,7 +81,6 @@
#include <linux/poll.h>
#include <linux/proc_fs.h>
#include <linux/mutex.h>
-#include <linux/smp_lock.h>
#include <linux/sysctl.h>
#include <linux/fs.h>
#include <linux/cdev.h>
@@ -94,6 +93,7 @@
#ifdef CONFIG_OF
/* For open firmware. */
+#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#endif
@@ -111,6 +111,7 @@
#define HWICAP_DEVICES 1
/* An array, which is set to true when the device is registered. */
+static DEFINE_MUTEX(hwicap_mutex);
static bool probed_devices[HWICAP_DEVICES];
static struct mutex icap_sem;
@@ -501,7 +502,7 @@ static int hwicap_open(struct inode *inode, struct file *file)
struct hwicap_drvdata *drvdata;
int status;
- lock_kernel();
+ mutex_lock(&hwicap_mutex);
drvdata = container_of(inode->i_cdev, struct hwicap_drvdata, cdev);
status = mutex_lock_interruptible(&drvdata->sem);
@@ -527,7 +528,7 @@ static int hwicap_open(struct inode *inode, struct file *file)
error:
mutex_unlock(&drvdata->sem);
out:
- unlock_kernel();
+ mutex_unlock(&hwicap_mutex);
return status;
}
@@ -566,6 +567,7 @@ static const struct file_operations hwicap_fops = {
.read = hwicap_read,
.open = hwicap_open,
.release = hwicap_release,
+ .llseek = noop_llseek,
};
static int __devinit hwicap_setup(struct device *dev, int id,
OpenPOWER on IntegriCloud