Commit 388c2896 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'staging-3.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging

Pull staging driver fixes from Greg Kroah-Hartman:
 "Here are some staging tree driver fixes for 3.10-rc2

  The drivers/iio/ changes are here as they are still tied into
  drivers/staging/iio/.

  Nothing major, just a number of small bugfixes, and a larger
  documentation update for the ramster code."

* tag 'staging-3.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (28 commits)
  staging: dwc2: remove compile warning for USB_DWC2_TRACK_MISSED_SOFS
  iio: exynos_adc: fix wrong structure extration in suspend and resume
  iio:common:st: added disable function after read info raw data
  iio: dac: Fix build error when CONFIG_SPI_MASTER=y && CONFIG_I2C=m
  staging:iio:light:tsl2x7x: fix the error handling in tsl2x7x_probe()
  staging/iio/mxs-lradc: fix preenable for multiple buffers
  staging: imx-drm: imx-tve: Check the return value of 'regulator_enable()'
  staging: video: imx: Select VIDEOMODE_HELPERS for parallel display
  staging: ramster: add how-to document
  staging: dwc2: Fix dma-enabled platform devices using a default dma_mask
  staging: vt6656: [bug] Fix missing spin lock in iwctl_siwpower.
  staging: Swap zram and zsmalloc in Kconfig
  staging: android: logger: use kuid_t instead of uid_t
  staging: zcache: Fix incorrect module_param_array types
  staging/solo6x10: depend on CONFIG_FONTS
  staging/drm: imx: add missing dependencies
  staging: ste_rmi4: Suppress 'ignoring return value of ‘regulator_enable()' warning
  staging: sep: fix driver build and kconfig
  staging: nvec: cleanup childs on remove
  staging: nvec: implement unregistering of notifiers
  ...
parents c7153d06 0797c3a3
...@@ -390,8 +390,8 @@ static int exynos_adc_remove(struct platform_device *pdev) ...@@ -390,8 +390,8 @@ static int exynos_adc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int exynos_adc_suspend(struct device *dev) static int exynos_adc_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct exynos_adc *info = platform_get_drvdata(pdev); struct exynos_adc *info = iio_priv(indio_dev);
u32 con; u32 con;
if (info->version == ADC_V2) { if (info->version == ADC_V2) {
...@@ -413,8 +413,8 @@ static int exynos_adc_suspend(struct device *dev) ...@@ -413,8 +413,8 @@ static int exynos_adc_suspend(struct device *dev)
static int exynos_adc_resume(struct device *dev) static int exynos_adc_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct exynos_adc *info = platform_get_drvdata(pdev); struct exynos_adc *info = iio_priv(indio_dev);
int ret; int ret;
ret = regulator_enable(info->vdd); ret = regulator_enable(info->vdd);
......
...@@ -312,6 +312,8 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev, ...@@ -312,6 +312,8 @@ int st_sensors_read_info_raw(struct iio_dev *indio_dev,
goto read_error; goto read_error;
*val = *val >> ch->scan_type.shift; *val = *val >> ch->scan_type.shift;
err = st_sensors_set_enable(indio_dev, false);
} }
mutex_unlock(&indio_dev->mlock); mutex_unlock(&indio_dev->mlock);
......
...@@ -5,7 +5,7 @@ menu "Digital to analog converters" ...@@ -5,7 +5,7 @@ menu "Digital to analog converters"
config AD5064 config AD5064
tristate "Analog Devices AD5064 and similar multi-channel DAC driver" tristate "Analog Devices AD5064 and similar multi-channel DAC driver"
depends on (SPI_MASTER || I2C) depends on (SPI_MASTER && I2C!=m) || I2C
help help
Say yes here to build support for Analog Devices AD5024, AD5025, AD5044, Say yes here to build support for Analog Devices AD5024, AD5025, AD5044,
AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668, AD5045, AD5064, AD5064-1, AD5065, AD5628, AD5629R, AD5648, AD5666, AD5668,
...@@ -27,7 +27,7 @@ config AD5360 ...@@ -27,7 +27,7 @@ config AD5360
config AD5380 config AD5380
tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver" tristate "Analog Devices AD5380/81/82/83/84/90/91/92 DAC driver"
depends on (SPI_MASTER || I2C) depends on (SPI_MASTER && I2C!=m) || I2C
select REGMAP_I2C if I2C select REGMAP_I2C if I2C
select REGMAP_SPI if SPI_MASTER select REGMAP_SPI if SPI_MASTER
help help
...@@ -57,7 +57,7 @@ config AD5624R_SPI ...@@ -57,7 +57,7 @@ config AD5624R_SPI
config AD5446 config AD5446
tristate "Analog Devices AD5446 and similar single channel DACs driver" tristate "Analog Devices AD5446 and similar single channel DACs driver"
depends on (SPI_MASTER || I2C) depends on (SPI_MASTER && I2C!=m) || I2C
help help
Say yes here to build support for Analog Devices AD5300, AD5301, AD5310, Say yes here to build support for Analog Devices AD5300, AD5301, AD5310,
AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453, AD5311, AD5320, AD5321, AD5444, AD5446, AD5450, AD5451, AD5452, AD5453,
......
...@@ -72,10 +72,10 @@ source "drivers/staging/sep/Kconfig" ...@@ -72,10 +72,10 @@ source "drivers/staging/sep/Kconfig"
source "drivers/staging/iio/Kconfig" source "drivers/staging/iio/Kconfig"
source "drivers/staging/zram/Kconfig"
source "drivers/staging/zsmalloc/Kconfig" source "drivers/staging/zsmalloc/Kconfig"
source "drivers/staging/zram/Kconfig"
source "drivers/staging/wlags49_h2/Kconfig" source "drivers/staging/wlags49_h2/Kconfig"
source "drivers/staging/wlags49_h25/Kconfig" source "drivers/staging/wlags49_h25/Kconfig"
......
...@@ -242,7 +242,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log, ...@@ -242,7 +242,7 @@ static ssize_t do_read_log_to_user(struct logger_log *log,
* 'log->buffer' which contains the first entry readable by 'euid' * 'log->buffer' which contains the first entry readable by 'euid'
*/ */
static size_t get_next_entry_by_uid(struct logger_log *log, static size_t get_next_entry_by_uid(struct logger_log *log,
size_t off, uid_t euid) size_t off, kuid_t euid)
{ {
while (off != log->w_off) { while (off != log->w_off) {
struct logger_entry *entry; struct logger_entry *entry;
...@@ -251,7 +251,7 @@ static size_t get_next_entry_by_uid(struct logger_log *log, ...@@ -251,7 +251,7 @@ static size_t get_next_entry_by_uid(struct logger_log *log,
entry = get_entry_header(log, off, &scratch); entry = get_entry_header(log, off, &scratch);
if (entry->euid == euid) if (uid_eq(entry->euid, euid))
return off; return off;
next_len = sizeof(struct logger_entry) + entry->len; next_len = sizeof(struct logger_entry) + entry->len;
......
...@@ -66,7 +66,7 @@ struct logger_entry { ...@@ -66,7 +66,7 @@ struct logger_entry {
__s32 tid; __s32 tid;
__s32 sec; __s32 sec;
__s32 nsec; __s32 nsec;
uid_t euid; kuid_t euid;
char msg[0]; char msg[0];
}; };
......
...@@ -981,6 +981,7 @@ config COMEDI_ME_DAQ ...@@ -981,6 +981,7 @@ config COMEDI_ME_DAQ
config COMEDI_NI_6527 config COMEDI_NI_6527
tristate "NI 6527 support" tristate "NI 6527 support"
depends on HAS_DMA
select COMEDI_MITE select COMEDI_MITE
---help--- ---help---
Enable support for the National Instruments 6527 PCI card Enable support for the National Instruments 6527 PCI card
...@@ -990,6 +991,7 @@ config COMEDI_NI_6527 ...@@ -990,6 +991,7 @@ config COMEDI_NI_6527
config COMEDI_NI_65XX config COMEDI_NI_65XX
tristate "NI 65xx static dio PCI card support" tristate "NI 65xx static dio PCI card support"
depends on HAS_DMA
select COMEDI_MITE select COMEDI_MITE
---help--- ---help---
Enable support for National Instruments 65xx static dio boards. Enable support for National Instruments 65xx static dio boards.
...@@ -1003,6 +1005,7 @@ config COMEDI_NI_65XX ...@@ -1003,6 +1005,7 @@ config COMEDI_NI_65XX
config COMEDI_NI_660X config COMEDI_NI_660X
tristate "NI 660x counter/timer PCI card support" tristate "NI 660x counter/timer PCI card support"
depends on HAS_DMA
select COMEDI_NI_TIOCMD select COMEDI_NI_TIOCMD
---help--- ---help---
Enable support for National Instruments PCI-6601 (ni_660x), PCI-6602, Enable support for National Instruments PCI-6601 (ni_660x), PCI-6602,
...@@ -1013,6 +1016,7 @@ config COMEDI_NI_660X ...@@ -1013,6 +1016,7 @@ config COMEDI_NI_660X
config COMEDI_NI_670X config COMEDI_NI_670X
tristate "NI 670x PCI card support" tristate "NI 670x PCI card support"
depends on HAS_DMA
select COMEDI_MITE select COMEDI_MITE
---help--- ---help---
Enable support for National Instruments PCI-6703 and PCI-6704 Enable support for National Instruments PCI-6703 and PCI-6704
...@@ -1022,6 +1026,7 @@ config COMEDI_NI_670X ...@@ -1022,6 +1026,7 @@ config COMEDI_NI_670X
config COMEDI_NI_LABPC_PCI config COMEDI_NI_LABPC_PCI
tristate "NI Lab-PC PCI-1200 support" tristate "NI Lab-PC PCI-1200 support"
depends on HAS_DMA
select COMEDI_NI_LABPC select COMEDI_NI_LABPC
select COMEDI_MITE select COMEDI_MITE
---help--- ---help---
...@@ -1032,6 +1037,7 @@ config COMEDI_NI_LABPC_PCI ...@@ -1032,6 +1037,7 @@ config COMEDI_NI_LABPC_PCI
config COMEDI_NI_PCIDIO config COMEDI_NI_PCIDIO
tristate "NI PCI-DIO32HS, PCI-6533, PCI-6534 support" tristate "NI PCI-DIO32HS, PCI-6533, PCI-6534 support"
depends on HAS_DMA
select COMEDI_MITE select COMEDI_MITE
select COMEDI_8255 select COMEDI_8255
---help--- ---help---
...@@ -1043,6 +1049,7 @@ config COMEDI_NI_PCIDIO ...@@ -1043,6 +1049,7 @@ config COMEDI_NI_PCIDIO
config COMEDI_NI_PCIMIO config COMEDI_NI_PCIMIO
tristate "NI PCI-MIO-E series and M series support" tristate "NI PCI-MIO-E series and M series support"
depends on HAS_DMA
select COMEDI_NI_TIOCMD select COMEDI_NI_TIOCMD
select COMEDI_8255 select COMEDI_8255
select COMEDI_FC select COMEDI_FC
...@@ -1095,10 +1102,12 @@ config COMEDI_SSV_DNP ...@@ -1095,10 +1102,12 @@ config COMEDI_SSV_DNP
called ssv_dnp. called ssv_dnp.
config COMEDI_MITE config COMEDI_MITE
depends on HAS_DMA
tristate tristate
config COMEDI_NI_TIOCMD config COMEDI_NI_TIOCMD
tristate tristate
depends on HAS_DMA
select COMEDI_NI_TIO select COMEDI_NI_TIO
select COMEDI_MITE select COMEDI_MITE
......
...@@ -51,10 +51,12 @@ static void __comedi_buf_free(struct comedi_device *dev, ...@@ -51,10 +51,12 @@ static void __comedi_buf_free(struct comedi_device *dev,
clear_bit(PG_reserved, clear_bit(PG_reserved,
&(virt_to_page(buf->virt_addr)->flags)); &(virt_to_page(buf->virt_addr)->flags));
if (s->async_dma_dir != DMA_NONE) { if (s->async_dma_dir != DMA_NONE) {
#ifdef CONFIG_HAS_DMA
dma_free_coherent(dev->hw_dev, dma_free_coherent(dev->hw_dev,
PAGE_SIZE, PAGE_SIZE,
buf->virt_addr, buf->virt_addr,
buf->dma_addr); buf->dma_addr);
#endif
} else { } else {
free_page((unsigned long)buf->virt_addr); free_page((unsigned long)buf->virt_addr);
} }
...@@ -74,6 +76,12 @@ static void __comedi_buf_alloc(struct comedi_device *dev, ...@@ -74,6 +76,12 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
struct comedi_buf_page *buf; struct comedi_buf_page *buf;
unsigned i; unsigned i;
if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) {
dev_err(dev->class_dev,
"dma buffer allocation not supported\n");
return;
}
async->buf_page_list = vzalloc(sizeof(*buf) * n_pages); async->buf_page_list = vzalloc(sizeof(*buf) * n_pages);
if (async->buf_page_list) if (async->buf_page_list)
pages = vmalloc(sizeof(struct page *) * n_pages); pages = vmalloc(sizeof(struct page *) * n_pages);
...@@ -84,11 +92,15 @@ static void __comedi_buf_alloc(struct comedi_device *dev, ...@@ -84,11 +92,15 @@ static void __comedi_buf_alloc(struct comedi_device *dev,
for (i = 0; i < n_pages; i++) { for (i = 0; i < n_pages; i++) {
buf = &async->buf_page_list[i]; buf = &async->buf_page_list[i];
if (s->async_dma_dir != DMA_NONE) if (s->async_dma_dir != DMA_NONE)
#ifdef CONFIG_HAS_DMA
buf->virt_addr = dma_alloc_coherent(dev->hw_dev, buf->virt_addr = dma_alloc_coherent(dev->hw_dev,
PAGE_SIZE, PAGE_SIZE,
&buf->dma_addr, &buf->dma_addr,
GFP_KERNEL | GFP_KERNEL |
__GFP_COMP); __GFP_COMP);
#else
break;
#endif
else else
buf->virt_addr = (void *)get_zeroed_page(GFP_KERNEL); buf->virt_addr = (void *)get_zeroed_page(GFP_KERNEL);
if (!buf->virt_addr) if (!buf->virt_addr)
......
...@@ -246,9 +246,6 @@ static int resize_async_buffer(struct comedi_device *dev, ...@@ -246,9 +246,6 @@ static int resize_async_buffer(struct comedi_device *dev,
return -EBUSY; return -EBUSY;
} }
if (!async->prealloc_buf)
return -EINVAL;
/* make sure buffer is an integral number of pages /* make sure buffer is an integral number of pages
* (we round up) */ * (we round up) */
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
......
...@@ -976,8 +976,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -976,8 +976,7 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
/* clear flip-flop to make sure 2-byte registers for /* clear flip-flop to make sure 2-byte registers for
* count and address get set correctly */ * count and address get set correctly */
clear_dma_ff(devpriv->dma_chan); clear_dma_ff(devpriv->dma_chan);
set_dma_addr(devpriv->dma_chan, set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
virt_to_bus(devpriv->dma_buffer));
/* set appropriate size of transfer */ /* set appropriate size of transfer */
devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd); devpriv->dma_transfer_size = labpc_suggest_transfer_size(cmd);
if (cmd->stop_src == TRIG_COUNT && if (cmd->stop_src == TRIG_COUNT &&
...@@ -1089,7 +1088,7 @@ static void labpc_drain_dma(struct comedi_device *dev) ...@@ -1089,7 +1088,7 @@ static void labpc_drain_dma(struct comedi_device *dev)
devpriv->count -= num_points; devpriv->count -= num_points;
/* set address and count for next transfer */ /* set address and count for next transfer */
set_dma_addr(devpriv->dma_chan, virt_to_bus(devpriv->dma_buffer)); set_dma_addr(devpriv->dma_chan, devpriv->dma_addr);
set_dma_count(devpriv->dma_chan, leftover * sample_size); set_dma_count(devpriv->dma_chan, leftover * sample_size);
release_dma_lock(flags); release_dma_lock(flags);
...@@ -1741,6 +1740,9 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it) ...@@ -1741,6 +1740,9 @@ static int labpc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
unsigned long dma_flags; unsigned long dma_flags;
devpriv->dma_chan = dma_chan; devpriv->dma_chan = dma_chan;
devpriv->dma_addr =
virt_to_bus(devpriv->dma_buffer);
dma_flags = claim_dma_lock(); dma_flags = claim_dma_lock();
disable_dma(devpriv->dma_chan); disable_dma(devpriv->dma_chan);
set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
......
...@@ -82,6 +82,7 @@ struct labpc_private { ...@@ -82,6 +82,7 @@ struct labpc_private {
unsigned int divisor_b1; unsigned int divisor_b1;
unsigned int dma_chan; /* dma channel to use */ unsigned int dma_chan; /* dma channel to use */
u16 *dma_buffer; /* buffer ai will dma into */ u16 *dma_buffer; /* buffer ai will dma into */
phys_addr_t dma_addr;
/* transfer size in bytes for current transfer */ /* transfer size in bytes for current transfer */
unsigned int dma_transfer_size; unsigned int dma_transfer_size;
/* we are using dma/fifo-half-full/etc. */ /* we are using dma/fifo-half-full/etc. */
......
...@@ -310,9 +310,11 @@ static int ni_gpct_insn_read(struct comedi_device *dev, ...@@ -310,9 +310,11 @@ static int ni_gpct_insn_read(struct comedi_device *dev,
static int ni_gpct_insn_config(struct comedi_device *dev, static int ni_gpct_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data); struct comedi_insn *insn, unsigned int *data);
#ifdef PCIDMA
static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s); static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
static int ni_gpct_cmdtest(struct comedi_device *dev, static int ni_gpct_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd); struct comedi_subdevice *s, struct comedi_cmd *cmd);
#endif
static int ni_gpct_cancel(struct comedi_device *dev, static int ni_gpct_cancel(struct comedi_device *dev,
struct comedi_subdevice *s); struct comedi_subdevice *s);
static void handle_gpct_interrupt(struct comedi_device *dev, static void handle_gpct_interrupt(struct comedi_device *dev,
...@@ -4617,9 +4619,7 @@ static int ni_E_init(struct comedi_device *dev) ...@@ -4617,9 +4619,7 @@ static int ni_E_init(struct comedi_device *dev)
for (j = 0; j < NUM_GPCT; ++j) { for (j = 0; j < NUM_GPCT; ++j) {
s = &dev->subdevices[NI_GPCT_SUBDEV(j)]; s = &dev->subdevices[NI_GPCT_SUBDEV(j)];
s->type = COMEDI_SUBD_COUNTER; s->type = COMEDI_SUBD_COUNTER;
s->subdev_flags = s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL;
SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL | SDF_CMD_READ
/* | SDF_CMD_WRITE */ ;
s->n_chan = 3; s->n_chan = 3;
if (board->reg_type & ni_reg_m_series_mask) if (board->reg_type & ni_reg_m_series_mask)
s->maxdata = 0xffffffff; s->maxdata = 0xffffffff;
...@@ -4628,11 +4628,14 @@ static int ni_E_init(struct comedi_device *dev) ...@@ -4628,11 +4628,14 @@ static int ni_E_init(struct comedi_device *dev)
s->insn_read = &ni_gpct_insn_read; s->insn_read = &ni_gpct_insn_read;
s->insn_write = &ni_gpct_insn_write; s->insn_write = &ni_gpct_insn_write;
s->insn_config = &ni_gpct_insn_config; s->insn_config = &ni_gpct_insn_config;
#ifdef PCIDMA
s->subdev_flags |= SDF_CMD_READ /* | SDF_CMD_WRITE */;
s->do_cmd = &ni_gpct_cmd; s->do_cmd = &ni_gpct_cmd;
s->len_chanlist = 1; s->len_chanlist = 1;
s->do_cmdtest = &ni_gpct_cmdtest; s->do_cmdtest = &ni_gpct_cmdtest;
s->cancel = &ni_gpct_cancel; s->cancel = &ni_gpct_cancel;
s->async_dma_dir = DMA_BIDIRECTIONAL; s->async_dma_dir = DMA_BIDIRECTIONAL;
#endif
s->private = &devpriv->counter_dev->counters[j]; s->private = &devpriv->counter_dev->counters[j];
devpriv->counter_dev->counters[j].chip_index = 0; devpriv->counter_dev->counters[j].chip_index = 0;
...@@ -5216,10 +5219,10 @@ static int ni_gpct_insn_write(struct comedi_device *dev, ...@@ -5216,10 +5219,10 @@ static int ni_gpct_insn_write(struct comedi_device *dev,
return ni_tio_winsn(counter, insn, data); return ni_tio_winsn(counter, insn, data);
} }
#ifdef PCIDMA
static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s) static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{ {
int retval; int retval;
#ifdef PCIDMA
struct ni_gpct *counter = s->private; struct ni_gpct *counter = s->private;
/* const struct comedi_cmd *cmd = &s->async->cmd; */ /* const struct comedi_cmd *cmd = &s->async->cmd; */
...@@ -5233,23 +5236,20 @@ static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s) ...@@ -5233,23 +5236,20 @@ static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL); ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL, NULL);
ni_e_series_enable_second_irq(dev, counter->counter_index, 1); ni_e_series_enable_second_irq(dev, counter->counter_index, 1);
retval = ni_tio_cmd(counter, s->async); retval = ni_tio_cmd(counter, s->async);
#else
retval = -ENOTSUPP;
#endif
return retval; return retval;
} }
#endif
#ifdef PCIDMA
static int ni_gpct_cmdtest(struct comedi_device *dev, static int ni_gpct_cmdtest(struct comedi_device *dev,
struct comedi_subdevice *s, struct comedi_cmd *cmd) struct comedi_subdevice *s, struct comedi_cmd *cmd)
{ {
#ifdef PCIDMA
struct ni_gpct *counter = s->private; struct ni_gpct *counter = s->private;
return ni_tio_cmdtest(counter, cmd); return ni_tio_cmdtest(counter, cmd);
#else
return -ENOTSUPP; return -ENOTSUPP;
#endif
} }
#endif
static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s) static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{ {
......
...@@ -38,6 +38,7 @@ config USB_DWC2_TRACK_MISSED_SOFS ...@@ -38,6 +38,7 @@ config USB_DWC2_TRACK_MISSED_SOFS
bool "Enable Missed SOF Tracking" bool "Enable Missed SOF Tracking"
help help
Say Y here to enable logging of missed SOF events to the dmesg log. Say Y here to enable logging of missed SOF events to the dmesg log.
WARNING: This feature is still experimental.
If in doubt, say N. If in doubt, say N.
config USB_DWC2_DEBUG_PERIODIC config USB_DWC2_DEBUG_PERIODIC
......
...@@ -56,8 +56,6 @@ ...@@ -56,8 +56,6 @@
static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg) static void dwc2_track_missed_sofs(struct dwc2_hsotg *hsotg)
{ {
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
#warning Compiling code to track missed SOFs
u16 curr_frame_number = hsotg->frame_number; u16 curr_frame_number = hsotg->frame_number;
if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) { if (hsotg->frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
......
...@@ -95,6 +95,14 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -95,6 +95,14 @@ static int dwc2_driver_probe(struct platform_device *dev)
hsotg->dev = &dev->dev; hsotg->dev = &dev->dev;
/*
* Use reasonable defaults so platforms don't have to provide these.
*/
if (!dev->dev.dma_mask)
dev->dev.dma_mask = &dev->dev.coherent_dma_mask;
if (!dev->dev.coherent_dma_mask)
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
irq = platform_get_irq(dev, 0); irq = platform_get_irq(dev, 0);
if (irq < 0) { if (irq < 0) {
dev_err(&dev->dev, "missing IRQ resource\n"); dev_err(&dev->dev, "missing IRQ resource\n");
......
...@@ -690,7 +690,6 @@ static void mxs_lradc_trigger_remove(struct iio_dev *iio) ...@@ -690,7 +690,6 @@ static void mxs_lradc_trigger_remove(struct iio_dev *iio)
static int mxs_lradc_buffer_preenable(struct iio_dev *iio) static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
{ {
struct mxs_lradc *lradc = iio_priv(iio); struct mxs_lradc *lradc = iio_priv(iio);
struct iio_buffer *buffer = iio->buffer;
int ret = 0, chan, ofs = 0; int ret = 0, chan, ofs = 0;
unsigned long enable = 0; unsigned long enable = 0;
uint32_t ctrl4_set = 0; uint32_t ctrl4_set = 0;
...@@ -698,7 +697,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) ...@@ -698,7 +697,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
uint32_t ctrl1_irq = 0; uint32_t ctrl1_irq = 0;
const uint32_t chan_value = LRADC_CH_ACCUMULATE | const uint32_t chan_value = LRADC_CH_ACCUMULATE |
((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
const int len = bitmap_weight(buffer->scan_mask, LRADC_MAX_TOTAL_CHANS); const int len = bitmap_weight(iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS);
if (!len) if (!len)
return -EINVAL; return -EINVAL;
...@@ -725,7 +724,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio) ...@@ -725,7 +724,7 @@ static int mxs_lradc_buffer_preenable(struct iio_dev *iio)
lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR); lradc->base + LRADC_CTRL1 + STMP_OFFSET_REG_CLR);
writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR); writel(0xff, lradc->base + LRADC_CTRL0 + STMP_OFFSET_REG_CLR);
for_each_set_bit(chan, buffer->scan_mask, LRADC_MAX_TOTAL_CHANS) { for_each_set_bit(chan, iio->active_scan_mask, LRADC_MAX_TOTAL_CHANS) {
ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs); ctrl4_set |= chan << LRADC_CTRL4_LRADCSELECT_OFFSET(ofs);
ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs); ctrl4_clr |= LRADC_CTRL4_LRADCSELECT_MASK(ofs);
ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs); ctrl1_irq |= LRADC_CTRL1_LRADC_IRQ_EN(ofs);
......
...@@ -1869,6 +1869,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp, ...@@ -1869,6 +1869,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
dev_info(&chip->client->dev, dev_info(&chip->client->dev,
"%s: i2c device found does not match expected id\n", "%s: i2c device found does not match expected id\n",
__func__); __func__);
ret = -EINVAL;
goto fail1; goto fail1;
} }
...@@ -1907,7 +1908,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp, ...@@ -1907,7 +1908,7 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
if (ret) { if (ret) {
dev_err(&clientp->dev, dev_err(&clientp->dev,
"%s: irq request failed", __func__); "%s: irq request failed", __func__);
goto fail2; goto fail1;
} }
} }
...@@ -1920,17 +1921,17 @@ static int tsl2x7x_probe(struct i2c_client *clientp, ...@@ -1920,17 +1921,17 @@ static int tsl2x7x_probe(struct i2c_client *clientp,
if (ret) { if (ret) {
dev_err(&clientp->dev, dev_err(&clientp->dev,
"%s: iio registration failed\n", __func__); "%s: iio registration failed\n", __func__);
goto fail1; goto fail2;
} }
dev_info(&clientp->dev, "%s Light sensor found.\n", id->name); dev_info(&clientp->dev, "%s Light sensor found.\n", id->name);
return 0; return 0;
fail1: fail2:
if (clientp->irq) if (clientp->irq)
free_irq(clientp->irq, indio_dev); free_irq(clientp->irq, indio_dev);
fail2: fail1:
iio_device_free(indio_dev); iio_device_free(indio_dev);
return ret; return ret;
......
config DRM_IMX config DRM_IMX
tristate "DRM Support for Freescale i.MX" tristate "DRM Support for Freescale i.MX"
select DRM_KMS_HELPER select DRM_KMS_HELPER
select VIDEOMODE_HELPERS
select DRM_GEM_CMA_HELPER select DRM_GEM_CMA_HELPER
select DRM_KMS_CMA_HELPER select DRM_KMS_CMA_HELPER
depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM) depends on DRM && (ARCH_MXC || ARCH_MULTIPLATFORM)
...@@ -19,10 +20,12 @@ config DRM_IMX_FB_HELPER ...@@ -19,10 +20,12 @@ config DRM_IMX_FB_HELPER
config DRM_IMX_PARALLEL_DISPLAY config DRM_IMX_PARALLEL_DISPLAY
tristate "Support for parallel displays" tristate "Support for parallel displays"
depends on DRM_IMX depends on DRM_IMX
select VIDEOMODE_HELPERS
config DRM_IMX_TVE config DRM_IMX_TVE
tristate "Support for TV and VGA displays" tristate "Support for TV and VGA displays"
depends on DRM_IMX depends on DRM_IMX
select REGMAP_MMIO
help help
Choose this to enable the internal Television Encoder (TVe) Choose this to enable the internal Television Encoder (TVe)
found on i.MX53 processors. found on i.MX53 processors.
...@@ -30,6 +33,7 @@ config DRM_IMX_TVE ...@@ -30,6 +33,7 @@ config DRM_IMX_TVE
config DRM_IMX_IPUV3_CORE config DRM_IMX_IPUV3_CORE
tristate "IPUv3 core support" tristate "IPUv3 core support"
depends on DRM_IMX depends on DRM_IMX
depends on RESET_CONTROLLER
help help
Choose this if you have a i.MX5/6 system and want Choose this if you have a i.MX5/6 system and want
to use the IPU. This option only enables IPU base to use the IPU. This option only enables IPU base
...@@ -38,5 +42,6 @@ config DRM_IMX_IPUV3_CORE ...@@ -38,5 +42,6 @@ config DRM_IMX_IPUV3_CORE
config DRM_IMX_IPUV3 config DRM_IMX_IPUV3
tristate "DRM Support for i.MX IPUv3" tristate "DRM Support for i.MX IPUv3"
depends on DRM_IMX depends on DRM_IMX
depends on DRM_IMX_IPUV3_CORE
help help
Choose this if you have a i.MX5 or i.MX6 processor. Choose this if you have a i.MX5 or i.MX6 processor.
...@@ -670,7 +670,9 @@ static int imx_tve_probe(struct platform_device *pdev) ...@@ -670,7 +670,9 @@ static int imx_tve_probe(struct platform_device *pdev)
tve->dac_reg = devm_regulator_get(&pdev->dev, "dac"); tve->dac_reg = devm_regulator_get(&pdev->dev, "dac");
if (!IS_ERR(tve->dac_reg)) { if (!IS_ERR(tve->dac_reg)) {
regulator_set_voltage(tve->dac_reg, 2750000, 2750000); regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
regulator_enable(tve->dac_reg); ret = regulator_enable(tve->dac_reg);
if (ret)
return ret;
} }
tve->clk = devm_clk_get(&pdev->dev, "tve"); tve->clk = devm_clk_get(&pdev->dev, "tve");
......
config SOLO6X10 config SOLO6X10
tristate "Softlogic 6x10 MPEG codec cards" tristate "Softlogic 6x10 MPEG codec cards"
depends on PCI && VIDEO_DEV && SND && I2C depends on PCI && VIDEO_DEV && SND && I2C
depends on FONTS
select VIDEOBUF2_DMA_SG select VIDEOBUF2_DMA_SG
select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_DMA_CONTIG
select SND_PCM select SND_PCM
......
...@@ -123,6 +123,20 @@ int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb, ...@@ -123,6 +123,20 @@ int nvec_register_notifier(struct nvec_chip *nvec, struct notifier_block *nb,
} }
EXPORT_SYMBOL_GPL(nvec_register_notifier); EXPORT_SYMBOL_GPL(nvec_register_notifier);
/**
* nvec_unregister_notifier - Unregister a notifier with nvec
* @nvec: A &struct nvec_chip
* @nb: The notifier block to unregister
*
* Unregisters a notifier with @nvec. The notifier will be removed from the
* atomic notifier chain.
*/
int nvec_unregister_notifier(struct nvec_chip *nvec, struct notifier_block *nb)
{
return atomic_notifier_chain_unregister(&nvec->notifier_list, nb);
}
EXPORT_SYMBOL_GPL(nvec_unregister_notifier);
/** /**
* nvec_status_notifier - The final notifier * nvec_status_notifier - The final notifier
* *
...@@ -185,7 +199,7 @@ static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec, ...@@ -185,7 +199,7 @@ static struct nvec_msg *nvec_msg_alloc(struct nvec_chip *nvec,
* *
* Free the given message * Free the given message
*/ */
inline void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg) void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg)
{ {
if (msg != &nvec->tx_scratch) if (msg != &nvec->tx_scratch)
dev_vdbg(nvec->dev, "INFO: Free %ti\n", msg - nvec->msg_pool); dev_vdbg(nvec->dev, "INFO: Free %ti\n", msg - nvec->msg_pool);
...@@ -810,7 +824,7 @@ static int tegra_nvec_probe(struct platform_device *pdev) ...@@ -810,7 +824,7 @@ static int tegra_nvec_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
i2c_clk = clk_get(&pdev->dev, "div-clk"); i2c_clk = devm_clk_get(&pdev->dev, "div-clk");
if (IS_ERR(i2c_clk)) { if (IS_ERR(i2c_clk)) {
dev_err(nvec->dev, "failed to get controller clock\n"); dev_err(nvec->dev, "failed to get controller clock\n");
return -ENODEV; return -ENODEV;
...@@ -897,8 +911,11 @@ static int tegra_nvec_remove(struct platform_device *pdev) ...@@ -897,8 +911,11 @@ static int tegra_nvec_remove(struct platform_device *pdev)
nvec_toggle_global_events(nvec, false); nvec_toggle_global_events(nvec, false);
mfd_remove_devices(nvec->dev); mfd_remove_devices(nvec->dev);
nvec_unregister_notifier(nvec, &nvec->nvec_status_notifier);
cancel_work_sync(&nvec->rx_work); cancel_work_sync(&nvec->rx_work);
cancel_work_sync(&nvec->tx_work); cancel_work_sync(&nvec->tx_work);
/* FIXME: needs check wether nvec is responsible for power off */
pm_power_off = NULL;
return 0; return 0;
} }
......
...@@ -197,9 +197,8 @@ extern int nvec_register_notifier(struct nvec_chip *nvec, ...@@ -197,9 +197,8 @@ extern int nvec_register_notifier(struct nvec_chip *nvec,
struct notifier_block *nb, struct notifier_block *nb,
unsigned int events); unsigned int events);
extern int nvec_unregister_notifier(struct device *dev, extern int nvec_unregister_notifier(struct nvec_chip *dev,
struct notifier_block *nb, struct notifier_block *nb);
unsigned int events);
extern void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg); extern void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);
......
...@@ -169,8 +169,15 @@ static int nvec_kbd_probe(struct platform_device *pdev) ...@@ -169,8 +169,15 @@ static int nvec_kbd_probe(struct platform_device *pdev)
static int nvec_kbd_remove(struct platform_device *pdev) static int nvec_kbd_remove(struct platform_device *pdev)
{ {
struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
char disable_kbd[] = { NVEC_KBD, DISABLE_KBD },
uncnfg_wake_key_reporting[] = { NVEC_KBD, CNFG_WAKE_KEY_REPORTING,
false };
nvec_write_async(nvec, uncnfg_wake_key_reporting, 3);
nvec_write_async(nvec, disable_kbd, 2);
nvec_unregister_notifier(nvec, &keys_dev.notifier);
input_unregister_device(keys_dev.input); input_unregister_device(keys_dev.input);
input_free_device(keys_dev.input);
return 0; return 0;
} }
...@@ -188,4 +195,5 @@ module_platform_driver(nvec_kbd_driver); ...@@ -188,4 +195,5 @@ module_platform_driver(nvec_kbd_driver);
MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>"); MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
MODULE_DESCRIPTION("NVEC keyboard driver"); MODULE_DESCRIPTION("NVEC keyboard driver");
MODULE_ALIAS("platform:nvec-kbd");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -414,6 +414,7 @@ static int nvec_power_remove(struct platform_device *pdev) ...@@ -414,6 +414,7 @@ static int nvec_power_remove(struct platform_device *pdev)
struct nvec_power *power = platform_get_drvdata(pdev); struct nvec_power *power = platform_get_drvdata(pdev);
cancel_delayed_work_sync(&power->poller); cancel_delayed_work_sync(&power->poller);
nvec_unregister_notifier(power->nvec, &power->notifier);
switch (pdev->id) { switch (pdev->id) {
case AC: case AC:
power_supply_unregister(&nvec_psy); power_supply_unregister(&nvec_psy);
......
...@@ -106,7 +106,7 @@ static int nvec_mouse_probe(struct platform_device *pdev) ...@@ -106,7 +106,7 @@ static int nvec_mouse_probe(struct platform_device *pdev)
struct serio *ser_dev; struct serio *ser_dev;
char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 }; char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 };
ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL); ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL);
if (ser_dev == NULL) if (ser_dev == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -133,6 +133,11 @@ static int nvec_mouse_probe(struct platform_device *pdev) ...@@ -133,6 +133,11 @@ static int nvec_mouse_probe(struct platform_device *pdev)
static int nvec_mouse_remove(struct platform_device *pdev) static int nvec_mouse_remove(struct platform_device *pdev)
{ {
struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent);
ps2_sendcommand(ps2_dev.ser_dev, DISABLE_MOUSE);
ps2_stopstreaming(ps2_dev.ser_dev);
nvec_unregister_notifier(nvec, &ps2_dev.notifier);
serio_unregister_port(ps2_dev.ser_dev); serio_unregister_port(ps2_dev.ser_dev);
return 0; return 0;
...@@ -179,4 +184,5 @@ module_platform_driver(nvec_mouse_driver); ...@@ -179,4 +184,5 @@ module_platform_driver(nvec_mouse_driver);
MODULE_DESCRIPTION("NVEC mouse driver"); MODULE_DESCRIPTION("NVEC mouse driver");
MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>"); MODULE_AUTHOR("Marc Dietrich <marvin24@gmx.de>");
MODULE_ALIAS("platform:nvec-mouse");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
config DX_SEP config DX_SEP
tristate "Discretix SEP driver" tristate "Discretix SEP driver"
depends on PCI depends on PCI && CRYPTO
help help
Discretix SEP driver; used for the security processor subsystem Discretix SEP driver; used for the security processor subsystem
on board the Intel Mobile Internet Device and adds SEP availability on board the Intel Mobile Internet Device and adds SEP availability
......
...@@ -1087,7 +1087,11 @@ static int synaptics_rmi4_resume(struct device *dev) ...@@ -1087,7 +1087,11 @@ static int synaptics_rmi4_resume(struct device *dev)
unsigned char intr_status; unsigned char intr_status;
struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev); struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
regulator_enable(rmi4_data->regulator); retval = regulator_enable(rmi4_data->regulator);
if (retval) {
dev_err(dev, "Regulator enable failed (%d)\n", retval);
return retval;
}
enable_irq(rmi4_data->i2c_client->irq); enable_irq(rmi4_data->i2c_client->irq);
rmi4_data->touch_stopped = false; rmi4_data->touch_stopped = false;
......
...@@ -133,7 +133,7 @@ static int hostap_disable_hostapd(struct vnt_private *pDevice, int rtnl_locked) ...@@ -133,7 +133,7 @@ static int hostap_disable_hostapd(struct vnt_private *pDevice, int rtnl_locked)
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
pDevice->dev->name, pDevice->apdev->name); pDevice->dev->name, pDevice->apdev->name);
} }
kfree(pDevice->apdev); free_netdev(pDevice->apdev);
pDevice->apdev = NULL; pDevice->apdev = NULL;
pDevice->bEnable8021x = false; pDevice->bEnable8021x = false;
pDevice->bEnableHostWEP = false; pDevice->bEnableHostWEP = false;
......
...@@ -1345,9 +1345,12 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info, ...@@ -1345,9 +1345,12 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
return rc; return rc;
} }
spin_lock_irq(&pDevice->lock);
if (wrq->disabled) { if (wrq->disabled) {
pDevice->ePSMode = WMAC_POWER_CAM; pDevice->ePSMode = WMAC_POWER_CAM;
PSvDisablePowerSaving(pDevice); PSvDisablePowerSaving(pDevice);
spin_unlock_irq(&pDevice->lock);
return rc; return rc;
} }
if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { if ((wrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
...@@ -1358,6 +1361,9 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info, ...@@ -1358,6 +1361,9 @@ int iwctl_siwpower(struct net_device *dev, struct iw_request_info *info,
pDevice->ePSMode = WMAC_POWER_FAST; pDevice->ePSMode = WMAC_POWER_FAST;
PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval); PSvEnablePowerSaving((void *)pDevice, pMgmt->wListenInterval);
} }
spin_unlock_irq(&pDevice->lock);
switch (wrq->flags & IW_POWER_MODE) { switch (wrq->flags & IW_POWER_MODE) {
case IW_POWER_UNICAST_R: case IW_POWER_UNICAST_R:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n"); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCSIWPOWER: IW_POWER_UNICAST_R \n");
......
RAMSTER HOW-TO
Author: Dan Magenheimer
Ramster maintainer: Konrad Wilk <konrad.wilk@oracle.com>
This is a HOWTO document for ramster which, as of this writing, is in
the kernel as a subdirectory of zcache in drivers/staging, called ramster.
(Zcache can be built with or without ramster functionality.) If enabled
and properly configured, ramster allows memory capacity load balancing
across multiple machines in a cluster. Further, the ramster code serves
as an example of asynchronous access for zcache (as well as cleancache and
frontswap) that may prove useful for future transcendent memory
implementations, such as KVM and NVRAM. While ramster works today on
any network connection that supports kernel sockets, its features may
become more interesting on future high-speed fabrics/interconnects.
Ramster requires both kernel and userland support. The userland support,
called ramster-tools, is known to work with EL6-based distros, but is a
set of poorly-hacked slightly-modified cluster tools based on ocfs2, which
includes an init file, a config file, and a userland binary that interfaces
to the kernel. This state of userland support reflects the abysmal userland
skills of this suitably-embarrassed author; any help/patches to turn
ramster-tools into more distributable rpms/debs useful for a wider range
of distros would be appreciated. The source RPM that can be used as a
starting point is available at:
http://oss.oracle.com/projects/tmem/files/RAMster/
As a result of this author's ignorance, userland setup described in this
HOWTO assumes an EL6 distro and is described in EL6 syntax. Apologies
if this offends anyone!
Kernel support has only been tested on x86_64. Systems with an active
ocfs2 filesystem should work, but since ramster leverages a lot of
code from ocfs2, there may be latent issues. A kernel configuration that
includes CONFIG_OCFS2_FS should build OK, and should certainly run OK
if no ocfs2 filesystem is mounted.
This HOWTO demonstrates memory capacity load balancing for a two-node
cluster, where one node called the "local" node becomes overcommitted
and the other node called the "remote" node provides additional RAM
capacity for use by the local node. Ramster is capable of more complex
topologies; see the last section titled "ADVANCED RAMSTER TOPOLOGIES".
If you find any terms in this HOWTO unfamiliar or don't understand the
motivation for ramster, the following LWN reading is recommended:
-- Transcendent Memory in a Nutshell (lwn.net/Articles/454795)
-- The future calculus of memory management (lwn.net/Articles/475681)
And since ramster is built on top of zcache, this article may be helpful:
-- In-kernel memory compression (lwn.net/Articles/545244)
Now that you've memorized the contents of those articles, let's get started!
A. PRELIMINARY
1) Install two x86_64 Linux systems that are known to work when
upgraded to a recent upstream Linux kernel version.
On each system:
2) Configure, build and install, then boot Linux, just to ensure it
can be done with an unmodified upstream kernel. Confirm you booted
the upstream kernel with "uname -a".
3) If you plan to do any performance testing or unless you plan to
test only swapping, the "WasActive" patch is also highly recommended.
(Search lkml.org for WasActive, apply the patch, rebuild your kernel.)
For a demo or simple testing, the patch can be ignored.
4) Install ramster-tools as root. An x86_64 rpm for EL6-based systems
can be found at:
http://oss.oracle.com/projects/tmem/files/RAMster/
(Sorry but for now, non-EL6 users must recreate ramster-tools on
their own from source. See above.)
5) Ensure that debugfs is mounted at each boot. Examples below assume it
is mounted at /sys/kernel/debug.
B. BUILDING RAMSTER INTO THE KERNEL
Do the following on each system:
1) Using the kernel configuration mechanism of your choice, change
your config to include:
CONFIG_CLEANCACHE=y
CONFIG_FRONTSWAP=y
CONFIG_STAGING=y
CONFIG_CONFIGFS_FS=y # NOTE: MUST BE y, not m
CONFIG_ZCACHE=y
CONFIG_RAMSTER=y
For a linux-3.10 or later kernel, you should also set:
CONFIG_ZCACHE_DEBUG=y
CONFIG_RAMSTER_DEBUG=y
Before building the kernel please doublecheck your kernel config
file to ensure all of the settings are correct.
2) Build this kernel and change your boot file (e.g. /etc/grub.conf)
so that the new kernel will boot.
3) Add "zcache" and "ramster" as kernel boot parameters for the new kernel.
4) Reboot each system approximately simultaneously.
5) Check dmesg to ensure there are some messages from ramster, prefixed
by "ramster:"
# dmesg | grep ramster
You should also see a lot of files in:
# ls /sys/kernel/debug/zcache
# ls /sys/kernel/debug/ramster
These are mostly counters for various zcache and ramster activities.
You should also see files in:
# ls /sys/kernel/mm/ramster
These are sysfs files that control ramster as we shall see.
Ramster now will act as a single-system zcache on each system
but doesn't yet know anything about the cluster so can't yet do
anything remotely.
C. CONFIGURING THE RAMSTER CLUSTER
This part can be error prone unless you are familiar with clustering
filesystems. We need to describe the cluster in a /etc/ramster.conf
file and the init scripts that parse it are extremely picky about
the syntax.
1) Create a /etc/ramster.conf file and ensure it is identical on both
systems. This file mimics the ocfs2 format and there is a good amount
of documentation that can be searched for ocfs2.conf, but you can use:
cluster:
name = ramster
node_count = 2
node:
name = system1
cluster = ramster
number = 0
ip_address = my.ip.ad.r1
ip_port = 7777
node:
name = system2
cluster = ramster
number = 1
ip_address = my.ip.ad.r2
ip_port = 7777
You must ensure that the "name" field in the file exactly matches
the output of "hostname" on each system; if "hostname" shows a
fully-qualified hostname, ensure the name is fully qualified in
/etc/ramster.conf. Obviously, substitute my.ip.ad.rx with proper
ip addresses.
2) Enable the ramster service and configure it. If you used the
EL6 ramster-tools, this would be:
# chkconfig --add ramster
# service ramster configure
Set "load on boot" to "y", cluster to start is "ramster" (or whatever
name you chose in ramster.conf), heartbeat dead threshold as "500",
network idle timeout as "1000000". Leave the others as default.
3) Reboot both systems. After reboot, try (assuming EL6 ramster-tools):
# service ramster status
You should see "Checking RAMSTER cluster "ramster": Online". If you do
not, something is wrong and ramster will not work. Note that you
should also see that the driver for "configfs" is loaded and mounted,
the driver for ocfs2_dlmfs is not loaded, and some numbers for network
parameters. You will also see "Checking RAMSTER heartbeat: Not active".
That's all OK.
4) Now you need to start the cluster heartbeat; the cluster is not "up"
until all nodes detect a heartbeat. In a real cluster, heartbeat detection
is done via a cluster filesystem, but ramster doesn't require one. Some
hack-y kernel code in ramster can start the heartbeat for you though if
you tell it what nodes are "up". To enable the heartbeat, do:
# echo 0 > /sys/kernel/mm/ramster/manual_node_up
# echo 1 > /sys/kernel/mm/ramster/manual_node_up
This must be done on BOTH nodes and, to avoid timeouts, must be done
approximately concurrently on both nodes. On an EL6 system, it is
convenient to put these lines in /etc/rc.local. To confirm that the
cluster is now up, on both systems do:
# dmesg | grep ramster
You should see ramster "Accepted connection" messages in dmesg on both
nodes after this. Note that if you check userland status again with
# service ramster status
you will still see "Checking RAMSTER heartbeat: Not active". That's
still OK... the ramster kernel heartbeat hack doesn't communicate to
userland.
5) You now must tell each node the node to which it should "remotify" pages.
On this two node cluster, we will assume the "local" node, node 0, has
memory overcommitted and will use ramster to utilize RAM capacity on
the "remote node", node 1. To configure this, on node 0, you do:
# echo 1 > /sys/kernel/mm/ramster/remote_target_nodenum
You should see "ramster: node 1 set as remotification target" in dmesg
on node 0. Again, on EL6, /etc/rc.local is a good place to put this
on node 0 so you don't forget to do it at each boot.
6) One more step: By default, the ramster code does not "remotify" any
pages; this is primarily for testing purposes, but sometimes it is
useful. This may change in the future, but for now, on node 0, you do:
# echo 1 > /sys/kernel/mm/ramster/pers_remotify_enable
# echo 1 > /sys/kernel/mm/ramster/eph_remotify_enable
The first enables remotifying swap (persistent, aka frontswap) pages,
the second enables remotifying of page cache (ephemeral, cleancache)
pages.
On EL6, these lines can also be put in /etc/rc.local (AFTER the
node_up lines), or at the beginning of a script that runs a workload.
7) Note that most testing has been done with both/all machines booted
roughly simultaneously to avoid cluster timeouts. Ideally, you should
do this too unless you are trying to break ramster rather than just
use it. ;-)
D. TESTING RAMSTER
1) Note that ramster has no value unless pages get "remotified". For
swap/frontswap/persistent pages, this doesn't happen unless/until
the workload would cause swapping to occur, at which point pages
are put into frontswap/zcache, and the remotification thread starts
working. To get to the point where the system swaps, you either
need a workload for which the working set exceeds the RAM in the
system; or you need to somehow reduce the amount of RAM one of
the system sees. This latter is easy when testing in a VM, but
harder on physical systems. In some cases, "mem=xxxM" on the
kernel command line restricts memory, but for some values of xxx
the kernel may fail to boot. One may also try creating a fixed
RAMdisk, doing nothing with it, but ensuring that it eats up a fixed
amount of RAM.
2) To see if ramster is working, on the "remote node", node 1, try:
# grep . /sys/kernel/debug/ramster/foreign_*
# # note, that is space-dot-space between grep and the pathname
to monitor the number (and max) ephemeral and persistent pages
that ramster has sent. If these stay at zero, ramster is not working
either because the workload on the local node (node 0) isn't creating
enough memory pressure or because "remotifying" isn't working. On the
local system, node 0, you can watch lots of useful information also.
Try:
grep . /sys/kernel/debug/zcache/*pageframes* \
/sys/kernel/debug/zcache/*zbytes* \
/sys/kernel/debug/zcache/*zpages* \
/sys/kernel/debug/ramster/*remote*
Of particular note are the remote_*_pages_succ_get counters. These
show how many disk reads and/or disk writes have been avoided on the
overcommitted local system by storing pages remotely using ramster.
At the risk of information overload, you can also grep:
/sys/kernel/debug/cleancache/* and /sys/kernel/debug/frontswap/*
These show, for example, how many disk reads and/or disk writes have
been avoided by using zcache to optimize RAM on the local system.
AUTOMATIC SWAP REPATRIATION
You may notice that while the systems are idle, the foreign persistent
page count on the remote machine slowly decreases. This is because
ramster implements "frontswap selfshrinking": When possible, swap
pages that have been remotified are slowly repatriated to the local
machine. This is so that local RAM can be used when possible and
so that, in case of remote machine crash, the probability of loss
of data is reduced.
REBOOTING / POWEROFF
If a system is shut down while some of its swap pages still reside
on a remote system, the system may lock up during the shutdown
sequence. This will occur if the network is shut down before the
swap mechansim is shut down, which is the default ordering on many
distros. To avoid this annoying problem, simply shut off the swap
subsystem before starting the shutdown sequence, e.g.:
# swapoff -a
# reboot
Ideally, this swapoff-before-ifdown ordering should be enforced permanently
using shutdown scripts.
KNOWN PROBLEMS
1) You may periodically see messages such as:
ramster_r2net, message length problem
This is harmless but indicates that a node is sending messages
containing compressed pages that exceed the maximum for zcache
(PAGE_SIZE*15/16). The sender side needs to be fixed.
2) If you see a "No longer connected to node..." message or a "No connection
established with node X after N seconds", it is possible you may
be in an unrecoverable state. If you are certain all of the
appropriate cluster configuration steps described above have been
performed, try rebooting the two servers concurrently to see if
the cluster starts.
Note that "Connection to node... shutdown, state 7" is an intermediate
connection state. As long as you later see "Accepted connection", the
intermediate states are harmless.
3) There are known issues in counting certain values. As a result
you may see periodic warnings from the kernel. Almost always you
will see "ramster: bad accounting for XXX". There are also "WARN_ONCE"
messages. If you see kernel warnings with a tombstone, please report
them. They are harmless but reflect bugs that need to be eventually fixed.
ADVANCED RAMSTER TOPOLOGIES
The kernel code for ramster can support up to eight nodes in a cluster,
but no testing has been done with more than three nodes.
In the example described above, the "remote" node serves as a RAM
overflow for the "local" node. This can be made symmetric by appropriate
settings of the sysfs remote_target_nodenum file. For example, by setting:
# echo 1 > /sys/kernel/mm/ramster/remote_target_nodenum
on node 0, and
# echo 0 > /sys/kernel/mm/ramster/remote_target_nodenum
on node 1, each node can serve as a RAM overflow for the other.
For more than two nodes, a "RAM server" can be configured. For a
three node system, set:
# echo 0 > /sys/kernel/mm/ramster/remote_target_nodenum
on node 1, and
# echo 0 > /sys/kernel/mm/ramster/remote_target_nodenum
on node 2. Then node 0 is a RAM server for node 1 and node 2.
In this implementation of ramster, any remote node is potentially a single
point of failure (SPOF). Though the probability of failure is reduced
by automatic swap repatriation (see above), a proposed future enhancement
to ramster improves high-availability for the cluster by sending a copy
of each page of date to two other nodes. Patches welcome!
...@@ -1922,15 +1922,15 @@ static int zcache_init(void) ...@@ -1922,15 +1922,15 @@ static int zcache_init(void)
#ifdef CONFIG_ZCACHE_MODULE #ifdef CONFIG_ZCACHE_MODULE
#ifdef CONFIG_RAMSTER #ifdef CONFIG_RAMSTER
module_param(ramster_enabled, int, S_IRUGO); module_param(ramster_enabled, bool, S_IRUGO);
module_param(disable_frontswap_selfshrink, int, S_IRUGO); module_param(disable_frontswap_selfshrink, int, S_IRUGO);
#endif #endif
module_param(disable_cleancache, int, S_IRUGO); module_param(disable_cleancache, bool, S_IRUGO);
module_param(disable_frontswap, int, S_IRUGO); module_param(disable_frontswap, bool, S_IRUGO);
#ifdef FRONTSWAP_HAS_EXCLUSIVE_GETS #ifdef FRONTSWAP_HAS_EXCLUSIVE_GETS
module_param(frontswap_has_exclusive_gets, bool, S_IRUGO); module_param(frontswap_has_exclusive_gets, bool, S_IRUGO);
#endif #endif
module_param(disable_frontswap_ignore_nonactive, int, S_IRUGO); module_param(disable_frontswap_ignore_nonactive, bool, S_IRUGO);
module_param(zcache_comp_name, charp, S_IRUGO); module_param(zcache_comp_name, charp, S_IRUGO);
module_init(zcache_init); module_init(zcache_init);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
......
...@@ -18,6 +18,8 @@ font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o ...@@ -18,6 +18,8 @@ font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
font-objs += $(font-objs-y) font-objs += $(font-objs-y)
obj-$(CONFIG_FONTS) += font.o
# Each configuration option enables a list of files. # Each configuration option enables a list of files.
obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o obj-$(CONFIG_DUMMY_CONSOLE) += dummycon.o
......
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