Commit da579dd6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-3.15-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging driver fixes from Greg KH:
 "Here are some staging driver fixes for 3.15.

  Three are for the speakup drivers (one fixes a regression caused in
  3.15-rc, and the other two resolve a tty issue found by Ben Hutchings)
  The comedi and r8192e_pci driver fixes also resolve reported issues"

* tag 'staging-3.15-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging:
  staging: r8192e_pci: fix htons error
  Staging: speakup: Update __speakup_paste_selection() tty (ab)usage to match vt
  Staging: speakup: Move pasting into a work item
  staging: comedi: ni_daq_700: add mux settling delay
  speakup: fix incorrect perms on speakup_acntsa.c
parents fad01e86 9326c5ca
...@@ -139,6 +139,8 @@ static int daq700_ai_rinsn(struct comedi_device *dev, ...@@ -139,6 +139,8 @@ static int daq700_ai_rinsn(struct comedi_device *dev,
/* write channel to multiplexer */ /* write channel to multiplexer */
/* set mask scan bit high to disable scanning */ /* set mask scan bit high to disable scanning */
outb(chan | 0x80, dev->iobase + CMD_R1); outb(chan | 0x80, dev->iobase + CMD_R1);
/* mux needs 2us to really settle [Fred Brooks]. */
udelay(2);
/* convert n samples */ /* convert n samples */
for (n = 0; n < insn->n; n++) { for (n = 0; n < insn->n; n++) {
......
...@@ -171,7 +171,7 @@ inline int rtllib_put_snap(u8 *data, u16 h_proto) ...@@ -171,7 +171,7 @@ inline int rtllib_put_snap(u8 *data, u16 h_proto)
snap->oui[1] = oui[1]; snap->oui[1] = oui[1];
snap->oui[2] = oui[2]; snap->oui[2] = oui[2];
*(u16 *)(data + SNAP_SIZE) = h_proto; *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
return SNAP_SIZE + sizeof(u16); return SNAP_SIZE + sizeof(u16);
} }
......
...@@ -2218,6 +2218,7 @@ static void __exit speakup_exit(void) ...@@ -2218,6 +2218,7 @@ static void __exit speakup_exit(void)
unregister_keyboard_notifier(&keyboard_notifier_block); unregister_keyboard_notifier(&keyboard_notifier_block);
unregister_vt_notifier(&vt_notifier_block); unregister_vt_notifier(&vt_notifier_block);
speakup_unregister_devsynth(); speakup_unregister_devsynth();
speakup_cancel_paste();
del_timer(&cursor_timer); del_timer(&cursor_timer);
kthread_stop(speakup_task); kthread_stop(speakup_task);
speakup_task = NULL; speakup_task = NULL;
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/device.h> /* for dev_warn */ #include <linux/device.h> /* for dev_warn */
#include <linux/selection.h> #include <linux/selection.h>
#include <linux/workqueue.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <asm/cmpxchg.h>
#include "speakup.h" #include "speakup.h"
...@@ -121,31 +125,61 @@ int speakup_set_selection(struct tty_struct *tty) ...@@ -121,31 +125,61 @@ int speakup_set_selection(struct tty_struct *tty)
return 0; return 0;
} }
/* TODO: move to some helper thread, probably. That'd fix having to check for struct speakup_paste_work {
* in_atomic(). */ struct work_struct work;
int speakup_paste_selection(struct tty_struct *tty) struct tty_struct *tty;
};
static void __speakup_paste_selection(struct work_struct *work)
{ {
struct speakup_paste_work *spw =
container_of(work, struct speakup_paste_work, work);
struct tty_struct *tty = xchg(&spw->tty, NULL);
struct vc_data *vc = (struct vc_data *) tty->driver_data; struct vc_data *vc = (struct vc_data *) tty->driver_data;
int pasted = 0, count; int pasted = 0, count;
struct tty_ldisc *ld;
DECLARE_WAITQUEUE(wait, current); DECLARE_WAITQUEUE(wait, current);
ld = tty_ldisc_ref_wait(tty);
tty_buffer_lock_exclusive(&vc->port);
add_wait_queue(&vc->paste_wait, &wait); add_wait_queue(&vc->paste_wait, &wait);
while (sel_buffer && sel_buffer_lth > pasted) { while (sel_buffer && sel_buffer_lth > pasted) {
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (test_bit(TTY_THROTTLED, &tty->flags)) { if (test_bit(TTY_THROTTLED, &tty->flags)) {
if (in_atomic())
/* if we are in an interrupt handler, abort */
break;
schedule(); schedule();
continue; continue;
} }
count = sel_buffer_lth - pasted; count = sel_buffer_lth - pasted;
count = min_t(int, count, tty->receive_room); count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL,
tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, count);
NULL, count);
pasted += count; pasted += count;
} }
remove_wait_queue(&vc->paste_wait, &wait); remove_wait_queue(&vc->paste_wait, &wait);
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
tty_buffer_unlock_exclusive(&vc->port);
tty_ldisc_deref(ld);
tty_kref_put(tty);
}
static struct speakup_paste_work speakup_paste_work = {
.work = __WORK_INITIALIZER(speakup_paste_work.work,
__speakup_paste_selection)
};
int speakup_paste_selection(struct tty_struct *tty)
{
if (cmpxchg(&speakup_paste_work.tty, NULL, tty) != NULL)
return -EBUSY;
tty_kref_get(tty);
schedule_work_on(WORK_CPU_UNBOUND, &speakup_paste_work.work);
return 0; return 0;
} }
void speakup_cancel_paste(void)
{
cancel_work_sync(&speakup_paste_work.work);
tty_kref_put(speakup_paste_work.tty);
}
...@@ -75,6 +75,7 @@ extern void synth_buffer_clear(void); ...@@ -75,6 +75,7 @@ extern void synth_buffer_clear(void);
extern void speakup_clear_selection(void); extern void speakup_clear_selection(void);
extern int speakup_set_selection(struct tty_struct *tty); extern int speakup_set_selection(struct tty_struct *tty);
extern int speakup_paste_selection(struct tty_struct *tty); extern int speakup_paste_selection(struct tty_struct *tty);
extern void speakup_cancel_paste(void);
extern void speakup_register_devsynth(void); extern void speakup_register_devsynth(void);
extern void speakup_unregister_devsynth(void); extern void speakup_unregister_devsynth(void);
extern void synth_write(const char *buf, size_t count); extern void synth_write(const char *buf, size_t count);
......
...@@ -60,15 +60,15 @@ static struct kobj_attribute vol_attribute = ...@@ -60,15 +60,15 @@ static struct kobj_attribute vol_attribute =
__ATTR(vol, S_IWUGO|S_IRUGO, spk_var_show, spk_var_store); __ATTR(vol, S_IWUGO|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute delay_time_attribute = static struct kobj_attribute delay_time_attribute =
__ATTR(delay_time, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store); __ATTR(delay_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute direct_attribute = static struct kobj_attribute direct_attribute =
__ATTR(direct, S_IWUGO|S_IRUGO, spk_var_show, spk_var_store); __ATTR(direct, S_IWUGO|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute full_time_attribute = static struct kobj_attribute full_time_attribute =
__ATTR(full_time, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store); __ATTR(full_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute jiffy_delta_attribute = static struct kobj_attribute jiffy_delta_attribute =
__ATTR(jiffy_delta, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store); __ATTR(jiffy_delta, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
static struct kobj_attribute trigger_time_attribute = static struct kobj_attribute trigger_time_attribute =
__ATTR(trigger_time, S_IRUSR|S_IRUGO, spk_var_show, spk_var_store); __ATTR(trigger_time, S_IWUSR|S_IRUGO, spk_var_show, spk_var_store);
/* /*
* Create a group of attributes so that we can create and destroy them all * Create a group of attributes so that we can create and destroy them all
......
...@@ -60,6 +60,7 @@ void tty_buffer_lock_exclusive(struct tty_port *port) ...@@ -60,6 +60,7 @@ void tty_buffer_lock_exclusive(struct tty_port *port)
atomic_inc(&buf->priority); atomic_inc(&buf->priority);
mutex_lock(&buf->lock); mutex_lock(&buf->lock);
} }
EXPORT_SYMBOL_GPL(tty_buffer_lock_exclusive);
void tty_buffer_unlock_exclusive(struct tty_port *port) void tty_buffer_unlock_exclusive(struct tty_port *port)
{ {
...@@ -73,6 +74,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port) ...@@ -73,6 +74,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port)
if (restart) if (restart)
queue_work(system_unbound_wq, &buf->work); queue_work(system_unbound_wq, &buf->work);
} }
EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive);
/** /**
* tty_buffer_space_avail - return unused buffer space * tty_buffer_space_avail - return unused buffer space
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment