Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Aaro Koskinen
Hi,

On Mon, Mar 02, 2015 at 05:38:51AM +0100, Sebastian Reichel wrote:
> From: Kai Vehmanen 
> 
> Introduces the cmt-speech driver, which implements
> a character device interface for transferring speech
> data frames over HSI/SSI.
> 
> The driver is used to exchange voice/speech data between
> the Nokia N900/N950/N9's modem and its cpu.
> 
> Signed-off-by: Kai Vehmanen 
> Signed-off-by: Carlos Chinea 
> Signed-off-by: Joni Lapilainen 
> Signed-off-by: Sebastian Reichel 

I think the initial mainline kernel submission for this driver should be
a single patch, so just squash all the cleanups and fixes into this one.
You can document the changes you have made by describing the changes
before your own Signed-off-by line.

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


Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Sebastian Reichel
Hi Oliver,

On Mon, Mar 02, 2015 at 11:22:33AM +0100, Oliver Neukum wrote:
> > +static ssize_t cs_char_read(struct file *file, char __user *buf, size_t 
> > count,
> > +   loff_t *unused)
> > +{
> > +   struct cs_char *csdata = file->private_data;
> > +   u32 data;
> > +   ssize_t retval;
> > +
> > +   if (count < sizeof(data))
> > +   return -EINVAL;
> > +
> > +   for ( ; ; ) {
> > +   DEFINE_WAIT(wait);
> > +
> > +   spin_lock_bh(>lock);
> > +   if (!list_empty(>chardev_queue)) {
> > +   data = cs_pop_entry(>chardev_queue);
> > +   } else if (!list_empty(>dataind_queue)) {
> > +   data = cs_pop_entry(>dataind_queue);
> > +   --csdata->dataind_pending;
> > +
> > +   } else {
> > +   data = 0;
> > +   }
> > +   spin_unlock_bh(>lock);
> > +
> > +   if (data)
> > +   break;
> > +   if (file->f_flags & O_NONBLOCK) {
> > +   retval = -EAGAIN;
> > +   goto out;
> > +   } else if (signal_pending(current)) {
> > +   retval = -ERESTARTSYS;
> > +   goto out;
> > +   }
> > +   prepare_to_wait_exclusive(>wait, ,
> > +   TASK_INTERRUPTIBLE);
> > +   schedule();
> > +   finish_wait(>wait, );
> > +   }
> > +
> > +   retval = put_user(data, (u32 __user *)buf);
> > +   if (!retval)
> > +   retval = sizeof(data);
> > +
> > +out:
> > +   return retval;
> > +}
> > +
> > +static ssize_t cs_char_write(struct file *file, const char __user *buf,
> > +   size_t count, loff_t *unused)
> > +{
> > +   struct cs_char *csdata = file->private_data;
> > +   u32 data;
> > +   int err;
> > +   ssize_t retval;
> > +
> > +   if (count < sizeof(data))
> > +   return -EINVAL;
> > +
> > +   if (get_user(data, (u32 __user *)buf))
> > +   retval = -EFAULT;
> > +   else
> > +   retval = count;
> 
> You want to execute the command even if you got -EFAULT?
> That is highly unusual.

I will change this in PATCHv2.

> > +
> > +   err = cs_hsi_command(csdata->hi, data);
> > +   if (err < 0)
> > +   retval = err;
> > +
> > +   return retval;
> > +}
> > +
> > +static long cs_char_ioctl(struct file *file, unsigned int cmd,
> > +   unsigned long arg)
> > +{
> > +   struct cs_char *csdata = file->private_data;
> > +   int r = 0;
> > +
> > +   switch (cmd) {
> > +   case CS_GET_STATE: {
> > +   unsigned int state;
> > +
> > +   state = cs_hsi_get_state(csdata->hi);
> > +   if (copy_to_user((void __user *)arg, , sizeof(state)))
> > +   r = -EFAULT;
> > +   }
> > +   break;
> > +   case CS_SET_WAKELINE: {
> > +   unsigned int state;
> > +
> > +   if (copy_from_user(, (void __user *)arg, sizeof(state)))
> > +   r = -EFAULT;
> > +   else
> > +   cs_hsi_set_wakeline(csdata->hi, state);
> 
> No sanity checking for state?

Will be added in PATCHv2, so that -EINVAL is returned for values > 1.

> > +   }
> > +   break;
> > +   case CS_GET_IF_VERSION: {
> > +   unsigned int ifver = CS_IF_VERSION;
> > +
> > +   if (copy_to_user((void __user *)arg, , sizeof(ifver)))
> > +   r = -EFAULT;
> > +   break;
> > +   }
> > +   case CS_CONFIG_BUFS: {
> > +   struct cs_buffer_config buf_cfg;
> > +
> > +   if (copy_from_user(_cfg, (void __user *)arg,
> > +   sizeof(buf_cfg)))
> > +   r = -EFAULT;
> > +   else
> > +   r = cs_hsi_buf_config(csdata->hi, _cfg);
> 
> Sanity checking?

cs_hsi_buf_config() calls check_buf_params().

> > +   break;
> > +   }
> > +   default:
> > +   r = -ENOTTY;
> > +   break;
> > +   }
> > +
> > +   return r;
> > +}
> > +
> > +static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
> > +{
> > +   if (vma->vm_end < vma->vm_start)
> > +   return -EINVAL;
> > +
> > +   if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) != 1)
> > +   return -EINVAL;
> > +
> > +   vma->vm_flags |= VM_RESERVED;
> > +   vma->vm_ops = _char_vm_ops;
> > +   vma->vm_private_data = file->private_data;
> > +
> > +   return 0;
> > +}
> > +
> > +static int cs_char_open(struct inode *unused, struct file *file)
> > +{
> > +   int ret = 0;
> > +
> > +   spin_lock_bh(_char_data.lock);
> > +   if (cs_char_data.opened) {
> > +   ret = -EBUSY;
> > +   spin_unlock_bh(_char_data.lock);
> > +   goto out;
> > +   }
> > +   cs_char_data.mmap_base = get_zeroed_page(GFP_ATOMIC);
> 
> This could be moved outside the locked sectionand use GFP_KERNEL.

Right, this is fixed by a follow up patch. I kept the patchset 

Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Oliver Neukum

> +static ssize_t cs_char_read(struct file *file, char __user *buf, size_t 
> count,
> + loff_t *unused)
> +{
> + struct cs_char *csdata = file->private_data;
> + u32 data;
> + ssize_t retval;
> +
> + if (count < sizeof(data))
> + return -EINVAL;
> +
> + for ( ; ; ) {
> + DEFINE_WAIT(wait);
> +
> + spin_lock_bh(>lock);
> + if (!list_empty(>chardev_queue)) {
> + data = cs_pop_entry(>chardev_queue);
> + } else if (!list_empty(>dataind_queue)) {
> + data = cs_pop_entry(>dataind_queue);
> + --csdata->dataind_pending;
> +
> + } else {
> + data = 0;
> + }
> + spin_unlock_bh(>lock);
> +
> + if (data)
> + break;
> + if (file->f_flags & O_NONBLOCK) {
> + retval = -EAGAIN;
> + goto out;
> + } else if (signal_pending(current)) {
> + retval = -ERESTARTSYS;
> + goto out;
> + }
> + prepare_to_wait_exclusive(>wait, ,
> + TASK_INTERRUPTIBLE);
> + schedule();
> + finish_wait(>wait, );
> + }
> +
> + retval = put_user(data, (u32 __user *)buf);
> + if (!retval)
> + retval = sizeof(data);
> +
> +out:
> + return retval;
> +}
> +
> +static ssize_t cs_char_write(struct file *file, const char __user *buf,
> + size_t count, loff_t *unused)
> +{
> + struct cs_char *csdata = file->private_data;
> + u32 data;
> + int err;
> + ssize_t retval;
> +
> + if (count < sizeof(data))
> + return -EINVAL;
> +
> + if (get_user(data, (u32 __user *)buf))
> + retval = -EFAULT;
> + else
> + retval = count;

You want to execute the command even if you got -EFAULT?
That is highly unusual.

> +
> + err = cs_hsi_command(csdata->hi, data);
> + if (err < 0)
> + retval = err;
> +
> + return retval;
> +}
> +
> +static long cs_char_ioctl(struct file *file, unsigned int cmd,
> + unsigned long arg)
> +{
> + struct cs_char *csdata = file->private_data;
> + int r = 0;
> +
> + switch (cmd) {
> + case CS_GET_STATE: {
> + unsigned int state;
> +
> + state = cs_hsi_get_state(csdata->hi);
> + if (copy_to_user((void __user *)arg, , sizeof(state)))
> + r = -EFAULT;
> + }
> + break;
> + case CS_SET_WAKELINE: {
> + unsigned int state;
> +
> + if (copy_from_user(, (void __user *)arg, sizeof(state)))
> + r = -EFAULT;
> + else
> + cs_hsi_set_wakeline(csdata->hi, state);

No sanity checking for state?

> + }
> + break;
> + case CS_GET_IF_VERSION: {
> + unsigned int ifver = CS_IF_VERSION;
> +
> + if (copy_to_user((void __user *)arg, , sizeof(ifver)))
> + r = -EFAULT;
> + break;
> + }
> + case CS_CONFIG_BUFS: {
> + struct cs_buffer_config buf_cfg;
> +
> + if (copy_from_user(_cfg, (void __user *)arg,
> + sizeof(buf_cfg)))
> + r = -EFAULT;
> + else
> + r = cs_hsi_buf_config(csdata->hi, _cfg);

Sanity checking?

> + break;
> + }
> + default:
> + r = -ENOTTY;
> + break;
> + }
> +
> + return r;
> +}
> +
> +static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
> +{
> + if (vma->vm_end < vma->vm_start)
> + return -EINVAL;
> +
> + if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) != 1)
> + return -EINVAL;
> +
> + vma->vm_flags |= VM_RESERVED;
> + vma->vm_ops = _char_vm_ops;
> + vma->vm_private_data = file->private_data;
> +
> + return 0;
> +}
> +
> +static int cs_char_open(struct inode *unused, struct file *file)
> +{
> + int ret = 0;
> +
> + spin_lock_bh(_char_data.lock);
> + if (cs_char_data.opened) {
> + ret = -EBUSY;
> + spin_unlock_bh(_char_data.lock);
> + goto out;
> + }
> + cs_char_data.mmap_base = get_zeroed_page(GFP_ATOMIC);

This could be moved outside the locked sectionand use GFP_KERNEL.

> + if (!cs_char_data.mmap_base) {
> + dev_err(_char_data.cl->device,
> + "Shared memory allocation failed.\n");
> + ret = -ENOMEM;
> + spin_unlock_bh(_char_data.lock);
> + goto out;
> + }
> + cs_char_data.mmap_size = CS_MMAP_SIZE;
> + cs_char_data.dataind_pending = 0;
> + 

Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Oliver Neukum
On Mon, 2015-03-02 at 05:38 +0100, Sebastian Reichel wrote:
> +static int cs_alloc_cmds(struct cs_hsi_iface *hi)
> +{
> +   struct hsi_msg *msg;
> +   u32 *buf;
> +   unsigned int i;
> +
> +   INIT_LIST_HEAD(>cmdqueue);
> +
> +   for (i = 0; i < CS_MAX_CMDS; i++) {
> +   msg = hsi_alloc_msg(1, GFP_ATOMIC);

Why does this need to be ATOMIC?
> +   if (!msg)
> +   goto out;
> +   buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
> +   if (!buf) {
> +   hsi_free_msg(msg);
> +   goto out;
> +   }
> +   sg_init_one(msg->sgt.sgl, buf, sizeof(*buf));
> +   msg->channel = CONTROL_HSI_CH;
> +   msg->context = hi;
> +   list_add_tail(>link, >cmdqueue);
> +   }
> +
> +   return 0;
> +
> +out:
> +   cs_free_cmds(hi);
> +   return -ENOMEM;
> +}
> +



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


Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Aaro Koskinen
Hi,

On Mon, Mar 02, 2015 at 05:38:51AM +0100, Sebastian Reichel wrote:
 From: Kai Vehmanen kai.vehma...@nokia.com
 
 Introduces the cmt-speech driver, which implements
 a character device interface for transferring speech
 data frames over HSI/SSI.
 
 The driver is used to exchange voice/speech data between
 the Nokia N900/N950/N9's modem and its cpu.
 
 Signed-off-by: Kai Vehmanen kai.vehma...@nokia.com
 Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
 Signed-off-by: Joni Lapilainen joni.lapilai...@gmail.com
 Signed-off-by: Sebastian Reichel s...@kernel.org

I think the initial mainline kernel submission for this driver should be
a single patch, so just squash all the cleanups and fixes into this one.
You can document the changes you have made by describing the changes
before your own Signed-off-by line.

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


Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Oliver Neukum
On Mon, 2015-03-02 at 05:38 +0100, Sebastian Reichel wrote:
 +static int cs_alloc_cmds(struct cs_hsi_iface *hi)
 +{
 +   struct hsi_msg *msg;
 +   u32 *buf;
 +   unsigned int i;
 +
 +   INIT_LIST_HEAD(hi-cmdqueue);
 +
 +   for (i = 0; i  CS_MAX_CMDS; i++) {
 +   msg = hsi_alloc_msg(1, GFP_ATOMIC);

Why does this need to be ATOMIC?
 +   if (!msg)
 +   goto out;
 +   buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
 +   if (!buf) {
 +   hsi_free_msg(msg);
 +   goto out;
 +   }
 +   sg_init_one(msg-sgt.sgl, buf, sizeof(*buf));
 +   msg-channel = CONTROL_HSI_CH;
 +   msg-context = hi;
 +   list_add_tail(msg-link, hi-cmdqueue);
 +   }
 +
 +   return 0;
 +
 +out:
 +   cs_free_cmds(hi);
 +   return -ENOMEM;
 +}
 +



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


Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Oliver Neukum

 +static ssize_t cs_char_read(struct file *file, char __user *buf, size_t 
 count,
 + loff_t *unused)
 +{
 + struct cs_char *csdata = file-private_data;
 + u32 data;
 + ssize_t retval;
 +
 + if (count  sizeof(data))
 + return -EINVAL;
 +
 + for ( ; ; ) {
 + DEFINE_WAIT(wait);
 +
 + spin_lock_bh(csdata-lock);
 + if (!list_empty(csdata-chardev_queue)) {
 + data = cs_pop_entry(csdata-chardev_queue);
 + } else if (!list_empty(csdata-dataind_queue)) {
 + data = cs_pop_entry(csdata-dataind_queue);
 + --csdata-dataind_pending;
 +
 + } else {
 + data = 0;
 + }
 + spin_unlock_bh(csdata-lock);
 +
 + if (data)
 + break;
 + if (file-f_flags  O_NONBLOCK) {
 + retval = -EAGAIN;
 + goto out;
 + } else if (signal_pending(current)) {
 + retval = -ERESTARTSYS;
 + goto out;
 + }
 + prepare_to_wait_exclusive(csdata-wait, wait,
 + TASK_INTERRUPTIBLE);
 + schedule();
 + finish_wait(csdata-wait, wait);
 + }
 +
 + retval = put_user(data, (u32 __user *)buf);
 + if (!retval)
 + retval = sizeof(data);
 +
 +out:
 + return retval;
 +}
 +
 +static ssize_t cs_char_write(struct file *file, const char __user *buf,
 + size_t count, loff_t *unused)
 +{
 + struct cs_char *csdata = file-private_data;
 + u32 data;
 + int err;
 + ssize_t retval;
 +
 + if (count  sizeof(data))
 + return -EINVAL;
 +
 + if (get_user(data, (u32 __user *)buf))
 + retval = -EFAULT;
 + else
 + retval = count;

You want to execute the command even if you got -EFAULT?
That is highly unusual.

 +
 + err = cs_hsi_command(csdata-hi, data);
 + if (err  0)
 + retval = err;
 +
 + return retval;
 +}
 +
 +static long cs_char_ioctl(struct file *file, unsigned int cmd,
 + unsigned long arg)
 +{
 + struct cs_char *csdata = file-private_data;
 + int r = 0;
 +
 + switch (cmd) {
 + case CS_GET_STATE: {
 + unsigned int state;
 +
 + state = cs_hsi_get_state(csdata-hi);
 + if (copy_to_user((void __user *)arg, state, sizeof(state)))
 + r = -EFAULT;
 + }
 + break;
 + case CS_SET_WAKELINE: {
 + unsigned int state;
 +
 + if (copy_from_user(state, (void __user *)arg, sizeof(state)))
 + r = -EFAULT;
 + else
 + cs_hsi_set_wakeline(csdata-hi, state);

No sanity checking for state?

 + }
 + break;
 + case CS_GET_IF_VERSION: {
 + unsigned int ifver = CS_IF_VERSION;
 +
 + if (copy_to_user((void __user *)arg, ifver, sizeof(ifver)))
 + r = -EFAULT;
 + break;
 + }
 + case CS_CONFIG_BUFS: {
 + struct cs_buffer_config buf_cfg;
 +
 + if (copy_from_user(buf_cfg, (void __user *)arg,
 + sizeof(buf_cfg)))
 + r = -EFAULT;
 + else
 + r = cs_hsi_buf_config(csdata-hi, buf_cfg);

Sanity checking?

 + break;
 + }
 + default:
 + r = -ENOTTY;
 + break;
 + }
 +
 + return r;
 +}
 +
 +static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
 +{
 + if (vma-vm_end  vma-vm_start)
 + return -EINVAL;
 +
 + if (((vma-vm_end - vma-vm_start)  PAGE_SHIFT) != 1)
 + return -EINVAL;
 +
 + vma-vm_flags |= VM_RESERVED;
 + vma-vm_ops = cs_char_vm_ops;
 + vma-vm_private_data = file-private_data;
 +
 + return 0;
 +}
 +
 +static int cs_char_open(struct inode *unused, struct file *file)
 +{
 + int ret = 0;
 +
 + spin_lock_bh(cs_char_data.lock);
 + if (cs_char_data.opened) {
 + ret = -EBUSY;
 + spin_unlock_bh(cs_char_data.lock);
 + goto out;
 + }
 + cs_char_data.mmap_base = get_zeroed_page(GFP_ATOMIC);

This could be moved outside the locked sectionand use GFP_KERNEL.

 + if (!cs_char_data.mmap_base) {
 + dev_err(cs_char_data.cl-device,
 + Shared memory allocation failed.\n);
 + ret = -ENOMEM;
 + spin_unlock_bh(cs_char_data.lock);
 + goto out;
 + }
 + cs_char_data.mmap_size = CS_MMAP_SIZE;
 + cs_char_data.dataind_pending = 0;
 + cs_char_data.opened = 1;
 + file-private_data = cs_char_data;
 + spin_unlock_bh(cs_char_data.lock);
 

Re: [PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-02 Thread Sebastian Reichel
Hi Oliver,

On Mon, Mar 02, 2015 at 11:22:33AM +0100, Oliver Neukum wrote:
  +static ssize_t cs_char_read(struct file *file, char __user *buf, size_t 
  count,
  +   loff_t *unused)
  +{
  +   struct cs_char *csdata = file-private_data;
  +   u32 data;
  +   ssize_t retval;
  +
  +   if (count  sizeof(data))
  +   return -EINVAL;
  +
  +   for ( ; ; ) {
  +   DEFINE_WAIT(wait);
  +
  +   spin_lock_bh(csdata-lock);
  +   if (!list_empty(csdata-chardev_queue)) {
  +   data = cs_pop_entry(csdata-chardev_queue);
  +   } else if (!list_empty(csdata-dataind_queue)) {
  +   data = cs_pop_entry(csdata-dataind_queue);
  +   --csdata-dataind_pending;
  +
  +   } else {
  +   data = 0;
  +   }
  +   spin_unlock_bh(csdata-lock);
  +
  +   if (data)
  +   break;
  +   if (file-f_flags  O_NONBLOCK) {
  +   retval = -EAGAIN;
  +   goto out;
  +   } else if (signal_pending(current)) {
  +   retval = -ERESTARTSYS;
  +   goto out;
  +   }
  +   prepare_to_wait_exclusive(csdata-wait, wait,
  +   TASK_INTERRUPTIBLE);
  +   schedule();
  +   finish_wait(csdata-wait, wait);
  +   }
  +
  +   retval = put_user(data, (u32 __user *)buf);
  +   if (!retval)
  +   retval = sizeof(data);
  +
  +out:
  +   return retval;
  +}
  +
  +static ssize_t cs_char_write(struct file *file, const char __user *buf,
  +   size_t count, loff_t *unused)
  +{
  +   struct cs_char *csdata = file-private_data;
  +   u32 data;
  +   int err;
  +   ssize_t retval;
  +
  +   if (count  sizeof(data))
  +   return -EINVAL;
  +
  +   if (get_user(data, (u32 __user *)buf))
  +   retval = -EFAULT;
  +   else
  +   retval = count;
 
 You want to execute the command even if you got -EFAULT?
 That is highly unusual.

I will change this in PATCHv2.

  +
  +   err = cs_hsi_command(csdata-hi, data);
  +   if (err  0)
  +   retval = err;
  +
  +   return retval;
  +}
  +
  +static long cs_char_ioctl(struct file *file, unsigned int cmd,
  +   unsigned long arg)
  +{
  +   struct cs_char *csdata = file-private_data;
  +   int r = 0;
  +
  +   switch (cmd) {
  +   case CS_GET_STATE: {
  +   unsigned int state;
  +
  +   state = cs_hsi_get_state(csdata-hi);
  +   if (copy_to_user((void __user *)arg, state, sizeof(state)))
  +   r = -EFAULT;
  +   }
  +   break;
  +   case CS_SET_WAKELINE: {
  +   unsigned int state;
  +
  +   if (copy_from_user(state, (void __user *)arg, sizeof(state)))
  +   r = -EFAULT;
  +   else
  +   cs_hsi_set_wakeline(csdata-hi, state);
 
 No sanity checking for state?

Will be added in PATCHv2, so that -EINVAL is returned for values  1.

  +   }
  +   break;
  +   case CS_GET_IF_VERSION: {
  +   unsigned int ifver = CS_IF_VERSION;
  +
  +   if (copy_to_user((void __user *)arg, ifver, sizeof(ifver)))
  +   r = -EFAULT;
  +   break;
  +   }
  +   case CS_CONFIG_BUFS: {
  +   struct cs_buffer_config buf_cfg;
  +
  +   if (copy_from_user(buf_cfg, (void __user *)arg,
  +   sizeof(buf_cfg)))
  +   r = -EFAULT;
  +   else
  +   r = cs_hsi_buf_config(csdata-hi, buf_cfg);
 
 Sanity checking?

cs_hsi_buf_config() calls check_buf_params().

  +   break;
  +   }
  +   default:
  +   r = -ENOTTY;
  +   break;
  +   }
  +
  +   return r;
  +}
  +
  +static int cs_char_mmap(struct file *file, struct vm_area_struct *vma)
  +{
  +   if (vma-vm_end  vma-vm_start)
  +   return -EINVAL;
  +
  +   if (((vma-vm_end - vma-vm_start)  PAGE_SHIFT) != 1)
  +   return -EINVAL;
  +
  +   vma-vm_flags |= VM_RESERVED;
  +   vma-vm_ops = cs_char_vm_ops;
  +   vma-vm_private_data = file-private_data;
  +
  +   return 0;
  +}
  +
  +static int cs_char_open(struct inode *unused, struct file *file)
  +{
  +   int ret = 0;
  +
  +   spin_lock_bh(cs_char_data.lock);
  +   if (cs_char_data.opened) {
  +   ret = -EBUSY;
  +   spin_unlock_bh(cs_char_data.lock);
  +   goto out;
  +   }
  +   cs_char_data.mmap_base = get_zeroed_page(GFP_ATOMIC);
 
 This could be moved outside the locked sectionand use GFP_KERNEL.

Right, this is fixed by a follow up patch. I kept the patchset split
to keep authorship information. I guess I can squash the first three
patches, though.

  +   if (!cs_char_data.mmap_base) {
  +   dev_err(cs_char_data.cl-device,
  +   Shared memory allocation 

[PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-01 Thread Sebastian Reichel
From: Kai Vehmanen 

Introduces the cmt-speech driver, which implements
a character device interface for transferring speech
data frames over HSI/SSI.

The driver is used to exchange voice/speech data between
the Nokia N900/N950/N9's modem and its cpu.

Signed-off-by: Kai Vehmanen 
Signed-off-by: Carlos Chinea 
Signed-off-by: Joni Lapilainen 
Signed-off-by: Sebastian Reichel 
---
 drivers/hsi/clients/cmt_speech.c | 1426 ++
 include/linux/cs-protocol.h  |  116 
 2 files changed, 1542 insertions(+)
 create mode 100644 drivers/hsi/clients/cmt_speech.c
 create mode 100644 include/linux/cs-protocol.h

diff --git a/drivers/hsi/clients/cmt_speech.c b/drivers/hsi/clients/cmt_speech.c
new file mode 100644
index 000..7c0f711
--- /dev/null
+++ b/drivers/hsi/clients/cmt_speech.c
@@ -0,0 +1,1426 @@
+/*
+ * cmt_speech.c - HSI CMT speech driver
+ *
+ * Copyright (C) 2008,2009,2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Kai Vehmanen 
+ * Original author: Peter Ujfalusi 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define CS_MMAP_SIZE   PAGE_SIZE
+#define DRIVER_NAME"cmt_speech"
+
+struct char_queue {
+   struct list_headlist;
+   u32 msg;
+};
+
+struct cs_char {
+   unsigned intopened;
+   struct hsi_client   *cl;
+   struct cs_hsi_iface *hi;
+   struct list_headchardev_queue;
+   struct list_headdataind_queue;
+   int dataind_pending;
+   /* mmap things */
+   unsigned long   mmap_base;
+   unsigned long   mmap_size;
+   spinlock_t  lock;
+   struct fasync_struct*async_queue;
+   wait_queue_head_t   wait;
+};
+
+#define SSI_CHANNEL_STATE_READING  1
+#define SSI_CHANNEL_STATE_WRITING  (1 << 1)
+#define SSI_CHANNEL_STATE_POLL (1 << 2)
+#define SSI_CHANNEL_STATE_ERROR(1 << 3)
+
+#define CONTROL_HSI_CH 1
+#define DATA_HSI_CH2
+
+#define TARGET_MASK0xf00
+#define TARGET_REMOTE  (1 << CS_DOMAIN_SHIFT)
+#define TARGET_LOCAL   0
+
+/* Number of pre-allocated commands buffers */
+#define CS_MAX_CMDS4
+
+/*
+ * During data transfers, transactions must be handled
+ * within 20ms (fixed value in cmtspeech HSI protocol)
+ */
+#define CS_QOS_LATENCY_FOR_DATA_USEC   2
+
+/* Timeout to wait for pending HSI transfers to complete */
+#define CS_HSI_TRANSFER_TIMEOUT_MS  500
+
+
+#define RX_PTR_BOUNDARY_SHIFT  8
+#define RX_PTR_MAX_SHIFT   (RX_PTR_BOUNDARY_SHIFT + \
+   CS_MAX_BUFFERS_SHIFT)
+struct cs_hsi_iface {
+   struct hsi_client   *cl;
+   struct hsi_client   *master;
+
+   unsigned intiface_state;
+   unsigned intwakeline_state;
+   unsigned intcontrol_state;
+   unsigned intdata_state;
+
+   /* state exposed to application */
+   struct cs_mmap_config_block *mmap_cfg;
+
+   unsigned long   mmap_base;
+   unsigned long   mmap_size;
+
+   unsigned intrx_slot;
+   unsigned inttx_slot;
+
+   /* note: for security reasons, we do not trust the contents of
+* mmap_cfg, but instead duplicate the variables here */
+   unsigned intbuf_size;
+   unsigned intrx_bufs;
+   unsigned inttx_bufs;
+   unsigned intrx_ptr_boundary;
+   unsigned intrx_offsets[CS_MAX_BUFFERS];
+   unsigned inttx_offsets[CS_MAX_BUFFERS];
+   /* size of aligned memory blocks */
+   unsigned intslot_size;
+   unsigned intflags;
+
+   struct list_headcmdqueue;
+
+   struct hsi_msg  *data_rx_msg;
+   struct hsi_msg  *data_tx_msg;

[PATCH 1/9] HSI: cmt_speech: Add cmt-speech driver

2015-03-01 Thread Sebastian Reichel
From: Kai Vehmanen kai.vehma...@nokia.com

Introduces the cmt-speech driver, which implements
a character device interface for transferring speech
data frames over HSI/SSI.

The driver is used to exchange voice/speech data between
the Nokia N900/N950/N9's modem and its cpu.

Signed-off-by: Kai Vehmanen kai.vehma...@nokia.com
Signed-off-by: Carlos Chinea carlos.chi...@nokia.com
Signed-off-by: Joni Lapilainen joni.lapilai...@gmail.com
Signed-off-by: Sebastian Reichel s...@kernel.org
---
 drivers/hsi/clients/cmt_speech.c | 1426 ++
 include/linux/cs-protocol.h  |  116 
 2 files changed, 1542 insertions(+)
 create mode 100644 drivers/hsi/clients/cmt_speech.c
 create mode 100644 include/linux/cs-protocol.h

diff --git a/drivers/hsi/clients/cmt_speech.c b/drivers/hsi/clients/cmt_speech.c
new file mode 100644
index 000..7c0f711
--- /dev/null
+++ b/drivers/hsi/clients/cmt_speech.c
@@ -0,0 +1,1426 @@
+/*
+ * cmt_speech.c - HSI CMT speech driver
+ *
+ * Copyright (C) 2008,2009,2010 Nokia Corporation. All rights reserved.
+ *
+ * Contact: Kai Vehmanen kai.vehma...@nokia.com
+ * Original author: Peter Ujfalusi peter.ujfal...@nokia.com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include linux/errno.h
+#include linux/module.h
+#include linux/types.h
+#include linux/init.h
+#include linux/device.h
+#include linux/miscdevice.h
+#include linux/mm.h
+#include linux/slab.h
+#include linux/fs.h
+#include linux/poll.h
+#include linux/sched.h
+#include linux/ioctl.h
+#include linux/uaccess.h
+#include linux/pm_qos_params.h
+#include linux/hsi/hsi.h
+#include linux/hsi/ssip_slave.h
+#include linux/cs-protocol.h
+
+#define CS_MMAP_SIZE   PAGE_SIZE
+#define DRIVER_NAMEcmt_speech
+
+struct char_queue {
+   struct list_headlist;
+   u32 msg;
+};
+
+struct cs_char {
+   unsigned intopened;
+   struct hsi_client   *cl;
+   struct cs_hsi_iface *hi;
+   struct list_headchardev_queue;
+   struct list_headdataind_queue;
+   int dataind_pending;
+   /* mmap things */
+   unsigned long   mmap_base;
+   unsigned long   mmap_size;
+   spinlock_t  lock;
+   struct fasync_struct*async_queue;
+   wait_queue_head_t   wait;
+};
+
+#define SSI_CHANNEL_STATE_READING  1
+#define SSI_CHANNEL_STATE_WRITING  (1  1)
+#define SSI_CHANNEL_STATE_POLL (1  2)
+#define SSI_CHANNEL_STATE_ERROR(1  3)
+
+#define CONTROL_HSI_CH 1
+#define DATA_HSI_CH2
+
+#define TARGET_MASK0xf00
+#define TARGET_REMOTE  (1  CS_DOMAIN_SHIFT)
+#define TARGET_LOCAL   0
+
+/* Number of pre-allocated commands buffers */
+#define CS_MAX_CMDS4
+
+/*
+ * During data transfers, transactions must be handled
+ * within 20ms (fixed value in cmtspeech HSI protocol)
+ */
+#define CS_QOS_LATENCY_FOR_DATA_USEC   2
+
+/* Timeout to wait for pending HSI transfers to complete */
+#define CS_HSI_TRANSFER_TIMEOUT_MS  500
+
+
+#define RX_PTR_BOUNDARY_SHIFT  8
+#define RX_PTR_MAX_SHIFT   (RX_PTR_BOUNDARY_SHIFT + \
+   CS_MAX_BUFFERS_SHIFT)
+struct cs_hsi_iface {
+   struct hsi_client   *cl;
+   struct hsi_client   *master;
+
+   unsigned intiface_state;
+   unsigned intwakeline_state;
+   unsigned intcontrol_state;
+   unsigned intdata_state;
+
+   /* state exposed to application */
+   struct cs_mmap_config_block *mmap_cfg;
+
+   unsigned long   mmap_base;
+   unsigned long   mmap_size;
+
+   unsigned intrx_slot;
+   unsigned inttx_slot;
+
+   /* note: for security reasons, we do not trust the contents of
+* mmap_cfg, but instead duplicate the variables here */
+   unsigned intbuf_size;
+   unsigned intrx_bufs;
+   unsigned inttx_bufs;
+   unsigned intrx_ptr_boundary;
+   unsigned int