Re: [PATCH v4 3/4] iio: hid-sensor-magn-3d: Scan for usage attributes before setting up iio channels

From: Srinivas Pandruvada
Date: Mon Jul 07 2014 - 15:58:55 EST


Hi Reyad,

I see panic in the probe function. Can you review your logic?
It is possible that platforms don't have all attributes, so looks
like the probe is returnning with error.

On 07/07/2014 09:44 AM, Jonathan Cameron wrote:
On 30/06/14 03:58, Reyad Attiyat wrote:
Scan for and count the HID usage attributes supported by the driver.
This allows for the driver to only setup the IIO channels for the
sensor usages present in the HID USB reports.

Signed-off-by: Reyad Attiyat <reyad.attiyat@xxxxxxxxx>
---
There should be an explanation here of what has changed from one version
to the
next.

The patches should have been run through checkpatch.pl (at least one
place below
indicates that didn't happen).

Mostly little bits left. Now I would definitely like an ack or reviewed-by
from Srinivas for this one if at all possible.

[ 7.653643] BUG: unable to handle kernel NULL pointer dereference at 0000000000000031
[ 7.653648] IP: [<ffffffff81242cee>] sysfs_remove_link+0xe/0x30
[ 7.653650] PGD 13d0fd067 PUD 147cbd067 PMD 0
[ 7.653652] Oops: 0000 [#1] SMP
[ 7.653676] Modules linked in: hid_sensor_magn_3d(+) hid_sensor_rotation hid_sensor_gyro_3d hid_sensor_trigger industrialio_triggered_buffer kfifo_buf industrialio asix(+) usb_storage hid_sensor_iio_common usbnet usbhid mii joydev usbserial(+) hid_rmi(+) intel_rapl x86_pkg_temp_thermal uvcvideo intel_powerclamp coretemp kvm_intel videobuf2_vmalloc videobuf2_memops videobuf2_core iwlwifi kvm v4l2_common videodev hid_multitouch hid_sensor_hub ppdev btusb crct10dif_pclmul cfg80211 crc32_pclmul ghash_clmulni_intel aesni_intel aes_x86_64 lrw gf128mul glue_helper ablk_helper cryptd mei_me(+) mei serio_raw lpc_ich(+) i915(+) snd_hda_codec_realtek snd_hda_codec_generic snd_hda_intel snd_hda_controller snd_hda_codec snd_hwdep snd_pcm snd_seq_midi drm_kms_helper snd_seq_midi_event snd_rawmidi snd_seq drm snd_seq_device snd_timer snd soundcore i2c_algo_bit mac_hid nfsd i2c_hid hid auth_rpcgss nfs_acl rfcomm nfs bnep bluetooth lockd winbond_cir sunrpc rc_core parport_pc dw_dmac dw_dmac_core video i2c_designware_platform spi_pxa2xx_platform i2c_designware_core binfmt_misc 8250_dw fscache lp nls_iso8859_1 parport ahci libahci sdhci_acpi sdhci
[ 7.653691] CPU: 1 PID: 372 Comm: systemd-udevd Not tainted 3.16.0-rc4+ #27
[ 7.653692] Hardware name: Intel Corporation Shark Bay Client platform/Harris Beach SDS, BIOS HSWLPTU1.86C.0133.R00.1309172123 09/17/2013
[ 7.653693] task: ffff880148584b60 ti: ffff880148914000 task.ti: ffff880148914000
[ 7.653696] RIP: 0010:[<ffffffff81242cee>] [<ffffffff81242cee>] sysfs_remove_link+0xe/0x30
[ 7.653697] RSP: 0018:ffff880148917c30 EFLAGS: 00010202
[ 7.653698] RAX: ffffffffa08a1028 RBX: ffff880090bef810 RCX: 0000000000001043
[ 7.653698] RDX: 0000000000001042 RSI: 0000000000000000 RDI: 0000000000000001
[ 7.653699] RBP: ffff880148917c30 R08: 00000000000171c0 R09: ffff88014f2571c0
[ 7.653700] R10: ffffea0002ac20c0 R11: ffffffff814a48a9 R12: 00000000fffffff0
[ 7.653701] R13: ffffffffa08a1028 R14: 0000000000000025 R15: 0000000000000001
[ 7.653702] FS: 00007fd70e437880(0000) GS:ffff88014f240000(0000) knlGS:0000000000000000
[ 7.653703] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 7.653704] CR2: 0000000000000031 CR3: 000000013d05e000 CR4: 00000000001407e0
[ 7.653705] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 7.653706] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 7.653706] Stack:
[ 7.653708] ffff880148917c48 ffffffff814a0626 ffff880090bef810 ffff880148917c78
[ 7.653710] ffffffff814a0c2e ffff880090bef810 ffffffffa08a1028 ffff880090bef870
[ 7.653712] 0000000000000000 ffff880148917ca0 ffffffff814a1053 0000000000000000
[ 7.653712] Call Trace:
[ 7.653716] [<ffffffff814a0626>] driver_sysfs_remove+0x26/0x40
[ 7.653719] [<ffffffff814a0c2e>] driver_probe_device+0x8e/0x3e0
[ 7.653720] [<ffffffff814a1053>] __driver_attach+0x93/0xa0
[ 7.653722] [<ffffffff814a0fc0>] ? __device_attach+0x40/0x40
[ 7.653725] [<ffffffff8149ec93>] bus_for_each_dev+0x63/0xa0
[ 7.653727] [<ffffffff814a06ce>] driver_attach+0x1e/0x20
[ 7.653728] [<ffffffff814a02e0>] bus_add_driver+0x180/0x250
[ 7.653731] [<ffffffffa005b000>] ? 0xffffffffa005afff
[ 7.653733] [<ffffffff814a1834>] driver_register+0x64/0xf0
[ 7.653735] [<ffffffff814a2dca>] __platform_driver_register+0x4a/0x50
[ 7.653737] [<ffffffffa005b017>] hid_magn_3d_platform_driver_init+0x17/0x1000 [hid_sensor_magn_3d]
[ 7.653741] [<ffffffff8100212c>] do_one_initcall+0xbc/0x1f0
[ 7.653744] [<ffffffff811b239d>] ? kfree+0xfd/0x140
[ 7.653747] [<ffffffff811996f2>] ? __vunmap+0xb2/0x100
[ 7.653750] [<ffffffff810eaf0c>] load_module+0x1cec/0x2700
[ 7.653752] [<ffffffff810e6e10>] ? store_uevent+0x40/0x40
[ 7.653755] [<ffffffff810e79f1>] ? copy_module_from_fd.isra.46+0x121/0x180
[ 7.653757] [<ffffffff810eba96>] SyS_finit_module+0x86/0xb0
[ 7.653761] [<ffffffff8173f73f>] tracesys+0xe1/0xe6
[ 7.653779] Code: 48 8b 35 8e 16 d5 00 48 8b 57 10 e8 0d de ff ff 5d c3 66 2e 0f 1f 84 00 00 00 00 00 90 0f 1f 44 00 00 55 48 85 ff 48 89 e5 74 12 <48> 8b 7f 30 31 d2 e8 47 dd ff ff 5d c3 0f 1f 44 00 00 48 8b 3d
[ 7.653781] RIP [<ffffffff81242cee>] sysfs_remove_link+0xe/0x30
[ 7.653782] RSP <ffff880148917c30>
[ 7.653782] CR2: 0000000000000031
[ 7.653785] ---[ end trace 05dd86b8f35f8800 ]---


Other changes, as suggested by Jontahan regarding format, one more
on iio_val in the structure magn_3d_state.


Any tested-bys, particularly with parts that don't have the new channel
types, would also be good.

Jonathan
drivers/iio/magnetometer/hid-sensor-magn-3d.c | 111
+++++++++++++++++---------
1 file changed, 75 insertions(+), 36 deletions(-)

diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index 41cf29e..070d20e 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -42,7 +42,8 @@ struct magn_3d_state {
struct hid_sensor_hub_callbacks callbacks;
struct hid_sensor_common common_attributes;
struct hid_sensor_hub_attribute_info magn[MAGN_3D_CHANNEL_MAX];
- u32 magn_val[MAGN_3D_CHANNEL_MAX];
+ u32 *magn_val_addr[MAGN_3D_CHANNEL_MAX];
+ u32 *iio_val;
I prefer iio_vals, as this stores all the values not a single value.

Thanks,
Srinivas
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
@@ -221,8 +222,8 @@ static int magn_3d_proc_event(struct
hid_sensor_hub_device *hsdev,
dev_dbg(&indio_dev->dev, "magn_3d_proc_event\n");
if (atomic_read(&magn_state->common_attributes.data_ready))
hid_sensor_push_data(indio_dev,
- magn_state->magn_val,
- sizeof(magn_state->magn_val));
+ magn_state->iio_val,
+ sizeof(magn_state->iio_val));

return 0;
}
@@ -236,52 +237,99 @@ static int magn_3d_capture_sample(struct
hid_sensor_hub_device *hsdev,
struct iio_dev *indio_dev = platform_get_drvdata(priv);
struct magn_3d_state *magn_state = iio_priv(indio_dev);
int offset;
- int ret = -EINVAL;
+ int ret = 0;
+ u32 *iio_val = NULL;
This has me a little confused. You have an iio_val in your state
structure and in this function. I can't actually find anywhere where
the elements of the one in the state structure are ever assigned to
anything.


switch (usage_id) {
case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS:
case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Y_AXIS:
case HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_Z_AXIS:
offset = usage_id - HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS;
- magn_state->magn_val[CHANNEL_SCAN_INDEX_X + offset] =
- *(u32 *)raw_data;
- ret = 0;
+ iio_val = magn_state->magn_val_addr[CHANNEL_SCAN_INDEX_X +
offset];
+
break;
default:
- break;
+ return -EINVAL;
}

+ if(iio_val)
white space after if please.
+ *iio_val = *(u32 *)raw_data;
+ else
+ ret = -EINVAL;
+
return ret;
}

/* Parse report which is specific to an usage id*/
static int magn_3d_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
- struct iio_chan_spec *channels,
+ struct iio_chan_spec **channels,
+ int *chan_count,
unsigned usage_id,
struct magn_3d_state *st)
{
- int ret;
+ int ret = 0;
int i;
+ int attr_count = 0;
+
+ /* Scan for each usage attribute supported */
+ for (i = 0; i < MAGN_3D_CHANNEL_MAX; i++) {
+ u32 address = magn_3d_addresses[i];

- for (i = 0; i <= CHANNEL_SCAN_INDEX_Z; ++i) {
+ /* Check if usage attribute exists in the sensor hub device */
ret = sensor_hub_input_get_attribute_info(hsdev,
- HID_INPUT_REPORT,
- usage_id,
- HID_USAGE_SENSOR_ORIENT_MAGN_FLUX_X_AXIS + i,
- &st->magn[CHANNEL_SCAN_INDEX_X + i]);
- if (ret < 0)
- break;
- magn_3d_adjust_channel_bit_mask(channels,
- CHANNEL_SCAN_INDEX_X + i,
- st->magn[CHANNEL_SCAN_INDEX_X + i].size);
I would have preferred you kept the indenting the same as before. That
would
make it more obvious what changed.
+ HID_INPUT_REPORT,
+ usage_id,
+ address,
+ &(st->magn[i]));
+ if (!ret)
+ attr_count++;
}
- dev_dbg(&pdev->dev, "magn_3d %x:%x, %x:%x, %x:%x\n",
+
+ dev_dbg(&pdev->dev, "magn_3d Found %d usage attributes\n",
+ attr_count);
+ dev_dbg(&pdev->dev, "magn_3d X: %x:%x Y: %x:%x Z: %x:%x\n",
st->magn[0].index,
st->magn[0].report_id,
st->magn[1].index, st->magn[1].report_id,
st->magn[2].index, st->magn[2].report_id);

+ if (attr_count > 0)
+ ret = 0;
This would suggest to me that you want to rename the ret above (used
to indicate if a channel is there) as something more specific so you
don't end up appearing to squash and error here...
+ else
+ return -EINVAL;
Again your spacing is messed up. Please fix.
+
+ /* Setup IIO channel array */
+ *channels = devm_kcalloc(&pdev->dev, attr_count,
+
The resulting indenting here is a complete mess. Please fix.
sizeof(struct iio_chan_spec),
+ GFP_KERNEL);
+ if (!*channels) {
+ dev_err(&pdev->dev, "failed to allocate space for iio
channels\n");
+ return -ENOMEM;
+ }
+
+ st->iio_val = devm_kcalloc(&pdev->dev, attr_count,
+ sizeof(u32),
+ GFP_KERNEL);
+ if (!st->iio_val) {
+ dev_err(&pdev->dev, "failed to allocate space for iio values
array\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0, *chan_count = 0;
+ i < MAGN_3D_CHANNEL_MAX && *chan_count < attr_count;
+ i++)
+ {
+ if (st->magn[i].index >= 0) {
+ /* Setup IIO channel struct */
+ *channels[*chan_count] = magn_3d_channels[i];
+
+ st->magn_val_addr[i] = &(st->iio_val[*chan_count]);
+ magn_3d_adjust_channel_bit_mask(*channels, *chan_count,
st->magn[i].size);
The above should be wrapped appropriately.
+ (*chan_count)++;
+ }
+ }
+
st->scale_precision = hid_sensor_format_scale(
HID_USAGE_SENSOR_COMPASS_3D,
&st->magn[CHANNEL_SCAN_INDEX_X],
@@ -311,6 +359,7 @@ static int hid_magn_3d_probe(struct
platform_device *pdev)
struct magn_3d_state *magn_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
+ int chan_count = 0;

indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct magn_3d_state));
@@ -331,22 +380,15 @@ static int hid_magn_3d_probe(struct
platform_device *pdev)
return ret;
}

- channels = kmemdup(magn_3d_channels, sizeof(magn_3d_channels),
- GFP_KERNEL);
- if (!channels) {
- dev_err(&pdev->dev, "failed to duplicate channels\n");
- return -ENOMEM;
- }
-
- ret = magn_3d_parse_report(pdev, hsdev, channels,
- HID_USAGE_SENSOR_COMPASS_3D, magn_state);
+ ret = magn_3d_parse_report(pdev, hsdev, &channels,
+ &chan_count, HID_USAGE_SENSOR_COMPASS_3D, magn_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
- goto error_free_dev_mem;
+ return ret;
}

indio_dev->channels = channels;
- indio_dev->num_channels = ARRAY_SIZE(magn_3d_channels);
+ indio_dev->num_channels = chan_count;
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &magn_3d_info;
indio_dev->name = name;
@@ -356,7 +398,7 @@ static int hid_magn_3d_probe(struct
platform_device *pdev)
NULL, NULL);
if (ret) {
dev_err(&pdev->dev, "failed to initialize trigger buffer\n");
- goto error_free_dev_mem;
+ return ret;
}
atomic_set(&magn_state->common_attributes.data_ready, 0);
ret = hid_sensor_setup_trigger(indio_dev, name,
@@ -390,8 +432,6 @@ error_remove_trigger:
hid_sensor_remove_trigger(&magn_state->common_attributes);
error_unreg_buffer_funcs:
iio_triggered_buffer_cleanup(indio_dev);
-error_free_dev_mem:
- kfree(indio_dev->channels);
return ret;
}

@@ -406,7 +446,6 @@ static int hid_magn_3d_remove(struct
platform_device *pdev)
iio_device_unregister(indio_dev);
hid_sensor_remove_trigger(&magn_state->common_attributes);
iio_triggered_buffer_cleanup(indio_dev);
- kfree(indio_dev->channels);

return 0;
}




--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/