linux/drivers/hsi/clients/hsi_char.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * HSI character device driver, implements the character device
   4 * interface.
   5 *
   6 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
   7 *
   8 * Contact: Andras Domokos <andras.domokos@nokia.com>
   9 */
  10
  11#include <linux/errno.h>
  12#include <linux/types.h>
  13#include <linux/atomic.h>
  14#include <linux/kernel.h>
  15#include <linux/init.h>
  16#include <linux/module.h>
  17#include <linux/mutex.h>
  18#include <linux/list.h>
  19#include <linux/slab.h>
  20#include <linux/kmemleak.h>
  21#include <linux/ioctl.h>
  22#include <linux/wait.h>
  23#include <linux/fs.h>
  24#include <linux/sched.h>
  25#include <linux/device.h>
  26#include <linux/cdev.h>
  27#include <linux/uaccess.h>
  28#include <linux/scatterlist.h>
  29#include <linux/stat.h>
  30#include <linux/hsi/hsi.h>
  31#include <linux/hsi/hsi_char.h>
  32
  33#define HSC_DEVS                16 /* Num of channels */
  34#define HSC_MSGS                4
  35
  36#define HSC_RXBREAK             0
  37
  38#define HSC_ID_BITS             6
  39#define HSC_PORT_ID_BITS        4
  40#define HSC_ID_MASK             3
  41#define HSC_PORT_ID_MASK        3
  42#define HSC_CH_MASK             0xf
  43
  44/*
  45 * We support up to 4 controllers that can have up to 4
  46 * ports, which should currently be more than enough.
  47 */
  48#define HSC_BASEMINOR(id, port_id) \
  49                ((((id) & HSC_ID_MASK) << HSC_ID_BITS) | \
  50                (((port_id) & HSC_PORT_ID_MASK) << HSC_PORT_ID_BITS))
  51
  52enum {
  53        HSC_CH_OPEN,
  54        HSC_CH_READ,
  55        HSC_CH_WRITE,
  56        HSC_CH_WLINE,
  57};
  58
  59enum {
  60        HSC_RX,
  61        HSC_TX,
  62};
  63
  64struct hsc_client_data;
  65/**
  66 * struct hsc_channel - hsi_char internal channel data
  67 * @ch: channel number
  68 * @flags: Keeps state of the channel (open/close, reading, writing)
  69 * @free_msgs_list: List of free HSI messages/requests
  70 * @rx_msgs_queue: List of pending RX requests
  71 * @tx_msgs_queue: List of pending TX requests
  72 * @lock: Serialize access to the lists
  73 * @cl: reference to the associated hsi_client
  74 * @cl_data: reference to the client data that this channels belongs to
  75 * @rx_wait: RX requests wait queue
  76 * @tx_wait: TX requests wait queue
  77 */
  78struct hsc_channel {
  79        unsigned int            ch;
  80        unsigned long           flags;
  81        struct list_head        free_msgs_list;
  82        struct list_head        rx_msgs_queue;
  83        struct list_head        tx_msgs_queue;
  84        spinlock_t              lock;
  85        struct hsi_client       *cl;
  86        struct hsc_client_data *cl_data;
  87        wait_queue_head_t       rx_wait;
  88        wait_queue_head_t       tx_wait;
  89};
  90
  91/**
  92 * struct hsc_client_data - hsi_char internal client data
  93 * @cdev: Characther device associated to the hsi_client
  94 * @lock: Lock to serialize open/close access
  95 * @flags: Keeps track of port state (rx hwbreak armed)
  96 * @usecnt: Use count for claiming the HSI port (mutex protected)
  97 * @cl: Referece to the HSI client
  98 * @channels: Array of channels accessible by the client
  99 */
 100struct hsc_client_data {
 101        struct cdev             cdev;
 102        struct mutex            lock;
 103        unsigned long           flags;
 104        unsigned int            usecnt;
 105        struct hsi_client       *cl;
 106        struct hsc_channel      channels[HSC_DEVS];
 107};
 108
 109/* Stores the major number dynamically allocated for hsi_char */
 110static unsigned int hsc_major;
 111/* Maximum buffer size that hsi_char will accept from userspace */
 112static unsigned int max_data_size = 0x1000;
 113module_param(max_data_size, uint, 0);
 114MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)");
 115
 116static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg,
 117                                                        struct list_head *queue)
 118{
 119        unsigned long flags;
 120
 121        spin_lock_irqsave(&channel->lock, flags);
 122        list_add_tail(&msg->link, queue);
 123        spin_unlock_irqrestore(&channel->lock, flags);
 124}
 125
 126static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel,
 127                                                        struct list_head *queue)
 128{
 129        struct hsi_msg *msg = NULL;
 130        unsigned long flags;
 131
 132        spin_lock_irqsave(&channel->lock, flags);
 133
 134        if (list_empty(queue))
 135                goto out;
 136
 137        msg = list_first_entry(queue, struct hsi_msg, link);
 138        list_del(&msg->link);
 139out:
 140        spin_unlock_irqrestore(&channel->lock, flags);
 141
 142        return msg;
 143}
 144
 145static inline void hsc_msg_free(struct hsi_msg *msg)
 146{
 147        kfree(sg_virt(msg->sgt.sgl));
 148        hsi_free_msg(msg);
 149}
 150
 151static void hsc_free_list(struct list_head *list)
 152{
 153        struct hsi_msg *msg, *tmp;
 154
 155        list_for_each_entry_safe(msg, tmp, list, link) {
 156                list_del(&msg->link);
 157                hsc_msg_free(msg);
 158        }
 159}
 160
 161static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l)
 162{
 163        unsigned long flags;
 164        LIST_HEAD(list);
 165
 166        spin_lock_irqsave(&channel->lock, flags);
 167        list_splice_init(l, &list);
 168        spin_unlock_irqrestore(&channel->lock, flags);
 169
 170        hsc_free_list(&list);
 171}
 172
 173static inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size)
 174{
 175        struct hsi_msg *msg;
 176        void *buf;
 177
 178        msg = hsi_alloc_msg(1, GFP_KERNEL);
 179        if (!msg)
 180                goto out;
 181        buf = kmalloc(alloc_size, GFP_KERNEL);
 182        if (!buf) {
 183                hsi_free_msg(msg);
 184                goto out;
 185        }
 186        sg_init_one(msg->sgt.sgl, buf, alloc_size);
 187        /* Ignore false positive, due to sg pointer handling */
 188        kmemleak_ignore(buf);
 189
 190        return msg;
 191out:
 192        return NULL;
 193}
 194
 195static inline int hsc_msgs_alloc(struct hsc_channel *channel)
 196{
 197        struct hsi_msg *msg;
 198        int i;
 199
 200        for (i = 0; i < HSC_MSGS; i++) {
 201                msg = hsc_msg_alloc(max_data_size);
 202                if (!msg)
 203                        goto out;
 204                msg->channel = channel->ch;
 205                list_add_tail(&msg->link, &channel->free_msgs_list);
 206        }
 207
 208        return 0;
 209out:
 210        hsc_free_list(&channel->free_msgs_list);
 211
 212        return -ENOMEM;
 213}
 214
 215static inline unsigned int hsc_msg_len_get(struct hsi_msg *msg)
 216{
 217        return msg->sgt.sgl->length;
 218}
 219
 220static inline void hsc_msg_len_set(struct hsi_msg *msg, unsigned int len)
 221{
 222        msg->sgt.sgl->length = len;
 223}
 224
 225static void hsc_rx_completed(struct hsi_msg *msg)
 226{
 227        struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
 228        struct hsc_channel *channel = cl_data->channels + msg->channel;
 229
 230        if (test_bit(HSC_CH_READ, &channel->flags)) {
 231                hsc_add_tail(channel, msg, &channel->rx_msgs_queue);
 232                wake_up(&channel->rx_wait);
 233        } else {
 234                hsc_add_tail(channel, msg, &channel->free_msgs_list);
 235        }
 236}
 237
 238static void hsc_rx_msg_destructor(struct hsi_msg *msg)
 239{
 240        msg->status = HSI_STATUS_ERROR;
 241        hsc_msg_len_set(msg, 0);
 242        hsc_rx_completed(msg);
 243}
 244
 245static void hsc_tx_completed(struct hsi_msg *msg)
 246{
 247        struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
 248        struct hsc_channel *channel = cl_data->channels + msg->channel;
 249
 250        if (test_bit(HSC_CH_WRITE, &channel->flags)) {
 251                hsc_add_tail(channel, msg, &channel->tx_msgs_queue);
 252                wake_up(&channel->tx_wait);
 253        } else {
 254                hsc_add_tail(channel, msg, &channel->free_msgs_list);
 255        }
 256}
 257
 258static void hsc_tx_msg_destructor(struct hsi_msg *msg)
 259{
 260        msg->status = HSI_STATUS_ERROR;
 261        hsc_msg_len_set(msg, 0);
 262        hsc_tx_completed(msg);
 263}
 264
 265static void hsc_break_req_destructor(struct hsi_msg *msg)
 266{
 267        struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
 268
 269        hsi_free_msg(msg);
 270        clear_bit(HSC_RXBREAK, &cl_data->flags);
 271}
 272
 273static void hsc_break_received(struct hsi_msg *msg)
 274{
 275        struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl);
 276        struct hsc_channel *channel = cl_data->channels;
 277        int i, ret;
 278
 279        /* Broadcast HWBREAK on all channels */
 280        for (i = 0; i < HSC_DEVS; i++, channel++) {
 281                struct hsi_msg *msg2;
 282
 283                if (!test_bit(HSC_CH_READ, &channel->flags))
 284                        continue;
 285                msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list);
 286                if (!msg2)
 287                        continue;
 288                clear_bit(HSC_CH_READ, &channel->flags);
 289                hsc_msg_len_set(msg2, 0);
 290                msg2->status = HSI_STATUS_COMPLETED;
 291                hsc_add_tail(channel, msg2, &channel->rx_msgs_queue);
 292                wake_up(&channel->rx_wait);
 293        }
 294        hsi_flush(msg->cl);
 295        ret = hsi_async_read(msg->cl, msg);
 296        if (ret < 0)
 297                hsc_break_req_destructor(msg);
 298}
 299
 300static int hsc_break_request(struct hsi_client *cl)
 301{
 302        struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
 303        struct hsi_msg *msg;
 304        int ret;
 305
 306        if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags))
 307                return -EBUSY;
 308
 309        msg = hsi_alloc_msg(0, GFP_KERNEL);
 310        if (!msg) {
 311                clear_bit(HSC_RXBREAK, &cl_data->flags);
 312                return -ENOMEM;
 313        }
 314        msg->break_frame = 1;
 315        msg->complete = hsc_break_received;
 316        msg->destructor = hsc_break_req_destructor;
 317        ret = hsi_async_read(cl, msg);
 318        if (ret < 0)
 319                hsc_break_req_destructor(msg);
 320
 321        return ret;
 322}
 323
 324static int hsc_break_send(struct hsi_client *cl)
 325{
 326        struct hsi_msg *msg;
 327        int ret;
 328
 329        msg = hsi_alloc_msg(0, GFP_ATOMIC);
 330        if (!msg)
 331                return -ENOMEM;
 332        msg->break_frame = 1;
 333        msg->complete = hsi_free_msg;
 334        msg->destructor = hsi_free_msg;
 335        ret = hsi_async_write(cl, msg);
 336        if (ret < 0)
 337                hsi_free_msg(msg);
 338
 339        return ret;
 340}
 341
 342static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc)
 343{
 344        struct hsi_config tmp;
 345        int ret;
 346
 347        if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME))
 348                return -EINVAL;
 349        if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS))
 350                return -EINVAL;
 351        if (rxc->channels & (rxc->channels - 1))
 352                return -EINVAL;
 353        if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE))
 354                return -EINVAL;
 355        tmp = cl->rx_cfg;
 356        cl->rx_cfg.mode = rxc->mode;
 357        cl->rx_cfg.num_hw_channels = rxc->channels;
 358        cl->rx_cfg.flow = rxc->flow;
 359        ret = hsi_setup(cl);
 360        if (ret < 0) {
 361                cl->rx_cfg = tmp;
 362                return ret;
 363        }
 364        if (rxc->mode == HSI_MODE_FRAME)
 365                hsc_break_request(cl);
 366
 367        return ret;
 368}
 369
 370static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc)
 371{
 372        rxc->mode = cl->rx_cfg.mode;
 373        rxc->channels = cl->rx_cfg.num_hw_channels;
 374        rxc->flow = cl->rx_cfg.flow;
 375}
 376
 377static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc)
 378{
 379        struct hsi_config tmp;
 380        int ret;
 381
 382        if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME))
 383                return -EINVAL;
 384        if ((txc->channels == 0) || (txc->channels > HSC_DEVS))
 385                return -EINVAL;
 386        if (txc->channels & (txc->channels - 1))
 387                return -EINVAL;
 388        if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO))
 389                return -EINVAL;
 390        tmp = cl->tx_cfg;
 391        cl->tx_cfg.mode = txc->mode;
 392        cl->tx_cfg.num_hw_channels = txc->channels;
 393        cl->tx_cfg.speed = txc->speed;
 394        cl->tx_cfg.arb_mode = txc->arb_mode;
 395        ret = hsi_setup(cl);
 396        if (ret < 0) {
 397                cl->tx_cfg = tmp;
 398                return ret;
 399        }
 400
 401        return ret;
 402}
 403
 404static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc)
 405{
 406        txc->mode = cl->tx_cfg.mode;
 407        txc->channels = cl->tx_cfg.num_hw_channels;
 408        txc->speed = cl->tx_cfg.speed;
 409        txc->arb_mode = cl->tx_cfg.arb_mode;
 410}
 411
 412static ssize_t hsc_read(struct file *file, char __user *buf, size_t len,
 413                                                loff_t *ppos __maybe_unused)
 414{
 415        struct hsc_channel *channel = file->private_data;
 416        struct hsi_msg *msg;
 417        ssize_t ret;
 418
 419        if (len == 0)
 420                return 0;
 421        if (!IS_ALIGNED(len, sizeof(u32)))
 422                return -EINVAL;
 423        if (len > max_data_size)
 424                len = max_data_size;
 425        if (channel->ch >= channel->cl->rx_cfg.num_hw_channels)
 426                return -ECHRNG;
 427        if (test_and_set_bit(HSC_CH_READ, &channel->flags))
 428                return -EBUSY;
 429        msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
 430        if (!msg) {
 431                ret = -ENOSPC;
 432                goto out;
 433        }
 434        hsc_msg_len_set(msg, len);
 435        msg->complete = hsc_rx_completed;
 436        msg->destructor = hsc_rx_msg_destructor;
 437        ret = hsi_async_read(channel->cl, msg);
 438        if (ret < 0) {
 439                hsc_add_tail(channel, msg, &channel->free_msgs_list);
 440                goto out;
 441        }
 442
 443        ret = wait_event_interruptible(channel->rx_wait,
 444                                        !list_empty(&channel->rx_msgs_queue));
 445        if (ret < 0) {
 446                clear_bit(HSC_CH_READ, &channel->flags);
 447                hsi_flush(channel->cl);
 448                return -EINTR;
 449        }
 450
 451        msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue);
 452        if (msg) {
 453                if (msg->status != HSI_STATUS_ERROR) {
 454                        ret = copy_to_user((void __user *)buf,
 455                        sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg));
 456                        if (ret)
 457                                ret = -EFAULT;
 458                        else
 459                                ret = hsc_msg_len_get(msg);
 460                } else {
 461                        ret = -EIO;
 462                }
 463                hsc_add_tail(channel, msg, &channel->free_msgs_list);
 464        }
 465out:
 466        clear_bit(HSC_CH_READ, &channel->flags);
 467
 468        return ret;
 469}
 470
 471static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len,
 472                                                loff_t *ppos __maybe_unused)
 473{
 474        struct hsc_channel *channel = file->private_data;
 475        struct hsi_msg *msg;
 476        ssize_t ret;
 477
 478        if ((len == 0) || !IS_ALIGNED(len, sizeof(u32)))
 479                return -EINVAL;
 480        if (len > max_data_size)
 481                len = max_data_size;
 482        if (channel->ch >= channel->cl->tx_cfg.num_hw_channels)
 483                return -ECHRNG;
 484        if (test_and_set_bit(HSC_CH_WRITE, &channel->flags))
 485                return -EBUSY;
 486        msg = hsc_get_first_msg(channel, &channel->free_msgs_list);
 487        if (!msg) {
 488                clear_bit(HSC_CH_WRITE, &channel->flags);
 489                return -ENOSPC;
 490        }
 491        if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) {
 492                ret = -EFAULT;
 493                goto out;
 494        }
 495        hsc_msg_len_set(msg, len);
 496        msg->complete = hsc_tx_completed;
 497        msg->destructor = hsc_tx_msg_destructor;
 498        ret = hsi_async_write(channel->cl, msg);
 499        if (ret < 0)
 500                goto out;
 501
 502        ret = wait_event_interruptible(channel->tx_wait,
 503                                        !list_empty(&channel->tx_msgs_queue));
 504        if (ret < 0) {
 505                clear_bit(HSC_CH_WRITE, &channel->flags);
 506                hsi_flush(channel->cl);
 507                return -EINTR;
 508        }
 509
 510        msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue);
 511        if (msg) {
 512                if (msg->status == HSI_STATUS_ERROR)
 513                        ret = -EIO;
 514                else
 515                        ret = hsc_msg_len_get(msg);
 516
 517                hsc_add_tail(channel, msg, &channel->free_msgs_list);
 518        }
 519out:
 520        clear_bit(HSC_CH_WRITE, &channel->flags);
 521
 522        return ret;
 523}
 524
 525static long hsc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 526{
 527        struct hsc_channel *channel = file->private_data;
 528        unsigned int state;
 529        struct hsc_rx_config rxc;
 530        struct hsc_tx_config txc;
 531        long ret = 0;
 532
 533        switch (cmd) {
 534        case HSC_RESET:
 535                hsi_flush(channel->cl);
 536                break;
 537        case HSC_SET_PM:
 538                if (copy_from_user(&state, (void __user *)arg, sizeof(state)))
 539                        return -EFAULT;
 540                if (state == HSC_PM_DISABLE) {
 541                        if (test_and_set_bit(HSC_CH_WLINE, &channel->flags))
 542                                return -EINVAL;
 543                        ret = hsi_start_tx(channel->cl);
 544                } else if (state == HSC_PM_ENABLE) {
 545                        if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
 546                                return -EINVAL;
 547                        ret = hsi_stop_tx(channel->cl);
 548                } else {
 549                        ret = -EINVAL;
 550                }
 551                break;
 552        case HSC_SEND_BREAK:
 553                return hsc_break_send(channel->cl);
 554        case HSC_SET_RX:
 555                if (copy_from_user(&rxc, (void __user *)arg, sizeof(rxc)))
 556                        return -EFAULT;
 557                return hsc_rx_set(channel->cl, &rxc);
 558        case HSC_GET_RX:
 559                hsc_rx_get(channel->cl, &rxc);
 560                if (copy_to_user((void __user *)arg, &rxc, sizeof(rxc)))
 561                        return -EFAULT;
 562                break;
 563        case HSC_SET_TX:
 564                if (copy_from_user(&txc, (void __user *)arg, sizeof(txc)))
 565                        return -EFAULT;
 566                return hsc_tx_set(channel->cl, &txc);
 567        case HSC_GET_TX:
 568                hsc_tx_get(channel->cl, &txc);
 569                if (copy_to_user((void __user *)arg, &txc, sizeof(txc)))
 570                        return -EFAULT;
 571                break;
 572        default:
 573                return -ENOIOCTLCMD;
 574        }
 575
 576        return ret;
 577}
 578
 579static inline void __hsc_port_release(struct hsc_client_data *cl_data)
 580{
 581        BUG_ON(cl_data->usecnt == 0);
 582
 583        if (--cl_data->usecnt == 0) {
 584                hsi_flush(cl_data->cl);
 585                hsi_release_port(cl_data->cl);
 586        }
 587}
 588
 589static int hsc_open(struct inode *inode, struct file *file)
 590{
 591        struct hsc_client_data *cl_data;
 592        struct hsc_channel *channel;
 593        int ret = 0;
 594
 595        pr_debug("open, minor = %d\n", iminor(inode));
 596
 597        cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev);
 598        mutex_lock(&cl_data->lock);
 599        channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK);
 600
 601        if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) {
 602                ret = -EBUSY;
 603                goto out;
 604        }
 605        /*
 606         * Check if we have already claimed the port associated to the HSI
 607         * client. If not then try to claim it, else increase its refcount
 608         */
 609        if (cl_data->usecnt == 0) {
 610                ret = hsi_claim_port(cl_data->cl, 0);
 611                if (ret < 0)
 612                        goto out;
 613                hsi_setup(cl_data->cl);
 614        }
 615        cl_data->usecnt++;
 616
 617        ret = hsc_msgs_alloc(channel);
 618        if (ret < 0) {
 619                __hsc_port_release(cl_data);
 620                goto out;
 621        }
 622
 623        file->private_data = channel;
 624        mutex_unlock(&cl_data->lock);
 625
 626        return ret;
 627out:
 628        mutex_unlock(&cl_data->lock);
 629
 630        return ret;
 631}
 632
 633static int hsc_release(struct inode *inode __maybe_unused, struct file *file)
 634{
 635        struct hsc_channel *channel = file->private_data;
 636        struct hsc_client_data *cl_data = channel->cl_data;
 637
 638        mutex_lock(&cl_data->lock);
 639        file->private_data = NULL;
 640        if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags))
 641                hsi_stop_tx(channel->cl);
 642        __hsc_port_release(cl_data);
 643        hsc_reset_list(channel, &channel->rx_msgs_queue);
 644        hsc_reset_list(channel, &channel->tx_msgs_queue);
 645        hsc_reset_list(channel, &channel->free_msgs_list);
 646        clear_bit(HSC_CH_READ, &channel->flags);
 647        clear_bit(HSC_CH_WRITE, &channel->flags);
 648        clear_bit(HSC_CH_OPEN, &channel->flags);
 649        wake_up(&channel->rx_wait);
 650        wake_up(&channel->tx_wait);
 651        mutex_unlock(&cl_data->lock);
 652
 653        return 0;
 654}
 655
 656static const struct file_operations hsc_fops = {
 657        .owner          = THIS_MODULE,
 658        .read           = hsc_read,
 659        .write          = hsc_write,
 660        .unlocked_ioctl = hsc_ioctl,
 661        .open           = hsc_open,
 662        .release        = hsc_release,
 663};
 664
 665static void hsc_channel_init(struct hsc_channel *channel)
 666{
 667        init_waitqueue_head(&channel->rx_wait);
 668        init_waitqueue_head(&channel->tx_wait);
 669        spin_lock_init(&channel->lock);
 670        INIT_LIST_HEAD(&channel->free_msgs_list);
 671        INIT_LIST_HEAD(&channel->rx_msgs_queue);
 672        INIT_LIST_HEAD(&channel->tx_msgs_queue);
 673}
 674
 675static int hsc_probe(struct device *dev)
 676{
 677        const char devname[] = "hsi_char";
 678        struct hsc_client_data *cl_data;
 679        struct hsc_channel *channel;
 680        struct hsi_client *cl = to_hsi_client(dev);
 681        unsigned int hsc_baseminor;
 682        dev_t hsc_dev;
 683        int ret;
 684        int i;
 685
 686        cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL);
 687        if (!cl_data)
 688                return -ENOMEM;
 689
 690        hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl));
 691        if (!hsc_major) {
 692                ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor,
 693                                                HSC_DEVS, devname);
 694                if (ret == 0)
 695                        hsc_major = MAJOR(hsc_dev);
 696        } else {
 697                hsc_dev = MKDEV(hsc_major, hsc_baseminor);
 698                ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname);
 699        }
 700        if (ret < 0) {
 701                dev_err(dev, "Device %s allocation failed %d\n",
 702                                        hsc_major ? "minor" : "major", ret);
 703                goto out1;
 704        }
 705        mutex_init(&cl_data->lock);
 706        hsi_client_set_drvdata(cl, cl_data);
 707        cdev_init(&cl_data->cdev, &hsc_fops);
 708        cl_data->cdev.owner = THIS_MODULE;
 709        cl_data->cl = cl;
 710        for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) {
 711                hsc_channel_init(channel);
 712                channel->ch = i;
 713                channel->cl = cl;
 714                channel->cl_data = cl_data;
 715        }
 716
 717        /* 1 hsi client -> N char devices (one for each channel) */
 718        ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS);
 719        if (ret) {
 720                dev_err(dev, "Could not add char device %d\n", ret);
 721                goto out2;
 722        }
 723
 724        return 0;
 725out2:
 726        unregister_chrdev_region(hsc_dev, HSC_DEVS);
 727out1:
 728        kfree(cl_data);
 729
 730        return ret;
 731}
 732
 733static int hsc_remove(struct device *dev)
 734{
 735        struct hsi_client *cl = to_hsi_client(dev);
 736        struct hsc_client_data *cl_data = hsi_client_drvdata(cl);
 737        dev_t hsc_dev = cl_data->cdev.dev;
 738
 739        cdev_del(&cl_data->cdev);
 740        unregister_chrdev_region(hsc_dev, HSC_DEVS);
 741        hsi_client_set_drvdata(cl, NULL);
 742        kfree(cl_data);
 743
 744        return 0;
 745}
 746
 747static struct hsi_client_driver hsc_driver = {
 748        .driver = {
 749                .name   = "hsi_char",
 750                .owner  = THIS_MODULE,
 751                .probe  = hsc_probe,
 752                .remove = hsc_remove,
 753        },
 754};
 755
 756static int __init hsc_init(void)
 757{
 758        int ret;
 759
 760        if ((max_data_size < 4) || (max_data_size > 0x10000) ||
 761                (max_data_size & (max_data_size - 1))) {
 762                pr_err("Invalid max read/write data size\n");
 763                return -EINVAL;
 764        }
 765
 766        ret = hsi_register_client_driver(&hsc_driver);
 767        if (ret) {
 768                pr_err("Error while registering HSI/SSI driver %d\n", ret);
 769                return ret;
 770        }
 771
 772        pr_info("HSI/SSI char device loaded\n");
 773
 774        return 0;
 775}
 776module_init(hsc_init);
 777
 778static void __exit hsc_exit(void)
 779{
 780        hsi_unregister_client_driver(&hsc_driver);
 781        pr_info("HSI char device removed\n");
 782}
 783module_exit(hsc_exit);
 784
 785MODULE_AUTHOR("Andras Domokos <andras.domokos@nokia.com>");
 786MODULE_ALIAS("hsi:hsi_char");
 787MODULE_DESCRIPTION("HSI character device");
 788MODULE_LICENSE("GPL v2");
 789