1/* 2 * proc.c 3 * 4 * DSP-BIOS Bridge driver support functions for TI OMAP processors. 5 * 6 * Processor interface at the driver level. 7 * 8 * Copyright (C) 2005-2006 Texas Instruments, Inc. 9 * 10 * This package is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 16 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 17 */ 18 19#include <linux/types.h> 20/* ------------------------------------ Host OS */ 21#include <linux/dma-mapping.h> 22#include <linux/scatterlist.h> 23#include <dspbridge/host_os.h> 24 25/* ----------------------------------- DSP/BIOS Bridge */ 26#include <dspbridge/dbdefs.h> 27 28/* ----------------------------------- OS Adaptation Layer */ 29#include <dspbridge/ntfy.h> 30#include <dspbridge/sync.h> 31/* ----------------------------------- Bridge Driver */ 32#include <dspbridge/dspdefs.h> 33#include <dspbridge/dspdeh.h> 34/* ----------------------------------- Platform Manager */ 35#include <dspbridge/cod.h> 36#include <dspbridge/dev.h> 37#include <dspbridge/procpriv.h> 38#include <dspbridge/dmm.h> 39 40/* ----------------------------------- Resource Manager */ 41#include <dspbridge/mgr.h> 42#include <dspbridge/node.h> 43#include <dspbridge/nldr.h> 44#include <dspbridge/rmm.h> 45 46/* ----------------------------------- Others */ 47#include <dspbridge/dbdcd.h> 48#include <dspbridge/msg.h> 49#include <dspbridge/dspioctl.h> 50#include <dspbridge/drv.h> 51 52/* ----------------------------------- This */ 53#include <dspbridge/proc.h> 54#include <dspbridge/pwr.h> 55 56#include <dspbridge/resourcecleanup.h> 57/* ----------------------------------- Defines, Data Structures, Typedefs */ 58#define MAXCMDLINELEN 255 59#define PROC_ENVPROCID "PROC_ID=%d" 60#define MAXPROCIDLEN (8 + 5) 61#define PROC_DFLT_TIMEOUT 10000 /* Time out in milliseconds */ 62#define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */ 63#define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */ 64 65#define DSP_CACHE_LINE 128 66 67#define BUFMODE_MASK (3 << 14) 68 69/* Buffer modes from DSP perspective */ 70#define RBUF 0x4000 /* Input buffer */ 71#define WBUF 0x8000 /* Output Buffer */ 72 73extern struct device *bridge; 74 75/* ----------------------------------- Globals */ 76 77/* The proc_object structure. */ 78struct proc_object { 79 struct list_head link; /* Link to next proc_object */ 80 struct dev_object *dev_obj; /* Device this PROC represents */ 81 u32 process; /* Process owning this Processor */ 82 struct mgr_object *mgr_obj; /* Manager Object Handle */ 83 u32 attach_count; /* Processor attach count */ 84 u32 processor_id; /* Processor number */ 85 u32 timeout; /* Time out count */ 86 enum dsp_procstate proc_state; /* Processor state */ 87 u32 unit; /* DDSP unit number */ 88 bool is_already_attached; /* 89 * True if the Device below has 90 * GPP Client attached 91 */ 92 struct ntfy_object *ntfy_obj; /* Manages notifications */ 93 /* Bridge Context Handle */ 94 struct bridge_dev_context *bridge_context; 95 /* Function interface to Bridge driver */ 96 struct bridge_drv_interface *intf_fxns; 97 char *last_coff; 98 struct list_head proc_list; 99}; 100 101DEFINE_MUTEX(proc_lock); /* For critical sections */ 102 103/* ----------------------------------- Function Prototypes */ 104static int proc_monitor(struct proc_object *proc_obj); 105static s32 get_envp_count(char **envp); 106static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems, 107 s32 cnew_envp, char *sz_var); 108 109/* remember mapping information */ 110static struct dmm_map_object *add_mapping_info(struct process_context *pr_ctxt, 111 u32 mpu_addr, u32 dsp_addr, u32 size) 112{ 113 struct dmm_map_object *map_obj; 114 115 u32 num_usr_pgs = size / PG_SIZE4K; 116 117 pr_debug("%s: adding map info: mpu_addr 0x%x virt 0x%x size 0x%x\n", 118 __func__, mpu_addr, 119 dsp_addr, size); 120 121 map_obj = kzalloc(sizeof(struct dmm_map_object), GFP_KERNEL); 122 if (!map_obj) { 123 pr_err("%s: kzalloc failed\n", __func__); 124 return NULL; 125 } 126 INIT_LIST_HEAD(&map_obj->link); 127 128 map_obj->pages = kcalloc(num_usr_pgs, sizeof(struct page *), 129 GFP_KERNEL); 130 if (!map_obj->pages) { 131 pr_err("%s: kzalloc failed\n", __func__); 132 kfree(map_obj); 133 return NULL; 134 } 135 136 map_obj->mpu_addr = mpu_addr; 137 map_obj->dsp_addr = dsp_addr; 138 map_obj->size = size; 139 map_obj->num_usr_pgs = num_usr_pgs; 140 141 spin_lock(&pr_ctxt->dmm_map_lock); 142 list_add(&map_obj->link, &pr_ctxt->dmm_map_list); 143 spin_unlock(&pr_ctxt->dmm_map_lock); 144 145 return map_obj; 146} 147 148static int match_exact_map_obj(struct dmm_map_object *map_obj, 149 u32 dsp_addr, u32 size) 150{ 151 if (map_obj->dsp_addr == dsp_addr && map_obj->size != size) 152 pr_err("%s: addr match (0x%x), size don't (0x%x != 0x%x)\n", 153 __func__, dsp_addr, map_obj->size, size); 154 155 return map_obj->dsp_addr == dsp_addr && 156 map_obj->size == size; 157} 158 159static void remove_mapping_information(struct process_context *pr_ctxt, 160 u32 dsp_addr, u32 size) 161{ 162 struct dmm_map_object *map_obj; 163 164 pr_debug("%s: looking for virt 0x%x size 0x%x\n", __func__, 165 dsp_addr, size); 166 167 spin_lock(&pr_ctxt->dmm_map_lock); 168 list_for_each_entry(map_obj, &pr_ctxt->dmm_map_list, link) { 169 pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x size 0x%x\n", 170 __func__, 171 map_obj->mpu_addr, 172 map_obj->dsp_addr, 173 map_obj->size); 174 175 if (match_exact_map_obj(map_obj, dsp_addr, size)) { 176 pr_debug("%s: match, deleting map info\n", __func__); 177 list_del(&map_obj->link); 178 kfree(map_obj->dma_info.sg); 179 kfree(map_obj->pages); 180 kfree(map_obj); 181 goto out; 182 } 183 pr_debug("%s: candidate didn't match\n", __func__); 184 } 185 186 pr_err("%s: failed to find given map info\n", __func__); 187out: 188 spin_unlock(&pr_ctxt->dmm_map_lock); 189} 190 191static int match_containing_map_obj(struct dmm_map_object *map_obj, 192 u32 mpu_addr, u32 size) 193{ 194 u32 map_obj_end = map_obj->mpu_addr + map_obj->size; 195 196 return mpu_addr >= map_obj->mpu_addr && 197 mpu_addr + size <= map_obj_end; 198} 199 200static struct dmm_map_object *find_containing_mapping( 201 struct process_context *pr_ctxt, 202 u32 mpu_addr, u32 size) 203{ 204 struct dmm_map_object *map_obj; 205 pr_debug("%s: looking for mpu_addr 0x%x size 0x%x\n", __func__, 206 mpu_addr, size); 207 208 spin_lock(&pr_ctxt->dmm_map_lock); 209 list_for_each_entry(map_obj, &pr_ctxt->dmm_map_list, link) { 210 pr_debug("%s: candidate: mpu_addr 0x%x virt 0x%x size 0x%x\n", 211 __func__, 212 map_obj->mpu_addr, 213 map_obj->dsp_addr, 214 map_obj->size); 215 if (match_containing_map_obj(map_obj, mpu_addr, size)) { 216 pr_debug("%s: match!\n", __func__); 217 goto out; 218 } 219 220 pr_debug("%s: no match!\n", __func__); 221 } 222 223 map_obj = NULL; 224out: 225 spin_unlock(&pr_ctxt->dmm_map_lock); 226 return map_obj; 227} 228 229static int find_first_page_in_cache(struct dmm_map_object *map_obj, 230 unsigned long mpu_addr) 231{ 232 u32 mapped_base_page = map_obj->mpu_addr >> PAGE_SHIFT; 233 u32 requested_base_page = mpu_addr >> PAGE_SHIFT; 234 int pg_index = requested_base_page - mapped_base_page; 235 236 if (pg_index < 0 || pg_index >= map_obj->num_usr_pgs) { 237 pr_err("%s: failed (got %d)\n", __func__, pg_index); 238 return -1; 239 } 240 241 pr_debug("%s: first page is %d\n", __func__, pg_index); 242 return pg_index; 243} 244 245static inline struct page *get_mapping_page(struct dmm_map_object *map_obj, 246 int pg_i) 247{ 248 pr_debug("%s: looking for pg_i %d, num_usr_pgs: %d\n", __func__, 249 pg_i, map_obj->num_usr_pgs); 250 251 if (pg_i < 0 || pg_i >= map_obj->num_usr_pgs) { 252 pr_err("%s: requested pg_i %d is out of mapped range\n", 253 __func__, pg_i); 254 return NULL; 255 } 256 257 return map_obj->pages[pg_i]; 258} 259 260/* 261 * ======== proc_attach ======== 262 * Purpose: 263 * Prepare for communication with a particular DSP processor, and return 264 * a handle to the processor object. 265 */ 266int 267proc_attach(u32 processor_id, 268 const struct dsp_processorattrin *attr_in, 269 void **ph_processor, struct process_context *pr_ctxt) 270{ 271 int status = 0; 272 struct dev_object *hdev_obj; 273 struct proc_object *p_proc_object = NULL; 274 struct mgr_object *hmgr_obj = NULL; 275 struct drv_object *hdrv_obj = NULL; 276 struct drv_data *drv_datap = dev_get_drvdata(bridge); 277 u8 dev_type; 278 279 if (pr_ctxt->processor) { 280 *ph_processor = pr_ctxt->processor; 281 return status; 282 } 283 284 /* Get the Driver and Manager Object Handles */ 285 if (!drv_datap || !drv_datap->drv_object || !drv_datap->mgr_object) { 286 status = -ENODATA; 287 pr_err("%s: Failed to get object handles\n", __func__); 288 } else { 289 hdrv_obj = drv_datap->drv_object; 290 hmgr_obj = drv_datap->mgr_object; 291 } 292 293 if (!status) { 294 /* Get the Device Object */ 295 status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj); 296 } 297 if (!status) 298 status = dev_get_dev_type(hdev_obj, &dev_type); 299 300 if (status) 301 goto func_end; 302 303 /* If we made it this far, create the Proceesor object: */ 304 p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL); 305 /* Fill out the Processor Object: */ 306 if (p_proc_object == NULL) { 307 status = -ENOMEM; 308 goto func_end; 309 } 310 p_proc_object->dev_obj = hdev_obj; 311 p_proc_object->mgr_obj = hmgr_obj; 312 p_proc_object->processor_id = dev_type; 313 /* Store TGID instead of process handle */ 314 p_proc_object->process = current->tgid; 315 316 INIT_LIST_HEAD(&p_proc_object->proc_list); 317 318 if (attr_in) 319 p_proc_object->timeout = attr_in->timeout; 320 else 321 p_proc_object->timeout = PROC_DFLT_TIMEOUT; 322 323 status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns); 324 if (!status) { 325 status = dev_get_bridge_context(hdev_obj, 326 &p_proc_object->bridge_context); 327 if (status) 328 kfree(p_proc_object); 329 } else 330 kfree(p_proc_object); 331 332 if (status) 333 goto func_end; 334 335 /* Create the Notification Object */ 336 /* This is created with no event mask, no notify mask 337 * and no valid handle to the notification. They all get 338 * filled up when proc_register_notify is called */ 339 p_proc_object->ntfy_obj = kmalloc(sizeof(struct ntfy_object), 340 GFP_KERNEL); 341 if (p_proc_object->ntfy_obj) 342 ntfy_init(p_proc_object->ntfy_obj); 343 else 344 status = -ENOMEM; 345 346 if (!status) { 347 /* Insert the Processor Object into the DEV List. 348 * Return handle to this Processor Object: 349 * Find out if the Device is already attached to a 350 * Processor. If so, return AlreadyAttached status */ 351 status = dev_insert_proc_object(p_proc_object->dev_obj, 352 (u32) p_proc_object, 353 &p_proc_object-> 354 is_already_attached); 355 if (!status) { 356 if (p_proc_object->is_already_attached) 357 status = 0; 358 } else { 359 if (p_proc_object->ntfy_obj) { 360 ntfy_delete(p_proc_object->ntfy_obj); 361 kfree(p_proc_object->ntfy_obj); 362 } 363 364 kfree(p_proc_object); 365 } 366 if (!status) { 367 *ph_processor = (void *)p_proc_object; 368 pr_ctxt->processor = *ph_processor; 369 (void)proc_notify_clients(p_proc_object, 370 DSP_PROCESSORATTACH); 371 } 372 } else { 373 /* Don't leak memory if status is failed */ 374 kfree(p_proc_object); 375 } 376func_end: 377 return status; 378} 379 380static int get_exec_file(struct cfg_devnode *dev_node_obj, 381 struct dev_object *hdev_obj, 382 u32 size, char *exec_file) 383{ 384 u8 dev_type; 385 s32 len; 386 struct drv_data *drv_datap = dev_get_drvdata(bridge); 387 388 dev_get_dev_type(hdev_obj, (u8 *) &dev_type); 389 390 if (!exec_file) 391 return -EFAULT; 392 393 if (dev_type == DSP_UNIT) { 394 if (!drv_datap || !drv_datap->base_img) 395 return -EFAULT; 396 397 if (strlen(drv_datap->base_img) > size) 398 return -EINVAL; 399 400 strcpy(exec_file, drv_datap->base_img); 401 } else if (dev_type == IVA_UNIT && iva_img) { 402 len = strlen(iva_img); 403 strncpy(exec_file, iva_img, len + 1); 404 } else { 405 return -ENOENT; 406 } 407 408 return 0; 409} 410 411/* 412 * ======== proc_auto_start ======== = 413 * Purpose: 414 * A Particular device gets loaded with the default image 415 * if the AutoStart flag is set. 416 * Parameters: 417 * hdev_obj: Handle to the Device 418 * Returns: 419 * 0: On Successful Loading 420 * -EPERM General Failure 421 * Requires: 422 * hdev_obj != NULL 423 * Ensures: 424 */ 425int proc_auto_start(struct cfg_devnode *dev_node_obj, 426 struct dev_object *hdev_obj) 427{ 428 int status = -EPERM; 429 struct proc_object *p_proc_object; 430 char sz_exec_file[MAXCMDLINELEN]; 431 char *argv[2]; 432 struct mgr_object *hmgr_obj = NULL; 433 struct drv_data *drv_datap = dev_get_drvdata(bridge); 434 u8 dev_type; 435 436 /* Create a Dummy PROC Object */ 437 if (!drv_datap || !drv_datap->mgr_object) { 438 status = -ENODATA; 439 pr_err("%s: Failed to retrieve the object handle\n", __func__); 440 goto func_end; 441 } else { 442 hmgr_obj = drv_datap->mgr_object; 443 } 444 445 p_proc_object = kzalloc(sizeof(struct proc_object), GFP_KERNEL); 446 if (p_proc_object == NULL) { 447 status = -ENOMEM; 448 goto func_end; 449 } 450 p_proc_object->dev_obj = hdev_obj; 451 p_proc_object->mgr_obj = hmgr_obj; 452 status = dev_get_intf_fxns(hdev_obj, &p_proc_object->intf_fxns); 453 if (!status) 454 status = dev_get_bridge_context(hdev_obj, 455 &p_proc_object->bridge_context); 456 if (status) 457 goto func_cont; 458 459 /* Stop the Device, put it into standby mode */ 460 status = proc_stop(p_proc_object); 461 462 if (status) 463 goto func_cont; 464 465 /* Get the default executable for this board... */ 466 dev_get_dev_type(hdev_obj, (u8 *) &dev_type); 467 p_proc_object->processor_id = dev_type; 468 status = get_exec_file(dev_node_obj, hdev_obj, sizeof(sz_exec_file), 469 sz_exec_file); 470 if (!status) { 471 argv[0] = sz_exec_file; 472 argv[1] = NULL; 473 /* ...and try to load it: */ 474 status = proc_load(p_proc_object, 1, (const char **)argv, NULL); 475 if (!status) 476 status = proc_start(p_proc_object); 477 } 478 kfree(p_proc_object->last_coff); 479 p_proc_object->last_coff = NULL; 480func_cont: 481 kfree(p_proc_object); 482func_end: 483 return status; 484} 485 486/* 487 * ======== proc_ctrl ======== 488 * Purpose: 489 * Pass control information to the GPP device driver managing the 490 * DSP processor. 491 * 492 * This will be an OEM-only function, and not part of the DSP/BIOS Bridge 493 * application developer's API. 494 * Call the bridge_dev_ctrl fxn with the Argument. This is a Synchronous 495 * Operation. arg can be null. 496 */ 497int proc_ctrl(void *hprocessor, u32 dw_cmd, struct dsp_cbdata * arg) 498{ 499 int status = 0; 500 struct proc_object *p_proc_object = hprocessor; 501 u32 timeout = 0; 502 503 if (p_proc_object) { 504 /* intercept PWR deep sleep command */ 505 if (dw_cmd == BRDIOCTL_DEEPSLEEP) { 506 timeout = arg->cb_data; 507 status = pwr_sleep_dsp(PWR_DEEPSLEEP, timeout); 508 } 509 /* intercept PWR emergency sleep command */ 510 else if (dw_cmd == BRDIOCTL_EMERGENCYSLEEP) { 511 timeout = arg->cb_data; 512 status = pwr_sleep_dsp(PWR_EMERGENCYDEEPSLEEP, timeout); 513 } else if (dw_cmd == PWR_DEEPSLEEP) { 514 /* timeout = arg->cb_data; */ 515 status = pwr_sleep_dsp(PWR_DEEPSLEEP, timeout); 516 } 517 /* intercept PWR wake commands */ 518 else if (dw_cmd == BRDIOCTL_WAKEUP) { 519 timeout = arg->cb_data; 520 status = pwr_wake_dsp(timeout); 521 } else if (dw_cmd == PWR_WAKEUP) { 522 /* timeout = arg->cb_data; */ 523 status = pwr_wake_dsp(timeout); 524 } else 525 if (!((*p_proc_object->intf_fxns->dev_cntrl) 526 (p_proc_object->bridge_context, dw_cmd, 527 arg))) { 528 status = 0; 529 } else { 530 status = -EPERM; 531 } 532 } else { 533 status = -EFAULT; 534 } 535 536 return status; 537} 538 539/* 540 * ======== proc_detach ======== 541 * Purpose: 542 * Destroys the Processor Object. Removes the notification from the Dev 543 * List. 544 */ 545int proc_detach(struct process_context *pr_ctxt) 546{ 547 int status = 0; 548 struct proc_object *p_proc_object = NULL; 549 550 p_proc_object = (struct proc_object *)pr_ctxt->processor; 551 552 if (p_proc_object) { 553 /* Notify the Client */ 554 ntfy_notify(p_proc_object->ntfy_obj, DSP_PROCESSORDETACH); 555 /* Remove the notification memory */ 556 if (p_proc_object->ntfy_obj) { 557 ntfy_delete(p_proc_object->ntfy_obj); 558 kfree(p_proc_object->ntfy_obj); 559 } 560 561 kfree(p_proc_object->last_coff); 562 p_proc_object->last_coff = NULL; 563 /* Remove the Proc from the DEV List */ 564 (void)dev_remove_proc_object(p_proc_object->dev_obj, 565 (u32) p_proc_object); 566 /* Free the Processor Object */ 567 kfree(p_proc_object); 568 pr_ctxt->processor = NULL; 569 } else { 570 status = -EFAULT; 571 } 572 573 return status; 574} 575 576/* 577 * ======== proc_enum_nodes ======== 578 * Purpose: 579 * Enumerate and get configuration information about nodes allocated 580 * on a DSP processor. 581 */ 582int proc_enum_nodes(void *hprocessor, void **node_tab, 583 u32 node_tab_size, u32 *pu_num_nodes, 584 u32 *pu_allocated) 585{ 586 int status = -EPERM; 587 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 588 struct node_mgr *hnode_mgr = NULL; 589 590 if (p_proc_object) { 591 if (!(dev_get_node_manager(p_proc_object->dev_obj, 592 &hnode_mgr))) { 593 if (hnode_mgr) { 594 status = node_enum_nodes(hnode_mgr, node_tab, 595 node_tab_size, 596 pu_num_nodes, 597 pu_allocated); 598 } 599 } 600 } else { 601 status = -EFAULT; 602 } 603 604 return status; 605} 606 607/* Cache operation against kernel address instead of users */ 608static int build_dma_sg(struct dmm_map_object *map_obj, unsigned long start, 609 ssize_t len, int pg_i) 610{ 611 struct page *page; 612 unsigned long offset; 613 ssize_t rest; 614 int ret = 0, i = 0; 615 struct scatterlist *sg = map_obj->dma_info.sg; 616 617 while (len) { 618 page = get_mapping_page(map_obj, pg_i); 619 if (!page) { 620 pr_err("%s: no page for %08lx\n", __func__, start); 621 ret = -EINVAL; 622 goto out; 623 } else if (IS_ERR(page)) { 624 pr_err("%s: err page for %08lx(%lu)\n", __func__, start, 625 PTR_ERR(page)); 626 ret = PTR_ERR(page); 627 goto out; 628 } 629 630 offset = start & ~PAGE_MASK; 631 rest = min_t(ssize_t, PAGE_SIZE - offset, len); 632 633 sg_set_page(&sg[i], page, rest, offset); 634 635 len -= rest; 636 start += rest; 637 pg_i++, i++; 638 } 639 640 if (i != map_obj->dma_info.num_pages) { 641 pr_err("%s: bad number of sg iterations\n", __func__); 642 ret = -EFAULT; 643 goto out; 644 } 645 646out: 647 return ret; 648} 649 650static int memory_regain_ownership(struct dmm_map_object *map_obj, 651 unsigned long start, ssize_t len, enum dma_data_direction dir) 652{ 653 int ret = 0; 654 unsigned long first_data_page = start >> PAGE_SHIFT; 655 unsigned long last_data_page = ((u32)(start + len - 1) >> PAGE_SHIFT); 656 /* calculating the number of pages this area spans */ 657 unsigned long num_pages = last_data_page - first_data_page + 1; 658 struct bridge_dma_map_info *dma_info = &map_obj->dma_info; 659 660 if (!dma_info->sg) 661 goto out; 662 663 if (dma_info->dir != dir || dma_info->num_pages != num_pages) { 664 pr_err("%s: dma info doesn't match given params\n", __func__); 665 return -EINVAL; 666 } 667 668 dma_unmap_sg(bridge, dma_info->sg, num_pages, dma_info->dir); 669 670 pr_debug("%s: dma_map_sg unmapped\n", __func__); 671 672 kfree(dma_info->sg); 673 674 map_obj->dma_info.sg = NULL; 675 676out: 677 return ret; 678} 679 680/* Cache operation against kernel address instead of users */ 681static int memory_give_ownership(struct dmm_map_object *map_obj, 682 unsigned long start, ssize_t len, enum dma_data_direction dir) 683{ 684 int pg_i, ret, sg_num; 685 struct scatterlist *sg; 686 unsigned long first_data_page = start >> PAGE_SHIFT; 687 unsigned long last_data_page = ((u32)(start + len - 1) >> PAGE_SHIFT); 688 /* calculating the number of pages this area spans */ 689 unsigned long num_pages = last_data_page - first_data_page + 1; 690 691 pg_i = find_first_page_in_cache(map_obj, start); 692 if (pg_i < 0) { 693 pr_err("%s: failed to find first page in cache\n", __func__); 694 ret = -EINVAL; 695 goto out; 696 } 697 698 sg = kcalloc(num_pages, sizeof(*sg), GFP_KERNEL); 699 if (!sg) { 700 pr_err("%s: kcalloc failed\n", __func__); 701 ret = -ENOMEM; 702 goto out; 703 } 704 705 sg_init_table(sg, num_pages); 706 707 /* cleanup a previous sg allocation */ 708 /* this may happen if application doesn't signal for e/o DMA */ 709 kfree(map_obj->dma_info.sg); 710 711 map_obj->dma_info.sg = sg; 712 map_obj->dma_info.dir = dir; 713 map_obj->dma_info.num_pages = num_pages; 714 715 ret = build_dma_sg(map_obj, start, len, pg_i); 716 if (ret) 717 goto kfree_sg; 718 719 sg_num = dma_map_sg(bridge, sg, num_pages, dir); 720 if (sg_num < 1) { 721 pr_err("%s: dma_map_sg failed: %d\n", __func__, sg_num); 722 ret = -EFAULT; 723 goto kfree_sg; 724 } 725 726 pr_debug("%s: dma_map_sg mapped %d elements\n", __func__, sg_num); 727 map_obj->dma_info.sg_num = sg_num; 728 729 return 0; 730 731kfree_sg: 732 kfree(sg); 733 map_obj->dma_info.sg = NULL; 734out: 735 return ret; 736} 737 738int proc_begin_dma(void *hprocessor, void *pmpu_addr, u32 ul_size, 739 enum dma_data_direction dir) 740{ 741 /* Keep STATUS here for future additions to this function */ 742 int status = 0; 743 struct process_context *pr_ctxt = (struct process_context *) hprocessor; 744 struct dmm_map_object *map_obj; 745 746 if (!pr_ctxt) { 747 status = -EFAULT; 748 goto err_out; 749 } 750 751 pr_debug("%s: addr 0x%x, size 0x%x, type %d\n", __func__, 752 (u32)pmpu_addr, 753 ul_size, dir); 754 755 mutex_lock(&proc_lock); 756 757 /* find requested memory are in cached mapping information */ 758 map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size); 759 if (!map_obj) { 760 pr_err("%s: find_containing_mapping failed\n", __func__); 761 status = -EFAULT; 762 goto no_map; 763 } 764 765 if (memory_give_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) { 766 pr_err("%s: InValid address parameters %p %x\n", 767 __func__, pmpu_addr, ul_size); 768 status = -EFAULT; 769 } 770 771no_map: 772 mutex_unlock(&proc_lock); 773err_out: 774 775 return status; 776} 777 778int proc_end_dma(void *hprocessor, void *pmpu_addr, u32 ul_size, 779 enum dma_data_direction dir) 780{ 781 /* Keep STATUS here for future additions to this function */ 782 int status = 0; 783 struct process_context *pr_ctxt = (struct process_context *) hprocessor; 784 struct dmm_map_object *map_obj; 785 786 if (!pr_ctxt) { 787 status = -EFAULT; 788 goto err_out; 789 } 790 791 pr_debug("%s: addr 0x%x, size 0x%x, type %d\n", __func__, 792 (u32)pmpu_addr, 793 ul_size, dir); 794 795 mutex_lock(&proc_lock); 796 797 /* find requested memory are in cached mapping information */ 798 map_obj = find_containing_mapping(pr_ctxt, (u32) pmpu_addr, ul_size); 799 if (!map_obj) { 800 pr_err("%s: find_containing_mapping failed\n", __func__); 801 status = -EFAULT; 802 goto no_map; 803 } 804 805 if (memory_regain_ownership(map_obj, (u32) pmpu_addr, ul_size, dir)) { 806 pr_err("%s: InValid address parameters %p %x\n", 807 __func__, pmpu_addr, ul_size); 808 status = -EFAULT; 809 } 810 811no_map: 812 mutex_unlock(&proc_lock); 813err_out: 814 return status; 815} 816 817/* 818 * ======== proc_flush_memory ======== 819 * Purpose: 820 * Flush cache 821 */ 822int proc_flush_memory(void *hprocessor, void *pmpu_addr, 823 u32 ul_size, u32 ul_flags) 824{ 825 enum dma_data_direction dir = DMA_BIDIRECTIONAL; 826 827 return proc_begin_dma(hprocessor, pmpu_addr, ul_size, dir); 828} 829 830/* 831 * ======== proc_invalidate_memory ======== 832 * Purpose: 833 * Invalidates the memory specified 834 */ 835int proc_invalidate_memory(void *hprocessor, void *pmpu_addr, u32 size) 836{ 837 enum dma_data_direction dir = DMA_FROM_DEVICE; 838 839 return proc_begin_dma(hprocessor, pmpu_addr, size, dir); 840} 841 842/* 843 * ======== proc_get_resource_info ======== 844 * Purpose: 845 * Enumerate the resources currently available on a processor. 846 */ 847int proc_get_resource_info(void *hprocessor, u32 resource_type, 848 struct dsp_resourceinfo *resource_info, 849 u32 resource_info_size) 850{ 851 int status = -EPERM; 852 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 853 struct node_mgr *hnode_mgr = NULL; 854 struct nldr_object *nldr_obj = NULL; 855 struct rmm_target_obj *rmm = NULL; 856 struct io_mgr *hio_mgr = NULL; /* IO manager handle */ 857 858 if (!p_proc_object) { 859 status = -EFAULT; 860 goto func_end; 861 } 862 switch (resource_type) { 863 case DSP_RESOURCE_DYNDARAM: 864 case DSP_RESOURCE_DYNSARAM: 865 case DSP_RESOURCE_DYNEXTERNAL: 866 case DSP_RESOURCE_DYNSRAM: 867 status = dev_get_node_manager(p_proc_object->dev_obj, 868 &hnode_mgr); 869 if (!hnode_mgr) { 870 status = -EFAULT; 871 goto func_end; 872 } 873 874 status = node_get_nldr_obj(hnode_mgr, &nldr_obj); 875 if (!status) { 876 status = nldr_get_rmm_manager(nldr_obj, &rmm); 877 if (rmm) { 878 if (!rmm_stat(rmm, 879 (enum dsp_memtype)resource_type, 880 (struct dsp_memstat *) 881 &(resource_info->result. 882 mem_stat))) 883 status = -EINVAL; 884 } else { 885 status = -EFAULT; 886 } 887 } 888 break; 889 case DSP_RESOURCE_PROCLOAD: 890 status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr); 891 if (hio_mgr) 892 status = 893 p_proc_object->intf_fxns-> 894 io_get_proc_load(hio_mgr, 895 (struct dsp_procloadstat *) 896 &(resource_info->result. 897 proc_load_stat)); 898 else 899 status = -EFAULT; 900 break; 901 default: 902 status = -EPERM; 903 break; 904 } 905func_end: 906 return status; 907} 908 909/* 910 * ======== proc_get_dev_object ======== 911 * Purpose: 912 * Return the Dev Object handle for a given Processor. 913 * 914 */ 915int proc_get_dev_object(void *hprocessor, 916 struct dev_object **device_obj) 917{ 918 int status = -EPERM; 919 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 920 921 if (p_proc_object) { 922 *device_obj = p_proc_object->dev_obj; 923 status = 0; 924 } else { 925 *device_obj = NULL; 926 status = -EFAULT; 927 } 928 929 return status; 930} 931 932/* 933 * ======== proc_get_state ======== 934 * Purpose: 935 * Report the state of the specified DSP processor. 936 */ 937int proc_get_state(void *hprocessor, 938 struct dsp_processorstate *proc_state_obj, 939 u32 state_info_size) 940{ 941 int status = 0; 942 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 943 int brd_status; 944 945 if (p_proc_object) { 946 /* First, retrieve BRD state information */ 947 status = (*p_proc_object->intf_fxns->brd_status) 948 (p_proc_object->bridge_context, &brd_status); 949 if (!status) { 950 switch (brd_status) { 951 case BRD_STOPPED: 952 proc_state_obj->proc_state = PROC_STOPPED; 953 break; 954 case BRD_SLEEP_TRANSITION: 955 case BRD_DSP_HIBERNATION: 956 /* Fall through */ 957 case BRD_RUNNING: 958 proc_state_obj->proc_state = PROC_RUNNING; 959 break; 960 case BRD_LOADED: 961 proc_state_obj->proc_state = PROC_LOADED; 962 break; 963 case BRD_ERROR: 964 proc_state_obj->proc_state = PROC_ERROR; 965 break; 966 default: 967 proc_state_obj->proc_state = 0xFF; 968 status = -EPERM; 969 break; 970 } 971 } 972 } else { 973 status = -EFAULT; 974 } 975 dev_dbg(bridge, "%s, results: status: 0x%x proc_state_obj: 0x%x\n", 976 __func__, status, proc_state_obj->proc_state); 977 return status; 978} 979 980/* 981 * ======== proc_get_trace ======== 982 * Purpose: 983 * Retrieve the current contents of the trace buffer, located on the 984 * Processor. Predefined symbols for the trace buffer must have been 985 * configured into the DSP executable. 986 * Details: 987 * We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a 988 * trace buffer, only. Treat it as an undocumented feature. 989 * This call is destructive, meaning the processor is placed in the monitor 990 * state as a result of this function. 991 */ 992int proc_get_trace(void *hprocessor, u8 * pbuf, u32 max_size) 993{ 994 int status; 995 status = -ENOSYS; 996 return status; 997} 998 999/* 1000 * ======== proc_load ======== 1001 * Purpose: 1002 * Reset a processor and load a new base program image. 1003 * This will be an OEM-only function, and not part of the DSP/BIOS Bridge 1004 * application developer's API. 1005 */ 1006int proc_load(void *hprocessor, const s32 argc_index, 1007 const char **user_args, const char **user_envp) 1008{ 1009 int status = 0; 1010 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1011 struct io_mgr *hio_mgr; /* IO manager handle */ 1012 struct msg_mgr *hmsg_mgr; 1013 struct cod_manager *cod_mgr; /* Code manager handle */ 1014 char *pargv0; /* temp argv[0] ptr */ 1015 char **new_envp; /* Updated envp[] array. */ 1016 char sz_proc_id[MAXPROCIDLEN]; /* Size of "PROC_ID=<n>" */ 1017 s32 envp_elems; /* Num elements in envp[]. */ 1018 s32 cnew_envp; /* " " in new_envp[] */ 1019 s32 nproc_id = 0; /* Anticipate MP version. */ 1020 struct dcd_manager *hdcd_handle; 1021 struct dmm_object *dmm_mgr; 1022 u32 dw_ext_end; 1023 u32 proc_id; 1024 int brd_state; 1025 struct drv_data *drv_datap = dev_get_drvdata(bridge); 1026 1027#ifdef OPT_LOAD_TIME_INSTRUMENTATION 1028 struct timeval tv1; 1029 struct timeval tv2; 1030#endif 1031 1032#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ) 1033 struct dspbridge_platform_data *pdata = 1034 omap_dspbridge_dev->dev.platform_data; 1035#endif 1036 1037#ifdef OPT_LOAD_TIME_INSTRUMENTATION 1038 do_gettimeofday(&tv1); 1039#endif 1040 if (!p_proc_object) { 1041 status = -EFAULT; 1042 goto func_end; 1043 } 1044 dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr); 1045 if (!cod_mgr) { 1046 status = -EPERM; 1047 goto func_end; 1048 } 1049 status = proc_stop(hprocessor); 1050 if (status) 1051 goto func_end; 1052 1053 /* Place the board in the monitor state. */ 1054 status = proc_monitor(hprocessor); 1055 if (status) 1056 goto func_end; 1057 1058 /* Save ptr to original argv[0]. */ 1059 pargv0 = (char *)user_args[0]; 1060 /*Prepend "PROC_ID=<nproc_id>"to envp array for target. */ 1061 envp_elems = get_envp_count((char **)user_envp); 1062 cnew_envp = (envp_elems ? (envp_elems + 1) : (envp_elems + 2)); 1063 new_envp = kzalloc(cnew_envp * sizeof(char **), GFP_KERNEL); 1064 if (new_envp) { 1065 status = snprintf(sz_proc_id, MAXPROCIDLEN, PROC_ENVPROCID, 1066 nproc_id); 1067 if (status == -1) { 1068 dev_dbg(bridge, "%s: Proc ID string overflow\n", 1069 __func__); 1070 status = -EPERM; 1071 } else { 1072 new_envp = 1073 prepend_envp(new_envp, (char **)user_envp, 1074 envp_elems, cnew_envp, sz_proc_id); 1075 /* Get the DCD Handle */ 1076 status = mgr_get_dcd_handle(p_proc_object->mgr_obj, 1077 (u32 *) &hdcd_handle); 1078 if (!status) { 1079 /* Before proceeding with new load, 1080 * check if a previously registered COFF 1081 * exists. 1082 * If yes, unregister nodes in previously 1083 * registered COFF. If any error occurred, 1084 * set previously registered COFF to NULL. */ 1085 if (p_proc_object->last_coff != NULL) { 1086 status = 1087 dcd_auto_unregister(hdcd_handle, 1088 p_proc_object-> 1089 last_coff); 1090 /* Regardless of auto unregister status, 1091 * free previously allocated 1092 * memory. */ 1093 kfree(p_proc_object->last_coff); 1094 p_proc_object->last_coff = NULL; 1095 } 1096 } 1097 /* On success, do cod_open_base() */ 1098 status = cod_open_base(cod_mgr, (char *)user_args[0], 1099 COD_SYMB); 1100 } 1101 } else { 1102 status = -ENOMEM; 1103 } 1104 if (!status) { 1105 /* Auto-register data base */ 1106 /* Get the DCD Handle */ 1107 status = mgr_get_dcd_handle(p_proc_object->mgr_obj, 1108 (u32 *) &hdcd_handle); 1109 if (!status) { 1110 /* Auto register nodes in specified COFF 1111 * file. If registration did not fail, 1112 * (status = 0 or -EACCES) 1113 * save the name of the COFF file for 1114 * de-registration in the future. */ 1115 status = 1116 dcd_auto_register(hdcd_handle, 1117 (char *)user_args[0]); 1118 if (status == -EACCES) 1119 status = 0; 1120 1121 if (status) { 1122 status = -EPERM; 1123 } else { 1124 /* Allocate memory for pszLastCoff */ 1125 p_proc_object->last_coff = 1126 kzalloc((strlen(user_args[0]) + 1127 1), GFP_KERNEL); 1128 /* If memory allocated, save COFF file name */ 1129 if (p_proc_object->last_coff) { 1130 strncpy(p_proc_object->last_coff, 1131 (char *)user_args[0], 1132 (strlen((char *)user_args[0]) + 1133 1)); 1134 } 1135 } 1136 } 1137 } 1138 /* Update shared memory address and size */ 1139 if (!status) { 1140 /* Create the message manager. This must be done 1141 * before calling the IOOnLoaded function. */ 1142 dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr); 1143 if (!hmsg_mgr) { 1144 status = msg_create(&hmsg_mgr, p_proc_object->dev_obj, 1145 (msg_onexit) node_on_exit); 1146 dev_set_msg_mgr(p_proc_object->dev_obj, hmsg_mgr); 1147 } 1148 } 1149 if (!status) { 1150 /* Set the Device object's message manager */ 1151 status = dev_get_io_mgr(p_proc_object->dev_obj, &hio_mgr); 1152 if (hio_mgr) 1153 status = (*p_proc_object->intf_fxns->io_on_loaded) 1154 (hio_mgr); 1155 else 1156 status = -EFAULT; 1157 } 1158 if (!status) { 1159 /* Now, attempt to load an exec: */ 1160 1161 /* Boost the OPP level to Maximum level supported by baseport */ 1162#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ) 1163 if (pdata->cpu_set_freq) 1164 (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP5]); 1165#endif 1166 status = cod_load_base(cod_mgr, argc_index, (char **)user_args, 1167 dev_brd_write_fxn, 1168 p_proc_object->dev_obj, NULL); 1169 if (status) { 1170 if (status == -EBADF) { 1171 dev_dbg(bridge, "%s: Failure to Load the EXE\n", 1172 __func__); 1173 } 1174 if (status == -ESPIPE) { 1175 pr_err("%s: Couldn't parse the file\n", 1176 __func__); 1177 } 1178 } 1179 /* Requesting the lowest opp supported */ 1180#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ) 1181 if (pdata->cpu_set_freq) 1182 (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP1]); 1183#endif 1184 1185 } 1186 if (!status) { 1187 /* Update the Processor status to loaded */ 1188 status = (*p_proc_object->intf_fxns->brd_set_state) 1189 (p_proc_object->bridge_context, BRD_LOADED); 1190 if (!status) { 1191 p_proc_object->proc_state = PROC_LOADED; 1192 if (p_proc_object->ntfy_obj) 1193 proc_notify_clients(p_proc_object, 1194 DSP_PROCESSORSTATECHANGE); 1195 } 1196 } 1197 if (!status) { 1198 status = proc_get_processor_id(hprocessor, &proc_id); 1199 if (proc_id == DSP_UNIT) { 1200 /* Use all available DSP address space after EXTMEM 1201 * for DMM */ 1202 if (!status) 1203 status = cod_get_sym_value(cod_mgr, EXTEND, 1204 &dw_ext_end); 1205 1206 /* Reset DMM structs and add an initial free chunk */ 1207 if (!status) { 1208 status = 1209 dev_get_dmm_mgr(p_proc_object->dev_obj, 1210 &dmm_mgr); 1211 if (dmm_mgr) { 1212 /* Set dw_ext_end to DMM START u8 1213 * address */ 1214 dw_ext_end = 1215 (dw_ext_end + 1) * DSPWORDSIZE; 1216 /* DMM memory is from EXT_END */ 1217 status = dmm_create_tables(dmm_mgr, 1218 dw_ext_end, 1219 DMMPOOLSIZE); 1220 } else { 1221 status = -EFAULT; 1222 } 1223 } 1224 } 1225 } 1226 /* Restore the original argv[0] */ 1227 kfree(new_envp); 1228 user_args[0] = pargv0; 1229 if (!status) { 1230 if (!((*p_proc_object->intf_fxns->brd_status) 1231 (p_proc_object->bridge_context, &brd_state))) { 1232 pr_info("%s: Processor Loaded %s\n", __func__, pargv0); 1233 kfree(drv_datap->base_img); 1234 drv_datap->base_img = kmalloc(strlen(pargv0) + 1, 1235 GFP_KERNEL); 1236 if (drv_datap->base_img) 1237 strncpy(drv_datap->base_img, pargv0, 1238 strlen(pargv0) + 1); 1239 else 1240 status = -ENOMEM; 1241 } 1242 } 1243 1244func_end: 1245 if (status) { 1246 pr_err("%s: Processor failed to load\n", __func__); 1247 proc_stop(p_proc_object); 1248 } 1249#ifdef OPT_LOAD_TIME_INSTRUMENTATION 1250 do_gettimeofday(&tv2); 1251 if (tv2.tv_usec < tv1.tv_usec) { 1252 tv2.tv_usec += 1000000; 1253 tv2.tv_sec--; 1254 } 1255 dev_dbg(bridge, "%s: time to load %d sec and %d usec\n", __func__, 1256 tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec); 1257#endif 1258 return status; 1259} 1260 1261/* 1262 * ======== proc_map ======== 1263 * Purpose: 1264 * Maps a MPU buffer to DSP address space. 1265 */ 1266int proc_map(void *hprocessor, void *pmpu_addr, u32 ul_size, 1267 void *req_addr, void **pp_map_addr, u32 ul_map_attr, 1268 struct process_context *pr_ctxt) 1269{ 1270 u32 va_align; 1271 u32 pa_align; 1272 struct dmm_object *dmm_mgr; 1273 u32 size_align; 1274 int status = 0; 1275 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1276 struct dmm_map_object *map_obj; 1277 u32 tmp_addr = 0; 1278 1279#ifdef CONFIG_TIDSPBRIDGE_CACHE_LINE_CHECK 1280 if ((ul_map_attr & BUFMODE_MASK) != RBUF) { 1281 if (!IS_ALIGNED((u32)pmpu_addr, DSP_CACHE_LINE) || 1282 !IS_ALIGNED(ul_size, DSP_CACHE_LINE)) { 1283 pr_err("%s: not aligned: 0x%x (%d)\n", __func__, 1284 (u32)pmpu_addr, ul_size); 1285 return -EFAULT; 1286 } 1287 } 1288#endif 1289 1290 /* Calculate the page-aligned PA, VA and size */ 1291 va_align = PG_ALIGN_LOW((u32) req_addr, PG_SIZE4K); 1292 pa_align = PG_ALIGN_LOW((u32) pmpu_addr, PG_SIZE4K); 1293 size_align = PG_ALIGN_HIGH(ul_size + (u32) pmpu_addr - pa_align, 1294 PG_SIZE4K); 1295 1296 if (!p_proc_object) { 1297 status = -EFAULT; 1298 goto func_end; 1299 } 1300 /* Critical section */ 1301 mutex_lock(&proc_lock); 1302 dmm_get_handle(p_proc_object, &dmm_mgr); 1303 if (dmm_mgr) 1304 status = dmm_map_memory(dmm_mgr, va_align, size_align); 1305 else 1306 status = -EFAULT; 1307 1308 /* Add mapping to the page tables. */ 1309 if (!status) { 1310 1311 /* Mapped address = MSB of VA | LSB of PA */ 1312 tmp_addr = (va_align | ((u32) pmpu_addr & (PG_SIZE4K - 1))); 1313 /* mapped memory resource tracking */ 1314 map_obj = add_mapping_info(pr_ctxt, pa_align, tmp_addr, 1315 size_align); 1316 if (!map_obj) 1317 status = -ENOMEM; 1318 else 1319 status = (*p_proc_object->intf_fxns->brd_mem_map) 1320 (p_proc_object->bridge_context, pa_align, va_align, 1321 size_align, ul_map_attr, map_obj->pages); 1322 } 1323 if (!status) { 1324 /* Mapped address = MSB of VA | LSB of PA */ 1325 *pp_map_addr = (void *) tmp_addr; 1326 } else { 1327 remove_mapping_information(pr_ctxt, tmp_addr, size_align); 1328 dmm_un_map_memory(dmm_mgr, va_align, &size_align); 1329 } 1330 mutex_unlock(&proc_lock); 1331 1332 if (status) 1333 goto func_end; 1334 1335func_end: 1336 dev_dbg(bridge, "%s: hprocessor %p, pmpu_addr %p, ul_size %x, " 1337 "req_addr %p, ul_map_attr %x, pp_map_addr %p, va_align %x, " 1338 "pa_align %x, size_align %x status 0x%x\n", __func__, 1339 hprocessor, pmpu_addr, ul_size, req_addr, ul_map_attr, 1340 pp_map_addr, va_align, pa_align, size_align, status); 1341 1342 return status; 1343} 1344 1345/* 1346 * ======== proc_register_notify ======== 1347 * Purpose: 1348 * Register to be notified of specific processor events. 1349 */ 1350int proc_register_notify(void *hprocessor, u32 event_mask, 1351 u32 notify_type, struct dsp_notification 1352 * hnotification) 1353{ 1354 int status = 0; 1355 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1356 struct deh_mgr *hdeh_mgr; 1357 1358 /* Check processor handle */ 1359 if (!p_proc_object) { 1360 status = -EFAULT; 1361 goto func_end; 1362 } 1363 /* Check if event mask is a valid processor related event */ 1364 if (event_mask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH | 1365 DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | 1366 DSP_MMUFAULT | DSP_SYSERROR | DSP_PWRERROR | 1367 DSP_WDTOVERFLOW)) 1368 status = -EINVAL; 1369 1370 /* Check if notify type is valid */ 1371 if (notify_type != DSP_SIGNALEVENT) 1372 status = -EINVAL; 1373 1374 if (!status) { 1375 /* If event mask is not DSP_SYSERROR, DSP_MMUFAULT, 1376 * or DSP_PWRERROR then register event immediately. */ 1377 if (event_mask & 1378 ~(DSP_SYSERROR | DSP_MMUFAULT | DSP_PWRERROR | 1379 DSP_WDTOVERFLOW)) { 1380 status = ntfy_register(p_proc_object->ntfy_obj, 1381 hnotification, event_mask, 1382 notify_type); 1383 /* Special case alert, special case alert! 1384 * If we're trying to *deregister* (i.e. event_mask 1385 * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification, 1386 * we have to deregister with the DEH manager. 1387 * There's no way to know, based on event_mask which 1388 * manager the notification event was registered with, 1389 * so if we're trying to deregister and ntfy_register 1390 * failed, we'll give the deh manager a shot. 1391 */ 1392 if ((event_mask == 0) && status) { 1393 status = 1394 dev_get_deh_mgr(p_proc_object->dev_obj, 1395 &hdeh_mgr); 1396 status = 1397 bridge_deh_register_notify(hdeh_mgr, 1398 event_mask, 1399 notify_type, 1400 hnotification); 1401 } 1402 } else { 1403 status = dev_get_deh_mgr(p_proc_object->dev_obj, 1404 &hdeh_mgr); 1405 status = 1406 bridge_deh_register_notify(hdeh_mgr, 1407 event_mask, 1408 notify_type, 1409 hnotification); 1410 1411 } 1412 } 1413func_end: 1414 return status; 1415} 1416 1417/* 1418 * ======== proc_reserve_memory ======== 1419 * Purpose: 1420 * Reserve a virtually contiguous region of DSP address space. 1421 */ 1422int proc_reserve_memory(void *hprocessor, u32 ul_size, 1423 void **pp_rsv_addr, 1424 struct process_context *pr_ctxt) 1425{ 1426 struct dmm_object *dmm_mgr; 1427 int status = 0; 1428 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1429 struct dmm_rsv_object *rsv_obj; 1430 1431 if (!p_proc_object) { 1432 status = -EFAULT; 1433 goto func_end; 1434 } 1435 1436 status = dmm_get_handle(p_proc_object, &dmm_mgr); 1437 if (!dmm_mgr) { 1438 status = -EFAULT; 1439 goto func_end; 1440 } 1441 1442 status = dmm_reserve_memory(dmm_mgr, ul_size, (u32 *) pp_rsv_addr); 1443 if (status != 0) 1444 goto func_end; 1445 1446 /* 1447 * A successful reserve should be followed by insertion of rsv_obj 1448 * into dmm_rsv_list, so that reserved memory resource tracking 1449 * remains uptodate 1450 */ 1451 rsv_obj = kmalloc(sizeof(struct dmm_rsv_object), GFP_KERNEL); 1452 if (rsv_obj) { 1453 rsv_obj->dsp_reserved_addr = (u32) *pp_rsv_addr; 1454 spin_lock(&pr_ctxt->dmm_rsv_lock); 1455 list_add(&rsv_obj->link, &pr_ctxt->dmm_rsv_list); 1456 spin_unlock(&pr_ctxt->dmm_rsv_lock); 1457 } 1458 1459func_end: 1460 dev_dbg(bridge, "%s: hprocessor: 0x%p ul_size: 0x%x pp_rsv_addr: 0x%p " 1461 "status 0x%x\n", __func__, hprocessor, 1462 ul_size, pp_rsv_addr, status); 1463 return status; 1464} 1465 1466/* 1467 * ======== proc_start ======== 1468 * Purpose: 1469 * Start a processor running. 1470 */ 1471int proc_start(void *hprocessor) 1472{ 1473 int status = 0; 1474 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1475 struct cod_manager *cod_mgr; /* Code manager handle */ 1476 u32 dw_dsp_addr; /* Loaded code's entry point. */ 1477 int brd_state; 1478 1479 if (!p_proc_object) { 1480 status = -EFAULT; 1481 goto func_end; 1482 } 1483 /* Call the bridge_brd_start */ 1484 if (p_proc_object->proc_state != PROC_LOADED) { 1485 status = -EBADR; 1486 goto func_end; 1487 } 1488 status = dev_get_cod_mgr(p_proc_object->dev_obj, &cod_mgr); 1489 if (!cod_mgr) { 1490 status = -EFAULT; 1491 goto func_cont; 1492 } 1493 1494 status = cod_get_entry(cod_mgr, &dw_dsp_addr); 1495 if (status) 1496 goto func_cont; 1497 1498 status = (*p_proc_object->intf_fxns->brd_start) 1499 (p_proc_object->bridge_context, dw_dsp_addr); 1500 if (status) 1501 goto func_cont; 1502 1503 /* Call dev_create2 */ 1504 status = dev_create2(p_proc_object->dev_obj); 1505 if (!status) { 1506 p_proc_object->proc_state = PROC_RUNNING; 1507 /* Deep sleep switces off the peripheral clocks. 1508 * we just put the DSP CPU in idle in the idle loop. 1509 * so there is no need to send a command to DSP */ 1510 1511 if (p_proc_object->ntfy_obj) { 1512 proc_notify_clients(p_proc_object, 1513 DSP_PROCESSORSTATECHANGE); 1514 } 1515 } else { 1516 /* Failed to Create Node Manager and DISP Object 1517 * Stop the Processor from running. Put it in STOPPED State */ 1518 (void)(*p_proc_object->intf_fxns-> 1519 brd_stop) (p_proc_object->bridge_context); 1520 p_proc_object->proc_state = PROC_STOPPED; 1521 } 1522func_cont: 1523 if (!status) { 1524 if (!((*p_proc_object->intf_fxns->brd_status) 1525 (p_proc_object->bridge_context, &brd_state))) { 1526 pr_info("%s: dsp in running state\n", __func__); 1527 } 1528 } else { 1529 pr_err("%s: Failed to start the dsp\n", __func__); 1530 proc_stop(p_proc_object); 1531 } 1532 1533func_end: 1534 return status; 1535} 1536 1537/* 1538 * ======== proc_stop ======== 1539 * Purpose: 1540 * Stop a processor running. 1541 */ 1542int proc_stop(void *hprocessor) 1543{ 1544 int status = 0; 1545 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1546 struct msg_mgr *hmsg_mgr; 1547 struct node_mgr *hnode_mgr; 1548 void *hnode; 1549 u32 node_tab_size = 1; 1550 u32 num_nodes = 0; 1551 u32 nodes_allocated = 0; 1552 1553 if (!p_proc_object) { 1554 status = -EFAULT; 1555 goto func_end; 1556 } 1557 /* check if there are any running nodes */ 1558 status = dev_get_node_manager(p_proc_object->dev_obj, &hnode_mgr); 1559 if (!status && hnode_mgr) { 1560 status = node_enum_nodes(hnode_mgr, &hnode, node_tab_size, 1561 &num_nodes, &nodes_allocated); 1562 if ((status == -EINVAL) || (nodes_allocated > 0)) { 1563 pr_err("%s: Can't stop device, active nodes = %d \n", 1564 __func__, nodes_allocated); 1565 return -EBADR; 1566 } 1567 } 1568 /* Call the bridge_brd_stop */ 1569 /* It is OK to stop a device that does n't have nodes OR not started */ 1570 status = 1571 (*p_proc_object->intf_fxns-> 1572 brd_stop) (p_proc_object->bridge_context); 1573 if (!status) { 1574 dev_dbg(bridge, "%s: processor in standby mode\n", __func__); 1575 p_proc_object->proc_state = PROC_STOPPED; 1576 /* Destroy the Node Manager, msg_ctrl Manager */ 1577 if (!(dev_destroy2(p_proc_object->dev_obj))) { 1578 /* Destroy the msg_ctrl by calling msg_delete */ 1579 dev_get_msg_mgr(p_proc_object->dev_obj, &hmsg_mgr); 1580 if (hmsg_mgr) { 1581 msg_delete(hmsg_mgr); 1582 dev_set_msg_mgr(p_proc_object->dev_obj, NULL); 1583 } 1584 } 1585 } else { 1586 pr_err("%s: Failed to stop the processor\n", __func__); 1587 } 1588func_end: 1589 1590 return status; 1591} 1592 1593/* 1594 * ======== proc_un_map ======== 1595 * Purpose: 1596 * Removes a MPU buffer mapping from the DSP address space. 1597 */ 1598int proc_un_map(void *hprocessor, void *map_addr, 1599 struct process_context *pr_ctxt) 1600{ 1601 int status = 0; 1602 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1603 struct dmm_object *dmm_mgr; 1604 u32 va_align; 1605 u32 size_align; 1606 1607 va_align = PG_ALIGN_LOW((u32) map_addr, PG_SIZE4K); 1608 if (!p_proc_object) { 1609 status = -EFAULT; 1610 goto func_end; 1611 } 1612 1613 status = dmm_get_handle(hprocessor, &dmm_mgr); 1614 if (!dmm_mgr) { 1615 status = -EFAULT; 1616 goto func_end; 1617 } 1618 1619 /* Critical section */ 1620 mutex_lock(&proc_lock); 1621 /* 1622 * Update DMM structures. Get the size to unmap. 1623 * This function returns error if the VA is not mapped 1624 */ 1625 status = dmm_un_map_memory(dmm_mgr, (u32) va_align, &size_align); 1626 /* Remove mapping from the page tables. */ 1627 if (!status) { 1628 status = (*p_proc_object->intf_fxns->brd_mem_un_map) 1629 (p_proc_object->bridge_context, va_align, size_align); 1630 } 1631 1632 if (status) 1633 goto unmap_failed; 1634 1635 /* 1636 * A successful unmap should be followed by removal of map_obj 1637 * from dmm_map_list, so that mapped memory resource tracking 1638 * remains uptodate 1639 */ 1640 remove_mapping_information(pr_ctxt, (u32) map_addr, size_align); 1641 1642unmap_failed: 1643 mutex_unlock(&proc_lock); 1644 1645func_end: 1646 dev_dbg(bridge, "%s: hprocessor: 0x%p map_addr: 0x%p status: 0x%x\n", 1647 __func__, hprocessor, map_addr, status); 1648 return status; 1649} 1650 1651/* 1652 * ======== proc_un_reserve_memory ======== 1653 * Purpose: 1654 * Frees a previously reserved region of DSP address space. 1655 */ 1656int proc_un_reserve_memory(void *hprocessor, void *prsv_addr, 1657 struct process_context *pr_ctxt) 1658{ 1659 struct dmm_object *dmm_mgr; 1660 int status = 0; 1661 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1662 struct dmm_rsv_object *rsv_obj; 1663 1664 if (!p_proc_object) { 1665 status = -EFAULT; 1666 goto func_end; 1667 } 1668 1669 status = dmm_get_handle(p_proc_object, &dmm_mgr); 1670 if (!dmm_mgr) { 1671 status = -EFAULT; 1672 goto func_end; 1673 } 1674 1675 status = dmm_un_reserve_memory(dmm_mgr, (u32) prsv_addr); 1676 if (status != 0) 1677 goto func_end; 1678 1679 /* 1680 * A successful unreserve should be followed by removal of rsv_obj 1681 * from dmm_rsv_list, so that reserved memory resource tracking 1682 * remains uptodate 1683 */ 1684 spin_lock(&pr_ctxt->dmm_rsv_lock); 1685 list_for_each_entry(rsv_obj, &pr_ctxt->dmm_rsv_list, link) { 1686 if (rsv_obj->dsp_reserved_addr == (u32) prsv_addr) { 1687 list_del(&rsv_obj->link); 1688 kfree(rsv_obj); 1689 break; 1690 } 1691 } 1692 spin_unlock(&pr_ctxt->dmm_rsv_lock); 1693 1694func_end: 1695 dev_dbg(bridge, "%s: hprocessor: 0x%p prsv_addr: 0x%p status: 0x%x\n", 1696 __func__, hprocessor, prsv_addr, status); 1697 return status; 1698} 1699 1700/* 1701 * ======== = proc_monitor ======== == 1702 * Purpose: 1703 * Place the Processor in Monitor State. This is an internal 1704 * function and a requirement before Processor is loaded. 1705 * This does a bridge_brd_stop, dev_destroy2 and bridge_brd_monitor. 1706 * In dev_destroy2 we delete the node manager. 1707 * Parameters: 1708 * p_proc_object: Pointer to Processor Object 1709 * Returns: 1710 * 0: Processor placed in monitor mode. 1711 * !0: Failed to place processor in monitor mode. 1712 * Requires: 1713 * Valid Processor Handle 1714 * Ensures: 1715 * Success: ProcObject state is PROC_IDLE 1716 */ 1717static int proc_monitor(struct proc_object *proc_obj) 1718{ 1719 int status = -EPERM; 1720 struct msg_mgr *hmsg_mgr; 1721 1722 /* This is needed only when Device is loaded when it is 1723 * already 'ACTIVE' */ 1724 /* Destroy the Node Manager, msg_ctrl Manager */ 1725 if (!dev_destroy2(proc_obj->dev_obj)) { 1726 /* Destroy the msg_ctrl by calling msg_delete */ 1727 dev_get_msg_mgr(proc_obj->dev_obj, &hmsg_mgr); 1728 if (hmsg_mgr) { 1729 msg_delete(hmsg_mgr); 1730 dev_set_msg_mgr(proc_obj->dev_obj, NULL); 1731 } 1732 } 1733 /* Place the Board in the Monitor State */ 1734 if (!((*proc_obj->intf_fxns->brd_monitor) 1735 (proc_obj->bridge_context))) { 1736 status = 0; 1737 } 1738 1739 return status; 1740} 1741 1742/* 1743 * ======== get_envp_count ======== 1744 * Purpose: 1745 * Return the number of elements in the envp array, including the 1746 * terminating NULL element. 1747 */ 1748static s32 get_envp_count(char **envp) 1749{ 1750 s32 ret = 0; 1751 if (envp) { 1752 while (*envp++) 1753 ret++; 1754 1755 ret += 1; /* Include the terminating NULL in the count. */ 1756 } 1757 1758 return ret; 1759} 1760 1761/* 1762 * ======== prepend_envp ======== 1763 * Purpose: 1764 * Prepend an environment variable=value pair to the new envp array, and 1765 * copy in the existing var=value pairs in the old envp array. 1766 */ 1767static char **prepend_envp(char **new_envp, char **envp, s32 envp_elems, 1768 s32 cnew_envp, char *sz_var) 1769{ 1770 char **pp_envp = new_envp; 1771 1772 /* Prepend new environ var=value string */ 1773 *new_envp++ = sz_var; 1774 1775 /* Copy user's environment into our own. */ 1776 while (envp_elems--) 1777 *new_envp++ = *envp++; 1778 1779 /* Ensure NULL terminates the new environment strings array. */ 1780 if (envp_elems == 0) 1781 *new_envp = NULL; 1782 1783 return pp_envp; 1784} 1785 1786/* 1787 * ======== proc_notify_clients ======== 1788 * Purpose: 1789 * Notify the processor the events. 1790 */ 1791int proc_notify_clients(void *proc, u32 events) 1792{ 1793 int status = 0; 1794 struct proc_object *p_proc_object = (struct proc_object *)proc; 1795 1796 if (!p_proc_object) { 1797 status = -EFAULT; 1798 goto func_end; 1799 } 1800 1801 ntfy_notify(p_proc_object->ntfy_obj, events); 1802func_end: 1803 return status; 1804} 1805 1806/* 1807 * ======== proc_notify_all_clients ======== 1808 * Purpose: 1809 * Notify the processor the events. This includes notifying all clients 1810 * attached to a particulat DSP. 1811 */ 1812int proc_notify_all_clients(void *proc, u32 events) 1813{ 1814 int status = 0; 1815 struct proc_object *p_proc_object = (struct proc_object *)proc; 1816 1817 if (!p_proc_object) { 1818 status = -EFAULT; 1819 goto func_end; 1820 } 1821 1822 dev_notify_clients(p_proc_object->dev_obj, events); 1823 1824func_end: 1825 return status; 1826} 1827 1828/* 1829 * ======== proc_get_processor_id ======== 1830 * Purpose: 1831 * Retrieves the processor ID. 1832 */ 1833int proc_get_processor_id(void *proc, u32 * proc_id) 1834{ 1835 int status = 0; 1836 struct proc_object *p_proc_object = (struct proc_object *)proc; 1837 1838 if (p_proc_object) 1839 *proc_id = p_proc_object->processor_id; 1840 else 1841 status = -EFAULT; 1842 1843 return status; 1844} 1845