aboutsummaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/agp.h3
-rw-r--r--drivers/char/agp/intel-agp.c7
-rw-r--r--drivers/char/drm/i915_drv.h6
-rw-r--r--drivers/char/drm/i915_irq.c12
-rw-r--r--drivers/char/hpet.c9
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c3
-rw-r--r--drivers/char/mspec.c65
-rw-r--r--drivers/char/random.c10
-rw-r--r--drivers/char/tty_ioctl.c14
-rw-r--r--drivers/char/vt_ioctl.c19
11 files changed, 107 insertions, 43 deletions
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index d68ddbe70f7..c78ff26647e 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -129,7 +129,7 @@ $(obj)/defkeymap.o: $(obj)/defkeymap.c
ifdef GENERATE_KEYMAP
-$(obj)/defkeymap.c $(obj)/%.c: $(src)/%.map
+$(obj)/defkeymap.c: $(obj)/%.c: $(src)/%.map
loadkeys --mktable $< > $@.tmp
sed -e 's/^static *//' $@.tmp > $@
rm $@.tmp
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 35ab1a9f8e8..8955e7ff759 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -176,7 +176,7 @@ struct agp_bridge_data {
#define I830_GMCH_MEM_MASK 0x1
#define I830_GMCH_MEM_64M 0x1
#define I830_GMCH_MEM_128M 0
-#define I830_GMCH_GMS_MASK 0xF0
+#define I830_GMCH_GMS_MASK 0x70
#define I830_GMCH_GMS_DISABLED 0x00
#define I830_GMCH_GMS_LOCAL 0x10
#define I830_GMCH_GMS_STOLEN_512 0x20
@@ -190,6 +190,7 @@ struct agp_bridge_data {
#define INTEL_I830_ERRSTS 0x92
/* Intel 855GM/852GM registers */
+#define I855_GMCH_GMS_MASK 0xF0
#define I855_GMCH_GMS_STOLEN_0M 0x0
#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 2c9ca2c6462..141ca176c39 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -506,7 +506,7 @@ static void intel_i830_init_gtt_entries(void)
break;
}
} else {
- switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
case I855_GMCH_GMS_STOLEN_1M:
gtt_entries = MB(1) - KB(size);
break;
@@ -914,6 +914,7 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
struct aper_size_info_fixed *size;
int num_entries;
u32 temp, temp2;
+ int gtt_map_size = 256 * 1024;
size = agp_bridge->current_size;
page_order = size->page_order;
@@ -923,7 +924,9 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
pci_read_config_dword(intel_private.pcidev, I915_MMADDR, &temp);
pci_read_config_dword(intel_private.pcidev, I915_PTEADDR,&temp2);
- intel_private.gtt = ioremap(temp2, 256 * 1024);
+ if (IS_G33)
+ gtt_map_size = 1024 * 1024; /* 1M on G33 */
+ intel_private.gtt = ioremap(temp2, gtt_map_size);
if (!intel_private.gtt)
return -ENOMEM;
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index 737088bd078..28b98733beb 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -210,6 +210,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
#define I915REG_INT_MASK_R 0x020a8
#define I915REG_INT_ENABLE_R 0x020a0
+#define I915REG_PIPEASTAT 0x70024
+#define I915REG_PIPEBSTAT 0x71024
+
+#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
+#define I915_VBLANK_CLEAR (1UL<<1)
+
#define SRX_INDEX 0x3c4
#define SRX_DATA 0x3c5
#define SR01 1
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index 4b4b2ce8986..bb8e9e9c820 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -214,6 +214,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
struct drm_device *dev = (struct drm_device *) arg;
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u16 temp;
+ u32 pipea_stats, pipeb_stats;
+
+ pipea_stats = I915_READ(I915REG_PIPEASTAT);
+ pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
temp = I915_READ16(I915REG_INT_IDENTITY_R);
@@ -225,6 +229,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
return IRQ_NONE;
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
+ (void) I915_READ16(I915REG_INT_IDENTITY_R);
+ DRM_READMEMORYBARRIER();
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
@@ -252,6 +258,12 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
if (dev_priv->swaps_pending > 0)
drm_locked_tasklet(dev, i915_vblank_tasklet);
+ I915_WRITE(I915REG_PIPEASTAT,
+ pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
+ I915_VBLANK_CLEAR);
+ I915_WRITE(I915REG_PIPEBSTAT,
+ pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
+ I915_VBLANK_CLEAR);
}
return IRQ_HANDLED;
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 7ecffc9c738..4c16778e3f8 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -62,6 +62,8 @@
static u32 hpet_nhpet, hpet_max_freq = HPET_USER_FREQ;
+/* This clocksource driver currently only works on ia64 */
+#ifdef CONFIG_IA64
static void __iomem *hpet_mctr;
static cycle_t read_hpet(void)
@@ -79,6 +81,7 @@ static struct clocksource clocksource_hpet = {
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};
static struct clocksource *hpet_clocksource;
+#endif
/* A lock for concurrent access by app and isr hpet activity. */
static DEFINE_SPINLOCK(hpet_lock);
@@ -943,14 +946,14 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
__FUNCTION__, hdp->hd_phys_address);
iounmap(hdp->hd_address);
- return -EBUSY;
+ return AE_ALREADY_EXISTS;
}
} else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) {
struct acpi_resource_fixed_memory32 *fixmem32;
fixmem32 = &res->data.fixed_memory32;
if (!fixmem32)
- return -EINVAL;
+ return AE_NO_MEMORY;
hdp->hd_phys_address = fixmem32->address;
hdp->hd_address = ioremap(fixmem32->address,
@@ -960,7 +963,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
printk(KERN_DEBUG "%s: 0x%lx is busy\n",
__FUNCTION__, hdp->hd_phys_address);
iounmap(hdp->hd_address);
- return -EBUSY;
+ return AE_ALREADY_EXISTS;
}
} else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
struct acpi_resource_extended_irq *irqp;
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 9b07f785106..dd441ff4af5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2215,7 +2215,8 @@ static int ipmi_pci_resume(struct pci_dev *pdev)
static struct pci_device_id ipmi_pci_devices[] = {
{ PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
- { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }
+ { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
+ { 0, }
};
MODULE_DEVICE_TABLE(pci, ipmi_pci_devices);
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c
index c08a4152ee8..04ac155d3a0 100644
--- a/drivers/char/mspec.c
+++ b/drivers/char/mspec.c
@@ -67,7 +67,7 @@
/*
* Page types allocated by the device.
*/
-enum {
+enum mspec_page_type {
MSPEC_FETCHOP = 1,
MSPEC_CACHED,
MSPEC_UNCACHED
@@ -83,15 +83,25 @@ static int is_sn2;
* One of these structures is allocated when an mspec region is mmaped. The
* structure is pointed to by the vma->vm_private_data field in the vma struct.
* This structure is used to record the addresses of the mspec pages.
+ * This structure is shared by all vma's that are split off from the
+ * original vma when split_vma()'s are done.
+ *
+ * The refcnt is incremented atomically because mm->mmap_sem does not
+ * protect in fork case where multiple tasks share the vma_data.
*/
struct vma_data {
atomic_t refcnt; /* Number of vmas sharing the data. */
- spinlock_t lock; /* Serialize access to the vma. */
+ spinlock_t lock; /* Serialize access to this structure. */
int count; /* Number of pages allocated. */
- int type; /* Type of pages allocated. */
+ enum mspec_page_type type; /* Type of pages allocated. */
+ int flags; /* See VMD_xxx below. */
+ unsigned long vm_start; /* Original (unsplit) base. */
+ unsigned long vm_end; /* Original (unsplit) end. */
unsigned long maddr[0]; /* Array of MSPEC addresses. */
};
+#define VMD_VMALLOCED 0x1 /* vmalloc'd rather than kmalloc'd */
+
/* used on shub2 to clear FOP cache in the HUB */
static unsigned long scratch_page[MAX_NUMNODES];
#define SH2_AMO_CACHE_ENTRIES 4
@@ -129,8 +139,8 @@ mspec_zero_block(unsigned long addr, int len)
* mspec_open
*
* Called when a device mapping is created by a means other than mmap
- * (via fork, etc.). Increments the reference count on the underlying
- * mspec data so it is not freed prematurely.
+ * (via fork, munmap, etc.). Increments the reference count on the
+ * underlying mspec data so it is not freed prematurely.
*/
static void
mspec_open(struct vm_area_struct *vma)
@@ -145,43 +155,43 @@ mspec_open(struct vm_area_struct *vma)
* mspec_close
*
* Called when unmapping a device mapping. Frees all mspec pages
- * belonging to the vma.
+ * belonging to all the vma's sharing this vma_data structure.
*/
static void
mspec_close(struct vm_area_struct *vma)
{
struct vma_data *vdata;
- int i, pages, result, vdata_size;
+ int index, last_index;
+ unsigned long my_page;
vdata = vma->vm_private_data;
+
if (!atomic_dec_and_test(&vdata->refcnt))
return;
- pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
- vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
- for (i = 0; i < pages; i++) {
- if (vdata->maddr[i] == 0)
+ last_index = (vdata->vm_end - vdata->vm_start) >> PAGE_SHIFT;
+ for (index = 0; index < last_index; index++) {
+ if (vdata->maddr[index] == 0)
continue;
/*
* Clear the page before sticking it back
* into the pool.
*/
- result = mspec_zero_block(vdata->maddr[i], PAGE_SIZE);
- if (!result)
- uncached_free_page(vdata->maddr[i]);
+ my_page = vdata->maddr[index];
+ vdata->maddr[index] = 0;
+ if (!mspec_zero_block(my_page, PAGE_SIZE))
+ uncached_free_page(my_page);
else
printk(KERN_WARNING "mspec_close(): "
- "failed to zero page %i\n",
- result);
+ "failed to zero page %ld\n", my_page);
}
- if (vdata_size <= PAGE_SIZE)
- kfree(vdata);
- else
+ if (vdata->flags & VMD_VMALLOCED)
vfree(vdata);
+ else
+ kfree(vdata);
}
-
/*
* mspec_nopfn
*
@@ -195,7 +205,8 @@ mspec_nopfn(struct vm_area_struct *vma, unsigned long address)
int index;
struct vma_data *vdata = vma->vm_private_data;
- index = (address - vma->vm_start) >> PAGE_SHIFT;
+ BUG_ON(address < vdata->vm_start || address >= vdata->vm_end);
+ index = (address - vdata->vm_start) >> PAGE_SHIFT;
maddr = (volatile unsigned long) vdata->maddr[index];
if (maddr == 0) {
maddr = uncached_alloc_page(numa_node_id());
@@ -237,10 +248,11 @@ static struct vm_operations_struct mspec_vm_ops = {
* underlying pages.
*/
static int
-mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
+mspec_mmap(struct file *file, struct vm_area_struct *vma,
+ enum mspec_page_type type)
{
struct vma_data *vdata;
- int pages, vdata_size;
+ int pages, vdata_size, flags = 0;
if (vma->vm_pgoff != 0)
return -EINVAL;
@@ -255,12 +267,17 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, int type)
vdata_size = sizeof(struct vma_data) + pages * sizeof(long);
if (vdata_size <= PAGE_SIZE)
vdata = kmalloc(vdata_size, GFP_KERNEL);
- else
+ else {
vdata = vmalloc(vdata_size);
+ flags = VMD_VMALLOCED;
+ }
if (!vdata)
return -ENOMEM;
memset(vdata, 0, vdata_size);
+ vdata->vm_start = vma->vm_start;
+ vdata->vm_end = vma->vm_end;
+ vdata->flags = flags;
vdata->type = type;
spin_lock_init(&vdata->lock);
vdata->refcnt = ATOMIC_INIT(1);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 397c714cf2b..af274e5a25e 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -1550,11 +1550,13 @@ __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
* As close as possible to RFC 793, which
* suggests using a 250 kHz clock.
* Further reading shows this assumes 2 Mb/s networks.
- * For 10 Gb/s Ethernet, a 1 GHz clock is appropriate.
- * That's funny, Linux has one built in! Use it!
- * (Networks are faster now - should this be increased?)
+ * For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.
+ * For 10 Gb/s Ethernet, a 1 GHz clock should be ok, but
+ * we also need to limit the resolution so that the u32 seq
+ * overlaps less than one time per MSL (2 minutes).
+ * Choosing a clock of 64 ns period is OK. (period of 274 s)
*/
- seq += ktime_get_real().tv64;
+ seq += ktime_get_real().tv64 >> 6;
#if 0
printk("init_seq(%lx, %lx, %d, %d) = %d\n",
saddr, daddr, sport, dport, seq);
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 3423e9ee648..3ee73cf64bd 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -795,6 +795,7 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
if (L_ICANON(tty))
retval = inq_canon(tty);
return put_user(retval, (unsigned int __user *) arg);
+#ifndef TCGETS2
case TIOCGLCKTRMIOS:
if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked))
return -EFAULT;
@@ -806,6 +807,19 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
if (user_termios_to_kernel_termios(real_tty->termios_locked, (struct termios __user *) arg))
return -EFAULT;
return 0;
+#else
+ case TIOCGLCKTRMIOS:
+ if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked))
+ return -EFAULT;
+ return 0;
+
+ case TIOCSLCKTRMIOS:
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (user_termios_to_kernel_termios_1(real_tty->termios_locked, (struct termios __user *) arg))
+ return -EFAULT;
+ return 0;
+#endif
case TIOCPKT:
{
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index c6f6f420973..7a61a2a9aaf 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -770,6 +770,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
/*
* Switching-from response
*/
+ acquire_console_sem();
if (vc->vt_newvt >= 0) {
if (arg == 0)
/*
@@ -784,7 +785,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* complete the switch.
*/
int newvt;
- acquire_console_sem();
newvt = vc->vt_newvt;
vc->vt_newvt = -1;
i = vc_allocate(newvt);
@@ -798,7 +798,6 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
* other console switches..
*/
complete_change_console(vc_cons[newvt].d);
- release_console_sem();
}
}
@@ -810,9 +809,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
/*
* If it's just an ACK, ignore it
*/
- if (arg != VT_ACKACQ)
+ if (arg != VT_ACKACQ) {
+ release_console_sem();
return -EINVAL;
+ }
}
+ release_console_sem();
return 0;
@@ -1030,7 +1032,7 @@ static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
/*
* Sleeps until a vt is activated, or the task is interrupted. Returns
- * 0 if activation, -EINTR if interrupted.
+ * 0 if activation, -EINTR if interrupted by a signal handler.
*/
int vt_waitactive(int vt)
{
@@ -1055,7 +1057,7 @@ int vt_waitactive(int vt)
break;
}
release_console_sem();
- retval = -EINTR;
+ retval = -ERESTARTNOHAND;
if (signal_pending(current))
break;
schedule();
@@ -1208,15 +1210,18 @@ void change_console(struct vc_data *new_vc)
/*
* Send the signal as privileged - kill_pid() will
* tell us if the process has gone or something else
- * is awry
+ * is awry.
+ *
+ * We need to set vt_newvt *before* sending the signal or we
+ * have a race.
*/
+ vc->vt_newvt = new_vc->vc_num;
if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
/*
* It worked. Mark the vt to switch to and
* return. The process needs to send us a
* VT_RELDISP ioctl to complete the switch.
*/
- vc->vt_newvt = new_vc->vc_num;
return;
}