Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

HSI: cmt_speech: Add cmt-speech driver

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.vehmanen@nokia.com>
Signed-off-by: Carlos Chinea <carlos.chinea@nokia.com>
Signed-off-by: Joni Lapilainen <joni.lapilainen@gmail.com>

Since the original driver has been written for 2.6.28 some
build fixes and general cleanups have been added by me:

* fix build for 4.0 kernel
* replace GFP_ATOMIC with GFP_KERNEL in cs_alloc_cmds()
* add sanity check for CS_SET_WAKELINE ioctl
* cleanup driver initialisation
* rename driver to cmt-speech to be consistent with
ssi-protocol driver
* move cs-protocol.h to include/uapi/linux/hsi, since
it describes a userspace API
* replace hardcoded channels numbers with values provided
via the HSI framework (e.g. coming from DT)

Acked-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Tested-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Sebastian Reichel <sre@kernel.org>

authored by

Kai Vehmanen and committed by
Sebastian Reichel
7f62fe8a b2249129

+1581 -1
+10
drivers/hsi/clients/Kconfig
··· 13 13 14 14 If unsure, say N. 15 15 16 + config CMT_SPEECH 17 + tristate "CMT speech" 18 + depends on HSI && SSI_PROTOCOL 19 + help 20 + If you say Y here, you will enable the CMT speech protocol used 21 + by Nokia modems. If you say M the protocol will be available as 22 + module named cmt_speech. 23 + 24 + If unsure, say N. 25 + 16 26 config SSI_PROTOCOL 17 27 tristate "SSI protocol" 18 28 depends on HSI && PHONET && OMAP_SSI
+1
drivers/hsi/clients/Makefile
··· 4 4 5 5 obj-$(CONFIG_NOKIA_MODEM) += nokia-modem.o 6 6 obj-$(CONFIG_SSI_PROTOCOL) += ssi_protocol.o 7 + obj-$(CONFIG_CMT_SPEECH) += cmt_speech.o 7 8 obj-$(CONFIG_HSI_CHAR) += hsi_char.o
+1456
drivers/hsi/clients/cmt_speech.c
··· 1 + /* 2 + * cmt_speech.c - HSI CMT speech driver 3 + * 4 + * Copyright (C) 2008,2009,2010 Nokia Corporation. All rights reserved. 5 + * 6 + * Contact: Kai Vehmanen <kai.vehmanen@nokia.com> 7 + * Original author: Peter Ujfalusi <peter.ujfalusi@nokia.com> 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License 11 + * version 2 as published by the Free Software Foundation. 12 + * 13 + * This program is distributed in the hope that it will be useful, but 14 + * WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 + * General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 + * 02110-1301 USA 22 + */ 23 + 24 + #include <linux/errno.h> 25 + #include <linux/module.h> 26 + #include <linux/types.h> 27 + #include <linux/init.h> 28 + #include <linux/device.h> 29 + #include <linux/miscdevice.h> 30 + #include <linux/mm.h> 31 + #include <linux/slab.h> 32 + #include <linux/fs.h> 33 + #include <linux/poll.h> 34 + #include <linux/sched.h> 35 + #include <linux/ioctl.h> 36 + #include <linux/uaccess.h> 37 + #include <linux/pm_qos.h> 38 + #include <linux/hsi/hsi.h> 39 + #include <linux/hsi/ssi_protocol.h> 40 + #include <linux/hsi/cs-protocol.h> 41 + 42 + #define CS_MMAP_SIZE PAGE_SIZE 43 + 44 + struct char_queue { 45 + struct list_head list; 46 + u32 msg; 47 + }; 48 + 49 + struct cs_char { 50 + unsigned int opened; 51 + struct hsi_client *cl; 52 + struct cs_hsi_iface *hi; 53 + struct list_head chardev_queue; 54 + struct list_head dataind_queue; 55 + int dataind_pending; 56 + /* mmap things */ 57 + unsigned long mmap_base; 58 + unsigned long mmap_size; 59 + spinlock_t lock; 60 + struct fasync_struct *async_queue; 61 + wait_queue_head_t wait; 62 + /* hsi channel ids */ 63 + int channel_id_cmd; 64 + int channel_id_data; 65 + }; 66 + 67 + #define SSI_CHANNEL_STATE_READING 1 68 + #define SSI_CHANNEL_STATE_WRITING (1 << 1) 69 + #define SSI_CHANNEL_STATE_POLL (1 << 2) 70 + #define SSI_CHANNEL_STATE_ERROR (1 << 3) 71 + 72 + #define TARGET_MASK 0xf000000 73 + #define TARGET_REMOTE (1 << CS_DOMAIN_SHIFT) 74 + #define TARGET_LOCAL 0 75 + 76 + /* Number of pre-allocated commands buffers */ 77 + #define CS_MAX_CMDS 4 78 + 79 + /* 80 + * During data transfers, transactions must be handled 81 + * within 20ms (fixed value in cmtspeech HSI protocol) 82 + */ 83 + #define CS_QOS_LATENCY_FOR_DATA_USEC 20000 84 + 85 + /* Timeout to wait for pending HSI transfers to complete */ 86 + #define CS_HSI_TRANSFER_TIMEOUT_MS 500 87 + 88 + 89 + #define RX_PTR_BOUNDARY_SHIFT 8 90 + #define RX_PTR_MAX_SHIFT (RX_PTR_BOUNDARY_SHIFT + \ 91 + CS_MAX_BUFFERS_SHIFT) 92 + struct cs_hsi_iface { 93 + struct hsi_client *cl; 94 + struct hsi_client *master; 95 + 96 + unsigned int iface_state; 97 + unsigned int wakeline_state; 98 + unsigned int control_state; 99 + unsigned int data_state; 100 + 101 + /* state exposed to application */ 102 + struct cs_mmap_config_block *mmap_cfg; 103 + 104 + unsigned long mmap_base; 105 + unsigned long mmap_size; 106 + 107 + unsigned int rx_slot; 108 + unsigned int tx_slot; 109 + 110 + /* note: for security reasons, we do not trust the contents of 111 + * mmap_cfg, but instead duplicate the variables here */ 112 + unsigned int buf_size; 113 + unsigned int rx_bufs; 114 + unsigned int tx_bufs; 115 + unsigned int rx_ptr_boundary; 116 + unsigned int rx_offsets[CS_MAX_BUFFERS]; 117 + unsigned int tx_offsets[CS_MAX_BUFFERS]; 118 + 119 + /* size of aligned memory blocks */ 120 + unsigned int slot_size; 121 + unsigned int flags; 122 + 123 + struct list_head cmdqueue; 124 + 125 + struct hsi_msg *data_rx_msg; 126 + struct hsi_msg *data_tx_msg; 127 + wait_queue_head_t datawait; 128 + 129 + struct pm_qos_request pm_qos_req; 130 + 131 + spinlock_t lock; 132 + }; 133 + 134 + static struct cs_char cs_char_data; 135 + 136 + static void cs_hsi_read_on_control(struct cs_hsi_iface *hi); 137 + static void cs_hsi_read_on_data(struct cs_hsi_iface *hi); 138 + 139 + static inline void rx_ptr_shift_too_big(void) 140 + { 141 + BUILD_BUG_ON((1LLU << RX_PTR_MAX_SHIFT) > UINT_MAX); 142 + } 143 + 144 + static void cs_notify(u32 message, struct list_head *head) 145 + { 146 + struct char_queue *entry; 147 + 148 + spin_lock(&cs_char_data.lock); 149 + 150 + if (!cs_char_data.opened) { 151 + spin_unlock(&cs_char_data.lock); 152 + goto out; 153 + } 154 + 155 + entry = kmalloc(sizeof(*entry), GFP_ATOMIC); 156 + if (!entry) { 157 + dev_err(&cs_char_data.cl->device, 158 + "Can't allocate new entry for the queue.\n"); 159 + spin_unlock(&cs_char_data.lock); 160 + goto out; 161 + } 162 + 163 + entry->msg = message; 164 + list_add_tail(&entry->list, head); 165 + 166 + spin_unlock(&cs_char_data.lock); 167 + 168 + wake_up_interruptible(&cs_char_data.wait); 169 + kill_fasync(&cs_char_data.async_queue, SIGIO, POLL_IN); 170 + 171 + out: 172 + return; 173 + } 174 + 175 + static u32 cs_pop_entry(struct list_head *head) 176 + { 177 + struct char_queue *entry; 178 + u32 data; 179 + 180 + entry = list_entry(head->next, struct char_queue, list); 181 + data = entry->msg; 182 + list_del(&entry->list); 183 + kfree(entry); 184 + 185 + return data; 186 + } 187 + 188 + static void cs_notify_control(u32 message) 189 + { 190 + cs_notify(message, &cs_char_data.chardev_queue); 191 + } 192 + 193 + static void cs_notify_data(u32 message, int maxlength) 194 + { 195 + cs_notify(message, &cs_char_data.dataind_queue); 196 + 197 + spin_lock(&cs_char_data.lock); 198 + cs_char_data.dataind_pending++; 199 + while (cs_char_data.dataind_pending > maxlength && 200 + !list_empty(&cs_char_data.dataind_queue)) { 201 + dev_dbg(&cs_char_data.cl->device, "data notification " 202 + "queue overrun (%u entries)\n", cs_char_data.dataind_pending); 203 + 204 + cs_pop_entry(&cs_char_data.dataind_queue); 205 + cs_char_data.dataind_pending--; 206 + } 207 + spin_unlock(&cs_char_data.lock); 208 + } 209 + 210 + static inline void cs_set_cmd(struct hsi_msg *msg, u32 cmd) 211 + { 212 + u32 *data = sg_virt(msg->sgt.sgl); 213 + *data = cmd; 214 + } 215 + 216 + static inline u32 cs_get_cmd(struct hsi_msg *msg) 217 + { 218 + u32 *data = sg_virt(msg->sgt.sgl); 219 + return *data; 220 + } 221 + 222 + static void cs_release_cmd(struct hsi_msg *msg) 223 + { 224 + struct cs_hsi_iface *hi = msg->context; 225 + 226 + list_add_tail(&msg->link, &hi->cmdqueue); 227 + } 228 + 229 + static void cs_cmd_destructor(struct hsi_msg *msg) 230 + { 231 + struct cs_hsi_iface *hi = msg->context; 232 + 233 + spin_lock(&hi->lock); 234 + 235 + dev_dbg(&cs_char_data.cl->device, "control cmd destructor\n"); 236 + 237 + if (hi->iface_state != CS_STATE_CLOSED) 238 + dev_err(&hi->cl->device, "Cmd flushed while driver active\n"); 239 + 240 + if (msg->ttype == HSI_MSG_READ) 241 + hi->control_state &= 242 + ~(SSI_CHANNEL_STATE_POLL | SSI_CHANNEL_STATE_READING); 243 + else if (msg->ttype == HSI_MSG_WRITE && 244 + hi->control_state & SSI_CHANNEL_STATE_WRITING) 245 + hi->control_state &= ~SSI_CHANNEL_STATE_WRITING; 246 + 247 + cs_release_cmd(msg); 248 + 249 + spin_unlock(&hi->lock); 250 + } 251 + 252 + static struct hsi_msg *cs_claim_cmd(struct cs_hsi_iface* ssi) 253 + { 254 + struct hsi_msg *msg; 255 + 256 + BUG_ON(list_empty(&ssi->cmdqueue)); 257 + 258 + msg = list_first_entry(&ssi->cmdqueue, struct hsi_msg, link); 259 + list_del(&msg->link); 260 + msg->destructor = cs_cmd_destructor; 261 + 262 + return msg; 263 + } 264 + 265 + static void cs_free_cmds(struct cs_hsi_iface *ssi) 266 + { 267 + struct hsi_msg *msg, *tmp; 268 + 269 + list_for_each_entry_safe(msg, tmp, &ssi->cmdqueue, link) { 270 + list_del(&msg->link); 271 + msg->destructor = NULL; 272 + kfree(sg_virt(msg->sgt.sgl)); 273 + hsi_free_msg(msg); 274 + } 275 + } 276 + 277 + static int cs_alloc_cmds(struct cs_hsi_iface *hi) 278 + { 279 + struct hsi_msg *msg; 280 + u32 *buf; 281 + unsigned int i; 282 + 283 + INIT_LIST_HEAD(&hi->cmdqueue); 284 + 285 + for (i = 0; i < CS_MAX_CMDS; i++) { 286 + msg = hsi_alloc_msg(1, GFP_KERNEL); 287 + if (!msg) 288 + goto out; 289 + buf = kmalloc(sizeof(*buf), GFP_KERNEL); 290 + if (!buf) { 291 + hsi_free_msg(msg); 292 + goto out; 293 + } 294 + sg_init_one(msg->sgt.sgl, buf, sizeof(*buf)); 295 + msg->channel = cs_char_data.channel_id_cmd; 296 + msg->context = hi; 297 + list_add_tail(&msg->link, &hi->cmdqueue); 298 + } 299 + 300 + return 0; 301 + 302 + out: 303 + cs_free_cmds(hi); 304 + return -ENOMEM; 305 + } 306 + 307 + static void cs_hsi_data_destructor(struct hsi_msg *msg) 308 + { 309 + struct cs_hsi_iface *hi = msg->context; 310 + const char *dir = (msg->ttype == HSI_MSG_READ) ? "TX" : "RX"; 311 + 312 + dev_dbg(&cs_char_data.cl->device, "Freeing data %s message\n", dir); 313 + 314 + spin_lock(&hi->lock); 315 + if (hi->iface_state != CS_STATE_CLOSED) 316 + dev_err(&cs_char_data.cl->device, 317 + "Data %s flush while device active\n", dir); 318 + if (msg->ttype == HSI_MSG_READ) 319 + hi->data_state &= 320 + ~(SSI_CHANNEL_STATE_POLL | SSI_CHANNEL_STATE_READING); 321 + else 322 + hi->data_state &= ~SSI_CHANNEL_STATE_WRITING; 323 + 324 + msg->status = HSI_STATUS_COMPLETED; 325 + if (unlikely(waitqueue_active(&hi->datawait))) 326 + wake_up_interruptible(&hi->datawait); 327 + 328 + spin_unlock(&hi->lock); 329 + } 330 + 331 + static int cs_hsi_alloc_data(struct cs_hsi_iface *hi) 332 + { 333 + struct hsi_msg *txmsg, *rxmsg; 334 + int res = 0; 335 + 336 + rxmsg = hsi_alloc_msg(1, GFP_KERNEL); 337 + if (!rxmsg) { 338 + res = -ENOMEM; 339 + goto out1; 340 + } 341 + rxmsg->channel = cs_char_data.channel_id_data; 342 + rxmsg->destructor = cs_hsi_data_destructor; 343 + rxmsg->context = hi; 344 + 345 + txmsg = hsi_alloc_msg(1, GFP_KERNEL); 346 + if (!txmsg) { 347 + res = -ENOMEM; 348 + goto out2; 349 + } 350 + txmsg->channel = cs_char_data.channel_id_data; 351 + txmsg->destructor = cs_hsi_data_destructor; 352 + txmsg->context = hi; 353 + 354 + hi->data_rx_msg = rxmsg; 355 + hi->data_tx_msg = txmsg; 356 + 357 + return 0; 358 + 359 + out2: 360 + hsi_free_msg(rxmsg); 361 + out1: 362 + return res; 363 + } 364 + 365 + static void cs_hsi_free_data_msg(struct hsi_msg *msg) 366 + { 367 + WARN_ON(msg->status != HSI_STATUS_COMPLETED && 368 + msg->status != HSI_STATUS_ERROR); 369 + hsi_free_msg(msg); 370 + } 371 + 372 + static void cs_hsi_free_data(struct cs_hsi_iface *hi) 373 + { 374 + cs_hsi_free_data_msg(hi->data_rx_msg); 375 + cs_hsi_free_data_msg(hi->data_tx_msg); 376 + } 377 + 378 + static inline void __cs_hsi_error_pre(struct cs_hsi_iface *hi, 379 + struct hsi_msg *msg, const char *info, 380 + unsigned int *state) 381 + { 382 + spin_lock(&hi->lock); 383 + dev_err(&hi->cl->device, "HSI %s error, msg %d, state %u\n", 384 + info, msg->status, *state); 385 + } 386 + 387 + static inline void __cs_hsi_error_post(struct cs_hsi_iface *hi) 388 + { 389 + spin_unlock(&hi->lock); 390 + } 391 + 392 + static inline void __cs_hsi_error_read_bits(unsigned int *state) 393 + { 394 + *state |= SSI_CHANNEL_STATE_ERROR; 395 + *state &= ~(SSI_CHANNEL_STATE_READING | SSI_CHANNEL_STATE_POLL); 396 + } 397 + 398 + static inline void __cs_hsi_error_write_bits(unsigned int *state) 399 + { 400 + *state |= SSI_CHANNEL_STATE_ERROR; 401 + *state &= ~SSI_CHANNEL_STATE_WRITING; 402 + } 403 + 404 + static void cs_hsi_control_read_error(struct cs_hsi_iface *hi, 405 + struct hsi_msg *msg) 406 + { 407 + __cs_hsi_error_pre(hi, msg, "control read", &hi->control_state); 408 + cs_release_cmd(msg); 409 + __cs_hsi_error_read_bits(&hi->control_state); 410 + __cs_hsi_error_post(hi); 411 + } 412 + 413 + static void cs_hsi_control_write_error(struct cs_hsi_iface *hi, 414 + struct hsi_msg *msg) 415 + { 416 + __cs_hsi_error_pre(hi, msg, "control write", &hi->control_state); 417 + cs_release_cmd(msg); 418 + __cs_hsi_error_write_bits(&hi->control_state); 419 + __cs_hsi_error_post(hi); 420 + 421 + } 422 + 423 + static void cs_hsi_data_read_error(struct cs_hsi_iface *hi, struct hsi_msg *msg) 424 + { 425 + __cs_hsi_error_pre(hi, msg, "data read", &hi->data_state); 426 + __cs_hsi_error_read_bits(&hi->data_state); 427 + __cs_hsi_error_post(hi); 428 + } 429 + 430 + static void cs_hsi_data_write_error(struct cs_hsi_iface *hi, 431 + struct hsi_msg *msg) 432 + { 433 + __cs_hsi_error_pre(hi, msg, "data write", &hi->data_state); 434 + __cs_hsi_error_write_bits(&hi->data_state); 435 + __cs_hsi_error_post(hi); 436 + } 437 + 438 + static void cs_hsi_read_on_control_complete(struct hsi_msg *msg) 439 + { 440 + u32 cmd = cs_get_cmd(msg); 441 + struct cs_hsi_iface *hi = msg->context; 442 + 443 + spin_lock(&hi->lock); 444 + hi->control_state &= ~SSI_CHANNEL_STATE_READING; 445 + if (msg->status == HSI_STATUS_ERROR) { 446 + dev_err(&hi->cl->device, "Control RX error detected\n"); 447 + cs_hsi_control_read_error(hi, msg); 448 + spin_unlock(&hi->lock); 449 + goto out; 450 + } 451 + dev_dbg(&hi->cl->device, "Read on control: %08X\n", cmd); 452 + cs_release_cmd(msg); 453 + if (hi->flags & CS_FEAT_TSTAMP_RX_CTRL) { 454 + struct timespec *tstamp = 455 + &hi->mmap_cfg->tstamp_rx_ctrl; 456 + do_posix_clock_monotonic_gettime(tstamp); 457 + } 458 + spin_unlock(&hi->lock); 459 + 460 + cs_notify_control(cmd); 461 + 462 + out: 463 + cs_hsi_read_on_control(hi); 464 + } 465 + 466 + static void cs_hsi_peek_on_control_complete(struct hsi_msg *msg) 467 + { 468 + struct cs_hsi_iface *hi = msg->context; 469 + int ret; 470 + 471 + if (msg->status == HSI_STATUS_ERROR) { 472 + dev_err(&hi->cl->device, "Control peek RX error detected\n"); 473 + cs_hsi_control_read_error(hi, msg); 474 + return; 475 + } 476 + 477 + WARN_ON(!(hi->control_state & SSI_CHANNEL_STATE_READING)); 478 + 479 + dev_dbg(&hi->cl->device, "Peek on control complete, reading\n"); 480 + msg->sgt.nents = 1; 481 + msg->complete = cs_hsi_read_on_control_complete; 482 + ret = hsi_async_read(hi->cl, msg); 483 + if (ret) 484 + cs_hsi_control_read_error(hi, msg); 485 + } 486 + 487 + static void cs_hsi_read_on_control(struct cs_hsi_iface *hi) 488 + { 489 + struct hsi_msg *msg; 490 + int ret; 491 + 492 + spin_lock(&hi->lock); 493 + if (hi->control_state & SSI_CHANNEL_STATE_READING) { 494 + dev_err(&hi->cl->device, "Control read already pending (%d)\n", 495 + hi->control_state); 496 + spin_unlock(&hi->lock); 497 + return; 498 + } 499 + if (hi->control_state & SSI_CHANNEL_STATE_ERROR) { 500 + dev_err(&hi->cl->device, "Control read error (%d)\n", 501 + hi->control_state); 502 + spin_unlock(&hi->lock); 503 + return; 504 + } 505 + hi->control_state |= SSI_CHANNEL_STATE_READING; 506 + dev_dbg(&hi->cl->device, "Issuing RX on control\n"); 507 + msg = cs_claim_cmd(hi); 508 + spin_unlock(&hi->lock); 509 + 510 + msg->sgt.nents = 0; 511 + msg->complete = cs_hsi_peek_on_control_complete; 512 + ret = hsi_async_read(hi->cl, msg); 513 + if (ret) 514 + cs_hsi_control_read_error(hi, msg); 515 + } 516 + 517 + static void cs_hsi_write_on_control_complete(struct hsi_msg *msg) 518 + { 519 + struct cs_hsi_iface *hi = msg->context; 520 + if (msg->status == HSI_STATUS_COMPLETED) { 521 + spin_lock(&hi->lock); 522 + hi->control_state &= ~SSI_CHANNEL_STATE_WRITING; 523 + cs_release_cmd(msg); 524 + spin_unlock(&hi->lock); 525 + } else if (msg->status == HSI_STATUS_ERROR) { 526 + cs_hsi_control_write_error(hi, msg); 527 + } else { 528 + dev_err(&hi->cl->device, 529 + "unexpected status in control write callback %d\n", 530 + msg->status); 531 + } 532 + } 533 + 534 + static int cs_hsi_write_on_control(struct cs_hsi_iface *hi, u32 message) 535 + { 536 + struct hsi_msg *msg; 537 + int ret; 538 + 539 + spin_lock(&hi->lock); 540 + if (hi->control_state & SSI_CHANNEL_STATE_ERROR) { 541 + spin_unlock(&hi->lock); 542 + return -EIO; 543 + } 544 + if (hi->control_state & SSI_CHANNEL_STATE_WRITING) { 545 + dev_err(&hi->cl->device, 546 + "Write still pending on control channel.\n"); 547 + spin_unlock(&hi->lock); 548 + return -EBUSY; 549 + } 550 + hi->control_state |= SSI_CHANNEL_STATE_WRITING; 551 + msg = cs_claim_cmd(hi); 552 + spin_unlock(&hi->lock); 553 + 554 + cs_set_cmd(msg, message); 555 + msg->sgt.nents = 1; 556 + msg->complete = cs_hsi_write_on_control_complete; 557 + dev_dbg(&hi->cl->device, 558 + "Sending control message %08X\n", message); 559 + ret = hsi_async_write(hi->cl, msg); 560 + if (ret) { 561 + dev_err(&hi->cl->device, 562 + "async_write failed with %d\n", ret); 563 + cs_hsi_control_write_error(hi, msg); 564 + } 565 + 566 + /* 567 + * Make sure control read is always pending when issuing 568 + * new control writes. This is needed as the controller 569 + * may flush our messages if e.g. the peer device reboots 570 + * unexpectedly (and we cannot directly resubmit a new read from 571 + * the message destructor; see cs_cmd_destructor()). 572 + */ 573 + if (!(hi->control_state & SSI_CHANNEL_STATE_READING)) { 574 + dev_err(&hi->cl->device, "Restarting control reads\n"); 575 + cs_hsi_read_on_control(hi); 576 + } 577 + 578 + return 0; 579 + } 580 + 581 + static void cs_hsi_read_on_data_complete(struct hsi_msg *msg) 582 + { 583 + struct cs_hsi_iface *hi = msg->context; 584 + u32 payload; 585 + 586 + if (unlikely(msg->status == HSI_STATUS_ERROR)) { 587 + cs_hsi_data_read_error(hi, msg); 588 + return; 589 + } 590 + 591 + spin_lock(&hi->lock); 592 + WARN_ON(!(hi->data_state & SSI_CHANNEL_STATE_READING)); 593 + hi->data_state &= ~SSI_CHANNEL_STATE_READING; 594 + payload = CS_RX_DATA_RECEIVED; 595 + payload |= hi->rx_slot; 596 + hi->rx_slot++; 597 + hi->rx_slot %= hi->rx_ptr_boundary; 598 + /* expose current rx ptr in mmap area */ 599 + hi->mmap_cfg->rx_ptr = hi->rx_slot; 600 + if (unlikely(waitqueue_active(&hi->datawait))) 601 + wake_up_interruptible(&hi->datawait); 602 + spin_unlock(&hi->lock); 603 + 604 + cs_notify_data(payload, hi->rx_bufs); 605 + cs_hsi_read_on_data(hi); 606 + } 607 + 608 + static void cs_hsi_peek_on_data_complete(struct hsi_msg *msg) 609 + { 610 + struct cs_hsi_iface *hi = msg->context; 611 + u32 *address; 612 + int ret; 613 + 614 + if (unlikely(msg->status == HSI_STATUS_ERROR)) { 615 + cs_hsi_data_read_error(hi, msg); 616 + return; 617 + } 618 + if (unlikely(hi->iface_state != CS_STATE_CONFIGURED)) { 619 + dev_err(&hi->cl->device, "Data received in invalid state\n"); 620 + cs_hsi_data_read_error(hi, msg); 621 + return; 622 + } 623 + 624 + spin_lock(&hi->lock); 625 + WARN_ON(!(hi->data_state & SSI_CHANNEL_STATE_POLL)); 626 + hi->data_state &= ~SSI_CHANNEL_STATE_POLL; 627 + hi->data_state |= SSI_CHANNEL_STATE_READING; 628 + spin_unlock(&hi->lock); 629 + 630 + address = (u32 *)(hi->mmap_base + 631 + hi->rx_offsets[hi->rx_slot % hi->rx_bufs]); 632 + sg_init_one(msg->sgt.sgl, address, hi->buf_size); 633 + msg->sgt.nents = 1; 634 + msg->complete = cs_hsi_read_on_data_complete; 635 + ret = hsi_async_read(hi->cl, msg); 636 + if (ret) 637 + cs_hsi_data_read_error(hi, msg); 638 + } 639 + 640 + /* 641 + * Read/write transaction is ongoing. Returns false if in 642 + * SSI_CHANNEL_STATE_POLL state. 643 + */ 644 + static inline int cs_state_xfer_active(unsigned int state) 645 + { 646 + return (state & SSI_CHANNEL_STATE_WRITING) || 647 + (state & SSI_CHANNEL_STATE_READING); 648 + } 649 + 650 + /* 651 + * No pending read/writes 652 + */ 653 + static inline int cs_state_idle(unsigned int state) 654 + { 655 + return !(state & ~SSI_CHANNEL_STATE_ERROR); 656 + } 657 + 658 + static void cs_hsi_read_on_data(struct cs_hsi_iface *hi) 659 + { 660 + struct hsi_msg *rxmsg; 661 + int ret; 662 + 663 + spin_lock(&hi->lock); 664 + if (hi->data_state & 665 + (SSI_CHANNEL_STATE_READING | SSI_CHANNEL_STATE_POLL)) { 666 + dev_dbg(&hi->cl->device, "Data read already pending (%u)\n", 667 + hi->data_state); 668 + spin_unlock(&hi->lock); 669 + return; 670 + } 671 + hi->data_state |= SSI_CHANNEL_STATE_POLL; 672 + spin_unlock(&hi->lock); 673 + 674 + rxmsg = hi->data_rx_msg; 675 + sg_init_one(rxmsg->sgt.sgl, (void *)hi->mmap_base, 0); 676 + rxmsg->sgt.nents = 0; 677 + rxmsg->complete = cs_hsi_peek_on_data_complete; 678 + 679 + ret = hsi_async_read(hi->cl, rxmsg); 680 + if (ret) 681 + cs_hsi_data_read_error(hi, rxmsg); 682 + } 683 + 684 + static void cs_hsi_write_on_data_complete(struct hsi_msg *msg) 685 + { 686 + struct cs_hsi_iface *hi = msg->context; 687 + 688 + if (msg->status == HSI_STATUS_COMPLETED) { 689 + spin_lock(&hi->lock); 690 + hi->data_state &= ~SSI_CHANNEL_STATE_WRITING; 691 + if (unlikely(waitqueue_active(&hi->datawait))) 692 + wake_up_interruptible(&hi->datawait); 693 + spin_unlock(&hi->lock); 694 + } else { 695 + cs_hsi_data_write_error(hi, msg); 696 + } 697 + } 698 + 699 + static int cs_hsi_write_on_data(struct cs_hsi_iface *hi, unsigned int slot) 700 + { 701 + u32 *address; 702 + struct hsi_msg *txmsg; 703 + int ret; 704 + 705 + spin_lock(&hi->lock); 706 + if (hi->iface_state != CS_STATE_CONFIGURED) { 707 + dev_err(&hi->cl->device, "Not configured, aborting\n"); 708 + ret = -EINVAL; 709 + goto error; 710 + } 711 + if (hi->data_state & SSI_CHANNEL_STATE_ERROR) { 712 + dev_err(&hi->cl->device, "HSI error, aborting\n"); 713 + ret = -EIO; 714 + goto error; 715 + } 716 + if (hi->data_state & SSI_CHANNEL_STATE_WRITING) { 717 + dev_err(&hi->cl->device, "Write pending on data channel.\n"); 718 + ret = -EBUSY; 719 + goto error; 720 + } 721 + hi->data_state |= SSI_CHANNEL_STATE_WRITING; 722 + spin_unlock(&hi->lock); 723 + 724 + hi->tx_slot = slot; 725 + address = (u32 *)(hi->mmap_base + hi->tx_offsets[hi->tx_slot]); 726 + txmsg = hi->data_tx_msg; 727 + sg_init_one(txmsg->sgt.sgl, address, hi->buf_size); 728 + txmsg->complete = cs_hsi_write_on_data_complete; 729 + ret = hsi_async_write(hi->cl, txmsg); 730 + if (ret) 731 + cs_hsi_data_write_error(hi, txmsg); 732 + 733 + return ret; 734 + 735 + error: 736 + spin_unlock(&hi->lock); 737 + if (ret == -EIO) 738 + cs_hsi_data_write_error(hi, hi->data_tx_msg); 739 + 740 + return ret; 741 + } 742 + 743 + static unsigned int cs_hsi_get_state(struct cs_hsi_iface *hi) 744 + { 745 + return hi->iface_state; 746 + } 747 + 748 + static int cs_hsi_command(struct cs_hsi_iface *hi, u32 cmd) 749 + { 750 + int ret = 0; 751 + 752 + local_bh_disable(); 753 + switch (cmd & TARGET_MASK) { 754 + case TARGET_REMOTE: 755 + ret = cs_hsi_write_on_control(hi, cmd); 756 + break; 757 + case TARGET_LOCAL: 758 + if ((cmd & CS_CMD_MASK) == CS_TX_DATA_READY) 759 + ret = cs_hsi_write_on_data(hi, cmd & CS_PARAM_MASK); 760 + else 761 + ret = -EINVAL; 762 + break; 763 + default: 764 + ret = -EINVAL; 765 + break; 766 + } 767 + local_bh_enable(); 768 + 769 + return ret; 770 + } 771 + 772 + static void cs_hsi_set_wakeline(struct cs_hsi_iface *hi, bool new_state) 773 + { 774 + int change = 0; 775 + 776 + spin_lock_bh(&hi->lock); 777 + if (hi->wakeline_state != new_state) { 778 + hi->wakeline_state = new_state; 779 + change = 1; 780 + dev_dbg(&hi->cl->device, "setting wake line to %d (%p)\n", 781 + new_state, hi->cl); 782 + } 783 + spin_unlock_bh(&hi->lock); 784 + 785 + if (change) { 786 + if (new_state) 787 + ssip_slave_start_tx(hi->master); 788 + else 789 + ssip_slave_stop_tx(hi->master); 790 + } 791 + 792 + dev_dbg(&hi->cl->device, "wake line set to %d (%p)\n", 793 + new_state, hi->cl); 794 + } 795 + 796 + static void set_buffer_sizes(struct cs_hsi_iface *hi, int rx_bufs, int tx_bufs) 797 + { 798 + hi->rx_bufs = rx_bufs; 799 + hi->tx_bufs = tx_bufs; 800 + hi->mmap_cfg->rx_bufs = rx_bufs; 801 + hi->mmap_cfg->tx_bufs = tx_bufs; 802 + 803 + if (hi->flags & CS_FEAT_ROLLING_RX_COUNTER) { 804 + /* 805 + * For more robust overrun detection, let the rx 806 + * pointer run in range 0..'boundary-1'. Boundary 807 + * is a multiple of rx_bufs, and limited in max size 808 + * by RX_PTR_MAX_SHIFT to allow for fast ptr-diff 809 + * calculation. 810 + */ 811 + hi->rx_ptr_boundary = (rx_bufs << RX_PTR_BOUNDARY_SHIFT); 812 + hi->mmap_cfg->rx_ptr_boundary = hi->rx_ptr_boundary; 813 + } else { 814 + hi->rx_ptr_boundary = hi->rx_bufs; 815 + } 816 + } 817 + 818 + static int check_buf_params(struct cs_hsi_iface *hi, 819 + const struct cs_buffer_config *buf_cfg) 820 + { 821 + size_t buf_size_aligned = L1_CACHE_ALIGN(buf_cfg->buf_size) * 822 + (buf_cfg->rx_bufs + buf_cfg->tx_bufs); 823 + size_t ctrl_size_aligned = L1_CACHE_ALIGN(sizeof(*hi->mmap_cfg)); 824 + int r = 0; 825 + 826 + if (buf_cfg->rx_bufs > CS_MAX_BUFFERS || 827 + buf_cfg->tx_bufs > CS_MAX_BUFFERS) { 828 + r = -EINVAL; 829 + } else if ((buf_size_aligned + ctrl_size_aligned) >= hi->mmap_size) { 830 + dev_err(&hi->cl->device, "No space for the requested buffer " 831 + "configuration\n"); 832 + r = -ENOBUFS; 833 + } 834 + 835 + return r; 836 + } 837 + 838 + /** 839 + * Block until pending data transfers have completed. 840 + */ 841 + static int cs_hsi_data_sync(struct cs_hsi_iface *hi) 842 + { 843 + int r = 0; 844 + 845 + spin_lock_bh(&hi->lock); 846 + 847 + if (!cs_state_xfer_active(hi->data_state)) { 848 + dev_dbg(&hi->cl->device, "hsi_data_sync break, idle\n"); 849 + goto out; 850 + } 851 + 852 + for (;;) { 853 + int s; 854 + DEFINE_WAIT(wait); 855 + if (!cs_state_xfer_active(hi->data_state)) 856 + goto out; 857 + if (signal_pending(current)) { 858 + r = -ERESTARTSYS; 859 + goto out; 860 + } 861 + /** 862 + * prepare_to_wait must be called with hi->lock held 863 + * so that callbacks can check for waitqueue_active() 864 + */ 865 + prepare_to_wait(&hi->datawait, &wait, TASK_INTERRUPTIBLE); 866 + spin_unlock_bh(&hi->lock); 867 + s = schedule_timeout( 868 + msecs_to_jiffies(CS_HSI_TRANSFER_TIMEOUT_MS)); 869 + spin_lock_bh(&hi->lock); 870 + finish_wait(&hi->datawait, &wait); 871 + if (!s) { 872 + dev_dbg(&hi->cl->device, 873 + "hsi_data_sync timeout after %d ms\n", 874 + CS_HSI_TRANSFER_TIMEOUT_MS); 875 + r = -EIO; 876 + goto out; 877 + } 878 + } 879 + 880 + out: 881 + spin_unlock_bh(&hi->lock); 882 + dev_dbg(&hi->cl->device, "hsi_data_sync done with res %d\n", r); 883 + 884 + return r; 885 + } 886 + 887 + static void cs_hsi_data_enable(struct cs_hsi_iface *hi, 888 + struct cs_buffer_config *buf_cfg) 889 + { 890 + unsigned int data_start, i; 891 + 892 + BUG_ON(hi->buf_size == 0); 893 + 894 + set_buffer_sizes(hi, buf_cfg->rx_bufs, buf_cfg->tx_bufs); 895 + 896 + hi->slot_size = L1_CACHE_ALIGN(hi->buf_size); 897 + dev_dbg(&hi->cl->device, 898 + "setting slot size to %u, buf size %u, align %u\n", 899 + hi->slot_size, hi->buf_size, L1_CACHE_BYTES); 900 + 901 + data_start = L1_CACHE_ALIGN(sizeof(*hi->mmap_cfg)); 902 + dev_dbg(&hi->cl->device, 903 + "setting data start at %u, cfg block %u, align %u\n", 904 + data_start, sizeof(*hi->mmap_cfg), L1_CACHE_BYTES); 905 + 906 + for (i = 0; i < hi->mmap_cfg->rx_bufs; i++) { 907 + hi->rx_offsets[i] = data_start + i * hi->slot_size; 908 + hi->mmap_cfg->rx_offsets[i] = hi->rx_offsets[i]; 909 + dev_dbg(&hi->cl->device, "DL buf #%u at %u\n", 910 + i, hi->rx_offsets[i]); 911 + } 912 + for (i = 0; i < hi->mmap_cfg->tx_bufs; i++) { 913 + hi->tx_offsets[i] = data_start + 914 + (i + hi->mmap_cfg->rx_bufs) * hi->slot_size; 915 + hi->mmap_cfg->tx_offsets[i] = hi->tx_offsets[i]; 916 + dev_dbg(&hi->cl->device, "UL buf #%u at %u\n", 917 + i, hi->rx_offsets[i]); 918 + } 919 + 920 + hi->iface_state = CS_STATE_CONFIGURED; 921 + } 922 + 923 + static void cs_hsi_data_disable(struct cs_hsi_iface *hi, int old_state) 924 + { 925 + if (old_state == CS_STATE_CONFIGURED) { 926 + dev_dbg(&hi->cl->device, 927 + "closing data channel with slot size 0\n"); 928 + hi->iface_state = CS_STATE_OPENED; 929 + } 930 + } 931 + 932 + static int cs_hsi_buf_config(struct cs_hsi_iface *hi, 933 + struct cs_buffer_config *buf_cfg) 934 + { 935 + int r = 0; 936 + unsigned int old_state = hi->iface_state; 937 + 938 + spin_lock_bh(&hi->lock); 939 + /* Prevent new transactions during buffer reconfig */ 940 + if (old_state == CS_STATE_CONFIGURED) 941 + hi->iface_state = CS_STATE_OPENED; 942 + spin_unlock_bh(&hi->lock); 943 + 944 + /* 945 + * make sure that no non-zero data reads are ongoing before 946 + * proceeding to change the buffer layout 947 + */ 948 + r = cs_hsi_data_sync(hi); 949 + if (r < 0) 950 + return r; 951 + 952 + WARN_ON(cs_state_xfer_active(hi->data_state)); 953 + 954 + spin_lock_bh(&hi->lock); 955 + r = check_buf_params(hi, buf_cfg); 956 + if (r < 0) 957 + goto error; 958 + 959 + hi->buf_size = buf_cfg->buf_size; 960 + hi->mmap_cfg->buf_size = hi->buf_size; 961 + hi->flags = buf_cfg->flags; 962 + 963 + hi->rx_slot = 0; 964 + hi->tx_slot = 0; 965 + hi->slot_size = 0; 966 + 967 + if (hi->buf_size) 968 + cs_hsi_data_enable(hi, buf_cfg); 969 + else 970 + cs_hsi_data_disable(hi, old_state); 971 + 972 + spin_unlock_bh(&hi->lock); 973 + 974 + if (old_state != hi->iface_state) { 975 + if (hi->iface_state == CS_STATE_CONFIGURED) { 976 + pm_qos_add_request(&hi->pm_qos_req, 977 + PM_QOS_CPU_DMA_LATENCY, 978 + CS_QOS_LATENCY_FOR_DATA_USEC); 979 + local_bh_disable(); 980 + cs_hsi_read_on_data(hi); 981 + local_bh_enable(); 982 + } else if (old_state == CS_STATE_CONFIGURED) { 983 + pm_qos_remove_request(&hi->pm_qos_req); 984 + } 985 + } 986 + return r; 987 + 988 + error: 989 + spin_unlock_bh(&hi->lock); 990 + return r; 991 + } 992 + 993 + static int cs_hsi_start(struct cs_hsi_iface **hi, struct hsi_client *cl, 994 + unsigned long mmap_base, unsigned long mmap_size) 995 + { 996 + int err = 0; 997 + struct cs_hsi_iface *hsi_if = kzalloc(sizeof(*hsi_if), GFP_KERNEL); 998 + 999 + dev_dbg(&cl->device, "cs_hsi_start\n"); 1000 + 1001 + if (!hsi_if) { 1002 + err = -ENOMEM; 1003 + goto leave0; 1004 + } 1005 + spin_lock_init(&hsi_if->lock); 1006 + hsi_if->cl = cl; 1007 + hsi_if->iface_state = CS_STATE_CLOSED; 1008 + hsi_if->mmap_cfg = (struct cs_mmap_config_block *)mmap_base; 1009 + hsi_if->mmap_base = mmap_base; 1010 + hsi_if->mmap_size = mmap_size; 1011 + memset(hsi_if->mmap_cfg, 0, sizeof(*hsi_if->mmap_cfg)); 1012 + init_waitqueue_head(&hsi_if->datawait); 1013 + err = cs_alloc_cmds(hsi_if); 1014 + if (err < 0) { 1015 + dev_err(&cl->device, "Unable to alloc HSI messages\n"); 1016 + goto leave1; 1017 + } 1018 + err = cs_hsi_alloc_data(hsi_if); 1019 + if (err < 0) { 1020 + dev_err(&cl->device, "Unable to alloc HSI messages for data\n"); 1021 + goto leave2; 1022 + } 1023 + err = hsi_claim_port(cl, 1); 1024 + if (err < 0) { 1025 + dev_err(&cl->device, 1026 + "Could not open, HSI port already claimed\n"); 1027 + goto leave3; 1028 + } 1029 + hsi_if->master = ssip_slave_get_master(cl); 1030 + if (IS_ERR(hsi_if->master)) { 1031 + dev_err(&cl->device, "Could not get HSI master client\n"); 1032 + goto leave4; 1033 + } 1034 + if (!ssip_slave_running(hsi_if->master)) { 1035 + err = -ENODEV; 1036 + dev_err(&cl->device, 1037 + "HSI port not initialized\n"); 1038 + goto leave4; 1039 + } 1040 + 1041 + hsi_if->iface_state = CS_STATE_OPENED; 1042 + local_bh_disable(); 1043 + cs_hsi_read_on_control(hsi_if); 1044 + local_bh_enable(); 1045 + 1046 + dev_dbg(&cl->device, "cs_hsi_start...done\n"); 1047 + 1048 + BUG_ON(!hi); 1049 + *hi = hsi_if; 1050 + 1051 + return 0; 1052 + 1053 + leave4: 1054 + hsi_release_port(cl); 1055 + leave3: 1056 + cs_hsi_free_data(hsi_if); 1057 + leave2: 1058 + cs_free_cmds(hsi_if); 1059 + leave1: 1060 + kfree(hsi_if); 1061 + leave0: 1062 + dev_dbg(&cl->device, "cs_hsi_start...done/error\n\n"); 1063 + 1064 + return err; 1065 + } 1066 + 1067 + static void cs_hsi_stop(struct cs_hsi_iface *hi) 1068 + { 1069 + dev_dbg(&hi->cl->device, "cs_hsi_stop\n"); 1070 + cs_hsi_set_wakeline(hi, 0); 1071 + ssip_slave_put_master(hi->master); 1072 + 1073 + /* hsi_release_port() needs to be called with CS_STATE_CLOSED */ 1074 + hi->iface_state = CS_STATE_CLOSED; 1075 + hsi_release_port(hi->cl); 1076 + 1077 + /* 1078 + * hsi_release_port() should flush out all the pending 1079 + * messages, so cs_state_idle() should be true for both 1080 + * control and data channels. 1081 + */ 1082 + WARN_ON(!cs_state_idle(hi->control_state)); 1083 + WARN_ON(!cs_state_idle(hi->data_state)); 1084 + 1085 + if (pm_qos_request_active(&hi->pm_qos_req)) 1086 + pm_qos_remove_request(&hi->pm_qos_req); 1087 + 1088 + spin_lock_bh(&hi->lock); 1089 + cs_hsi_free_data(hi); 1090 + cs_free_cmds(hi); 1091 + spin_unlock_bh(&hi->lock); 1092 + kfree(hi); 1093 + } 1094 + 1095 + static int cs_char_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 1096 + { 1097 + struct cs_char *csdata = vma->vm_private_data; 1098 + struct page *page; 1099 + 1100 + page = virt_to_page(csdata->mmap_base); 1101 + get_page(page); 1102 + vmf->page = page; 1103 + 1104 + return 0; 1105 + } 1106 + 1107 + static struct vm_operations_struct cs_char_vm_ops = { 1108 + .fault = cs_char_vma_fault, 1109 + }; 1110 + 1111 + static int cs_char_fasync(int fd, struct file *file, int on) 1112 + { 1113 + struct cs_char *csdata = file->private_data; 1114 + 1115 + if (fasync_helper(fd, file, on, &csdata->async_queue) < 0) 1116 + return -EIO; 1117 + 1118 + return 0; 1119 + } 1120 + 1121 + static unsigned int cs_char_poll(struct file *file, poll_table *wait) 1122 + { 1123 + struct cs_char *csdata = file->private_data; 1124 + unsigned int ret = 0; 1125 + 1126 + poll_wait(file, &cs_char_data.wait, wait); 1127 + spin_lock_bh(&csdata->lock); 1128 + if (!list_empty(&csdata->chardev_queue)) 1129 + ret = POLLIN | POLLRDNORM; 1130 + else if (!list_empty(&csdata->dataind_queue)) 1131 + ret = POLLIN | POLLRDNORM; 1132 + spin_unlock_bh(&csdata->lock); 1133 + 1134 + return ret; 1135 + } 1136 + 1137 + static ssize_t cs_char_read(struct file *file, char __user *buf, size_t count, 1138 + loff_t *unused) 1139 + { 1140 + struct cs_char *csdata = file->private_data; 1141 + u32 data; 1142 + ssize_t retval; 1143 + 1144 + if (count < sizeof(data)) 1145 + return -EINVAL; 1146 + 1147 + for (;;) { 1148 + DEFINE_WAIT(wait); 1149 + 1150 + spin_lock_bh(&csdata->lock); 1151 + if (!list_empty(&csdata->chardev_queue)) { 1152 + data = cs_pop_entry(&csdata->chardev_queue); 1153 + } else if (!list_empty(&csdata->dataind_queue)) { 1154 + data = cs_pop_entry(&csdata->dataind_queue); 1155 + csdata->dataind_pending--; 1156 + } else { 1157 + data = 0; 1158 + } 1159 + spin_unlock_bh(&csdata->lock); 1160 + 1161 + if (data) 1162 + break; 1163 + if (file->f_flags & O_NONBLOCK) { 1164 + retval = -EAGAIN; 1165 + goto out; 1166 + } else if (signal_pending(current)) { 1167 + retval = -ERESTARTSYS; 1168 + goto out; 1169 + } 1170 + prepare_to_wait_exclusive(&csdata->wait, &wait, 1171 + TASK_INTERRUPTIBLE); 1172 + schedule(); 1173 + finish_wait(&csdata->wait, &wait); 1174 + } 1175 + 1176 + retval = put_user(data, (u32 __user *)buf); 1177 + if (!retval) 1178 + retval = sizeof(data); 1179 + 1180 + out: 1181 + return retval; 1182 + } 1183 + 1184 + static ssize_t cs_char_write(struct file *file, const char __user *buf, 1185 + size_t count, loff_t *unused) 1186 + { 1187 + struct cs_char *csdata = file->private_data; 1188 + u32 data; 1189 + int err; 1190 + ssize_t retval; 1191 + 1192 + if (count < sizeof(data)) 1193 + return -EINVAL; 1194 + 1195 + if (get_user(data, (u32 __user *)buf)) 1196 + retval = -EFAULT; 1197 + else 1198 + retval = count; 1199 + 1200 + err = cs_hsi_command(csdata->hi, data); 1201 + if (err < 0) 1202 + retval = err; 1203 + 1204 + return retval; 1205 + } 1206 + 1207 + static long cs_char_ioctl(struct file *file, unsigned int cmd, 1208 + unsigned long arg) 1209 + { 1210 + struct cs_char *csdata = file->private_data; 1211 + int r = 0; 1212 + 1213 + switch (cmd) { 1214 + case CS_GET_STATE: { 1215 + unsigned int state; 1216 + 1217 + state = cs_hsi_get_state(csdata->hi); 1218 + if (copy_to_user((void __user *)arg, &state, sizeof(state))) 1219 + r = -EFAULT; 1220 + 1221 + break; 1222 + } 1223 + case CS_SET_WAKELINE: { 1224 + unsigned int state; 1225 + 1226 + if (copy_from_user(&state, (void __user *)arg, sizeof(state))) { 1227 + r = -EFAULT; 1228 + break; 1229 + } 1230 + 1231 + if (state > 1) { 1232 + r = -EINVAL; 1233 + break; 1234 + } 1235 + 1236 + cs_hsi_set_wakeline(csdata->hi, !!state); 1237 + 1238 + break; 1239 + } 1240 + case CS_GET_IF_VERSION: { 1241 + unsigned int ifver = CS_IF_VERSION; 1242 + 1243 + if (copy_to_user((void __user *)arg, &ifver, sizeof(ifver))) 1244 + r = -EFAULT; 1245 + 1246 + break; 1247 + } 1248 + case CS_CONFIG_BUFS: { 1249 + struct cs_buffer_config buf_cfg; 1250 + 1251 + if (copy_from_user(&buf_cfg, (void __user *)arg, 1252 + sizeof(buf_cfg))) 1253 + r = -EFAULT; 1254 + else 1255 + r = cs_hsi_buf_config(csdata->hi, &buf_cfg); 1256 + 1257 + break; 1258 + } 1259 + default: 1260 + r = -ENOTTY; 1261 + break; 1262 + } 1263 + 1264 + return r; 1265 + } 1266 + 1267 + static int cs_char_mmap(struct file *file, struct vm_area_struct *vma) 1268 + { 1269 + if (vma->vm_end < vma->vm_start) 1270 + return -EINVAL; 1271 + 1272 + if (((vma->vm_end - vma->vm_start) >> PAGE_SHIFT) != 1) 1273 + return -EINVAL; 1274 + 1275 + vma->vm_flags |= VM_IO | VM_DONTDUMP | VM_DONTEXPAND; 1276 + vma->vm_ops = &cs_char_vm_ops; 1277 + vma->vm_private_data = file->private_data; 1278 + 1279 + return 0; 1280 + } 1281 + 1282 + static int cs_char_open(struct inode *unused, struct file *file) 1283 + { 1284 + int ret = 0; 1285 + unsigned long p; 1286 + 1287 + spin_lock_bh(&cs_char_data.lock); 1288 + if (cs_char_data.opened) { 1289 + ret = -EBUSY; 1290 + spin_unlock_bh(&cs_char_data.lock); 1291 + goto out1; 1292 + } 1293 + cs_char_data.opened = 1; 1294 + cs_char_data.dataind_pending = 0; 1295 + spin_unlock_bh(&cs_char_data.lock); 1296 + 1297 + p = get_zeroed_page(GFP_KERNEL); 1298 + if (!p) { 1299 + ret = -ENOMEM; 1300 + goto out2; 1301 + } 1302 + 1303 + ret = cs_hsi_start(&cs_char_data.hi, cs_char_data.cl, p, CS_MMAP_SIZE); 1304 + if (ret) { 1305 + dev_err(&cs_char_data.cl->device, "Unable to initialize HSI\n"); 1306 + goto out3; 1307 + } 1308 + 1309 + /* these are only used in release so lock not needed */ 1310 + cs_char_data.mmap_base = p; 1311 + cs_char_data.mmap_size = CS_MMAP_SIZE; 1312 + 1313 + file->private_data = &cs_char_data; 1314 + 1315 + return 0; 1316 + 1317 + out3: 1318 + free_page(p); 1319 + out2: 1320 + spin_lock_bh(&cs_char_data.lock); 1321 + cs_char_data.opened = 0; 1322 + spin_unlock_bh(&cs_char_data.lock); 1323 + out1: 1324 + return ret; 1325 + } 1326 + 1327 + static void cs_free_char_queue(struct list_head *head) 1328 + { 1329 + struct char_queue *entry; 1330 + struct list_head *cursor, *next; 1331 + 1332 + if (!list_empty(head)) { 1333 + list_for_each_safe(cursor, next, head) { 1334 + entry = list_entry(cursor, struct char_queue, list); 1335 + list_del(&entry->list); 1336 + kfree(entry); 1337 + } 1338 + } 1339 + 1340 + } 1341 + 1342 + static int cs_char_release(struct inode *unused, struct file *file) 1343 + { 1344 + struct cs_char *csdata = file->private_data; 1345 + 1346 + cs_hsi_stop(csdata->hi); 1347 + spin_lock_bh(&csdata->lock); 1348 + csdata->hi = NULL; 1349 + free_page(csdata->mmap_base); 1350 + cs_free_char_queue(&csdata->chardev_queue); 1351 + cs_free_char_queue(&csdata->dataind_queue); 1352 + csdata->opened = 0; 1353 + spin_unlock_bh(&csdata->lock); 1354 + 1355 + return 0; 1356 + } 1357 + 1358 + static const struct file_operations cs_char_fops = { 1359 + .owner = THIS_MODULE, 1360 + .read = cs_char_read, 1361 + .write = cs_char_write, 1362 + .poll = cs_char_poll, 1363 + .unlocked_ioctl = cs_char_ioctl, 1364 + .mmap = cs_char_mmap, 1365 + .open = cs_char_open, 1366 + .release = cs_char_release, 1367 + .fasync = cs_char_fasync, 1368 + }; 1369 + 1370 + static struct miscdevice cs_char_miscdev = { 1371 + .minor = MISC_DYNAMIC_MINOR, 1372 + .name = "cmt_speech", 1373 + .fops = &cs_char_fops 1374 + }; 1375 + 1376 + static int cs_hsi_client_probe(struct device *dev) 1377 + { 1378 + int err = 0; 1379 + struct hsi_client *cl = to_hsi_client(dev); 1380 + 1381 + dev_dbg(dev, "hsi_client_probe\n"); 1382 + init_waitqueue_head(&cs_char_data.wait); 1383 + spin_lock_init(&cs_char_data.lock); 1384 + cs_char_data.opened = 0; 1385 + cs_char_data.cl = cl; 1386 + cs_char_data.hi = NULL; 1387 + INIT_LIST_HEAD(&cs_char_data.chardev_queue); 1388 + INIT_LIST_HEAD(&cs_char_data.dataind_queue); 1389 + 1390 + cs_char_data.channel_id_cmd = hsi_get_channel_id_by_name(cl, 1391 + "speech-control"); 1392 + if (cs_char_data.channel_id_cmd < 0) { 1393 + err = cs_char_data.channel_id_cmd; 1394 + dev_err(dev, "Could not get cmd channel (%d)\n", err); 1395 + return err; 1396 + } 1397 + 1398 + cs_char_data.channel_id_data = hsi_get_channel_id_by_name(cl, 1399 + "speech-data"); 1400 + if (cs_char_data.channel_id_data < 0) { 1401 + err = cs_char_data.channel_id_data; 1402 + dev_err(dev, "Could not get data channel (%d)\n", err); 1403 + return err; 1404 + } 1405 + 1406 + err = misc_register(&cs_char_miscdev); 1407 + if (err) 1408 + dev_err(dev, "Failed to register: %d\n", err); 1409 + 1410 + return err; 1411 + } 1412 + 1413 + static int cs_hsi_client_remove(struct device *dev) 1414 + { 1415 + struct cs_hsi_iface *hi; 1416 + 1417 + dev_dbg(dev, "hsi_client_remove\n"); 1418 + misc_deregister(&cs_char_miscdev); 1419 + spin_lock_bh(&cs_char_data.lock); 1420 + hi = cs_char_data.hi; 1421 + cs_char_data.hi = NULL; 1422 + spin_unlock_bh(&cs_char_data.lock); 1423 + if (hi) 1424 + cs_hsi_stop(hi); 1425 + 1426 + return 0; 1427 + } 1428 + 1429 + static struct hsi_client_driver cs_hsi_driver = { 1430 + .driver = { 1431 + .name = "cmt-speech", 1432 + .owner = THIS_MODULE, 1433 + .probe = cs_hsi_client_probe, 1434 + .remove = cs_hsi_client_remove, 1435 + }, 1436 + }; 1437 + 1438 + static int __init cs_char_init(void) 1439 + { 1440 + pr_info("CMT speech driver added\n"); 1441 + return hsi_register_client_driver(&cs_hsi_driver); 1442 + } 1443 + module_init(cs_char_init); 1444 + 1445 + static void __exit cs_char_exit(void) 1446 + { 1447 + hsi_unregister_client_driver(&cs_hsi_driver); 1448 + pr_info("CMT speech driver removed\n"); 1449 + } 1450 + module_exit(cs_char_exit); 1451 + 1452 + MODULE_ALIAS("hsi:cmt-speech"); 1453 + MODULE_AUTHOR("Kai Vehmanen <kai.vehmanen@nokia.com>"); 1454 + MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>"); 1455 + MODULE_DESCRIPTION("CMT speech driver"); 1456 + MODULE_LICENSE("GPL v2");
+1 -1
include/uapi/linux/hsi/Kbuild
··· 1 1 # UAPI Header export list 2 - header-y += hsi_char.h 2 + header-y += hsi_char.h cs-protocol.h
+113
include/uapi/linux/hsi/cs-protocol.h
··· 1 + /* 2 + * cmt-speech interface definitions 3 + * 4 + * Copyright (C) 2008,2009,2010 Nokia Corporation. All rights reserved. 5 + * 6 + * Contact: Kai Vehmanen <kai.vehmanen@nokia.com> 7 + * Original author: Peter Ujfalusi <peter.ujfalusi@nokia.com> 8 + * 9 + * This program is free software; you can redistribute it and/or 10 + * modify it under the terms of the GNU General Public License 11 + * version 2 as published by the Free Software Foundation. 12 + * 13 + * This program is distributed in the hope that it will be useful, but 14 + * WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 + * General Public License for more details. 17 + * 18 + * You should have received a copy of the GNU General Public License 19 + * along with this program; if not, write to the Free Software 20 + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 21 + * 02110-1301 USA 22 + */ 23 + 24 + #ifndef _CS_PROTOCOL_H 25 + #define _CS_PROTOCOL_H 26 + 27 + #include <linux/types.h> 28 + #include <linux/ioctl.h> 29 + 30 + /* chardev parameters */ 31 + #define CS_DEV_FILE_NAME "/dev/cmt_speech" 32 + 33 + /* user-space API versioning */ 34 + #define CS_IF_VERSION 2 35 + 36 + /* APE kernel <-> user space messages */ 37 + #define CS_CMD_SHIFT 28 38 + #define CS_DOMAIN_SHIFT 24 39 + 40 + #define CS_CMD_MASK 0xff000000 41 + #define CS_PARAM_MASK 0xffffff 42 + 43 + #define CS_CMD(id, dom) \ 44 + (((id) << CS_CMD_SHIFT) | ((dom) << CS_DOMAIN_SHIFT)) 45 + 46 + #define CS_ERROR CS_CMD(1, 0) 47 + #define CS_RX_DATA_RECEIVED CS_CMD(2, 0) 48 + #define CS_TX_DATA_READY CS_CMD(3, 0) 49 + #define CS_TX_DATA_SENT CS_CMD(4, 0) 50 + 51 + /* params to CS_ERROR indication */ 52 + #define CS_ERR_PEER_RESET 0 53 + 54 + /* ioctl interface */ 55 + 56 + /* parameters to CS_CONFIG_BUFS ioctl */ 57 + #define CS_FEAT_TSTAMP_RX_CTRL (1 << 0) 58 + #define CS_FEAT_ROLLING_RX_COUNTER (2 << 0) 59 + 60 + /* parameters to CS_GET_STATE ioctl */ 61 + #define CS_STATE_CLOSED 0 62 + #define CS_STATE_OPENED 1 /* resource allocated */ 63 + #define CS_STATE_CONFIGURED 2 /* data path active */ 64 + 65 + /* maximum number of TX/RX buffers */ 66 + #define CS_MAX_BUFFERS_SHIFT 4 67 + #define CS_MAX_BUFFERS (1 << CS_MAX_BUFFERS_SHIFT) 68 + 69 + /* Parameters for setting up the data buffers */ 70 + struct cs_buffer_config { 71 + __u32 rx_bufs; /* number of RX buffer slots */ 72 + __u32 tx_bufs; /* number of TX buffer slots */ 73 + __u32 buf_size; /* bytes */ 74 + __u32 flags; /* see CS_FEAT_* */ 75 + __u32 reserved[4]; 76 + }; 77 + 78 + /* 79 + * Struct describing the layout and contents of the driver mmap area. 80 + * This information is meant as read-only information for the application. 81 + */ 82 + struct cs_mmap_config_block { 83 + __u32 reserved1; 84 + __u32 buf_size; /* 0=disabled, otherwise the transfer size */ 85 + __u32 rx_bufs; /* # of RX buffers */ 86 + __u32 tx_bufs; /* # of TX buffers */ 87 + __u32 reserved2; 88 + /* array of offsets within the mmap area for each RX and TX buffer */ 89 + __u32 rx_offsets[CS_MAX_BUFFERS]; 90 + __u32 tx_offsets[CS_MAX_BUFFERS]; 91 + __u32 rx_ptr; 92 + __u32 rx_ptr_boundary; 93 + __u32 reserved3[2]; 94 + /* 95 + * if enabled with CS_FEAT_TSTAMP_RX_CTRL, monotonic 96 + * timestamp taken when the last control command was received 97 + */ 98 + struct timespec tstamp_rx_ctrl; 99 + }; 100 + 101 + #define CS_IO_MAGIC 'C' 102 + 103 + #define CS_IOW(num, dtype) _IOW(CS_IO_MAGIC, num, dtype) 104 + #define CS_IOR(num, dtype) _IOR(CS_IO_MAGIC, num, dtype) 105 + #define CS_IOWR(num, dtype) _IOWR(CS_IO_MAGIC, num, dtype) 106 + #define CS_IO(num) _IO(CS_IO_MAGIC, num) 107 + 108 + #define CS_GET_STATE CS_IOR(21, unsigned int) 109 + #define CS_SET_WAKELINE CS_IOW(23, unsigned int) 110 + #define CS_GET_IF_VERSION CS_IOR(30, unsigned int) 111 + #define CS_CONFIG_BUFS CS_IOW(31, struct cs_buffer_config) 112 + 113 + #endif /* _CS_PROTOCOL_H */