mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-27 09:11:49 +00:00
2054 lines
55 KiB
Diff
2054 lines
55 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index 0864af4a683b..fda1dab589be 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 4
|
|
-SUBLEVEL = 94
|
|
+SUBLEVEL = 95
|
|
EXTRAVERSION =
|
|
NAME = Saber-toothed Squirrel
|
|
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
|
|
index 1995cb05acf2..6e49bb47f8b2 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
|
|
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
|
|
@@ -92,8 +92,6 @@ MODULE_PARM_DESC(log_num_mgm_entry_size, "log mgm size, that defines the num"
|
|
" 10 gives 248.range: 9<="
|
|
" log_num_mgm_entry_size <= 12");
|
|
|
|
-#define MLX4_VF (1 << 0)
|
|
-
|
|
#define HCA_GLOBAL_CAP_MASK 0
|
|
#define PF_CONTEXT_BEHAVIOUR_MASK 0
|
|
|
|
@@ -1731,7 +1729,7 @@ static void mlx4_free_ownership(struct mlx4_dev *dev)
|
|
iounmap(owner);
|
|
}
|
|
|
|
-static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
+static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data)
|
|
{
|
|
struct mlx4_priv *priv;
|
|
struct mlx4_dev *dev;
|
|
@@ -1754,12 +1752,11 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
/*
|
|
* Check for BARs.
|
|
*/
|
|
- if (((id == NULL) || !(id->driver_data & MLX4_VF)) &&
|
|
+ if (!(pci_dev_data & MLX4_PCI_DEV_IS_VF) &&
|
|
!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
|
|
dev_err(&pdev->dev, "Missing DCS, aborting."
|
|
- "(id == 0X%p, id->driver_data: 0x%lx,"
|
|
- " pci_resource_flags(pdev, 0):0x%lx)\n", id,
|
|
- id ? id->driver_data : 0, pci_resource_flags(pdev, 0));
|
|
+ "(driver_data: 0x%x, pci_resource_flags(pdev, 0):0x%lx)\n",
|
|
+ pci_dev_data, pci_resource_flags(pdev, 0));
|
|
err = -ENODEV;
|
|
goto err_disable_pdev;
|
|
}
|
|
@@ -1801,15 +1798,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
/* Allow large DMA segments, up to the firmware limit of 1 GB */
|
|
dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
|
|
|
|
- priv = kzalloc(sizeof *priv, GFP_KERNEL);
|
|
- if (!priv) {
|
|
- dev_err(&pdev->dev, "Device struct alloc failed, "
|
|
- "aborting.\n");
|
|
- err = -ENOMEM;
|
|
- goto err_release_regions;
|
|
- }
|
|
-
|
|
- dev = &priv->dev;
|
|
+ dev = pci_get_drvdata(pdev);
|
|
+ priv = mlx4_priv(dev);
|
|
dev->pdev = pdev;
|
|
INIT_LIST_HEAD(&priv->ctx_list);
|
|
spin_lock_init(&priv->ctx_lock);
|
|
@@ -1824,7 +1814,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|
|
|
dev->rev_id = pdev->revision;
|
|
/* Detect if this device is a virtual function */
|
|
- if (id && id->driver_data & MLX4_VF) {
|
|
+ if (pci_dev_data & MLX4_PCI_DEV_IS_VF) {
|
|
/* When acting as pf, we normally skip vfs unless explicitly
|
|
* requested to probe them. */
|
|
if (num_vfs && extended_func_num(pdev) > probe_vf) {
|
|
@@ -1970,7 +1960,7 @@ slave_start:
|
|
mlx4_sense_init(dev);
|
|
mlx4_start_sense(dev);
|
|
|
|
- pci_set_drvdata(pdev, dev);
|
|
+ priv->removed = 0;
|
|
|
|
return 0;
|
|
|
|
@@ -2037,79 +2027,111 @@ err_disable_pdev:
|
|
static int __devinit mlx4_init_one(struct pci_dev *pdev,
|
|
const struct pci_device_id *id)
|
|
{
|
|
+ struct mlx4_priv *priv;
|
|
+ struct mlx4_dev *dev;
|
|
+
|
|
printk_once(KERN_INFO "%s", mlx4_version);
|
|
|
|
- return __mlx4_init_one(pdev, id);
|
|
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
|
+ if (!priv)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ dev = &priv->dev;
|
|
+ pci_set_drvdata(pdev, dev);
|
|
+ priv->pci_dev_data = id->driver_data;
|
|
+
|
|
+ return __mlx4_init_one(pdev, id->driver_data);
|
|
}
|
|
|
|
-static void mlx4_remove_one(struct pci_dev *pdev)
|
|
+static void __mlx4_remove_one(struct pci_dev *pdev)
|
|
{
|
|
struct mlx4_dev *dev = pci_get_drvdata(pdev);
|
|
struct mlx4_priv *priv = mlx4_priv(dev);
|
|
+ int pci_dev_data;
|
|
int p;
|
|
|
|
- if (dev) {
|
|
- /* in SRIOV it is not allowed to unload the pf's
|
|
- * driver while there are alive vf's */
|
|
- if (mlx4_is_master(dev)) {
|
|
- if (mlx4_how_many_lives_vf(dev))
|
|
- printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
|
|
- }
|
|
- mlx4_stop_sense(dev);
|
|
- mlx4_unregister_device(dev);
|
|
+ if (priv->removed)
|
|
+ return;
|
|
|
|
- for (p = 1; p <= dev->caps.num_ports; p++) {
|
|
- mlx4_cleanup_port_info(&priv->port[p]);
|
|
- mlx4_CLOSE_PORT(dev, p);
|
|
- }
|
|
+ pci_dev_data = priv->pci_dev_data;
|
|
|
|
- mlx4_cleanup_counters_table(dev);
|
|
- mlx4_cleanup_mcg_table(dev);
|
|
- mlx4_cleanup_qp_table(dev);
|
|
- mlx4_cleanup_srq_table(dev);
|
|
- mlx4_cleanup_cq_table(dev);
|
|
- mlx4_cmd_use_polling(dev);
|
|
- mlx4_cleanup_eq_table(dev);
|
|
- mlx4_cleanup_mr_table(dev);
|
|
- mlx4_cleanup_xrcd_table(dev);
|
|
- mlx4_cleanup_pd_table(dev);
|
|
+ /* in SRIOV it is not allowed to unload the pf's
|
|
+ * driver while there are alive vf's */
|
|
+ if (mlx4_is_master(dev)) {
|
|
+ if (mlx4_how_many_lives_vf(dev))
|
|
+ printk(KERN_ERR "Removing PF when there are assigned VF's !!!\n");
|
|
+ }
|
|
+ mlx4_stop_sense(dev);
|
|
+ mlx4_unregister_device(dev);
|
|
|
|
- if (mlx4_is_master(dev))
|
|
- mlx4_free_resource_tracker(dev);
|
|
-
|
|
- iounmap(priv->kar);
|
|
- mlx4_uar_free(dev, &priv->driver_uar);
|
|
- mlx4_cleanup_uar_table(dev);
|
|
- if (!mlx4_is_slave(dev))
|
|
- mlx4_clear_steering(dev);
|
|
- mlx4_free_eq_table(dev);
|
|
- if (mlx4_is_master(dev))
|
|
- mlx4_multi_func_cleanup(dev);
|
|
- mlx4_close_hca(dev);
|
|
- if (mlx4_is_slave(dev))
|
|
- mlx4_multi_func_cleanup(dev);
|
|
- mlx4_cmd_cleanup(dev);
|
|
-
|
|
- if (dev->flags & MLX4_FLAG_MSI_X)
|
|
- pci_disable_msix(pdev);
|
|
- if (num_vfs && (dev->flags & MLX4_FLAG_SRIOV)) {
|
|
- mlx4_warn(dev, "Disabling sriov\n");
|
|
- pci_disable_sriov(pdev);
|
|
- }
|
|
+ for (p = 1; p <= dev->caps.num_ports; p++) {
|
|
+ mlx4_cleanup_port_info(&priv->port[p]);
|
|
+ mlx4_CLOSE_PORT(dev, p);
|
|
+ }
|
|
+
|
|
+ mlx4_cleanup_counters_table(dev);
|
|
+ mlx4_cleanup_mcg_table(dev);
|
|
+ mlx4_cleanup_qp_table(dev);
|
|
+ mlx4_cleanup_srq_table(dev);
|
|
+ mlx4_cleanup_cq_table(dev);
|
|
+ mlx4_cmd_use_polling(dev);
|
|
+ mlx4_cleanup_eq_table(dev);
|
|
+ mlx4_cleanup_mr_table(dev);
|
|
+ mlx4_cleanup_xrcd_table(dev);
|
|
+ mlx4_cleanup_pd_table(dev);
|
|
+
|
|
+ if (mlx4_is_master(dev))
|
|
+ mlx4_free_resource_tracker(dev);
|
|
+
|
|
+ iounmap(priv->kar);
|
|
+ mlx4_uar_free(dev, &priv->driver_uar);
|
|
+ mlx4_cleanup_uar_table(dev);
|
|
+ if (!mlx4_is_slave(dev))
|
|
+ mlx4_clear_steering(dev);
|
|
+ mlx4_free_eq_table(dev);
|
|
+ if (mlx4_is_master(dev))
|
|
+ mlx4_multi_func_cleanup(dev);
|
|
+ mlx4_close_hca(dev);
|
|
+ if (mlx4_is_slave(dev))
|
|
+ mlx4_multi_func_cleanup(dev);
|
|
+ mlx4_cmd_cleanup(dev);
|
|
|
|
- if (!mlx4_is_slave(dev))
|
|
- mlx4_free_ownership(dev);
|
|
- kfree(priv);
|
|
- pci_release_regions(pdev);
|
|
- pci_disable_device(pdev);
|
|
- pci_set_drvdata(pdev, NULL);
|
|
+ if (dev->flags & MLX4_FLAG_MSI_X)
|
|
+ pci_disable_msix(pdev);
|
|
+ if (num_vfs && (dev->flags & MLX4_FLAG_SRIOV)) {
|
|
+ mlx4_warn(dev, "Disabling sriov\n");
|
|
+ pci_disable_sriov(pdev);
|
|
}
|
|
+
|
|
+ if (!mlx4_is_slave(dev))
|
|
+ mlx4_free_ownership(dev);
|
|
+
|
|
+ pci_release_regions(pdev);
|
|
+ pci_disable_device(pdev);
|
|
+ memset(priv, 0, sizeof(*priv));
|
|
+ priv->pci_dev_data = pci_dev_data;
|
|
+ priv->removed = 1;
|
|
+}
|
|
+
|
|
+static void mlx4_remove_one(struct pci_dev *pdev)
|
|
+{
|
|
+ struct mlx4_dev *dev = pci_get_drvdata(pdev);
|
|
+ struct mlx4_priv *priv = mlx4_priv(dev);
|
|
+
|
|
+ __mlx4_remove_one(pdev);
|
|
+ kfree(priv);
|
|
+ pci_set_drvdata(pdev, NULL);
|
|
}
|
|
|
|
int mlx4_restart_one(struct pci_dev *pdev)
|
|
{
|
|
- mlx4_remove_one(pdev);
|
|
- return __mlx4_init_one(pdev, NULL);
|
|
+ struct mlx4_dev *dev = pci_get_drvdata(pdev);
|
|
+ struct mlx4_priv *priv = mlx4_priv(dev);
|
|
+ int pci_dev_data;
|
|
+
|
|
+ pci_dev_data = priv->pci_dev_data;
|
|
+ __mlx4_remove_one(pdev);
|
|
+ return __mlx4_init_one(pdev, pci_dev_data);
|
|
}
|
|
|
|
static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = {
|
|
@@ -2138,11 +2160,11 @@ static DEFINE_PCI_DEVICE_TABLE(mlx4_pci_table) = {
|
|
/* MT26478 ConnectX2 40GigE PCIe gen2 */
|
|
{ PCI_VDEVICE(MELLANOX, 0x676e), 0 },
|
|
/* MT25400 Family [ConnectX-2 Virtual Function] */
|
|
- { PCI_VDEVICE(MELLANOX, 0x1002), MLX4_VF },
|
|
+ { PCI_VDEVICE(MELLANOX, 0x1002), MLX4_PCI_DEV_IS_VF },
|
|
/* MT27500 Family [ConnectX-3] */
|
|
{ PCI_VDEVICE(MELLANOX, 0x1003), 0 },
|
|
/* MT27500 Family [ConnectX-3 Virtual Function] */
|
|
- { PCI_VDEVICE(MELLANOX, 0x1004), MLX4_VF },
|
|
+ { PCI_VDEVICE(MELLANOX, 0x1004), MLX4_PCI_DEV_IS_VF },
|
|
{ PCI_VDEVICE(MELLANOX, 0x1005), 0 }, /* MT27510 Family */
|
|
{ PCI_VDEVICE(MELLANOX, 0x1006), 0 }, /* MT27511 Family */
|
|
{ PCI_VDEVICE(MELLANOX, 0x1007), 0 }, /* MT27520 Family */
|
|
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
|
|
index 2a0ff2cc7182..a3ef1dff163d 100644
|
|
--- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h
|
|
+++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h
|
|
@@ -711,6 +711,10 @@ struct mlx4_steer {
|
|
struct list_head steer_entries[MLX4_NUM_STEERS];
|
|
};
|
|
|
|
+enum {
|
|
+ MLX4_PCI_DEV_IS_VF = 1 << 0,
|
|
+};
|
|
+
|
|
struct mlx4_priv {
|
|
struct mlx4_dev dev;
|
|
|
|
@@ -718,6 +722,9 @@ struct mlx4_priv {
|
|
struct list_head ctx_list;
|
|
spinlock_t ctx_lock;
|
|
|
|
+ int pci_dev_data;
|
|
+ int removed;
|
|
+
|
|
struct list_head pgdir_list;
|
|
struct mutex pgdir_mutex;
|
|
|
|
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
|
|
index 8f81805c6825..d16800f5168a 100644
|
|
--- a/drivers/net/team/team.c
|
|
+++ b/drivers/net/team/team.c
|
|
@@ -889,6 +889,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
|
|
* to traverse list in reverse under rcu_read_lock
|
|
*/
|
|
mutex_lock(&team->lock);
|
|
+ team->port_mtu_change_allowed = true;
|
|
list_for_each_entry(port, &team->port_list, list) {
|
|
err = dev_set_mtu(port->dev, new_mtu);
|
|
if (err) {
|
|
@@ -897,6 +898,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
|
|
goto unwind;
|
|
}
|
|
}
|
|
+ team->port_mtu_change_allowed = false;
|
|
mutex_unlock(&team->lock);
|
|
|
|
dev->mtu = new_mtu;
|
|
@@ -906,6 +908,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
|
|
unwind:
|
|
list_for_each_entry_continue_reverse(port, &team->port_list, list)
|
|
dev_set_mtu(port->dev, dev->mtu);
|
|
+ team->port_mtu_change_allowed = false;
|
|
mutex_unlock(&team->lock);
|
|
|
|
return err;
|
|
@@ -1671,7 +1674,9 @@ static int team_device_event(struct notifier_block *unused,
|
|
break;
|
|
case NETDEV_CHANGEMTU:
|
|
/* Forbid to change mtu of underlaying device */
|
|
- return NOTIFY_BAD;
|
|
+ if (!port->team->port_mtu_change_allowed)
|
|
+ return NOTIFY_BAD;
|
|
+ break;
|
|
case NETDEV_PRE_TYPE_CHANGE:
|
|
/* Forbid to change type of underlaying device */
|
|
return NOTIFY_BAD;
|
|
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
|
|
index b54f6ecf90d9..cbb04f37ec36 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_auth.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_auth.c
|
|
@@ -342,6 +342,16 @@ static int chap_server_compute_md5(
|
|
goto out;
|
|
}
|
|
/*
|
|
+ * During mutual authentication, the CHAP_C generated by the
|
|
+ * initiator must not match the original CHAP_C generated by
|
|
+ * the target.
|
|
+ */
|
|
+ if (!memcmp(challenge_binhex, chap->challenge, CHAP_CHALLENGE_LENGTH)) {
|
|
+ pr_err("initiator CHAP_C matches target CHAP_C, failing"
|
|
+ " login attempt\n");
|
|
+ goto out;
|
|
+ }
|
|
+ /*
|
|
* Generate CHAP_N and CHAP_R for mutual authentication.
|
|
*/
|
|
tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
|
|
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
|
|
index f509888b7ad0..2f2540ff21f6 100644
|
|
--- a/drivers/usb/class/cdc-acm.c
|
|
+++ b/drivers/usb/class/cdc-acm.c
|
|
@@ -123,13 +123,23 @@ static void acm_release_minor(struct acm *acm)
|
|
static int acm_ctrl_msg(struct acm *acm, int request, int value,
|
|
void *buf, int len)
|
|
{
|
|
- int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
|
|
+ int retval;
|
|
+
|
|
+ retval = usb_autopm_get_interface(acm->control);
|
|
+ if (retval)
|
|
+ return retval;
|
|
+
|
|
+ retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
|
|
request, USB_RT_ACM, value,
|
|
acm->control->altsetting[0].desc.bInterfaceNumber,
|
|
buf, len, 5000);
|
|
+
|
|
dev_dbg(&acm->control->dev,
|
|
"%s - rq 0x%02x, val %#x, len %#x, result %d\n",
|
|
__func__, request, value, len, retval);
|
|
+
|
|
+ usb_autopm_put_interface(acm->control);
|
|
+
|
|
return retval < 0 ? retval : 0;
|
|
}
|
|
|
|
@@ -234,12 +244,9 @@ static int acm_write_start(struct acm *acm, int wbn)
|
|
acm->susp_count);
|
|
usb_autopm_get_interface_async(acm->control);
|
|
if (acm->susp_count) {
|
|
- if (!acm->delayed_wb)
|
|
- acm->delayed_wb = wb;
|
|
- else
|
|
- usb_autopm_put_interface_async(acm->control);
|
|
+ usb_anchor_urb(wb->urb, &acm->delayed);
|
|
spin_unlock_irqrestore(&acm->write_lock, flags);
|
|
- return 0; /* A white lie */
|
|
+ return 0;
|
|
}
|
|
usb_mark_last_busy(acm->dev);
|
|
|
|
@@ -535,6 +542,7 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
|
|
{
|
|
struct acm *acm = container_of(port, struct acm, port);
|
|
int retval = -ENODEV;
|
|
+ int i;
|
|
|
|
dev_dbg(&acm->control->dev, "%s\n", __func__);
|
|
|
|
@@ -583,6 +591,8 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty)
|
|
return 0;
|
|
|
|
error_submit_read_urbs:
|
|
+ for (i = 0; i < acm->rx_buflimit; i++)
|
|
+ usb_kill_urb(acm->read_urbs[i]);
|
|
acm->ctrlout = 0;
|
|
acm_set_control(acm, acm->ctrlout);
|
|
error_set_control:
|
|
@@ -610,21 +620,35 @@ static void acm_port_destruct(struct tty_port *port)
|
|
static void acm_port_shutdown(struct tty_port *port)
|
|
{
|
|
struct acm *acm = container_of(port, struct acm, port);
|
|
+ struct urb *urb;
|
|
+ struct acm_wb *wb;
|
|
int i;
|
|
+ int pm_err;
|
|
|
|
dev_dbg(&acm->control->dev, "%s\n", __func__);
|
|
|
|
mutex_lock(&acm->mutex);
|
|
if (!acm->disconnected) {
|
|
- usb_autopm_get_interface(acm->control);
|
|
+ pm_err = usb_autopm_get_interface(acm->control);
|
|
acm_set_control(acm, acm->ctrlout = 0);
|
|
+
|
|
+ for (;;) {
|
|
+ urb = usb_get_from_anchor(&acm->delayed);
|
|
+ if (!urb)
|
|
+ break;
|
|
+ wb = urb->context;
|
|
+ wb->use = 0;
|
|
+ usb_autopm_put_interface_async(acm->control);
|
|
+ }
|
|
+
|
|
usb_kill_urb(acm->ctrlurb);
|
|
for (i = 0; i < ACM_NW; i++)
|
|
usb_kill_urb(acm->wb[i].urb);
|
|
for (i = 0; i < acm->rx_buflimit; i++)
|
|
usb_kill_urb(acm->read_urbs[i]);
|
|
acm->control->needs_remote_wakeup = 0;
|
|
- usb_autopm_put_interface(acm->control);
|
|
+ if (!pm_err)
|
|
+ usb_autopm_put_interface(acm->control);
|
|
}
|
|
mutex_unlock(&acm->mutex);
|
|
}
|
|
@@ -1211,6 +1235,7 @@ made_compressed_probe:
|
|
acm->bInterval = epread->bInterval;
|
|
tty_port_init(&acm->port);
|
|
acm->port.ops = &acm_port_ops;
|
|
+ init_usb_anchor(&acm->delayed);
|
|
|
|
buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma);
|
|
if (!buf) {
|
|
@@ -1441,18 +1466,15 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
|
|
struct acm *acm = usb_get_intfdata(intf);
|
|
int cnt;
|
|
|
|
+ spin_lock_irq(&acm->read_lock);
|
|
+ spin_lock(&acm->write_lock);
|
|
if (PMSG_IS_AUTO(message)) {
|
|
- int b;
|
|
-
|
|
- spin_lock_irq(&acm->write_lock);
|
|
- b = acm->transmitting;
|
|
- spin_unlock_irq(&acm->write_lock);
|
|
- if (b)
|
|
+ if (acm->transmitting) {
|
|
+ spin_unlock(&acm->write_lock);
|
|
+ spin_unlock_irq(&acm->read_lock);
|
|
return -EBUSY;
|
|
+ }
|
|
}
|
|
-
|
|
- spin_lock_irq(&acm->read_lock);
|
|
- spin_lock(&acm->write_lock);
|
|
cnt = acm->susp_count++;
|
|
spin_unlock(&acm->write_lock);
|
|
spin_unlock_irq(&acm->read_lock);
|
|
@@ -1460,8 +1482,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
|
|
if (cnt)
|
|
return 0;
|
|
|
|
- if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
|
|
- stop_data_traffic(acm);
|
|
+ stop_data_traffic(acm);
|
|
|
|
return 0;
|
|
}
|
|
@@ -1469,29 +1490,24 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message)
|
|
static int acm_resume(struct usb_interface *intf)
|
|
{
|
|
struct acm *acm = usb_get_intfdata(intf);
|
|
- struct acm_wb *wb;
|
|
+ struct urb *urb;
|
|
int rv = 0;
|
|
- int cnt;
|
|
|
|
spin_lock_irq(&acm->read_lock);
|
|
- acm->susp_count -= 1;
|
|
- cnt = acm->susp_count;
|
|
- spin_unlock_irq(&acm->read_lock);
|
|
+ spin_lock(&acm->write_lock);
|
|
|
|
- if (cnt)
|
|
- return 0;
|
|
+ if (--acm->susp_count)
|
|
+ goto out;
|
|
|
|
if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags)) {
|
|
- rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO);
|
|
-
|
|
- spin_lock_irq(&acm->write_lock);
|
|
- if (acm->delayed_wb) {
|
|
- wb = acm->delayed_wb;
|
|
- acm->delayed_wb = NULL;
|
|
- spin_unlock_irq(&acm->write_lock);
|
|
- acm_start_wb(acm, wb);
|
|
- } else {
|
|
- spin_unlock_irq(&acm->write_lock);
|
|
+ rv = usb_submit_urb(acm->ctrlurb, GFP_ATOMIC);
|
|
+
|
|
+ for (;;) {
|
|
+ urb = usb_get_from_anchor(&acm->delayed);
|
|
+ if (!urb)
|
|
+ break;
|
|
+
|
|
+ acm_start_wb(acm, urb->context);
|
|
}
|
|
|
|
/*
|
|
@@ -1499,12 +1515,14 @@ static int acm_resume(struct usb_interface *intf)
|
|
* do the write path at all cost
|
|
*/
|
|
if (rv < 0)
|
|
- goto err_out;
|
|
+ goto out;
|
|
|
|
- rv = acm_submit_read_urbs(acm, GFP_NOIO);
|
|
+ rv = acm_submit_read_urbs(acm, GFP_ATOMIC);
|
|
}
|
|
+out:
|
|
+ spin_unlock(&acm->write_lock);
|
|
+ spin_unlock_irq(&acm->read_lock);
|
|
|
|
-err_out:
|
|
return rv;
|
|
}
|
|
|
|
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
|
|
index 35ef887b7417..96147806b9a4 100644
|
|
--- a/drivers/usb/class/cdc-acm.h
|
|
+++ b/drivers/usb/class/cdc-acm.h
|
|
@@ -117,7 +117,7 @@ struct acm {
|
|
unsigned int throttled:1; /* actually throttled */
|
|
unsigned int throttle_req:1; /* throttle requested */
|
|
u8 bInterval;
|
|
- struct acm_wb *delayed_wb; /* write queued for a device about to be woken */
|
|
+ struct usb_anchor delayed; /* writes queued for a device about to be woken */
|
|
};
|
|
|
|
#define CDC_DATA_INTERFACE_TYPE 0x0a
|
|
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
|
|
index 58404b0c5010..b159b10d915d 100644
|
|
--- a/include/linux/if_team.h
|
|
+++ b/include/linux/if_team.h
|
|
@@ -113,6 +113,7 @@ struct team {
|
|
|
|
const struct team_mode *mode;
|
|
struct team_mode_ops ops;
|
|
+ bool port_mtu_change_allowed;
|
|
long mode_priv[TEAM_MODE_PRIV_LONGS];
|
|
};
|
|
|
|
diff --git a/include/linux/lzo.h b/include/linux/lzo.h
|
|
index d793497ec1ca..a0848d9377e5 100644
|
|
--- a/include/linux/lzo.h
|
|
+++ b/include/linux/lzo.h
|
|
@@ -4,28 +4,28 @@
|
|
* LZO Public Kernel Interface
|
|
* A mini subset of the LZO real-time data compression library
|
|
*
|
|
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
*
|
|
* The full LZO package can be found at:
|
|
* http://www.oberhumer.com/opensource/lzo/
|
|
*
|
|
- * Changed for kernel use by:
|
|
+ * Changed for Linux kernel use by:
|
|
* Nitin Gupta <nitingupta910@gmail.com>
|
|
* Richard Purdie <rpurdie@openedhand.com>
|
|
*/
|
|
|
|
-#define LZO1X_MEM_COMPRESS (16384 * sizeof(unsigned char *))
|
|
-#define LZO1X_1_MEM_COMPRESS LZO1X_MEM_COMPRESS
|
|
+#define LZO1X_1_MEM_COMPRESS (8192 * sizeof(unsigned short))
|
|
+#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS
|
|
|
|
#define lzo1x_worst_compress(x) ((x) + ((x) / 16) + 64 + 3)
|
|
|
|
-/* This requires 'workmem' of size LZO1X_1_MEM_COMPRESS */
|
|
+/* This requires 'wrkmem' of size LZO1X_1_MEM_COMPRESS */
|
|
int lzo1x_1_compress(const unsigned char *src, size_t src_len,
|
|
- unsigned char *dst, size_t *dst_len, void *wrkmem);
|
|
+ unsigned char *dst, size_t *dst_len, void *wrkmem);
|
|
|
|
/* safe decompression with overrun testing */
|
|
int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
|
|
- unsigned char *dst, size_t *dst_len);
|
|
+ unsigned char *dst, size_t *dst_len);
|
|
|
|
/*
|
|
* Return values (< 0 = Error)
|
|
@@ -40,5 +40,6 @@ int lzo1x_decompress_safe(const unsigned char *src, size_t src_len,
|
|
#define LZO_E_EOF_NOT_FOUND (-7)
|
|
#define LZO_E_INPUT_NOT_CONSUMED (-8)
|
|
#define LZO_E_NOT_YET_IMPLEMENTED (-9)
|
|
+#define LZO_E_INVALID_ARGUMENT (-10)
|
|
|
|
#endif
|
|
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
|
|
index 2040bff945d4..2d643649f0f8 100644
|
|
--- a/include/net/inetpeer.h
|
|
+++ b/include/net/inetpeer.h
|
|
@@ -114,16 +114,9 @@ static inline void inet_peer_refcheck(const struct inet_peer *p)
|
|
/* can be called with or without local BH being disabled */
|
|
static inline int inet_getid(struct inet_peer *p, int more)
|
|
{
|
|
- int old, new;
|
|
more++;
|
|
inet_peer_refcheck(p);
|
|
- do {
|
|
- old = atomic_read(&p->ip_id_count);
|
|
- new = old + more;
|
|
- if (!new)
|
|
- new = 1;
|
|
- } while (atomic_cmpxchg(&p->ip_id_count, old, new) != old);
|
|
- return new;
|
|
+ return atomic_add_return(more, &p->ip_id_count) - more;
|
|
}
|
|
|
|
#endif /* _NET_INETPEER_H */
|
|
diff --git a/include/sound/core.h b/include/sound/core.h
|
|
index 93896ad1fcdd..8d29d28d3696 100644
|
|
--- a/include/sound/core.h
|
|
+++ b/include/sound/core.h
|
|
@@ -120,6 +120,8 @@ struct snd_card {
|
|
int user_ctl_count; /* count of all user controls */
|
|
struct list_head controls; /* all controls for this card */
|
|
struct list_head ctl_files; /* active control files */
|
|
+ struct mutex user_ctl_lock; /* protects user controls against
|
|
+ concurrent access */
|
|
|
|
struct snd_info_entry *proc_root; /* root for soundcard specific files */
|
|
struct snd_info_entry *proc_id; /* the card id */
|
|
diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
|
|
index 638dadf6295f..67106f88dca1 100644
|
|
--- a/kernel/time/tick-sched.c
|
|
+++ b/kernel/time/tick-sched.c
|
|
@@ -296,8 +296,10 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
|
|
tick_do_timer_cpu = TICK_DO_TIMER_NONE;
|
|
}
|
|
|
|
- if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
|
|
+ if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE)) {
|
|
+ ts->sleep_length = (ktime_t) { .tv64 = NSEC_PER_SEC/HZ };
|
|
return;
|
|
+ }
|
|
|
|
if (need_resched())
|
|
return;
|
|
diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c
|
|
index 4531294fa62f..960183d4258f 100644
|
|
--- a/lib/decompress_unlzo.c
|
|
+++ b/lib/decompress_unlzo.c
|
|
@@ -31,7 +31,7 @@
|
|
*/
|
|
|
|
#ifdef STATIC
|
|
-#include "lzo/lzo1x_decompress.c"
|
|
+#include "lzo/lzo1x_decompress_safe.c"
|
|
#else
|
|
#include <linux/decompress/unlzo.h>
|
|
#endif
|
|
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
|
|
index e764116ea12d..f0f7d7ca2b83 100644
|
|
--- a/lib/lzo/Makefile
|
|
+++ b/lib/lzo/Makefile
|
|
@@ -1,5 +1,5 @@
|
|
lzo_compress-objs := lzo1x_compress.o
|
|
-lzo_decompress-objs := lzo1x_decompress.o
|
|
+lzo_decompress-objs := lzo1x_decompress_safe.o
|
|
|
|
obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
|
|
obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
|
|
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
|
|
index a6040990a62e..236eb21167b5 100644
|
|
--- a/lib/lzo/lzo1x_compress.c
|
|
+++ b/lib/lzo/lzo1x_compress.c
|
|
@@ -1,194 +1,243 @@
|
|
/*
|
|
- * LZO1X Compressor from MiniLZO
|
|
+ * LZO1X Compressor from LZO
|
|
*
|
|
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
*
|
|
* The full LZO package can be found at:
|
|
* http://www.oberhumer.com/opensource/lzo/
|
|
*
|
|
- * Changed for kernel use by:
|
|
+ * Changed for Linux kernel use by:
|
|
* Nitin Gupta <nitingupta910@gmail.com>
|
|
* Richard Purdie <rpurdie@openedhand.com>
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
-#include <linux/lzo.h>
|
|
#include <asm/unaligned.h>
|
|
+#include <linux/lzo.h>
|
|
#include "lzodefs.h"
|
|
|
|
static noinline size_t
|
|
-_lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
|
|
- unsigned char *out, size_t *out_len, void *wrkmem)
|
|
+lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
|
|
+ unsigned char *out, size_t *out_len,
|
|
+ size_t ti, void *wrkmem)
|
|
{
|
|
+ const unsigned char *ip;
|
|
+ unsigned char *op;
|
|
const unsigned char * const in_end = in + in_len;
|
|
- const unsigned char * const ip_end = in + in_len - M2_MAX_LEN - 5;
|
|
- const unsigned char ** const dict = wrkmem;
|
|
- const unsigned char *ip = in, *ii = ip;
|
|
- const unsigned char *end, *m, *m_pos;
|
|
- size_t m_off, m_len, dindex;
|
|
- unsigned char *op = out;
|
|
+ const unsigned char * const ip_end = in + in_len - 20;
|
|
+ const unsigned char *ii;
|
|
+ lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
|
|
|
|
- ip += 4;
|
|
+ op = out;
|
|
+ ip = in;
|
|
+ ii = ip;
|
|
+ ip += ti < 4 ? 4 - ti : 0;
|
|
|
|
for (;;) {
|
|
- dindex = ((size_t)(0x21 * DX3(ip, 5, 5, 6)) >> 5) & D_MASK;
|
|
- m_pos = dict[dindex];
|
|
-
|
|
- if (m_pos < in)
|
|
- goto literal;
|
|
-
|
|
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
|
|
- goto literal;
|
|
-
|
|
- m_off = ip - m_pos;
|
|
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
|
|
- goto try_match;
|
|
-
|
|
- dindex = (dindex & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f);
|
|
- m_pos = dict[dindex];
|
|
-
|
|
- if (m_pos < in)
|
|
- goto literal;
|
|
-
|
|
- if (ip == m_pos || ((size_t)(ip - m_pos) > M4_MAX_OFFSET))
|
|
- goto literal;
|
|
-
|
|
- m_off = ip - m_pos;
|
|
- if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
|
|
- goto try_match;
|
|
-
|
|
- goto literal;
|
|
-
|
|
-try_match:
|
|
- if (get_unaligned((const unsigned short *)m_pos)
|
|
- == get_unaligned((const unsigned short *)ip)) {
|
|
- if (likely(m_pos[2] == ip[2]))
|
|
- goto match;
|
|
- }
|
|
-
|
|
+ const unsigned char *m_pos;
|
|
+ size_t t, m_len, m_off;
|
|
+ u32 dv;
|
|
literal:
|
|
- dict[dindex] = ip;
|
|
- ++ip;
|
|
+ ip += 1 + ((ip - ii) >> 5);
|
|
+next:
|
|
if (unlikely(ip >= ip_end))
|
|
break;
|
|
- continue;
|
|
-
|
|
-match:
|
|
- dict[dindex] = ip;
|
|
- if (ip != ii) {
|
|
- size_t t = ip - ii;
|
|
+ dv = get_unaligned_le32(ip);
|
|
+ t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
|
|
+ m_pos = in + dict[t];
|
|
+ dict[t] = (lzo_dict_t) (ip - in);
|
|
+ if (unlikely(dv != get_unaligned_le32(m_pos)))
|
|
+ goto literal;
|
|
|
|
+ ii -= ti;
|
|
+ ti = 0;
|
|
+ t = ip - ii;
|
|
+ if (t != 0) {
|
|
if (t <= 3) {
|
|
op[-2] |= t;
|
|
- } else if (t <= 18) {
|
|
+ COPY4(op, ii);
|
|
+ op += t;
|
|
+ } else if (t <= 16) {
|
|
*op++ = (t - 3);
|
|
+ COPY8(op, ii);
|
|
+ COPY8(op + 8, ii + 8);
|
|
+ op += t;
|
|
} else {
|
|
- size_t tt = t - 18;
|
|
-
|
|
- *op++ = 0;
|
|
- while (tt > 255) {
|
|
- tt -= 255;
|
|
+ if (t <= 18) {
|
|
+ *op++ = (t - 3);
|
|
+ } else {
|
|
+ size_t tt = t - 18;
|
|
*op++ = 0;
|
|
+ while (unlikely(tt > 255)) {
|
|
+ tt -= 255;
|
|
+ *op++ = 0;
|
|
+ }
|
|
+ *op++ = tt;
|
|
}
|
|
- *op++ = tt;
|
|
+ do {
|
|
+ COPY8(op, ii);
|
|
+ COPY8(op + 8, ii + 8);
|
|
+ op += 16;
|
|
+ ii += 16;
|
|
+ t -= 16;
|
|
+ } while (t >= 16);
|
|
+ if (t > 0) do {
|
|
+ *op++ = *ii++;
|
|
+ } while (--t > 0);
|
|
}
|
|
- do {
|
|
- *op++ = *ii++;
|
|
- } while (--t > 0);
|
|
}
|
|
|
|
- ip += 3;
|
|
- if (m_pos[3] != *ip++ || m_pos[4] != *ip++
|
|
- || m_pos[5] != *ip++ || m_pos[6] != *ip++
|
|
- || m_pos[7] != *ip++ || m_pos[8] != *ip++) {
|
|
- --ip;
|
|
- m_len = ip - ii;
|
|
+ m_len = 4;
|
|
+ {
|
|
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
|
|
+ u64 v;
|
|
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
|
|
+ get_unaligned((const u64 *) (m_pos + m_len));
|
|
+ if (unlikely(v == 0)) {
|
|
+ do {
|
|
+ m_len += 8;
|
|
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
|
|
+ get_unaligned((const u64 *) (m_pos + m_len));
|
|
+ if (unlikely(ip + m_len >= ip_end))
|
|
+ goto m_len_done;
|
|
+ } while (v == 0);
|
|
+ }
|
|
+# if defined(__LITTLE_ENDIAN)
|
|
+ m_len += (unsigned) __builtin_ctzll(v) / 8;
|
|
+# elif defined(__BIG_ENDIAN)
|
|
+ m_len += (unsigned) __builtin_clzll(v) / 8;
|
|
+# else
|
|
+# error "missing endian definition"
|
|
+# endif
|
|
+#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
|
|
+ u32 v;
|
|
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
|
|
+ get_unaligned((const u32 *) (m_pos + m_len));
|
|
+ if (unlikely(v == 0)) {
|
|
+ do {
|
|
+ m_len += 4;
|
|
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
|
|
+ get_unaligned((const u32 *) (m_pos + m_len));
|
|
+ if (v != 0)
|
|
+ break;
|
|
+ m_len += 4;
|
|
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
|
|
+ get_unaligned((const u32 *) (m_pos + m_len));
|
|
+ if (unlikely(ip + m_len >= ip_end))
|
|
+ goto m_len_done;
|
|
+ } while (v == 0);
|
|
+ }
|
|
+# if defined(__LITTLE_ENDIAN)
|
|
+ m_len += (unsigned) __builtin_ctz(v) / 8;
|
|
+# elif defined(__BIG_ENDIAN)
|
|
+ m_len += (unsigned) __builtin_clz(v) / 8;
|
|
+# else
|
|
+# error "missing endian definition"
|
|
+# endif
|
|
+#else
|
|
+ if (unlikely(ip[m_len] == m_pos[m_len])) {
|
|
+ do {
|
|
+ m_len += 1;
|
|
+ if (ip[m_len] != m_pos[m_len])
|
|
+ break;
|
|
+ m_len += 1;
|
|
+ if (ip[m_len] != m_pos[m_len])
|
|
+ break;
|
|
+ m_len += 1;
|
|
+ if (ip[m_len] != m_pos[m_len])
|
|
+ break;
|
|
+ m_len += 1;
|
|
+ if (ip[m_len] != m_pos[m_len])
|
|
+ break;
|
|
+ m_len += 1;
|
|
+ if (ip[m_len] != m_pos[m_len])
|
|
+ break;
|
|
+ m_len += 1;
|
|
+ if (ip[m_len] != m_pos[m_len])
|
|
+ break;
|
|
+ m_len += 1;
|
|
+ if (ip[m_len] != m_pos[m_len])
|
|
+ break;
|
|
+ m_len += 1;
|
|
+ if (unlikely(ip + m_len >= ip_end))
|
|
+ goto m_len_done;
|
|
+ } while (ip[m_len] == m_pos[m_len]);
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
+m_len_done:
|
|
|
|
- if (m_off <= M2_MAX_OFFSET) {
|
|
- m_off -= 1;
|
|
- *op++ = (((m_len - 1) << 5)
|
|
- | ((m_off & 7) << 2));
|
|
- *op++ = (m_off >> 3);
|
|
- } else if (m_off <= M3_MAX_OFFSET) {
|
|
- m_off -= 1;
|
|
+ m_off = ip - m_pos;
|
|
+ ip += m_len;
|
|
+ ii = ip;
|
|
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
|
|
+ m_off -= 1;
|
|
+ *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
|
|
+ *op++ = (m_off >> 3);
|
|
+ } else if (m_off <= M3_MAX_OFFSET) {
|
|
+ m_off -= 1;
|
|
+ if (m_len <= M3_MAX_LEN)
|
|
*op++ = (M3_MARKER | (m_len - 2));
|
|
- goto m3_m4_offset;
|
|
- } else {
|
|
- m_off -= 0x4000;
|
|
-
|
|
- *op++ = (M4_MARKER | ((m_off & 0x4000) >> 11)
|
|
- | (m_len - 2));
|
|
- goto m3_m4_offset;
|
|
+ else {
|
|
+ m_len -= M3_MAX_LEN;
|
|
+ *op++ = M3_MARKER | 0;
|
|
+ while (unlikely(m_len > 255)) {
|
|
+ m_len -= 255;
|
|
+ *op++ = 0;
|
|
+ }
|
|
+ *op++ = (m_len);
|
|
}
|
|
+ *op++ = (m_off << 2);
|
|
+ *op++ = (m_off >> 6);
|
|
} else {
|
|
- end = in_end;
|
|
- m = m_pos + M2_MAX_LEN + 1;
|
|
-
|
|
- while (ip < end && *m == *ip) {
|
|
- m++;
|
|
- ip++;
|
|
- }
|
|
- m_len = ip - ii;
|
|
-
|
|
- if (m_off <= M3_MAX_OFFSET) {
|
|
- m_off -= 1;
|
|
- if (m_len <= 33) {
|
|
- *op++ = (M3_MARKER | (m_len - 2));
|
|
- } else {
|
|
- m_len -= 33;
|
|
- *op++ = M3_MARKER | 0;
|
|
- goto m3_m4_len;
|
|
- }
|
|
- } else {
|
|
- m_off -= 0x4000;
|
|
- if (m_len <= M4_MAX_LEN) {
|
|
- *op++ = (M4_MARKER
|
|
- | ((m_off & 0x4000) >> 11)
|
|
+ m_off -= 0x4000;
|
|
+ if (m_len <= M4_MAX_LEN)
|
|
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8)
|
|
| (m_len - 2));
|
|
- } else {
|
|
- m_len -= M4_MAX_LEN;
|
|
- *op++ = (M4_MARKER
|
|
- | ((m_off & 0x4000) >> 11));
|
|
-m3_m4_len:
|
|
- while (m_len > 255) {
|
|
- m_len -= 255;
|
|
- *op++ = 0;
|
|
- }
|
|
-
|
|
- *op++ = (m_len);
|
|
+ else {
|
|
+ m_len -= M4_MAX_LEN;
|
|
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8));
|
|
+ while (unlikely(m_len > 255)) {
|
|
+ m_len -= 255;
|
|
+ *op++ = 0;
|
|
}
|
|
+ *op++ = (m_len);
|
|
}
|
|
-m3_m4_offset:
|
|
- *op++ = ((m_off & 63) << 2);
|
|
+ *op++ = (m_off << 2);
|
|
*op++ = (m_off >> 6);
|
|
}
|
|
-
|
|
- ii = ip;
|
|
- if (unlikely(ip >= ip_end))
|
|
- break;
|
|
+ goto next;
|
|
}
|
|
-
|
|
*out_len = op - out;
|
|
- return in_end - ii;
|
|
+ return in_end - (ii - ti);
|
|
}
|
|
|
|
-int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
|
|
- size_t *out_len, void *wrkmem)
|
|
+int lzo1x_1_compress(const unsigned char *in, size_t in_len,
|
|
+ unsigned char *out, size_t *out_len,
|
|
+ void *wrkmem)
|
|
{
|
|
- const unsigned char *ii;
|
|
+ const unsigned char *ip = in;
|
|
unsigned char *op = out;
|
|
- size_t t;
|
|
+ size_t l = in_len;
|
|
+ size_t t = 0;
|
|
|
|
- if (unlikely(in_len <= M2_MAX_LEN + 5)) {
|
|
- t = in_len;
|
|
- } else {
|
|
- t = _lzo1x_1_do_compress(in, in_len, op, out_len, wrkmem);
|
|
+ while (l > 20) {
|
|
+ size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
|
|
+ uintptr_t ll_end = (uintptr_t) ip + ll;
|
|
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end)
|
|
+ break;
|
|
+ BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
|
|
+ memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
|
|
+ t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem);
|
|
+ ip += ll;
|
|
op += *out_len;
|
|
+ l -= ll;
|
|
}
|
|
+ t += l;
|
|
|
|
if (t > 0) {
|
|
- ii = in + in_len - t;
|
|
+ const unsigned char *ii = in + in_len - t;
|
|
|
|
if (op == out && t <= 238) {
|
|
*op++ = (17 + t);
|
|
@@ -198,16 +247,21 @@ int lzo1x_1_compress(const unsigned char *in, size_t in_len, unsigned char *out,
|
|
*op++ = (t - 3);
|
|
} else {
|
|
size_t tt = t - 18;
|
|
-
|
|
*op++ = 0;
|
|
while (tt > 255) {
|
|
tt -= 255;
|
|
*op++ = 0;
|
|
}
|
|
-
|
|
*op++ = tt;
|
|
}
|
|
- do {
|
|
+ if (t >= 16) do {
|
|
+ COPY8(op, ii);
|
|
+ COPY8(op + 8, ii + 8);
|
|
+ op += 16;
|
|
+ ii += 16;
|
|
+ t -= 16;
|
|
+ } while (t >= 16);
|
|
+ if (t > 0) do {
|
|
*op++ = *ii++;
|
|
} while (--t > 0);
|
|
}
|
|
@@ -223,4 +277,3 @@ EXPORT_SYMBOL_GPL(lzo1x_1_compress);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_DESCRIPTION("LZO1X-1 Compressor");
|
|
-
|
|
diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c
|
|
deleted file mode 100644
|
|
index f2fd09850223..000000000000
|
|
--- a/lib/lzo/lzo1x_decompress.c
|
|
+++ /dev/null
|
|
@@ -1,255 +0,0 @@
|
|
-/*
|
|
- * LZO1X Decompressor from MiniLZO
|
|
- *
|
|
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
- *
|
|
- * The full LZO package can be found at:
|
|
- * http://www.oberhumer.com/opensource/lzo/
|
|
- *
|
|
- * Changed for kernel use by:
|
|
- * Nitin Gupta <nitingupta910@gmail.com>
|
|
- * Richard Purdie <rpurdie@openedhand.com>
|
|
- */
|
|
-
|
|
-#ifndef STATIC
|
|
-#include <linux/module.h>
|
|
-#include <linux/kernel.h>
|
|
-#endif
|
|
-
|
|
-#include <asm/unaligned.h>
|
|
-#include <linux/lzo.h>
|
|
-#include "lzodefs.h"
|
|
-
|
|
-#define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x))
|
|
-#define HAVE_OP(x, op_end, op) ((size_t)(op_end - op) < (x))
|
|
-#define HAVE_LB(m_pos, out, op) (m_pos < out || m_pos >= op)
|
|
-
|
|
-#define COPY4(dst, src) \
|
|
- put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
|
|
-
|
|
-int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
|
|
- unsigned char *out, size_t *out_len)
|
|
-{
|
|
- const unsigned char * const ip_end = in + in_len;
|
|
- unsigned char * const op_end = out + *out_len;
|
|
- const unsigned char *ip = in, *m_pos;
|
|
- unsigned char *op = out;
|
|
- size_t t;
|
|
-
|
|
- *out_len = 0;
|
|
-
|
|
- if (*ip > 17) {
|
|
- t = *ip++ - 17;
|
|
- if (t < 4)
|
|
- goto match_next;
|
|
- if (HAVE_OP(t, op_end, op))
|
|
- goto output_overrun;
|
|
- if (HAVE_IP(t + 1, ip_end, ip))
|
|
- goto input_overrun;
|
|
- do {
|
|
- *op++ = *ip++;
|
|
- } while (--t > 0);
|
|
- goto first_literal_run;
|
|
- }
|
|
-
|
|
- while ((ip < ip_end)) {
|
|
- t = *ip++;
|
|
- if (t >= 16)
|
|
- goto match;
|
|
- if (t == 0) {
|
|
- if (HAVE_IP(1, ip_end, ip))
|
|
- goto input_overrun;
|
|
- while (*ip == 0) {
|
|
- t += 255;
|
|
- ip++;
|
|
- if (HAVE_IP(1, ip_end, ip))
|
|
- goto input_overrun;
|
|
- }
|
|
- t += 15 + *ip++;
|
|
- }
|
|
- if (HAVE_OP(t + 3, op_end, op))
|
|
- goto output_overrun;
|
|
- if (HAVE_IP(t + 4, ip_end, ip))
|
|
- goto input_overrun;
|
|
-
|
|
- COPY4(op, ip);
|
|
- op += 4;
|
|
- ip += 4;
|
|
- if (--t > 0) {
|
|
- if (t >= 4) {
|
|
- do {
|
|
- COPY4(op, ip);
|
|
- op += 4;
|
|
- ip += 4;
|
|
- t -= 4;
|
|
- } while (t >= 4);
|
|
- if (t > 0) {
|
|
- do {
|
|
- *op++ = *ip++;
|
|
- } while (--t > 0);
|
|
- }
|
|
- } else {
|
|
- do {
|
|
- *op++ = *ip++;
|
|
- } while (--t > 0);
|
|
- }
|
|
- }
|
|
-
|
|
-first_literal_run:
|
|
- t = *ip++;
|
|
- if (t >= 16)
|
|
- goto match;
|
|
- m_pos = op - (1 + M2_MAX_OFFSET);
|
|
- m_pos -= t >> 2;
|
|
- m_pos -= *ip++ << 2;
|
|
-
|
|
- if (HAVE_LB(m_pos, out, op))
|
|
- goto lookbehind_overrun;
|
|
-
|
|
- if (HAVE_OP(3, op_end, op))
|
|
- goto output_overrun;
|
|
- *op++ = *m_pos++;
|
|
- *op++ = *m_pos++;
|
|
- *op++ = *m_pos;
|
|
-
|
|
- goto match_done;
|
|
-
|
|
- do {
|
|
-match:
|
|
- if (t >= 64) {
|
|
- m_pos = op - 1;
|
|
- m_pos -= (t >> 2) & 7;
|
|
- m_pos -= *ip++ << 3;
|
|
- t = (t >> 5) - 1;
|
|
- if (HAVE_LB(m_pos, out, op))
|
|
- goto lookbehind_overrun;
|
|
- if (HAVE_OP(t + 3 - 1, op_end, op))
|
|
- goto output_overrun;
|
|
- goto copy_match;
|
|
- } else if (t >= 32) {
|
|
- t &= 31;
|
|
- if (t == 0) {
|
|
- if (HAVE_IP(1, ip_end, ip))
|
|
- goto input_overrun;
|
|
- while (*ip == 0) {
|
|
- t += 255;
|
|
- ip++;
|
|
- if (HAVE_IP(1, ip_end, ip))
|
|
- goto input_overrun;
|
|
- }
|
|
- t += 31 + *ip++;
|
|
- }
|
|
- m_pos = op - 1;
|
|
- m_pos -= get_unaligned_le16(ip) >> 2;
|
|
- ip += 2;
|
|
- } else if (t >= 16) {
|
|
- m_pos = op;
|
|
- m_pos -= (t & 8) << 11;
|
|
-
|
|
- t &= 7;
|
|
- if (t == 0) {
|
|
- if (HAVE_IP(1, ip_end, ip))
|
|
- goto input_overrun;
|
|
- while (*ip == 0) {
|
|
- t += 255;
|
|
- ip++;
|
|
- if (HAVE_IP(1, ip_end, ip))
|
|
- goto input_overrun;
|
|
- }
|
|
- t += 7 + *ip++;
|
|
- }
|
|
- m_pos -= get_unaligned_le16(ip) >> 2;
|
|
- ip += 2;
|
|
- if (m_pos == op)
|
|
- goto eof_found;
|
|
- m_pos -= 0x4000;
|
|
- } else {
|
|
- m_pos = op - 1;
|
|
- m_pos -= t >> 2;
|
|
- m_pos -= *ip++ << 2;
|
|
-
|
|
- if (HAVE_LB(m_pos, out, op))
|
|
- goto lookbehind_overrun;
|
|
- if (HAVE_OP(2, op_end, op))
|
|
- goto output_overrun;
|
|
-
|
|
- *op++ = *m_pos++;
|
|
- *op++ = *m_pos;
|
|
- goto match_done;
|
|
- }
|
|
-
|
|
- if (HAVE_LB(m_pos, out, op))
|
|
- goto lookbehind_overrun;
|
|
- if (HAVE_OP(t + 3 - 1, op_end, op))
|
|
- goto output_overrun;
|
|
-
|
|
- if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) {
|
|
- COPY4(op, m_pos);
|
|
- op += 4;
|
|
- m_pos += 4;
|
|
- t -= 4 - (3 - 1);
|
|
- do {
|
|
- COPY4(op, m_pos);
|
|
- op += 4;
|
|
- m_pos += 4;
|
|
- t -= 4;
|
|
- } while (t >= 4);
|
|
- if (t > 0)
|
|
- do {
|
|
- *op++ = *m_pos++;
|
|
- } while (--t > 0);
|
|
- } else {
|
|
-copy_match:
|
|
- *op++ = *m_pos++;
|
|
- *op++ = *m_pos++;
|
|
- do {
|
|
- *op++ = *m_pos++;
|
|
- } while (--t > 0);
|
|
- }
|
|
-match_done:
|
|
- t = ip[-2] & 3;
|
|
- if (t == 0)
|
|
- break;
|
|
-match_next:
|
|
- if (HAVE_OP(t, op_end, op))
|
|
- goto output_overrun;
|
|
- if (HAVE_IP(t + 1, ip_end, ip))
|
|
- goto input_overrun;
|
|
-
|
|
- *op++ = *ip++;
|
|
- if (t > 1) {
|
|
- *op++ = *ip++;
|
|
- if (t > 2)
|
|
- *op++ = *ip++;
|
|
- }
|
|
-
|
|
- t = *ip++;
|
|
- } while (ip < ip_end);
|
|
- }
|
|
-
|
|
- *out_len = op - out;
|
|
- return LZO_E_EOF_NOT_FOUND;
|
|
-
|
|
-eof_found:
|
|
- *out_len = op - out;
|
|
- return (ip == ip_end ? LZO_E_OK :
|
|
- (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
|
|
-input_overrun:
|
|
- *out_len = op - out;
|
|
- return LZO_E_INPUT_OVERRUN;
|
|
-
|
|
-output_overrun:
|
|
- *out_len = op - out;
|
|
- return LZO_E_OUTPUT_OVERRUN;
|
|
-
|
|
-lookbehind_overrun:
|
|
- *out_len = op - out;
|
|
- return LZO_E_LOOKBEHIND_OVERRUN;
|
|
-}
|
|
-#ifndef STATIC
|
|
-EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
|
|
-
|
|
-MODULE_LICENSE("GPL");
|
|
-MODULE_DESCRIPTION("LZO1X Decompressor");
|
|
-
|
|
-#endif
|
|
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
|
|
new file mode 100644
|
|
index 000000000000..8563081e8da3
|
|
--- /dev/null
|
|
+++ b/lib/lzo/lzo1x_decompress_safe.c
|
|
@@ -0,0 +1,257 @@
|
|
+/*
|
|
+ * LZO1X Decompressor from LZO
|
|
+ *
|
|
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
+ *
|
|
+ * The full LZO package can be found at:
|
|
+ * http://www.oberhumer.com/opensource/lzo/
|
|
+ *
|
|
+ * Changed for Linux kernel use by:
|
|
+ * Nitin Gupta <nitingupta910@gmail.com>
|
|
+ * Richard Purdie <rpurdie@openedhand.com>
|
|
+ */
|
|
+
|
|
+#ifndef STATIC
|
|
+#include <linux/module.h>
|
|
+#include <linux/kernel.h>
|
|
+#endif
|
|
+#include <asm/unaligned.h>
|
|
+#include <linux/lzo.h>
|
|
+#include "lzodefs.h"
|
|
+
|
|
+#define HAVE_IP(t, x) \
|
|
+ (((size_t)(ip_end - ip) >= (size_t)(t + x)) && \
|
|
+ (((t + x) >= t) && ((t + x) >= x)))
|
|
+
|
|
+#define HAVE_OP(t, x) \
|
|
+ (((size_t)(op_end - op) >= (size_t)(t + x)) && \
|
|
+ (((t + x) >= t) && ((t + x) >= x)))
|
|
+
|
|
+#define NEED_IP(t, x) \
|
|
+ do { \
|
|
+ if (!HAVE_IP(t, x)) \
|
|
+ goto input_overrun; \
|
|
+ } while (0)
|
|
+
|
|
+#define NEED_OP(t, x) \
|
|
+ do { \
|
|
+ if (!HAVE_OP(t, x)) \
|
|
+ goto output_overrun; \
|
|
+ } while (0)
|
|
+
|
|
+#define TEST_LB(m_pos) \
|
|
+ do { \
|
|
+ if ((m_pos) < out) \
|
|
+ goto lookbehind_overrun; \
|
|
+ } while (0)
|
|
+
|
|
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
|
|
+ unsigned char *out, size_t *out_len)
|
|
+{
|
|
+ unsigned char *op;
|
|
+ const unsigned char *ip;
|
|
+ size_t t, next;
|
|
+ size_t state = 0;
|
|
+ const unsigned char *m_pos;
|
|
+ const unsigned char * const ip_end = in + in_len;
|
|
+ unsigned char * const op_end = out + *out_len;
|
|
+
|
|
+ op = out;
|
|
+ ip = in;
|
|
+
|
|
+ if (unlikely(in_len < 3))
|
|
+ goto input_overrun;
|
|
+ if (*ip > 17) {
|
|
+ t = *ip++ - 17;
|
|
+ if (t < 4) {
|
|
+ next = t;
|
|
+ goto match_next;
|
|
+ }
|
|
+ goto copy_literal_run;
|
|
+ }
|
|
+
|
|
+ for (;;) {
|
|
+ t = *ip++;
|
|
+ if (t < 16) {
|
|
+ if (likely(state == 0)) {
|
|
+ if (unlikely(t == 0)) {
|
|
+ while (unlikely(*ip == 0)) {
|
|
+ t += 255;
|
|
+ ip++;
|
|
+ NEED_IP(1, 0);
|
|
+ }
|
|
+ t += 15 + *ip++;
|
|
+ }
|
|
+ t += 3;
|
|
+copy_literal_run:
|
|
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
|
+ if (likely(HAVE_IP(t, 15) && HAVE_OP(t, 15))) {
|
|
+ const unsigned char *ie = ip + t;
|
|
+ unsigned char *oe = op + t;
|
|
+ do {
|
|
+ COPY8(op, ip);
|
|
+ op += 8;
|
|
+ ip += 8;
|
|
+ COPY8(op, ip);
|
|
+ op += 8;
|
|
+ ip += 8;
|
|
+ } while (ip < ie);
|
|
+ ip = ie;
|
|
+ op = oe;
|
|
+ } else
|
|
+#endif
|
|
+ {
|
|
+ NEED_OP(t, 0);
|
|
+ NEED_IP(t, 3);
|
|
+ do {
|
|
+ *op++ = *ip++;
|
|
+ } while (--t > 0);
|
|
+ }
|
|
+ state = 4;
|
|
+ continue;
|
|
+ } else if (state != 4) {
|
|
+ next = t & 3;
|
|
+ m_pos = op - 1;
|
|
+ m_pos -= t >> 2;
|
|
+ m_pos -= *ip++ << 2;
|
|
+ TEST_LB(m_pos);
|
|
+ NEED_OP(2, 0);
|
|
+ op[0] = m_pos[0];
|
|
+ op[1] = m_pos[1];
|
|
+ op += 2;
|
|
+ goto match_next;
|
|
+ } else {
|
|
+ next = t & 3;
|
|
+ m_pos = op - (1 + M2_MAX_OFFSET);
|
|
+ m_pos -= t >> 2;
|
|
+ m_pos -= *ip++ << 2;
|
|
+ t = 3;
|
|
+ }
|
|
+ } else if (t >= 64) {
|
|
+ next = t & 3;
|
|
+ m_pos = op - 1;
|
|
+ m_pos -= (t >> 2) & 7;
|
|
+ m_pos -= *ip++ << 3;
|
|
+ t = (t >> 5) - 1 + (3 - 1);
|
|
+ } else if (t >= 32) {
|
|
+ t = (t & 31) + (3 - 1);
|
|
+ if (unlikely(t == 2)) {
|
|
+ while (unlikely(*ip == 0)) {
|
|
+ t += 255;
|
|
+ ip++;
|
|
+ NEED_IP(1, 0);
|
|
+ }
|
|
+ t += 31 + *ip++;
|
|
+ NEED_IP(2, 0);
|
|
+ }
|
|
+ m_pos = op - 1;
|
|
+ next = get_unaligned_le16(ip);
|
|
+ ip += 2;
|
|
+ m_pos -= next >> 2;
|
|
+ next &= 3;
|
|
+ } else {
|
|
+ m_pos = op;
|
|
+ m_pos -= (t & 8) << 11;
|
|
+ t = (t & 7) + (3 - 1);
|
|
+ if (unlikely(t == 2)) {
|
|
+ while (unlikely(*ip == 0)) {
|
|
+ t += 255;
|
|
+ ip++;
|
|
+ NEED_IP(1, 0);
|
|
+ }
|
|
+ t += 7 + *ip++;
|
|
+ NEED_IP(2, 0);
|
|
+ }
|
|
+ next = get_unaligned_le16(ip);
|
|
+ ip += 2;
|
|
+ m_pos -= next >> 2;
|
|
+ next &= 3;
|
|
+ if (m_pos == op)
|
|
+ goto eof_found;
|
|
+ m_pos -= 0x4000;
|
|
+ }
|
|
+ TEST_LB(m_pos);
|
|
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
|
+ if (op - m_pos >= 8) {
|
|
+ unsigned char *oe = op + t;
|
|
+ if (likely(HAVE_OP(t, 15))) {
|
|
+ do {
|
|
+ COPY8(op, m_pos);
|
|
+ op += 8;
|
|
+ m_pos += 8;
|
|
+ COPY8(op, m_pos);
|
|
+ op += 8;
|
|
+ m_pos += 8;
|
|
+ } while (op < oe);
|
|
+ op = oe;
|
|
+ if (HAVE_IP(6, 0)) {
|
|
+ state = next;
|
|
+ COPY4(op, ip);
|
|
+ op += next;
|
|
+ ip += next;
|
|
+ continue;
|
|
+ }
|
|
+ } else {
|
|
+ NEED_OP(t, 0);
|
|
+ do {
|
|
+ *op++ = *m_pos++;
|
|
+ } while (op < oe);
|
|
+ }
|
|
+ } else
|
|
+#endif
|
|
+ {
|
|
+ unsigned char *oe = op + t;
|
|
+ NEED_OP(t, 0);
|
|
+ op[0] = m_pos[0];
|
|
+ op[1] = m_pos[1];
|
|
+ op += 2;
|
|
+ m_pos += 2;
|
|
+ do {
|
|
+ *op++ = *m_pos++;
|
|
+ } while (op < oe);
|
|
+ }
|
|
+match_next:
|
|
+ state = next;
|
|
+ t = next;
|
|
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
|
|
+ if (likely(HAVE_IP(6, 0) && HAVE_OP(4, 0))) {
|
|
+ COPY4(op, ip);
|
|
+ op += t;
|
|
+ ip += t;
|
|
+ } else
|
|
+#endif
|
|
+ {
|
|
+ NEED_IP(t, 3);
|
|
+ NEED_OP(t, 0);
|
|
+ while (t > 0) {
|
|
+ *op++ = *ip++;
|
|
+ t--;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+eof_found:
|
|
+ *out_len = op - out;
|
|
+ return (t != 3 ? LZO_E_ERROR :
|
|
+ ip == ip_end ? LZO_E_OK :
|
|
+ ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
|
|
+
|
|
+input_overrun:
|
|
+ *out_len = op - out;
|
|
+ return LZO_E_INPUT_OVERRUN;
|
|
+
|
|
+output_overrun:
|
|
+ *out_len = op - out;
|
|
+ return LZO_E_OUTPUT_OVERRUN;
|
|
+
|
|
+lookbehind_overrun:
|
|
+ *out_len = op - out;
|
|
+ return LZO_E_LOOKBEHIND_OVERRUN;
|
|
+}
|
|
+#ifndef STATIC
|
|
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
|
|
+
|
|
+MODULE_LICENSE("GPL");
|
|
+MODULE_DESCRIPTION("LZO1X Decompressor");
|
|
+
|
|
+#endif
|
|
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
|
|
index b6d482c492ef..6710b83ce72e 100644
|
|
--- a/lib/lzo/lzodefs.h
|
|
+++ b/lib/lzo/lzodefs.h
|
|
@@ -1,19 +1,37 @@
|
|
/*
|
|
* lzodefs.h -- architecture, OS and compiler specific defines
|
|
*
|
|
- * Copyright (C) 1996-2005 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
|
|
*
|
|
* The full LZO package can be found at:
|
|
* http://www.oberhumer.com/opensource/lzo/
|
|
*
|
|
- * Changed for kernel use by:
|
|
+ * Changed for Linux kernel use by:
|
|
* Nitin Gupta <nitingupta910@gmail.com>
|
|
* Richard Purdie <rpurdie@openedhand.com>
|
|
*/
|
|
|
|
-#define LZO_VERSION 0x2020
|
|
-#define LZO_VERSION_STRING "2.02"
|
|
-#define LZO_VERSION_DATE "Oct 17 2005"
|
|
+
|
|
+#define COPY4(dst, src) \
|
|
+ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
|
|
+#if defined(__x86_64__)
|
|
+#define COPY8(dst, src) \
|
|
+ put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
|
|
+#else
|
|
+#define COPY8(dst, src) \
|
|
+ COPY4(dst, src); COPY4((dst) + 4, (src) + 4)
|
|
+#endif
|
|
+
|
|
+#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
|
|
+#error "conflicting endian definitions"
|
|
+#elif defined(__x86_64__)
|
|
+#define LZO_USE_CTZ64 1
|
|
+#define LZO_USE_CTZ32 1
|
|
+#elif defined(__i386__) || defined(__powerpc__)
|
|
+#define LZO_USE_CTZ32 1
|
|
+#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5)
|
|
+#define LZO_USE_CTZ32 1
|
|
+#endif
|
|
|
|
#define M1_MAX_OFFSET 0x0400
|
|
#define M2_MAX_OFFSET 0x0800
|
|
@@ -34,10 +52,8 @@
|
|
#define M3_MARKER 32
|
|
#define M4_MARKER 16
|
|
|
|
-#define D_BITS 14
|
|
-#define D_MASK ((1u << D_BITS) - 1)
|
|
+#define lzo_dict_t unsigned short
|
|
+#define D_BITS 13
|
|
+#define D_SIZE (1u << D_BITS)
|
|
+#define D_MASK (D_SIZE - 1)
|
|
#define D_HIGH ((D_MASK >> 1) + 1)
|
|
-
|
|
-#define DX2(p, s1, s2) (((((size_t)((p)[2]) << (s2)) ^ (p)[1]) \
|
|
- << (s1)) ^ (p)[0])
|
|
-#define DX3(p, s1, s2, s3) ((DX2((p)+1, s2, s3) << (s1)) ^ (p)[0])
|
|
diff --git a/lib/nlattr.c b/lib/nlattr.c
|
|
index 01c67507dc43..60abf1b5545a 100644
|
|
--- a/lib/nlattr.c
|
|
+++ b/lib/nlattr.c
|
|
@@ -13,6 +13,7 @@
|
|
#include <linux/skbuff.h>
|
|
#include <linux/string.h>
|
|
#include <linux/types.h>
|
|
+#include <linux/ratelimit.h>
|
|
#include <net/netlink.h>
|
|
|
|
static const u16 nla_attr_minlen[NLA_TYPE_MAX+1] = {
|
|
@@ -197,8 +198,8 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
|
|
}
|
|
|
|
if (unlikely(rem > 0))
|
|
- printk(KERN_WARNING "netlink: %d bytes leftover after parsing "
|
|
- "attributes.\n", rem);
|
|
+ pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
|
|
+ rem, current->comm);
|
|
|
|
err = 0;
|
|
errout:
|
|
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
|
|
index d2f634880bdd..490132664d07 100644
|
|
--- a/net/ipv4/ipip.c
|
|
+++ b/net/ipv4/ipip.c
|
|
@@ -908,4 +908,5 @@ static void __exit ipip_fini(void)
|
|
module_init(ipip_init);
|
|
module_exit(ipip_fini);
|
|
MODULE_LICENSE("GPL");
|
|
+MODULE_ALIAS_RTNL_LINK("ipip");
|
|
MODULE_ALIAS_NETDEV("tunl0");
|
|
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
|
|
index 5a2d819d8262..077b9a3f8d25 100644
|
|
--- a/net/ipv6/ip6_output.c
|
|
+++ b/net/ipv6/ip6_output.c
|
|
@@ -611,7 +611,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
|
|
void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
|
|
{
|
|
static atomic_t ipv6_fragmentation_id;
|
|
- int old, new;
|
|
+ int ident;
|
|
|
|
if (rt && !(rt->dst.flags & DST_NOPEER)) {
|
|
struct inet_peer *peer;
|
|
@@ -624,13 +624,8 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
|
|
return;
|
|
}
|
|
}
|
|
- do {
|
|
- old = atomic_read(&ipv6_fragmentation_id);
|
|
- new = old + 1;
|
|
- if (!new)
|
|
- new = 1;
|
|
- } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old);
|
|
- fhdr->identification = htonl(new);
|
|
+ ident = atomic_inc_return(&ipv6_fragmentation_id);
|
|
+ fhdr->identification = htonl(ident);
|
|
}
|
|
|
|
int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
|
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
|
|
index aa21da6a09cd..b876a2f81263 100644
|
|
--- a/net/ipv6/ip6_tunnel.c
|
|
+++ b/net/ipv6/ip6_tunnel.c
|
|
@@ -57,6 +57,7 @@
|
|
MODULE_AUTHOR("Ville Nuorvala");
|
|
MODULE_DESCRIPTION("IPv6 tunneling device");
|
|
MODULE_LICENSE("GPL");
|
|
+MODULE_ALIAS_RTNL_LINK("ip6tnl");
|
|
MODULE_ALIAS_NETDEV("ip6tnl0");
|
|
|
|
#ifdef IP6_TNL_DEBUG
|
|
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
|
|
index c4ffd1743528..3f20ba4f9547 100644
|
|
--- a/net/ipv6/sit.c
|
|
+++ b/net/ipv6/sit.c
|
|
@@ -1303,4 +1303,5 @@ static int __init sit_init(void)
|
|
module_init(sit_init);
|
|
module_exit(sit_cleanup);
|
|
MODULE_LICENSE("GPL");
|
|
+MODULE_ALIAS_RTNL_LINK("sit");
|
|
MODULE_ALIAS_NETDEV("sit0");
|
|
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
|
|
index 3c04692d699a..25b207b3ffe4 100644
|
|
--- a/net/sctp/associola.c
|
|
+++ b/net/sctp/associola.c
|
|
@@ -389,7 +389,7 @@ void sctp_association_free(struct sctp_association *asoc)
|
|
/* Only real associations count against the endpoint, so
|
|
* don't bother for if this is a temporary association.
|
|
*/
|
|
- if (!asoc->temp) {
|
|
+ if (!list_empty(&asoc->asocs)) {
|
|
list_del(&asoc->asocs);
|
|
|
|
/* Decrement the backlog value for a TCP-style listening
|
|
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
|
|
index 8901501425f4..c487715698ab 100644
|
|
--- a/security/integrity/evm/evm_main.c
|
|
+++ b/security/integrity/evm/evm_main.c
|
|
@@ -271,12 +271,20 @@ static int evm_protect_xattr(struct dentry *dentry, const char *xattr_name,
|
|
* @xattr_value: pointer to the new extended attribute value
|
|
* @xattr_value_len: pointer to the new extended attribute value length
|
|
*
|
|
- * Updating 'security.evm' requires CAP_SYS_ADMIN privileges and that
|
|
- * the current value is valid.
|
|
+ * Before allowing the 'security.evm' protected xattr to be updated,
|
|
+ * verify the existing value is valid. As only the kernel should have
|
|
+ * access to the EVM encrypted key needed to calculate the HMAC, prevent
|
|
+ * userspace from writing HMAC value. Writing 'security.evm' requires
|
|
+ * requires CAP_SYS_ADMIN privileges.
|
|
*/
|
|
int evm_inode_setxattr(struct dentry *dentry, const char *xattr_name,
|
|
const void *xattr_value, size_t xattr_value_len)
|
|
{
|
|
+ const struct evm_ima_xattr_data *xattr_data = xattr_value;
|
|
+
|
|
+ if ((strcmp(xattr_name, XATTR_NAME_EVM) == 0)
|
|
+ && (xattr_data->type == EVM_XATTR_HMAC))
|
|
+ return -EPERM;
|
|
return evm_protect_xattr(dentry, xattr_name, xattr_value,
|
|
xattr_value_len);
|
|
}
|
|
diff --git a/sound/core/control.c b/sound/core/control.c
|
|
index daa4fc8872f3..e773d5ed1e9a 100644
|
|
--- a/sound/core/control.c
|
|
+++ b/sound/core/control.c
|
|
@@ -288,6 +288,10 @@ static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
|
|
{
|
|
struct snd_kcontrol *kctl;
|
|
|
|
+ /* Make sure that the ids assigned to the control do not wrap around */
|
|
+ if (card->last_numid >= UINT_MAX - count)
|
|
+ card->last_numid = 0;
|
|
+
|
|
list_for_each_entry(kctl, &card->controls, list) {
|
|
if (kctl->id.numid < card->last_numid + 1 + count &&
|
|
kctl->id.numid + kctl->count > card->last_numid + 1) {
|
|
@@ -329,6 +333,7 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
|
{
|
|
struct snd_ctl_elem_id id;
|
|
unsigned int idx;
|
|
+ unsigned int count;
|
|
int err = -EINVAL;
|
|
|
|
if (! kcontrol)
|
|
@@ -336,6 +341,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
|
if (snd_BUG_ON(!card || !kcontrol->info))
|
|
goto error;
|
|
id = kcontrol->id;
|
|
+ if (id.index > UINT_MAX - kcontrol->count)
|
|
+ goto error;
|
|
+
|
|
down_write(&card->controls_rwsem);
|
|
if (snd_ctl_find_id(card, &id)) {
|
|
up_write(&card->controls_rwsem);
|
|
@@ -357,8 +365,9 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
|
|
card->controls_count += kcontrol->count;
|
|
kcontrol->id.numid = card->last_numid + 1;
|
|
card->last_numid += kcontrol->count;
|
|
+ count = kcontrol->count;
|
|
up_write(&card->controls_rwsem);
|
|
- for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
|
|
+ for (idx = 0; idx < count; idx++, id.index++, id.numid++)
|
|
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
|
|
return 0;
|
|
|
|
@@ -387,6 +396,7 @@ int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol,
|
|
bool add_on_replace)
|
|
{
|
|
struct snd_ctl_elem_id id;
|
|
+ unsigned int count;
|
|
unsigned int idx;
|
|
struct snd_kcontrol *old;
|
|
int ret;
|
|
@@ -422,8 +432,9 @@ add:
|
|
card->controls_count += kcontrol->count;
|
|
kcontrol->id.numid = card->last_numid + 1;
|
|
card->last_numid += kcontrol->count;
|
|
+ count = kcontrol->count;
|
|
up_write(&card->controls_rwsem);
|
|
- for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++)
|
|
+ for (idx = 0; idx < count; idx++, id.index++, id.numid++)
|
|
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
|
|
return 0;
|
|
|
|
@@ -894,9 +905,9 @@ static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
|
|
result = kctl->put(kctl, control);
|
|
}
|
|
if (result > 0) {
|
|
+ struct snd_ctl_elem_id id = control->id;
|
|
up_read(&card->controls_rwsem);
|
|
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE,
|
|
- &control->id);
|
|
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -988,6 +999,7 @@ static int snd_ctl_elem_unlock(struct snd_ctl_file *file,
|
|
|
|
struct user_element {
|
|
struct snd_ctl_elem_info info;
|
|
+ struct snd_card *card;
|
|
void *elem_data; /* element data */
|
|
unsigned long elem_data_size; /* size of element data in bytes */
|
|
void *tlv_data; /* TLV data */
|
|
@@ -1031,7 +1043,9 @@ static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
|
|
{
|
|
struct user_element *ue = kcontrol->private_data;
|
|
|
|
+ mutex_lock(&ue->card->user_ctl_lock);
|
|
memcpy(&ucontrol->value, ue->elem_data, ue->elem_data_size);
|
|
+ mutex_unlock(&ue->card->user_ctl_lock);
|
|
return 0;
|
|
}
|
|
|
|
@@ -1040,10 +1054,12 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
|
|
{
|
|
int change;
|
|
struct user_element *ue = kcontrol->private_data;
|
|
-
|
|
+
|
|
+ mutex_lock(&ue->card->user_ctl_lock);
|
|
change = memcmp(&ucontrol->value, ue->elem_data, ue->elem_data_size) != 0;
|
|
if (change)
|
|
memcpy(ue->elem_data, &ucontrol->value, ue->elem_data_size);
|
|
+ mutex_unlock(&ue->card->user_ctl_lock);
|
|
return change;
|
|
}
|
|
|
|
@@ -1063,19 +1079,32 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
|
|
new_data = memdup_user(tlv, size);
|
|
if (IS_ERR(new_data))
|
|
return PTR_ERR(new_data);
|
|
+ mutex_lock(&ue->card->user_ctl_lock);
|
|
change = ue->tlv_data_size != size;
|
|
if (!change)
|
|
change = memcmp(ue->tlv_data, new_data, size);
|
|
kfree(ue->tlv_data);
|
|
ue->tlv_data = new_data;
|
|
ue->tlv_data_size = size;
|
|
+ mutex_unlock(&ue->card->user_ctl_lock);
|
|
} else {
|
|
- if (! ue->tlv_data_size || ! ue->tlv_data)
|
|
- return -ENXIO;
|
|
- if (size < ue->tlv_data_size)
|
|
- return -ENOSPC;
|
|
+ int ret = 0;
|
|
+
|
|
+ mutex_lock(&ue->card->user_ctl_lock);
|
|
+ if (!ue->tlv_data_size || !ue->tlv_data) {
|
|
+ ret = -ENXIO;
|
|
+ goto err_unlock;
|
|
+ }
|
|
+ if (size < ue->tlv_data_size) {
|
|
+ ret = -ENOSPC;
|
|
+ goto err_unlock;
|
|
+ }
|
|
if (copy_to_user(tlv, ue->tlv_data, ue->tlv_data_size))
|
|
- return -EFAULT;
|
|
+ ret = -EFAULT;
|
|
+err_unlock:
|
|
+ mutex_unlock(&ue->card->user_ctl_lock);
|
|
+ if (ret)
|
|
+ return ret;
|
|
}
|
|
return change;
|
|
}
|
|
@@ -1133,8 +1162,6 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
|
struct user_element *ue;
|
|
int idx, err;
|
|
|
|
- if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS)
|
|
- return -ENOMEM;
|
|
if (info->count < 1)
|
|
return -EINVAL;
|
|
access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
|
|
@@ -1143,21 +1170,16 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
|
SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE));
|
|
info->id.numid = 0;
|
|
memset(&kctl, 0, sizeof(kctl));
|
|
- down_write(&card->controls_rwsem);
|
|
- _kctl = snd_ctl_find_id(card, &info->id);
|
|
- err = 0;
|
|
- if (_kctl) {
|
|
- if (replace)
|
|
- err = snd_ctl_remove(card, _kctl);
|
|
- else
|
|
- err = -EBUSY;
|
|
- } else {
|
|
- if (replace)
|
|
- err = -ENOENT;
|
|
+
|
|
+ if (replace) {
|
|
+ err = snd_ctl_remove_user_ctl(file, &info->id);
|
|
+ if (err)
|
|
+ return err;
|
|
}
|
|
- up_write(&card->controls_rwsem);
|
|
- if (err < 0)
|
|
- return err;
|
|
+
|
|
+ if (card->user_ctl_count >= MAX_USER_CONTROLS)
|
|
+ return -ENOMEM;
|
|
+
|
|
memcpy(&kctl.id, &info->id, sizeof(info->id));
|
|
kctl.count = info->owner ? info->owner : 1;
|
|
access |= SNDRV_CTL_ELEM_ACCESS_USER;
|
|
@@ -1207,6 +1229,7 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
|
|
ue = kzalloc(sizeof(struct user_element) + private_size, GFP_KERNEL);
|
|
if (ue == NULL)
|
|
return -ENOMEM;
|
|
+ ue->card = card;
|
|
ue->info = *info;
|
|
ue->info.access = 0;
|
|
ue->elem_data = (char *)ue + sizeof(*ue);
|
|
@@ -1318,8 +1341,9 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
|
|
}
|
|
err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
|
|
if (err > 0) {
|
|
+ struct snd_ctl_elem_id id = kctl->id;
|
|
up_read(&card->controls_rwsem);
|
|
- snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
|
|
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &id);
|
|
return 0;
|
|
}
|
|
} else {
|
|
diff --git a/sound/core/init.c b/sound/core/init.c
|
|
index 7b012d15c2cf..41020d7395f3 100644
|
|
--- a/sound/core/init.c
|
|
+++ b/sound/core/init.c
|
|
@@ -208,6 +208,7 @@ int snd_card_create(int idx, const char *xid,
|
|
INIT_LIST_HEAD(&card->devices);
|
|
init_rwsem(&card->controls_rwsem);
|
|
rwlock_init(&card->ctl_files_rwlock);
|
|
+ mutex_init(&card->user_ctl_lock);
|
|
INIT_LIST_HEAD(&card->controls);
|
|
INIT_LIST_HEAD(&card->ctl_files);
|
|
spin_lock_init(&card->files_lock);
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index 2415dcec3265..4dac0b332a36 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -7062,6 +7062,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
|
|
{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
|
|
{ .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
|
|
{ .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
|
|
+ { .id = 0x10ec0867, .name = "ALC891", .patch = patch_alc882 },
|
|
{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
|
|
{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
|
|
{ .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc882 },
|