diff options
Diffstat (limited to 'drivers/scsi/aacraid/rx.c')
-rw-r--r-- | drivers/scsi/aacraid/rx.c | 115 |
1 files changed, 72 insertions, 43 deletions
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index d242e2611d67..0c71315cbf1a 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * based on the old aacraid driver that is.. | 5 | * based on the old aacraid driver that is.. |
6 | * Adaptec aacraid device driver for Linux. | 6 | * Adaptec aacraid device driver for Linux. |
7 | * | 7 | * |
8 | * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -57,25 +57,25 @@ static irqreturn_t aac_rx_intr_producer(int irq, void *dev_id) | |||
57 | * been enabled. | 57 | * been enabled. |
58 | * Check to see if this is our interrupt. If it isn't just return | 58 | * Check to see if this is our interrupt. If it isn't just return |
59 | */ | 59 | */ |
60 | if (intstat & ~(dev->OIMR)) { | 60 | if (likely(intstat & ~(dev->OIMR))) { |
61 | bellbits = rx_readl(dev, OutboundDoorbellReg); | 61 | bellbits = rx_readl(dev, OutboundDoorbellReg); |
62 | if (bellbits & DoorBellPrintfReady) { | 62 | if (unlikely(bellbits & DoorBellPrintfReady)) { |
63 | aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); | 63 | aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5])); |
64 | rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); | 64 | rx_writel(dev, MUnit.ODR,DoorBellPrintfReady); |
65 | rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); | 65 | rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone); |
66 | } | 66 | } |
67 | else if (bellbits & DoorBellAdapterNormCmdReady) { | 67 | else if (unlikely(bellbits & DoorBellAdapterNormCmdReady)) { |
68 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); | 68 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady); |
69 | aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); | 69 | aac_command_normal(&dev->queues->queue[HostNormCmdQueue]); |
70 | } | 70 | } |
71 | else if (bellbits & DoorBellAdapterNormRespReady) { | 71 | else if (likely(bellbits & DoorBellAdapterNormRespReady)) { |
72 | rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); | 72 | rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady); |
73 | aac_response_normal(&dev->queues->queue[HostNormRespQueue]); | 73 | aac_response_normal(&dev->queues->queue[HostNormRespQueue]); |
74 | } | 74 | } |
75 | else if (bellbits & DoorBellAdapterNormCmdNotFull) { | 75 | else if (unlikely(bellbits & DoorBellAdapterNormCmdNotFull)) { |
76 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); | 76 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); |
77 | } | 77 | } |
78 | else if (bellbits & DoorBellAdapterNormRespNotFull) { | 78 | else if (unlikely(bellbits & DoorBellAdapterNormRespNotFull)) { |
79 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); | 79 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); |
80 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); | 80 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); |
81 | } | 81 | } |
@@ -88,11 +88,11 @@ static irqreturn_t aac_rx_intr_message(int irq, void *dev_id) | |||
88 | { | 88 | { |
89 | struct aac_dev *dev = dev_id; | 89 | struct aac_dev *dev = dev_id; |
90 | u32 Index = rx_readl(dev, MUnit.OutboundQueue); | 90 | u32 Index = rx_readl(dev, MUnit.OutboundQueue); |
91 | if (Index == 0xFFFFFFFFL) | 91 | if (unlikely(Index == 0xFFFFFFFFL)) |
92 | Index = rx_readl(dev, MUnit.OutboundQueue); | 92 | Index = rx_readl(dev, MUnit.OutboundQueue); |
93 | if (Index != 0xFFFFFFFFL) { | 93 | if (likely(Index != 0xFFFFFFFFL)) { |
94 | do { | 94 | do { |
95 | if (aac_intr_normal(dev, Index)) { | 95 | if (unlikely(aac_intr_normal(dev, Index))) { |
96 | rx_writel(dev, MUnit.OutboundQueue, Index); | 96 | rx_writel(dev, MUnit.OutboundQueue, Index); |
97 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); | 97 | rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady); |
98 | } | 98 | } |
@@ -204,7 +204,7 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, | |||
204 | */ | 204 | */ |
205 | msleep(1); | 205 | msleep(1); |
206 | } | 206 | } |
207 | if (ok != 1) { | 207 | if (unlikely(ok != 1)) { |
208 | /* | 208 | /* |
209 | * Restore interrupt mask even though we timed out | 209 | * Restore interrupt mask even though we timed out |
210 | */ | 210 | */ |
@@ -294,7 +294,7 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event) | |||
294 | * Start up processing on an i960 based AAC adapter | 294 | * Start up processing on an i960 based AAC adapter |
295 | */ | 295 | */ |
296 | 296 | ||
297 | void aac_rx_start_adapter(struct aac_dev *dev) | 297 | static void aac_rx_start_adapter(struct aac_dev *dev) |
298 | { | 298 | { |
299 | struct aac_init *init; | 299 | struct aac_init *init; |
300 | 300 | ||
@@ -319,12 +319,12 @@ static int aac_rx_check_health(struct aac_dev *dev) | |||
319 | /* | 319 | /* |
320 | * Check to see if the board failed any self tests. | 320 | * Check to see if the board failed any self tests. |
321 | */ | 321 | */ |
322 | if (status & SELF_TEST_FAILED) | 322 | if (unlikely(status & SELF_TEST_FAILED)) |
323 | return -1; | 323 | return -1; |
324 | /* | 324 | /* |
325 | * Check to see if the board panic'd. | 325 | * Check to see if the board panic'd. |
326 | */ | 326 | */ |
327 | if (status & KERNEL_PANIC) { | 327 | if (unlikely(status & KERNEL_PANIC)) { |
328 | char * buffer; | 328 | char * buffer; |
329 | struct POSTSTATUS { | 329 | struct POSTSTATUS { |
330 | __le32 Post_Command; | 330 | __le32 Post_Command; |
@@ -333,15 +333,15 @@ static int aac_rx_check_health(struct aac_dev *dev) | |||
333 | dma_addr_t paddr, baddr; | 333 | dma_addr_t paddr, baddr; |
334 | int ret; | 334 | int ret; |
335 | 335 | ||
336 | if ((status & 0xFF000000L) == 0xBC000000L) | 336 | if (likely((status & 0xFF000000L) == 0xBC000000L)) |
337 | return (status >> 16) & 0xFF; | 337 | return (status >> 16) & 0xFF; |
338 | buffer = pci_alloc_consistent(dev->pdev, 512, &baddr); | 338 | buffer = pci_alloc_consistent(dev->pdev, 512, &baddr); |
339 | ret = -2; | 339 | ret = -2; |
340 | if (buffer == NULL) | 340 | if (unlikely(buffer == NULL)) |
341 | return ret; | 341 | return ret; |
342 | post = pci_alloc_consistent(dev->pdev, | 342 | post = pci_alloc_consistent(dev->pdev, |
343 | sizeof(struct POSTSTATUS), &paddr); | 343 | sizeof(struct POSTSTATUS), &paddr); |
344 | if (post == NULL) { | 344 | if (unlikely(post == NULL)) { |
345 | pci_free_consistent(dev->pdev, 512, buffer, baddr); | 345 | pci_free_consistent(dev->pdev, 512, buffer, baddr); |
346 | return ret; | 346 | return ret; |
347 | } | 347 | } |
@@ -353,7 +353,7 @@ static int aac_rx_check_health(struct aac_dev *dev) | |||
353 | NULL, NULL, NULL, NULL, NULL); | 353 | NULL, NULL, NULL, NULL, NULL); |
354 | pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), | 354 | pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS), |
355 | post, paddr); | 355 | post, paddr); |
356 | if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) { | 356 | if (likely((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X')))) { |
357 | ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); | 357 | ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10); |
358 | ret <<= 4; | 358 | ret <<= 4; |
359 | ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); | 359 | ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10); |
@@ -364,7 +364,7 @@ static int aac_rx_check_health(struct aac_dev *dev) | |||
364 | /* | 364 | /* |
365 | * Wait for the adapter to be up and running. | 365 | * Wait for the adapter to be up and running. |
366 | */ | 366 | */ |
367 | if (!(status & KERNEL_UP_AND_RUNNING)) | 367 | if (unlikely(!(status & KERNEL_UP_AND_RUNNING))) |
368 | return -3; | 368 | return -3; |
369 | /* | 369 | /* |
370 | * Everything is OK | 370 | * Everything is OK |
@@ -387,7 +387,7 @@ static int aac_rx_deliver_producer(struct fib * fib) | |||
387 | unsigned long nointr = 0; | 387 | unsigned long nointr = 0; |
388 | 388 | ||
389 | spin_lock_irqsave(q->lock, qflags); | 389 | spin_lock_irqsave(q->lock, qflags); |
390 | aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib, 1, fib, &nointr); | 390 | aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); |
391 | 391 | ||
392 | q->numpending++; | 392 | q->numpending++; |
393 | *(q->headers.producer) = cpu_to_le32(Index + 1); | 393 | *(q->headers.producer) = cpu_to_le32(Index + 1); |
@@ -419,9 +419,9 @@ static int aac_rx_deliver_message(struct fib * fib) | |||
419 | spin_unlock_irqrestore(q->lock, qflags); | 419 | spin_unlock_irqrestore(q->lock, qflags); |
420 | for(;;) { | 420 | for(;;) { |
421 | Index = rx_readl(dev, MUnit.InboundQueue); | 421 | Index = rx_readl(dev, MUnit.InboundQueue); |
422 | if (Index == 0xFFFFFFFFL) | 422 | if (unlikely(Index == 0xFFFFFFFFL)) |
423 | Index = rx_readl(dev, MUnit.InboundQueue); | 423 | Index = rx_readl(dev, MUnit.InboundQueue); |
424 | if (Index != 0xFFFFFFFFL) | 424 | if (likely(Index != 0xFFFFFFFFL)) |
425 | break; | 425 | break; |
426 | if (--count == 0) { | 426 | if (--count == 0) { |
427 | spin_lock_irqsave(q->lock, qflags); | 427 | spin_lock_irqsave(q->lock, qflags); |
@@ -437,7 +437,7 @@ static int aac_rx_deliver_message(struct fib * fib) | |||
437 | device += sizeof(u32); | 437 | device += sizeof(u32); |
438 | writel((u32)(addr >> 32), device); | 438 | writel((u32)(addr >> 32), device); |
439 | device += sizeof(u32); | 439 | device += sizeof(u32); |
440 | writel(le16_to_cpu(fib->hw_fib->header.Size), device); | 440 | writel(le16_to_cpu(fib->hw_fib_va->header.Size), device); |
441 | rx_writel(dev, MUnit.InboundQueue, Index); | 441 | rx_writel(dev, MUnit.InboundQueue, Index); |
442 | return 0; | 442 | return 0; |
443 | } | 443 | } |
@@ -460,22 +460,34 @@ static int aac_rx_ioremap(struct aac_dev * dev, u32 size) | |||
460 | return 0; | 460 | return 0; |
461 | } | 461 | } |
462 | 462 | ||
463 | static int aac_rx_restart_adapter(struct aac_dev *dev) | 463 | static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) |
464 | { | 464 | { |
465 | u32 var; | 465 | u32 var; |
466 | 466 | ||
467 | printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", | 467 | if (bled) |
468 | dev->name, dev->id); | 468 | printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", |
469 | 469 | dev->name, dev->id, bled); | |
470 | if (aac_rx_check_health(dev) <= 0) | 470 | else { |
471 | return 1; | 471 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, |
472 | if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, | 472 | 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); |
473 | &var, NULL, NULL, NULL, NULL)) | 473 | if (!bled && (var != 0x00000001)) |
474 | return 1; | 474 | bled = -EINVAL; |
475 | } | ||
476 | if (bled && (bled != -ETIMEDOUT)) | ||
477 | bled = aac_adapter_sync_cmd(dev, IOP_RESET, | ||
478 | 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); | ||
479 | |||
480 | if (bled && (bled != -ETIMEDOUT)) | ||
481 | return -EINVAL; | ||
482 | if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */ | ||
483 | rx_writel(dev, MUnit.reserved2, 3); | ||
484 | msleep(5000); /* Delay 5 seconds */ | ||
485 | var = 0x00000001; | ||
486 | } | ||
475 | if (var != 0x00000001) | 487 | if (var != 0x00000001) |
476 | return 1; | 488 | return -EINVAL; |
477 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | 489 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) |
478 | return 1; | 490 | return -ENODEV; |
479 | return 0; | 491 | return 0; |
480 | } | 492 | } |
481 | 493 | ||
@@ -517,24 +529,29 @@ int _aac_rx_init(struct aac_dev *dev) | |||
517 | { | 529 | { |
518 | unsigned long start; | 530 | unsigned long start; |
519 | unsigned long status; | 531 | unsigned long status; |
520 | int instance; | 532 | int restart = 0; |
521 | const char * name; | 533 | int instance = dev->id; |
522 | 534 | const char * name = dev->name; | |
523 | instance = dev->id; | ||
524 | name = dev->name; | ||
525 | 535 | ||
526 | if (aac_adapter_ioremap(dev, dev->base_size)) { | 536 | if (aac_adapter_ioremap(dev, dev->base_size)) { |
527 | printk(KERN_WARNING "%s: unable to map adapter.\n", name); | 537 | printk(KERN_WARNING "%s: unable to map adapter.\n", name); |
528 | goto error_iounmap; | 538 | goto error_iounmap; |
529 | } | 539 | } |
530 | 540 | ||
541 | /* Failure to reset here is an option ... */ | ||
542 | dev->OIMR = status = rx_readb (dev, MUnit.OIMR); | ||
543 | if ((((status & 0xff) != 0xff) || reset_devices) && | ||
544 | !aac_rx_restart_adapter(dev, 0)) | ||
545 | ++restart; | ||
531 | /* | 546 | /* |
532 | * Check to see if the board panic'd while booting. | 547 | * Check to see if the board panic'd while booting. |
533 | */ | 548 | */ |
534 | status = rx_readl(dev, MUnit.OMRx[0]); | 549 | status = rx_readl(dev, MUnit.OMRx[0]); |
535 | if (status & KERNEL_PANIC) | 550 | if (status & KERNEL_PANIC) { |
536 | if (aac_rx_restart_adapter(dev)) | 551 | if (aac_rx_restart_adapter(dev, aac_rx_check_health(dev))) |
537 | goto error_iounmap; | 552 | goto error_iounmap; |
553 | ++restart; | ||
554 | } | ||
538 | /* | 555 | /* |
539 | * Check to see if the board failed any self tests. | 556 | * Check to see if the board failed any self tests. |
540 | */ | 557 | */ |
@@ -556,12 +573,23 @@ int _aac_rx_init(struct aac_dev *dev) | |||
556 | */ | 573 | */ |
557 | while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) | 574 | while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING)) |
558 | { | 575 | { |
559 | if(time_after(jiffies, start+startup_timeout*HZ)) | 576 | if ((restart && |
560 | { | 577 | (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) || |
578 | time_after(jiffies, start+HZ*startup_timeout)) { | ||
561 | printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", | 579 | printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n", |
562 | dev->name, instance, status); | 580 | dev->name, instance, status); |
563 | goto error_iounmap; | 581 | goto error_iounmap; |
564 | } | 582 | } |
583 | if (!restart && | ||
584 | ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) || | ||
585 | time_after(jiffies, start + HZ * | ||
586 | ((startup_timeout > 60) | ||
587 | ? (startup_timeout - 60) | ||
588 | : (startup_timeout / 2))))) { | ||
589 | if (likely(!aac_rx_restart_adapter(dev, aac_rx_check_health(dev)))) | ||
590 | start = jiffies; | ||
591 | ++restart; | ||
592 | } | ||
565 | msleep(1); | 593 | msleep(1); |
566 | } | 594 | } |
567 | /* | 595 | /* |
@@ -572,6 +600,7 @@ int _aac_rx_init(struct aac_dev *dev) | |||
572 | dev->a_ops.adapter_notify = aac_rx_notify_adapter; | 600 | dev->a_ops.adapter_notify = aac_rx_notify_adapter; |
573 | dev->a_ops.adapter_sync_cmd = rx_sync_cmd; | 601 | dev->a_ops.adapter_sync_cmd = rx_sync_cmd; |
574 | dev->a_ops.adapter_check_health = aac_rx_check_health; | 602 | dev->a_ops.adapter_check_health = aac_rx_check_health; |
603 | dev->a_ops.adapter_restart = aac_rx_restart_adapter; | ||
575 | 604 | ||
576 | /* | 605 | /* |
577 | * First clear out all interrupts. Then enable the one's that we | 606 | * First clear out all interrupts. Then enable the one's that we |