1/*************************************************************************** 2 BCM70010 Linux driver 3 Copyright (c) 2005-2009, Broadcom Corporation. 4 5 This driver is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, version 2 of the License. 8 9 This driver is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this driver. If not, see <http://www.gnu.org/licenses/>. 16***************************************************************************/ 17 18#include <linux/mutex.h> 19#include <linux/slab.h> 20 21#include "crystalhd_lnx.h" 22 23static DEFINE_MUTEX(chd_dec_mutex); 24static struct class *crystalhd_class; 25 26static struct crystalhd_adp *g_adp_info; 27 28static irqreturn_t chd_dec_isr(int irq, void *arg) 29{ 30 struct crystalhd_adp *adp = (struct crystalhd_adp *) arg; 31 int rc = 0; 32 if (adp) 33 rc = crystalhd_cmd_interrupt(&adp->cmds); 34 35 return IRQ_RETVAL(rc); 36} 37 38static int chd_dec_enable_int(struct crystalhd_adp *adp) 39{ 40 int rc = 0; 41 42 if (!adp || !adp->pdev) { 43 BCMLOG_ERR("Invalid arg!!\n"); 44 return -EINVAL; 45 } 46 47 if (adp->pdev->msi_enabled) 48 adp->msi = 1; 49 else 50 adp->msi = pci_enable_msi(adp->pdev); 51 52 rc = request_irq(adp->pdev->irq, chd_dec_isr, IRQF_SHARED, 53 adp->name, (void *)adp); 54 if (rc) { 55 BCMLOG_ERR("Interrupt request failed..\n"); 56 pci_disable_msi(adp->pdev); 57 } 58 59 return rc; 60} 61 62static int chd_dec_disable_int(struct crystalhd_adp *adp) 63{ 64 if (!adp || !adp->pdev) { 65 BCMLOG_ERR("Invalid arg!!\n"); 66 return -EINVAL; 67 } 68 69 free_irq(adp->pdev->irq, adp); 70 71 if (adp->msi) 72 pci_disable_msi(adp->pdev); 73 74 return 0; 75} 76 77struct crystalhd_ioctl_data *chd_dec_alloc_iodata(struct crystalhd_adp *adp, bool isr) 78{ 79 unsigned long flags = 0; 80 struct crystalhd_ioctl_data *temp; 81 82 if (!adp) 83 return NULL; 84 85 spin_lock_irqsave(&adp->lock, flags); 86 87 temp = adp->idata_free_head; 88 if (temp) { 89 adp->idata_free_head = adp->idata_free_head->next; 90 memset(temp, 0, sizeof(*temp)); 91 } 92 93 spin_unlock_irqrestore(&adp->lock, flags); 94 return temp; 95} 96 97void chd_dec_free_iodata(struct crystalhd_adp *adp, struct crystalhd_ioctl_data *iodata, 98 bool isr) 99{ 100 unsigned long flags = 0; 101 102 if (!adp || !iodata) 103 return; 104 105 spin_lock_irqsave(&adp->lock, flags); 106 iodata->next = adp->idata_free_head; 107 adp->idata_free_head = iodata; 108 spin_unlock_irqrestore(&adp->lock, flags); 109} 110 111static inline int crystalhd_user_data(unsigned long ud, void *dr, int size, int set) 112{ 113 int rc; 114 115 if (!ud || !dr) { 116 BCMLOG_ERR("Invalid arg\n"); 117 return -EINVAL; 118 } 119 120 if (set) 121 rc = copy_to_user((void *)ud, dr, size); 122 else 123 rc = copy_from_user(dr, (void *)ud, size); 124 125 if (rc) { 126 BCMLOG_ERR("Invalid args for command\n"); 127 rc = -EFAULT; 128 } 129 130 return rc; 131} 132 133static int chd_dec_fetch_cdata(struct crystalhd_adp *adp, struct crystalhd_ioctl_data *io, 134 uint32_t m_sz, unsigned long ua) 135{ 136 unsigned long ua_off; 137 int rc = 0; 138 139 if (!adp || !io || !ua || !m_sz) { 140 BCMLOG_ERR("Invalid Arg!!\n"); 141 return -EINVAL; 142 } 143 144 io->add_cdata = vmalloc(m_sz); 145 if (!io->add_cdata) { 146 BCMLOG_ERR("kalloc fail for sz:%x\n", m_sz); 147 return -ENOMEM; 148 } 149 150 io->add_cdata_sz = m_sz; 151 ua_off = ua + sizeof(io->udata); 152 rc = crystalhd_user_data(ua_off, io->add_cdata, io->add_cdata_sz, 0); 153 if (rc) { 154 BCMLOG_ERR("failed to pull add_cdata sz:%x ua_off:%x\n", 155 io->add_cdata_sz, (unsigned int)ua_off); 156 kfree(io->add_cdata); 157 io->add_cdata = NULL; 158 return -ENODATA; 159 } 160 161 return rc; 162} 163 164static int chd_dec_release_cdata(struct crystalhd_adp *adp, 165 struct crystalhd_ioctl_data *io, unsigned long ua) 166{ 167 unsigned long ua_off; 168 int rc; 169 170 if (!adp || !io || !ua) { 171 BCMLOG_ERR("Invalid Arg!!\n"); 172 return -EINVAL; 173 } 174 175 if (io->cmd != BCM_IOC_FW_DOWNLOAD) { 176 ua_off = ua + sizeof(io->udata); 177 rc = crystalhd_user_data(ua_off, io->add_cdata, 178 io->add_cdata_sz, 1); 179 if (rc) { 180 BCMLOG_ERR("failed to push add_cdata sz:%x ua_off:%x\n", 181 io->add_cdata_sz, (unsigned int)ua_off); 182 return -ENODATA; 183 } 184 } 185 186 if (io->add_cdata) { 187 vfree(io->add_cdata); 188 io->add_cdata = NULL; 189 } 190 191 return 0; 192} 193 194static int chd_dec_proc_user_data(struct crystalhd_adp *adp, 195 struct crystalhd_ioctl_data *io, 196 unsigned long ua, int set) 197{ 198 int rc; 199 uint32_t m_sz = 0; 200 201 if (!adp || !io || !ua) { 202 BCMLOG_ERR("Invalid Arg!!\n"); 203 return -EINVAL; 204 } 205 206 rc = crystalhd_user_data(ua, &io->udata, sizeof(io->udata), set); 207 if (rc) { 208 BCMLOG_ERR("failed to %s iodata\n", (set ? "set" : "get")); 209 return rc; 210 } 211 212 switch (io->cmd) { 213 case BCM_IOC_MEM_RD: 214 case BCM_IOC_MEM_WR: 215 case BCM_IOC_FW_DOWNLOAD: 216 m_sz = io->udata.u.devMem.NumDwords * 4; 217 if (set) 218 rc = chd_dec_release_cdata(adp, io, ua); 219 else 220 rc = chd_dec_fetch_cdata(adp, io, m_sz, ua); 221 break; 222 default: 223 break; 224 } 225 226 return rc; 227} 228 229static int chd_dec_api_cmd(struct crystalhd_adp *adp, unsigned long ua, 230 uint32_t uid, uint32_t cmd, crystalhd_cmd_proc func) 231{ 232 int rc; 233 struct crystalhd_ioctl_data *temp; 234 enum BC_STATUS sts = BC_STS_SUCCESS; 235 236 temp = chd_dec_alloc_iodata(adp, 0); 237 if (!temp) { 238 BCMLOG_ERR("Failed to get iodata..\n"); 239 return -EINVAL; 240 } 241 242 temp->u_id = uid; 243 temp->cmd = cmd; 244 245 rc = chd_dec_proc_user_data(adp, temp, ua, 0); 246 if (!rc) { 247 sts = func(&adp->cmds, temp); 248 if (sts == BC_STS_PENDING) 249 sts = BC_STS_NOT_IMPL; 250 temp->udata.RetSts = sts; 251 rc = chd_dec_proc_user_data(adp, temp, ua, 1); 252 } 253 254 if (temp) { 255 chd_dec_free_iodata(adp, temp, 0); 256 temp = NULL; 257 } 258 259 return rc; 260} 261 262/* API interfaces */ 263static long chd_dec_ioctl(struct file *fd, unsigned int cmd, unsigned long ua) 264{ 265 struct crystalhd_adp *adp = chd_get_adp(); 266 crystalhd_cmd_proc cproc; 267 struct crystalhd_user *uc; 268 int ret; 269 270 if (!adp || !fd) { 271 BCMLOG_ERR("Invalid adp\n"); 272 return -EINVAL; 273 } 274 275 uc = fd->private_data; 276 if (!uc) { 277 BCMLOG_ERR("Failed to get uc\n"); 278 return -ENODATA; 279 } 280 281 mutex_lock(&chd_dec_mutex); 282 cproc = crystalhd_get_cmd_proc(&adp->cmds, cmd, uc); 283 if (!cproc) { 284 BCMLOG_ERR("Unhandled command: %d\n", cmd); 285 mutex_unlock(&chd_dec_mutex); 286 return -EINVAL; 287 } 288 289 ret = chd_dec_api_cmd(adp, ua, uc->uid, cmd, cproc); 290 mutex_unlock(&chd_dec_mutex); 291 return ret; 292} 293 294static int chd_dec_open(struct inode *in, struct file *fd) 295{ 296 struct crystalhd_adp *adp = chd_get_adp(); 297 int rc = 0; 298 enum BC_STATUS sts = BC_STS_SUCCESS; 299 struct crystalhd_user *uc = NULL; 300 301 BCMLOG_ENTER; 302 if (!adp) { 303 BCMLOG_ERR("Invalid adp\n"); 304 return -EINVAL; 305 } 306 307 if (adp->cfg_users >= BC_LINK_MAX_OPENS) { 308 BCMLOG(BCMLOG_INFO, "Already in use.%d\n", adp->cfg_users); 309 return -EBUSY; 310 } 311 312 sts = crystalhd_user_open(&adp->cmds, &uc); 313 if (sts != BC_STS_SUCCESS) { 314 BCMLOG_ERR("cmd_user_open - %d\n", sts); 315 rc = -EBUSY; 316 } 317 318 adp->cfg_users++; 319 320 fd->private_data = uc; 321 322 return rc; 323} 324 325static int chd_dec_close(struct inode *in, struct file *fd) 326{ 327 struct crystalhd_adp *adp = chd_get_adp(); 328 struct crystalhd_user *uc; 329 330 BCMLOG_ENTER; 331 if (!adp) { 332 BCMLOG_ERR("Invalid adp\n"); 333 return -EINVAL; 334 } 335 336 uc = fd->private_data; 337 if (!uc) { 338 BCMLOG_ERR("Failed to get uc\n"); 339 return -ENODATA; 340 } 341 342 crystalhd_user_close(&adp->cmds, uc); 343 344 adp->cfg_users--; 345 346 return 0; 347} 348 349static const struct file_operations chd_dec_fops = { 350 .owner = THIS_MODULE, 351 .unlocked_ioctl = chd_dec_ioctl, 352 .open = chd_dec_open, 353 .release = chd_dec_close, 354}; 355 356static int __devinit chd_dec_init_chdev(struct crystalhd_adp *adp) 357{ 358 struct crystalhd_ioctl_data *temp; 359 struct device *dev; 360 int rc = -ENODEV, i = 0; 361 362 if (!adp) 363 goto fail; 364 365 adp->chd_dec_major = register_chrdev(0, CRYSTALHD_API_NAME, 366 &chd_dec_fops); 367 if (adp->chd_dec_major < 0) { 368 BCMLOG_ERR("Failed to create config dev\n"); 369 rc = adp->chd_dec_major; 370 goto fail; 371 } 372 373 /* register crystalhd class */ 374 crystalhd_class = class_create(THIS_MODULE, "crystalhd"); 375 if (IS_ERR(crystalhd_class)) { 376 BCMLOG_ERR("failed to create class\n"); 377 goto fail; 378 } 379 380 dev = device_create(crystalhd_class, NULL, MKDEV(adp->chd_dec_major, 0), 381 NULL, "crystalhd"); 382 if (IS_ERR(dev)) { 383 BCMLOG_ERR("failed to create device\n"); 384 goto device_create_fail; 385 } 386 387 rc = crystalhd_create_elem_pool(adp, BC_LINK_ELEM_POOL_SZ); 388 if (rc) { 389 BCMLOG_ERR("failed to create device\n"); 390 goto elem_pool_fail; 391 } 392 393 /* Allocate general purpose ioctl pool. */ 394 for (i = 0; i < CHD_IODATA_POOL_SZ; i++) { 395 temp = kzalloc(sizeof(struct crystalhd_ioctl_data), GFP_ATOMIC); 396 if (!temp) { 397 BCMLOG_ERR("ioctl data pool kzalloc failed\n"); 398 rc = -ENOMEM; 399 goto kzalloc_fail; 400 } 401 /* Add to global pool.. */ 402 chd_dec_free_iodata(adp, temp, 0); 403 } 404 405 return 0; 406 407kzalloc_fail: 408 crystalhd_delete_elem_pool(adp); 409elem_pool_fail: 410 device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0)); 411device_create_fail: 412 class_destroy(crystalhd_class); 413fail: 414 return rc; 415} 416 417static void __devexit chd_dec_release_chdev(struct crystalhd_adp *adp) 418{ 419 struct crystalhd_ioctl_data *temp = NULL; 420 if (!adp) 421 return; 422 423 if (adp->chd_dec_major > 0) { 424 /* unregister crystalhd class */ 425 device_destroy(crystalhd_class, MKDEV(adp->chd_dec_major, 0)); 426 unregister_chrdev(adp->chd_dec_major, CRYSTALHD_API_NAME); 427 BCMLOG(BCMLOG_INFO, "released api device - %d\n", 428 adp->chd_dec_major); 429 class_destroy(crystalhd_class); 430 } 431 adp->chd_dec_major = 0; 432 433 /* Clear iodata pool.. */ 434 do { 435 temp = chd_dec_alloc_iodata(adp, 0); 436 kfree(temp); 437 } while (temp); 438 439 crystalhd_delete_elem_pool(adp); 440} 441 442static int __devinit chd_pci_reserve_mem(struct crystalhd_adp *pinfo) 443{ 444 int rc; 445 unsigned long bar2 = pci_resource_start(pinfo->pdev, 2); 446 uint32_t mem_len = pci_resource_len(pinfo->pdev, 2); 447 unsigned long bar0 = pci_resource_start(pinfo->pdev, 0); 448 uint32_t i2o_len = pci_resource_len(pinfo->pdev, 0); 449 450 BCMLOG(BCMLOG_SSTEP, "bar2:0x%lx-0x%08x bar0:0x%lx-0x%08x\n", 451 bar2, mem_len, bar0, i2o_len); 452 453 rc = check_mem_region(bar2, mem_len); 454 if (rc) { 455 BCMLOG_ERR("No valid mem region...\n"); 456 return -ENOMEM; 457 } 458 459 pinfo->addr = ioremap_nocache(bar2, mem_len); 460 if (!pinfo->addr) { 461 BCMLOG_ERR("Failed to remap mem region...\n"); 462 return -ENOMEM; 463 } 464 465 pinfo->pci_mem_start = bar2; 466 pinfo->pci_mem_len = mem_len; 467 468 rc = check_mem_region(bar0, i2o_len); 469 if (rc) { 470 BCMLOG_ERR("No valid mem region...\n"); 471 return -ENOMEM; 472 } 473 474 pinfo->i2o_addr = ioremap_nocache(bar0, i2o_len); 475 if (!pinfo->i2o_addr) { 476 BCMLOG_ERR("Failed to remap mem region...\n"); 477 return -ENOMEM; 478 } 479 480 pinfo->pci_i2o_start = bar0; 481 pinfo->pci_i2o_len = i2o_len; 482 483 rc = pci_request_regions(pinfo->pdev, pinfo->name); 484 if (rc < 0) { 485 BCMLOG_ERR("Region request failed: %d\n", rc); 486 return rc; 487 } 488 489 BCMLOG(BCMLOG_SSTEP, "Mapped addr:0x%08lx i2o_addr:0x%08lx\n", 490 (unsigned long)pinfo->addr, (unsigned long)pinfo->i2o_addr); 491 492 return 0; 493} 494 495static void __devexit chd_pci_release_mem(struct crystalhd_adp *pinfo) 496{ 497 if (!pinfo) 498 return; 499 500 if (pinfo->addr) 501 iounmap(pinfo->addr); 502 503 if (pinfo->i2o_addr) 504 iounmap(pinfo->i2o_addr); 505 506 pci_release_regions(pinfo->pdev); 507} 508 509 510static void __devexit chd_dec_pci_remove(struct pci_dev *pdev) 511{ 512 struct crystalhd_adp *pinfo; 513 enum BC_STATUS sts = BC_STS_SUCCESS; 514 515 BCMLOG_ENTER; 516 517 pinfo = (struct crystalhd_adp *) pci_get_drvdata(pdev); 518 if (!pinfo) { 519 BCMLOG_ERR("could not get adp\n"); 520 return; 521 } 522 523 sts = crystalhd_delete_cmd_context(&pinfo->cmds); 524 if (sts != BC_STS_SUCCESS) 525 BCMLOG_ERR("cmd delete :%d\n", sts); 526 527 chd_dec_release_chdev(pinfo); 528 529 chd_dec_disable_int(pinfo); 530 531 chd_pci_release_mem(pinfo); 532 pci_disable_device(pinfo->pdev); 533 534 kfree(pinfo); 535 g_adp_info = NULL; 536} 537 538static int __devinit chd_dec_pci_probe(struct pci_dev *pdev, 539 const struct pci_device_id *entry) 540{ 541 struct crystalhd_adp *pinfo; 542 int rc; 543 enum BC_STATUS sts = BC_STS_SUCCESS; 544 545 BCMLOG(BCMLOG_DBG, "PCI_INFO: Vendor:0x%04x Device:0x%04x " 546 "s_vendor:0x%04x s_device: 0x%04x\n", 547 pdev->vendor, pdev->device, pdev->subsystem_vendor, 548 pdev->subsystem_device); 549 550 pinfo = kzalloc(sizeof(struct crystalhd_adp), GFP_ATOMIC); 551 if (!pinfo) { 552 BCMLOG_ERR("Failed to allocate memory\n"); 553 return -ENOMEM; 554 } 555 556 pinfo->pdev = pdev; 557 558 rc = pci_enable_device(pdev); 559 if (rc) { 560 BCMLOG_ERR("Failed to enable PCI device\n"); 561 return rc; 562 } 563 564 snprintf(pinfo->name, 31, "crystalhd_pci_e:%d:%d:%d", 565 pdev->bus->number, PCI_SLOT(pdev->devfn), 566 PCI_FUNC(pdev->devfn)); 567 568 rc = chd_pci_reserve_mem(pinfo); 569 if (rc) { 570 BCMLOG_ERR("Failed to setup memory regions.\n"); 571 return -ENOMEM; 572 } 573 574 pinfo->present = 1; 575 pinfo->drv_data = entry->driver_data; 576 577 /* Setup adapter level lock.. */ 578 spin_lock_init(&pinfo->lock); 579 580 /* setup api stuff.. */ 581 chd_dec_init_chdev(pinfo); 582 rc = chd_dec_enable_int(pinfo); 583 if (rc) { 584 BCMLOG_ERR("_enable_int err:%d\n", rc); 585 pci_disable_device(pdev); 586 return -ENODEV; 587 } 588 589 /* Set dma mask... */ 590 if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { 591 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); 592 pinfo->dmabits = 64; 593 } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { 594 pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); 595 pinfo->dmabits = 32; 596 } else { 597 BCMLOG_ERR("Unabled to setup DMA %d\n", rc); 598 pci_disable_device(pdev); 599 return -ENODEV; 600 } 601 602 sts = crystalhd_setup_cmd_context(&pinfo->cmds, pinfo); 603 if (sts != BC_STS_SUCCESS) { 604 BCMLOG_ERR("cmd setup :%d\n", sts); 605 pci_disable_device(pdev); 606 return -ENODEV; 607 } 608 609 pci_set_master(pdev); 610 611 pci_set_drvdata(pdev, pinfo); 612 613 g_adp_info = pinfo; 614 615 return 0; 616} 617 618#ifdef CONFIG_PM 619int chd_dec_pci_suspend(struct pci_dev *pdev, pm_message_t state) 620{ 621 struct crystalhd_adp *adp; 622 struct crystalhd_ioctl_data *temp; 623 enum BC_STATUS sts = BC_STS_SUCCESS; 624 625 adp = (struct crystalhd_adp *)pci_get_drvdata(pdev); 626 if (!adp) { 627 BCMLOG_ERR("could not get adp\n"); 628 return -ENODEV; 629 } 630 631 temp = chd_dec_alloc_iodata(adp, false); 632 if (!temp) { 633 BCMLOG_ERR("could not get ioctl data\n"); 634 return -ENODEV; 635 } 636 637 sts = crystalhd_suspend(&adp->cmds, temp); 638 if (sts != BC_STS_SUCCESS) { 639 BCMLOG_ERR("BCM70012 Suspend %d\n", sts); 640 return -ENODEV; 641 } 642 643 chd_dec_free_iodata(adp, temp, false); 644 chd_dec_disable_int(adp); 645 pci_save_state(pdev); 646 647 /* Disable IO/bus master/irq router */ 648 pci_disable_device(pdev); 649 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 650 return 0; 651} 652 653int chd_dec_pci_resume(struct pci_dev *pdev) 654{ 655 struct crystalhd_adp *adp; 656 enum BC_STATUS sts = BC_STS_SUCCESS; 657 int rc; 658 659 adp = (struct crystalhd_adp *)pci_get_drvdata(pdev); 660 if (!adp) { 661 BCMLOG_ERR("could not get adp\n"); 662 return -ENODEV; 663 } 664 665 pci_set_power_state(pdev, PCI_D0); 666 pci_restore_state(pdev); 667 668 /* device's irq possibly is changed, driver should take care */ 669 if (pci_enable_device(pdev)) { 670 BCMLOG_ERR("Failed to enable PCI device\n"); 671 return 1; 672 } 673 674 pci_set_master(pdev); 675 676 rc = chd_dec_enable_int(adp); 677 if (rc) { 678 BCMLOG_ERR("_enable_int err:%d\n", rc); 679 pci_disable_device(pdev); 680 return -ENODEV; 681 } 682 683 sts = crystalhd_resume(&adp->cmds); 684 if (sts != BC_STS_SUCCESS) { 685 BCMLOG_ERR("BCM70012 Resume %d\n", sts); 686 pci_disable_device(pdev); 687 return -ENODEV; 688 } 689 690 return 0; 691} 692#endif 693 694static DEFINE_PCI_DEVICE_TABLE(chd_dec_pci_id_table) = { 695 { PCI_VDEVICE(BROADCOM, 0x1612), 8 }, 696 { 0, }, 697}; 698MODULE_DEVICE_TABLE(pci, chd_dec_pci_id_table); 699 700static struct pci_driver bc_chd_70012_driver = { 701 .name = "Broadcom 70012 Decoder", 702 .probe = chd_dec_pci_probe, 703 .remove = __devexit_p(chd_dec_pci_remove), 704 .id_table = chd_dec_pci_id_table, 705#ifdef CONFIG_PM 706 .suspend = chd_dec_pci_suspend, 707 .resume = chd_dec_pci_resume 708#endif 709}; 710 711void chd_set_log_level(struct crystalhd_adp *adp, char *arg) 712{ 713 if ((!arg) || (strlen(arg) < 3)) 714 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA; 715 else if (!strncmp(arg, "sstep", 5)) 716 g_linklog_level = BCMLOG_INFO | BCMLOG_DATA | BCMLOG_DBG | 717 BCMLOG_SSTEP | BCMLOG_ERROR; 718 else if (!strncmp(arg, "info", 4)) 719 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO; 720 else if (!strncmp(arg, "debug", 5)) 721 g_linklog_level = BCMLOG_ERROR | BCMLOG_DATA | BCMLOG_INFO | 722 BCMLOG_DBG; 723 else if (!strncmp(arg, "pball", 5)) 724 g_linklog_level = 0xFFFFFFFF & ~(BCMLOG_SPINLOCK); 725 else if (!strncmp(arg, "silent", 6)) 726 g_linklog_level = 0; 727 else 728 g_linklog_level = 0; 729} 730 731struct crystalhd_adp *chd_get_adp(void) 732{ 733 return g_adp_info; 734} 735 736static int __init chd_dec_module_init(void) 737{ 738 int rc; 739 740 chd_set_log_level(NULL, "debug"); 741 BCMLOG(BCMLOG_DATA, "Loading crystalhd %d.%d.%d\n", 742 crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev); 743 744 rc = pci_register_driver(&bc_chd_70012_driver); 745 746 if (rc < 0) 747 BCMLOG_ERR("Could not find any devices. err:%d\n", rc); 748 749 return rc; 750} 751module_init(chd_dec_module_init); 752 753static void __exit chd_dec_module_cleanup(void) 754{ 755 BCMLOG(BCMLOG_DATA, "unloading crystalhd %d.%d.%d\n", 756 crystalhd_kmod_major, crystalhd_kmod_minor, crystalhd_kmod_rev); 757 758 pci_unregister_driver(&bc_chd_70012_driver); 759} 760module_exit(chd_dec_module_cleanup); 761 762MODULE_AUTHOR("Naren Sankar <nsankar@broadcom.com>"); 763MODULE_AUTHOR("Prasad Bolisetty <prasadb@broadcom.com>"); 764MODULE_DESCRIPTION(CRYSTAL_HD_NAME); 765MODULE_LICENSE("GPL"); 766MODULE_ALIAS("bcm70012"); 767