Commit d0631c6e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'akpm' (fixes from Andrew)

Merge emailed fixes from Andrew Morton:
 "Bunch of fixes:

   - delayed IPC updates.  I held back on this because of some possible
     outstanding bug reports, but they appear to have been addressed in
     later versions

   - A bunch of MAINTAINERS updates

   - Yet Another RTC driver.  I'd held this back while a couple of
     little issues were being worked out.

  I'm expecting an intrusive-but-simple patchset from Joe Perches which
  splits up printk.c into kernel/printk/*.  That will be a pig to
  maintain for two months so if it passes testing I'd like to get it
  upstream after a week or so."

* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (35 commits)
  printk: fix incorrect length from print_time() when seconds > 99999
  drivers/rtc/rtc-vt8500.c: fix handling of data passed in struct rtc_time
  drivers/rtc/rtc-vt8500.c: correct handling of CR_24H bitfield
  rtc: add RTC driver for TPS6586x
  MAINTAINERS: fix drivers/staging/sm7xx/
  MAINTAINERS: remove include/linux/of_pwm.h
  MAINTAINERS: remove arch/*/lib/perf_event*.c
  MAINTAINERS: remove drivers/mmc/host/imxmmc.*
  MAINTAINERS: fix Documentation/mei/
  MAINTAINERS: remove arch/x86/platform/mrst/pmu.*
  MAINTAINERS: remove firmware/isci/
  MAINTAINERS: fix drivers/ieee802154/
  MAINTAINERS: fix .../plat-mxc/include/mach/imxfb.h
  MAINTAINERS: remove drivers/video/epson1355fb.c
  MAINTAINERS: fix drivers/media/usb/dvb-usb/cxusb*
  MAINTAINERS: adjust for UAPI
  MAINTAINERS: fix drivers/media/platform/atmel-isi.c
  MAINTAINERS: fix arch/arm/mach-at91/include/mach/at_hdmac.h
  MAINTAINERS: fix drivers/rtc/rtc-vt8500.c
  MAINTAINERS: remove arch/arm/plat-s5p/
  ...
parents de9ac5ce 35dac27c
...@@ -38,6 +38,7 @@ show up in /proc/sys/kernel: ...@@ -38,6 +38,7 @@ show up in /proc/sys/kernel:
- l2cr [ PPC only ] - l2cr [ PPC only ]
- modprobe ==> Documentation/debugging-modules.txt - modprobe ==> Documentation/debugging-modules.txt
- modules_disabled - modules_disabled
- msg_next_id [ sysv ipc ]
- msgmax - msgmax
- msgmnb - msgmnb
- msgmni - msgmni
...@@ -62,7 +63,9 @@ show up in /proc/sys/kernel: ...@@ -62,7 +63,9 @@ show up in /proc/sys/kernel:
- rtsig-max - rtsig-max
- rtsig-nr - rtsig-nr
- sem - sem
- sem_next_id [ sysv ipc ]
- sg-big-buff [ generic SCSI device (sg) ] - sg-big-buff [ generic SCSI device (sg) ]
- shm_next_id [ sysv ipc ]
- shm_rmid_forced - shm_rmid_forced
- shmall - shmall
- shmmax [ sysv ipc ] - shmmax [ sysv ipc ]
...@@ -320,6 +323,22 @@ to false. ...@@ -320,6 +323,22 @@ to false.
============================================================== ==============================================================
msg_next_id, sem_next_id, and shm_next_id:
These three toggles allows to specify desired id for next allocated IPC
object: message, semaphore or shared memory respectively.
By default they are equal to -1, which means generic allocation logic.
Possible values to set are in range {0..INT_MAX}.
Notes:
1) kernel doesn't guarantee, that new object will have desired id. So,
it's up to userspace, how to handle an object with "wrong" id.
2) Toggle with non-default value will be set back to -1 by kernel after
successful IPC object allocation.
==============================================================
nmi_watchdog: nmi_watchdog:
Enables/Disables the NMI watchdog on x86 systems. When the value is Enables/Disables the NMI watchdog on x86 systems. When the value is
...@@ -542,6 +561,19 @@ are doing anyway :) ...@@ -542,6 +561,19 @@ are doing anyway :)
============================================================== ==============================================================
shmall:
This parameter sets the total amount of shared memory pages that
can be used system wide. Hence, SHMALL should always be at least
ceil(shmmax/PAGE_SIZE).
If you are not sure what the default PAGE_SIZE is on your Linux
system, you can run the following command:
# getconf PAGE_SIZE
==============================================================
shmmax: shmmax:
This value can be used to query and set the run time limit This value can be used to query and set the run time limit
......
This diff is collapsed.
...@@ -352,6 +352,14 @@ config RTC_DRV_TWL4030 ...@@ -352,6 +352,14 @@ config RTC_DRV_TWL4030
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-twl. will be called rtc-twl.
config RTC_DRV_TPS6586X
tristate "TI TPS6586X RTC driver"
depends on MFD_TPS6586X
help
TI Power Managment IC TPS6586X supports RTC functionality
along with alarm. This driver supports the RTC driver for
the TPS6586X RTC module.
config RTC_DRV_TPS65910 config RTC_DRV_TPS65910
tristate "TI TPS65910 RTC driver" tristate "TI TPS65910 RTC driver"
depends on RTC_CLASS && MFD_TPS65910 depends on RTC_CLASS && MFD_TPS65910
......
...@@ -111,6 +111,7 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o ...@@ -111,6 +111,7 @@ obj-$(CONFIG_RTC_DRV_TEGRA) += rtc-tegra.o
obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o obj-$(CONFIG_RTC_DRV_TILE) += rtc-tile.o
obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl.o
obj-$(CONFIG_RTC_DRV_TPS6586X) += rtc-tps6586x.o
obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o obj-$(CONFIG_RTC_DRV_TPS65910) += rtc-tps65910.o
obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
......
...@@ -303,6 +303,12 @@ static struct rtc_class_ops tegra_rtc_ops = { ...@@ -303,6 +303,12 @@ static struct rtc_class_ops tegra_rtc_ops = {
.alarm_irq_enable = tegra_rtc_alarm_irq_enable, .alarm_irq_enable = tegra_rtc_alarm_irq_enable,
}; };
static const struct of_device_id tegra_rtc_dt_match[] = {
{ .compatible = "nvidia,tegra20-rtc", },
{}
};
MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match);
static int tegra_rtc_probe(struct platform_device *pdev) static int tegra_rtc_probe(struct platform_device *pdev)
{ {
struct tegra_rtc_info *info; struct tegra_rtc_info *info;
...@@ -440,6 +446,7 @@ static struct platform_driver tegra_rtc_driver = { ...@@ -440,6 +446,7 @@ static struct platform_driver tegra_rtc_driver = {
.driver = { .driver = {
.name = "tegra_rtc", .name = "tegra_rtc",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = tegra_rtc_dt_match,
}, },
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = tegra_rtc_suspend, .suspend = tegra_rtc_suspend,
......
/*
* rtc-tps6586x.c: RTC driver for TI PMIC TPS6586X
*
* Copyright (c) 2012, NVIDIA Corporation.
*
* Author: Laxman Dewangan <ldewangan@nvidia.com>
*
* 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 version 2.
*
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
* whether express or implied; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307, USA
*/
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mfd/tps6586x.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#define RTC_CTRL 0xc0
#define POR_RESET_N BIT(7)
#define OSC_SRC_SEL BIT(6)
#define RTC_ENABLE BIT(5) /* enables alarm */
#define RTC_BUF_ENABLE BIT(4) /* 32 KHz buffer enable */
#define PRE_BYPASS BIT(3) /* 0=1KHz or 1=32KHz updates */
#define CL_SEL_MASK (BIT(2)|BIT(1))
#define CL_SEL_POS 1
#define RTC_ALARM1_HI 0xc1
#define RTC_COUNT4 0xc6
/* start a PMU RTC access by reading the register prior to the RTC_COUNT4 */
#define RTC_COUNT4_DUMMYREAD 0xc5
/*only 14-bits width in second*/
#define ALM1_VALID_RANGE_IN_SEC 0x3FFF
#define TPS6586X_RTC_CL_SEL_1_5PF 0x0
#define TPS6586X_RTC_CL_SEL_6_5PF 0x1
#define TPS6586X_RTC_CL_SEL_7_5PF 0x2
#define TPS6586X_RTC_CL_SEL_12_5PF 0x3
struct tps6586x_rtc {
struct device *dev;
struct rtc_device *rtc;
int irq;
bool irq_en;
unsigned long long epoch_start;
};
static inline struct device *to_tps6586x_dev(struct device *dev)
{
return dev->parent;
}
static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long long ticks = 0;
unsigned long seconds;
u8 buff[6];
int ret;
int i;
ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD, sizeof(buff), buff);
if (ret < 0) {
dev_err(dev, "read counter failed with err %d\n", ret);
return ret;
}
for (i = 1; i < sizeof(buff); i++) {
ticks <<= 8;
ticks |= buff[i];
}
seconds = ticks >> 10;
seconds += rtc->epoch_start;
rtc_time_to_tm(seconds, tm);
return rtc_valid_tm(tm);
}
static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long long ticks;
unsigned long seconds;
u8 buff[5];
int ret;
rtc_tm_to_time(tm, &seconds);
if (seconds < rtc->epoch_start) {
dev_err(dev, "requested time unsupported\n");
return -EINVAL;
}
seconds -= rtc->epoch_start;
ticks = (unsigned long long)seconds << 10;
buff[0] = (ticks >> 32) & 0xff;
buff[1] = (ticks >> 24) & 0xff;
buff[2] = (ticks >> 16) & 0xff;
buff[3] = (ticks >> 8) & 0xff;
buff[4] = ticks & 0xff;
/* Disable RTC before changing time */
ret = tps6586x_clr_bits(tps_dev, RTC_CTRL, RTC_ENABLE);
if (ret < 0) {
dev_err(dev, "failed to clear RTC_ENABLE\n");
return ret;
}
ret = tps6586x_writes(tps_dev, RTC_COUNT4, sizeof(buff), buff);
if (ret < 0) {
dev_err(dev, "failed to program new time\n");
return ret;
}
/* Enable RTC */
ret = tps6586x_set_bits(tps_dev, RTC_CTRL, RTC_ENABLE);
if (ret < 0) {
dev_err(dev, "failed to set RTC_ENABLE\n");
return ret;
}
return 0;
}
static int tps6586x_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
if (enabled && !rtc->irq_en) {
enable_irq(rtc->irq);
rtc->irq_en = true;
} else if (!enabled && rtc->irq_en) {
disable_irq(rtc->irq);
rtc->irq_en = false;
}
return 0;
}
static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long seconds;
unsigned long ticks;
unsigned long rtc_current_time;
unsigned long long rticks = 0;
u8 buff[3];
u8 rbuff[6];
int ret;
int i;
rtc_tm_to_time(&alrm->time, &seconds);
if (alrm->enabled && (seconds < rtc->epoch_start)) {
dev_err(dev, "can't set alarm to requested time\n");
return -EINVAL;
}
ret = tps6586x_rtc_alarm_irq_enable(dev, alrm->enabled);
if (ret < 0) {
dev_err(dev, "can't set alarm irq, err %d\n", ret);
return ret;
}
seconds -= rtc->epoch_start;
ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD,
sizeof(rbuff), rbuff);
if (ret < 0) {
dev_err(dev, "read counter failed with err %d\n", ret);
return ret;
}
for (i = 1; i < sizeof(rbuff); i++) {
rticks <<= 8;
rticks |= rbuff[i];
}
rtc_current_time = rticks >> 10;
if ((seconds - rtc_current_time) > ALM1_VALID_RANGE_IN_SEC)
seconds = rtc_current_time - 1;
ticks = (unsigned long long)seconds << 10;
buff[0] = (ticks >> 16) & 0xff;
buff[1] = (ticks >> 8) & 0xff;
buff[2] = ticks & 0xff;
ret = tps6586x_writes(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff);
if (ret)
dev_err(dev, "programming alarm failed with err %d\n", ret);
return ret;
}
static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long ticks;
unsigned long seconds;
u8 buff[3];
int ret;
ret = tps6586x_reads(tps_dev, RTC_ALARM1_HI, sizeof(buff), buff);
if (ret) {
dev_err(dev, "read RTC_ALARM1_HI failed with err %d\n", ret);
return ret;
}
ticks = (buff[0] << 16) | (buff[1] << 8) | buff[2];
seconds = ticks >> 10;
seconds += rtc->epoch_start;
rtc_time_to_tm(seconds, &alrm->time);
return 0;
}
static const struct rtc_class_ops tps6586x_rtc_ops = {
.read_time = tps6586x_rtc_read_time,
.set_time = tps6586x_rtc_set_time,
.set_alarm = tps6586x_rtc_set_alarm,
.read_alarm = tps6586x_rtc_read_alarm,
.alarm_irq_enable = tps6586x_rtc_alarm_irq_enable,
};
static irqreturn_t tps6586x_rtc_irq(int irq, void *data)
{
struct tps6586x_rtc *rtc = data;
rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static int tps6586x_rtc_probe(struct platform_device *pdev)
{
struct device *tps_dev = to_tps6586x_dev(&pdev->dev);
struct tps6586x_rtc *rtc;
int ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
rtc->dev = &pdev->dev;
rtc->irq = platform_get_irq(pdev, 0);
/* Set epoch start as 00:00:00:01:01:2009 */
rtc->epoch_start = mktime(2009, 1, 1, 0, 0, 0);
/* 1 kHz tick mode, enable tick counting */
ret = tps6586x_update(tps_dev, RTC_CTRL,
RTC_ENABLE | OSC_SRC_SEL |
((TPS6586X_RTC_CL_SEL_1_5PF << CL_SEL_POS) & CL_SEL_MASK),
RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
if (ret < 0) {
dev_err(&pdev->dev, "unable to start counter\n");
return ret;
}
platform_set_drvdata(pdev, rtc);
rtc->rtc = rtc_device_register(dev_name(&pdev->dev), &pdev->dev,
&tps6586x_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc);
dev_err(&pdev->dev, "RTC device register: ret %d\n", ret);
goto fail_rtc_register;
}
ret = request_threaded_irq(rtc->irq, NULL, tps6586x_rtc_irq,
IRQF_ONESHOT | IRQF_EARLY_RESUME,
dev_name(&pdev->dev), rtc);
if (ret < 0) {
dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n",
rtc->irq, ret);
goto fail_req_irq;
}
disable_irq(rtc->irq);
device_set_wakeup_capable(&pdev->dev, 1);
return 0;
fail_req_irq:
rtc_device_unregister(rtc->rtc);
fail_rtc_register:
tps6586x_update(tps_dev, RTC_CTRL, 0,
RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
return ret;
};
static int tps6586x_rtc_remove(struct platform_device *pdev)
{
struct tps6586x_rtc *rtc = platform_get_drvdata(pdev);
struct device *tps_dev = to_tps6586x_dev(&pdev->dev);
tps6586x_update(tps_dev, RTC_CTRL, 0,
RTC_ENABLE | OSC_SRC_SEL | PRE_BYPASS | CL_SEL_MASK);
rtc_device_unregister(rtc->rtc);
free_irq(rtc->irq, rtc);
return 0;
}
#ifdef CONFIG_PM_SLEEP
static int tps6586x_rtc_suspend(struct device *dev)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
enable_irq_wake(rtc->irq);
return 0;
}
static int tps6586x_rtc_resume(struct device *dev)
{
struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
disable_irq_wake(rtc->irq);
return 0;
}
#endif
static const struct dev_pm_ops tps6586x_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(tps6586x_rtc_suspend, tps6586x_rtc_resume)
};
static struct platform_driver tps6586x_rtc_driver = {
.driver = {
.name = "tps6586x-rtc",
.owner = THIS_MODULE,
.pm = &tps6586x_pm_ops,
},
.probe = tps6586x_rtc_probe,
.remove = tps6586x_rtc_remove,
};
module_platform_driver(tps6586x_rtc_driver);
MODULE_ALIAS("platform:rtc-tps6586x");
MODULE_DESCRIPTION("TI TPS6586x RTC driver");
MODULE_AUTHOR("Laxman dewangan <ldewangan@nvidia.com>");
MODULE_LICENSE("GPL v2");
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
| ALARM_SEC_BIT) | ALARM_SEC_BIT)
#define VT8500_RTC_CR_ENABLE (1 << 0) /* Enable RTC */ #define VT8500_RTC_CR_ENABLE (1 << 0) /* Enable RTC */
#define VT8500_RTC_CR_24H (1 << 1) /* 24h time format */ #define VT8500_RTC_CR_12H (1 << 1) /* 12h time format */
#define VT8500_RTC_CR_SM_ENABLE (1 << 2) /* Enable periodic irqs */ #define VT8500_RTC_CR_SM_ENABLE (1 << 2) /* Enable periodic irqs */
#define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */
#define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */
...@@ -119,7 +119,7 @@ static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -119,7 +119,7 @@ static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S); tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S);
tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S); tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S);
tm->tm_mday = bcd2bin(date & DATE_DAY_MASK); tm->tm_mday = bcd2bin(date & DATE_DAY_MASK);
tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S); tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S) - 1;
tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S) tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S)
+ ((date >> DATE_CENTURY_S) & 1 ? 200 : 100); + ((date >> DATE_CENTURY_S) & 1 ? 200 : 100);
tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S; tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S;
...@@ -138,8 +138,9 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -138,8 +138,9 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm)
} }
writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S)
| (bin2bcd(tm->tm_mon) << DATE_MONTH_S) | (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S)
| (bin2bcd(tm->tm_mday)), | (bin2bcd(tm->tm_mday))
| ((tm->tm_year >= 200) << DATE_CENTURY_S),
vt8500_rtc->regbase + VT8500_RTC_DS); vt8500_rtc->regbase + VT8500_RTC_DS);
writel((bin2bcd(tm->tm_wday) << TIME_DOW_S) writel((bin2bcd(tm->tm_wday) << TIME_DOW_S)
| (bin2bcd(tm->tm_hour) << TIME_HOUR_S) | (bin2bcd(tm->tm_hour) << TIME_HOUR_S)
...@@ -247,7 +248,7 @@ static int vt8500_rtc_probe(struct platform_device *pdev) ...@@ -247,7 +248,7 @@ static int vt8500_rtc_probe(struct platform_device *pdev)
} }
/* Enable RTC and set it to 24-hour mode */ /* Enable RTC and set it to 24-hour mode */
writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H, writel(VT8500_RTC_CR_ENABLE,
vt8500_rtc->regbase + VT8500_RTC_CR); vt8500_rtc->regbase + VT8500_RTC_CR);
vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev,
......
...@@ -78,6 +78,14 @@ struct mmu_gather_batch { ...@@ -78,6 +78,14 @@ struct mmu_gather_batch {
#define MAX_GATHER_BATCH \ #define MAX_GATHER_BATCH \
((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *)) ((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *))
/*
* Limit the maximum number of mmu_gather batches to reduce a risk of soft
* lockups for non-preemptible kernels on huge machines when a lot of memory
* is zapped during unmapping.
* 10K pages freed at once should be safe even without a preemption point.
*/
#define MAX_GATHER_BATCH_COUNT (10000UL/MAX_GATHER_BATCH)
/* struct mmu_gather is an opaque type used by the mm code for passing around /* struct mmu_gather is an opaque type used by the mm code for passing around
* any data needed by arch specific code for tlb_remove_page. * any data needed by arch specific code for tlb_remove_page.
*/ */
...@@ -96,6 +104,7 @@ struct mmu_gather { ...@@ -96,6 +104,7 @@ struct mmu_gather {
struct mmu_gather_batch *active; struct mmu_gather_batch *active;
struct mmu_gather_batch local; struct mmu_gather_batch local;
struct page *__pages[MMU_GATHER_BUNDLE]; struct page *__pages[MMU_GATHER_BUNDLE];
unsigned int batch_count;
}; };
#define HAVE_GENERIC_MMU_GATHER #define HAVE_GENERIC_MMU_GATHER
......
...@@ -24,6 +24,7 @@ struct ipc_ids { ...@@ -24,6 +24,7 @@ struct ipc_ids {
unsigned short seq_max; unsigned short seq_max;
struct rw_semaphore rw_mutex; struct rw_semaphore rw_mutex;
struct idr ipcs_idr; struct idr ipcs_idr;
int next_id;
}; };
struct ipc_namespace { struct ipc_namespace {
......
...@@ -503,14 +503,6 @@ struct zone { ...@@ -503,14 +503,6 @@ struct zone {
* rarely used fields: * rarely used fields:
*/ */
const char *name; const char *name;
#ifdef CONFIG_MEMORY_ISOLATION
/*
* the number of MIGRATE_ISOLATE *pageblock*.
* We need this for free page counting. Look at zone_watermark_ok_safe.
* It's protected by zone->lock
*/
int nr_pageblock_isolate;
#endif
} ____cacheline_internodealigned_in_smp; } ____cacheline_internodealigned_in_smp;
typedef enum { typedef enum {
......
...@@ -34,7 +34,9 @@ struct msg_queue { ...@@ -34,7 +34,9 @@ struct msg_queue {
/* Helper routines for sys_msgsnd and sys_msgrcv */ /* Helper routines for sys_msgsnd and sys_msgrcv */
extern long do_msgsnd(int msqid, long mtype, void __user *mtext, extern long do_msgsnd(int msqid, long mtype, void __user *mtext,
size_t msgsz, int msgflg); size_t msgsz, int msgflg);
extern long do_msgrcv(int msqid, long *pmtype, void __user *mtext, extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
size_t msgsz, long msgtyp, int msgflg); int msgflg,
long (*msg_fill)(void __user *, struct msg_msg *,
size_t));
#endif /* _LINUX_MSG_H */ #endif /* _LINUX_MSG_H */
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
/* msgrcv options */ /* msgrcv options */
#define MSG_NOERROR 010000 /* no error if message is too big */ #define MSG_NOERROR 010000 /* no error if message is too big */
#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/ #define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/
#define MSG_COPY 040000 /* copy (not remove) all queue messages */
/* Obsolete, used only for backwards compatibility and libc5 compiles */ /* Obsolete, used only for backwards compatibility and libc5 compiles */
struct msqid_ds { struct msqid_ds {
......
...@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad) ...@@ -306,6 +306,20 @@ static long do_compat_semctl(int first, int second, int third, u32 pad)
return err; return err;
} }
long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
{
struct compat_msgbuf __user *msgp = dest;
size_t msgsz;
if (put_user(msg->m_type, &msgp->mtype))
return -EFAULT;
msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
if (store_msg(msgp->mtext, msg, msgsz))
return -EFAULT;
return msgsz;
}
#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
long compat_sys_semctl(int first, int second, int third, void __user *uptr) long compat_sys_semctl(int first, int second, int third, void __user *uptr)
{ {
...@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr) ...@@ -337,10 +351,6 @@ long compat_sys_msgsnd(int first, int second, int third, void __user *uptr)
long compat_sys_msgrcv(int first, int second, int msgtyp, int third, long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
int version, void __user *uptr) int version, void __user *uptr)
{ {
struct compat_msgbuf __user *up;
long type;
int err;
if (first < 0) if (first < 0)
return -EINVAL; return -EINVAL;
if (second < 0) if (second < 0)
...@@ -348,23 +358,15 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third, ...@@ -348,23 +358,15 @@ long compat_sys_msgrcv(int first, int second, int msgtyp, int third,
if (!version) { if (!version) {
struct compat_ipc_kludge ipck; struct compat_ipc_kludge ipck;
err = -EINVAL;
if (!uptr) if (!uptr)
goto out; return -EINVAL;
err = -EFAULT;
if (copy_from_user (&ipck, uptr, sizeof(ipck))) if (copy_from_user (&ipck, uptr, sizeof(ipck)))
goto out; return -EFAULT;
uptr = compat_ptr(ipck.msgp); uptr = compat_ptr(ipck.msgp);
msgtyp = ipck.msgtyp; msgtyp = ipck.msgtyp;
} }
up = uptr; return do_msgrcv(first, uptr, second, msgtyp, third,
err = do_msgrcv(first, &type, up->mtext, second, msgtyp, third); compat_do_msg_fill);
if (err < 0)
goto out;
if (put_user(type, &up->mtype))
err = -EFAULT;
out:
return err;
} }
#else #else
long compat_sys_semctl(int semid, int semnum, int cmd, int arg) long compat_sys_semctl(int semid, int semnum, int cmd, int arg)
...@@ -385,16 +387,8 @@ long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp, ...@@ -385,16 +387,8 @@ long compat_sys_msgsnd(int msqid, struct compat_msgbuf __user *msgp,
long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp, long compat_sys_msgrcv(int msqid, struct compat_msgbuf __user *msgp,
compat_ssize_t msgsz, long msgtyp, int msgflg) compat_ssize_t msgsz, long msgtyp, int msgflg)
{ {
long err, mtype; return do_msgrcv(msqid, msgp, (ssize_t)msgsz, msgtyp, msgflg,
compat_do_msg_fill);
err = do_msgrcv(msqid, &mtype, msgp->mtext, (ssize_t)msgsz, msgtyp, msgflg);
if (err < 0)
goto out;
if (put_user(mtype, &msgp->mtype))
err = -EFAULT;
out:
return err;
} }
#endif #endif
......
...@@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, ...@@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
static int zero; static int zero;
static int one = 1; static int one = 1;
#ifdef CONFIG_CHECKPOINT_RESTORE
static int int_max = INT_MAX;
#endif
static struct ctl_table ipc_kern_table[] = { static struct ctl_table ipc_kern_table[] = {
{ {
...@@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = { ...@@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = {
.extra1 = &zero, .extra1 = &zero,
.extra2 = &one, .extra2 = &one,
}, },
#ifdef CONFIG_CHECKPOINT_RESTORE
{
.procname = "sem_next_id",
.data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
.maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
.mode = 0644,
.proc_handler = proc_ipc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &int_max,
},
{
.procname = "msg_next_id",
.data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
.maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
.mode = 0644,
.proc_handler = proc_ipc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &int_max,
},
{
.procname = "shm_next_id",
.data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
.maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
.mode = 0644,
.proc_handler = proc_ipc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &int_max,
},
#endif
{} {}
}; };
......
...@@ -755,26 +755,91 @@ static inline int convert_mode(long *msgtyp, int msgflg) ...@@ -755,26 +755,91 @@ static inline int convert_mode(long *msgtyp, int msgflg)
return SEARCH_EQUAL; return SEARCH_EQUAL;
} }
long do_msgrcv(int msqid, long *pmtype, void __user *mtext, static long do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
size_t msgsz, long msgtyp, int msgflg) {
struct msgbuf __user *msgp = dest;
size_t msgsz;
if (put_user(msg->m_type, &msgp->mtype))
return -EFAULT;
msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
if (store_msg(msgp->mtext, msg, msgsz))
return -EFAULT;
return msgsz;
}
#ifdef CONFIG_CHECKPOINT_RESTORE
/*
* This function creates new kernel message structure, large enough to store
* bufsz message bytes.
*/
static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
int msgflg, long *msgtyp,
unsigned long *copy_number)
{
struct msg_msg *copy;
*copy_number = *msgtyp;
*msgtyp = 0;
/*
* Create dummy message to copy real message to.
*/
copy = load_msg(buf, bufsz);
if (!IS_ERR(copy))
copy->m_ts = bufsz;
return copy;
}
static inline void free_copy(struct msg_msg *copy)
{
if (copy)
free_msg(copy);
}
#else
static inline struct msg_msg *prepare_copy(void __user *buf, size_t bufsz,
int msgflg, long *msgtyp,
unsigned long *copy_number)
{
return ERR_PTR(-ENOSYS);
}
static inline void free_copy(struct msg_msg *copy)
{
}
#endif
long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
int msgflg,
long (*msg_handler)(void __user *, struct msg_msg *, size_t))
{ {
struct msg_queue *msq; struct msg_queue *msq;
struct msg_msg *msg; struct msg_msg *msg;
int mode; int mode;
struct ipc_namespace *ns; struct ipc_namespace *ns;
struct msg_msg *copy = NULL;
unsigned long copy_number = 0;
if (msqid < 0 || (long) msgsz < 0) if (msqid < 0 || (long) bufsz < 0)
return -EINVAL; return -EINVAL;
if (msgflg & MSG_COPY) {
copy = prepare_copy(buf, bufsz, msgflg, &msgtyp, &copy_number);
if (IS_ERR(copy))
return PTR_ERR(copy);
}
mode = convert_mode(&msgtyp, msgflg); mode = convert_mode(&msgtyp, msgflg);
ns = current->nsproxy->ipc_ns; ns = current->nsproxy->ipc_ns;
msq = msg_lock_check(ns, msqid); msq = msg_lock_check(ns, msqid);
if (IS_ERR(msq)) if (IS_ERR(msq)) {
free_copy(copy);
return PTR_ERR(msq); return PTR_ERR(msq);
}
for (;;) { for (;;) {
struct msg_receiver msr_d; struct msg_receiver msr_d;
struct list_head *tmp; struct list_head *tmp;
long msg_counter = 0;
msg = ERR_PTR(-EACCES); msg = ERR_PTR(-EACCES);
if (ipcperms(ns, &msq->q_perm, S_IRUGO)) if (ipcperms(ns, &msq->q_perm, S_IRUGO))
...@@ -793,12 +858,21 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, ...@@ -793,12 +858,21 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
msg = walk_msg; msg = walk_msg;
if (mode == SEARCH_LESSEQUAL && if (mode == SEARCH_LESSEQUAL &&
walk_msg->m_type != 1) { walk_msg->m_type != 1) {
msg = walk_msg;
msgtyp = walk_msg->m_type - 1; msgtyp = walk_msg->m_type - 1;
} else { } else if (msgflg & MSG_COPY) {
msg = walk_msg; if (copy_number == msg_counter) {
/*
* Found requested message.
* Copy it.
*/
msg = copy_msg(msg, copy);
if (IS_ERR(msg))
goto out_unlock;
break; break;
} }
} else
break;
msg_counter++;
} }
tmp = tmp->next; tmp = tmp->next;
} }
...@@ -807,10 +881,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, ...@@ -807,10 +881,16 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
* Found a suitable message. * Found a suitable message.
* Unlink it from the queue. * Unlink it from the queue.
*/ */
if ((msgsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) { if ((bufsz < msg->m_ts) && !(msgflg & MSG_NOERROR)) {
msg = ERR_PTR(-E2BIG); msg = ERR_PTR(-E2BIG);
goto out_unlock; goto out_unlock;
} }
/*
* If we are copying, then do not unlink message and do
* not update queue parameters.
*/
if (msgflg & MSG_COPY)
goto out_unlock;
list_del(&msg->m_list); list_del(&msg->m_list);
msq->q_qnum--; msq->q_qnum--;
msq->q_rtime = get_seconds(); msq->q_rtime = get_seconds();
...@@ -834,7 +914,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, ...@@ -834,7 +914,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
if (msgflg & MSG_NOERROR) if (msgflg & MSG_NOERROR)
msr_d.r_maxsize = INT_MAX; msr_d.r_maxsize = INT_MAX;
else else
msr_d.r_maxsize = msgsz; msr_d.r_maxsize = bufsz;
msr_d.r_msg = ERR_PTR(-EAGAIN); msr_d.r_msg = ERR_PTR(-EAGAIN);
current->state = TASK_INTERRUPTIBLE; current->state = TASK_INTERRUPTIBLE;
msg_unlock(msq); msg_unlock(msq);
...@@ -894,32 +974,21 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext, ...@@ -894,32 +974,21 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,
break; break;
} }
} }
if (IS_ERR(msg)) if (IS_ERR(msg)) {
free_copy(copy);
return PTR_ERR(msg); return PTR_ERR(msg);
}
msgsz = (msgsz > msg->m_ts) ? msg->m_ts : msgsz; bufsz = msg_handler(buf, msg, bufsz);
*pmtype = msg->m_type;
if (store_msg(mtext, msg, msgsz))
msgsz = -EFAULT;
free_msg(msg); free_msg(msg);
return msgsz; return bufsz;
} }
SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
long, msgtyp, int, msgflg) long, msgtyp, int, msgflg)
{ {
long err, mtype; return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
err = do_msgrcv(msqid, &mtype, msgp->mtext, msgsz, msgtyp, msgflg);
if (err < 0)
goto out;
if (put_user(mtype, &msgp->mtype))
err = -EFAULT;
out:
return err;
} }
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
......
...@@ -102,7 +102,50 @@ struct msg_msg *load_msg(const void __user *src, int len) ...@@ -102,7 +102,50 @@ struct msg_msg *load_msg(const void __user *src, int len)
free_msg(msg); free_msg(msg);
return ERR_PTR(err); return ERR_PTR(err);
} }
#ifdef CONFIG_CHECKPOINT_RESTORE
struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
{
struct msg_msgseg *dst_pseg, *src_pseg;
int len = src->m_ts;
int alen;
BUG_ON(dst == NULL);
if (src->m_ts > dst->m_ts)
return ERR_PTR(-EINVAL);
alen = len;
if (alen > DATALEN_MSG)
alen = DATALEN_MSG;
dst->next = NULL;
dst->security = NULL;
memcpy(dst + 1, src + 1, alen);
len -= alen;
dst_pseg = dst->next;
src_pseg = src->next;
while (len > 0) {
alen = len;
if (alen > DATALEN_SEG)
alen = DATALEN_SEG;
memcpy(dst_pseg + 1, src_pseg + 1, alen);
dst_pseg = dst_pseg->next;
len -= alen;
src_pseg = src_pseg->next;
}
dst->m_type = src->m_type;
dst->m_ts = src->m_ts;
return dst;
}
#else
struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
{
return ERR_PTR(-ENOSYS);
}
#endif
int store_msg(void __user *dest, struct msg_msg *msg, int len) int store_msg(void __user *dest, struct msg_msg *msg, int len)
{ {
int alen; int alen;
......
...@@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids) ...@@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids)
ids->in_use = 0; ids->in_use = 0;
ids->seq = 0; ids->seq = 0;
ids->next_id = -1;
{ {
int seq_limit = INT_MAX/SEQ_MULTIPLIER; int seq_limit = INT_MAX/SEQ_MULTIPLIER;
if (seq_limit > USHRT_MAX) if (seq_limit > USHRT_MAX)
...@@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) ...@@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
kuid_t euid; kuid_t euid;
kgid_t egid; kgid_t egid;
int id, err; int id, err;
int next_id = ids->next_id;
if (size > IPCMNI) if (size > IPCMNI)
size = IPCMNI; size = IPCMNI;
...@@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) ...@@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
rcu_read_lock(); rcu_read_lock();
spin_lock(&new->lock); spin_lock(&new->lock);
err = idr_get_new(&ids->ipcs_idr, new, &id); err = idr_get_new_above(&ids->ipcs_idr, new,
(next_id < 0) ? 0 : ipcid_to_idx(next_id), &id);
if (err) { if (err) {
spin_unlock(&new->lock); spin_unlock(&new->lock);
rcu_read_unlock(); rcu_read_unlock();
...@@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) ...@@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
new->cuid = new->uid = euid; new->cuid = new->uid = euid;
new->gid = new->cgid = egid; new->gid = new->cgid = egid;
if (next_id < 0) {
new->seq = ids->seq++; new->seq = ids->seq++;
if(ids->seq > ids->seq_max) if (ids->seq > ids->seq_max)
ids->seq = 0; ids->seq = 0;
} else {
new->seq = ipcid_to_seqx(next_id);
ids->next_id = -1;
}
new->id = ipc_buildid(id, new->seq); new->id = ipc_buildid(id, new->seq);
return id; return id;
......
...@@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header, ...@@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
#define IPC_SHM_IDS 2 #define IPC_SHM_IDS 2
#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
/* must be called with ids->rw_mutex acquired for writing */ /* must be called with ids->rw_mutex acquired for writing */
int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
...@@ -139,6 +140,7 @@ int ipc_parse_version (int *cmd); ...@@ -139,6 +140,7 @@ int ipc_parse_version (int *cmd);
extern void free_msg(struct msg_msg *msg); extern void free_msg(struct msg_msg *msg);
extern struct msg_msg *load_msg(const void __user *src, int len); extern struct msg_msg *load_msg(const void __user *src, int len);
extern struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst);
extern int store_msg(void __user *dest, struct msg_msg *msg, int len); extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
extern void recompute_msgmni(struct ipc_namespace *); extern void recompute_msgmni(struct ipc_namespace *);
......
...@@ -870,10 +870,11 @@ static size_t print_time(u64 ts, char *buf) ...@@ -870,10 +870,11 @@ static size_t print_time(u64 ts, char *buf)
if (!printk_time) if (!printk_time)
return 0; return 0;
rem_nsec = do_div(ts, 1000000000);
if (!buf) if (!buf)
return 15; return snprintf(NULL, 0, "[%5lu.000000] ", (unsigned long)ts);
rem_nsec = do_div(ts, 1000000000);
return sprintf(buf, "[%5lu.%06lu] ", return sprintf(buf, "[%5lu.%06lu] ",
(unsigned long)ts, rem_nsec / 1000); (unsigned long)ts, rem_nsec / 1000);
} }
......
...@@ -184,10 +184,14 @@ static int tlb_next_batch(struct mmu_gather *tlb) ...@@ -184,10 +184,14 @@ static int tlb_next_batch(struct mmu_gather *tlb)
return 1; return 1;
} }
if (tlb->batch_count == MAX_GATHER_BATCH_COUNT)
return 0;
batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
if (!batch) if (!batch)
return 0; return 0;
tlb->batch_count++;
batch->next = NULL; batch->next = NULL;
batch->nr = 0; batch->nr = 0;
batch->max = MAX_GATHER_BATCH; batch->max = MAX_GATHER_BATCH;
...@@ -216,6 +220,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm) ...@@ -216,6 +220,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)
tlb->local.nr = 0; tlb->local.nr = 0;
tlb->local.max = ARRAY_SIZE(tlb->__pages); tlb->local.max = ARRAY_SIZE(tlb->__pages);
tlb->active = &tlb->local; tlb->active = &tlb->local;
tlb->batch_count = 0;
#ifdef CONFIG_HAVE_RCU_TABLE_FREE #ifdef CONFIG_HAVE_RCU_TABLE_FREE
tlb->batch = NULL; tlb->batch = NULL;
......
...@@ -221,11 +221,6 @@ EXPORT_SYMBOL(nr_online_nodes); ...@@ -221,11 +221,6 @@ EXPORT_SYMBOL(nr_online_nodes);
int page_group_by_mobility_disabled __read_mostly; int page_group_by_mobility_disabled __read_mostly;
/*
* NOTE:
* Don't use set_pageblock_migratetype(page, MIGRATE_ISOLATE) directly.
* Instead, use {un}set_pageblock_isolate.
*/
void set_pageblock_migratetype(struct page *page, int migratetype) void set_pageblock_migratetype(struct page *page, int migratetype)
{ {
...@@ -1655,20 +1650,6 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark, ...@@ -1655,20 +1650,6 @@ static bool __zone_watermark_ok(struct zone *z, int order, unsigned long mark,
return true; return true;
} }
#ifdef CONFIG_MEMORY_ISOLATION
static inline unsigned long nr_zone_isolate_freepages(struct zone *zone)
{
if (unlikely(zone->nr_pageblock_isolate))
return zone->nr_pageblock_isolate * pageblock_nr_pages;
return 0;
}
#else
static inline unsigned long nr_zone_isolate_freepages(struct zone *zone)
{
return 0;
}
#endif
bool zone_watermark_ok(struct zone *z, int order, unsigned long mark, bool zone_watermark_ok(struct zone *z, int order, unsigned long mark,
int classzone_idx, int alloc_flags) int classzone_idx, int alloc_flags)
{ {
...@@ -1684,14 +1665,6 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark, ...@@ -1684,14 +1665,6 @@ bool zone_watermark_ok_safe(struct zone *z, int order, unsigned long mark,
if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark) if (z->percpu_drift_mark && free_pages < z->percpu_drift_mark)
free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES); free_pages = zone_page_state_snapshot(z, NR_FREE_PAGES);
/*
* If the zone has MIGRATE_ISOLATE type free pages, we should consider
* it. nr_zone_isolate_freepages is never accurate so kswapd might not
* sleep although it could do so. But this is more desirable for memory
* hotplug than sleeping which can cause a livelock in the direct
* reclaim path.
*/
free_pages -= nr_zone_isolate_freepages(z);
return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags, return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags,
free_pages); free_pages);
} }
......
...@@ -8,28 +8,6 @@ ...@@ -8,28 +8,6 @@
#include <linux/memory.h> #include <linux/memory.h>
#include "internal.h" #include "internal.h"
/* called while holding zone->lock */
static void set_pageblock_isolate(struct page *page)
{
if (get_pageblock_migratetype(page) == MIGRATE_ISOLATE)
return;
set_pageblock_migratetype(page, MIGRATE_ISOLATE);
page_zone(page)->nr_pageblock_isolate++;
}
/* called while holding zone->lock */
static void restore_pageblock_isolate(struct page *page, int migratetype)
{
struct zone *zone = page_zone(page);
if (WARN_ON(get_pageblock_migratetype(page) != MIGRATE_ISOLATE))
return;
BUG_ON(zone->nr_pageblock_isolate <= 0);
set_pageblock_migratetype(page, migratetype);
zone->nr_pageblock_isolate--;
}
int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages) int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages)
{ {
struct zone *zone; struct zone *zone;
...@@ -80,7 +58,7 @@ int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages) ...@@ -80,7 +58,7 @@ int set_migratetype_isolate(struct page *page, bool skip_hwpoisoned_pages)
unsigned long nr_pages; unsigned long nr_pages;
int migratetype = get_pageblock_migratetype(page); int migratetype = get_pageblock_migratetype(page);
set_pageblock_isolate(page); set_pageblock_migratetype(page, MIGRATE_ISOLATE);
nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE); nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE);
__mod_zone_freepage_state(zone, -nr_pages, migratetype); __mod_zone_freepage_state(zone, -nr_pages, migratetype);
...@@ -103,7 +81,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype) ...@@ -103,7 +81,7 @@ void unset_migratetype_isolate(struct page *page, unsigned migratetype)
goto out; goto out;
nr_pages = move_freepages_block(zone, page, migratetype); nr_pages = move_freepages_block(zone, page, migratetype);
__mod_zone_freepage_state(zone, nr_pages, migratetype); __mod_zone_freepage_state(zone, nr_pages, migratetype);
restore_pageblock_isolate(page, migratetype); set_pageblock_migratetype(page, migratetype);
out: out:
spin_unlock_irqrestore(&zone->lock, flags); spin_unlock_irqrestore(&zone->lock, flags);
} }
......
uname_M := $(shell uname -m 2>/dev/null || echo not)
ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/i386/)
ifeq ($(ARCH),i386)
ARCH := X86
CFLAGS := -DCONFIG_X86_32 -D__i386__
endif
ifeq ($(ARCH),x86_64)
ARCH := X86
CFLAGS := -DCONFIG_X86_64 -D__x86_64__
endif
CFLAGS += -I../../../../usr/include/
all:
ifeq ($(ARCH),X86)
gcc $(CFLAGS) msgque.c -o msgque_test
else
echo "Not an x86 target, can't build msgque selftest"
endif
run_tests: all
./msgque_test
clean:
rm -fr ./msgque_test
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <linux/msg.h>
#include <fcntl.h>
#define MAX_MSG_SIZE 32
struct msg1 {
int msize;
long mtype;
char mtext[MAX_MSG_SIZE];
};
#define TEST_STRING "Test sysv5 msg"
#define MSG_TYPE 1
#define ANOTHER_TEST_STRING "Yet another test sysv5 msg"
#define ANOTHER_MSG_TYPE 26538
struct msgque_data {
key_t key;
int msq_id;
int qbytes;
int qnum;
int mode;
struct msg1 *messages;
};
int restore_queue(struct msgque_data *msgque)
{
int fd, ret, id, i;
char buf[32];
fd = open("/proc/sys/kernel/msg_next_id", O_WRONLY);
if (fd == -1) {
printf("Failed to open /proc/sys/kernel/msg_next_id\n");
return -errno;
}
sprintf(buf, "%d", msgque->msq_id);
ret = write(fd, buf, strlen(buf));
if (ret != strlen(buf)) {
printf("Failed to write to /proc/sys/kernel/msg_next_id\n");
return -errno;
}
id = msgget(msgque->key, msgque->mode | IPC_CREAT | IPC_EXCL);
if (id == -1) {
printf("Failed to create queue\n");
return -errno;
}
if (id != msgque->msq_id) {
printf("Restored queue has wrong id (%d instead of %d)\n",
id, msgque->msq_id);
ret = -EFAULT;
goto destroy;
}
for (i = 0; i < msgque->qnum; i++) {
if (msgsnd(msgque->msq_id, &msgque->messages[i].mtype,
msgque->messages[i].msize, IPC_NOWAIT) != 0) {
printf("msgsnd failed (%m)\n");
ret = -errno;
goto destroy;
};
}
return 0;
destroy:
if (msgctl(id, IPC_RMID, 0))
printf("Failed to destroy queue: %d\n", -errno);
return ret;
}
int check_and_destroy_queue(struct msgque_data *msgque)
{
struct msg1 message;
int cnt = 0, ret;
while (1) {
ret = msgrcv(msgque->msq_id, &message.mtype, MAX_MSG_SIZE,
0, IPC_NOWAIT);
if (ret < 0) {
if (errno == ENOMSG)
break;
printf("Failed to read IPC message: %m\n");
ret = -errno;
goto err;
}
if (ret != msgque->messages[cnt].msize) {
printf("Wrong message size: %d (expected %d)\n", ret,
msgque->messages[cnt].msize);
ret = -EINVAL;
goto err;
}
if (message.mtype != msgque->messages[cnt].mtype) {
printf("Wrong message type\n");
ret = -EINVAL;
goto err;
}
if (memcmp(message.mtext, msgque->messages[cnt].mtext, ret)) {
printf("Wrong message content\n");
ret = -EINVAL;
goto err;
}
cnt++;
}
if (cnt != msgque->qnum) {
printf("Wrong message number\n");
ret = -EINVAL;
goto err;
}
ret = 0;
err:
if (msgctl(msgque->msq_id, IPC_RMID, 0)) {
printf("Failed to destroy queue: %d\n", -errno);
return -errno;
}
return ret;
}
int dump_queue(struct msgque_data *msgque)
{
struct msqid64_ds ds;
int kern_id;
int i, ret;
for (kern_id = 0; kern_id < 256; kern_id++) {
ret = msgctl(kern_id, MSG_STAT, &ds);
if (ret < 0) {
if (errno == -EINVAL)
continue;
printf("Failed to get stats for IPC queue with id %d\n",
kern_id);
return -errno;
}
if (ret == msgque->msq_id)
break;
}
msgque->messages = malloc(sizeof(struct msg1) * ds.msg_qnum);
if (msgque->messages == NULL) {
printf("Failed to get stats for IPC queue\n");
return -ENOMEM;
}
msgque->qnum = ds.msg_qnum;
msgque->mode = ds.msg_perm.mode;
msgque->qbytes = ds.msg_qbytes;
for (i = 0; i < msgque->qnum; i++) {
ret = msgrcv(msgque->msq_id, &msgque->messages[i].mtype,
MAX_MSG_SIZE, i, IPC_NOWAIT | MSG_COPY);
if (ret < 0) {
printf("Failed to copy IPC message: %m (%d)\n", errno);
return -errno;
}
msgque->messages[i].msize = ret;
}
return 0;
}
int fill_msgque(struct msgque_data *msgque)
{
struct msg1 msgbuf;
msgbuf.mtype = MSG_TYPE;
memcpy(msgbuf.mtext, TEST_STRING, sizeof(TEST_STRING));
if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(TEST_STRING),
IPC_NOWAIT) != 0) {
printf("First message send failed (%m)\n");
return -errno;
};
msgbuf.mtype = ANOTHER_MSG_TYPE;
memcpy(msgbuf.mtext, ANOTHER_TEST_STRING, sizeof(ANOTHER_TEST_STRING));
if (msgsnd(msgque->msq_id, &msgbuf.mtype, sizeof(ANOTHER_TEST_STRING),
IPC_NOWAIT) != 0) {
printf("Second message send failed (%m)\n");
return -errno;
};
return 0;
}
int main(int argc, char **argv)
{
int msg, pid, err;
struct msgque_data msgque;
msgque.key = ftok(argv[0], 822155650);
if (msgque.key == -1) {
printf("Can't make key\n");
return -errno;
}
msgque.msq_id = msgget(msgque.key, IPC_CREAT | IPC_EXCL | 0666);
if (msgque.msq_id == -1) {
printf("Can't create queue\n");
goto err_out;
}
err = fill_msgque(&msgque);
if (err) {
printf("Failed to fill queue\n");
goto err_destroy;
}
err = dump_queue(&msgque);
if (err) {
printf("Failed to dump queue\n");
goto err_destroy;
}
err = check_and_destroy_queue(&msgque);
if (err) {
printf("Failed to check and destroy queue\n");
goto err_out;
}
err = restore_queue(&msgque);
if (err) {
printf("Failed to restore queue\n");
goto err_destroy;
}
err = check_and_destroy_queue(&msgque);
if (err) {
printf("Failed to test queue\n");
goto err_out;
}
return 0;
err_destroy:
if (msgctl(msgque.msq_id, IPC_RMID, 0)) {
printf("Failed to destroy queue: %d\n", -errno);
return -errno;
}
err_out:
return err;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment