staging: most: remove proprietary kobjects

This patch removes the proprietary kobjects used by the driver modules and
replaces them with device structs. The patch is needed to have the driver
being integrated into the kernel's device model.

Signed-off-by: Christian Gromm <christian.gromm@microchip.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Christian Gromm 2017-11-21 15:04:43 +01:00 committed by Greg Kroah-Hartman
parent 2c22cdfb4e
commit 4d5f022f3a
11 changed files with 340 additions and 854 deletions

View file

@ -412,7 +412,6 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
* @iface: pointer to interface instance
* @channel_id: channel index/ID
* @cfg: pointer to actual channel configuration
* @parent: pointer to kobject (needed for sysfs hook-up)
* @name: name of the device to be created
*
* This allocates achannel object and creates the device node in /dev
@ -420,15 +419,14 @@ static int aim_tx_completion(struct most_interface *iface, int channel_id)
* Returns 0 on success or error code otherwise.
*/
static int aim_probe(struct most_interface *iface, int channel_id,
struct most_channel_config *cfg,
struct kobject *parent, char *name)
struct most_channel_config *cfg, char *name)
{
struct aim_channel *c;
unsigned long cl_flags;
int retval;
int current_minor;
if ((!iface) || (!cfg) || (!parent) || (!name)) {
if ((!iface) || (!cfg) || (!name)) {
pr_info("Probing AIM with bad arguments");
return -EINVAL;
}

File diff suppressed because it is too large Load diff

View file

@ -17,8 +17,8 @@
#define __MOST_CORE_H__
#include <linux/types.h>
#include <linux/device.h>
struct kobject;
struct module;
/**
@ -232,6 +232,7 @@ struct mbo {
* @priv Private field used by mostcore to store context information.
*/
struct most_interface {
struct device dev;
struct module *mod;
enum most_interface_type interface;
const char *description;
@ -249,6 +250,8 @@ struct most_interface {
void *priv;
};
#define to_most_interface(d) container_of(d, struct most_interface, dev)
/**
* struct most_aim - identifies MOST device driver to mostcore
* @name: Driver name
@ -259,10 +262,10 @@ struct most_interface {
* @context: context pointer to be used by mostcore
*/
struct most_aim {
struct device dev;
const char *name;
int (*probe_channel)(struct most_interface *iface, int channel_idx,
struct most_channel_config *cfg,
struct kobject *parent, char *name);
struct most_channel_config *cfg, char *name);
int (*disconnect_channel)(struct most_interface *iface,
int channel_idx);
int (*rx_completion)(struct mbo *mbo);
@ -270,6 +273,8 @@ struct most_aim {
void *context;
};
#define to_most_aim(d) container_of(d, struct most_aim, dev)
/**
* most_register_interface - Registers instance of the interface.
* @iface: Pointer to the interface instance description.
@ -279,7 +284,7 @@ struct most_aim {
* Note: HDM has to ensure that any reference held on the kobj is
* released before deregistering the interface.
*/
struct kobject *most_register_interface(struct most_interface *iface);
int most_register_interface(struct most_interface *iface);
/**
* Deregisters instance of the interface.

View file

@ -87,6 +87,7 @@ struct hdm_channel {
* @atx_idx: index of async tx channel
*/
struct dim2_hdm {
struct device dev;
struct hdm_channel hch[DMA_CHANNELS];
struct most_channel_capability capabilities[DMA_CHANNELS];
struct most_interface most_iface;
@ -738,7 +739,6 @@ static int dim2_probe(struct platform_device *pdev)
struct dim2_hdm *dev;
struct resource *res;
int ret, i;
struct kobject *kobj;
int irq;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
@ -826,17 +826,20 @@ static int dim2_probe(struct platform_device *pdev)
dev->most_iface.enqueue = enqueue;
dev->most_iface.poison_channel = poison_channel;
dev->most_iface.request_netinfo = request_netinfo;
dev->dev.init_name = "dim2_state";
dev->dev.parent = &dev->most_iface.dev;
kobj = most_register_interface(&dev->most_iface);
if (IS_ERR(kobj)) {
ret = PTR_ERR(kobj);
ret = most_register_interface(&dev->most_iface);
if (ret) {
dev_err(&pdev->dev, "failed to register MOST interface\n");
goto err_stop_thread;
}
ret = dim2_sysfs_probe(&dev->bus, kobj);
if (ret)
ret = dim2_sysfs_probe(&dev->dev);
if (ret) {
dev_err(&pdev->dev, "failed to create sysfs attribute\n");
goto err_unreg_iface;
}
ret = startup_dim(pdev);
if (ret) {
@ -847,7 +850,7 @@ static int dim2_probe(struct platform_device *pdev)
return 0;
err_destroy_bus:
dim2_sysfs_destroy(&dev->bus);
dim2_sysfs_destroy(&dev->dev);
err_unreg_iface:
most_deregister_interface(&dev->most_iface);
err_stop_thread:
@ -875,7 +878,7 @@ static int dim2_remove(struct platform_device *pdev)
if (pdata && pdata->destroy)
pdata->destroy(pdata);
dim2_sysfs_destroy(&dev->bus);
dim2_sysfs_destroy(&dev->dev);
most_deregister_interface(&dev->most_iface);
kthread_stop(dev->netinfo_task);

View file

@ -11,99 +11,39 @@
#include <linux/kernel.h>
#include "sysfs.h"
#include <linux/device.h>
struct bus_attr {
struct attribute attr;
ssize_t (*show)(struct medialb_bus *bus, char *buf);
ssize_t (*store)(struct medialb_bus *bus, const char *buf,
size_t count);
};
static ssize_t state_show(struct medialb_bus *bus, char *buf)
static ssize_t state_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
bool state = dim2_sysfs_get_state_cb();
return sprintf(buf, "%s\n", state ? "locked" : "");
}
static struct bus_attr state_attr = __ATTR_RO(state);
DEVICE_ATTR_RO(state);
static struct attribute *bus_default_attrs[] = {
&state_attr.attr,
static struct attribute *dev_attrs[] = {
&dev_attr_state.attr,
NULL,
};
static const struct attribute_group bus_attr_group = {
.attrs = bus_default_attrs,
static struct attribute_group dev_attr_group = {
.attrs = dev_attrs,
};
static void bus_kobj_release(struct kobject *kobj)
{
}
static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct medialb_bus *bus =
container_of(kobj, struct medialb_bus, kobj_group);
struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
if (!xattr->show)
return -EIO;
return xattr->show(bus, buf);
}
static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
const char *buf, size_t count)
{
struct medialb_bus *bus =
container_of(kobj, struct medialb_bus, kobj_group);
struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
if (!xattr->store)
return -EIO;
return xattr->store(bus, buf, count);
}
static struct sysfs_ops const bus_kobj_sysfs_ops = {
.show = bus_kobj_attr_show,
.store = bus_kobj_attr_store,
static const struct attribute_group *dev_attr_groups[] = {
&dev_attr_group,
NULL,
};
static struct kobj_type bus_ktype = {
.release = bus_kobj_release,
.sysfs_ops = &bus_kobj_sysfs_ops,
};
int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
int dim2_sysfs_probe(struct device *dev)
{
int err;
kobject_init(&bus->kobj_group, &bus_ktype);
err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
if (err) {
pr_err("kobject_add() failed: %d\n", err);
goto err_kobject_add;
}
err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
if (err) {
pr_err("sysfs_create_group() failed: %d\n", err);
goto err_create_group;
}
return 0;
err_create_group:
kobject_put(&bus->kobj_group);
err_kobject_add:
return err;
dev->groups = dev_attr_groups;
return device_register(dev);
}
void dim2_sysfs_destroy(struct medialb_bus *bus)
void dim2_sysfs_destroy(struct device *dev)
{
kobject_put(&bus->kobj_group);
device_unregister(dev);
}

View file

@ -16,10 +16,10 @@ struct medialb_bus {
struct kobject kobj_group;
};
struct dim2_hdm;
struct device;
int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
void dim2_sysfs_destroy(struct medialb_bus *bus);
int dim2_sysfs_probe(struct device *dev);
void dim2_sysfs_destroy(struct device *dev);
/*
* callback,

View file

@ -303,7 +303,6 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct hdm_i2c *dev;
int ret, i;
struct kobject *kobj;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
@ -341,11 +340,11 @@ static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev->client = client;
i2c_set_clientdata(client, dev);
kobj = most_register_interface(&dev->most_iface);
if (IS_ERR(kobj)) {
ret = most_register_interface(&dev->most_iface);
if (ret) {
pr_err("Failed to register i2c as a MOST interface\n");
kfree(dev);
return PTR_ERR(kobj);
return ret;
}
dev->polling_mode = polling_req || client->irq <= 0;

View file

@ -291,8 +291,7 @@ static struct net_dev_context *get_net_dev_hold(struct most_interface *iface)
}
static int aim_probe_channel(struct most_interface *iface, int channel_idx,
struct most_channel_config *ccfg,
struct kobject *parent, char *name)
struct most_channel_config *ccfg, char *name)
{
struct net_dev_context *nd;
struct net_dev_channel *ch;

View file

@ -539,7 +539,6 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
* @iface: pointer to interface instance
* @channel_id: channel index/ID
* @cfg: pointer to actual channel configuration
* @parent: pointer to kobject (needed for sysfs hook-up)
* @arg_list: string that provides the name of the device to be created in /dev
* plus the desired audio resolution
*
@ -549,7 +548,7 @@ static int audio_set_hw_params(struct snd_pcm_hardware *pcm_hw,
*/
static int audio_probe_channel(struct most_interface *iface, int channel_id,
struct most_channel_config *cfg,
struct kobject *parent, char *arg_list)
char *arg_list)
{
struct channel *channel;
struct snd_card *card;

View file

@ -64,12 +64,12 @@
* @reg_addr: register address for arbitrary DCI access
*/
struct most_dci_obj {
struct kobject kobj;
struct device dev;
struct usb_device *usb_device;
u16 reg_addr;
};
#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
#define to_dci_obj(p) container_of(p, struct most_dci_obj, dev)
struct most_dev;
@ -84,7 +84,6 @@ struct clear_hold_work {
/**
* struct most_dev - holds all usb interface specific stuff
* @parent: parent object in sysfs
* @usb_device: pointer to usb device
* @iface: hardware interface
* @cap: channel capabilities
@ -102,7 +101,6 @@ struct clear_hold_work {
* @poll_work_obj: work for polling link status
*/
struct most_dev {
struct kobject *parent;
struct usb_device *usb_device;
struct most_interface iface;
struct most_channel_capability *cap;
@ -834,94 +832,6 @@ static const struct usb_device_id usbid[] = {
{ } /* Terminating entry */
};
#define MOST_DCI_RO_ATTR(_name) \
struct most_dci_attribute most_dci_attr_##_name = \
__ATTR(_name, 0444, show_value, NULL)
#define MOST_DCI_ATTR(_name) \
struct most_dci_attribute most_dci_attr_##_name = \
__ATTR(_name, 0644, show_value, store_value)
#define MOST_DCI_WO_ATTR(_name) \
struct most_dci_attribute most_dci_attr_##_name = \
__ATTR(_name, 0200, NULL, store_value)
/**
* struct most_dci_attribute - to access the attributes of a dci object
* @attr: attributes of a dci object
* @show: pointer to the show function
* @store: pointer to the store function
*/
struct most_dci_attribute {
struct attribute attr;
ssize_t (*show)(struct most_dci_obj *d,
struct most_dci_attribute *attr,
char *buf);
ssize_t (*store)(struct most_dci_obj *d,
struct most_dci_attribute *attr,
const char *buf,
size_t count);
};
#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
/**
* dci_attr_show - show function for dci object
* @kobj: pointer to kobject
* @attr: pointer to attribute struct
* @buf: buffer
*/
static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr,
char *buf)
{
struct most_dci_attribute *dci_attr = to_dci_attr(attr);
struct most_dci_obj *dci_obj = to_dci_obj(kobj);
if (!dci_attr->show)
return -EIO;
return dci_attr->show(dci_obj, dci_attr, buf);
}
/**
* dci_attr_store - store function for dci object
* @kobj: pointer to kobject
* @attr: pointer to attribute struct
* @buf: buffer
* @len: length of buffer
*/
static ssize_t dci_attr_store(struct kobject *kobj,
struct attribute *attr,
const char *buf,
size_t len)
{
struct most_dci_attribute *dci_attr = to_dci_attr(attr);
struct most_dci_obj *dci_obj = to_dci_obj(kobj);
if (!dci_attr->store)
return -EIO;
return dci_attr->store(dci_obj, dci_attr, buf, len);
}
static const struct sysfs_ops most_dci_sysfs_ops = {
.show = dci_attr_show,
.store = dci_attr_store,
};
/**
* most_dci_release - release function for dci object
* @kobj: pointer to kobject
*
* This frees the memory allocated for the dci object
*/
static void most_dci_release(struct kobject *kobj)
{
struct most_dci_obj *dci_obj = to_dci_obj(kobj);
kfree(dci_obj);
}
struct regs {
const char *name;
u16 reg;
@ -962,10 +872,11 @@ static int get_stat_reg_addr(const struct regs *regs, int size,
#define get_static_reg_addr(regs, name, reg_addr) \
get_stat_reg_addr(regs, ARRAY_SIZE(regs), name, reg_addr)
static ssize_t show_value(struct most_dci_obj *dci_obj,
struct most_dci_attribute *attr, char *buf)
static ssize_t show_value(struct device *dev, struct device_attribute *attr,
char *buf)
{
const char *name = attr->attr.name;
struct most_dci_obj *dci_obj = to_dci_obj(dev);
u16 val;
u16 reg_addr;
int err;
@ -986,13 +897,13 @@ static ssize_t show_value(struct most_dci_obj *dci_obj,
return snprintf(buf, PAGE_SIZE, "%04x\n", val);
}
static ssize_t store_value(struct most_dci_obj *dci_obj,
struct most_dci_attribute *attr,
static ssize_t store_value(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
u16 val;
u16 reg_addr;
const char *name = attr->attr.name;
struct most_dci_obj *dci_obj = to_dci_obj(dev);
struct usb_device *usb_dev = dci_obj->usb_device;
int err = kstrtou16(buf, 16, &val);
@ -1019,86 +930,49 @@ static ssize_t store_value(struct most_dci_obj *dci_obj,
return count;
}
static MOST_DCI_RO_ATTR(ni_state);
static MOST_DCI_RO_ATTR(packet_bandwidth);
static MOST_DCI_RO_ATTR(node_address);
static MOST_DCI_RO_ATTR(node_position);
static MOST_DCI_WO_ATTR(sync_ep);
static MOST_DCI_ATTR(mep_filter);
static MOST_DCI_ATTR(mep_hash0);
static MOST_DCI_ATTR(mep_hash1);
static MOST_DCI_ATTR(mep_hash2);
static MOST_DCI_ATTR(mep_hash3);
static MOST_DCI_ATTR(mep_eui48_hi);
static MOST_DCI_ATTR(mep_eui48_mi);
static MOST_DCI_ATTR(mep_eui48_lo);
static MOST_DCI_ATTR(arb_address);
static MOST_DCI_ATTR(arb_value);
DEVICE_ATTR(ni_state, 0444, show_value, NULL);
DEVICE_ATTR(packet_bandwidth, 0444, show_value, NULL);
DEVICE_ATTR(node_address, 0444, show_value, NULL);
DEVICE_ATTR(node_position, 0444, show_value, NULL);
DEVICE_ATTR(sync_ep, 0200, NULL, store_value);
DEVICE_ATTR(mep_filter, 0644, show_value, store_value);
DEVICE_ATTR(mep_hash0, 0644, show_value, store_value);
DEVICE_ATTR(mep_hash1, 0644, show_value, store_value);
DEVICE_ATTR(mep_hash2, 0644, show_value, store_value);
DEVICE_ATTR(mep_hash3, 0644, show_value, store_value);
DEVICE_ATTR(mep_eui48_hi, 0644, show_value, store_value);
DEVICE_ATTR(mep_eui48_mi, 0644, show_value, store_value);
DEVICE_ATTR(mep_eui48_lo, 0644, show_value, store_value);
DEVICE_ATTR(arb_address, 0644, show_value, store_value);
DEVICE_ATTR(arb_value, 0644, show_value, store_value);
/**
* most_dci_def_attrs - array of default attribute files of the dci object
*/
static struct attribute *most_dci_def_attrs[] = {
&most_dci_attr_ni_state.attr,
&most_dci_attr_packet_bandwidth.attr,
&most_dci_attr_node_address.attr,
&most_dci_attr_node_position.attr,
&most_dci_attr_sync_ep.attr,
&most_dci_attr_mep_filter.attr,
&most_dci_attr_mep_hash0.attr,
&most_dci_attr_mep_hash1.attr,
&most_dci_attr_mep_hash2.attr,
&most_dci_attr_mep_hash3.attr,
&most_dci_attr_mep_eui48_hi.attr,
&most_dci_attr_mep_eui48_mi.attr,
&most_dci_attr_mep_eui48_lo.attr,
&most_dci_attr_arb_address.attr,
&most_dci_attr_arb_value.attr,
static struct attribute *dci_attrs[] = {
&dev_attr_ni_state.attr,
&dev_attr_packet_bandwidth.attr,
&dev_attr_node_address.attr,
&dev_attr_node_position.attr,
&dev_attr_sync_ep.attr,
&dev_attr_mep_filter.attr,
&dev_attr_mep_hash0.attr,
&dev_attr_mep_hash1.attr,
&dev_attr_mep_hash2.attr,
&dev_attr_mep_hash3.attr,
&dev_attr_mep_eui48_hi.attr,
&dev_attr_mep_eui48_mi.attr,
&dev_attr_mep_eui48_lo.attr,
&dev_attr_arb_address.attr,
&dev_attr_arb_value.attr,
NULL,
};
/**
* DCI ktype
*/
static struct kobj_type most_dci_ktype = {
.sysfs_ops = &most_dci_sysfs_ops,
.release = most_dci_release,
.default_attrs = most_dci_def_attrs,
static struct attribute_group dci_attr_group = {
.attrs = dci_attrs,
};
/**
* create_most_dci_obj - allocates a dci object
* @parent: parent kobject
*
* This creates a dci object and registers it with sysfs.
* Returns a pointer to the object or NULL when something went wrong.
*/
static struct
most_dci_obj *create_most_dci_obj(struct kobject *parent)
{
struct most_dci_obj *most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL);
int retval;
if (!most_dci)
return NULL;
retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent,
"dci");
if (retval) {
kobject_put(&most_dci->kobj);
return NULL;
}
return most_dci;
}
/**
* destroy_most_dci_obj - DCI object release function
* @p: pointer to dci object
*/
static void destroy_most_dci_obj(struct most_dci_obj *p)
{
kobject_put(&p->kobj);
}
static const struct attribute_group *dci_attr_groups[] = {
&dci_attr_group,
NULL,
};
/**
* hdm_probe - probe function of USB device driver
@ -1211,20 +1085,15 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
usb_dev->config->desc.bConfigurationValue,
usb_iface_desc->desc.bInterfaceNumber);
mdev->parent = most_register_interface(&mdev->iface);
if (IS_ERR(mdev->parent)) {
ret = PTR_ERR(mdev->parent);
ret = most_register_interface(&mdev->iface);
if (ret)
goto exit_free4;
}
mutex_lock(&mdev->io_mutex);
if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81118 ||
le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81119 ||
le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_OS81210) {
/* this increments the reference count of the instance
* object of the core
*/
mdev->dci = create_most_dci_obj(mdev->parent);
mdev->dci = kzalloc(sizeof(*mdev->dci), GFP_KERNEL);
if (!mdev->dci) {
mutex_unlock(&mdev->io_mutex);
most_deregister_interface(&mdev->iface);
@ -1232,12 +1101,21 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
goto exit_free4;
}
kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
mdev->dci->dev.init_name = "dci";
mdev->dci->dev.parent = &mdev->iface.dev;
mdev->dci->dev.groups = dci_attr_groups;
if (device_register(&mdev->dci->dev)) {
mutex_unlock(&mdev->io_mutex);
most_deregister_interface(&mdev->iface);
ret = -ENOMEM;
goto exit_free5;
}
mdev->dci->usb_device = mdev->usb_device;
}
mutex_unlock(&mdev->io_mutex);
return 0;
exit_free5:
kfree(mdev->dci);
exit_free4:
kfree(mdev->busy_urbs);
exit_free3:
@ -1277,7 +1155,8 @@ static void hdm_disconnect(struct usb_interface *interface)
del_timer_sync(&mdev->link_stat_timer);
cancel_work_sync(&mdev->poll_work_obj);
destroy_most_dci_obj(mdev->dci);
device_unregister(&mdev->dci->dev);
kfree(mdev->dci);
most_deregister_interface(&mdev->iface);
kfree(mdev->busy_urbs);

View file

@ -480,8 +480,7 @@ static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
}
static int aim_probe_channel(struct most_interface *iface, int channel_idx,
struct most_channel_config *ccfg,
struct kobject *parent, char *name)
struct most_channel_config *ccfg, char *name)
{
int ret;
struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);