mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 20:23:57 +08:00
Merge branch 'akpm' (patches from Andrew)
Merge misc fixes from Andrew Morton: "16 patches This includes a new rtc driver for the Abracon AB x80x and isn't very appropriate for -rc2. It was still being fiddled with a bit during the merge window and I fell asleep during -rc1" [ So I took the new driver, it seems small and won't regress anything. I'm a softy. - Linus ] * emailed patches from Andrew Morton <akpm@linux-foundation.org>: rtc: armada38x: fix concurrency access in armada38x_rtc_set_time ocfs2: dlm: fix race between purge and get lock resource nilfs2: fix sanity check of btree level in nilfs_btree_root_broken() util_macros.h: have array pointer point to array of constants configfs: init configfs module earlier at boot time mm/hwpoison-inject: check PageLRU of hpage mm/hwpoison-inject: fix refcounting in no-injection case mm: soft-offline: fix num_poisoned_pages counting on concurrent events rtc: add rtc-abx80x, a driver for the Abracon AB x80x i2c rtc Documentation: bindings: add abracon,abx80x kasan: show gcc version requirements in Kconfig and Documentation mm/memory-failure: call shake_page() when error hits thp tail page lib: delete lib/find_last_bit.c MAINTAINERS: add co-maintainer for LED subsystem zram: add Designated Reviewer for zram in MAINTAINERS revert "zram: move compact_store() to sysfs functions area"
This commit is contained in:
commit
2a171aa21a
30
Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
Normal file
30
Documentation/devicetree/bindings/rtc/abracon,abx80x.txt
Normal file
@ -0,0 +1,30 @@
|
||||
Abracon ABX80X I2C ultra low power RTC/Alarm chip
|
||||
|
||||
The Abracon ABX80X family consist of the ab0801, ab0803, ab0804, ab0805, ab1801,
|
||||
ab1803, ab1804 and ab1805. The ab0805 is the superset of ab080x and the ab1805
|
||||
is the superset of ab180x.
|
||||
|
||||
Required properties:
|
||||
|
||||
- "compatible": should one of:
|
||||
"abracon,abx80x"
|
||||
"abracon,ab0801"
|
||||
"abracon,ab0803"
|
||||
"abracon,ab0804"
|
||||
"abracon,ab0805"
|
||||
"abracon,ab1801"
|
||||
"abracon,ab1803"
|
||||
"abracon,ab1804"
|
||||
"abracon,ab1805"
|
||||
Using "abracon,abx80x" will enable chip autodetection.
|
||||
- "reg": I2C bus address of the device
|
||||
|
||||
Optional properties:
|
||||
|
||||
The abx804 and abx805 have a trickle charger that is able to charge the
|
||||
connected battery or supercap. Both the following properties have to be defined
|
||||
and valid to enable charging:
|
||||
|
||||
- "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
|
||||
- "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
|
||||
resistor, the other values are in ohm.
|
@ -9,7 +9,9 @@ a fast and comprehensive solution for finding use-after-free and out-of-bounds
|
||||
bugs.
|
||||
|
||||
KASan uses compile-time instrumentation for checking every memory access,
|
||||
therefore you will need a certain version of GCC > 4.9.2
|
||||
therefore you will need a gcc version of 4.9.2 or later. KASan could detect out
|
||||
of bounds accesses to stack or global variables, but only if gcc 5.0 or later was
|
||||
used to built the kernel.
|
||||
|
||||
Currently KASan is supported only for x86_64 architecture and requires that the
|
||||
kernel be built with the SLUB allocator.
|
||||
@ -23,8 +25,8 @@ To enable KASAN configure kernel with:
|
||||
|
||||
and choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE. Outline/inline
|
||||
is compiler instrumentation types. The former produces smaller binary the
|
||||
latter is 1.1 - 2 times faster. Inline instrumentation requires GCC 5.0 or
|
||||
latter.
|
||||
latter is 1.1 - 2 times faster. Inline instrumentation requires a gcc version
|
||||
of 5.0 or later.
|
||||
|
||||
Currently KASAN works only with the SLUB memory allocator.
|
||||
For better bug detection and nicer report, enable CONFIG_STACKTRACE and put
|
||||
|
@ -5805,6 +5805,7 @@ F: drivers/scsi/53c700*
|
||||
LED SUBSYSTEM
|
||||
M: Bryan Wu <cooloney@gmail.com>
|
||||
M: Richard Purdie <rpurdie@rpsys.net>
|
||||
M: Jacek Anaszewski <j.anaszewski@samsung.com>
|
||||
L: linux-leds@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
|
||||
S: Maintained
|
||||
@ -11037,6 +11038,7 @@ F: drivers/media/pci/zoran/
|
||||
ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER
|
||||
M: Minchan Kim <minchan@kernel.org>
|
||||
M: Nitin Gupta <ngupta@vflare.org>
|
||||
R: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
|
||||
L: linux-kernel@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/block/zram/
|
||||
|
@ -74,6 +74,27 @@ static inline struct zram *dev_to_zram(struct device *dev)
|
||||
return (struct zram *)dev_to_disk(dev)->private_data;
|
||||
}
|
||||
|
||||
static ssize_t compact_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t len)
|
||||
{
|
||||
unsigned long nr_migrated;
|
||||
struct zram *zram = dev_to_zram(dev);
|
||||
struct zram_meta *meta;
|
||||
|
||||
down_read(&zram->init_lock);
|
||||
if (!init_done(zram)) {
|
||||
up_read(&zram->init_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
meta = zram->meta;
|
||||
nr_migrated = zs_compact(meta->mem_pool);
|
||||
atomic64_add(nr_migrated, &zram->stats.num_migrated);
|
||||
up_read(&zram->init_lock);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t disksize_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
@ -1038,6 +1059,7 @@ static const struct block_device_operations zram_devops = {
|
||||
.owner = THIS_MODULE
|
||||
};
|
||||
|
||||
static DEVICE_ATTR_WO(compact);
|
||||
static DEVICE_ATTR_RW(disksize);
|
||||
static DEVICE_ATTR_RO(initstate);
|
||||
static DEVICE_ATTR_WO(reset);
|
||||
@ -1114,6 +1136,7 @@ static struct attribute *zram_disk_attrs[] = {
|
||||
&dev_attr_num_writes.attr,
|
||||
&dev_attr_failed_reads.attr,
|
||||
&dev_attr_failed_writes.attr,
|
||||
&dev_attr_compact.attr,
|
||||
&dev_attr_invalid_io.attr,
|
||||
&dev_attr_notify_free.attr,
|
||||
&dev_attr_zero_pages.attr,
|
||||
|
@ -164,6 +164,16 @@ config RTC_DRV_ABB5ZES3
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-ab-b5ze-s3.
|
||||
|
||||
config RTC_DRV_ABX80X
|
||||
tristate "Abracon ABx80x"
|
||||
help
|
||||
If you say yes here you get support for Abracon AB080X and AB180X
|
||||
families of ultra-low-power battery- and capacitor-backed real-time
|
||||
clock chips.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-abx80x.
|
||||
|
||||
config RTC_DRV_AS3722
|
||||
tristate "ams AS3722 RTC driver"
|
||||
depends on MFD_AS3722
|
||||
|
@ -25,6 +25,7 @@ obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
|
||||
obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o
|
||||
obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o
|
||||
obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
|
||||
obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o
|
||||
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
|
||||
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o
|
||||
obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
|
||||
|
307
drivers/rtc/rtc-abx80x.c
Normal file
307
drivers/rtc/rtc-abx80x.c
Normal file
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* A driver for the I2C members of the Abracon AB x8xx RTC family,
|
||||
* and compatible: AB 1805 and AB 0805
|
||||
*
|
||||
* Copyright 2014-2015 Macq S.A.
|
||||
*
|
||||
* Author: Philippe De Muyter <phdm@macqel.be>
|
||||
* Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
#define ABX8XX_REG_HTH 0x00
|
||||
#define ABX8XX_REG_SC 0x01
|
||||
#define ABX8XX_REG_MN 0x02
|
||||
#define ABX8XX_REG_HR 0x03
|
||||
#define ABX8XX_REG_DA 0x04
|
||||
#define ABX8XX_REG_MO 0x05
|
||||
#define ABX8XX_REG_YR 0x06
|
||||
#define ABX8XX_REG_WD 0x07
|
||||
|
||||
#define ABX8XX_REG_CTRL1 0x10
|
||||
#define ABX8XX_CTRL_WRITE BIT(1)
|
||||
#define ABX8XX_CTRL_12_24 BIT(6)
|
||||
|
||||
#define ABX8XX_REG_CFG_KEY 0x1f
|
||||
#define ABX8XX_CFG_KEY_MISC 0x9d
|
||||
|
||||
#define ABX8XX_REG_ID0 0x28
|
||||
|
||||
#define ABX8XX_REG_TRICKLE 0x20
|
||||
#define ABX8XX_TRICKLE_CHARGE_ENABLE 0xa0
|
||||
#define ABX8XX_TRICKLE_STANDARD_DIODE 0x8
|
||||
#define ABX8XX_TRICKLE_SCHOTTKY_DIODE 0x4
|
||||
|
||||
static u8 trickle_resistors[] = {0, 3, 6, 11};
|
||||
|
||||
enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
|
||||
AB1801, AB1803, AB1804, AB1805, ABX80X};
|
||||
|
||||
struct abx80x_cap {
|
||||
u16 pn;
|
||||
bool has_tc;
|
||||
};
|
||||
|
||||
static struct abx80x_cap abx80x_caps[] = {
|
||||
[AB0801] = {.pn = 0x0801},
|
||||
[AB0803] = {.pn = 0x0803},
|
||||
[AB0804] = {.pn = 0x0804, .has_tc = true},
|
||||
[AB0805] = {.pn = 0x0805, .has_tc = true},
|
||||
[AB1801] = {.pn = 0x1801},
|
||||
[AB1803] = {.pn = 0x1803},
|
||||
[AB1804] = {.pn = 0x1804, .has_tc = true},
|
||||
[AB1805] = {.pn = 0x1805, .has_tc = true},
|
||||
[ABX80X] = {.pn = 0}
|
||||
};
|
||||
|
||||
static struct i2c_driver abx80x_driver;
|
||||
|
||||
static int abx80x_enable_trickle_charger(struct i2c_client *client,
|
||||
u8 trickle_cfg)
|
||||
{
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Write the configuration key register to enable access to the Trickle
|
||||
* register
|
||||
*/
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
|
||||
ABX8XX_CFG_KEY_MISC);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to write configuration key\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_TRICKLE,
|
||||
ABX8XX_TRICKLE_CHARGE_ENABLE |
|
||||
trickle_cfg);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to write trickle register\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
unsigned char buf[8];
|
||||
int err;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_HTH,
|
||||
sizeof(buf), buf);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to read date\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
tm->tm_sec = bcd2bin(buf[ABX8XX_REG_SC] & 0x7F);
|
||||
tm->tm_min = bcd2bin(buf[ABX8XX_REG_MN] & 0x7F);
|
||||
tm->tm_hour = bcd2bin(buf[ABX8XX_REG_HR] & 0x3F);
|
||||
tm->tm_wday = buf[ABX8XX_REG_WD] & 0x7;
|
||||
tm->tm_mday = bcd2bin(buf[ABX8XX_REG_DA] & 0x3F);
|
||||
tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F) - 1;
|
||||
tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 100;
|
||||
|
||||
err = rtc_valid_tm(tm);
|
||||
if (err < 0)
|
||||
dev_err(&client->dev, "retrieved date/time is not valid.\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
unsigned char buf[8];
|
||||
int err;
|
||||
|
||||
if (tm->tm_year < 100)
|
||||
return -EINVAL;
|
||||
|
||||
buf[ABX8XX_REG_HTH] = 0;
|
||||
buf[ABX8XX_REG_SC] = bin2bcd(tm->tm_sec);
|
||||
buf[ABX8XX_REG_MN] = bin2bcd(tm->tm_min);
|
||||
buf[ABX8XX_REG_HR] = bin2bcd(tm->tm_hour);
|
||||
buf[ABX8XX_REG_DA] = bin2bcd(tm->tm_mday);
|
||||
buf[ABX8XX_REG_MO] = bin2bcd(tm->tm_mon + 1);
|
||||
buf[ABX8XX_REG_YR] = bin2bcd(tm->tm_year - 100);
|
||||
buf[ABX8XX_REG_WD] = tm->tm_wday;
|
||||
|
||||
err = i2c_smbus_write_i2c_block_data(client, ABX8XX_REG_HTH,
|
||||
sizeof(buf), buf);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to write to date registers\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops abx80x_rtc_ops = {
|
||||
.read_time = abx80x_rtc_read_time,
|
||||
.set_time = abx80x_rtc_set_time,
|
||||
};
|
||||
|
||||
static int abx80x_dt_trickle_cfg(struct device_node *np)
|
||||
{
|
||||
const char *diode;
|
||||
int trickle_cfg = 0;
|
||||
int i, ret;
|
||||
u32 tmp;
|
||||
|
||||
ret = of_property_read_string(np, "abracon,tc-diode", &diode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!strcmp(diode, "standard"))
|
||||
trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE;
|
||||
else if (!strcmp(diode, "schottky"))
|
||||
trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < sizeof(trickle_resistors); i++)
|
||||
if (trickle_resistors[i] == tmp)
|
||||
break;
|
||||
|
||||
if (i == sizeof(trickle_resistors))
|
||||
return -EINVAL;
|
||||
|
||||
return (trickle_cfg | i);
|
||||
}
|
||||
|
||||
static int abx80x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device_node *np = client->dev.of_node;
|
||||
struct rtc_device *rtc;
|
||||
int i, data, err, trickle_cfg = -EINVAL;
|
||||
char buf[7];
|
||||
unsigned int part = id->driver_data;
|
||||
unsigned int partnumber;
|
||||
unsigned int majrev, minrev;
|
||||
unsigned int lot;
|
||||
unsigned int wafer;
|
||||
unsigned int uid;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
return -ENODEV;
|
||||
|
||||
err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ID0,
|
||||
sizeof(buf), buf);
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to read partnumber\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
partnumber = (buf[0] << 8) | buf[1];
|
||||
majrev = buf[2] >> 3;
|
||||
minrev = buf[2] & 0x7;
|
||||
lot = ((buf[4] & 0x80) << 2) | ((buf[6] & 0x80) << 1) | buf[3];
|
||||
uid = ((buf[4] & 0x7f) << 8) | buf[5];
|
||||
wafer = (buf[6] & 0x7c) >> 2;
|
||||
dev_info(&client->dev, "model %04x, revision %u.%u, lot %x, wafer %x, uid %x\n",
|
||||
partnumber, majrev, minrev, lot, wafer, uid);
|
||||
|
||||
data = i2c_smbus_read_byte_data(client, ABX8XX_REG_CTRL1);
|
||||
if (data < 0) {
|
||||
dev_err(&client->dev, "Unable to read control register\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL1,
|
||||
((data & ~ABX8XX_CTRL_12_24) |
|
||||
ABX8XX_CTRL_WRITE));
|
||||
if (err < 0) {
|
||||
dev_err(&client->dev, "Unable to write control register\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* part autodetection */
|
||||
if (part == ABX80X) {
|
||||
for (i = 0; abx80x_caps[i].pn; i++)
|
||||
if (partnumber == abx80x_caps[i].pn)
|
||||
break;
|
||||
if (abx80x_caps[i].pn == 0) {
|
||||
dev_err(&client->dev, "Unknown part: %04x\n",
|
||||
partnumber);
|
||||
return -EINVAL;
|
||||
}
|
||||
part = i;
|
||||
}
|
||||
|
||||
if (partnumber != abx80x_caps[part].pn) {
|
||||
dev_err(&client->dev, "partnumber mismatch %04x != %04x\n",
|
||||
partnumber, abx80x_caps[part].pn);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (np && abx80x_caps[part].has_tc)
|
||||
trickle_cfg = abx80x_dt_trickle_cfg(np);
|
||||
|
||||
if (trickle_cfg > 0) {
|
||||
dev_info(&client->dev, "Enabling trickle charger: %02x\n",
|
||||
trickle_cfg);
|
||||
abx80x_enable_trickle_charger(client, trickle_cfg);
|
||||
}
|
||||
|
||||
rtc = devm_rtc_device_register(&client->dev, abx80x_driver.driver.name,
|
||||
&abx80x_rtc_ops, THIS_MODULE);
|
||||
|
||||
if (IS_ERR(rtc))
|
||||
return PTR_ERR(rtc);
|
||||
|
||||
i2c_set_clientdata(client, rtc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int abx80x_remove(struct i2c_client *client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id abx80x_id[] = {
|
||||
{ "abx80x", ABX80X },
|
||||
{ "ab0801", AB0801 },
|
||||
{ "ab0803", AB0803 },
|
||||
{ "ab0804", AB0804 },
|
||||
{ "ab0805", AB0805 },
|
||||
{ "ab1801", AB1801 },
|
||||
{ "ab1803", AB1803 },
|
||||
{ "ab1804", AB1804 },
|
||||
{ "ab1805", AB1805 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, abx80x_id);
|
||||
|
||||
static struct i2c_driver abx80x_driver = {
|
||||
.driver = {
|
||||
.name = "rtc-abx80x",
|
||||
},
|
||||
.probe = abx80x_probe,
|
||||
.remove = abx80x_remove,
|
||||
.id_table = abx80x_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(abx80x_driver);
|
||||
|
||||
MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>");
|
||||
MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
|
||||
MODULE_DESCRIPTION("Abracon ABX80X RTC driver");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -40,6 +40,13 @@ struct armada38x_rtc {
|
||||
void __iomem *regs;
|
||||
void __iomem *regs_soc;
|
||||
spinlock_t lock;
|
||||
/*
|
||||
* While setting the time, the RTC TIME register should not be
|
||||
* accessed. Setting the RTC time involves sleeping during
|
||||
* 100ms, so a mutex instead of a spinlock is used to protect
|
||||
* it
|
||||
*/
|
||||
struct mutex mutex_time;
|
||||
int irq;
|
||||
};
|
||||
|
||||
@ -59,8 +66,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
|
||||
unsigned long time, time_check, flags;
|
||||
|
||||
spin_lock_irqsave(&rtc->lock, flags);
|
||||
|
||||
mutex_lock(&rtc->mutex_time);
|
||||
time = readl(rtc->regs + RTC_TIME);
|
||||
/*
|
||||
* WA for failing time set attempts. As stated in HW ERRATA if
|
||||
@ -71,7 +77,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
if ((time_check - time) > 1)
|
||||
time_check = readl(rtc->regs + RTC_TIME);
|
||||
|
||||
spin_unlock_irqrestore(&rtc->lock, flags);
|
||||
mutex_unlock(&rtc->mutex_time);
|
||||
|
||||
rtc_time_to_tm(time_check, tm);
|
||||
|
||||
@ -94,19 +100,12 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
* then wait for 100ms before writing to the time register to be
|
||||
* sure that the data will be taken into account.
|
||||
*/
|
||||
spin_lock_irqsave(&rtc->lock, flags);
|
||||
|
||||
mutex_lock(&rtc->mutex_time);
|
||||
rtc_delayed_write(0, rtc, RTC_STATUS);
|
||||
|
||||
spin_unlock_irqrestore(&rtc->lock, flags);
|
||||
|
||||
msleep(100);
|
||||
|
||||
spin_lock_irqsave(&rtc->lock, flags);
|
||||
|
||||
rtc_delayed_write(time, rtc, RTC_TIME);
|
||||
mutex_unlock(&rtc->mutex_time);
|
||||
|
||||
spin_unlock_irqrestore(&rtc->lock, flags);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
@ -230,6 +229,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&rtc->lock);
|
||||
mutex_init(&rtc->mutex_time);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
|
||||
rtc->regs = devm_ioremap_resource(&pdev->dev, res);
|
||||
|
@ -173,5 +173,5 @@ MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION("0.0.2");
|
||||
MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration.");
|
||||
|
||||
module_init(configfs_init);
|
||||
core_initcall(configfs_init);
|
||||
module_exit(configfs_exit);
|
||||
|
@ -388,7 +388,7 @@ static int nilfs_btree_root_broken(const struct nilfs_btree_node *node,
|
||||
nchildren = nilfs_btree_node_get_nchildren(node);
|
||||
|
||||
if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
|
||||
level > NILFS_BTREE_LEVEL_MAX ||
|
||||
level >= NILFS_BTREE_LEVEL_MAX ||
|
||||
nchildren < 0 ||
|
||||
nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) {
|
||||
pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n",
|
||||
|
@ -757,6 +757,19 @@ lookup:
|
||||
if (tmpres) {
|
||||
spin_unlock(&dlm->spinlock);
|
||||
spin_lock(&tmpres->spinlock);
|
||||
|
||||
/*
|
||||
* Right after dlm spinlock was released, dlm_thread could have
|
||||
* purged the lockres. Check if lockres got unhashed. If so
|
||||
* start over.
|
||||
*/
|
||||
if (hlist_unhashed(&tmpres->hash_node)) {
|
||||
spin_unlock(&tmpres->spinlock);
|
||||
dlm_lockres_put(tmpres);
|
||||
tmpres = NULL;
|
||||
goto lookup;
|
||||
}
|
||||
|
||||
/* Wait on the thread that is mastering the resource */
|
||||
if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
|
||||
__dlm_wait_on_lockres(tmpres);
|
||||
|
@ -460,7 +460,7 @@ struct nilfs_btree_node {
|
||||
/* level */
|
||||
#define NILFS_BTREE_LEVEL_DATA 0
|
||||
#define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1)
|
||||
#define NILFS_BTREE_LEVEL_MAX 14
|
||||
#define NILFS_BTREE_LEVEL_MAX 14 /* Max level (exclusive) */
|
||||
|
||||
/**
|
||||
* struct nilfs_palloc_group_desc - block group descriptor
|
||||
|
@ -5,7 +5,7 @@
|
||||
({ \
|
||||
typeof(as) __fc_i, __fc_as = (as) - 1; \
|
||||
typeof(x) __fc_x = (x); \
|
||||
typeof(*a) *__fc_a = (a); \
|
||||
typeof(*a) const *__fc_a = (a); \
|
||||
for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \
|
||||
if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \
|
||||
__fc_a[__fc_i + 1], 2)) \
|
||||
|
@ -10,8 +10,11 @@ config KASAN
|
||||
help
|
||||
Enables kernel address sanitizer - runtime memory debugger,
|
||||
designed to find out-of-bounds accesses and use-after-free bugs.
|
||||
This is strictly debugging feature. It consumes about 1/8
|
||||
of available memory and brings about ~x3 performance slowdown.
|
||||
This is strictly a debugging feature and it requires a gcc version
|
||||
of 4.9.2 or later. Detection of out of bounds accesses to stack or
|
||||
global variables requires gcc 5.0 or later.
|
||||
This feature consumes about 1/8 of available memory and brings about
|
||||
~x3 performance slowdown.
|
||||
For better error detection enable CONFIG_STACKTRACE,
|
||||
and add slub_debug=U to boot cmdline.
|
||||
|
||||
@ -40,6 +43,7 @@ config KASAN_INLINE
|
||||
memory accesses. This is faster than outline (in some workloads
|
||||
it gives about x2 boost over outline instrumentation), but
|
||||
make kernel's .text size much bigger.
|
||||
This requires a gcc version of 5.0 or later.
|
||||
|
||||
endchoice
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
/* find_last_bit.c: fallback find next bit implementation
|
||||
*
|
||||
* Copyright (C) 2008 IBM Corporation
|
||||
* Written by Rusty Russell <rusty@rustcorp.com.au>
|
||||
* (Inspired by David Howell's find_next_bit implementation)
|
||||
*
|
||||
* Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
|
||||
* size and improve performance, 2015.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#ifndef find_last_bit
|
||||
|
||||
unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
|
||||
{
|
||||
if (size) {
|
||||
unsigned long val = BITMAP_LAST_WORD_MASK(size);
|
||||
unsigned long idx = (size-1) / BITS_PER_LONG;
|
||||
|
||||
do {
|
||||
val &= addr[idx];
|
||||
if (val)
|
||||
return idx * BITS_PER_LONG + __fls(val);
|
||||
|
||||
val = ~0ul;
|
||||
} while (idx--);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
EXPORT_SYMBOL(find_last_bit);
|
||||
|
||||
#endif
|
@ -34,13 +34,13 @@ static int hwpoison_inject(void *data, u64 val)
|
||||
if (!hwpoison_filter_enable)
|
||||
goto inject;
|
||||
|
||||
if (!PageLRU(p) && !PageHuge(p))
|
||||
shake_page(p, 0);
|
||||
if (!PageLRU(hpage) && !PageHuge(p))
|
||||
shake_page(hpage, 0);
|
||||
/*
|
||||
* This implies unable to support non-LRU pages.
|
||||
*/
|
||||
if (!PageLRU(p) && !PageHuge(p))
|
||||
return 0;
|
||||
if (!PageLRU(hpage) && !PageHuge(p))
|
||||
goto put_out;
|
||||
|
||||
/*
|
||||
* do a racy check with elevated page count, to make sure PG_hwpoison
|
||||
@ -52,11 +52,14 @@ static int hwpoison_inject(void *data, u64 val)
|
||||
err = hwpoison_filter(hpage);
|
||||
unlock_page(hpage);
|
||||
if (err)
|
||||
return 0;
|
||||
goto put_out;
|
||||
|
||||
inject:
|
||||
pr_info("Injecting memory failure at pfn %#lx\n", pfn);
|
||||
return memory_failure(pfn, 18, MF_COUNT_INCREASED);
|
||||
put_out:
|
||||
put_page(hpage);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hwpoison_unpoison(void *data, u64 val)
|
||||
|
@ -1187,10 +1187,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
|
||||
* The check (unnecessarily) ignores LRU pages being isolated and
|
||||
* walked by the page reclaim code, however that's not a big loss.
|
||||
*/
|
||||
if (!PageHuge(p) && !PageTransTail(p)) {
|
||||
if (!PageLRU(p))
|
||||
shake_page(p, 0);
|
||||
if (!PageLRU(p)) {
|
||||
if (!PageHuge(p)) {
|
||||
if (!PageLRU(hpage))
|
||||
shake_page(hpage, 0);
|
||||
if (!PageLRU(hpage)) {
|
||||
/*
|
||||
* shake_page could have turned it free.
|
||||
*/
|
||||
@ -1777,12 +1777,12 @@ int soft_offline_page(struct page *page, int flags)
|
||||
} else if (ret == 0) { /* for free pages */
|
||||
if (PageHuge(page)) {
|
||||
set_page_hwpoison_huge_page(hpage);
|
||||
dequeue_hwpoisoned_huge_page(hpage);
|
||||
atomic_long_add(1 << compound_order(hpage),
|
||||
if (!dequeue_hwpoisoned_huge_page(hpage))
|
||||
atomic_long_add(1 << compound_order(hpage),
|
||||
&num_poisoned_pages);
|
||||
} else {
|
||||
SetPageHWPoison(page);
|
||||
atomic_long_inc(&num_poisoned_pages);
|
||||
if (!TestSetPageHWPoison(page))
|
||||
atomic_long_inc(&num_poisoned_pages);
|
||||
}
|
||||
}
|
||||
unset_migratetype_isolate(page, MIGRATE_MOVABLE);
|
||||
|
Loading…
Reference in New Issue
Block a user