Commit 914a1fe5 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc/IIO driver fixes from Greg KH:
 "Here are a bunch of small driver fixes (mostly all IIO) for 6.15-rc6.
  Included in here are:

   - loads of tiny IIO driver fixes for reported issues

   - hyperv driver fix for a much-reported and worked on sysfs ring
     buffer creation bug

  All of these have been in linux-next for over a week (the IIO ones for
  many weeks now), with no reported issues"

* tag 'char-misc-6.15-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (30 commits)
  Drivers: hv: Make the sysfs node size for the ring buffer dynamic
  uio_hv_generic: Fix sysfs creation path for ring buffer
  iio: adis16201: Correct inclinometer channel resolution
  iio: adc: ad7606: fix serial register access
  iio: pressure: mprls0025pa: use aligned_s64 for timestamp
  iio: imu: adis16550: align buffers for timestamp
  staging: iio: adc: ad7816: Correct conditional logic for store mode
  iio: adc: ad7266: Fix potential timestamp alignment issue.
  iio: adc: ad7768-1: Fix insufficient alignment of timestamp.
  iio: adc: dln2: Use aligned_s64 for timestamp
  iio: accel: adxl355: Make timestamp 64-bit aligned using aligned_s64
  iio: temp: maxim-thermocouple: Fix potential lack of DMA safe buffer.
  iio: chemical: pms7003: use aligned_s64 for timestamp
  iio: chemical: sps30: use aligned_s64 for timestamp
  iio: imu: inv_mpu6050: align buffer for timestamp
  iio: imu: st_lsm6dsx: Fix wakeup source leaks on device unbind
  iio: adc: qcom-spmi-iadc: Fix wakeup source leaks on device unbind
  iio: accel: fxls8962af: Fix wakeup source leaks on device unbind
  iio: adc: ad7380: fix event threshold shift
  iio: hid-sensor-prox: Fix incorrect OFFSET calculation
  ...
parents ed36b437 65995e97
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -477,4 +477,10 @@ static inline int hv_debug_add_dev_dir(struct hv_device *dev)

#endif /* CONFIG_HYPERV_TESTING */

/* Create and remove sysfs entry for memory mapped ring buffers for a channel */
int hv_create_ring_sysfs(struct vmbus_channel *channel,
			 int (*hv_mmap_ring_buffer)(struct vmbus_channel *channel,
						    struct vm_area_struct *vma));
int hv_remove_ring_sysfs(struct vmbus_channel *channel);

#endif /* _HYPERV_VMBUS_H */
+108 −1
Original line number Diff line number Diff line
@@ -1802,6 +1802,26 @@ static ssize_t subchannel_id_show(struct vmbus_channel *channel,
}
static VMBUS_CHAN_ATTR_RO(subchannel_id);

static int hv_mmap_ring_buffer_wrapper(struct file *filp, struct kobject *kobj,
				       const struct bin_attribute *attr,
				       struct vm_area_struct *vma)
{
	struct vmbus_channel *channel = container_of(kobj, struct vmbus_channel, kobj);

	/*
	 * hv_(create|remove)_ring_sysfs implementation ensures that mmap_ring_buffer
	 * is not NULL.
	 */
	return channel->mmap_ring_buffer(channel, vma);
}

static struct bin_attribute chan_attr_ring_buffer = {
	.attr = {
		.name = "ring",
		.mode = 0600,
	},
	.mmap = hv_mmap_ring_buffer_wrapper,
};
static struct attribute *vmbus_chan_attrs[] = {
	&chan_attr_out_mask.attr,
	&chan_attr_in_mask.attr,
@@ -1821,6 +1841,11 @@ static struct attribute *vmbus_chan_attrs[] = {
	NULL
};

static struct bin_attribute *vmbus_chan_bin_attrs[] = {
	&chan_attr_ring_buffer,
	NULL
};

/*
 * Channel-level attribute_group callback function. Returns the permission for
 * each attribute, and returns 0 if an attribute is not visible.
@@ -1841,9 +1866,34 @@ static umode_t vmbus_chan_attr_is_visible(struct kobject *kobj,
	return attr->mode;
}

static umode_t vmbus_chan_bin_attr_is_visible(struct kobject *kobj,
					      const struct bin_attribute *attr, int idx)
{
	const struct vmbus_channel *channel =
		container_of(kobj, struct vmbus_channel, kobj);

	/* Hide ring attribute if channel's ring_sysfs_visible is set to false */
	if (attr ==  &chan_attr_ring_buffer && !channel->ring_sysfs_visible)
		return 0;

	return attr->attr.mode;
}

static size_t vmbus_chan_bin_size(struct kobject *kobj,
				  const struct bin_attribute *bin_attr, int a)
{
	const struct vmbus_channel *channel =
		container_of(kobj, struct vmbus_channel, kobj);

	return channel->ringbuffer_pagecount << PAGE_SHIFT;
}

static const struct attribute_group vmbus_chan_group = {
	.attrs = vmbus_chan_attrs,
	.is_visible = vmbus_chan_attr_is_visible
	.bin_attrs = vmbus_chan_bin_attrs,
	.is_visible = vmbus_chan_attr_is_visible,
	.is_bin_visible = vmbus_chan_bin_attr_is_visible,
	.bin_size = vmbus_chan_bin_size,
};

static const struct kobj_type vmbus_chan_ktype = {
@@ -1851,6 +1901,63 @@ static const struct kobj_type vmbus_chan_ktype = {
	.release = vmbus_chan_release,
};

/**
 * hv_create_ring_sysfs() - create "ring" sysfs entry corresponding to ring buffers for a channel.
 * @channel: Pointer to vmbus_channel structure
 * @hv_mmap_ring_buffer: function pointer for initializing the function to be called on mmap of
 *                       channel's "ring" sysfs node, which is for the ring buffer of that channel.
 *                       Function pointer is of below type:
 *                       int (*hv_mmap_ring_buffer)(struct vmbus_channel *channel,
 *                                                  struct vm_area_struct *vma))
 *                       This has a pointer to the channel and a pointer to vm_area_struct,
 *                       used for mmap, as arguments.
 *
 * Sysfs node for ring buffer of a channel is created along with other fields, however its
 * visibility is disabled by default. Sysfs creation needs to be controlled when the use-case
 * is running.
 * For example, HV_NIC device is used either by uio_hv_generic or hv_netvsc at any given point of
 * time, and "ring" sysfs is needed only when uio_hv_generic is bound to that device. To avoid
 * exposing the ring buffer by default, this function is reponsible to enable visibility of
 * ring for userspace to use.
 * Note: Race conditions can happen with userspace and it is not encouraged to create new
 * use-cases for this. This was added to maintain backward compatibility, while solving
 * one of the race conditions in uio_hv_generic while creating sysfs.
 *
 * Returns 0 on success or error code on failure.
 */
int hv_create_ring_sysfs(struct vmbus_channel *channel,
			 int (*hv_mmap_ring_buffer)(struct vmbus_channel *channel,
						    struct vm_area_struct *vma))
{
	struct kobject *kobj = &channel->kobj;

	channel->mmap_ring_buffer = hv_mmap_ring_buffer;
	channel->ring_sysfs_visible = true;

	return sysfs_update_group(kobj, &vmbus_chan_group);
}
EXPORT_SYMBOL_GPL(hv_create_ring_sysfs);

/**
 * hv_remove_ring_sysfs() - remove ring sysfs entry corresponding to ring buffers for a channel.
 * @channel: Pointer to vmbus_channel structure
 *
 * Hide "ring" sysfs for a channel by changing its is_visible attribute and updating sysfs group.
 *
 * Returns 0 on success or error code on failure.
 */
int hv_remove_ring_sysfs(struct vmbus_channel *channel)
{
	struct kobject *kobj = &channel->kobj;
	int ret;

	channel->ring_sysfs_visible = false;
	ret = sysfs_update_group(kobj, &vmbus_chan_group);
	channel->mmap_ring_buffer = NULL;
	return ret;
}
EXPORT_SYMBOL_GPL(hv_remove_ring_sysfs);

/*
 * vmbus_add_channel_kobj - setup a sub-directory under device/channels
 */
+2 −2
Original line number Diff line number Diff line
@@ -211,9 +211,9 @@ static const struct iio_chan_spec adis16201_channels[] = {
			BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
	ADIS_AUX_ADC_CHAN(ADIS16201_AUX_ADC_REG, ADIS16201_SCAN_AUX_ADC, 0, 12),
	ADIS_INCLI_CHAN(X, ADIS16201_XINCL_OUT_REG, ADIS16201_SCAN_INCLI_X,
			BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
			BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 12),
	ADIS_INCLI_CHAN(Y, ADIS16201_YINCL_OUT_REG, ADIS16201_SCAN_INCLI_Y,
			BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14),
			BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 12),
	IIO_CHAN_SOFT_TIMESTAMP(7)
};

+1 −1
Original line number Diff line number Diff line
@@ -231,7 +231,7 @@ struct adxl355_data {
		u8 transf_buf[3];
		struct {
			u8 buf[14];
			s64 ts;
			aligned_s64 ts;
		} buffer;
	} __aligned(IIO_DMA_MINALIGN);
};
+3 −7
Original line number Diff line number Diff line
@@ -601,18 +601,14 @@ static int _adxl367_set_odr(struct adxl367_state *st, enum adxl367_odr odr)
	if (ret)
		return ret;

	st->odr = odr;

	/* Activity timers depend on ODR */
	ret = _adxl367_set_act_time_ms(st, st->act_time_ms);
	if (ret)
		return ret;

	ret = _adxl367_set_inact_time_ms(st, st->inact_time_ms);
	if (ret)
		return ret;

	st->odr = odr;

	return 0;
	return _adxl367_set_inact_time_ms(st, st->inact_time_ms);
}

static int adxl367_set_odr(struct iio_dev *indio_dev, enum adxl367_odr odr)
Loading