Richard Neumann
Richard Neumann

Reputation: 3361

Getting container of a void pointer

I am currently trying to get rid of a backref I need for the following function:

/**
 * amd_sfh_hid_poll - Updates the input report for a HID device.
 * @work:   The delayed work
 *
 * Polls input reports from the respective HID devices and submits
 * them by invoking hid_input_report() from hid-core.
 */
static void amd_sfh_hid_poll(struct work_struct *work)
{
    struct amd_sfh_hid_data *hid_data;
    struct hid_device *hid;
    size_t size;
    u8 *buf;

    hid_data = container_of(work, struct amd_sfh_hid_data, work.work);
    hid = hid_data->hid;
    size = get_descriptor_size(hid_data->sensor_idx, AMD_SFH_INPUT_REPORT);

    buf = kzalloc(size, GFP_KERNEL);
    if (!buf) {
        hid_err(hid, "Failed to allocate memory for input report!\n");
        goto reschedule;
    }

    size = get_input_report(hid_data->sensor_idx, 1, buf, size,
                            hid_data->cpu_addr);
    if (size < 0) {
        hid_err(hid, "Failed to get input report!\n");
        goto free_buf;
    }

    hid_input_report(hid, HID_INPUT_REPORT, buf, size, 0);

free_buf:
    kfree(buf);
reschedule:
    schedule_delayed_work(&hid_data->work, hid_data->interval);
}

The struct amd_sfh_hid_data is the driver data stored under hid->driver_data for the respective struct hid_device. Within the work queue, I need to access the HID's driver data and from that the HID device, which I currently do by accessing the backref hid = hid_data->hid. I now tried to get rid of the backref by using container_of on the driver data:

hid = container_of((void*)hid_data, struct hid_device, driver_data);

But this results in page faults, as does

hid = container_of((void**)*hid_data, struct hid_device, driver_data);

What is the correct way to get a struct hid_device * given its member void *driver_data using container_of?

Upvotes: 0

Views: 234

Answers (1)

Tsyvarev
Tsyvarev

Reputation: 65928

What is the correct way to get a struct hid_device * given its member void *driver_data using container_of?

No way.

Usage of container_of implies that you have a pointer to a member, not a value of a member, as in your case.

Short example:

struct B;
struct C;

struct A {
   struct B field1;
   struct C* field2;
}

Having a pointer to the field1, using container_of you may got a pointer to the whole struct A object.

Having a value of field2 (even it has a type struct C*, that is pointer), you cannot get a pointer to the struct A object.

Upvotes: 2

Related Questions