mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-21 22:31:51 +00:00
2180 lines
70 KiB
Diff
2180 lines
70 KiB
Diff
diff --git a/Makefile b/Makefile
|
|
index fbf4ec689957..b738f644c71e 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,6 +1,6 @@
|
|
VERSION = 3
|
|
PATCHLEVEL = 14
|
|
-SUBLEVEL = 61
|
|
+SUBLEVEL = 62
|
|
EXTRAVERSION =
|
|
NAME = Remembering Coco
|
|
|
|
diff --git a/arch/arm/boot/dts/kirkwood-ts219.dtsi b/arch/arm/boot/dts/kirkwood-ts219.dtsi
|
|
index 911f3a8cee23..f4227da77265 100644
|
|
--- a/arch/arm/boot/dts/kirkwood-ts219.dtsi
|
|
+++ b/arch/arm/boot/dts/kirkwood-ts219.dtsi
|
|
@@ -47,7 +47,7 @@
|
|
};
|
|
poweroff@12100 {
|
|
compatible = "qnap,power-off";
|
|
- reg = <0x12000 0x100>;
|
|
+ reg = <0x12100 0x100>;
|
|
clocks = <&gate_clk 7>;
|
|
};
|
|
spi@10600 {
|
|
diff --git a/arch/arm/common/icst.c b/arch/arm/common/icst.c
|
|
index 2dc6da70ae59..d7ed252708c5 100644
|
|
--- a/arch/arm/common/icst.c
|
|
+++ b/arch/arm/common/icst.c
|
|
@@ -16,7 +16,7 @@
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
-
|
|
+#include <asm/div64.h>
|
|
#include <asm/hardware/icst.h>
|
|
|
|
/*
|
|
@@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div);
|
|
|
|
unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco)
|
|
{
|
|
- return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]);
|
|
+ u64 dividend = p->ref * 2 * (u64)(vco.v + 8);
|
|
+ u32 divisor = (vco.r + 2) * p->s2div[vco.s];
|
|
+
|
|
+ do_div(dividend, divisor);
|
|
+ return (unsigned long)dividend;
|
|
}
|
|
|
|
EXPORT_SYMBOL(icst_hz);
|
|
@@ -58,6 +62,7 @@ icst_hz_to_vco(const struct icst_params *p, unsigned long freq)
|
|
|
|
if (f > p->vco_min && f <= p->vco_max)
|
|
break;
|
|
+ i++;
|
|
} while (i < 8);
|
|
|
|
if (i >= 8)
|
|
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
|
|
index fdedc31e0f40..093eff182d63 100644
|
|
--- a/arch/arm/mm/proc-v7.S
|
|
+++ b/arch/arm/mm/proc-v7.S
|
|
@@ -95,7 +95,7 @@ ENDPROC(cpu_v7_dcache_clean_area)
|
|
.equ cpu_v7_suspend_size, 4 * 9
|
|
#ifdef CONFIG_ARM_CPU_SUSPEND
|
|
ENTRY(cpu_v7_do_suspend)
|
|
- stmfd sp!, {r4 - r10, lr}
|
|
+ stmfd sp!, {r4 - r11, lr}
|
|
mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
|
|
mrc p15, 0, r5, c13, c0, 3 @ User r/o thread ID
|
|
stmia r0!, {r4 - r5}
|
|
@@ -112,7 +112,7 @@ ENTRY(cpu_v7_do_suspend)
|
|
mrc p15, 0, r9, c1, c0, 1 @ Auxiliary control register
|
|
mrc p15, 0, r10, c1, c0, 2 @ Co-processor access control
|
|
stmia r0, {r5 - r11}
|
|
- ldmfd sp!, {r4 - r10, pc}
|
|
+ ldmfd sp!, {r4 - r11, pc}
|
|
ENDPROC(cpu_v7_do_suspend)
|
|
|
|
ENTRY(cpu_v7_do_resume)
|
|
diff --git a/arch/m32r/kernel/setup.c b/arch/m32r/kernel/setup.c
|
|
index 0392112a5d70..a5ecef7188ba 100644
|
|
--- a/arch/m32r/kernel/setup.c
|
|
+++ b/arch/m32r/kernel/setup.c
|
|
@@ -81,7 +81,10 @@ static struct resource code_resource = {
|
|
};
|
|
|
|
unsigned long memory_start;
|
|
+EXPORT_SYMBOL(memory_start);
|
|
+
|
|
unsigned long memory_end;
|
|
+EXPORT_SYMBOL(memory_end);
|
|
|
|
void __init setup_arch(char **);
|
|
int get_cpuinfo(char *);
|
|
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
|
index 818dce344e82..b3bad672e5d9 100644
|
|
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
|
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
|
|
@@ -1805,7 +1805,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
|
|
|
|
/* Emulate H_SET_DABR/X on P8 for the sake of compat mode guests */
|
|
2: rlwimi r5, r4, 5, DAWRX_DR | DAWRX_DW
|
|
- rlwimi r5, r4, 1, DAWRX_WT
|
|
+ rlwimi r5, r4, 2, DAWRX_WT
|
|
clrrdi r4, r4, 3
|
|
std r4, VCPU_DAWR(r3)
|
|
std r5, VCPU_DAWRX(r3)
|
|
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
|
|
index fed892de9baf..bdd2a44fbb1a 100644
|
|
--- a/arch/x86/mm/pageattr.c
|
|
+++ b/arch/x86/mm/pageattr.c
|
|
@@ -33,7 +33,7 @@ struct cpa_data {
|
|
pgd_t *pgd;
|
|
pgprot_t mask_set;
|
|
pgprot_t mask_clr;
|
|
- int numpages;
|
|
+ unsigned long numpages;
|
|
int flags;
|
|
unsigned long pfn;
|
|
unsigned force_split : 1;
|
|
@@ -1289,7 +1289,7 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias)
|
|
* CPA operation. Either a large page has been
|
|
* preserved or a single page update happened.
|
|
*/
|
|
- BUG_ON(cpa->numpages > numpages);
|
|
+ BUG_ON(cpa->numpages > numpages || !cpa->numpages);
|
|
numpages -= cpa->numpages;
|
|
if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
|
|
cpa->curpage++;
|
|
diff --git a/block/blk-core.c b/block/blk-core.c
|
|
index e45b321cf6a0..46be0cddf819 100644
|
|
--- a/block/blk-core.c
|
|
+++ b/block/blk-core.c
|
|
@@ -3164,6 +3164,9 @@ int blk_pre_runtime_suspend(struct request_queue *q)
|
|
{
|
|
int ret = 0;
|
|
|
|
+ if (!q->dev)
|
|
+ return ret;
|
|
+
|
|
spin_lock_irq(q->queue_lock);
|
|
if (q->nr_pending) {
|
|
ret = -EBUSY;
|
|
@@ -3191,6 +3194,9 @@ EXPORT_SYMBOL(blk_pre_runtime_suspend);
|
|
*/
|
|
void blk_post_runtime_suspend(struct request_queue *q, int err)
|
|
{
|
|
+ if (!q->dev)
|
|
+ return;
|
|
+
|
|
spin_lock_irq(q->queue_lock);
|
|
if (!err) {
|
|
q->rpm_status = RPM_SUSPENDED;
|
|
@@ -3215,6 +3221,9 @@ EXPORT_SYMBOL(blk_post_runtime_suspend);
|
|
*/
|
|
void blk_pre_runtime_resume(struct request_queue *q)
|
|
{
|
|
+ if (!q->dev)
|
|
+ return;
|
|
+
|
|
spin_lock_irq(q->queue_lock);
|
|
q->rpm_status = RPM_RESUMING;
|
|
spin_unlock_irq(q->queue_lock);
|
|
@@ -3237,6 +3246,9 @@ EXPORT_SYMBOL(blk_pre_runtime_resume);
|
|
*/
|
|
void blk_post_runtime_resume(struct request_queue *q, int err)
|
|
{
|
|
+ if (!q->dev)
|
|
+ return;
|
|
+
|
|
spin_lock_irq(q->queue_lock);
|
|
if (!err) {
|
|
q->rpm_status = RPM_ACTIVE;
|
|
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
|
|
index de5ab4876a89..951ecd52226c 100644
|
|
--- a/drivers/gpu/drm/i915/i915_gem.c
|
|
+++ b/drivers/gpu/drm/i915/i915_gem.c
|
|
@@ -3655,6 +3655,7 @@ unlock:
|
|
int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
|
|
struct drm_file *file)
|
|
{
|
|
+ struct drm_i915_private *dev_priv = dev->dev_private;
|
|
struct drm_i915_gem_caching *args = data;
|
|
struct drm_i915_gem_object *obj;
|
|
enum i915_cache_level level;
|
|
@@ -3674,9 +3675,11 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ intel_runtime_pm_get(dev_priv);
|
|
+
|
|
ret = i915_mutex_lock_interruptible(dev);
|
|
if (ret)
|
|
- return ret;
|
|
+ goto rpm_put;
|
|
|
|
obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
|
|
if (&obj->base == NULL) {
|
|
@@ -3689,6 +3692,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
|
|
drm_gem_object_unreference(&obj->base);
|
|
unlock:
|
|
mutex_unlock(&dev->struct_mutex);
|
|
+rpm_put:
|
|
+ intel_runtime_pm_put(dev_priv);
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
|
|
index 4dddeabdfbb0..5da07546e182 100644
|
|
--- a/drivers/iio/adc/ad7793.c
|
|
+++ b/drivers/iio/adc/ad7793.c
|
|
@@ -101,7 +101,7 @@
|
|
#define AD7795_CH_AIN1M_AIN1M 8 /* AIN1(-) - AIN1(-) */
|
|
|
|
/* ID Register Bit Designations (AD7793_REG_ID) */
|
|
-#define AD7785_ID 0xB
|
|
+#define AD7785_ID 0x3
|
|
#define AD7792_ID 0xA
|
|
#define AD7793_ID 0xB
|
|
#define AD7794_ID 0xF
|
|
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
|
|
index f03b92fd3803..aac16fecdfa8 100644
|
|
--- a/drivers/iio/dac/ad5064.c
|
|
+++ b/drivers/iio/dac/ad5064.c
|
|
@@ -113,12 +113,16 @@ enum ad5064_type {
|
|
ID_AD5065,
|
|
ID_AD5628_1,
|
|
ID_AD5628_2,
|
|
+ ID_AD5629_1,
|
|
+ ID_AD5629_2,
|
|
ID_AD5648_1,
|
|
ID_AD5648_2,
|
|
ID_AD5666_1,
|
|
ID_AD5666_2,
|
|
ID_AD5668_1,
|
|
ID_AD5668_2,
|
|
+ ID_AD5669_1,
|
|
+ ID_AD5669_2,
|
|
};
|
|
|
|
static int ad5064_write(struct ad5064_state *st, unsigned int cmd,
|
|
@@ -291,7 +295,7 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
|
|
{ },
|
|
};
|
|
|
|
-#define AD5064_CHANNEL(chan, addr, bits) { \
|
|
+#define AD5064_CHANNEL(chan, addr, bits, _shift) { \
|
|
.type = IIO_VOLTAGE, \
|
|
.indexed = 1, \
|
|
.output = 1, \
|
|
@@ -303,36 +307,39 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
|
|
.sign = 'u', \
|
|
.realbits = (bits), \
|
|
.storagebits = 16, \
|
|
- .shift = 20 - bits, \
|
|
+ .shift = (_shift), \
|
|
}, \
|
|
.ext_info = ad5064_ext_info, \
|
|
}
|
|
|
|
-#define DECLARE_AD5064_CHANNELS(name, bits) \
|
|
+#define DECLARE_AD5064_CHANNELS(name, bits, shift) \
|
|
const struct iio_chan_spec name[] = { \
|
|
- AD5064_CHANNEL(0, 0, bits), \
|
|
- AD5064_CHANNEL(1, 1, bits), \
|
|
- AD5064_CHANNEL(2, 2, bits), \
|
|
- AD5064_CHANNEL(3, 3, bits), \
|
|
- AD5064_CHANNEL(4, 4, bits), \
|
|
- AD5064_CHANNEL(5, 5, bits), \
|
|
- AD5064_CHANNEL(6, 6, bits), \
|
|
- AD5064_CHANNEL(7, 7, bits), \
|
|
+ AD5064_CHANNEL(0, 0, bits, shift), \
|
|
+ AD5064_CHANNEL(1, 1, bits, shift), \
|
|
+ AD5064_CHANNEL(2, 2, bits, shift), \
|
|
+ AD5064_CHANNEL(3, 3, bits, shift), \
|
|
+ AD5064_CHANNEL(4, 4, bits, shift), \
|
|
+ AD5064_CHANNEL(5, 5, bits, shift), \
|
|
+ AD5064_CHANNEL(6, 6, bits, shift), \
|
|
+ AD5064_CHANNEL(7, 7, bits, shift), \
|
|
}
|
|
|
|
-#define DECLARE_AD5065_CHANNELS(name, bits) \
|
|
+#define DECLARE_AD5065_CHANNELS(name, bits, shift) \
|
|
const struct iio_chan_spec name[] = { \
|
|
- AD5064_CHANNEL(0, 0, bits), \
|
|
- AD5064_CHANNEL(1, 3, bits), \
|
|
+ AD5064_CHANNEL(0, 0, bits, shift), \
|
|
+ AD5064_CHANNEL(1, 3, bits, shift), \
|
|
}
|
|
|
|
-static DECLARE_AD5064_CHANNELS(ad5024_channels, 12);
|
|
-static DECLARE_AD5064_CHANNELS(ad5044_channels, 14);
|
|
-static DECLARE_AD5064_CHANNELS(ad5064_channels, 16);
|
|
+static DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8);
|
|
+static DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6);
|
|
+static DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4);
|
|
|
|
-static DECLARE_AD5065_CHANNELS(ad5025_channels, 12);
|
|
-static DECLARE_AD5065_CHANNELS(ad5045_channels, 14);
|
|
-static DECLARE_AD5065_CHANNELS(ad5065_channels, 16);
|
|
+static DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8);
|
|
+static DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6);
|
|
+static DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4);
|
|
+
|
|
+static DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4);
|
|
+static DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0);
|
|
|
|
static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
|
|
[ID_AD5024] = {
|
|
@@ -382,6 +389,18 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
|
|
.channels = ad5024_channels,
|
|
.num_channels = 8,
|
|
},
|
|
+ [ID_AD5629_1] = {
|
|
+ .shared_vref = true,
|
|
+ .internal_vref = 2500000,
|
|
+ .channels = ad5629_channels,
|
|
+ .num_channels = 8,
|
|
+ },
|
|
+ [ID_AD5629_2] = {
|
|
+ .shared_vref = true,
|
|
+ .internal_vref = 5000000,
|
|
+ .channels = ad5629_channels,
|
|
+ .num_channels = 8,
|
|
+ },
|
|
[ID_AD5648_1] = {
|
|
.shared_vref = true,
|
|
.internal_vref = 2500000,
|
|
@@ -418,6 +437,18 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
|
|
.channels = ad5064_channels,
|
|
.num_channels = 8,
|
|
},
|
|
+ [ID_AD5669_1] = {
|
|
+ .shared_vref = true,
|
|
+ .internal_vref = 2500000,
|
|
+ .channels = ad5669_channels,
|
|
+ .num_channels = 8,
|
|
+ },
|
|
+ [ID_AD5669_2] = {
|
|
+ .shared_vref = true,
|
|
+ .internal_vref = 5000000,
|
|
+ .channels = ad5669_channels,
|
|
+ .num_channels = 8,
|
|
+ },
|
|
};
|
|
|
|
static inline unsigned int ad5064_num_vref(struct ad5064_state *st)
|
|
@@ -598,10 +629,16 @@ static int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd,
|
|
unsigned int addr, unsigned int val)
|
|
{
|
|
struct i2c_client *i2c = to_i2c_client(st->dev);
|
|
+ int ret;
|
|
|
|
st->data.i2c[0] = (cmd << 4) | addr;
|
|
put_unaligned_be16(val, &st->data.i2c[1]);
|
|
- return i2c_master_send(i2c, st->data.i2c, 3);
|
|
+
|
|
+ ret = i2c_master_send(i2c, st->data.i2c, 3);
|
|
+ if (ret < 0)
|
|
+ return ret;
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
static int ad5064_i2c_probe(struct i2c_client *i2c,
|
|
@@ -617,12 +654,12 @@ static int ad5064_i2c_remove(struct i2c_client *i2c)
|
|
}
|
|
|
|
static const struct i2c_device_id ad5064_i2c_ids[] = {
|
|
- {"ad5629-1", ID_AD5628_1},
|
|
- {"ad5629-2", ID_AD5628_2},
|
|
- {"ad5629-3", ID_AD5628_2}, /* similar enough to ad5629-2 */
|
|
- {"ad5669-1", ID_AD5668_1},
|
|
- {"ad5669-2", ID_AD5668_2},
|
|
- {"ad5669-3", ID_AD5668_2}, /* similar enough to ad5669-2 */
|
|
+ {"ad5629-1", ID_AD5629_1},
|
|
+ {"ad5629-2", ID_AD5629_2},
|
|
+ {"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */
|
|
+ {"ad5669-1", ID_AD5669_1},
|
|
+ {"ad5669-2", ID_AD5669_2},
|
|
+ {"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */
|
|
{}
|
|
};
|
|
MODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids);
|
|
diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c
|
|
index 7d9f5c31d2fc..0cedc81be312 100644
|
|
--- a/drivers/iio/dac/mcp4725.c
|
|
+++ b/drivers/iio/dac/mcp4725.c
|
|
@@ -301,6 +301,7 @@ static int mcp4725_probe(struct i2c_client *client,
|
|
data->client = client;
|
|
|
|
indio_dev->dev.parent = &client->dev;
|
|
+ indio_dev->name = id->name;
|
|
indio_dev->info = &mcp4725_info;
|
|
indio_dev->channels = &mcp4725_channel;
|
|
indio_dev->num_channels = 1;
|
|
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
|
|
index cb32b593f1c5..36607d52fee0 100644
|
|
--- a/drivers/iio/imu/adis_buffer.c
|
|
+++ b/drivers/iio/imu/adis_buffer.c
|
|
@@ -43,7 +43,7 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
|
|
return -ENOMEM;
|
|
|
|
rx = adis->buffer;
|
|
- tx = rx + indio_dev->scan_bytes;
|
|
+ tx = rx + scan_count;
|
|
|
|
spi_message_init(&adis->msg);
|
|
|
|
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
|
|
index 37b52bd44f86..a9164b51b5dc 100644
|
|
--- a/drivers/iio/industrialio-buffer.c
|
|
+++ b/drivers/iio/industrialio-buffer.c
|
|
@@ -830,7 +830,7 @@ int iio_scan_mask_set(struct iio_dev *indio_dev,
|
|
if (trialmask == NULL)
|
|
return -ENOMEM;
|
|
if (!indio_dev->masklength) {
|
|
- WARN_ON("Trying to set scanmask prior to registering buffer\n");
|
|
+ WARN(1, "Trying to set scanmask prior to registering buffer\n");
|
|
goto err_invalid_mask;
|
|
}
|
|
bitmap_copy(trialmask, buffer->scan_mask, indio_dev->masklength);
|
|
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
|
|
index acc911a836ca..a7b073b5e263 100644
|
|
--- a/drivers/iio/industrialio-core.c
|
|
+++ b/drivers/iio/industrialio-core.c
|
|
@@ -589,7 +589,7 @@ int __iio_device_attr_init(struct device_attribute *dev_attr,
|
|
break;
|
|
case IIO_SEPARATE:
|
|
if (!chan->indexed) {
|
|
- WARN_ON("Differential channels must be indexed\n");
|
|
+ WARN(1, "Differential channels must be indexed\n");
|
|
ret = -EINVAL;
|
|
goto error_free_full_postfix;
|
|
}
|
|
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
|
|
index 94eaaf0c49b3..9e497e4041a6 100644
|
|
--- a/drivers/input/mouse/elantech.c
|
|
+++ b/drivers/input/mouse/elantech.c
|
|
@@ -1111,7 +1111,7 @@ static int elantech_set_input_params(struct psmouse *psmouse)
|
|
input_set_abs_params(dev, ABS_TOOL_WIDTH, ETP_WMIN_V2,
|
|
ETP_WMAX_V2, 0, 0);
|
|
}
|
|
- input_mt_init_slots(dev, 2, 0);
|
|
+ input_mt_init_slots(dev, 2, INPUT_MT_SEMI_MT);
|
|
input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
|
|
input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
|
|
break;
|
|
@@ -1387,6 +1387,13 @@ static const struct dmi_system_id no_hw_res_dmi_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "U2442"),
|
|
},
|
|
},
|
|
+ {
|
|
+ /* Fujitsu LIFEBOOK U745 does not work with crc_enabled == 0 */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
|
|
+ },
|
|
+ },
|
|
#endif
|
|
{ }
|
|
};
|
|
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
|
|
index dd6d14d2337f..a4baf9677a45 100644
|
|
--- a/drivers/input/serio/i8042-x86ia64io.h
|
|
+++ b/drivers/input/serio/i8042-x86ia64io.h
|
|
@@ -258,6 +258,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
|
|
},
|
|
},
|
|
{
|
|
+ /* Fujitsu Lifebook U745 */
|
|
+ .matches = {
|
|
+ DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
|
+ DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK U745"),
|
|
+ },
|
|
+ },
|
|
+ {
|
|
/* Fujitsu T70H */
|
|
.matches = {
|
|
DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
|
|
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
|
|
index 158156543410..2d7bb594626c 100644
|
|
--- a/drivers/iommu/dmar.c
|
|
+++ b/drivers/iommu/dmar.c
|
|
@@ -986,7 +986,7 @@ void dmar_disable_qi(struct intel_iommu *iommu)
|
|
|
|
raw_spin_lock_irqsave(&iommu->register_lock, flags);
|
|
|
|
- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
|
|
+ sts = readl(iommu->reg + DMAR_GSTS_REG);
|
|
if (!(sts & DMA_GSTS_QIES))
|
|
goto end;
|
|
|
|
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
|
|
index ef5f65dbafe9..ffad080db013 100644
|
|
--- a/drivers/iommu/intel_irq_remapping.c
|
|
+++ b/drivers/iommu/intel_irq_remapping.c
|
|
@@ -489,7 +489,7 @@ static void iommu_disable_irq_remapping(struct intel_iommu *iommu)
|
|
|
|
raw_spin_lock_irqsave(&iommu->register_lock, flags);
|
|
|
|
- sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
|
|
+ sts = readl(iommu->reg + DMAR_GSTS_REG);
|
|
if (!(sts & DMA_GSTS_IRES))
|
|
goto end;
|
|
|
|
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
|
|
index 5895f1978691..e98de425f8e0 100644
|
|
--- a/drivers/net/wan/x25_asy.c
|
|
+++ b/drivers/net/wan/x25_asy.c
|
|
@@ -545,16 +545,12 @@ static void x25_asy_receive_buf(struct tty_struct *tty,
|
|
|
|
static int x25_asy_open_tty(struct tty_struct *tty)
|
|
{
|
|
- struct x25_asy *sl = tty->disc_data;
|
|
+ struct x25_asy *sl;
|
|
int err;
|
|
|
|
if (tty->ops->write == NULL)
|
|
return -EOPNOTSUPP;
|
|
|
|
- /* First make sure we're not already connected. */
|
|
- if (sl && sl->magic == X25_ASY_MAGIC)
|
|
- return -EEXIST;
|
|
-
|
|
/* OK. Find a free X.25 channel to use. */
|
|
sl = x25_asy_alloc();
|
|
if (sl == NULL)
|
|
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
|
|
index aaac3594f83b..452b637be676 100644
|
|
--- a/drivers/phy/phy-twl4030-usb.c
|
|
+++ b/drivers/phy/phy-twl4030-usb.c
|
|
@@ -777,6 +777,7 @@ static int twl4030_usb_remove(struct platform_device *pdev)
|
|
struct twl4030_usb *twl = platform_get_drvdata(pdev);
|
|
int val;
|
|
|
|
+ usb_remove_phy(&twl->phy);
|
|
pm_runtime_get_sync(twl->dev);
|
|
cancel_delayed_work(&twl->id_workaround_work);
|
|
device_remove_file(twl->dev, &dev_attr_vbus);
|
|
diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x86/intel_scu_ipcutil.c
|
|
index 02bc5a6343c3..aa454241489c 100644
|
|
--- a/drivers/platform/x86/intel_scu_ipcutil.c
|
|
+++ b/drivers/platform/x86/intel_scu_ipcutil.c
|
|
@@ -49,7 +49,7 @@ struct scu_ipc_data {
|
|
|
|
static int scu_reg_access(u32 cmd, struct scu_ipc_data *data)
|
|
{
|
|
- int count = data->count;
|
|
+ unsigned int count = data->count;
|
|
|
|
if (count == 0 || count == 3 || count > 4)
|
|
return -EINVAL;
|
|
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
|
|
index 4b9cf93f3fb6..d233170cd439 100644
|
|
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
|
|
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
|
|
@@ -569,7 +569,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev,
|
|
/*
|
|
* Command Lock contention
|
|
*/
|
|
- err = SCSI_DH_RETRY;
|
|
+ err = SCSI_DH_IMM_RETRY;
|
|
break;
|
|
default:
|
|
break;
|
|
@@ -619,6 +619,8 @@ retry:
|
|
err = mode_select_handle_sense(sdev, h->sense);
|
|
if (err == SCSI_DH_RETRY && retry_cnt--)
|
|
goto retry;
|
|
+ if (err == SCSI_DH_IMM_RETRY)
|
|
+ goto retry;
|
|
}
|
|
if (err == SCSI_DH_OK) {
|
|
h->state = RDAC_STATE_ACTIVE;
|
|
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
|
|
index f28ea070d3df..bd5fd3b7e178 100644
|
|
--- a/drivers/scsi/hosts.c
|
|
+++ b/drivers/scsi/hosts.c
|
|
@@ -308,6 +308,17 @@ static void scsi_host_dev_release(struct device *dev)
|
|
kfree(queuedata);
|
|
}
|
|
|
|
+ if (shost->shost_state == SHOST_CREATED) {
|
|
+ /*
|
|
+ * Free the shost_dev device name here if scsi_host_alloc()
|
|
+ * and scsi_host_put() have been called but neither
|
|
+ * scsi_host_add() nor scsi_host_remove() has been called.
|
|
+ * This avoids that the memory allocated for the shost_dev
|
|
+ * name is leaked.
|
|
+ */
|
|
+ kfree(dev_name(&shost->shost_dev));
|
|
+ }
|
|
+
|
|
scsi_destroy_command_freelist(shost);
|
|
if (shost->bqt)
|
|
blk_free_tags(shost->bqt);
|
|
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
|
|
index 262ab837a704..8790e8640acd 100644
|
|
--- a/drivers/scsi/scsi_devinfo.c
|
|
+++ b/drivers/scsi/scsi_devinfo.c
|
|
@@ -205,6 +205,7 @@ static struct {
|
|
{"Intel", "Multi-Flex", NULL, BLIST_NO_RSOC},
|
|
{"iRiver", "iFP Mass Driver", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
|
|
{"LASOUND", "CDX7405", "3.10", BLIST_MAX5LUN | BLIST_SINGLELUN},
|
|
+ {"Marvell", "Console", NULL, BLIST_SKIP_VPD_PAGES},
|
|
{"MATSHITA", "PD-1", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
|
|
{"MATSHITA", "DMC-LC5", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
|
|
{"MATSHITA", "DMC-LC40", NULL, BLIST_NOT_LOCKABLE | BLIST_INQUIRY_36},
|
|
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
|
|
index a59be67b92d5..88e136c716e9 100644
|
|
--- a/drivers/scsi/scsi_pm.c
|
|
+++ b/drivers/scsi/scsi_pm.c
|
|
@@ -151,13 +151,13 @@ static int sdev_runtime_suspend(struct device *dev)
|
|
struct scsi_device *sdev = to_scsi_device(dev);
|
|
int err = 0;
|
|
|
|
- if (pm && pm->runtime_suspend) {
|
|
- err = blk_pre_runtime_suspend(sdev->request_queue);
|
|
- if (err)
|
|
- return err;
|
|
+ err = blk_pre_runtime_suspend(sdev->request_queue);
|
|
+ if (err)
|
|
+ return err;
|
|
+ if (pm && pm->runtime_suspend)
|
|
err = pm->runtime_suspend(dev);
|
|
- blk_post_runtime_suspend(sdev->request_queue, err);
|
|
- }
|
|
+ blk_post_runtime_suspend(sdev->request_queue, err);
|
|
+
|
|
return err;
|
|
}
|
|
|
|
@@ -180,11 +180,11 @@ static int sdev_runtime_resume(struct device *dev)
|
|
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
|
|
int err = 0;
|
|
|
|
- if (pm && pm->runtime_resume) {
|
|
- blk_pre_runtime_resume(sdev->request_queue);
|
|
+ blk_pre_runtime_resume(sdev->request_queue);
|
|
+ if (pm && pm->runtime_resume)
|
|
err = pm->runtime_resume(dev);
|
|
- blk_post_runtime_resume(sdev->request_queue, err);
|
|
- }
|
|
+ blk_post_runtime_resume(sdev->request_queue, err);
|
|
+
|
|
return err;
|
|
}
|
|
|
|
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
|
|
index 665acbf83693..5706bb89f6a0 100644
|
|
--- a/drivers/scsi/scsi_sysfs.c
|
|
+++ b/drivers/scsi/scsi_sysfs.c
|
|
@@ -882,7 +882,7 @@ sdev_store_queue_ramp_up_period(struct device *dev,
|
|
return -EINVAL;
|
|
|
|
sdev->queue_ramp_up_period = msecs_to_jiffies(period);
|
|
- return period;
|
|
+ return count;
|
|
}
|
|
|
|
static struct device_attribute sdev_attr_queue_ramp_up_period =
|
|
@@ -1123,31 +1123,25 @@ static void __scsi_remove_target(struct scsi_target *starget)
|
|
void scsi_remove_target(struct device *dev)
|
|
{
|
|
struct Scsi_Host *shost = dev_to_shost(dev->parent);
|
|
- struct scsi_target *starget, *last = NULL;
|
|
+ struct scsi_target *starget, *last_target = NULL;
|
|
unsigned long flags;
|
|
|
|
- /* remove targets being careful to lookup next entry before
|
|
- * deleting the last
|
|
- */
|
|
+restart:
|
|
spin_lock_irqsave(shost->host_lock, flags);
|
|
list_for_each_entry(starget, &shost->__targets, siblings) {
|
|
- if (starget->state == STARGET_DEL)
|
|
+ if (starget->state == STARGET_DEL ||
|
|
+ starget == last_target)
|
|
continue;
|
|
if (starget->dev.parent == dev || &starget->dev == dev) {
|
|
- /* assuming new targets arrive at the end */
|
|
kref_get(&starget->reap_ref);
|
|
+ last_target = starget;
|
|
spin_unlock_irqrestore(shost->host_lock, flags);
|
|
- if (last)
|
|
- scsi_target_reap(last);
|
|
- last = starget;
|
|
__scsi_remove_target(starget);
|
|
- spin_lock_irqsave(shost->host_lock, flags);
|
|
+ scsi_target_reap(starget);
|
|
+ goto restart;
|
|
}
|
|
}
|
|
spin_unlock_irqrestore(shost->host_lock, flags);
|
|
-
|
|
- if (last)
|
|
- scsi_target_reap(last);
|
|
}
|
|
EXPORT_SYMBOL(scsi_remove_target);
|
|
|
|
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
|
|
index a10706409927..614531c14777 100644
|
|
--- a/drivers/scsi/sd.c
|
|
+++ b/drivers/scsi/sd.c
|
|
@@ -3129,8 +3129,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
|
|
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
|
|
int ret = 0;
|
|
|
|
- if (!sdkp)
|
|
- return 0; /* this can happen */
|
|
+ if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
|
|
+ return 0;
|
|
|
|
if (sdkp->WCE && sdkp->media_present) {
|
|
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
|
|
@@ -3171,6 +3171,9 @@ static int sd_resume(struct device *dev)
|
|
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
|
|
int ret = 0;
|
|
|
|
+ if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
|
|
+ return 0;
|
|
+
|
|
if (!sdkp->device->manage_start_stop)
|
|
goto done;
|
|
|
|
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
|
|
index 721d839d6c54..0be16bf5f0cd 100644
|
|
--- a/drivers/scsi/sg.c
|
|
+++ b/drivers/scsi/sg.c
|
|
@@ -1258,7 +1258,7 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
|
|
}
|
|
|
|
sfp->mmap_called = 1;
|
|
- vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
|
|
+ vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
|
|
vma->vm_private_data = sfp;
|
|
vma->vm_ops = &sg_mmap_vm_ops;
|
|
return 0;
|
|
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
|
|
index 40d85929aefe..2d3d11021bb6 100644
|
|
--- a/drivers/scsi/sr.c
|
|
+++ b/drivers/scsi/sr.c
|
|
@@ -142,6 +142,9 @@ static int sr_runtime_suspend(struct device *dev)
|
|
{
|
|
struct scsi_cd *cd = dev_get_drvdata(dev);
|
|
|
|
+ if (!cd) /* E.g.: runtime suspend following sr_remove() */
|
|
+ return 0;
|
|
+
|
|
if (cd->media_present)
|
|
return -EBUSY;
|
|
else
|
|
@@ -995,6 +998,7 @@ static int sr_remove(struct device *dev)
|
|
|
|
blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
|
|
del_gendisk(cd->disk);
|
|
+ dev_set_drvdata(dev, NULL);
|
|
|
|
mutex_lock(&sr_ref_mutex);
|
|
kref_put(&cd->kref, sr_kref_release);
|
|
diff --git a/drivers/staging/iio/adc/lpc32xx_adc.c b/drivers/staging/iio/adc/lpc32xx_adc.c
|
|
index a876ce755351..22818550efd3 100644
|
|
--- a/drivers/staging/iio/adc/lpc32xx_adc.c
|
|
+++ b/drivers/staging/iio/adc/lpc32xx_adc.c
|
|
@@ -76,7 +76,7 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
|
|
|
|
if (mask == IIO_CHAN_INFO_RAW) {
|
|
mutex_lock(&indio_dev->mlock);
|
|
- clk_enable(info->clk);
|
|
+ clk_prepare_enable(info->clk);
|
|
/* Measurement setup */
|
|
__raw_writel(AD_INTERNAL | (chan->address) | AD_REFp | AD_REFm,
|
|
LPC32XX_ADC_SELECT(info->adc_base));
|
|
@@ -84,7 +84,7 @@ static int lpc32xx_read_raw(struct iio_dev *indio_dev,
|
|
__raw_writel(AD_PDN_CTRL | AD_STROBE,
|
|
LPC32XX_ADC_CTRL(info->adc_base));
|
|
wait_for_completion(&info->completion); /* set by ISR */
|
|
- clk_disable(info->clk);
|
|
+ clk_disable_unprepare(info->clk);
|
|
*val = info->value;
|
|
mutex_unlock(&indio_dev->mlock);
|
|
|
|
diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c
|
|
index ca04d3669acc..34a6deef1d6c 100644
|
|
--- a/drivers/staging/speakup/selection.c
|
|
+++ b/drivers/staging/speakup/selection.c
|
|
@@ -140,7 +140,9 @@ static void __speakup_paste_selection(struct work_struct *work)
|
|
struct tty_ldisc *ld;
|
|
DECLARE_WAITQUEUE(wait, current);
|
|
|
|
- ld = tty_ldisc_ref_wait(tty);
|
|
+ ld = tty_ldisc_ref(tty);
|
|
+ if (!ld)
|
|
+ goto tty_unref;
|
|
tty_buffer_lock_exclusive(&vc->port);
|
|
|
|
add_wait_queue(&vc->paste_wait, &wait);
|
|
@@ -160,6 +162,7 @@ static void __speakup_paste_selection(struct work_struct *work)
|
|
|
|
tty_buffer_unlock_exclusive(&vc->port);
|
|
tty_ldisc_deref(ld);
|
|
+tty_unref:
|
|
tty_kref_put(tty);
|
|
}
|
|
|
|
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
|
|
index 9dbf17671439..c066e6e298c3 100644
|
|
--- a/drivers/target/iscsi/iscsi_target.c
|
|
+++ b/drivers/target/iscsi/iscsi_target.c
|
|
@@ -4027,6 +4027,17 @@ reject:
|
|
return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
|
|
}
|
|
|
|
+static bool iscsi_target_check_conn_state(struct iscsi_conn *conn)
|
|
+{
|
|
+ bool ret;
|
|
+
|
|
+ spin_lock_bh(&conn->state_lock);
|
|
+ ret = (conn->conn_state != TARG_CONN_STATE_LOGGED_IN);
|
|
+ spin_unlock_bh(&conn->state_lock);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
int iscsi_target_rx_thread(void *arg)
|
|
{
|
|
int ret, rc;
|
|
@@ -4044,7 +4055,7 @@ int iscsi_target_rx_thread(void *arg)
|
|
* incoming iscsi/tcp socket I/O, and/or failing the connection.
|
|
*/
|
|
rc = wait_for_completion_interruptible(&conn->rx_login_comp);
|
|
- if (rc < 0)
|
|
+ if (rc < 0 || iscsi_target_check_conn_state(conn))
|
|
return 0;
|
|
|
|
if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
|
|
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
|
|
index 1c0088fe9e99..83465617ad6d 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_configfs.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
|
|
@@ -1876,7 +1876,8 @@ static void lio_tpg_release_fabric_acl(
|
|
}
|
|
|
|
/*
|
|
- * Called with spin_lock_bh(struct se_portal_group->session_lock) held..
|
|
+ * Called with spin_lock_irq(struct se_portal_group->session_lock) held
|
|
+ * or not held.
|
|
*
|
|
* Also, this function calls iscsit_inc_session_usage_count() on the
|
|
* struct iscsi_session in question.
|
|
@@ -1884,19 +1885,32 @@ static void lio_tpg_release_fabric_acl(
|
|
static int lio_tpg_shutdown_session(struct se_session *se_sess)
|
|
{
|
|
struct iscsi_session *sess = se_sess->fabric_sess_ptr;
|
|
+ struct se_portal_group *se_tpg = se_sess->se_tpg;
|
|
+ bool local_lock = false;
|
|
+
|
|
+ if (!spin_is_locked(&se_tpg->session_lock)) {
|
|
+ spin_lock_irq(&se_tpg->session_lock);
|
|
+ local_lock = true;
|
|
+ }
|
|
|
|
spin_lock(&sess->conn_lock);
|
|
if (atomic_read(&sess->session_fall_back_to_erl0) ||
|
|
atomic_read(&sess->session_logout) ||
|
|
(sess->time2retain_timer_flags & ISCSI_TF_EXPIRED)) {
|
|
spin_unlock(&sess->conn_lock);
|
|
+ if (local_lock)
|
|
+ spin_unlock_irq(&sess->conn_lock);
|
|
return 0;
|
|
}
|
|
atomic_set(&sess->session_reinstatement, 1);
|
|
spin_unlock(&sess->conn_lock);
|
|
|
|
iscsit_stop_time2retain_timer(sess);
|
|
+ spin_unlock_irq(&se_tpg->session_lock);
|
|
+
|
|
iscsit_stop_session(sess, 1, 1);
|
|
+ if (!local_lock)
|
|
+ spin_lock_irq(&se_tpg->session_lock);
|
|
|
|
return 1;
|
|
}
|
|
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
|
|
index 25ad113c5978..abbac7fe64e2 100644
|
|
--- a/drivers/target/iscsi/iscsi_target_nego.c
|
|
+++ b/drivers/target/iscsi/iscsi_target_nego.c
|
|
@@ -393,6 +393,7 @@ err:
|
|
if (login->login_complete) {
|
|
if (conn->rx_thread && conn->rx_thread_active) {
|
|
send_sig(SIGINT, conn->rx_thread, 1);
|
|
+ complete(&conn->rx_login_comp);
|
|
kthread_stop(conn->rx_thread);
|
|
}
|
|
if (conn->tx_thread && conn->tx_thread_active) {
|
|
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
|
|
index e49616eeb1cc..c3f9b9920d8d 100644
|
|
--- a/drivers/tty/pty.c
|
|
+++ b/drivers/tty/pty.c
|
|
@@ -617,7 +617,14 @@ static void pty_unix98_remove(struct tty_driver *driver, struct tty_struct *tty)
|
|
/* this is called once with whichever end is closed last */
|
|
static void pty_unix98_shutdown(struct tty_struct *tty)
|
|
{
|
|
- devpts_kill_index(tty->driver_data, tty->index);
|
|
+ struct inode *ptmx_inode;
|
|
+
|
|
+ if (tty->driver->subtype == PTY_TYPE_MASTER)
|
|
+ ptmx_inode = tty->driver_data;
|
|
+ else
|
|
+ ptmx_inode = tty->link->driver_data;
|
|
+ devpts_kill_index(ptmx_inode, tty->index);
|
|
+ devpts_del_ref(ptmx_inode);
|
|
}
|
|
|
|
static const struct tty_operations ptm_unix98_ops = {
|
|
@@ -708,6 +715,18 @@ static int ptmx_open(struct inode *inode, struct file *filp)
|
|
set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
|
|
tty->driver_data = inode;
|
|
|
|
+ /*
|
|
+ * In the case where all references to ptmx inode are dropped and we
|
|
+ * still have /dev/tty opened pointing to the master/slave pair (ptmx
|
|
+ * is closed/released before /dev/tty), we must make sure that the inode
|
|
+ * is still valid when we call the final pty_unix98_shutdown, thus we
|
|
+ * hold an additional reference to the ptmx inode. For the same /dev/tty
|
|
+ * last close case, we also need to make sure the super_block isn't
|
|
+ * destroyed (devpts instance unmounted), before /dev/tty is closed and
|
|
+ * on its release devpts_kill_index is called.
|
|
+ */
|
|
+ devpts_add_ref(inode);
|
|
+
|
|
tty_add_file(tty, filp);
|
|
|
|
slave_inode = devpts_pty_new(inode,
|
|
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
|
|
index 996f8f3fd423..1e1fed47eabc 100644
|
|
--- a/drivers/tty/serial/8250/8250_pci.c
|
|
+++ b/drivers/tty/serial/8250/8250_pci.c
|
|
@@ -1613,6 +1613,9 @@ static int pci_eg20t_init(struct pci_dev *dev)
|
|
#endif
|
|
}
|
|
|
|
+#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358
|
|
+#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358
|
|
+
|
|
static int
|
|
pci_xr17c154_setup(struct serial_private *priv,
|
|
const struct pciserial_board *board,
|
|
@@ -1622,6 +1625,15 @@ pci_xr17c154_setup(struct serial_private *priv,
|
|
return pci_default_setup(priv, board, port, idx);
|
|
}
|
|
|
|
+static inline int
|
|
+xr17v35x_has_slave(struct serial_private *priv)
|
|
+{
|
|
+ const int dev_id = priv->dev->device;
|
|
+
|
|
+ return ((dev_id == PCI_DEVICE_ID_EXAR_XR17V4358) ||
|
|
+ (dev_id == PCI_DEVICE_ID_EXAR_XR17V8358));
|
|
+}
|
|
+
|
|
static int
|
|
pci_xr17v35x_setup(struct serial_private *priv,
|
|
const struct pciserial_board *board,
|
|
@@ -1636,6 +1648,13 @@ pci_xr17v35x_setup(struct serial_private *priv,
|
|
port->port.flags |= UPF_EXAR_EFR;
|
|
|
|
/*
|
|
+ * Setup the uart clock for the devices on expansion slot to
|
|
+ * half the clock speed of the main chip (which is 125MHz)
|
|
+ */
|
|
+ if (xr17v35x_has_slave(priv) && idx >= 8)
|
|
+ port->port.uartclk = (7812500 * 16 / 2);
|
|
+
|
|
+ /*
|
|
* Setup Multipurpose Input/Output pins.
|
|
*/
|
|
if (idx == 0) {
|
|
@@ -1772,9 +1791,6 @@ pci_wch_ch353_setup(struct serial_private *priv,
|
|
#define PCI_DEVICE_ID_SUNIX_1999 0x1999
|
|
|
|
|
|
-#define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358
|
|
-#define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358
|
|
-
|
|
/* 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
|
|
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
|
|
index 27688e3b0a4c..b63507bbf74b 100644
|
|
--- a/drivers/usb/host/xhci.c
|
|
+++ b/drivers/usb/host/xhci.c
|
|
@@ -1523,7 +1523,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
|
|
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
|
|
"HW died, freeing TD.");
|
|
urb_priv = urb->hcpriv;
|
|
- for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
|
|
+ for (i = urb_priv->td_cnt;
|
|
+ i < urb_priv->length && xhci->devs[urb->dev->slot_id];
|
|
+ i++) {
|
|
td = urb_priv->td[i];
|
|
if (!list_empty(&td->td_list))
|
|
list_del_init(&td->td_list);
|
|
diff --git a/fs/aio.c b/fs/aio.c
|
|
index 3241659491b1..0612022162ad 100644
|
|
--- a/fs/aio.c
|
|
+++ b/fs/aio.c
|
|
@@ -1375,11 +1375,16 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb,
|
|
unsigned long *nr_segs,
|
|
struct iovec *iovec)
|
|
{
|
|
- if (unlikely(!access_ok(!rw, buf, kiocb->ki_nbytes)))
|
|
+ size_t len = kiocb->ki_nbytes;
|
|
+
|
|
+ if (len > MAX_RW_COUNT)
|
|
+ len = MAX_RW_COUNT;
|
|
+
|
|
+ if (unlikely(!access_ok(!rw, buf, len)))
|
|
return -EFAULT;
|
|
|
|
iovec->iov_base = buf;
|
|
- iovec->iov_len = kiocb->ki_nbytes;
|
|
+ iovec->iov_len = len;
|
|
*nr_segs = 1;
|
|
return 0;
|
|
}
|
|
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c
|
|
index 0529defbdf73..9b8447e4ac3f 100644
|
|
--- a/fs/btrfs/backref.c
|
|
+++ b/fs/btrfs/backref.c
|
|
@@ -1264,7 +1264,8 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
|
|
read_extent_buffer(eb, dest + bytes_left,
|
|
name_off, name_len);
|
|
if (eb != eb_in) {
|
|
- btrfs_tree_read_unlock_blocking(eb);
|
|
+ if (!path->skip_locking)
|
|
+ btrfs_tree_read_unlock_blocking(eb);
|
|
free_extent_buffer(eb);
|
|
}
|
|
ret = inode_ref_info(parent, 0, fs_root, path, &found_key);
|
|
@@ -1283,9 +1284,10 @@ char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path,
|
|
eb = path->nodes[0];
|
|
/* make sure we can use eb after releasing the path */
|
|
if (eb != eb_in) {
|
|
- atomic_inc(&eb->refs);
|
|
- btrfs_tree_read_lock(eb);
|
|
- btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
|
|
+ if (!path->skip_locking)
|
|
+ btrfs_set_lock_blocking_rw(eb, BTRFS_READ_LOCK);
|
|
+ path->nodes[0] = NULL;
|
|
+ path->locks[0] = 0;
|
|
}
|
|
btrfs_release_path(path);
|
|
iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref);
|
|
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
|
|
index 12e35566d2fc..cc4790f11795 100644
|
|
--- a/fs/btrfs/delayed-inode.c
|
|
+++ b/fs/btrfs/delayed-inode.c
|
|
@@ -1686,7 +1686,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list,
|
|
*
|
|
*/
|
|
int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
|
|
- struct list_head *ins_list)
|
|
+ struct list_head *ins_list, bool *emitted)
|
|
{
|
|
struct btrfs_dir_item *di;
|
|
struct btrfs_delayed_item *curr, *next;
|
|
@@ -1730,6 +1730,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
|
|
|
|
if (over)
|
|
return 1;
|
|
+ *emitted = true;
|
|
}
|
|
return 0;
|
|
}
|
|
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h
|
|
index f70119f25421..0167853c84ae 100644
|
|
--- a/fs/btrfs/delayed-inode.h
|
|
+++ b/fs/btrfs/delayed-inode.h
|
|
@@ -144,7 +144,7 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
|
|
int btrfs_should_delete_dir_index(struct list_head *del_list,
|
|
u64 index);
|
|
int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
|
|
- struct list_head *ins_list);
|
|
+ struct list_head *ins_list, bool *emitted);
|
|
|
|
/* for init */
|
|
int __init btrfs_delayed_inode_init(void);
|
|
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
|
|
index 7f0dcfc58cbf..08824fe6ef44 100644
|
|
--- a/fs/btrfs/inode.c
|
|
+++ b/fs/btrfs/inode.c
|
|
@@ -5205,6 +5205,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
|
|
char *name_ptr;
|
|
int name_len;
|
|
int is_curr = 0; /* ctx->pos points to the current index? */
|
|
+ bool emitted;
|
|
|
|
/* FIXME, use a real flag for deciding about the key type */
|
|
if (root->fs_info->tree_root == root)
|
|
@@ -5233,6 +5234,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
|
|
if (ret < 0)
|
|
goto err;
|
|
|
|
+ emitted = false;
|
|
while (1) {
|
|
leaf = path->nodes[0];
|
|
slot = path->slots[0];
|
|
@@ -5312,6 +5314,7 @@ skip:
|
|
|
|
if (over)
|
|
goto nopos;
|
|
+ emitted = true;
|
|
di_len = btrfs_dir_name_len(leaf, di) +
|
|
btrfs_dir_data_len(leaf, di) + sizeof(*di);
|
|
di_cur += di_len;
|
|
@@ -5324,11 +5327,20 @@ next:
|
|
if (key_type == BTRFS_DIR_INDEX_KEY) {
|
|
if (is_curr)
|
|
ctx->pos++;
|
|
- ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
|
|
+ ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
|
|
if (ret)
|
|
goto nopos;
|
|
}
|
|
|
|
+ /*
|
|
+ * If we haven't emitted any dir entry, we must not touch ctx->pos as
|
|
+ * it was was set to the termination value in previous call. We assume
|
|
+ * that "." and ".." were emitted if we reach this point and set the
|
|
+ * termination value as well for an empty directory.
|
|
+ */
|
|
+ if (ctx->pos > 2 && !emitted)
|
|
+ goto nopos;
|
|
+
|
|
/* Reached end of directory/root. Bump pos past the last item. */
|
|
ctx->pos++;
|
|
|
|
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
|
|
index 3299778391fd..0bd335a393f8 100644
|
|
--- a/fs/cifs/cifsencrypt.c
|
|
+++ b/fs/cifs/cifsencrypt.c
|
|
@@ -710,7 +710,7 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
|
|
|
|
ses->auth_key.response = kmalloc(baselen + tilen, GFP_KERNEL);
|
|
if (!ses->auth_key.response) {
|
|
- rc = ENOMEM;
|
|
+ rc = -ENOMEM;
|
|
ses->auth_key.len = 0;
|
|
goto setup_ntlmv2_rsp_ret;
|
|
}
|
|
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
|
|
index b334a89d6a66..1320d1ecc630 100644
|
|
--- a/fs/cifs/readdir.c
|
|
+++ b/fs/cifs/readdir.c
|
|
@@ -849,6 +849,7 @@ int cifs_readdir(struct file *file, struct dir_context *ctx)
|
|
* if buggy server returns . and .. late do we want to
|
|
* check for that here?
|
|
*/
|
|
+ *tmp_buf = 0;
|
|
rc = cifs_filldir(current_entry, file, ctx,
|
|
tmp_buf, max_len);
|
|
if (rc) {
|
|
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
|
|
index a726b9f29cb7..61af24e379ad 100644
|
|
--- a/fs/devpts/inode.c
|
|
+++ b/fs/devpts/inode.c
|
|
@@ -564,6 +564,26 @@ void devpts_kill_index(struct inode *ptmx_inode, int idx)
|
|
mutex_unlock(&allocated_ptys_lock);
|
|
}
|
|
|
|
+/*
|
|
+ * pty code needs to hold extra references in case of last /dev/tty close
|
|
+ */
|
|
+
|
|
+void devpts_add_ref(struct inode *ptmx_inode)
|
|
+{
|
|
+ struct super_block *sb = pts_sb_from_inode(ptmx_inode);
|
|
+
|
|
+ atomic_inc(&sb->s_active);
|
|
+ ihold(ptmx_inode);
|
|
+}
|
|
+
|
|
+void devpts_del_ref(struct inode *ptmx_inode)
|
|
+{
|
|
+ struct super_block *sb = pts_sb_from_inode(ptmx_inode);
|
|
+
|
|
+ iput(ptmx_inode);
|
|
+ deactivate_super(sb);
|
|
+}
|
|
+
|
|
/**
|
|
* devpts_pty_new -- create a new inode in /dev/pts/
|
|
* @ptmx_inode: inode of the master
|
|
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
|
|
index 831cb305c63f..ae8ce49c0437 100644
|
|
--- a/fs/ext4/resize.c
|
|
+++ b/fs/ext4/resize.c
|
|
@@ -186,7 +186,7 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size)
|
|
if (flex_gd == NULL)
|
|
goto out3;
|
|
|
|
- if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data))
|
|
+ if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_group_data))
|
|
goto out2;
|
|
flex_gd->count = flexbg_size;
|
|
|
|
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
|
|
index d8a60270581c..f9785e3c63ac 100644
|
|
--- a/fs/fuse/file.c
|
|
+++ b/fs/fuse/file.c
|
|
@@ -1006,6 +1006,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
|
|
tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
|
|
flush_dcache_page(page);
|
|
|
|
+ iov_iter_advance(ii, tmp);
|
|
if (!tmp) {
|
|
unlock_page(page);
|
|
page_cache_release(page);
|
|
@@ -1018,7 +1019,6 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req,
|
|
req->page_descs[req->num_pages].length = tmp;
|
|
req->num_pages++;
|
|
|
|
- iov_iter_advance(ii, tmp);
|
|
count += tmp;
|
|
pos += tmp;
|
|
offset += tmp;
|
|
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
|
|
index 7b945957e230..45a7dd36b4a6 100644
|
|
--- a/fs/nfs/nfs4proc.c
|
|
+++ b/fs/nfs/nfs4proc.c
|
|
@@ -1169,6 +1169,7 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s
|
|
* Protect the call to nfs4_state_set_mode_locked and
|
|
* serialise the stateid update
|
|
*/
|
|
+ spin_lock(&state->owner->so_lock);
|
|
write_seqlock(&state->seqlock);
|
|
if (deleg_stateid != NULL) {
|
|
nfs4_stateid_copy(&state->stateid, deleg_stateid);
|
|
@@ -1177,7 +1178,6 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s
|
|
if (open_stateid != NULL)
|
|
nfs_set_open_stateid_locked(state, open_stateid, fmode);
|
|
write_sequnlock(&state->seqlock);
|
|
- spin_lock(&state->owner->so_lock);
|
|
update_open_stateflags(state, fmode);
|
|
spin_unlock(&state->owner->so_lock);
|
|
}
|
|
diff --git a/fs/proc/array.c b/fs/proc/array.c
|
|
index baf3464bbce0..ca4a64b4b119 100644
|
|
--- a/fs/proc/array.c
|
|
+++ b/fs/proc/array.c
|
|
@@ -391,7 +391,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
|
|
|
|
state = *get_task_state(task);
|
|
vsize = eip = esp = 0;
|
|
- permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
|
|
+ permitted = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS | PTRACE_MODE_NOAUDIT);
|
|
mm = get_task_mm(task);
|
|
if (mm) {
|
|
vsize = task_vsize(mm);
|
|
diff --git a/fs/proc/base.c b/fs/proc/base.c
|
|
index 489ba8caafc0..be78847782c4 100644
|
|
--- a/fs/proc/base.c
|
|
+++ b/fs/proc/base.c
|
|
@@ -239,7 +239,7 @@ out:
|
|
|
|
static int proc_pid_auxv(struct task_struct *task, char *buffer)
|
|
{
|
|
- struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ);
|
|
+ struct mm_struct *mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
|
|
int res = PTR_ERR(mm);
|
|
if (mm && !IS_ERR(mm)) {
|
|
unsigned int nwords = 0;
|
|
@@ -269,7 +269,7 @@ static int proc_pid_wchan(struct task_struct *task, char *buffer)
|
|
wchan = get_wchan(task);
|
|
|
|
if (lookup_symbol_name(wchan, symname) < 0)
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
|
|
return 0;
|
|
else
|
|
return sprintf(buffer, "%lu", wchan);
|
|
@@ -283,7 +283,7 @@ static int lock_trace(struct task_struct *task)
|
|
int err = mutex_lock_killable(&task->signal->cred_guard_mutex);
|
|
if (err)
|
|
return err;
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_ATTACH)) {
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_ATTACH_FSCREDS)) {
|
|
mutex_unlock(&task->signal->cred_guard_mutex);
|
|
return -EPERM;
|
|
}
|
|
@@ -557,7 +557,7 @@ static int proc_fd_access_allowed(struct inode *inode)
|
|
*/
|
|
task = get_proc_task(inode);
|
|
if (task) {
|
|
- allowed = ptrace_may_access(task, PTRACE_MODE_READ);
|
|
+ allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
|
|
put_task_struct(task);
|
|
}
|
|
return allowed;
|
|
@@ -592,7 +592,7 @@ static bool has_pid_permissions(struct pid_namespace *pid,
|
|
return true;
|
|
if (in_group_p(pid->pid_gid))
|
|
return true;
|
|
- return ptrace_may_access(task, PTRACE_MODE_READ);
|
|
+ return ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
|
|
}
|
|
|
|
|
|
@@ -707,7 +707,7 @@ static int __mem_open(struct inode *inode, struct file *file, unsigned int mode)
|
|
if (!task)
|
|
return -ESRCH;
|
|
|
|
- mm = mm_access(task, mode);
|
|
+ mm = mm_access(task, mode | PTRACE_MODE_FSCREDS);
|
|
put_task_struct(task);
|
|
|
|
if (IS_ERR(mm))
|
|
@@ -1760,7 +1760,7 @@ static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
|
|
if (!task)
|
|
goto out_notask;
|
|
|
|
- mm = mm_access(task, PTRACE_MODE_READ);
|
|
+ mm = mm_access(task, PTRACE_MODE_READ_FSCREDS);
|
|
if (IS_ERR_OR_NULL(mm))
|
|
goto out;
|
|
|
|
@@ -1895,7 +1895,7 @@ static struct dentry *proc_map_files_lookup(struct inode *dir,
|
|
goto out;
|
|
|
|
result = -EACCES;
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
|
|
goto out_put_task;
|
|
|
|
result = -ENOENT;
|
|
@@ -1952,7 +1952,7 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)
|
|
goto out;
|
|
|
|
ret = -EACCES;
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
|
|
goto out_put_task;
|
|
|
|
ret = 0;
|
|
@@ -2431,7 +2431,7 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
|
|
if (result)
|
|
return result;
|
|
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_READ)) {
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS)) {
|
|
result = -EACCES;
|
|
goto out_unlock;
|
|
}
|
|
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c
|
|
index 9ae46b87470d..a05ed26075e3 100644
|
|
--- a/fs/proc/namespaces.c
|
|
+++ b/fs/proc/namespaces.c
|
|
@@ -119,7 +119,7 @@ static void *proc_ns_follow_link(struct dentry *dentry, struct nameidata *nd)
|
|
if (!task)
|
|
goto out;
|
|
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
|
|
goto out_put_task;
|
|
|
|
ns_path.dentry = proc_ns_get_dentry(sb, task, ei->ns.ns_ops);
|
|
@@ -152,7 +152,7 @@ static int proc_ns_readlink(struct dentry *dentry, char __user *buffer, int bufl
|
|
if (!task)
|
|
goto out;
|
|
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
|
|
goto out_put_task;
|
|
|
|
len = -ENOENT;
|
|
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
|
|
index 142d29e3ccdf..5808bfe95126 100644
|
|
--- a/fs/udf/inode.c
|
|
+++ b/fs/udf/inode.c
|
|
@@ -2062,14 +2062,29 @@ void udf_write_aext(struct inode *inode, struct extent_position *epos,
|
|
epos->offset += adsize;
|
|
}
|
|
|
|
+/*
|
|
+ * Only 1 indirect extent in a row really makes sense but allow upto 16 in case
|
|
+ * someone does some weird stuff.
|
|
+ */
|
|
+#define UDF_MAX_INDIR_EXTS 16
|
|
+
|
|
int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
|
|
struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
|
|
{
|
|
int8_t etype;
|
|
+ unsigned int indirections = 0;
|
|
|
|
while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
|
|
(EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
|
|
int block;
|
|
+
|
|
+ if (++indirections > UDF_MAX_INDIR_EXTS) {
|
|
+ udf_err(inode->i_sb,
|
|
+ "too many indirect extents in inode %lu\n",
|
|
+ inode->i_ino);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
epos->block = *eloc;
|
|
epos->offset = sizeof(struct allocExtDesc);
|
|
brelse(epos->bh);
|
|
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
|
|
index 44b815e57f94..685fbd8a2937 100644
|
|
--- a/fs/udf/unicode.c
|
|
+++ b/fs/udf/unicode.c
|
|
@@ -132,11 +132,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
|
|
if (c < 0x80U)
|
|
utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
|
|
else if (c < 0x800U) {
|
|
+ if (utf_o->u_len > (UDF_NAME_LEN - 4))
|
|
+ break;
|
|
utf_o->u_name[utf_o->u_len++] =
|
|
(uint8_t)(0xc0 | (c >> 6));
|
|
utf_o->u_name[utf_o->u_len++] =
|
|
(uint8_t)(0x80 | (c & 0x3f));
|
|
} else {
|
|
+ if (utf_o->u_len > (UDF_NAME_LEN - 5))
|
|
+ break;
|
|
utf_o->u_name[utf_o->u_len++] =
|
|
(uint8_t)(0xe0 | (c >> 12));
|
|
utf_o->u_name[utf_o->u_len++] =
|
|
@@ -177,17 +181,22 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
|
|
static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
|
|
{
|
|
unsigned c, i, max_val, utf_char;
|
|
- int utf_cnt, u_len;
|
|
+ int utf_cnt, u_len, u_ch;
|
|
|
|
memset(ocu, 0, sizeof(dstring) * length);
|
|
ocu[0] = 8;
|
|
max_val = 0xffU;
|
|
+ u_ch = 1;
|
|
|
|
try_again:
|
|
u_len = 0U;
|
|
utf_char = 0U;
|
|
utf_cnt = 0U;
|
|
for (i = 0U; i < utf->u_len; i++) {
|
|
+ /* Name didn't fit? */
|
|
+ if (u_len + 1 + u_ch >= length)
|
|
+ return 0;
|
|
+
|
|
c = (uint8_t)utf->u_name[i];
|
|
|
|
/* Complete a multi-byte UTF-8 character */
|
|
@@ -229,6 +238,7 @@ try_again:
|
|
if (max_val == 0xffU) {
|
|
max_val = 0xffffU;
|
|
ocu[0] = (uint8_t)0x10U;
|
|
+ u_ch = 2;
|
|
goto try_again;
|
|
}
|
|
goto error_out;
|
|
@@ -281,7 +291,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
|
|
c = (c << 8) | ocu[i++];
|
|
|
|
len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len],
|
|
- UDF_NAME_LEN - utf_o->u_len);
|
|
+ UDF_NAME_LEN - 2 - utf_o->u_len);
|
|
/* Valid character? */
|
|
if (len >= 0)
|
|
utf_o->u_len += len;
|
|
@@ -299,15 +309,19 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni,
|
|
int len;
|
|
unsigned i, max_val;
|
|
uint16_t uni_char;
|
|
- int u_len;
|
|
+ int u_len, u_ch;
|
|
|
|
memset(ocu, 0, sizeof(dstring) * length);
|
|
ocu[0] = 8;
|
|
max_val = 0xffU;
|
|
+ u_ch = 1;
|
|
|
|
try_again:
|
|
u_len = 0U;
|
|
for (i = 0U; i < uni->u_len; i++) {
|
|
+ /* Name didn't fit? */
|
|
+ if (u_len + 1 + u_ch >= length)
|
|
+ return 0;
|
|
len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char);
|
|
if (!len)
|
|
continue;
|
|
@@ -320,6 +334,7 @@ try_again:
|
|
if (uni_char > max_val) {
|
|
max_val = 0xffffU;
|
|
ocu[0] = (uint8_t)0x10U;
|
|
+ u_ch = 2;
|
|
goto try_again;
|
|
}
|
|
|
|
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
|
|
index 2472740d7ab2..6977192bdb59 100644
|
|
--- a/include/linux/compiler.h
|
|
+++ b/include/linux/compiler.h
|
|
@@ -131,7 +131,7 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
|
|
*/
|
|
#define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
|
|
#define __trace_if(cond) \
|
|
- if (__builtin_constant_p((cond)) ? !!(cond) : \
|
|
+ if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
|
|
({ \
|
|
int ______r; \
|
|
static struct ftrace_branch_data \
|
|
diff --git a/include/linux/devpts_fs.h b/include/linux/devpts_fs.h
|
|
index 251a2090a554..e0ee0b3000b2 100644
|
|
--- a/include/linux/devpts_fs.h
|
|
+++ b/include/linux/devpts_fs.h
|
|
@@ -19,6 +19,8 @@
|
|
|
|
int devpts_new_index(struct inode *ptmx_inode);
|
|
void devpts_kill_index(struct inode *ptmx_inode, int idx);
|
|
+void devpts_add_ref(struct inode *ptmx_inode);
|
|
+void devpts_del_ref(struct inode *ptmx_inode);
|
|
/* mknod in devpts */
|
|
struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
|
|
void *priv);
|
|
@@ -32,6 +34,8 @@ void devpts_pty_kill(struct inode *inode);
|
|
/* Dummy stubs in the no-pty case */
|
|
static inline int devpts_new_index(struct inode *ptmx_inode) { return -EINVAL; }
|
|
static inline void devpts_kill_index(struct inode *ptmx_inode, int idx) { }
|
|
+static inline void devpts_add_ref(struct inode *ptmx_inode) { }
|
|
+static inline void devpts_del_ref(struct inode *ptmx_inode) { }
|
|
static inline struct inode *devpts_pty_new(struct inode *ptmx_inode,
|
|
dev_t device, int index, void *priv)
|
|
{
|
|
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
|
|
index cc79eff4a1ad..608d90444b6f 100644
|
|
--- a/include/linux/ptrace.h
|
|
+++ b/include/linux/ptrace.h
|
|
@@ -56,7 +56,29 @@ extern void exit_ptrace(struct task_struct *tracer);
|
|
#define PTRACE_MODE_READ 0x01
|
|
#define PTRACE_MODE_ATTACH 0x02
|
|
#define PTRACE_MODE_NOAUDIT 0x04
|
|
-/* Returns true on success, false on denial. */
|
|
+#define PTRACE_MODE_FSCREDS 0x08
|
|
+#define PTRACE_MODE_REALCREDS 0x10
|
|
+
|
|
+/* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
|
|
+#define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
|
|
+#define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
|
|
+#define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
|
|
+#define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
|
|
+
|
|
+/**
|
|
+ * ptrace_may_access - check whether the caller is permitted to access
|
|
+ * a target task.
|
|
+ * @task: target task
|
|
+ * @mode: selects type of access and caller credentials
|
|
+ *
|
|
+ * Returns true on success, false on denial.
|
|
+ *
|
|
+ * One of the flags PTRACE_MODE_FSCREDS and PTRACE_MODE_REALCREDS must
|
|
+ * be set in @mode to specify whether the access was requested through
|
|
+ * a filesystem syscall (should use effective capabilities and fsuid
|
|
+ * of the caller) or through an explicit syscall such as
|
|
+ * process_vm_writev or ptrace (and should use the real credentials).
|
|
+ */
|
|
extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
|
|
|
|
static inline int ptrace_reparented(struct task_struct *child)
|
|
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h
|
|
index e8be53ecfc45..16604454e95f 100644
|
|
--- a/include/linux/radix-tree.h
|
|
+++ b/include/linux/radix-tree.h
|
|
@@ -320,12 +320,28 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
|
|
struct radix_tree_iter *iter, unsigned flags);
|
|
|
|
/**
|
|
+ * radix_tree_iter_retry - retry this chunk of the iteration
|
|
+ * @iter: iterator state
|
|
+ *
|
|
+ * If we iterate over a tree protected only by the RCU lock, a race
|
|
+ * against deletion or creation may result in seeing a slot for which
|
|
+ * radix_tree_deref_retry() returns true. If so, call this function
|
|
+ * and continue the iteration.
|
|
+ */
|
|
+static inline __must_check
|
|
+void **radix_tree_iter_retry(struct radix_tree_iter *iter)
|
|
+{
|
|
+ iter->next_index = iter->index;
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+/**
|
|
* radix_tree_chunk_size - get current chunk size
|
|
*
|
|
* @iter: pointer to radix tree iterator
|
|
* Returns: current chunk size
|
|
*/
|
|
-static __always_inline unsigned
|
|
+static __always_inline long
|
|
radix_tree_chunk_size(struct radix_tree_iter *iter)
|
|
{
|
|
return iter->next_index - iter->index;
|
|
@@ -359,9 +375,9 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags)
|
|
return slot + offset + 1;
|
|
}
|
|
} else {
|
|
- unsigned size = radix_tree_chunk_size(iter) - 1;
|
|
+ long size = radix_tree_chunk_size(iter);
|
|
|
|
- while (size--) {
|
|
+ while (--size > 0) {
|
|
slot++;
|
|
iter->index++;
|
|
if (likely(*slot))
|
|
diff --git a/kernel/events/core.c b/kernel/events/core.c
|
|
index 3bf20e36a8e7..bfd91336e888 100644
|
|
--- a/kernel/events/core.c
|
|
+++ b/kernel/events/core.c
|
|
@@ -3096,7 +3096,7 @@ find_lively_task_by_vpid(pid_t vpid)
|
|
|
|
/* Reuse ptrace permission checks for now. */
|
|
err = -EACCES;
|
|
- if (!ptrace_may_access(task, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
|
|
goto errout;
|
|
|
|
return task;
|
|
@@ -5945,6 +5945,10 @@ static int perf_tp_filter_match(struct perf_event *event,
|
|
{
|
|
void *record = data->raw->data;
|
|
|
|
+ /* only top level events have filters set */
|
|
+ if (event->parent)
|
|
+ event = event->parent;
|
|
+
|
|
if (likely(!event->filter) || filter_match_preds(event->filter, record))
|
|
return 1;
|
|
return 0;
|
|
diff --git a/kernel/futex.c b/kernel/futex.c
|
|
index fda2950f2ce4..b125c385a257 100644
|
|
--- a/kernel/futex.c
|
|
+++ b/kernel/futex.c
|
|
@@ -2648,6 +2648,11 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
|
|
if (q.pi_state && (q.pi_state->owner != current)) {
|
|
spin_lock(q.lock_ptr);
|
|
ret = fixup_pi_state_owner(uaddr2, &q, current);
|
|
+ /*
|
|
+ * Drop the reference to the pi state which
|
|
+ * the requeue_pi() code acquired for us.
|
|
+ */
|
|
+ free_pi_state(q.pi_state);
|
|
spin_unlock(q.lock_ptr);
|
|
}
|
|
} else {
|
|
@@ -2774,7 +2779,7 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
|
|
}
|
|
|
|
ret = -EPERM;
|
|
- if (!ptrace_may_access(p, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
|
|
goto err_unlock;
|
|
|
|
head = p->robust_list;
|
|
diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
|
|
index f9f44fd4d34d..3888617a1f9e 100644
|
|
--- a/kernel/futex_compat.c
|
|
+++ b/kernel/futex_compat.c
|
|
@@ -155,7 +155,7 @@ COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid,
|
|
}
|
|
|
|
ret = -EPERM;
|
|
- if (!ptrace_may_access(p, PTRACE_MODE_READ))
|
|
+ if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
|
|
goto err_unlock;
|
|
|
|
head = p->compat_robust_list;
|
|
diff --git a/kernel/kcmp.c b/kernel/kcmp.c
|
|
index 0aa69ea1d8fd..3a47fa998fe0 100644
|
|
--- a/kernel/kcmp.c
|
|
+++ b/kernel/kcmp.c
|
|
@@ -122,8 +122,8 @@ SYSCALL_DEFINE5(kcmp, pid_t, pid1, pid_t, pid2, int, type,
|
|
&task2->signal->cred_guard_mutex);
|
|
if (ret)
|
|
goto err;
|
|
- if (!ptrace_may_access(task1, PTRACE_MODE_READ) ||
|
|
- !ptrace_may_access(task2, PTRACE_MODE_READ)) {
|
|
+ if (!ptrace_may_access(task1, PTRACE_MODE_READ_REALCREDS) ||
|
|
+ !ptrace_may_access(task2, PTRACE_MODE_READ_REALCREDS)) {
|
|
ret = -EPERM;
|
|
goto err_unlock;
|
|
}
|
|
diff --git a/kernel/module.c b/kernel/module.c
|
|
index 49f17c27bf11..e40617fac8ad 100644
|
|
--- a/kernel/module.c
|
|
+++ b/kernel/module.c
|
|
@@ -3381,6 +3381,11 @@ static inline int is_arm_mapping_symbol(const char *str)
|
|
&& (str[2] == '\0' || str[2] == '.');
|
|
}
|
|
|
|
+static const char *symname(struct module *mod, unsigned int symnum)
|
|
+{
|
|
+ return mod->strtab + mod->symtab[symnum].st_name;
|
|
+}
|
|
+
|
|
static const char *get_ksymbol(struct module *mod,
|
|
unsigned long addr,
|
|
unsigned long *size,
|
|
@@ -3403,15 +3408,15 @@ static const char *get_ksymbol(struct module *mod,
|
|
|
|
/* We ignore unnamed symbols: they're uninformative
|
|
* and inserted at a whim. */
|
|
+ if (*symname(mod, i) == '\0'
|
|
+ || is_arm_mapping_symbol(symname(mod, i)))
|
|
+ continue;
|
|
+
|
|
if (mod->symtab[i].st_value <= addr
|
|
- && mod->symtab[i].st_value > mod->symtab[best].st_value
|
|
- && *(mod->strtab + mod->symtab[i].st_name) != '\0'
|
|
- && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
|
|
+ && mod->symtab[i].st_value > mod->symtab[best].st_value)
|
|
best = i;
|
|
if (mod->symtab[i].st_value > addr
|
|
- && mod->symtab[i].st_value < nextval
|
|
- && *(mod->strtab + mod->symtab[i].st_name) != '\0'
|
|
- && !is_arm_mapping_symbol(mod->strtab + mod->symtab[i].st_name))
|
|
+ && mod->symtab[i].st_value < nextval)
|
|
nextval = mod->symtab[i].st_value;
|
|
}
|
|
|
|
@@ -3422,7 +3427,7 @@ static const char *get_ksymbol(struct module *mod,
|
|
*size = nextval - mod->symtab[best].st_value;
|
|
if (offset)
|
|
*offset = addr - mod->symtab[best].st_value;
|
|
- return mod->strtab + mod->symtab[best].st_name;
|
|
+ return symname(mod, best);
|
|
}
|
|
|
|
/* For kallsyms to ask for address resolution. NULL means not found. Careful
|
|
@@ -3523,8 +3528,7 @@ int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
|
|
if (symnum < mod->num_symtab) {
|
|
*value = mod->symtab[symnum].st_value;
|
|
*type = mod->symtab[symnum].st_info;
|
|
- strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
|
|
- KSYM_NAME_LEN);
|
|
+ strlcpy(name, symname(mod, symnum), KSYM_NAME_LEN);
|
|
strlcpy(module_name, mod->name, MODULE_NAME_LEN);
|
|
*exported = is_exported(name, *value, mod);
|
|
preempt_enable();
|
|
@@ -3541,7 +3545,7 @@ static unsigned long mod_find_symname(struct module *mod, const char *name)
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < mod->num_symtab; i++)
|
|
- if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0 &&
|
|
+ if (strcmp(name, symname(mod, i)) == 0 &&
|
|
mod->symtab[i].st_info != 'U')
|
|
return mod->symtab[i].st_value;
|
|
return 0;
|
|
@@ -3583,7 +3587,7 @@ int module_kallsyms_on_each_symbol(int (*fn)(void *, const char *,
|
|
if (mod->state == MODULE_STATE_UNFORMED)
|
|
continue;
|
|
for (i = 0; i < mod->num_symtab; i++) {
|
|
- ret = fn(data, mod->strtab + mod->symtab[i].st_name,
|
|
+ ret = fn(data, symname(mod, i),
|
|
mod, mod->symtab[i].st_value);
|
|
if (ret != 0)
|
|
return ret;
|
|
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
|
|
index be9760f8284a..4524314ecbb4 100644
|
|
--- a/kernel/ptrace.c
|
|
+++ b/kernel/ptrace.c
|
|
@@ -225,6 +225,14 @@ static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
|
|
static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
|
{
|
|
const struct cred *cred = current_cred(), *tcred;
|
|
+ int dumpable = 0;
|
|
+ kuid_t caller_uid;
|
|
+ kgid_t caller_gid;
|
|
+
|
|
+ if (!(mode & PTRACE_MODE_FSCREDS) == !(mode & PTRACE_MODE_REALCREDS)) {
|
|
+ WARN(1, "denying ptrace access check without PTRACE_MODE_*CREDS\n");
|
|
+ return -EPERM;
|
|
+ }
|
|
|
|
/* May we inspect the given task?
|
|
* This check is used both for attaching with ptrace
|
|
@@ -234,18 +242,33 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
|
* because setting up the necessary parent/child relationship
|
|
* or halting the specified task is impossible.
|
|
*/
|
|
- int dumpable = 0;
|
|
+
|
|
/* Don't let security modules deny introspection */
|
|
if (same_thread_group(task, current))
|
|
return 0;
|
|
rcu_read_lock();
|
|
+ if (mode & PTRACE_MODE_FSCREDS) {
|
|
+ caller_uid = cred->fsuid;
|
|
+ caller_gid = cred->fsgid;
|
|
+ } else {
|
|
+ /*
|
|
+ * Using the euid would make more sense here, but something
|
|
+ * in userland might rely on the old behavior, and this
|
|
+ * shouldn't be a security problem since
|
|
+ * PTRACE_MODE_REALCREDS implies that the caller explicitly
|
|
+ * used a syscall that requests access to another process
|
|
+ * (and not a filesystem syscall to procfs).
|
|
+ */
|
|
+ caller_uid = cred->uid;
|
|
+ caller_gid = cred->gid;
|
|
+ }
|
|
tcred = __task_cred(task);
|
|
- if (uid_eq(cred->uid, tcred->euid) &&
|
|
- uid_eq(cred->uid, tcred->suid) &&
|
|
- uid_eq(cred->uid, tcred->uid) &&
|
|
- gid_eq(cred->gid, tcred->egid) &&
|
|
- gid_eq(cred->gid, tcred->sgid) &&
|
|
- gid_eq(cred->gid, tcred->gid))
|
|
+ if (uid_eq(caller_uid, tcred->euid) &&
|
|
+ uid_eq(caller_uid, tcred->suid) &&
|
|
+ uid_eq(caller_uid, tcred->uid) &&
|
|
+ gid_eq(caller_gid, tcred->egid) &&
|
|
+ gid_eq(caller_gid, tcred->sgid) &&
|
|
+ gid_eq(caller_gid, tcred->gid))
|
|
goto ok;
|
|
if (ptrace_has_cap(tcred->user_ns, mode))
|
|
goto ok;
|
|
@@ -312,7 +335,7 @@ static int ptrace_attach(struct task_struct *task, long request,
|
|
goto out;
|
|
|
|
task_lock(task);
|
|
- retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
|
|
+ retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH_REALCREDS);
|
|
task_unlock(task);
|
|
if (retval)
|
|
goto unlock_creds;
|
|
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
|
|
index 98f2d7e91a91..1cbfc16d0b37 100644
|
|
--- a/lib/dma-debug.c
|
|
+++ b/lib/dma-debug.c
|
|
@@ -1165,7 +1165,7 @@ static inline bool overlap(void *addr, unsigned long len, void *start, void *end
|
|
|
|
static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len)
|
|
{
|
|
- if (overlap(addr, len, _text, _etext) ||
|
|
+ if (overlap(addr, len, _stext, _etext) ||
|
|
overlap(addr, len, __start_rodata, __end_rodata))
|
|
err_printk(dev, NULL, "DMA-API: device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len);
|
|
}
|
|
@@ -1440,7 +1440,7 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
|
|
entry->type = dma_debug_coherent;
|
|
entry->dev = dev;
|
|
entry->pfn = page_to_pfn(virt_to_page(virt));
|
|
- entry->offset = (size_t) virt & PAGE_MASK;
|
|
+ entry->offset = (size_t) virt & ~PAGE_MASK;
|
|
entry->size = size;
|
|
entry->dev_addr = dma_addr;
|
|
entry->direction = DMA_BIDIRECTIONAL;
|
|
@@ -1456,7 +1456,7 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
|
|
.type = dma_debug_coherent,
|
|
.dev = dev,
|
|
.pfn = page_to_pfn(virt_to_page(virt)),
|
|
- .offset = (size_t) virt & PAGE_MASK,
|
|
+ .offset = (size_t) virt & ~PAGE_MASK,
|
|
.dev_addr = addr,
|
|
.size = size,
|
|
.direction = DMA_BIDIRECTIONAL,
|
|
diff --git a/lib/dump_stack.c b/lib/dump_stack.c
|
|
index f23b63f0a1c3..1e21b4682666 100644
|
|
--- a/lib/dump_stack.c
|
|
+++ b/lib/dump_stack.c
|
|
@@ -25,6 +25,7 @@ static atomic_t dump_lock = ATOMIC_INIT(-1);
|
|
|
|
asmlinkage void dump_stack(void)
|
|
{
|
|
+ unsigned long flags;
|
|
int was_locked;
|
|
int old;
|
|
int cpu;
|
|
@@ -33,9 +34,8 @@ asmlinkage void dump_stack(void)
|
|
* Permit this cpu to perform nested stack dumps while serialising
|
|
* against other CPUs
|
|
*/
|
|
- preempt_disable();
|
|
-
|
|
retry:
|
|
+ local_irq_save(flags);
|
|
cpu = smp_processor_id();
|
|
old = atomic_cmpxchg(&dump_lock, -1, cpu);
|
|
if (old == -1) {
|
|
@@ -43,6 +43,7 @@ retry:
|
|
} else if (old == cpu) {
|
|
was_locked = 1;
|
|
} else {
|
|
+ local_irq_restore(flags);
|
|
cpu_relax();
|
|
goto retry;
|
|
}
|
|
@@ -52,7 +53,7 @@ retry:
|
|
if (!was_locked)
|
|
atomic_set(&dump_lock, -1);
|
|
|
|
- preempt_enable();
|
|
+ local_irq_restore(flags);
|
|
}
|
|
#else
|
|
asmlinkage void dump_stack(void)
|
|
diff --git a/lib/klist.c b/lib/klist.c
|
|
index 358a368a2947..2e59aecbec0d 100644
|
|
--- a/lib/klist.c
|
|
+++ b/lib/klist.c
|
|
@@ -282,9 +282,9 @@ void klist_iter_init_node(struct klist *k, struct klist_iter *i,
|
|
struct klist_node *n)
|
|
{
|
|
i->i_klist = k;
|
|
- i->i_cur = n;
|
|
- if (n)
|
|
- kref_get(&n->n_ref);
|
|
+ i->i_cur = NULL;
|
|
+ if (n && kref_get_unless_zero(&n->n_ref))
|
|
+ i->i_cur = n;
|
|
}
|
|
EXPORT_SYMBOL_GPL(klist_iter_init_node);
|
|
|
|
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
|
|
index 7e30d2a7f346..7fdc4121e44c 100644
|
|
--- a/lib/radix-tree.c
|
|
+++ b/lib/radix-tree.c
|
|
@@ -977,9 +977,13 @@ radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
|
|
return 0;
|
|
|
|
radix_tree_for_each_slot(slot, root, &iter, first_index) {
|
|
- results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
|
|
+ results[ret] = rcu_dereference_raw(*slot);
|
|
if (!results[ret])
|
|
continue;
|
|
+ if (radix_tree_is_indirect_ptr(results[ret])) {
|
|
+ slot = radix_tree_iter_retry(&iter);
|
|
+ continue;
|
|
+ }
|
|
if (++ret == max_items)
|
|
break;
|
|
}
|
|
@@ -1056,9 +1060,13 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
|
|
return 0;
|
|
|
|
radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) {
|
|
- results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
|
|
+ results[ret] = rcu_dereference_raw(*slot);
|
|
if (!results[ret])
|
|
continue;
|
|
+ if (radix_tree_is_indirect_ptr(results[ret])) {
|
|
+ slot = radix_tree_iter_retry(&iter);
|
|
+ continue;
|
|
+ }
|
|
if (++ret == max_items)
|
|
break;
|
|
}
|
|
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
|
|
index b58d4fbe6c48..51d7cc8bb5f1 100644
|
|
--- a/mm/memcontrol.c
|
|
+++ b/mm/memcontrol.c
|
|
@@ -5858,16 +5858,17 @@ static void __mem_cgroup_usage_unregister_event(struct mem_cgroup *memcg,
|
|
swap_buffers:
|
|
/* Swap primary and spare array */
|
|
thresholds->spare = thresholds->primary;
|
|
- /* If all events are unregistered, free the spare array */
|
|
- if (!new) {
|
|
- kfree(thresholds->spare);
|
|
- thresholds->spare = NULL;
|
|
- }
|
|
|
|
rcu_assign_pointer(thresholds->primary, new);
|
|
|
|
/* To be sure that nobody uses thresholds */
|
|
synchronize_rcu();
|
|
+
|
|
+ /* If all events are unregistered, free the spare array */
|
|
+ if (!new) {
|
|
+ kfree(thresholds->spare);
|
|
+ thresholds->spare = NULL;
|
|
+ }
|
|
unlock:
|
|
mutex_unlock(&memcg->thresholds_lock);
|
|
}
|
|
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
|
|
index 42aeb848b8e9..580dbc22ef74 100644
|
|
--- a/mm/memory-failure.c
|
|
+++ b/mm/memory-failure.c
|
|
@@ -1509,7 +1509,7 @@ static int get_any_page(struct page *page, unsigned long pfn, int flags)
|
|
* Did it turn free?
|
|
*/
|
|
ret = __get_any_page(page, pfn, 0);
|
|
- if (!PageLRU(page)) {
|
|
+ if (ret == 1 && !PageLRU(page)) {
|
|
/* Drop page reference which is from __get_any_page() */
|
|
put_page(page);
|
|
pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n",
|
|
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
|
|
index 5bba3b35bec8..35e14c784bef 100644
|
|
--- a/mm/memory_hotplug.c
|
|
+++ b/mm/memory_hotplug.c
|
|
@@ -1220,23 +1220,30 @@ int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
|
|
*/
|
|
static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
|
|
{
|
|
- unsigned long pfn;
|
|
+ unsigned long pfn, sec_end_pfn;
|
|
struct zone *zone = NULL;
|
|
struct page *page;
|
|
int i;
|
|
- for (pfn = start_pfn;
|
|
+ for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
|
|
pfn < end_pfn;
|
|
- pfn += MAX_ORDER_NR_PAGES) {
|
|
- i = 0;
|
|
- /* This is just a CONFIG_HOLES_IN_ZONE check.*/
|
|
- while ((i < MAX_ORDER_NR_PAGES) && !pfn_valid_within(pfn + i))
|
|
- i++;
|
|
- if (i == MAX_ORDER_NR_PAGES)
|
|
+ pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
|
|
+ /* Make sure the memory section is present first */
|
|
+ if (!present_section_nr(pfn_to_section_nr(pfn)))
|
|
continue;
|
|
- page = pfn_to_page(pfn + i);
|
|
- if (zone && page_zone(page) != zone)
|
|
- return 0;
|
|
- zone = page_zone(page);
|
|
+ for (; pfn < sec_end_pfn && pfn < end_pfn;
|
|
+ pfn += MAX_ORDER_NR_PAGES) {
|
|
+ i = 0;
|
|
+ /* This is just a CONFIG_HOLES_IN_ZONE check.*/
|
|
+ while ((i < MAX_ORDER_NR_PAGES) &&
|
|
+ !pfn_valid_within(pfn + i))
|
|
+ i++;
|
|
+ if (i == MAX_ORDER_NR_PAGES)
|
|
+ continue;
|
|
+ page = pfn_to_page(pfn + i);
|
|
+ if (zone && page_zone(page) != zone)
|
|
+ return 0;
|
|
+ zone = page_zone(page);
|
|
+ }
|
|
}
|
|
return 1;
|
|
}
|
|
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
|
|
index fd26d0433509..e739825be8b3 100644
|
|
--- a/mm/process_vm_access.c
|
|
+++ b/mm/process_vm_access.c
|
|
@@ -298,7 +298,7 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec,
|
|
goto free_proc_pages;
|
|
}
|
|
|
|
- mm = mm_access(task, PTRACE_MODE_ATTACH);
|
|
+ mm = mm_access(task, PTRACE_MODE_ATTACH_REALCREDS);
|
|
if (!mm || IS_ERR(mm)) {
|
|
rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
|
|
/*
|
|
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
|
|
index 9ad561152eb6..8b61288e5746 100644
|
|
--- a/net/ipv6/ip6mr.c
|
|
+++ b/net/ipv6/ip6mr.c
|
|
@@ -336,7 +336,7 @@ static struct mr6_table *ip6mr_new_table(struct net *net, u32 id)
|
|
|
|
static void ip6mr_free_table(struct mr6_table *mrt)
|
|
{
|
|
- del_timer(&mrt->ipmr_expire_timer);
|
|
+ del_timer_sync(&mrt->ipmr_expire_timer);
|
|
mroute_clean_tables(mrt, true);
|
|
kfree(mrt);
|
|
}
|
|
diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter
|
|
index 549d0ab8c662..dabd2a4cb4e5 100755
|
|
--- a/scripts/bloat-o-meter
|
|
+++ b/scripts/bloat-o-meter
|
|
@@ -56,8 +56,8 @@ for name in common:
|
|
delta.sort()
|
|
delta.reverse()
|
|
|
|
-print "add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
|
|
- (add, remove, grow, shrink, up, -down, up-down)
|
|
-print "%-40s %7s %7s %+7s" % ("function", "old", "new", "delta")
|
|
+print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \
|
|
+ (add, remove, grow, shrink, up, -down, up-down))
|
|
+print("%-40s %7s %7s %+7s" % ("function", "old", "new", "delta"))
|
|
for d, n in delta:
|
|
- if d: print "%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)
|
|
+ if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d))
|
|
diff --git a/security/commoncap.c b/security/commoncap.c
|
|
index 963dc5981661..a484506445d7 100644
|
|
--- a/security/commoncap.c
|
|
+++ b/security/commoncap.c
|
|
@@ -142,12 +142,17 @@ int cap_ptrace_access_check(struct task_struct *child, unsigned int mode)
|
|
{
|
|
int ret = 0;
|
|
const struct cred *cred, *child_cred;
|
|
+ const kernel_cap_t *caller_caps;
|
|
|
|
rcu_read_lock();
|
|
cred = current_cred();
|
|
child_cred = __task_cred(child);
|
|
+ if (mode & PTRACE_MODE_FSCREDS)
|
|
+ caller_caps = &cred->cap_effective;
|
|
+ else
|
|
+ caller_caps = &cred->cap_permitted;
|
|
if (cred->user_ns == child_cred->user_ns &&
|
|
- cap_issubset(child_cred->cap_permitted, cred->cap_permitted))
|
|
+ cap_issubset(child_cred->cap_permitted, *caller_caps))
|
|
goto out;
|
|
if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE))
|
|
goto out;
|
|
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
|
|
index 67c91d226552..ee0522a8f730 100644
|
|
--- a/sound/core/seq/seq_ports.c
|
|
+++ b/sound/core/seq/seq_ports.c
|
|
@@ -540,19 +540,22 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
|
|
bool is_src, bool ack)
|
|
{
|
|
struct snd_seq_port_subs_info *grp;
|
|
+ struct list_head *list;
|
|
+ bool empty;
|
|
|
|
grp = is_src ? &port->c_src : &port->c_dest;
|
|
+ list = is_src ? &subs->src_list : &subs->dest_list;
|
|
down_write(&grp->list_mutex);
|
|
write_lock_irq(&grp->list_lock);
|
|
- if (is_src)
|
|
- list_del(&subs->src_list);
|
|
- else
|
|
- list_del(&subs->dest_list);
|
|
+ empty = list_empty(list);
|
|
+ if (!empty)
|
|
+ list_del_init(list);
|
|
grp->exclusive = 0;
|
|
write_unlock_irq(&grp->list_lock);
|
|
up_write(&grp->list_mutex);
|
|
|
|
- unsubscribe_port(client, port, grp, &subs->info, ack);
|
|
+ if (!empty)
|
|
+ unsubscribe_port(client, port, grp, &subs->info, ack);
|
|
}
|
|
|
|
/* connect two ports */
|
|
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
|
|
index 30e8e0c3f117..56b8a3e00522 100644
|
|
--- a/tools/lib/traceevent/event-parse.c
|
|
+++ b/tools/lib/traceevent/event-parse.c
|
|
@@ -4249,13 +4249,12 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
|
|
sizeof(long) != 8) {
|
|
char *p;
|
|
|
|
- ls = 2;
|
|
/* make %l into %ll */
|
|
- p = strchr(format, 'l');
|
|
- if (p)
|
|
+ if (ls == 1 && (p = strchr(format, 'l')))
|
|
memmove(p+1, p, strlen(p)+1);
|
|
else if (strcmp(format, "%p") == 0)
|
|
strcpy(format, "0x%llx");
|
|
+ ls = 2;
|
|
}
|
|
switch (ls) {
|
|
case -2:
|
|
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
|
|
index fae38d9a44a4..65d6a7a88c53 100644
|
|
--- a/tools/perf/Documentation/perf-trace.txt
|
|
+++ b/tools/perf/Documentation/perf-trace.txt
|
|
@@ -59,7 +59,6 @@ OPTIONS
|
|
--verbose=::
|
|
Verbosity level.
|
|
|
|
--i::
|
|
--no-inherit::
|
|
Child tasks do not inherit counters.
|
|
|