in clients/hsi_char.c [675:731]
static int hsc_probe(struct device *dev)
{
const char devname[] = "hsi_char";
struct hsc_client_data *cl_data;
struct hsc_channel *channel;
struct hsi_client *cl = to_hsi_client(dev);
unsigned int hsc_baseminor;
dev_t hsc_dev;
int ret;
int i;
cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL);
if (!cl_data)
return -ENOMEM;
hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl));
if (!hsc_major) {
ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor,
HSC_DEVS, devname);
if (ret == 0)
hsc_major = MAJOR(hsc_dev);
} else {
hsc_dev = MKDEV(hsc_major, hsc_baseminor);
ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname);
}
if (ret < 0) {
dev_err(dev, "Device %s allocation failed %d\n",
hsc_major ? "minor" : "major", ret);
goto out1;
}
mutex_init(&cl_data->lock);
hsi_client_set_drvdata(cl, cl_data);
cdev_init(&cl_data->cdev, &hsc_fops);
cl_data->cdev.owner = THIS_MODULE;
cl_data->cl = cl;
for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) {
hsc_channel_init(channel);
channel->ch = i;
channel->cl = cl;
channel->cl_data = cl_data;
}
/* 1 hsi client -> N char devices (one for each channel) */
ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS);
if (ret) {
dev_err(dev, "Could not add char device %d\n", ret);
goto out2;
}
return 0;
out2:
unregister_chrdev_region(hsc_dev, HSC_DEVS);
out1:
kfree(cl_data);
return ret;
}