mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-27 01:02:19 +00:00
2577 lines
85 KiB
Diff
2577 lines
85 KiB
Diff
diff --git a/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
|
|
index b8b27b0aca10..3f89cbdc60b6 100644
|
|
--- a/Documentation/devicetree/bindings/tty/serial/of-serial.txt
|
|
+++ b/Documentation/devicetree/bindings/tty/serial/of-serial.txt
|
|
@@ -10,6 +10,9 @@ Required properties:
|
|
- "ns16850"
|
|
- "nvidia,tegra20-uart"
|
|
- "ibm,qpace-nwp-serial"
|
|
+ - "altr,16550-FIFO32"
|
|
+ - "altr,16550-FIFO64"
|
|
+ - "altr,16550-FIFO128"
|
|
- "serial" if the port type is unknown.
|
|
- reg : offset and length of the register set for the device.
|
|
- interrupts : should contain uart interrupt.
|
|
diff --git a/Makefile b/Makefile
|
|
index 513b460b49f9..20f420096dfa 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 92
|
|
+SUBLEVEL = 93
|
|
EXTRAVERSION =
|
|
NAME = Saber-toothed Squirrel
|
|
|
|
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
|
|
index 0a070e98625d..b04850fdeb5b 100644
|
|
--- a/arch/arm/include/asm/uaccess.h
|
|
+++ b/arch/arm/include/asm/uaccess.h
|
|
@@ -158,8 +158,9 @@ extern int __put_user_8(void *, unsigned long long);
|
|
#define put_user(x,p) \
|
|
({ \
|
|
unsigned long __limit = current_thread_info()->addr_limit - 1; \
|
|
+ const typeof(*(p)) __user *__tmp_p = (p); \
|
|
register const typeof(*(p)) __r2 asm("r2") = (x); \
|
|
- register const typeof(*(p)) __user *__p asm("r0") = (p);\
|
|
+ register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
|
|
register unsigned long __l asm("r1") = __limit; \
|
|
register int __e asm("r0"); \
|
|
switch (sizeof(*(__p))) { \
|
|
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
|
|
index e51fdc72cdc0..98bb43fc7df7 100644
|
|
--- a/drivers/block/virtio_blk.c
|
|
+++ b/drivers/block/virtio_blk.c
|
|
@@ -27,9 +27,6 @@ struct virtio_blk
|
|
/* The disk structure for the kernel. */
|
|
struct gendisk *disk;
|
|
|
|
- /* Request tracking. */
|
|
- struct list_head reqs;
|
|
-
|
|
mempool_t *pool;
|
|
|
|
/* Process context for config space updates */
|
|
@@ -53,7 +50,6 @@ struct virtio_blk
|
|
|
|
struct virtblk_req
|
|
{
|
|
- struct list_head list;
|
|
struct request *req;
|
|
struct virtio_blk_outhdr out_hdr;
|
|
struct virtio_scsi_inhdr in_hdr;
|
|
@@ -97,7 +93,6 @@ static void blk_done(struct virtqueue *vq)
|
|
}
|
|
|
|
__blk_end_request_all(vbr->req, error);
|
|
- list_del(&vbr->list);
|
|
mempool_free(vbr, vblk->pool);
|
|
}
|
|
/* In case queue is stopped waiting for more buffers. */
|
|
@@ -182,7 +177,6 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
|
|
return false;
|
|
}
|
|
|
|
- list_add_tail(&vbr->list, &vblk->reqs);
|
|
return true;
|
|
}
|
|
|
|
@@ -435,7 +429,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
|
|
goto out_free_index;
|
|
}
|
|
|
|
- INIT_LIST_HEAD(&vblk->reqs);
|
|
vblk->vdev = vdev;
|
|
vblk->sg_elems = sg_elems;
|
|
sg_init_table(vblk->sg, vblk->sg_elems);
|
|
@@ -580,27 +573,30 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
|
|
{
|
|
struct virtio_blk *vblk = vdev->priv;
|
|
int index = vblk->index;
|
|
+ int refc;
|
|
|
|
/* Prevent config work handler from accessing the device. */
|
|
mutex_lock(&vblk->config_lock);
|
|
vblk->config_enable = false;
|
|
mutex_unlock(&vblk->config_lock);
|
|
|
|
- /* Nothing should be pending. */
|
|
- BUG_ON(!list_empty(&vblk->reqs));
|
|
+ del_gendisk(vblk->disk);
|
|
+ blk_cleanup_queue(vblk->disk->queue);
|
|
|
|
/* Stop all the virtqueues. */
|
|
vdev->config->reset(vdev);
|
|
|
|
flush_work(&vblk->config_work);
|
|
|
|
- del_gendisk(vblk->disk);
|
|
- blk_cleanup_queue(vblk->disk->queue);
|
|
+ refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
|
|
put_disk(vblk->disk);
|
|
mempool_destroy(vblk->pool);
|
|
vdev->config->del_vqs(vdev);
|
|
kfree(vblk);
|
|
- ida_simple_remove(&vd_index_ida, index);
|
|
+
|
|
+ /* Only free device id if we don't have any users */
|
|
+ if (refc == 1)
|
|
+ ida_simple_remove(&vd_index_ida, index);
|
|
}
|
|
|
|
#ifdef CONFIG_PM
|
|
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
|
|
index 681be14f3605..d02f761d84ec 100644
|
|
--- a/drivers/bluetooth/ath3k.c
|
|
+++ b/drivers/bluetooth/ath3k.c
|
|
@@ -63,6 +63,7 @@ static struct usb_device_id ath3k_table[] = {
|
|
|
|
/* Atheros AR3011 with sflash firmware*/
|
|
{ USB_DEVICE(0x0CF3, 0x3002) },
|
|
+ { USB_DEVICE(0x0CF3, 0xE019) },
|
|
{ USB_DEVICE(0x13d3, 0x3304) },
|
|
{ USB_DEVICE(0x0930, 0x0215) },
|
|
{ USB_DEVICE(0x0489, 0xE03D) },
|
|
@@ -74,16 +75,35 @@ static struct usb_device_id ath3k_table[] = {
|
|
/* Atheros AR3012 with sflash firmware*/
|
|
{ USB_DEVICE(0x0CF3, 0x0036) },
|
|
{ USB_DEVICE(0x0CF3, 0x3004) },
|
|
+ { USB_DEVICE(0x0CF3, 0x3008) },
|
|
{ USB_DEVICE(0x0CF3, 0x311D) },
|
|
{ USB_DEVICE(0x0CF3, 0x817a) },
|
|
{ USB_DEVICE(0x13d3, 0x3375) },
|
|
+ { USB_DEVICE(0x04CA, 0x3004) },
|
|
{ USB_DEVICE(0x04CA, 0x3005) },
|
|
+ { USB_DEVICE(0x04CA, 0x3006) },
|
|
+ { USB_DEVICE(0x04CA, 0x3008) },
|
|
{ USB_DEVICE(0x13d3, 0x3362) },
|
|
{ USB_DEVICE(0x0CF3, 0xE004) },
|
|
+ { USB_DEVICE(0x0CF3, 0xE005) },
|
|
+ { USB_DEVICE(0x0930, 0x0219) },
|
|
+ { USB_DEVICE(0x0489, 0xe057) },
|
|
+ { USB_DEVICE(0x13d3, 0x3393) },
|
|
+ { USB_DEVICE(0x0489, 0xe04e) },
|
|
+ { USB_DEVICE(0x0489, 0xe056) },
|
|
+ { USB_DEVICE(0x0489, 0xe04d) },
|
|
+ { USB_DEVICE(0x04c5, 0x1330) },
|
|
+ { USB_DEVICE(0x13d3, 0x3402) },
|
|
+ { USB_DEVICE(0x0cf3, 0x3121) },
|
|
+ { USB_DEVICE(0x0cf3, 0xe003) },
|
|
|
|
/* Atheros AR5BBU12 with sflash firmware */
|
|
{ USB_DEVICE(0x0489, 0xE02C) },
|
|
|
|
+ /* Atheros AR5BBU22 with sflash firmware */
|
|
+ { USB_DEVICE(0x0489, 0xE03C) },
|
|
+ { USB_DEVICE(0x0489, 0xE036) },
|
|
+
|
|
{ } /* Terminating entry */
|
|
};
|
|
|
|
@@ -97,12 +117,31 @@ static struct usb_device_id ath3k_blist_tbl[] = {
|
|
/* Atheros AR3012 with sflash firmware*/
|
|
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
|
+
|
|
+ /* Atheros AR5BBU22 with sflash firmware */
|
|
+ { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
|
|
|
|
{ } /* Terminating entry */
|
|
};
|
|
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
|
index 56fede149c1d..3cc242535012 100644
|
|
--- a/drivers/bluetooth/btusb.c
|
|
+++ b/drivers/bluetooth/btusb.c
|
|
@@ -63,6 +63,9 @@ static struct usb_device_id btusb_table[] = {
|
|
/* Apple-specific (Broadcom) devices */
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
|
|
|
|
+ /* MediaTek MT76x0E */
|
|
+ { USB_DEVICE(0x0e8d, 0x763f) },
|
|
+
|
|
/* Broadcom SoftSailing reporting vendor specific */
|
|
{ USB_DEVICE(0x0a5c, 0x21e1) },
|
|
|
|
@@ -104,11 +107,14 @@ static struct usb_device_id btusb_table[] = {
|
|
{ USB_DEVICE(0x0c10, 0x0000) },
|
|
|
|
/* Broadcom BCM20702A0 */
|
|
+ { USB_DEVICE(0x0b05, 0x17b5) },
|
|
+ { USB_DEVICE(0x0b05, 0x17cb) },
|
|
+ { USB_DEVICE(0x04ca, 0x2003) },
|
|
{ USB_DEVICE(0x0489, 0xe042) },
|
|
{ USB_DEVICE(0x413c, 0x8197) },
|
|
|
|
/* Foxconn - Hon Hai */
|
|
- { USB_DEVICE(0x0489, 0xe033) },
|
|
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
|
|
|
|
/*Broadcom devices with vendor specific id */
|
|
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
|
|
@@ -127,6 +133,7 @@ static struct usb_device_id blacklist_table[] = {
|
|
|
|
/* Atheros 3011 with sflash firmware */
|
|
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
|
|
+ { USB_DEVICE(0x0cf3, 0xe019), .driver_info = BTUSB_IGNORE },
|
|
{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
|
|
{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
|
|
{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
|
|
@@ -138,16 +145,35 @@ static struct usb_device_id blacklist_table[] = {
|
|
/* Atheros 3012 with sflash firmware */
|
|
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
|
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0xe005), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0x3121), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0cf3, 0xe003), .driver_info = BTUSB_ATH3012 },
|
|
|
|
/* Atheros AR5BBU12 with sflash firmware */
|
|
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
|
|
|
+ /* Atheros AR5BBU12 with sflash firmware */
|
|
+ { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
|
|
+ { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
|
|
+
|
|
/* Broadcom BCM2035 */
|
|
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
|
|
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
|
|
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
|
|
index 0cd2d50f9a56..a81f4694f322 100644
|
|
--- a/drivers/char/virtio_console.c
|
|
+++ b/drivers/char/virtio_console.c
|
|
@@ -131,7 +131,8 @@ struct ports_device {
|
|
spinlock_t ports_lock;
|
|
|
|
/* To protect the vq operations for the control channel */
|
|
- spinlock_t cvq_lock;
|
|
+ spinlock_t c_ivq_lock;
|
|
+ spinlock_t c_ovq_lock;
|
|
|
|
/* The current config space is stored here */
|
|
struct virtio_console_config config;
|
|
@@ -460,11 +461,14 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
|
|
vq = portdev->c_ovq;
|
|
|
|
sg_init_one(sg, &cpkt, sizeof(cpkt));
|
|
+
|
|
+ spin_lock(&portdev->c_ovq_lock);
|
|
if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) {
|
|
virtqueue_kick(vq);
|
|
while (!virtqueue_get_buf(vq, &len))
|
|
cpu_relax();
|
|
}
|
|
+ spin_unlock(&portdev->c_ovq_lock);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1474,23 +1478,23 @@ static void control_work_handler(struct work_struct *work)
|
|
portdev = container_of(work, struct ports_device, control_work);
|
|
vq = portdev->c_ivq;
|
|
|
|
- spin_lock(&portdev->cvq_lock);
|
|
+ spin_lock(&portdev->c_ivq_lock);
|
|
while ((buf = virtqueue_get_buf(vq, &len))) {
|
|
- spin_unlock(&portdev->cvq_lock);
|
|
+ spin_unlock(&portdev->c_ivq_lock);
|
|
|
|
buf->len = len;
|
|
buf->offset = 0;
|
|
|
|
handle_control_message(portdev, buf);
|
|
|
|
- spin_lock(&portdev->cvq_lock);
|
|
+ spin_lock(&portdev->c_ivq_lock);
|
|
if (add_inbuf(portdev->c_ivq, buf) < 0) {
|
|
dev_warn(&portdev->vdev->dev,
|
|
"Error adding buffer to queue\n");
|
|
free_buf(buf);
|
|
}
|
|
}
|
|
- spin_unlock(&portdev->cvq_lock);
|
|
+ spin_unlock(&portdev->c_ivq_lock);
|
|
}
|
|
|
|
static void out_intr(struct virtqueue *vq)
|
|
@@ -1751,10 +1755,12 @@ static int __devinit virtcons_probe(struct virtio_device *vdev)
|
|
if (multiport) {
|
|
unsigned int nr_added_bufs;
|
|
|
|
- spin_lock_init(&portdev->cvq_lock);
|
|
+ spin_lock_init(&portdev->c_ivq_lock);
|
|
+ spin_lock_init(&portdev->c_ovq_lock);
|
|
INIT_WORK(&portdev->control_work, &control_work_handler);
|
|
|
|
- nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
|
|
+ nr_added_bufs = fill_queue(portdev->c_ivq,
|
|
+ &portdev->c_ivq_lock);
|
|
if (!nr_added_bufs) {
|
|
dev_err(&vdev->dev,
|
|
"Error allocating buffers for control queue\n");
|
|
@@ -1895,7 +1901,7 @@ static int virtcons_restore(struct virtio_device *vdev)
|
|
return ret;
|
|
|
|
if (use_multiport(portdev))
|
|
- fill_queue(portdev->c_ivq, &portdev->cvq_lock);
|
|
+ fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
|
|
|
|
list_for_each_entry(port, &portdev->ports, list) {
|
|
port->in_vq = portdev->in_vqs[port->id];
|
|
diff --git a/drivers/md/md.c b/drivers/md/md.c
|
|
index 8590d2c256a6..3a8ef589d8c0 100644
|
|
--- a/drivers/md/md.c
|
|
+++ b/drivers/md/md.c
|
|
@@ -7071,8 +7071,10 @@ void md_do_sync(struct mddev *mddev)
|
|
/* just incase thread restarts... */
|
|
if (test_bit(MD_RECOVERY_DONE, &mddev->recovery))
|
|
return;
|
|
- if (mddev->ro) /* never try to sync a read-only array */
|
|
+ if (mddev->ro) {/* never try to sync a read-only array */
|
|
+ set_bit(MD_RECOVERY_INTR, &mddev->recovery);
|
|
return;
|
|
+ }
|
|
|
|
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
|
|
if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery))
|
|
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
|
|
index 599240af2244..bc88cabcfd43 100644
|
|
--- a/drivers/scsi/hpsa.c
|
|
+++ b/drivers/scsi/hpsa.c
|
|
@@ -99,6 +99,15 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
|
|
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3354},
|
|
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3355},
|
|
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x3356},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1920},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1921},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1922},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1923},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1924},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1925},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1926},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSH, 0x103C, 0x1928},
|
|
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x334d},
|
|
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
|
|
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
|
|
{0,}
|
|
@@ -118,13 +127,22 @@ static struct board_type products[] = {
|
|
{0x3249103C, "Smart Array P812", &SA5_access},
|
|
{0x324a103C, "Smart Array P712m", &SA5_access},
|
|
{0x324b103C, "Smart Array P711m", &SA5_access},
|
|
- {0x3350103C, "Smart Array", &SA5_access},
|
|
- {0x3351103C, "Smart Array", &SA5_access},
|
|
- {0x3352103C, "Smart Array", &SA5_access},
|
|
- {0x3353103C, "Smart Array", &SA5_access},
|
|
- {0x3354103C, "Smart Array", &SA5_access},
|
|
- {0x3355103C, "Smart Array", &SA5_access},
|
|
- {0x3356103C, "Smart Array", &SA5_access},
|
|
+ {0x3350103C, "Smart Array P222", &SA5_access},
|
|
+ {0x3351103C, "Smart Array P420", &SA5_access},
|
|
+ {0x3352103C, "Smart Array P421", &SA5_access},
|
|
+ {0x3353103C, "Smart Array P822", &SA5_access},
|
|
+ {0x3354103C, "Smart Array P420i", &SA5_access},
|
|
+ {0x3355103C, "Smart Array P220i", &SA5_access},
|
|
+ {0x3356103C, "Smart Array P721m", &SA5_access},
|
|
+ {0x1920103C, "Smart Array", &SA5_access},
|
|
+ {0x1921103C, "Smart Array", &SA5_access},
|
|
+ {0x1922103C, "Smart Array", &SA5_access},
|
|
+ {0x1923103C, "Smart Array", &SA5_access},
|
|
+ {0x1924103C, "Smart Array", &SA5_access},
|
|
+ {0x1925103C, "Smart Array", &SA5_access},
|
|
+ {0x1926103C, "Smart Array", &SA5_access},
|
|
+ {0x1928103C, "Smart Array", &SA5_access},
|
|
+ {0x334d103C, "Smart Array P822se", &SA5_access},
|
|
{0xFFFF103C, "Unknown Smart Array", &SA5_access},
|
|
};
|
|
|
|
diff --git a/drivers/scsi/isci/task.c b/drivers/scsi/isci/task.c
|
|
index 2a81e1793e5d..b53becf3fe75 100644
|
|
--- a/drivers/scsi/isci/task.c
|
|
+++ b/drivers/scsi/isci/task.c
|
|
@@ -956,6 +956,7 @@ int isci_task_abort_task(struct sas_task *task)
|
|
int ret = TMF_RESP_FUNC_FAILED;
|
|
unsigned long flags;
|
|
int perform_termination = 0;
|
|
+ int target_done_already = 0;
|
|
|
|
/* Get the isci_request reference from the task. Note that
|
|
* this check does not depend on the pending request list
|
|
@@ -970,9 +971,11 @@ int isci_task_abort_task(struct sas_task *task)
|
|
/* If task is already done, the request isn't valid */
|
|
if (!(task->task_state_flags & SAS_TASK_STATE_DONE) &&
|
|
(task->task_state_flags & SAS_TASK_AT_INITIATOR) &&
|
|
- old_request)
|
|
+ old_request) {
|
|
isci_device = isci_lookup_device(task->dev);
|
|
-
|
|
+ target_done_already = test_bit(IREQ_COMPLETE_IN_TARGET,
|
|
+ &old_request->flags);
|
|
+ }
|
|
spin_unlock(&task->task_state_lock);
|
|
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
|
|
|
|
@@ -1031,7 +1034,7 @@ int isci_task_abort_task(struct sas_task *task)
|
|
}
|
|
if (task->task_proto == SAS_PROTOCOL_SMP ||
|
|
sas_protocol_ata(task->task_proto) ||
|
|
- test_bit(IREQ_COMPLETE_IN_TARGET, &old_request->flags)) {
|
|
+ target_done_already) {
|
|
|
|
spin_unlock_irqrestore(&isci_host->scic_lock, flags);
|
|
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
|
|
index db793621c403..f98cae7730b0 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
|
|
@@ -80,10 +80,6 @@ static int msix_disable = -1;
|
|
module_param(msix_disable, int, 0);
|
|
MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
|
|
|
|
-static int missing_delay[2] = {-1, -1};
|
|
-module_param_array(missing_delay, int, NULL, 0);
|
|
-MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
|
|
-
|
|
static int mpt2sas_fwfault_debug;
|
|
MODULE_PARM_DESC(mpt2sas_fwfault_debug, " enable detection of firmware fault "
|
|
"and halt firmware - (default=0)");
|
|
@@ -2168,7 +2164,7 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
|
|
}
|
|
|
|
/**
|
|
- * _base_update_missing_delay - change the missing delay timers
|
|
+ * mpt2sas_base_update_missing_delay - change the missing delay timers
|
|
* @ioc: per adapter object
|
|
* @device_missing_delay: amount of time till device is reported missing
|
|
* @io_missing_delay: interval IO is returned when there is a missing device
|
|
@@ -2179,8 +2175,8 @@ _base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
|
|
* delay, as well as the io missing delay. This should be called at driver
|
|
* load time.
|
|
*/
|
|
-static void
|
|
-_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
|
|
+void
|
|
+mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
|
|
u16 device_missing_delay, u8 io_missing_delay)
|
|
{
|
|
u16 dmd, dmd_new, dmd_orignal;
|
|
@@ -4371,9 +4367,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
|
|
if (r)
|
|
goto out_free_resources;
|
|
|
|
- if (missing_delay[0] != -1 && missing_delay[1] != -1)
|
|
- _base_update_missing_delay(ioc, missing_delay[0],
|
|
- missing_delay[1]);
|
|
|
|
return 0;
|
|
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
|
|
index c7459fdc06cc..04968bec5dc7 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
|
|
@@ -1047,6 +1047,9 @@ void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_ty
|
|
|
|
void mpt2sas_halt_firmware(struct MPT2SAS_ADAPTER *ioc);
|
|
|
|
+void mpt2sas_base_update_missing_delay(struct MPT2SAS_ADAPTER *ioc,
|
|
+ u16 device_missing_delay, u8 io_missing_delay);
|
|
+
|
|
int mpt2sas_port_enable(struct MPT2SAS_ADAPTER *ioc);
|
|
|
|
/* scsih shared API */
|
|
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
|
|
index 9b2fb60d49c4..a16bc6110905 100644
|
|
--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
|
|
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
|
|
@@ -101,6 +101,10 @@ static ushort max_sectors = 0xFFFF;
|
|
module_param(max_sectors, ushort, 0);
|
|
MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767");
|
|
|
|
+static int missing_delay[2] = {-1, -1};
|
|
+module_param_array(missing_delay, int, NULL, 0);
|
|
+MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay");
|
|
+
|
|
/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
|
|
#define MPT2SAS_MAX_LUN (16895)
|
|
static int max_lun = MPT2SAS_MAX_LUN;
|
|
@@ -7039,11 +7043,14 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
struct _sas_device *sas_device;
|
|
struct _sas_node *expander_device;
|
|
static struct _raid_device *raid_device;
|
|
+ u8 retry_count;
|
|
|
|
printk(MPT2SAS_INFO_FMT "scan devices: start\n", ioc->name);
|
|
|
|
_scsih_sas_host_refresh(ioc);
|
|
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices: expanders start\n",
|
|
+ ioc->name);
|
|
/* expanders */
|
|
handle = 0xFFFF;
|
|
while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
|
|
@@ -7052,19 +7059,39 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
MPI2_IOCSTATUS_MASK;
|
|
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
|
|
break;
|
|
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tbreak from expander scan: "
|
|
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
|
|
+ ioc->name, ioc_status,
|
|
+ le32_to_cpu(mpi_reply.IOCLogInfo));
|
|
+ break;
|
|
+ }
|
|
handle = le16_to_cpu(expander_pg0.DevHandle);
|
|
expander_device = mpt2sas_scsih_expander_find_by_sas_address(
|
|
ioc, le64_to_cpu(expander_pg0.SASAddress));
|
|
if (expander_device)
|
|
_scsih_refresh_expander_links(ioc, expander_device,
|
|
handle);
|
|
- else
|
|
+ else {
|
|
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding expander: "
|
|
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
|
|
+ ioc->name, handle, (unsigned long long)
|
|
+ le64_to_cpu(expander_pg0.SASAddress));
|
|
_scsih_expander_add(ioc, handle);
|
|
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding expander: "
|
|
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
|
|
+ ioc->name, handle, (unsigned long long)
|
|
+ le64_to_cpu(expander_pg0.SASAddress));
|
|
+ }
|
|
}
|
|
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices: expanders complete\n",
|
|
+ ioc->name);
|
|
+
|
|
if (!ioc->ir_firmware)
|
|
goto skip_to_sas;
|
|
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices phys disk start\n", ioc->name);
|
|
/* phys disk */
|
|
phys_disk_num = 0xFF;
|
|
while (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
|
|
@@ -7074,6 +7101,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
MPI2_IOCSTATUS_MASK;
|
|
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
|
|
break;
|
|
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan:"
|
|
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
|
|
+ ioc->name, ioc_status,
|
|
+ le32_to_cpu(mpi_reply.IOCLogInfo));
|
|
+ break;
|
|
+ }
|
|
phys_disk_num = pd_pg0.PhysDiskNum;
|
|
handle = le16_to_cpu(pd_pg0.DevHandle);
|
|
sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
|
|
@@ -7083,17 +7117,46 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
&sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
|
|
handle) != 0)
|
|
continue;
|
|
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
|
+ MPI2_IOCSTATUS_MASK;
|
|
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tbreak from phys disk scan "
|
|
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
|
|
+ ioc->name, ioc_status,
|
|
+ le32_to_cpu(mpi_reply.IOCLogInfo));
|
|
+ break;
|
|
+ }
|
|
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
|
|
if (!_scsih_get_sas_address(ioc, parent_handle,
|
|
&sas_address)) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding phys disk: "
|
|
+ " handle (0x%04x), sas_addr(0x%016llx)\n",
|
|
+ ioc->name, handle, (unsigned long long)
|
|
+ le64_to_cpu(sas_device_pg0.SASAddress));
|
|
mpt2sas_transport_update_links(ioc, sas_address,
|
|
handle, sas_device_pg0.PhyNum,
|
|
MPI2_SAS_NEG_LINK_RATE_1_5);
|
|
set_bit(handle, ioc->pd_handles);
|
|
- _scsih_add_device(ioc, handle, 0, 1);
|
|
+ retry_count = 0;
|
|
+ /* This will retry adding the end device.
|
|
+ * _scsih_add_device() will decide on retries and
|
|
+ * return "1" when it should be retried
|
|
+ */
|
|
+ while (_scsih_add_device(ioc, handle, retry_count++,
|
|
+ 1)) {
|
|
+ ssleep(1);
|
|
+ }
|
|
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding phys disk: "
|
|
+ " handle (0x%04x), sas_addr(0x%016llx)\n",
|
|
+ ioc->name, handle, (unsigned long long)
|
|
+ le64_to_cpu(sas_device_pg0.SASAddress));
|
|
}
|
|
}
|
|
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices: phys disk complete\n",
|
|
+ ioc->name);
|
|
+
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices: volumes start\n", ioc->name);
|
|
/* volumes */
|
|
handle = 0xFFFF;
|
|
while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
|
|
@@ -7102,6 +7165,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
MPI2_IOCSTATUS_MASK;
|
|
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
|
|
break;
|
|
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
|
|
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
|
|
+ ioc->name, ioc_status,
|
|
+ le32_to_cpu(mpi_reply.IOCLogInfo));
|
|
+ break;
|
|
+ }
|
|
handle = le16_to_cpu(volume_pg1.DevHandle);
|
|
raid_device = _scsih_raid_device_find_by_wwid(ioc,
|
|
le64_to_cpu(volume_pg1.WWID));
|
|
@@ -7111,18 +7181,38 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
&volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle,
|
|
sizeof(Mpi2RaidVolPage0_t)))
|
|
continue;
|
|
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
|
|
+ MPI2_IOCSTATUS_MASK;
|
|
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tbreak from volume scan: "
|
|
+ "ioc_status(0x%04x), loginfo(0x%08x)\n",
|
|
+ ioc->name, ioc_status,
|
|
+ le32_to_cpu(mpi_reply.IOCLogInfo));
|
|
+ break;
|
|
+ }
|
|
if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL ||
|
|
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE ||
|
|
volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) {
|
|
memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t));
|
|
element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED;
|
|
element.VolDevHandle = volume_pg1.DevHandle;
|
|
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding volume: "
|
|
+ " handle (0x%04x)\n", ioc->name,
|
|
+ volume_pg1.DevHandle);
|
|
_scsih_sas_volume_add(ioc, &element);
|
|
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding volume: "
|
|
+ " handle (0x%04x)\n", ioc->name,
|
|
+ volume_pg1.DevHandle);
|
|
}
|
|
}
|
|
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices: volumes complete\n",
|
|
+ ioc->name);
|
|
+
|
|
skip_to_sas:
|
|
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices: end devices start\n",
|
|
+ ioc->name);
|
|
/* sas devices */
|
|
handle = 0xFFFF;
|
|
while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
|
|
@@ -7132,6 +7222,13 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
MPI2_IOCSTATUS_MASK;
|
|
if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
|
|
break;
|
|
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tbreak from end device scan:"
|
|
+ " ioc_status(0x%04x), loginfo(0x%08x)\n",
|
|
+ ioc->name, ioc_status,
|
|
+ le32_to_cpu(mpi_reply.IOCLogInfo));
|
|
+ break;
|
|
+ }
|
|
handle = le16_to_cpu(sas_device_pg0.DevHandle);
|
|
if (!(_scsih_is_end_device(
|
|
le32_to_cpu(sas_device_pg0.DeviceInfo))))
|
|
@@ -7142,12 +7239,31 @@ _scsih_scan_for_devices_after_reset(struct MPT2SAS_ADAPTER *ioc)
|
|
continue;
|
|
parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle);
|
|
if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) {
|
|
+ printk(MPT2SAS_INFO_FMT "\tBEFORE adding end device: "
|
|
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
|
|
+ ioc->name, handle, (unsigned long long)
|
|
+ le64_to_cpu(sas_device_pg0.SASAddress));
|
|
mpt2sas_transport_update_links(ioc, sas_address, handle,
|
|
sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5);
|
|
- _scsih_add_device(ioc, handle, 0, 0);
|
|
+ retry_count = 0;
|
|
+ /* This will retry adding the end device.
|
|
+ * _scsih_add_device() will decide on retries and
|
|
+ * return "1" when it should be retried
|
|
+ */
|
|
+ while (_scsih_add_device(ioc, handle, retry_count++,
|
|
+ 0)) {
|
|
+ ssleep(1);
|
|
+ }
|
|
+ printk(MPT2SAS_INFO_FMT "\tAFTER adding end device: "
|
|
+ "handle (0x%04x), sas_addr(0x%016llx)\n",
|
|
+ ioc->name, handle, (unsigned long long)
|
|
+ le64_to_cpu(sas_device_pg0.SASAddress));
|
|
}
|
|
}
|
|
|
|
+ printk(MPT2SAS_INFO_FMT "\tscan devices: end devices complete\n",
|
|
+ ioc->name);
|
|
+
|
|
printk(MPT2SAS_INFO_FMT "scan devices: complete\n", ioc->name);
|
|
}
|
|
|
|
@@ -7239,7 +7355,9 @@ _firmware_event_work(struct work_struct *work)
|
|
case MPT2SAS_PORT_ENABLE_COMPLETE:
|
|
ioc->start_scan = 0;
|
|
|
|
-
|
|
+ if (missing_delay[0] != -1 && missing_delay[1] != -1)
|
|
+ mpt2sas_base_update_missing_delay(ioc, missing_delay[0],
|
|
+ missing_delay[1]);
|
|
|
|
dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "port enable: complete "
|
|
"from worker thread\n", ioc->name));
|
|
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
|
|
index 463d125ee77b..192218ae6797 100644
|
|
--- a/drivers/staging/speakup/main.c
|
|
+++ b/drivers/staging/speakup/main.c
|
|
@@ -2219,6 +2219,7 @@ static void __exit speakup_exit(void)
|
|
unregister_keyboard_notifier(&keyboard_notifier_block);
|
|
unregister_vt_notifier(&vt_notifier_block);
|
|
speakup_unregister_devsynth();
|
|
+ speakup_cancel_paste();
|
|
del_timer(&cursor_timer);
|
|
kthread_stop(speakup_task);
|
|
speakup_task = NULL;
|
|
diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c
|
|
index 1217c79ed712..7eb602c8b6a0 100644
|
|
--- a/drivers/staging/speakup/selection.c
|
|
+++ b/drivers/staging/speakup/selection.c
|
|
@@ -3,6 +3,8 @@
|
|
#include <linux/interrupt.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/selection.h>
|
|
+#include <linux/workqueue.h>
|
|
+#include <asm/cmpxchg.h>
|
|
|
|
#include "speakup.h"
|
|
|
|
@@ -121,20 +123,24 @@ int speakup_set_selection(struct tty_struct *tty)
|
|
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;
|
|
int pasted = 0, count;
|
|
DECLARE_WAITQUEUE(wait, current);
|
|
+
|
|
add_wait_queue(&vc->paste_wait, &wait);
|
|
while (sel_buffer && sel_buffer_lth > pasted) {
|
|
set_current_state(TASK_INTERRUPTIBLE);
|
|
if (test_bit(TTY_THROTTLED, &tty->flags)) {
|
|
- if (in_atomic())
|
|
- /* if we are in an interrupt handler, abort */
|
|
- break;
|
|
schedule();
|
|
continue;
|
|
}
|
|
@@ -146,6 +152,26 @@ int speakup_paste_selection(struct tty_struct *tty)
|
|
}
|
|
remove_wait_queue(&vc->paste_wait, &wait);
|
|
current->state = TASK_RUNNING;
|
|
+ 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;
|
|
}
|
|
|
|
+void speakup_cancel_paste(void)
|
|
+{
|
|
+ cancel_work_sync(&speakup_paste_work.work);
|
|
+ tty_kref_put(speakup_paste_work.tty);
|
|
+}
|
|
diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h
|
|
index 22f0fbb85f42..cfbd88c191a4 100644
|
|
--- a/drivers/staging/speakup/speakup.h
|
|
+++ b/drivers/staging/speakup/speakup.h
|
|
@@ -84,6 +84,7 @@ extern void synth_buffer_clear(void);
|
|
extern void speakup_clear_selection(void);
|
|
extern int speakup_set_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_unregister_devsynth(void);
|
|
extern void synth_write(const char *buf, size_t count);
|
|
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
|
|
index 3cb7a4f5b988..bc7d08fc8bbd 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_login.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_login.c
|
|
@@ -131,13 +131,13 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
|
|
|
|
initiatorname_param = iscsi_find_param_from_key(
|
|
INITIATORNAME, conn->param_list);
|
|
- if (!initiatorname_param)
|
|
- return -1;
|
|
-
|
|
sessiontype_param = iscsi_find_param_from_key(
|
|
SESSIONTYPE, conn->param_list);
|
|
- if (!sessiontype_param)
|
|
+ if (!initiatorname_param || !sessiontype_param) {
|
|
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
|
|
+ ISCSI_LOGIN_STATUS_MISSING_FIELDS);
|
|
return -1;
|
|
+ }
|
|
|
|
sessiontype = (strncmp(sessiontype_param->value, NORMAL, 6)) ? 1 : 0;
|
|
|
|
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
|
|
index 60470ee98fe2..89f89092b5f2 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_nego.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_nego.c
|
|
@@ -628,8 +628,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
|
|
login->req_buf,
|
|
payload_length,
|
|
conn->param_list);
|
|
- if (ret < 0)
|
|
+ if (ret < 0) {
|
|
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
|
|
+ ISCSI_LOGIN_STATUS_INIT_ERR);
|
|
return -1;
|
|
+ }
|
|
|
|
if (login->first_request)
|
|
if (iscsi_target_check_first_request(conn, login) < 0)
|
|
@@ -644,8 +647,11 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
|
|
login->rsp_buf,
|
|
&login->rsp_length,
|
|
conn->param_list);
|
|
- if (ret < 0)
|
|
+ if (ret < 0) {
|
|
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
|
|
+ ISCSI_LOGIN_STATUS_INIT_ERR);
|
|
return -1;
|
|
+ }
|
|
|
|
if (!login->auth_complete &&
|
|
ISCSI_TPG_ATTRIB(ISCSI_TPG_C(conn))->authentication) {
|
|
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
|
|
index aa3c1062157a..b10f585cd11a 100644
|
|
--- a/drivers/target/target_core_alua.c
|
|
+++ b/drivers/target/target_core_alua.c
|
|
@@ -394,7 +394,7 @@ static inline int core_alua_state_standby(
|
|
case SEND_DIAGNOSTIC:
|
|
return 0;
|
|
case MAINTENANCE_IN:
|
|
- switch (cdb[1]) {
|
|
+ switch (cdb[1] & 0x1f) {
|
|
case MI_REPORT_TARGET_PGS:
|
|
return 0;
|
|
default:
|
|
@@ -437,7 +437,7 @@ static inline int core_alua_state_unavailable(
|
|
case REPORT_LUNS:
|
|
return 0;
|
|
case MAINTENANCE_IN:
|
|
- switch (cdb[1]) {
|
|
+ switch (cdb[1] & 0x1f) {
|
|
case MI_REPORT_TARGET_PGS:
|
|
return 0;
|
|
default:
|
|
@@ -478,7 +478,7 @@ static inline int core_alua_state_transition(
|
|
case REPORT_LUNS:
|
|
return 0;
|
|
case MAINTENANCE_IN:
|
|
- switch (cdb[1]) {
|
|
+ switch (cdb[1] & 0x1f) {
|
|
case MI_REPORT_TARGET_PGS:
|
|
return 0;
|
|
default:
|
|
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
|
|
index a251efd783de..f44459a2a7c5 100644
|
|
--- a/drivers/target/target_core_file.c
|
|
+++ b/drivers/target/target_core_file.c
|
|
@@ -299,7 +299,7 @@ static int fd_do_readv(struct se_task *task)
|
|
|
|
for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
|
|
iov[i].iov_len = sg->length;
|
|
- iov[i].iov_base = sg_virt(sg);
|
|
+ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset;
|
|
}
|
|
|
|
old_fs = get_fs();
|
|
@@ -307,6 +307,8 @@ static int fd_do_readv(struct se_task *task)
|
|
ret = vfs_readv(fd, &iov[0], task->task_sg_nents, &pos);
|
|
set_fs(old_fs);
|
|
|
|
+ for_each_sg(task->task_sg, sg, task->task_sg_nents, i)
|
|
+ kunmap(sg_page(sg));
|
|
kfree(iov);
|
|
/*
|
|
* Return zeros and GOOD status even if the READ did not return
|
|
@@ -352,7 +354,7 @@ static int fd_do_writev(struct se_task *task)
|
|
|
|
for_each_sg(task->task_sg, sg, task->task_sg_nents, i) {
|
|
iov[i].iov_len = sg->length;
|
|
- iov[i].iov_base = sg_virt(sg);
|
|
+ iov[i].iov_base = kmap(sg_page(sg)) + sg->offset;
|
|
}
|
|
|
|
old_fs = get_fs();
|
|
@@ -360,6 +362,9 @@ static int fd_do_writev(struct se_task *task)
|
|
ret = vfs_writev(fd, &iov[0], task->task_sg_nents, &pos);
|
|
set_fs(old_fs);
|
|
|
|
+ for_each_sg(task->task_sg, sg, task->task_sg_nents, i)
|
|
+ kunmap(sg_page(sg));
|
|
+
|
|
kfree(iov);
|
|
|
|
if (ret < 0 || ret != task->task_size) {
|
|
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
|
|
index d084ba328af0..d34577dbfd25 100644
|
|
--- a/drivers/target/target_core_pscsi.c
|
|
+++ b/drivers/target/target_core_pscsi.c
|
|
@@ -128,10 +128,10 @@ static int pscsi_pmode_enable_hba(struct se_hba *hba, unsigned long mode_flag)
|
|
* pSCSI Host ID and enable for phba mode
|
|
*/
|
|
sh = scsi_host_lookup(phv->phv_host_id);
|
|
- if (IS_ERR(sh)) {
|
|
+ if (!sh) {
|
|
pr_err("pSCSI: Unable to locate SCSI Host for"
|
|
" phv_host_id: %d\n", phv->phv_host_id);
|
|
- return PTR_ERR(sh);
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
phv->phv_lld_host = sh;
|
|
@@ -562,10 +562,10 @@ static struct se_device *pscsi_create_virtdevice(
|
|
sh = phv->phv_lld_host;
|
|
} else {
|
|
sh = scsi_host_lookup(pdv->pdv_host_id);
|
|
- if (IS_ERR(sh)) {
|
|
+ if (!sh) {
|
|
pr_err("pSCSI: Unable to locate"
|
|
" pdv_host_id: %d\n", pdv->pdv_host_id);
|
|
- return ERR_CAST(sh);
|
|
+ return ERR_PTR(-EINVAL);
|
|
}
|
|
}
|
|
} else {
|
|
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
|
|
index f687892b00be..34df0b2a630e 100644
|
|
--- a/drivers/target/target_core_transport.c
|
|
+++ b/drivers/target/target_core_transport.c
|
|
@@ -1458,6 +1458,7 @@ static inline void transport_generic_prepare_cdb(
|
|
case VERIFY_16: /* SBC - VRProtect */
|
|
case WRITE_VERIFY: /* SBC - VRProtect */
|
|
case WRITE_VERIFY_12: /* SBC - VRProtect */
|
|
+ case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
|
|
break;
|
|
default:
|
|
cdb[1] &= 0x1f; /* clear logical unit number */
|
|
@@ -2813,7 +2814,7 @@ static int transport_generic_cmd_sequencer(
|
|
/*
|
|
* Check for emulated MI_REPORT_TARGET_PGS.
|
|
*/
|
|
- if (cdb[1] == MI_REPORT_TARGET_PGS &&
|
|
+ if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS &&
|
|
su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
|
|
cmd->execute_task =
|
|
target_emulate_report_target_port_groups;
|
|
@@ -4701,7 +4702,7 @@ int transport_send_check_condition_and_sense(
|
|
/* ILLEGAL REQUEST */
|
|
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
|
/* LOGICAL UNIT COMMUNICATION FAILURE */
|
|
- buffer[offset+SPC_ASC_KEY_OFFSET] = 0x80;
|
|
+ buffer[offset+SPC_ASC_KEY_OFFSET] = 0x08;
|
|
break;
|
|
}
|
|
/*
|
|
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
|
|
index d537431d7e2e..5fe219142d41 100644
|
|
--- a/drivers/tty/serial/8250/8250.c
|
|
+++ b/drivers/tty/serial/8250/8250.c
|
|
@@ -282,6 +282,33 @@ static const struct serial8250_config uart_config[] = {
|
|
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
|
.flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR,
|
|
},
|
|
+ [PORT_BRCM_TRUMANAGE] = {
|
|
+ .name = "TruManage",
|
|
+ .fifo_size = 1,
|
|
+ .tx_loadsz = 1024,
|
|
+ .flags = UART_CAP_HFIFO,
|
|
+ },
|
|
+ [PORT_ALTR_16550_F32] = {
|
|
+ .name = "Altera 16550 FIFO32",
|
|
+ .fifo_size = 32,
|
|
+ .tx_loadsz = 32,
|
|
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
|
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
|
|
+ },
|
|
+ [PORT_ALTR_16550_F64] = {
|
|
+ .name = "Altera 16550 FIFO64",
|
|
+ .fifo_size = 64,
|
|
+ .tx_loadsz = 64,
|
|
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
|
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
|
|
+ },
|
|
+ [PORT_ALTR_16550_F128] = {
|
|
+ .name = "Altera 16550 FIFO128",
|
|
+ .fifo_size = 128,
|
|
+ .tx_loadsz = 128,
|
|
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
|
|
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
|
|
+ },
|
|
};
|
|
|
|
#if defined(CONFIG_MIPS_ALCHEMY)
|
|
@@ -1470,6 +1497,11 @@ void serial8250_tx_chars(struct uart_8250_port *up)
|
|
port->icount.tx++;
|
|
if (uart_circ_empty(xmit))
|
|
break;
|
|
+ if (up->capabilities & UART_CAP_HFIFO) {
|
|
+ if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
|
|
+ BOTH_EMPTY)
|
|
+ break;
|
|
+ }
|
|
} while (--count > 0);
|
|
|
|
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
|
|
@@ -2641,7 +2673,7 @@ serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
|
|
if (ser->irq >= nr_irqs || ser->irq < 0 ||
|
|
ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
|
|
ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
|
|
- ser->type == PORT_STARTECH)
|
|
+ ser->type == PORT_STARTECH || uart_config[ser->type].name == NULL)
|
|
return -EINVAL;
|
|
return 0;
|
|
}
|
|
@@ -2651,7 +2683,7 @@ serial8250_type(struct uart_port *port)
|
|
{
|
|
int type = port->type;
|
|
|
|
- if (type >= ARRAY_SIZE(uart_config))
|
|
+ if (type >= ARRAY_SIZE(uart_config) || uart_config[type].name == NULL)
|
|
type = 0;
|
|
return uart_config[type].name;
|
|
}
|
|
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
|
|
index 2868a1da254d..b37147c45c5c 100644
|
|
--- a/drivers/tty/serial/8250/8250.h
|
|
+++ b/drivers/tty/serial/8250/8250.h
|
|
@@ -69,6 +69,7 @@ struct serial8250_config {
|
|
#define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */
|
|
#define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */
|
|
#define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */
|
|
+#define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */
|
|
|
|
#define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */
|
|
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
|
|
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
|
|
index fdc669cbf7c5..c48cf891e6bc 100644
|
|
--- a/drivers/tty/serial/8250/8250_pci.c
|
|
+++ b/drivers/tty/serial/8250/8250_pci.c
|
|
@@ -1077,6 +1077,18 @@ pci_omegapci_setup(struct serial_private *priv,
|
|
return setup_port(priv, port, 2, idx * 8, 0);
|
|
}
|
|
|
|
+static int
|
|
+pci_brcm_trumanage_setup(struct serial_private *priv,
|
|
+ const struct pciserial_board *board,
|
|
+ struct uart_8250_port *port, int idx)
|
|
+{
|
|
+ int ret = pci_default_setup(priv, board, port, idx);
|
|
+
|
|
+ port->port.type = PORT_BRCM_TRUMANAGE;
|
|
+ port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
static int skip_tx_en_setup(struct serial_private *priv,
|
|
const struct pciserial_board *board,
|
|
struct uart_port *port, int idx)
|
|
@@ -1151,9 +1163,11 @@ pci_xr17c154_setup(struct serial_private *priv,
|
|
#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6
|
|
#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
|
|
#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
|
|
+#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
|
|
|
|
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
|
|
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
|
|
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
|
|
|
|
/*
|
|
* Master list of serial port init/setup/exit quirks.
|
|
@@ -1425,15 +1439,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|
},
|
|
{
|
|
.vendor = PCI_VENDOR_ID_PLX,
|
|
- .device = PCI_DEVICE_ID_PLX_9050,
|
|
- .subvendor = PCI_VENDOR_ID_PLX,
|
|
- .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
|
|
- .init = pci_plx9050_init,
|
|
- .setup = pci_default_setup,
|
|
- .exit = __devexit_p(pci_plx9050_exit),
|
|
- },
|
|
- {
|
|
- .vendor = PCI_VENDOR_ID_PLX,
|
|
.device = PCI_DEVICE_ID_PLX_ROMULUS,
|
|
.subvendor = PCI_VENDOR_ID_PLX,
|
|
.subdevice = PCI_DEVICE_ID_PLX_ROMULUS,
|
|
@@ -1692,6 +1697,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
|
|
.setup = pci_omegapci_setup,
|
|
},
|
|
/*
|
|
+ * Broadcom TruManage (NetXtreme)
|
|
+ */
|
|
+ {
|
|
+ .vendor = PCI_VENDOR_ID_BROADCOM,
|
|
+ .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
|
|
+ .subvendor = PCI_ANY_ID,
|
|
+ .subdevice = PCI_ANY_ID,
|
|
+ .setup = pci_brcm_trumanage_setup,
|
|
+ },
|
|
+
|
|
+ /*
|
|
* Default "match everything" terminator entry
|
|
*/
|
|
{
|
|
@@ -1880,6 +1896,7 @@ enum pci_board_num_t {
|
|
pbn_ce4100_1_115200,
|
|
pbn_omegapci,
|
|
pbn_NETMOS9900_2s_115200,
|
|
+ pbn_brcm_trumanage,
|
|
};
|
|
|
|
/*
|
|
@@ -2586,6 +2603,12 @@ static struct pciserial_board pci_boards[] __devinitdata = {
|
|
.num_ports = 2,
|
|
.base_baud = 115200,
|
|
},
|
|
+ [pbn_brcm_trumanage] = {
|
|
+ .flags = FL_BASE0,
|
|
+ .num_ports = 1,
|
|
+ .reg_shift = 2,
|
|
+ .base_baud = 115200,
|
|
+ },
|
|
};
|
|
|
|
static const struct pci_device_id softmodem_blacklist[] = {
|
|
@@ -3109,7 +3132,12 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
|
PCI_VENDOR_ID_PLX,
|
|
PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
|
|
- pbn_b0_4_115200 },
|
|
+ pbn_b2_4_115200 },
|
|
+ /* Unknown card - subdevice 0x1588 */
|
|
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
|
+ PCI_VENDOR_ID_PLX,
|
|
+ PCI_SUBDEVICE_ID_UNKNOWN_0x1588, 0, 0,
|
|
+ pbn_b2_8_115200 },
|
|
{ PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
|
|
PCI_SUBVENDOR_ID_KEYSPAN,
|
|
PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
|
|
@@ -4143,6 +4171,13 @@ static struct pci_device_id serial_pci_tbl[] = {
|
|
pbn_omegapci },
|
|
|
|
/*
|
|
+ * Broadcom TruManage
|
|
+ */
|
|
+ { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
|
|
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
|
|
+ pbn_brcm_trumanage },
|
|
+
|
|
+ /*
|
|
* These entries match devices with class COMMUNICATION_SERIAL,
|
|
* COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL
|
|
*/
|
|
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
|
|
index e8c9cee07d00..6563cad09293 100644
|
|
--- a/drivers/tty/serial/of_serial.c
|
|
+++ b/drivers/tty/serial/of_serial.c
|
|
@@ -182,6 +182,12 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = {
|
|
{ .compatible = "ns16750", .data = (void *)PORT_16750, },
|
|
{ .compatible = "ns16850", .data = (void *)PORT_16850, },
|
|
{ .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
|
|
+ { .compatible = "altr,16550-FIFO32",
|
|
+ .data = (void *)PORT_ALTR_16550_F32, },
|
|
+ { .compatible = "altr,16550-FIFO64",
|
|
+ .data = (void *)PORT_ALTR_16550_F64, },
|
|
+ { .compatible = "altr,16550-FIFO128",
|
|
+ .data = (void *)PORT_ALTR_16550_F128, },
|
|
#ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
|
|
{ .compatible = "ibm,qpace-nwp-serial",
|
|
.data = (void *)PORT_NWPSERIAL, },
|
|
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
|
|
index 2e99f7959b96..e78d2a6b4083 100644
|
|
--- a/drivers/tty/serial/pch_uart.c
|
|
+++ b/drivers/tty/serial/pch_uart.c
|
|
@@ -646,11 +646,12 @@ static int dma_push_rx(struct eg20t_port *priv, int size)
|
|
dev_warn(port->dev, "Rx overrun: dropping %u bytes\n",
|
|
size - room);
|
|
if (!room)
|
|
- return room;
|
|
+ goto out;
|
|
|
|
tty_insert_flip_string(tty, sg_virt(&priv->sg_rx), size);
|
|
|
|
port->icount.rx += room;
|
|
+out:
|
|
tty_kref_put(tty);
|
|
|
|
return room;
|
|
@@ -1064,6 +1065,8 @@ static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr)
|
|
if (tty == NULL) {
|
|
for (i = 0; error_msg[i] != NULL; i++)
|
|
dev_err(&priv->pdev->dev, error_msg[i]);
|
|
+ } else {
|
|
+ tty_kref_put(tty);
|
|
}
|
|
}
|
|
|
|
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
|
|
index 6c9b7cd6778a..4f02f9ce05c5 100644
|
|
--- a/drivers/tty/tty_buffer.c
|
|
+++ b/drivers/tty/tty_buffer.c
|
|
@@ -114,11 +114,14 @@ static void __tty_buffer_flush(struct tty_struct *tty)
|
|
{
|
|
struct tty_buffer *thead;
|
|
|
|
- while ((thead = tty->buf.head) != NULL) {
|
|
- tty->buf.head = thead->next;
|
|
- tty_buffer_free(tty, thead);
|
|
+ if (tty->buf.head == NULL)
|
|
+ return;
|
|
+ while ((thead = tty->buf.head->next) != NULL) {
|
|
+ tty_buffer_free(tty, tty->buf.head);
|
|
+ tty->buf.head = thead;
|
|
}
|
|
- tty->buf.tail = NULL;
|
|
+ WARN_ON(tty->buf.head != tty->buf.tail);
|
|
+ tty->buf.head->read = tty->buf.head->commit;
|
|
}
|
|
|
|
/**
|
|
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
|
|
index c4d894a95701..35bc3baa8427 100644
|
|
--- a/drivers/usb/core/driver.c
|
|
+++ b/drivers/usb/core/driver.c
|
|
@@ -1708,10 +1708,13 @@ int usb_runtime_suspend(struct device *dev)
|
|
if (status == -EAGAIN || status == -EBUSY)
|
|
usb_mark_last_busy(udev);
|
|
|
|
- /* The PM core reacts badly unless the return code is 0,
|
|
- * -EAGAIN, or -EBUSY, so always return -EBUSY on an error.
|
|
+ /*
|
|
+ * The PM core reacts badly unless the return code is 0,
|
|
+ * -EAGAIN, or -EBUSY, so always return -EBUSY on an error
|
|
+ * (except for root hubs, because they don't suspend through
|
|
+ * an upstream port like other USB devices).
|
|
*/
|
|
- if (status != 0)
|
|
+ if (status != 0 && udev->parent)
|
|
return -EBUSY;
|
|
return status;
|
|
}
|
|
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
|
|
index d2b7327d9de3..e0d4d901e99d 100644
|
|
--- a/drivers/usb/core/hub.c
|
|
+++ b/drivers/usb/core/hub.c
|
|
@@ -1401,8 +1401,19 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
|
desc = intf->cur_altsetting;
|
|
hdev = interface_to_usbdev(intf);
|
|
|
|
- /* Hubs have proper suspend/resume support. */
|
|
- usb_enable_autosuspend(hdev);
|
|
+ /*
|
|
+ * Hubs have proper suspend/resume support, except for root hubs
|
|
+ * where the controller driver doesn't have bus_suspend and
|
|
+ * bus_resume methods.
|
|
+ */
|
|
+ if (hdev->parent) { /* normal device */
|
|
+ usb_enable_autosuspend(hdev);
|
|
+ } else { /* root hub */
|
|
+ const struct hc_driver *drv = bus_to_hcd(hdev->bus)->driver;
|
|
+
|
|
+ if (drv->bus_suspend && drv->bus_resume)
|
|
+ usb_enable_autosuspend(hdev);
|
|
+ }
|
|
|
|
if (hdev->level == MAX_TOPO_LEVEL) {
|
|
dev_err(&intf->dev,
|
|
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
|
|
index 3347e9be9a67..197685852638 100644
|
|
--- a/drivers/usb/host/xhci-mem.c
|
|
+++ b/drivers/usb/host/xhci-mem.c
|
|
@@ -1812,6 +1812,16 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|
kfree(cur_cd);
|
|
}
|
|
|
|
+ num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
|
|
+ for (i = 0; i < num_ports; i++) {
|
|
+ struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
|
|
+ for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
|
|
+ struct list_head *ep = &bwt->interval_bw[j].endpoints;
|
|
+ while (!list_empty(ep))
|
|
+ list_del_init(ep->next);
|
|
+ }
|
|
+ }
|
|
+
|
|
for (i = 1; i < MAX_HC_SLOTS; ++i)
|
|
xhci_free_virt_device(xhci, i);
|
|
|
|
@@ -1852,16 +1862,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
|
|
if (!xhci->rh_bw)
|
|
goto no_bw;
|
|
|
|
- num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
|
|
- for (i = 0; i < num_ports; i++) {
|
|
- struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table;
|
|
- for (j = 0; j < XHCI_MAX_INTERVAL; j++) {
|
|
- struct list_head *ep = &bwt->interval_bw[j].endpoints;
|
|
- while (!list_empty(ep))
|
|
- list_del_init(ep->next);
|
|
- }
|
|
- }
|
|
-
|
|
for (i = 0; i < num_ports; i++) {
|
|
struct xhci_tt_bw_info *tt, *n;
|
|
list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) {
|
|
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
|
|
index 3b2dfe9c5212..bb9f4111d1b8 100644
|
|
--- a/drivers/usb/serial/ftdi_sio.c
|
|
+++ b/drivers/usb/serial/ftdi_sio.c
|
|
@@ -591,6 +591,8 @@ static struct usb_device_id id_table_combined [] = {
|
|
{ USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
|
|
{ USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID),
|
|
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
|
+ { USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
|
|
+ .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
|
|
/*
|
|
* ELV devices:
|
|
*/
|
|
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
|
|
index 993c93df6874..500474c48f4b 100644
|
|
--- a/drivers/usb/serial/ftdi_sio_ids.h
|
|
+++ b/drivers/usb/serial/ftdi_sio_ids.h
|
|
@@ -538,6 +538,11 @@
|
|
*/
|
|
#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */
|
|
|
|
+/*
|
|
+ * NovaTech product ids (FTDI_VID)
|
|
+ */
|
|
+#define FTDI_NT_ORIONLXM_PID 0x7c90 /* OrionLXm Substation Automation Platform */
|
|
+
|
|
|
|
/********************************/
|
|
/** third-party VID/PID combos **/
|
|
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
|
|
index 5cca1b3cb083..51751828562f 100644
|
|
--- a/drivers/usb/serial/io_ti.c
|
|
+++ b/drivers/usb/serial/io_ti.c
|
|
@@ -915,7 +915,7 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
|
|
firmware_rec = (struct ti_i2c_firmware_rec*)i2c_header->Data;
|
|
|
|
i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK;
|
|
- i2c_header->Size = (__u16)buffer_size;
|
|
+ i2c_header->Size = cpu_to_le16(buffer_size);
|
|
i2c_header->CheckSum = cs;
|
|
firmware_rec->Ver_Major = OperationalMajorVersion;
|
|
firmware_rec->Ver_Minor = OperationalMinorVersion;
|
|
diff --git a/drivers/usb/serial/io_usbvend.h b/drivers/usb/serial/io_usbvend.h
|
|
index 51f83fbb73bb..6f6a856bc37c 100644
|
|
--- a/drivers/usb/serial/io_usbvend.h
|
|
+++ b/drivers/usb/serial/io_usbvend.h
|
|
@@ -594,7 +594,7 @@ struct edge_boot_descriptor {
|
|
|
|
struct ti_i2c_desc {
|
|
__u8 Type; // Type of descriptor
|
|
- __u16 Size; // Size of data only not including header
|
|
+ __le16 Size; // Size of data only not including header
|
|
__u8 CheckSum; // Checksum (8 bit sum of data only)
|
|
__u8 Data[0]; // Data starts here
|
|
} __attribute__((packed));
|
|
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
|
|
index e9c113dab5c4..def9ed02bf19 100644
|
|
--- a/drivers/usb/serial/option.c
|
|
+++ b/drivers/usb/serial/option.c
|
|
@@ -161,6 +161,7 @@ static void option_instat_callback(struct urb *urb);
|
|
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000
|
|
#define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001
|
|
#define NOVATELWIRELESS_PRODUCT_E362 0x9010
|
|
+#define NOVATELWIRELESS_PRODUCT_E371 0x9011
|
|
#define NOVATELWIRELESS_PRODUCT_G2 0xA010
|
|
#define NOVATELWIRELESS_PRODUCT_MC551 0xB001
|
|
|
|
@@ -1025,6 +1026,7 @@ static const struct usb_device_id option_ids[] = {
|
|
/* Novatel Ovation MC551 a.k.a. Verizon USB551L */
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
|
|
{ USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
|
|
+ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E371, 0xff, 0xff, 0xff) },
|
|
|
|
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
|
|
{ USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
|
|
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
|
|
index d014727fc8f2..4db777d3dc05 100644
|
|
--- a/fs/nfsd/nfsctl.c
|
|
+++ b/fs/nfsd/nfsctl.c
|
|
@@ -213,6 +213,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
|
|
struct sockaddr *sap = (struct sockaddr *)&address;
|
|
size_t salen = sizeof(address);
|
|
char *fo_path;
|
|
+ struct net *net = file->f_dentry->d_sb->s_fs_info;
|
|
|
|
/* sanity check */
|
|
if (size == 0)
|
|
@@ -225,7 +226,7 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
|
|
if (qword_get(&buf, fo_path, size) < 0)
|
|
return -EINVAL;
|
|
|
|
- if (rpc_pton(&init_net, fo_path, size, sap, salen) == 0)
|
|
+ if (rpc_pton(net, fo_path, size, sap, salen) == 0)
|
|
return -EINVAL;
|
|
|
|
return nlmsvc_unlock_all_by_ip(sap);
|
|
@@ -389,6 +390,8 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
|
|
{
|
|
char *mesg = buf;
|
|
int rv;
|
|
+ struct net *net = file->f_dentry->d_sb->s_fs_info;
|
|
+
|
|
if (size > 0) {
|
|
int newthreads;
|
|
rv = get_int(&mesg, &newthreads);
|
|
@@ -396,7 +399,7 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size)
|
|
return rv;
|
|
if (newthreads < 0)
|
|
return -EINVAL;
|
|
- rv = nfsd_svc(NFS_PORT, newthreads);
|
|
+ rv = nfsd_svc(NFS_PORT, newthreads, net);
|
|
if (rv < 0)
|
|
return rv;
|
|
} else
|
|
@@ -438,6 +441,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
|
|
int len;
|
|
int npools;
|
|
int *nthreads;
|
|
+ struct net *net = file->f_dentry->d_sb->s_fs_info;
|
|
|
|
mutex_lock(&nfsd_mutex);
|
|
npools = nfsd_nrpools();
|
|
@@ -468,7 +472,7 @@ static ssize_t write_pool_threads(struct file *file, char *buf, size_t size)
|
|
if (nthreads[i] < 0)
|
|
goto out_free;
|
|
}
|
|
- rv = nfsd_set_nrthreads(i, nthreads);
|
|
+ rv = nfsd_set_nrthreads(i, nthreads, net);
|
|
if (rv)
|
|
goto out_free;
|
|
}
|
|
@@ -647,17 +651,21 @@ static ssize_t __write_ports_names(char *buf)
|
|
* a socket of a supported family/protocol, and we use it as an
|
|
* nfsd listener.
|
|
*/
|
|
-static ssize_t __write_ports_addfd(char *buf)
|
|
+static ssize_t __write_ports_addfd(char *buf, struct net *net)
|
|
{
|
|
char *mesg = buf;
|
|
int fd, err;
|
|
- struct net *net = &init_net;
|
|
|
|
err = get_int(&mesg, &fd);
|
|
if (err != 0 || fd < 0)
|
|
return -EINVAL;
|
|
|
|
- err = nfsd_create_serv();
|
|
+ if (svc_alien_sock(net, fd)) {
|
|
+ printk(KERN_ERR "%s: socket net is different to NFSd's one\n", __func__);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ err = nfsd_create_serv(net);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
@@ -695,12 +703,11 @@ static ssize_t __write_ports_delfd(char *buf)
|
|
* A transport listener is added by writing it's transport name and
|
|
* a port number.
|
|
*/
|
|
-static ssize_t __write_ports_addxprt(char *buf)
|
|
+static ssize_t __write_ports_addxprt(char *buf, struct net *net)
|
|
{
|
|
char transport[16];
|
|
struct svc_xprt *xprt;
|
|
int port, err;
|
|
- struct net *net = &init_net;
|
|
|
|
if (sscanf(buf, "%15s %4u", transport, &port) != 2)
|
|
return -EINVAL;
|
|
@@ -708,7 +715,7 @@ static ssize_t __write_ports_addxprt(char *buf)
|
|
if (port < 1 || port > USHRT_MAX)
|
|
return -EINVAL;
|
|
|
|
- err = nfsd_create_serv();
|
|
+ err = nfsd_create_serv(net);
|
|
if (err != 0)
|
|
return err;
|
|
|
|
@@ -740,7 +747,7 @@ out_err:
|
|
* A transport listener is removed by writing a "-", it's transport
|
|
* name, and it's port number.
|
|
*/
|
|
-static ssize_t __write_ports_delxprt(char *buf)
|
|
+static ssize_t __write_ports_delxprt(char *buf, struct net *net)
|
|
{
|
|
struct svc_xprt *xprt;
|
|
char transport[16];
|
|
@@ -752,7 +759,7 @@ static ssize_t __write_ports_delxprt(char *buf)
|
|
if (port < 1 || port > USHRT_MAX || nfsd_serv == NULL)
|
|
return -EINVAL;
|
|
|
|
- xprt = svc_find_xprt(nfsd_serv, transport, &init_net, AF_UNSPEC, port);
|
|
+ xprt = svc_find_xprt(nfsd_serv, transport, net, AF_UNSPEC, port);
|
|
if (xprt == NULL)
|
|
return -ENOTCONN;
|
|
|
|
@@ -761,22 +768,23 @@ static ssize_t __write_ports_delxprt(char *buf)
|
|
return 0;
|
|
}
|
|
|
|
-static ssize_t __write_ports(struct file *file, char *buf, size_t size)
|
|
+static ssize_t __write_ports(struct file *file, char *buf, size_t size,
|
|
+ struct net *net)
|
|
{
|
|
if (size == 0)
|
|
return __write_ports_names(buf);
|
|
|
|
if (isdigit(buf[0]))
|
|
- return __write_ports_addfd(buf);
|
|
+ return __write_ports_addfd(buf, net);
|
|
|
|
if (buf[0] == '-' && isdigit(buf[1]))
|
|
return __write_ports_delfd(buf);
|
|
|
|
if (isalpha(buf[0]))
|
|
- return __write_ports_addxprt(buf);
|
|
+ return __write_ports_addxprt(buf, net);
|
|
|
|
if (buf[0] == '-' && isalpha(buf[1]))
|
|
- return __write_ports_delxprt(buf);
|
|
+ return __write_ports_delxprt(buf, net);
|
|
|
|
return -EINVAL;
|
|
}
|
|
@@ -855,9 +863,10 @@ static ssize_t __write_ports(struct file *file, char *buf, size_t size)
|
|
static ssize_t write_ports(struct file *file, char *buf, size_t size)
|
|
{
|
|
ssize_t rv;
|
|
+ struct net *net = file->f_dentry->d_sb->s_fs_info;
|
|
|
|
mutex_lock(&nfsd_mutex);
|
|
- rv = __write_ports(file, buf, size);
|
|
+ rv = __write_ports(file, buf, size, net);
|
|
mutex_unlock(&nfsd_mutex);
|
|
return rv;
|
|
}
|
|
@@ -1092,20 +1101,35 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
|
|
#endif
|
|
/* last one */ {""}
|
|
};
|
|
- return simple_fill_super(sb, 0x6e667364, nfsd_files);
|
|
+ struct net *net = data;
|
|
+ int ret;
|
|
+
|
|
+ ret = simple_fill_super(sb, 0x6e667364, nfsd_files);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+ sb->s_fs_info = get_net(net);
|
|
+ return 0;
|
|
}
|
|
|
|
static struct dentry *nfsd_mount(struct file_system_type *fs_type,
|
|
int flags, const char *dev_name, void *data)
|
|
{
|
|
- return mount_single(fs_type, flags, data, nfsd_fill_super);
|
|
+ return mount_ns(fs_type, flags, current->nsproxy->net_ns, nfsd_fill_super);
|
|
+}
|
|
+
|
|
+static void nfsd_umount(struct super_block *sb)
|
|
+{
|
|
+ struct net *net = sb->s_fs_info;
|
|
+
|
|
+ kill_litter_super(sb);
|
|
+ put_net(net);
|
|
}
|
|
|
|
static struct file_system_type nfsd_fs_type = {
|
|
.owner = THIS_MODULE,
|
|
.name = "nfsd",
|
|
.mount = nfsd_mount,
|
|
- .kill_sb = kill_litter_super,
|
|
+ .kill_sb = nfsd_umount,
|
|
};
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h
|
|
index 1336a6512cdc..a0989a269262 100644
|
|
--- a/fs/nfsd/nfsd.h
|
|
+++ b/fs/nfsd/nfsd.h
|
|
@@ -65,13 +65,13 @@ extern const struct seq_operations nfs_exports_op;
|
|
/*
|
|
* Function prototypes.
|
|
*/
|
|
-int nfsd_svc(unsigned short port, int nrservs);
|
|
+int nfsd_svc(unsigned short port, int nrservs, struct net *net);
|
|
int nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp);
|
|
|
|
int nfsd_nrthreads(void);
|
|
int nfsd_nrpools(void);
|
|
int nfsd_get_nrthreads(int n, int *);
|
|
-int nfsd_set_nrthreads(int n, int *);
|
|
+int nfsd_set_nrthreads(int n, int *, struct net *);
|
|
|
|
static inline void nfsd_destroy(struct net *net)
|
|
{
|
|
@@ -101,7 +101,7 @@ enum vers_op {NFSD_SET, NFSD_CLEAR, NFSD_TEST, NFSD_AVAIL };
|
|
int nfsd_vers(int vers, enum vers_op change);
|
|
int nfsd_minorversion(u32 minorversion, enum vers_op change);
|
|
void nfsd_reset_versions(void);
|
|
-int nfsd_create_serv(void);
|
|
+int nfsd_create_serv(struct net *net);
|
|
|
|
extern int nfsd_max_blksize;
|
|
|
|
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
|
|
index 25d839ed0ae1..ed8eedfbdb63 100644
|
|
--- a/fs/nfsd/nfssvc.c
|
|
+++ b/fs/nfsd/nfssvc.c
|
|
@@ -182,18 +182,18 @@ int nfsd_nrthreads(void)
|
|
return rv;
|
|
}
|
|
|
|
-static int nfsd_init_socks(int port)
|
|
+static int nfsd_init_socks(int port, struct net *net)
|
|
{
|
|
int error;
|
|
if (!list_empty(&nfsd_serv->sv_permsocks))
|
|
return 0;
|
|
|
|
- error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port,
|
|
+ error = svc_create_xprt(nfsd_serv, "udp", net, PF_INET, port,
|
|
SVC_SOCK_DEFAULTS);
|
|
if (error < 0)
|
|
return error;
|
|
|
|
- error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port,
|
|
+ error = svc_create_xprt(nfsd_serv, "tcp", net, PF_INET, port,
|
|
SVC_SOCK_DEFAULTS);
|
|
if (error < 0)
|
|
return error;
|
|
@@ -203,7 +203,7 @@ static int nfsd_init_socks(int port)
|
|
|
|
static bool nfsd_up = false;
|
|
|
|
-static int nfsd_startup(unsigned short port, int nrservs)
|
|
+static int nfsd_startup(unsigned short port, int nrservs, struct net *net)
|
|
{
|
|
int ret;
|
|
|
|
@@ -217,10 +217,10 @@ static int nfsd_startup(unsigned short port, int nrservs)
|
|
ret = nfsd_racache_init(2*nrservs);
|
|
if (ret)
|
|
return ret;
|
|
- ret = nfsd_init_socks(port);
|
|
+ ret = nfsd_init_socks(port, net);
|
|
if (ret)
|
|
goto out_racache;
|
|
- ret = lockd_up(&init_net);
|
|
+ ret = lockd_up(net);
|
|
if (ret)
|
|
goto out_racache;
|
|
ret = nfs4_state_start();
|
|
@@ -229,13 +229,13 @@ static int nfsd_startup(unsigned short port, int nrservs)
|
|
nfsd_up = true;
|
|
return 0;
|
|
out_lockd:
|
|
- lockd_down(&init_net);
|
|
+ lockd_down(net);
|
|
out_racache:
|
|
nfsd_racache_shutdown();
|
|
return ret;
|
|
}
|
|
|
|
-static void nfsd_shutdown(void)
|
|
+static void nfsd_shutdown(struct net *net)
|
|
{
|
|
/*
|
|
* write_ports can create the server without actually starting
|
|
@@ -246,14 +246,14 @@ static void nfsd_shutdown(void)
|
|
if (!nfsd_up)
|
|
return;
|
|
nfs4_state_shutdown();
|
|
- lockd_down(&init_net);
|
|
+ lockd_down(net);
|
|
nfsd_racache_shutdown();
|
|
nfsd_up = false;
|
|
}
|
|
|
|
static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
|
|
{
|
|
- nfsd_shutdown();
|
|
+ nfsd_shutdown(net);
|
|
|
|
svc_rpcb_cleanup(serv, net);
|
|
|
|
@@ -326,10 +326,9 @@ static int nfsd_get_default_max_blksize(void)
|
|
return ret;
|
|
}
|
|
|
|
-int nfsd_create_serv(void)
|
|
+int nfsd_create_serv(struct net *net)
|
|
{
|
|
int error;
|
|
- struct net *net = &init_net;
|
|
|
|
WARN_ON(!mutex_is_locked(&nfsd_mutex));
|
|
if (nfsd_serv) {
|
|
@@ -375,12 +374,11 @@ int nfsd_get_nrthreads(int n, int *nthreads)
|
|
return 0;
|
|
}
|
|
|
|
-int nfsd_set_nrthreads(int n, int *nthreads)
|
|
+int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
|
|
{
|
|
int i = 0;
|
|
int tot = 0;
|
|
int err = 0;
|
|
- struct net *net = &init_net;
|
|
|
|
WARN_ON(!mutex_is_locked(&nfsd_mutex));
|
|
|
|
@@ -435,11 +433,10 @@ int nfsd_set_nrthreads(int n, int *nthreads)
|
|
* this is the first time nrservs is nonzero.
|
|
*/
|
|
int
|
|
-nfsd_svc(unsigned short port, int nrservs)
|
|
+nfsd_svc(unsigned short port, int nrservs, struct net *net)
|
|
{
|
|
int error;
|
|
bool nfsd_up_before;
|
|
- struct net *net = &init_net;
|
|
|
|
mutex_lock(&nfsd_mutex);
|
|
dprintk("nfsd: creating service\n");
|
|
@@ -451,13 +448,13 @@ nfsd_svc(unsigned short port, int nrservs)
|
|
if (nrservs == 0 && nfsd_serv == NULL)
|
|
goto out;
|
|
|
|
- error = nfsd_create_serv();
|
|
+ error = nfsd_create_serv(net);
|
|
if (error)
|
|
goto out;
|
|
|
|
nfsd_up_before = nfsd_up;
|
|
|
|
- error = nfsd_startup(port, nrservs);
|
|
+ error = nfsd_startup(port, nrservs, net);
|
|
if (error)
|
|
goto out_destroy;
|
|
error = svc_set_num_threads(nfsd_serv, NULL, nrservs);
|
|
@@ -470,7 +467,7 @@ nfsd_svc(unsigned short port, int nrservs)
|
|
error = nfsd_serv->sv_nrthreads - 1;
|
|
out_shutdown:
|
|
if (error < 0 && !nfsd_up_before)
|
|
- nfsd_shutdown();
|
|
+ nfsd_shutdown(net);
|
|
out_destroy:
|
|
nfsd_destroy(net); /* Release server */
|
|
out:
|
|
@@ -486,6 +483,8 @@ static int
|
|
nfsd(void *vrqstp)
|
|
{
|
|
struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp;
|
|
+ struct svc_xprt *perm_sock = list_entry(rqstp->rq_server->sv_permsocks.next, typeof(struct svc_xprt), xpt_list);
|
|
+ struct net *net = perm_sock->xpt_net;
|
|
int err, preverr = 0;
|
|
|
|
/* Lock module and set up kernel thread */
|
|
@@ -560,7 +559,7 @@ out:
|
|
/* Release the thread */
|
|
svc_exit_thread(rqstp);
|
|
|
|
- nfsd_destroy(&init_net);
|
|
+ nfsd_destroy(net);
|
|
|
|
/* Release module */
|
|
mutex_unlock(&nfsd_mutex);
|
|
@@ -671,7 +670,7 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file)
|
|
int nfsd_pool_stats_release(struct inode *inode, struct file *file)
|
|
{
|
|
int ret = seq_release(inode, file);
|
|
- struct net *net = &init_net;
|
|
+ struct net *net = inode->i_sb->s_fs_info;
|
|
|
|
mutex_lock(&nfsd_mutex);
|
|
/* this function really, really should have been called svc_put() */
|
|
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
|
|
index d3999b4e26cc..e186e3c28ed8 100644
|
|
--- a/include/linux/highmem.h
|
|
+++ b/include/linux/highmem.h
|
|
@@ -39,10 +39,17 @@ extern unsigned long totalhigh_pages;
|
|
|
|
void kmap_flush_unused(void);
|
|
|
|
+struct page *kmap_to_page(void *addr);
|
|
+
|
|
#else /* CONFIG_HIGHMEM */
|
|
|
|
static inline unsigned int nr_free_highpages(void) { return 0; }
|
|
|
|
+static inline struct page *kmap_to_page(void *addr)
|
|
+{
|
|
+ return virt_to_page(addr);
|
|
+}
|
|
+
|
|
#define totalhigh_pages 0UL
|
|
|
|
#ifndef ARCH_HAS_KMAP
|
|
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
|
|
index d7dbf4ec89d2..0a7e4f4201b1 100644
|
|
--- a/include/linux/pci_ids.h
|
|
+++ b/include/linux/pci_ids.h
|
|
@@ -752,6 +752,7 @@
|
|
#define PCI_DEVICE_ID_HP_CISSD 0x3238
|
|
#define PCI_DEVICE_ID_HP_CISSE 0x323a
|
|
#define PCI_DEVICE_ID_HP_CISSF 0x323b
|
|
+#define PCI_DEVICE_ID_HP_CISSH 0x323c
|
|
#define PCI_DEVICE_ID_HP_ZX2_IOC 0x4031
|
|
|
|
#define PCI_VENDOR_ID_PCTECH 0x1042
|
|
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
|
|
index 2db407a40051..60f55645af32 100644
|
|
--- a/include/linux/serial_core.h
|
|
+++ b/include/linux/serial_core.h
|
|
@@ -47,7 +47,11 @@
|
|
#define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */
|
|
#define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */
|
|
#define PORT_XR17D15X 21 /* Exar XR17D15x UART */
|
|
-#define PORT_MAX_8250 21 /* max port ID */
|
|
+#define PORT_BRCM_TRUMANAGE 25
|
|
+#define PORT_ALTR_16550_F32 26 /* Altera 16550 UART with 32 FIFOs */
|
|
+#define PORT_ALTR_16550_F64 27 /* Altera 16550 UART with 64 FIFOs */
|
|
+#define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
|
|
+#define PORT_MAX_8250 28 /* max port ID */
|
|
|
|
/*
|
|
* ARM specific type numbers. These are not currently guaranteed
|
|
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
|
|
index cb4ac69e1f33..e4c6cec9ff1a 100644
|
|
--- a/include/linux/sunrpc/svcsock.h
|
|
+++ b/include/linux/sunrpc/svcsock.h
|
|
@@ -42,6 +42,7 @@ void svc_sock_update_bufs(struct svc_serv *serv);
|
|
int svc_sock_names(struct svc_serv *serv, char *buf,
|
|
const size_t buflen,
|
|
const char *toclose);
|
|
+bool svc_alien_sock(struct net *net, int fd);
|
|
int svc_addsock(struct svc_serv *serv, const int fd,
|
|
char *name_return, const size_t len);
|
|
void svc_init_xprt_sock(void);
|
|
diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h
|
|
index bdf4b0034739..82e12ad3d97f 100644
|
|
--- a/include/linux/virtio_console.h
|
|
+++ b/include/linux/virtio_console.h
|
|
@@ -39,7 +39,7 @@
|
|
#define VIRTIO_CONSOLE_F_SIZE 0 /* Does host provide console size? */
|
|
#define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */
|
|
|
|
-#define VIRTIO_CONSOLE_BAD_ID (~(u32)0)
|
|
+#define VIRTIO_CONSOLE_BAD_ID (~(__u32)0)
|
|
|
|
struct virtio_console_config {
|
|
/* colums of the screens */
|
|
diff --git a/kernel/cpu.c b/kernel/cpu.c
|
|
index 26feaa985a52..04671bf91c12 100644
|
|
--- a/kernel/cpu.c
|
|
+++ b/kernel/cpu.c
|
|
@@ -631,10 +631,12 @@ void set_cpu_present(unsigned int cpu, bool present)
|
|
|
|
void set_cpu_online(unsigned int cpu, bool online)
|
|
{
|
|
- if (online)
|
|
+ if (online) {
|
|
cpumask_set_cpu(cpu, to_cpumask(cpu_online_bits));
|
|
- else
|
|
+ cpumask_set_cpu(cpu, to_cpumask(cpu_active_bits));
|
|
+ } else {
|
|
cpumask_clear_cpu(cpu, to_cpumask(cpu_online_bits));
|
|
+ }
|
|
}
|
|
|
|
void set_cpu_active(unsigned int cpu, bool active)
|
|
diff --git a/kernel/events/core.c b/kernel/events/core.c
|
|
index e39346fb2e91..685ce46b2aff 100644
|
|
--- a/kernel/events/core.c
|
|
+++ b/kernel/events/core.c
|
|
@@ -1196,6 +1196,11 @@ group_sched_out(struct perf_event *group_event,
|
|
cpuctx->exclusive = 0;
|
|
}
|
|
|
|
+struct remove_event {
|
|
+ struct perf_event *event;
|
|
+ bool detach_group;
|
|
+};
|
|
+
|
|
/*
|
|
* Cross CPU call to remove a performance event
|
|
*
|
|
@@ -1204,12 +1209,15 @@ group_sched_out(struct perf_event *group_event,
|
|
*/
|
|
static int __perf_remove_from_context(void *info)
|
|
{
|
|
- struct perf_event *event = info;
|
|
+ struct remove_event *re = info;
|
|
+ struct perf_event *event = re->event;
|
|
struct perf_event_context *ctx = event->ctx;
|
|
struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
|
|
|
|
raw_spin_lock(&ctx->lock);
|
|
event_sched_out(event, cpuctx, ctx);
|
|
+ if (re->detach_group)
|
|
+ perf_group_detach(event);
|
|
list_del_event(event, ctx);
|
|
if (!ctx->nr_events && cpuctx->task_ctx == ctx) {
|
|
ctx->is_active = 0;
|
|
@@ -1234,10 +1242,14 @@ static int __perf_remove_from_context(void *info)
|
|
* When called from perf_event_exit_task, it's OK because the
|
|
* context has been detached from its task.
|
|
*/
|
|
-static void perf_remove_from_context(struct perf_event *event)
|
|
+static void perf_remove_from_context(struct perf_event *event, bool detach_group)
|
|
{
|
|
struct perf_event_context *ctx = event->ctx;
|
|
struct task_struct *task = ctx->task;
|
|
+ struct remove_event re = {
|
|
+ .event = event,
|
|
+ .detach_group = detach_group,
|
|
+ };
|
|
|
|
lockdep_assert_held(&ctx->mutex);
|
|
|
|
@@ -1246,12 +1258,12 @@ static void perf_remove_from_context(struct perf_event *event)
|
|
* Per cpu events are removed via an smp call and
|
|
* the removal is always successful.
|
|
*/
|
|
- cpu_function_call(event->cpu, __perf_remove_from_context, event);
|
|
+ cpu_function_call(event->cpu, __perf_remove_from_context, &re);
|
|
return;
|
|
}
|
|
|
|
retry:
|
|
- if (!task_function_call(task, __perf_remove_from_context, event))
|
|
+ if (!task_function_call(task, __perf_remove_from_context, &re))
|
|
return;
|
|
|
|
raw_spin_lock_irq(&ctx->lock);
|
|
@@ -1268,6 +1280,8 @@ retry:
|
|
* Since the task isn't running, its safe to remove the event, us
|
|
* holding the ctx->lock ensures the task won't get scheduled in.
|
|
*/
|
|
+ if (detach_group)
|
|
+ perf_group_detach(event);
|
|
list_del_event(event, ctx);
|
|
raw_spin_unlock_irq(&ctx->lock);
|
|
}
|
|
@@ -2962,10 +2976,7 @@ int perf_event_release_kernel(struct perf_event *event)
|
|
* to trigger the AB-BA case.
|
|
*/
|
|
mutex_lock_nested(&ctx->mutex, SINGLE_DEPTH_NESTING);
|
|
- raw_spin_lock_irq(&ctx->lock);
|
|
- perf_group_detach(event);
|
|
- raw_spin_unlock_irq(&ctx->lock);
|
|
- perf_remove_from_context(event);
|
|
+ perf_remove_from_context(event, true);
|
|
mutex_unlock(&ctx->mutex);
|
|
|
|
free_event(event);
|
|
@@ -4854,6 +4865,9 @@ struct swevent_htable {
|
|
|
|
/* Recursion avoidance in each contexts */
|
|
int recursion[PERF_NR_CONTEXTS];
|
|
+
|
|
+ /* Keeps track of cpu being initialized/exited */
|
|
+ bool online;
|
|
};
|
|
|
|
static DEFINE_PER_CPU(struct swevent_htable, swevent_htable);
|
|
@@ -5101,8 +5115,14 @@ static int perf_swevent_add(struct perf_event *event, int flags)
|
|
hwc->state = !(flags & PERF_EF_START);
|
|
|
|
head = find_swevent_head(swhash, event);
|
|
- if (WARN_ON_ONCE(!head))
|
|
+ if (!head) {
|
|
+ /*
|
|
+ * We can race with cpu hotplug code. Do not
|
|
+ * WARN if the cpu just got unplugged.
|
|
+ */
|
|
+ WARN_ON_ONCE(swhash->online);
|
|
return -EINVAL;
|
|
+ }
|
|
|
|
hlist_add_head_rcu(&event->hlist_entry, head);
|
|
|
|
@@ -6347,6 +6367,9 @@ SYSCALL_DEFINE5(perf_event_open,
|
|
if (attr.freq) {
|
|
if (attr.sample_freq > sysctl_perf_event_sample_rate)
|
|
return -EINVAL;
|
|
+ } else {
|
|
+ if (attr.sample_period & (1ULL << 63))
|
|
+ return -EINVAL;
|
|
}
|
|
|
|
/*
|
|
@@ -6493,7 +6516,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
|
struct perf_event_context *gctx = group_leader->ctx;
|
|
|
|
mutex_lock(&gctx->mutex);
|
|
- perf_remove_from_context(group_leader);
|
|
+ perf_remove_from_context(group_leader, false);
|
|
|
|
/*
|
|
* Removing from the context ends up with disabled
|
|
@@ -6503,7 +6526,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
|
perf_event__state_init(group_leader);
|
|
list_for_each_entry(sibling, &group_leader->sibling_list,
|
|
group_entry) {
|
|
- perf_remove_from_context(sibling);
|
|
+ perf_remove_from_context(sibling, false);
|
|
perf_event__state_init(sibling);
|
|
put_ctx(gctx);
|
|
}
|
|
@@ -6656,13 +6679,7 @@ __perf_event_exit_task(struct perf_event *child_event,
|
|
struct perf_event_context *child_ctx,
|
|
struct task_struct *child)
|
|
{
|
|
- if (child_event->parent) {
|
|
- raw_spin_lock_irq(&child_ctx->lock);
|
|
- perf_group_detach(child_event);
|
|
- raw_spin_unlock_irq(&child_ctx->lock);
|
|
- }
|
|
-
|
|
- perf_remove_from_context(child_event);
|
|
+ perf_remove_from_context(child_event, !!child_event->parent);
|
|
|
|
/*
|
|
* It can happen that the parent exits first, and has events
|
|
@@ -7124,6 +7141,7 @@ static void __cpuinit perf_event_init_cpu(int cpu)
|
|
struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu);
|
|
|
|
mutex_lock(&swhash->hlist_mutex);
|
|
+ swhash->online = true;
|
|
if (swhash->hlist_refcount > 0) {
|
|
struct swevent_hlist *hlist;
|
|
|
|
@@ -7146,14 +7164,14 @@ static void perf_pmu_rotate_stop(struct pmu *pmu)
|
|
|
|
static void __perf_event_exit_context(void *__info)
|
|
{
|
|
+ struct remove_event re = { .detach_group = false };
|
|
struct perf_event_context *ctx = __info;
|
|
- struct perf_event *event;
|
|
|
|
perf_pmu_rotate_stop(ctx->pmu);
|
|
|
|
rcu_read_lock();
|
|
- list_for_each_entry_rcu(event, &ctx->event_list, event_entry)
|
|
- __perf_remove_from_context(event);
|
|
+ list_for_each_entry_rcu(re.event, &ctx->event_list, event_entry)
|
|
+ __perf_remove_from_context(&re);
|
|
rcu_read_unlock();
|
|
}
|
|
|
|
@@ -7181,6 +7199,7 @@ static void perf_event_exit_cpu(int cpu)
|
|
perf_event_exit_cpu_context(cpu);
|
|
|
|
mutex_lock(&swhash->hlist_mutex);
|
|
+ swhash->online = false;
|
|
swevent_hlist_release(swhash);
|
|
mutex_unlock(&swhash->hlist_mutex);
|
|
}
|
|
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
|
|
index e01398f0a52e..af837d82634e 100644
|
|
--- a/kernel/sched/core.c
|
|
+++ b/kernel/sched/core.c
|
|
@@ -5656,7 +5656,6 @@ static int __cpuinit sched_cpu_active(struct notifier_block *nfb,
|
|
unsigned long action, void *hcpu)
|
|
{
|
|
switch (action & ~CPU_TASKS_FROZEN) {
|
|
- case CPU_STARTING:
|
|
case CPU_DOWN_FAILED:
|
|
set_cpu_active((long)hcpu, true);
|
|
return NOTIFY_OK;
|
|
diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c
|
|
index d72586fdf660..beb9a8f3811e 100644
|
|
--- a/kernel/sched/cpupri.c
|
|
+++ b/kernel/sched/cpupri.c
|
|
@@ -68,8 +68,7 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
|
|
int idx = 0;
|
|
int task_pri = convert_prio(p->prio);
|
|
|
|
- if (task_pri >= MAX_RT_PRIO)
|
|
- return 0;
|
|
+ BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);
|
|
|
|
for (idx = 0; idx < task_pri; idx++) {
|
|
struct cpupri_vec *vec = &cp->pri_to_cpu[idx];
|
|
diff --git a/mm/highmem.c b/mm/highmem.c
|
|
index 57d82c6250c3..09fc744d104e 100644
|
|
--- a/mm/highmem.c
|
|
+++ b/mm/highmem.c
|
|
@@ -94,6 +94,19 @@ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait);
|
|
do { spin_unlock(&kmap_lock); (void)(flags); } while (0)
|
|
#endif
|
|
|
|
+struct page *kmap_to_page(void *vaddr)
|
|
+{
|
|
+ unsigned long addr = (unsigned long)vaddr;
|
|
+
|
|
+ if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) {
|
|
+ int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT;
|
|
+ return pte_page(pkmap_page_table[i]);
|
|
+ }
|
|
+
|
|
+ return virt_to_page(addr);
|
|
+}
|
|
+EXPORT_SYMBOL(kmap_to_page);
|
|
+
|
|
static void flush_all_zero_pkmaps(void)
|
|
{
|
|
int i;
|
|
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
|
|
index 455a67971570..2fe9bf640c71 100644
|
|
--- a/mm/memory-failure.c
|
|
+++ b/mm/memory-failure.c
|
|
@@ -1122,6 +1122,8 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
|
|
*/
|
|
if (!PageHWPoison(p)) {
|
|
printk(KERN_ERR "MCE %#lx: just unpoisoned\n", pfn);
|
|
+ atomic_long_sub(nr_pages, &mce_bad_pages);
|
|
+ put_page(hpage);
|
|
res = 0;
|
|
goto out;
|
|
}
|
|
diff --git a/mm/rmap.c b/mm/rmap.c
|
|
index f02c862fab69..3ff473feafd4 100644
|
|
--- a/mm/rmap.c
|
|
+++ b/mm/rmap.c
|
|
@@ -1721,10 +1721,9 @@ void __put_anon_vma(struct anon_vma *anon_vma)
|
|
{
|
|
struct anon_vma *root = anon_vma->root;
|
|
|
|
+ anon_vma_free(anon_vma);
|
|
if (root != anon_vma && atomic_dec_and_test(&root->refcount))
|
|
anon_vma_free(root);
|
|
-
|
|
- anon_vma_free(anon_vma);
|
|
}
|
|
|
|
#ifdef CONFIG_MIGRATION
|
|
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
|
|
index 052d343d43ff..9f4fcc5419e5 100644
|
|
--- a/net/9p/trans_virtio.c
|
|
+++ b/net/9p/trans_virtio.c
|
|
@@ -39,6 +39,7 @@
|
|
#include <linux/inet.h>
|
|
#include <linux/idr.h>
|
|
#include <linux/file.h>
|
|
+#include <linux/highmem.h>
|
|
#include <linux/slab.h>
|
|
#include <net/9p/9p.h>
|
|
#include <linux/parser.h>
|
|
@@ -325,7 +326,7 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
|
|
int count = nr_pages;
|
|
while (nr_pages) {
|
|
s = rest_of_page(data);
|
|
- pages[index++] = virt_to_page(data);
|
|
+ pages[index++] = kmap_to_page(data);
|
|
data += s;
|
|
nr_pages--;
|
|
}
|
|
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
|
|
index 932420de2f38..3bb535b08822 100644
|
|
--- a/net/bluetooth/l2cap_core.c
|
|
+++ b/net/bluetooth/l2cap_core.c
|
|
@@ -2620,10 +2620,15 @@ done:
|
|
}
|
|
}
|
|
|
|
-static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static inline int l2cap_command_rej(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ u8 *data)
|
|
{
|
|
struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data;
|
|
|
|
+ if (cmd_len < sizeof(*rej))
|
|
+ return -EPROTO;
|
|
+
|
|
if (rej->reason != L2CAP_REJ_NOT_UNDERSTOOD)
|
|
return 0;
|
|
|
|
@@ -2640,7 +2645,8 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|
return 0;
|
|
}
|
|
|
|
-static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static int l2cap_connect_req(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data)
|
|
{
|
|
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
|
|
struct l2cap_conn_rsp rsp;
|
|
@@ -2648,8 +2654,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|
struct sock *parent, *sk = NULL;
|
|
int result, status = L2CAP_CS_NO_INFO;
|
|
|
|
- u16 dcid = 0, scid = __le16_to_cpu(req->scid);
|
|
- __le16 psm = req->psm;
|
|
+ u16 dcid = 0, scid;
|
|
+ __le16 psm;
|
|
+
|
|
+ if (cmd_len < sizeof(struct l2cap_conn_req))
|
|
+ return -EPROTO;
|
|
+
|
|
+ scid = __le16_to_cpu(req->scid);
|
|
+ psm = req->psm;
|
|
|
|
BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid);
|
|
|
|
@@ -2770,7 +2782,9 @@ sendresp:
|
|
return 0;
|
|
}
|
|
|
|
-static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static int l2cap_connect_rsp(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ u8 *data)
|
|
{
|
|
struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data;
|
|
u16 scid, dcid, result, status;
|
|
@@ -2778,6 +2792,9 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
|
u8 req[128];
|
|
int err;
|
|
|
|
+ if (cmd_len < sizeof(*rsp))
|
|
+ return -EPROTO;
|
|
+
|
|
scid = __le16_to_cpu(rsp->scid);
|
|
dcid = __le16_to_cpu(rsp->dcid);
|
|
result = __le16_to_cpu(rsp->result);
|
|
@@ -2857,6 +2874,9 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
|
|
struct l2cap_chan *chan;
|
|
int len;
|
|
|
|
+ if (cmd_len < sizeof(*req))
|
|
+ return -EPROTO;
|
|
+
|
|
dcid = __le16_to_cpu(req->dcid);
|
|
flags = __le16_to_cpu(req->flags);
|
|
|
|
@@ -2882,7 +2902,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
|
|
|
|
/* Reject if config buffer is too small. */
|
|
len = cmd_len - sizeof(*req);
|
|
- if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) {
|
|
+ if (chan->conf_len + len > sizeof(chan->conf_req)) {
|
|
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP,
|
|
l2cap_build_conf_rsp(chan, rsp,
|
|
L2CAP_CONF_REJECT, flags), rsp);
|
|
@@ -2959,12 +2979,17 @@ unlock:
|
|
return 0;
|
|
}
|
|
|
|
-static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static inline int l2cap_config_rsp(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ u8 *data)
|
|
{
|
|
struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data;
|
|
u16 scid, flags, result;
|
|
struct l2cap_chan *chan;
|
|
- int len = cmd->len - sizeof(*rsp);
|
|
+ int len = cmd_len - sizeof(*rsp);
|
|
+
|
|
+ if (cmd_len < sizeof(*rsp))
|
|
+ return -EPROTO;
|
|
|
|
scid = __le16_to_cpu(rsp->scid);
|
|
flags = __le16_to_cpu(rsp->flags);
|
|
@@ -3066,7 +3091,9 @@ done:
|
|
return 0;
|
|
}
|
|
|
|
-static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ u8 *data)
|
|
{
|
|
struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data;
|
|
struct l2cap_disconn_rsp rsp;
|
|
@@ -3074,6 +3101,9 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
|
|
struct l2cap_chan *chan;
|
|
struct sock *sk;
|
|
|
|
+ if (cmd_len != sizeof(*req))
|
|
+ return -EPROTO;
|
|
+
|
|
scid = __le16_to_cpu(req->scid);
|
|
dcid = __le16_to_cpu(req->dcid);
|
|
|
|
@@ -3110,12 +3140,17 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
|
|
return 0;
|
|
}
|
|
|
|
-static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ u8 *data)
|
|
{
|
|
struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data;
|
|
u16 dcid, scid;
|
|
struct l2cap_chan *chan;
|
|
|
|
+ if (cmd_len != sizeof(*rsp))
|
|
+ return -EPROTO;
|
|
+
|
|
scid = __le16_to_cpu(rsp->scid);
|
|
dcid = __le16_to_cpu(rsp->dcid);
|
|
|
|
@@ -3142,11 +3177,16 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
|
|
return 0;
|
|
}
|
|
|
|
-static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static inline int l2cap_information_req(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ u8 *data)
|
|
{
|
|
struct l2cap_info_req *req = (struct l2cap_info_req *) data;
|
|
u16 type;
|
|
|
|
+ if (cmd_len != sizeof(*req))
|
|
+ return -EPROTO;
|
|
+
|
|
type = __le16_to_cpu(req->type);
|
|
|
|
BT_DBG("type 0x%4.4x", type);
|
|
@@ -3192,11 +3232,16 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm
|
|
return 0;
|
|
}
|
|
|
|
-static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data)
|
|
+static inline int l2cap_information_rsp(struct l2cap_conn *conn,
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ u8 *data)
|
|
{
|
|
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data;
|
|
u16 type, result;
|
|
|
|
+ if (cmd_len != sizeof(*rsp))
|
|
+ return -EPROTO;
|
|
+
|
|
type = __le16_to_cpu(rsp->type);
|
|
result = __le16_to_cpu(rsp->result);
|
|
|
|
@@ -3282,11 +3327,12 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn,
|
|
}
|
|
|
|
static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn,
|
|
- struct l2cap_cmd_hdr *cmd, void *data)
|
|
+ struct l2cap_cmd_hdr *cmd, u16 cmd_len,
|
|
+ void *data)
|
|
{
|
|
BT_DBG("conn %p", conn);
|
|
|
|
- return l2cap_connect_rsp(conn, cmd, data);
|
|
+ return l2cap_connect_rsp(conn, cmd, cmd_len, data);
|
|
}
|
|
|
|
static void l2cap_send_move_chan_rsp(struct l2cap_conn *conn, u8 ident,
|
|
@@ -3399,7 +3445,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn,
|
|
struct l2cap_move_chan_cfm_rsp *rsp = data;
|
|
u16 icid;
|
|
|
|
- if (cmd_len != sizeof(*rsp))
|
|
+ if (cmd_len < sizeof(*rsp))
|
|
return -EPROTO;
|
|
|
|
icid = le16_to_cpu(rsp->icid);
|
|
@@ -3479,15 +3525,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
|
|
|
|
switch (cmd->code) {
|
|
case L2CAP_COMMAND_REJ:
|
|
- l2cap_command_rej(conn, cmd, data);
|
|
+ l2cap_command_rej(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_CONN_REQ:
|
|
- err = l2cap_connect_req(conn, cmd, data);
|
|
+ err = l2cap_connect_req(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_CONN_RSP:
|
|
- err = l2cap_connect_rsp(conn, cmd, data);
|
|
+ err = l2cap_connect_rsp(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_CONF_REQ:
|
|
@@ -3495,15 +3541,15 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
|
|
break;
|
|
|
|
case L2CAP_CONF_RSP:
|
|
- err = l2cap_config_rsp(conn, cmd, data);
|
|
+ err = l2cap_config_rsp(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_DISCONN_REQ:
|
|
- err = l2cap_disconnect_req(conn, cmd, data);
|
|
+ err = l2cap_disconnect_req(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_DISCONN_RSP:
|
|
- err = l2cap_disconnect_rsp(conn, cmd, data);
|
|
+ err = l2cap_disconnect_rsp(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_ECHO_REQ:
|
|
@@ -3514,11 +3560,11 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
|
|
break;
|
|
|
|
case L2CAP_INFO_REQ:
|
|
- err = l2cap_information_req(conn, cmd, data);
|
|
+ err = l2cap_information_req(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_INFO_RSP:
|
|
- err = l2cap_information_rsp(conn, cmd, data);
|
|
+ err = l2cap_information_rsp(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_CREATE_CHAN_REQ:
|
|
@@ -3526,7 +3572,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn,
|
|
break;
|
|
|
|
case L2CAP_CREATE_CHAN_RSP:
|
|
- err = l2cap_create_channel_rsp(conn, cmd, data);
|
|
+ err = l2cap_create_channel_rsp(conn, cmd, cmd_len, data);
|
|
break;
|
|
|
|
case L2CAP_MOVE_CHAN_REQ:
|
|
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
|
|
index f190ea96f112..4c23cfc0296c 100644
|
|
--- a/net/sunrpc/svcsock.c
|
|
+++ b/net/sunrpc/svcsock.c
|
|
@@ -1441,6 +1441,22 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv,
|
|
return svsk;
|
|
}
|
|
|
|
+bool svc_alien_sock(struct net *net, int fd)
|
|
+{
|
|
+ int err;
|
|
+ struct socket *sock = sockfd_lookup(fd, &err);
|
|
+ bool ret = false;
|
|
+
|
|
+ if (!sock)
|
|
+ goto out;
|
|
+ if (sock_net(sock->sk) != net)
|
|
+ ret = true;
|
|
+ sockfd_put(sock);
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(svc_alien_sock);
|
|
+
|
|
/**
|
|
* svc_addsock - add a listener socket to an RPC service
|
|
* @serv: pointer to RPC service to which to add a new listener
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 2a122954d2a6..2415dcec3265 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -4951,12 +4951,10 @@ static const struct alc_fixup alc260_fixups[] = {
|
|
[ALC260_FIXUP_COEF] = {
|
|
.type = ALC_FIXUP_VERBS,
|
|
.v.verbs = (const struct hda_verb[]) {
|
|
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 },
|
|
+ { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
+ { 0x1a, AC_VERB_SET_PROC_COEF, 0x3040 },
|
|
{ }
|
|
},
|
|
- .chained = true,
|
|
- .chain_id = ALC260_FIXUP_HP_PIN_0F,
|
|
},
|
|
[ALC260_FIXUP_GPIO1] = {
|
|
.type = ALC_FIXUP_VERBS,
|
|
@@ -4971,8 +4969,8 @@ static const struct alc_fixup alc260_fixups[] = {
|
|
[ALC260_FIXUP_REPLACER] = {
|
|
.type = ALC_FIXUP_VERBS,
|
|
.v.verbs = (const struct hda_verb[]) {
|
|
- { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
- { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
|
|
+ { 0x1a, AC_VERB_SET_COEF_INDEX, 0x07 },
|
|
+ { 0x1a, AC_VERB_SET_PROC_COEF, 0x3050 },
|
|
{ }
|
|
},
|
|
.chained = true,
|