rx.c (17523B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Adaptec AAC series RAID controller driver 4 * (c) Copyright 2001 Red Hat Inc. 5 * 6 * based on the old aacraid driver that is.. 7 * Adaptec aacraid device driver for Linux. 8 * 9 * Copyright (c) 2000-2010 Adaptec, Inc. 10 * 2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com) 11 * 2016-2017 Microsemi Corp. (aacraid@microsemi.com) 12 * 13 * Module Name: 14 * rx.c 15 * 16 * Abstract: Hardware miniport for Drawbridge specific hardware functions. 17 */ 18 19#include <linux/kernel.h> 20#include <linux/init.h> 21#include <linux/types.h> 22#include <linux/pci.h> 23#include <linux/spinlock.h> 24#include <linux/blkdev.h> 25#include <linux/delay.h> 26#include <linux/completion.h> 27#include <linux/time.h> 28#include <linux/interrupt.h> 29 30#include <scsi/scsi_host.h> 31 32#include "aacraid.h" 33 34static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) 35{ 36 struct aac_dev *dev = dev_id; 37 unsigned long bellbits; 38 u8 intstat = rx_readb(dev, MUnit.OISR); 39 40 /* 41 * Read mask and invert because drawbridge is reversed. 42 * This allows us to only service interrupts that have 43 * been enabled. 44 * Check to see if this is our interrupt. If it isn't just return 45 */ 46 if (likely(intstat & ~(dev->OIMR))) { 47 bellbits = rx_readl(dev, OutboundDoorbellReg); 48 if (unlikely(bellbits & DoorBellPrintfReady)) { 49 aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); 50 rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); 51 rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); 52 } 53 else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) { 54 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); 55 aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); 56 } 57 else if (likely(bellbits & DoorBellAdapterNormRespReady)) { 58 rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); 59 aac_response_normal(&dev->queues->queue[HostNormRespQueue]); 60 } 61 else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) { 62 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); 63 } 64 else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) { 65 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); 66 rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); 67 } 68 return IRQ_HANDLED; 69 } 70 return IRQ_NONE; 71} 72 73static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) 74{ 75 int isAif, isFastResponse, isSpecial; 76 struct aac_dev *dev = dev_id; 77 u32 Index = rx_readl(dev, MUnit.OutboundQueue); 78 if (unlikely(Index == 0xFFFFFFFFL)) 79 Index = rx_readl(dev, MUnit.OutboundQueue); 80 if (likely(Index != 0xFFFFFFFFL)) { 81 do { 82 isAif = isFastResponse = isSpecial = 0; 83 if (Index & 0x00000002L) { 84 isAif = 1; 85 if (Index == 0xFFFFFFFEL) 86 isSpecial = 1; 87 Index &= ~0x00000002L; 88 } else { 89 if (Index & 0x00000001L) 90 isFastResponse = 1; 91 Index >>= 2; 92 } 93 if (!isSpecial) { 94 if (unlikely(aac_intr_normal(dev, 95 Index, isAif, 96 isFastResponse, NULL))) { 97 rx_writel(dev, 98 MUnit.OutboundQueue, 99 Index); 100 rx_writel(dev, 101 MUnit.ODR, 102 DoorBellAdapterNormRespReady); 103 } 104 } 105 Index = rx_readl(dev, MUnit.OutboundQueue); 106 } while (Index != 0xFFFFFFFFL); 107 return IRQ_HANDLED; 108 } 109 return IRQ_NONE; 110} 111 112/** 113 * aac_rx_disable_interrupt - Disable interrupts 114 * @dev: Adapter 115 */ 116 117static void aac_rx_disable_interrupt(struct aac_dev *dev) 118{ 119 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); 120} 121 122/** 123 * aac_rx_enable_interrupt_producer - Enable interrupts 124 * @dev: Adapter 125 */ 126 127static void aac_rx_enable_interrupt_producer(struct aac_dev *dev) 128{ 129 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb); 130} 131 132/** 133 * aac_rx_enable_interrupt_message - Enable interrupts 134 * @dev: Adapter 135 */ 136 137static void aac_rx_enable_interrupt_message(struct aac_dev *dev) 138{ 139 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7); 140} 141 142/** 143 * rx_sync_cmd - send a command and wait 144 * @dev: Adapter 145 * @command: Command to execute 146 * @p1: first parameter 147 * @p2: second parameter 148 * @p3: third parameter 149 * @p4: forth parameter 150 * @p5: fifth parameter 151 * @p6: sixth parameter 152 * @status: adapter status 153 * @r1: first return value 154 * @r2: second return value 155 * @r3: third return value 156 * @r4: forth return value 157 * 158 * This routine will send a synchronous command to the adapter and wait 159 * for its completion. 160 */ 161 162static int rx_sync_cmd(struct aac_dev *dev, u32 command, 163 u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, 164 u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4) 165{ 166 unsigned long start; 167 int ok; 168 /* 169 * Write the command into Mailbox 0 170 */ 171 writel(command, &dev->IndexRegs->Mailbox[0]); 172 /* 173 * Write the parameters into Mailboxes 1 - 6 174 */ 175 writel(p1, &dev->IndexRegs->Mailbox[1]); 176 writel(p2, &dev->IndexRegs->Mailbox[2]); 177 writel(p3, &dev->IndexRegs->Mailbox[3]); 178 writel(p4, &dev->IndexRegs->Mailbox[4]); 179 /* 180 * Clear the synch command doorbell to start on a clean slate. 181 */ 182 rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); 183 /* 184 * Disable doorbell interrupts 185 */ 186 rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); 187 /* 188 * Force the completion of the mask register write before issuing 189 * the interrupt. 190 */ 191 rx_readb (dev, MUnit.OIMR); 192 /* 193 * Signal that there is a new synch command 194 */ 195 rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0); 196 197 ok = 0; 198 start = jiffies; 199 200 /* 201 * Wait up to 30 seconds 202 */ 203 while (time_before(jiffies, start+30*HZ)) 204 { 205 udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ 206 /* 207 * Mon960 will set doorbell0 bit when it has completed the command. 208 */ 209 if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) { 210 /* 211 * Clear the doorbell. 212 */ 213 rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); 214 ok = 1; 215 break; 216 } 217 /* 218 * Yield the processor in case we are slow 219 */ 220 msleep(1); 221 } 222 if (unlikely(ok != 1)) { 223 /* 224 * Restore interrupt mask even though we timed out 225 */ 226 aac_adapter_enable_int(dev); 227 return -ETIMEDOUT; 228 } 229 /* 230 * Pull the synch status from Mailbox 0. 231 */ 232 if (status) 233 *status = readl(&dev->IndexRegs->Mailbox[0]); 234 if (r1) 235 *r1 = readl(&dev->IndexRegs->Mailbox[1]); 236 if (r2) 237 *r2 = readl(&dev->IndexRegs->Mailbox[2]); 238 if (r3) 239 *r3 = readl(&dev->IndexRegs->Mailbox[3]); 240 if (r4) 241 *r4 = readl(&dev->IndexRegs->Mailbox[4]); 242 /* 243 * Clear the synch command doorbell. 244 */ 245 rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0); 246 /* 247 * Restore interrupt mask 248 */ 249 aac_adapter_enable_int(dev); 250 return 0; 251 252} 253 254/** 255 * aac_rx_interrupt_adapter - interrupt adapter 256 * @dev: Adapter 257 * 258 * Send an interrupt to the i960 and breakpoint it. 259 */ 260 261static void aac_rx_interrupt_adapter(struct aac_dev *dev) 262{ 263 rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 264} 265 266/** 267 * aac_rx_notify_adapter - send an event to the adapter 268 * @dev: Adapter 269 * @event: Event to send 270 * 271 * Notify the i960 that something it probably cares about has 272 * happened. 273 */ 274 275static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) 276{ 277 switch (event) { 278 279 case AdapNormCmdQue: 280 rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1); 281 break; 282 case HostNormRespNotFull: 283 rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4); 284 break; 285 case AdapNormRespQue: 286 rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2); 287 break; 288 case HostNormCmdNotFull: 289 rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3); 290 break; 291 case HostShutdown: 292 break; 293 case FastIo: 294 rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6); 295 break; 296 case AdapPrintfDone: 297 rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5); 298 break; 299 default: 300 BUG(); 301 break; 302 } 303} 304 305/** 306 * aac_rx_start_adapter - activate adapter 307 * @dev: Adapter 308 * 309 * Start up processing on an i960 based AAC adapter 310 */ 311 312static void aac_rx_start_adapter(struct aac_dev *dev) 313{ 314 union aac_init *init; 315 316 init = dev->init; 317 init->r7.host_elapsed_seconds = cpu_to_le32(ktime_get_real_seconds()); 318 // We can only use a 32 bit address here 319 rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, 320 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 321} 322 323/** 324 * aac_rx_check_health 325 * @dev: device to check if healthy 326 * 327 * Will attempt to determine if the specified adapter is alive and 328 * capable of handling requests, returning 0 if alive. 329 */ 330static int aac_rx_check_health(struct aac_dev *dev) 331{ 332 u32 status = rx_readl(dev, MUnit.OMRx[0]); 333 334 /* 335 * Check to see if the board failed any self tests. 336 */ 337 if (unlikely(status & SELF_TEST_FAILED)) 338 return -1; 339 /* 340 * Check to see if the board panic'd. 341 */ 342 if (unlikely(status & KERNEL_PANIC)) { 343 char * buffer; 344 struct POSTSTATUS { 345 __le32 Post_Command; 346 __le32 Post_Address; 347 } * post; 348 dma_addr_t paddr, baddr; 349 int ret; 350 351 if (likely((status & 0xFF000000L) == 0xBC000000L)) 352 return (status >> 16) & 0xFF; 353 buffer = dma_alloc_coherent(&dev->pdev->dev, 512, &baddr, 354 GFP_KERNEL); 355 ret = -2; 356 if (unlikely(buffer == NULL)) 357 return ret; 358 post = dma_alloc_coherent(&dev->pdev->dev, 359 sizeof(struct POSTSTATUS), &paddr, 360 GFP_KERNEL); 361 if (unlikely(post == NULL)) { 362 dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr); 363 return ret; 364 } 365 memset(buffer, 0, 512); 366 post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS); 367 post->Post_Address = cpu_to_le32(baddr); 368 rx_writel(dev, MUnit.IMRx[0], paddr); 369 rx_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0, 370 NULL, NULL, NULL, NULL, NULL); 371 dma_free_coherent(&dev->pdev->dev, sizeof(struct POSTSTATUS), 372 post, paddr); 373 if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { 374 ret = (hex_to_bin(buffer[2]) << 4) + 375 hex_to_bin(buffer[3]); 376 } 377 dma_free_coherent(&dev->pdev->dev, 512, buffer, baddr); 378 return ret; 379 } 380 /* 381 * Wait for the adapter to be up and running. 382 */ 383 if (unlikely(!(status & KERNEL_UP_AND_RUNNING))) 384 return -3; 385 /* 386 * Everything is OK 387 */ 388 return 0; 389} 390 391/** 392 * aac_rx_deliver_producer 393 * @fib: fib to issue 394 * 395 * Will send a fib, returning 0 if successful. 396 */ 397int aac_rx_deliver_producer(struct fib * fib) 398{ 399 struct aac_dev *dev = fib->dev; 400 struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; 401 u32 Index; 402 unsigned long nointr = 0; 403 404 aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); 405 406 atomic_inc(&q->numpending); 407 *(q->headers.producer) = cpu_to_le32(Index + 1); 408 if (!(nointr & aac_config.irq_mod)) 409 aac_adapter_notify(dev, AdapNormCmdQueue); 410 411 return 0; 412} 413 414/** 415 * aac_rx_deliver_message 416 * @fib: fib to issue 417 * 418 * Will send a fib, returning 0 if successful. 419 */ 420static int aac_rx_deliver_message(struct fib * fib) 421{ 422 struct aac_dev *dev = fib->dev; 423 struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; 424 u32 Index; 425 u64 addr; 426 volatile void __iomem *device; 427 428 unsigned long count = 10000000L; /* 50 seconds */ 429 atomic_inc(&q->numpending); 430 for(;;) { 431 Index = rx_readl(dev, MUnit.InboundQueue); 432 if (unlikely(Index == 0xFFFFFFFFL)) 433 Index = rx_readl(dev, MUnit.InboundQueue); 434 if (likely(Index != 0xFFFFFFFFL)) 435 break; 436 if (--count == 0) { 437 atomic_dec(&q->numpending); 438 return -ETIMEDOUT; 439 } 440 udelay(5); 441 } 442 device = dev->base + Index; 443 addr = fib->hw_fib_pa; 444 writel((u32)(addr & 0xffffffff), device); 445 device += sizeof(u32); 446 writel((u32)(addr >> 32), device); 447 device += sizeof(u32); 448 writel(le16_to_cpu(fib->hw_fib_va->header.Size), device); 449 rx_writel(dev, MUnit.InboundQueue, Index); 450 return 0; 451} 452 453/** 454 * aac_rx_ioremap 455 * @dev: adapter 456 * @size: mapping resize request 457 * 458 */ 459static int aac_rx_ioremap(struct aac_dev * dev, u32 size) 460{ 461 if (!size) { 462 iounmap(dev->regs.rx); 463 return 0; 464 } 465 dev->base = dev->regs.rx = ioremap(dev->base_start, size); 466 if (dev->base == NULL) 467 return -1; 468 dev->IndexRegs = &dev->regs.rx->IndexRegs; 469 return 0; 470} 471 472static int aac_rx_restart_adapter(struct aac_dev *dev, int bled, u8 reset_type) 473{ 474 u32 var = 0; 475 476 if (!(dev->supplement_adapter_info.supported_options2 & 477 AAC_OPTION_MU_RESET) || (bled >= 0) || (bled == -2)) { 478 if (bled) 479 printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", 480 dev->name, dev->id, bled); 481 else { 482 bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, 483 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); 484 if (!bled && (var != 0x00000001) && (var != 0x3803000F)) 485 bled = -EINVAL; 486 } 487 if (bled && (bled != -ETIMEDOUT)) 488 bled = aac_adapter_sync_cmd(dev, IOP_RESET, 489 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); 490 491 if (bled && (bled != -ETIMEDOUT)) 492 return -EINVAL; 493 } 494 if (bled && (var == 0x3803000F)) { /* USE_OTHER_METHOD */ 495 rx_writel(dev, MUnit.reserved2, 3); 496 msleep(5000); /* Delay 5 seconds */ 497 var = 0x00000001; 498 } 499 if (bled && (var != 0x00000001)) 500 return -EINVAL; 501 ssleep(5); 502 if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) 503 return -ENODEV; 504 if (startup_timeout < 300) 505 startup_timeout = 300; 506 return 0; 507} 508 509/** 510 * aac_rx_select_comm - Select communications method 511 * @dev: Adapter 512 * @comm: communications method 513 */ 514 515int aac_rx_select_comm(struct aac_dev *dev, int comm) 516{ 517 switch (comm) { 518 case AAC_COMM_PRODUCER: 519 dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_producer; 520 dev->a_ops.adapter_intr = aac_rx_intr_producer; 521 dev->a_ops.adapter_deliver = aac_rx_deliver_producer; 522 break; 523 case AAC_COMM_MESSAGE: 524 dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt_message; 525 dev->a_ops.adapter_intr = aac_rx_intr_message; 526 dev->a_ops.adapter_deliver = aac_rx_deliver_message; 527 break; 528 default: 529 return 1; 530 } 531 return 0; 532} 533 534/** 535 * _aac_rx_init - initialize an i960 based AAC card 536 * @dev: device to configure 537 * 538 * Allocate and set up resources for the i960 based AAC variants. The 539 * device_interface in the commregion will be allocated and linked 540 * to the comm region. 541 */ 542 543int _aac_rx_init(struct aac_dev *dev) 544{ 545 unsigned long start; 546 unsigned long status; 547 int restart = 0; 548 int instance = dev->id; 549 const char * name = dev->name; 550 551 if (aac_adapter_ioremap(dev, dev->base_size)) { 552 printk(KERN_WARNING "%s: unable to map adapter.\n", name); 553 goto error_iounmap; 554 } 555 556 /* Failure to reset here is an option ... */ 557 dev->a_ops.adapter_sync_cmd = rx_sync_cmd; 558 dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt; 559 dev->OIMR = status = rx_readb (dev, MUnit.OIMR); 560 561 if (((status & 0x0c) != 0x0c) || dev->init_reset) { 562 dev->init_reset = false; 563 if (!aac_rx_restart_adapter(dev, 0, IOP_HWSOFT_RESET)) { 564 /* Make sure the Hardware FIFO is empty */ 565 while ((++restart < 512) && 566 (rx_readl(dev, MUnit.OutboundQueue) != 0xFFFFFFFFL)); 567 } 568 } 569 570 /* 571 * Check to see if the board panic'd while booting. 572 */ 573 status = rx_readl(dev, MUnit.OMRx[0]); 574 if (status & KERNEL_PANIC) { 575 if (aac_rx_restart_adapter(dev, 576 aac_rx_check_health(dev), IOP_HWSOFT_RESET)) 577 goto error_iounmap; 578 ++restart; 579 } 580 /* 581 * Check to see if the board failed any self tests. 582 */ 583 status = rx_readl(dev, MUnit.OMRx[0]); 584 if (status & SELF_TEST_FAILED) { 585 printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance); 586 goto error_iounmap; 587 } 588 /* 589 * Check to see if the monitor panic'd while booting. 590 */ 591 if (status & MONITOR_PANIC) { 592 printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); 593 goto error_iounmap; 594 } 595 start = jiffies; 596 /* 597 * Wait for the adapter to be up and running. Wait up to 3 minutes 598 */ 599 while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) 600 { 601 if ((restart && 602 (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || 603 time_after(jiffies, start+HZ*startup_timeout)) { 604 printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", 605 dev->name, instance, status); 606 goto error_iounmap; 607 } 608 if (!restart && 609 ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || 610 time_after(jiffies, start + HZ * 611 ((startup_timeout > 60) 612 ? (startup_timeout - 60) 613 : (startup_timeout / 2))))) { 614 if (likely(!aac_rx_restart_adapter(dev, 615 aac_rx_check_health(dev), IOP_HWSOFT_RESET))) 616 start = jiffies; 617 ++restart; 618 } 619 msleep(1); 620 } 621 if (restart && aac_commit) 622 aac_commit = 1; 623 /* 624 * Fill in the common function dispatch table. 625 */ 626 dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter; 627 dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt; 628 dev->a_ops.adapter_notify = aac_rx_notify_adapter; 629 dev->a_ops.adapter_sync_cmd = rx_sync_cmd; 630 dev->a_ops.adapter_check_health = aac_rx_check_health; 631 dev->a_ops.adapter_restart = aac_rx_restart_adapter; 632 dev->a_ops.adapter_start = aac_rx_start_adapter; 633 634 /* 635 * First clear out all interrupts. Then enable the one's that we 636 * can handle. 637 */ 638 aac_adapter_comm(dev, AAC_COMM_PRODUCER); 639 aac_adapter_disable_int(dev); 640 rx_writel(dev, MUnit.ODR, 0xffffffff); 641 aac_adapter_enable_int(dev); 642 643 if (aac_init_adapter(dev) == NULL) 644 goto error_iounmap; 645 aac_adapter_comm(dev, dev->comm_interface); 646 dev->sync_mode = 0; /* sync. mode not supported */ 647 dev->msi = aac_msi && !pci_enable_msi(dev->pdev); 648 if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, 649 IRQF_SHARED, "aacraid", dev) < 0) { 650 if (dev->msi) 651 pci_disable_msi(dev->pdev); 652 printk(KERN_ERR "%s%d: Interrupt unavailable.\n", 653 name, instance); 654 goto error_iounmap; 655 } 656 dev->dbg_base = dev->base_start; 657 dev->dbg_base_mapped = dev->base; 658 dev->dbg_size = dev->base_size; 659 660 aac_adapter_enable_int(dev); 661 /* 662 * Tell the adapter that all is configured, and it can 663 * start accepting requests 664 */ 665 aac_rx_start_adapter(dev); 666 667 return 0; 668 669error_iounmap: 670 671 return -1; 672} 673 674int aac_rx_init(struct aac_dev *dev) 675{ 676 /* 677 * Fill in the function dispatch table. 678 */ 679 dev->a_ops.adapter_ioremap = aac_rx_ioremap; 680 dev->a_ops.adapter_comm = aac_rx_select_comm; 681 682 return _aac_rx_init(dev); 683}