浏览代码

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
Linus Torvalds 11 年之前
父节点
当前提交
da579dd6a1

+ 2 - 0
drivers/staging/comedi/drivers/ni_daq_700.c

@@ -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++) {

+ 1 - 1
drivers/staging/rtl8192e/rtllib_tx.c

@@ -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);
 }
 }

+ 1 - 0
drivers/staging/speakup/main.c

@@ -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;

+ 43 - 9
drivers/staging/speakup/selection.c

@@ -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)
 	return 0;
 	return 0;
 }
 }
 
 
-/* TODO: move to some helper thread, probably.  That'd fix having to check for
- * in_atomic().  */
-int speakup_paste_selection(struct tty_struct *tty)
+struct speakup_paste_work {
+	struct work_struct work;
+	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);
-		tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted,
-			NULL, count);
+		count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, 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);
+}

+ 1 - 0
drivers/staging/speakup/speakup.h

@@ -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);

+ 4 - 4
drivers/staging/speakup/speakup_acntsa.c

@@ -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

+ 2 - 0
drivers/tty/tty_buffer.c

@@ -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)
 	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