mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
Char/Misc driver fixes for 6.11-rc7
Here are some small char/misc/other driver fixes for 6.11-rc7. It's nothing huge, just a bunch of small fixes of reported problems, including: - lots of tiny iio driver fixes - nvmem driver fixex - binder UAF bugfix - uio driver crash fix - other small fixes All of these have been in linux-next this week with no reported problems. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCZt1VBw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ynTEACgzhPgd29DA9pmR+BcDPJtxLBRQtcAoNiAFApH Gzo5Ucw+Snl5wQvBJGhI =J4Is -----END PGP SIGNATURE----- Merge tag 'char-misc-6.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc driver fixes from Greg KH: "Here are some small char/misc/other driver fixes for 6.11-rc7. It's nothing huge, just a bunch of small fixes of reported problems, including: - lots of tiny iio driver fixes - nvmem driver fixex - binder UAF bugfix - uio driver crash fix - other small fixes All of these have been in linux-next this week with no reported problems" * tag 'char-misc-6.11-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (21 commits) VMCI: Fix use-after-free when removing resource in vmci_resource_remove() Drivers: hv: vmbus: Fix rescind handling in uio_hv_generic uio_hv_generic: Fix kernel NULL pointer dereference in hv_uio_rescind misc: keba: Fix sysfs group creation dt-bindings: nvmem: Use soc-nvmem node name instead of nvmem nvmem: Fix return type of devm_nvmem_device_get() in kerneldoc nvmem: u-boot-env: error if NVMEM device is too small misc: fastrpc: Fix double free of 'buf' in error path binder: fix UAF caused by offsets overwrite iio: imu: inv_mpu6050: fix interrupt status read for old buggy chips iio: adc: ad7173: fix GPIO device info iio: adc: ad7124: fix DT configuration parsing iio: adc: ad_sigma_delta: fix irq_flags on irq request iio: adc: ads1119: Fix IRQ flags iio: fix scale application in iio_convert_raw_to_processed_unlocked iio: adc: ad7124: fix config comparison iio: adc: ad7124: fix chip ID mismatch iio: adc: ad7173: Fix incorrect compatible string iio: buffer-dmaengine: fix releasing dma channel on error iio: adc: ad7606: remove frstdata check for serial mode ...
This commit is contained in:
commit
5dadc1be8f
@ -28,7 +28,7 @@ unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
nvmem {
|
||||
soc-nvmem {
|
||||
compatible = "xlnx,zynqmp-nvmem-fw";
|
||||
nvmem-layout {
|
||||
compatible = "fixed-layout";
|
||||
|
@ -3422,6 +3422,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
*/
|
||||
copy_size = object_offset - user_offset;
|
||||
if (copy_size && (user_offset > object_offset ||
|
||||
object_offset > tr->data_size ||
|
||||
binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer, user_offset,
|
||||
|
@ -1952,6 +1952,7 @@ void vmbus_device_unregister(struct hv_device *device_obj)
|
||||
*/
|
||||
device_unregister(&device_obj->device);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(vmbus_device_unregister);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
/*
|
||||
|
@ -147,15 +147,18 @@ struct ad7124_chip_info {
|
||||
struct ad7124_channel_config {
|
||||
bool live;
|
||||
unsigned int cfg_slot;
|
||||
enum ad7124_ref_sel refsel;
|
||||
bool bipolar;
|
||||
bool buf_positive;
|
||||
bool buf_negative;
|
||||
unsigned int vref_mv;
|
||||
unsigned int pga_bits;
|
||||
unsigned int odr;
|
||||
unsigned int odr_sel_bits;
|
||||
unsigned int filter_type;
|
||||
/* Following fields are used to compare equality. */
|
||||
struct_group(config_props,
|
||||
enum ad7124_ref_sel refsel;
|
||||
bool bipolar;
|
||||
bool buf_positive;
|
||||
bool buf_negative;
|
||||
unsigned int vref_mv;
|
||||
unsigned int pga_bits;
|
||||
unsigned int odr;
|
||||
unsigned int odr_sel_bits;
|
||||
unsigned int filter_type;
|
||||
);
|
||||
};
|
||||
|
||||
struct ad7124_channel {
|
||||
@ -334,11 +337,12 @@ static struct ad7124_channel_config *ad7124_find_similar_live_cfg(struct ad7124_
|
||||
ptrdiff_t cmp_size;
|
||||
int i;
|
||||
|
||||
cmp_size = (u8 *)&cfg->live - (u8 *)cfg;
|
||||
cmp_size = sizeof_field(struct ad7124_channel_config, config_props);
|
||||
for (i = 0; i < st->num_channels; i++) {
|
||||
cfg_aux = &st->channels[i].cfg;
|
||||
|
||||
if (cfg_aux->live && !memcmp(cfg, cfg_aux, cmp_size))
|
||||
if (cfg_aux->live &&
|
||||
!memcmp(&cfg->config_props, &cfg_aux->config_props, cmp_size))
|
||||
return cfg_aux;
|
||||
}
|
||||
|
||||
@ -764,6 +768,7 @@ static int ad7124_soft_reset(struct ad7124_state *st)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
fsleep(200);
|
||||
timeout = 100;
|
||||
do {
|
||||
ret = ad_sd_read_reg(&st->sd, AD7124_STATUS, 1, &readval);
|
||||
@ -839,8 +844,6 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
st->channels = channels;
|
||||
|
||||
device_for_each_child_node_scoped(dev, child) {
|
||||
cfg = &st->channels[channel].cfg;
|
||||
|
||||
ret = fwnode_property_read_u32(child, "reg", &channel);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -858,6 +861,7 @@ static int ad7124_parse_channel_config(struct iio_dev *indio_dev,
|
||||
st->channels[channel].ain = AD7124_CHANNEL_AINP(ain[0]) |
|
||||
AD7124_CHANNEL_AINM(ain[1]);
|
||||
|
||||
cfg = &st->channels[channel].cfg;
|
||||
cfg->bipolar = fwnode_property_read_bool(child, "bipolar");
|
||||
|
||||
ret = fwnode_property_read_u32(child, "adi,reference-select", &tmp);
|
||||
|
@ -302,7 +302,6 @@ static const struct ad7173_device_info ad4114_device_info = {
|
||||
.num_configs = 8,
|
||||
.num_voltage_in = 16,
|
||||
.num_gpios = 4,
|
||||
.higher_gpio_bits = true,
|
||||
.has_vincom_input = true,
|
||||
.has_temp = true,
|
||||
.has_input_buf = true,
|
||||
@ -320,7 +319,6 @@ static const struct ad7173_device_info ad4115_device_info = {
|
||||
.num_configs = 8,
|
||||
.num_voltage_in = 16,
|
||||
.num_gpios = 4,
|
||||
.higher_gpio_bits = true,
|
||||
.has_vincom_input = true,
|
||||
.has_temp = true,
|
||||
.has_input_buf = true,
|
||||
@ -338,7 +336,6 @@ static const struct ad7173_device_info ad4116_device_info = {
|
||||
.num_configs = 8,
|
||||
.num_voltage_in = 16,
|
||||
.num_gpios = 4,
|
||||
.higher_gpio_bits = true,
|
||||
.has_vincom_input = true,
|
||||
.has_temp = true,
|
||||
.has_input_buf = true,
|
||||
@ -1435,11 +1432,11 @@ static int ad7173_probe(struct spi_device *spi)
|
||||
}
|
||||
|
||||
static const struct of_device_id ad7173_of_match[] = {
|
||||
{ .compatible = "ad4111", .data = &ad4111_device_info },
|
||||
{ .compatible = "ad4112", .data = &ad4112_device_info },
|
||||
{ .compatible = "ad4114", .data = &ad4114_device_info },
|
||||
{ .compatible = "ad4115", .data = &ad4115_device_info },
|
||||
{ .compatible = "ad4116", .data = &ad4116_device_info },
|
||||
{ .compatible = "adi,ad4111", .data = &ad4111_device_info },
|
||||
{ .compatible = "adi,ad4112", .data = &ad4112_device_info },
|
||||
{ .compatible = "adi,ad4114", .data = &ad4114_device_info },
|
||||
{ .compatible = "adi,ad4115", .data = &ad4115_device_info },
|
||||
{ .compatible = "adi,ad4116", .data = &ad4116_device_info },
|
||||
{ .compatible = "adi,ad7172-2", .data = &ad7172_2_device_info },
|
||||
{ .compatible = "adi,ad7172-4", .data = &ad7172_4_device_info },
|
||||
{ .compatible = "adi,ad7173-8", .data = &ad7173_8_device_info },
|
||||
|
@ -49,7 +49,7 @@ static const unsigned int ad7616_oversampling_avail[8] = {
|
||||
1, 2, 4, 8, 16, 32, 64, 128,
|
||||
};
|
||||
|
||||
static int ad7606_reset(struct ad7606_state *st)
|
||||
int ad7606_reset(struct ad7606_state *st)
|
||||
{
|
||||
if (st->gpio_reset) {
|
||||
gpiod_set_value(st->gpio_reset, 1);
|
||||
@ -60,6 +60,7 @@ static int ad7606_reset(struct ad7606_state *st)
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606);
|
||||
|
||||
static int ad7606_reg_access(struct iio_dev *indio_dev,
|
||||
unsigned int reg,
|
||||
@ -88,31 +89,6 @@ static int ad7606_read_samples(struct ad7606_state *st)
|
||||
{
|
||||
unsigned int num = st->chip_info->num_channels - 1;
|
||||
u16 *data = st->data;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* The frstdata signal is set to high while and after reading the sample
|
||||
* of the first channel and low for all other channels. This can be used
|
||||
* to check that the incoming data is correctly aligned. During normal
|
||||
* operation the data should never become unaligned, but some glitch or
|
||||
* electrostatic discharge might cause an extra read or clock cycle.
|
||||
* Monitoring the frstdata signal allows to recover from such failure
|
||||
* situations.
|
||||
*/
|
||||
|
||||
if (st->gpio_frstdata) {
|
||||
ret = st->bops->read_block(st->dev, 1, data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!gpiod_get_value(st->gpio_frstdata)) {
|
||||
ad7606_reset(st);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
data++;
|
||||
num--;
|
||||
}
|
||||
|
||||
return st->bops->read_block(st->dev, num, data);
|
||||
}
|
||||
|
@ -151,6 +151,8 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
|
||||
const char *name, unsigned int id,
|
||||
const struct ad7606_bus_ops *bops);
|
||||
|
||||
int ad7606_reset(struct ad7606_state *st);
|
||||
|
||||
enum ad7606_supported_device_ids {
|
||||
ID_AD7605_4,
|
||||
ID_AD7606_8,
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/err.h>
|
||||
@ -21,8 +22,29 @@ static int ad7606_par16_read_block(struct device *dev,
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
|
||||
insw((unsigned long)st->base_address, buf, count);
|
||||
|
||||
/*
|
||||
* On the parallel interface, the frstdata signal is set to high while
|
||||
* and after reading the sample of the first channel and low for all
|
||||
* other channels. This can be used to check that the incoming data is
|
||||
* correctly aligned. During normal operation the data should never
|
||||
* become unaligned, but some glitch or electrostatic discharge might
|
||||
* cause an extra read or clock cycle. Monitoring the frstdata signal
|
||||
* allows to recover from such failure situations.
|
||||
*/
|
||||
int num = count;
|
||||
u16 *_buf = buf;
|
||||
|
||||
if (st->gpio_frstdata) {
|
||||
insw((unsigned long)st->base_address, _buf, 1);
|
||||
if (!gpiod_get_value(st->gpio_frstdata)) {
|
||||
ad7606_reset(st);
|
||||
return -EIO;
|
||||
}
|
||||
_buf++;
|
||||
num--;
|
||||
}
|
||||
insw((unsigned long)st->base_address, _buf, num);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -35,8 +57,28 @@ static int ad7606_par8_read_block(struct device *dev,
|
||||
{
|
||||
struct iio_dev *indio_dev = dev_get_drvdata(dev);
|
||||
struct ad7606_state *st = iio_priv(indio_dev);
|
||||
/*
|
||||
* On the parallel interface, the frstdata signal is set to high while
|
||||
* and after reading the sample of the first channel and low for all
|
||||
* other channels. This can be used to check that the incoming data is
|
||||
* correctly aligned. During normal operation the data should never
|
||||
* become unaligned, but some glitch or electrostatic discharge might
|
||||
* cause an extra read or clock cycle. Monitoring the frstdata signal
|
||||
* allows to recover from such failure situations.
|
||||
*/
|
||||
int num = count;
|
||||
u16 *_buf = buf;
|
||||
|
||||
insb((unsigned long)st->base_address, buf, count * 2);
|
||||
if (st->gpio_frstdata) {
|
||||
insb((unsigned long)st->base_address, _buf, 2);
|
||||
if (!gpiod_get_value(st->gpio_frstdata)) {
|
||||
ad7606_reset(st);
|
||||
return -EIO;
|
||||
}
|
||||
_buf++;
|
||||
num--;
|
||||
}
|
||||
insb((unsigned long)st->base_address, _buf, num * 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -569,7 +569,7 @@ EXPORT_SYMBOL_NS_GPL(ad_sd_validate_trigger, IIO_AD_SIGMA_DELTA);
|
||||
static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev)
|
||||
{
|
||||
struct ad_sigma_delta *sigma_delta = iio_device_get_drvdata(indio_dev);
|
||||
unsigned long irq_flags = irq_get_trigger_type(sigma_delta->spi->irq);
|
||||
unsigned long irq_flags = irq_get_trigger_type(sigma_delta->irq_line);
|
||||
int ret;
|
||||
|
||||
if (dev != &sigma_delta->spi->dev) {
|
||||
|
@ -735,7 +735,7 @@ static int ads1119_probe(struct i2c_client *client)
|
||||
if (client->irq > 0) {
|
||||
ret = devm_request_threaded_irq(dev, client->irq,
|
||||
ads1119_irq_handler,
|
||||
NULL, IRQF_TRIGGER_FALLING,
|
||||
NULL, IRQF_ONESHOT,
|
||||
"ads1119", indio_dev);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
|
@ -237,7 +237,7 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
|
||||
|
||||
ret = dma_get_slave_caps(chan, &caps);
|
||||
if (ret < 0)
|
||||
goto err_free;
|
||||
goto err_release;
|
||||
|
||||
/* Needs to be aligned to the maximum of the minimums */
|
||||
if (caps.src_addr_widths)
|
||||
@ -263,6 +263,8 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct device *dev,
|
||||
|
||||
return &dmaengine_buffer->queue.buffer;
|
||||
|
||||
err_release:
|
||||
dma_release_channel(chan);
|
||||
err_free:
|
||||
kfree(dmaengine_buffer);
|
||||
return ERR_PTR(ret);
|
||||
|
@ -248,12 +248,20 @@ static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p)
|
||||
int result;
|
||||
|
||||
switch (st->chip_type) {
|
||||
case INV_MPU6000:
|
||||
case INV_MPU6050:
|
||||
case INV_MPU9150:
|
||||
/*
|
||||
* WoM is not supported and interrupt status read seems to be broken for
|
||||
* some chips. Since data ready is the only interrupt, bypass interrupt
|
||||
* status read and always assert data ready bit.
|
||||
*/
|
||||
wom_bits = 0;
|
||||
int_status = INV_MPU6050_BIT_RAW_DATA_RDY_INT;
|
||||
goto data_ready_interrupt;
|
||||
case INV_MPU6500:
|
||||
case INV_MPU6515:
|
||||
case INV_MPU6880:
|
||||
case INV_MPU6000:
|
||||
case INV_MPU9150:
|
||||
case INV_MPU9250:
|
||||
case INV_MPU9255:
|
||||
wom_bits = INV_MPU6500_BIT_WOM_INT;
|
||||
@ -279,6 +287,7 @@ static irqreturn_t inv_mpu6050_interrupt_handle(int irq, void *p)
|
||||
}
|
||||
}
|
||||
|
||||
data_ready_interrupt:
|
||||
/* handle raw data interrupt */
|
||||
if (int_status & INV_MPU6050_BIT_RAW_DATA_RDY_INT) {
|
||||
indio_dev->pollfunc->timestamp = st->it_timestamp;
|
||||
|
@ -647,17 +647,17 @@ static int iio_convert_raw_to_processed_unlocked(struct iio_channel *chan,
|
||||
break;
|
||||
case IIO_VAL_INT_PLUS_MICRO:
|
||||
if (scale_val2 < 0)
|
||||
*processed = -raw64 * scale_val;
|
||||
*processed = -raw64 * scale_val * scale;
|
||||
else
|
||||
*processed = raw64 * scale_val;
|
||||
*processed = raw64 * scale_val * scale;
|
||||
*processed += div_s64(raw64 * (s64)scale_val2 * scale,
|
||||
1000000LL);
|
||||
break;
|
||||
case IIO_VAL_INT_PLUS_NANO:
|
||||
if (scale_val2 < 0)
|
||||
*processed = -raw64 * scale_val;
|
||||
*processed = -raw64 * scale_val * scale;
|
||||
else
|
||||
*processed = raw64 * scale_val;
|
||||
*processed = raw64 * scale_val * scale;
|
||||
*processed += div_s64(raw64 * (s64)scale_val2 * scale,
|
||||
1000000000LL);
|
||||
break;
|
||||
|
@ -1910,7 +1910,8 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
|
||||
&args[0]);
|
||||
if (err) {
|
||||
dev_err(dev, "mmap error (len 0x%08llx)\n", buf->size);
|
||||
goto err_invoke;
|
||||
fastrpc_buf_free(buf);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* update the buffer to be able to deallocate the memory on the DSP */
|
||||
@ -1948,8 +1949,6 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
|
||||
|
||||
err_assign:
|
||||
fastrpc_req_munmap_impl(fl, buf);
|
||||
err_invoke:
|
||||
fastrpc_buf_free(buf);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -212,12 +212,12 @@ static ssize_t keep_cfg_store(struct device *dev, struct device_attribute *attr,
|
||||
}
|
||||
static DEVICE_ATTR_RW(keep_cfg);
|
||||
|
||||
static struct attribute *attrs[] = {
|
||||
static struct attribute *cp500_attrs[] = {
|
||||
&dev_attr_version.attr,
|
||||
&dev_attr_keep_cfg.attr,
|
||||
NULL
|
||||
};
|
||||
static const struct attribute_group attrs_group = { .attrs = attrs };
|
||||
ATTRIBUTE_GROUPS(cp500);
|
||||
|
||||
static void cp500_i2c_release(struct device *dev)
|
||||
{
|
||||
@ -396,20 +396,15 @@ static int cp500_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
|
||||
|
||||
pci_set_drvdata(pci_dev, cp500);
|
||||
|
||||
ret = sysfs_create_group(&pci_dev->dev.kobj, &attrs_group);
|
||||
if (ret != 0)
|
||||
goto out_free_irq;
|
||||
|
||||
ret = cp500_enable(cp500);
|
||||
if (ret != 0)
|
||||
goto out_remove_group;
|
||||
goto out_free_irq;
|
||||
|
||||
cp500_register_auxiliary_devs(cp500);
|
||||
|
||||
return 0;
|
||||
|
||||
out_remove_group:
|
||||
sysfs_remove_group(&pci_dev->dev.kobj, &attrs_group);
|
||||
out_free_irq:
|
||||
pci_free_irq_vectors(pci_dev);
|
||||
out_disable:
|
||||
@ -427,8 +422,6 @@ static void cp500_remove(struct pci_dev *pci_dev)
|
||||
|
||||
cp500_disable(cp500);
|
||||
|
||||
sysfs_remove_group(&pci_dev->dev.kobj, &attrs_group);
|
||||
|
||||
pci_set_drvdata(pci_dev, 0);
|
||||
|
||||
pci_free_irq_vectors(pci_dev);
|
||||
@ -450,6 +443,7 @@ static struct pci_driver cp500_driver = {
|
||||
.id_table = cp500_ids,
|
||||
.probe = cp500_probe,
|
||||
.remove = cp500_remove,
|
||||
.dev_groups = cp500_groups,
|
||||
};
|
||||
module_pci_driver(cp500_driver);
|
||||
|
||||
|
@ -144,7 +144,8 @@ void vmci_resource_remove(struct vmci_resource *resource)
|
||||
spin_lock(&vmci_resource_table.lock);
|
||||
|
||||
hlist_for_each_entry(r, &vmci_resource_table.entries[idx], node) {
|
||||
if (vmci_handle_is_equal(r->handle, resource->handle)) {
|
||||
if (vmci_handle_is_equal(r->handle, resource->handle) &&
|
||||
resource->type == r->type) {
|
||||
hlist_del_init_rcu(&r->node);
|
||||
break;
|
||||
}
|
||||
|
@ -1276,13 +1276,13 @@ void nvmem_device_put(struct nvmem_device *nvmem)
|
||||
EXPORT_SYMBOL_GPL(nvmem_device_put);
|
||||
|
||||
/**
|
||||
* devm_nvmem_device_get() - Get nvmem cell of device form a given id
|
||||
* devm_nvmem_device_get() - Get nvmem device of device form a given id
|
||||
*
|
||||
* @dev: Device that requests the nvmem device.
|
||||
* @id: name id for the requested nvmem device.
|
||||
*
|
||||
* Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
|
||||
* on success. The nvmem_cell will be freed by the automatically once the
|
||||
* Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
|
||||
* on success. The nvmem_device will be freed by the automatically once the
|
||||
* device is freed.
|
||||
*/
|
||||
struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
|
||||
|
@ -176,6 +176,13 @@ static int u_boot_env_parse(struct u_boot_env *priv)
|
||||
data_offset = offsetof(struct u_boot_env_image_broadcom, data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev_size < data_offset) {
|
||||
dev_err(dev, "Device too small for u-boot-env\n");
|
||||
err = -EIO;
|
||||
goto err_kfree;
|
||||
}
|
||||
|
||||
crc32_addr = (__le32 *)(buf + crc32_offset);
|
||||
crc32 = le32_to_cpu(*crc32_addr);
|
||||
crc32_data_len = dev_size - crc32_data_offset;
|
||||
|
@ -114,7 +114,7 @@ static int ad9834_write_frequency(struct ad9834_state *st,
|
||||
|
||||
clk_freq = clk_get_rate(st->mclk);
|
||||
|
||||
if (fout > (clk_freq / 2))
|
||||
if (!clk_freq || fout > (clk_freq / 2))
|
||||
return -EINVAL;
|
||||
|
||||
regval = ad9834_calc_freqreg(clk_freq, fout);
|
||||
|
@ -106,10 +106,11 @@ static void hv_uio_channel_cb(void *context)
|
||||
|
||||
/*
|
||||
* Callback from vmbus_event when channel is rescinded.
|
||||
* It is meant for rescind of primary channels only.
|
||||
*/
|
||||
static void hv_uio_rescind(struct vmbus_channel *channel)
|
||||
{
|
||||
struct hv_device *hv_dev = channel->primary_channel->device_obj;
|
||||
struct hv_device *hv_dev = channel->device_obj;
|
||||
struct hv_uio_private_data *pdata = hv_get_drvdata(hv_dev);
|
||||
|
||||
/*
|
||||
@ -120,6 +121,14 @@ static void hv_uio_rescind(struct vmbus_channel *channel)
|
||||
|
||||
/* Wake up reader */
|
||||
uio_event_notify(&pdata->info);
|
||||
|
||||
/*
|
||||
* With rescind callback registered, rescind path will not unregister the device
|
||||
* from vmbus when the primary channel is rescinded.
|
||||
* Without it, rescind handling is incomplete and next onoffer msg does not come.
|
||||
* Unregister the device from vmbus here.
|
||||
*/
|
||||
vmbus_device_unregister(channel->device_obj);
|
||||
}
|
||||
|
||||
/* Sysfs API to allow mmap of the ring buffers
|
||||
|
Loading…
Reference in New Issue
Block a user