diff options
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 54 | ||||
-rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 5 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commctrl.c | 25 | ||||
-rw-r--r-- | drivers/scsi/aacraid/comminit.c | 2 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 273 | ||||
-rw-r--r-- | drivers/scsi/aacraid/dpcsup.c | 10 | ||||
-rw-r--r-- | drivers/scsi/aacraid/linit.c | 18 | ||||
-rw-r--r-- | drivers/scsi/aacraid/rkt.c | 29 | ||||
-rw-r--r-- | drivers/scsi/aacraid/rx.c | 29 |
9 files changed, 397 insertions, 48 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 83b5c7d085f2..37c55ddce214 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -175,7 +175,7 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. | |||
175 | * | 175 | * |
176 | * Query config status, and commit the configuration if needed. | 176 | * Query config status, and commit the configuration if needed. |
177 | */ | 177 | */ |
178 | int aac_get_config_status(struct aac_dev *dev) | 178 | int aac_get_config_status(struct aac_dev *dev, int commit_flag) |
179 | { | 179 | { |
180 | int status = 0; | 180 | int status = 0; |
181 | struct fib * fibptr; | 181 | struct fib * fibptr; |
@@ -219,7 +219,7 @@ int aac_get_config_status(struct aac_dev *dev) | |||
219 | aac_fib_complete(fibptr); | 219 | aac_fib_complete(fibptr); |
220 | /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ | 220 | /* Send a CT_COMMIT_CONFIG to enable discovery of devices */ |
221 | if (status >= 0) { | 221 | if (status >= 0) { |
222 | if (commit == 1) { | 222 | if ((commit == 1) || commit_flag) { |
223 | struct aac_commit_config * dinfo; | 223 | struct aac_commit_config * dinfo; |
224 | aac_fib_init(fibptr); | 224 | aac_fib_init(fibptr); |
225 | dinfo = (struct aac_commit_config *) fib_data(fibptr); | 225 | dinfo = (struct aac_commit_config *) fib_data(fibptr); |
@@ -489,6 +489,8 @@ int aac_probe_container(struct aac_dev *dev, int cid) | |||
489 | unsigned instance; | 489 | unsigned instance; |
490 | 490 | ||
491 | fsa_dev_ptr = dev->fsa_dev; | 491 | fsa_dev_ptr = dev->fsa_dev; |
492 | if (!fsa_dev_ptr) | ||
493 | return -ENOMEM; | ||
492 | instance = dev->scsi_host_ptr->unique_id; | 494 | instance = dev->scsi_host_ptr->unique_id; |
493 | 495 | ||
494 | if (!(fibptr = aac_fib_alloc(dev))) | 496 | if (!(fibptr = aac_fib_alloc(dev))) |
@@ -782,8 +784,9 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
782 | dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount); | 784 | dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount); |
783 | } | 785 | } |
784 | 786 | ||
785 | tmp = le32_to_cpu(dev->adapter_info.kernelrev); | 787 | if (!dev->in_reset) { |
786 | printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", | 788 | tmp = le32_to_cpu(dev->adapter_info.kernelrev); |
789 | printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", | ||
787 | dev->name, | 790 | dev->name, |
788 | dev->id, | 791 | dev->id, |
789 | tmp>>24, | 792 | tmp>>24, |
@@ -792,20 +795,21 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
792 | le32_to_cpu(dev->adapter_info.kernelbuild), | 795 | le32_to_cpu(dev->adapter_info.kernelbuild), |
793 | (int)sizeof(dev->supplement_adapter_info.BuildDate), | 796 | (int)sizeof(dev->supplement_adapter_info.BuildDate), |
794 | dev->supplement_adapter_info.BuildDate); | 797 | dev->supplement_adapter_info.BuildDate); |
795 | tmp = le32_to_cpu(dev->adapter_info.monitorrev); | 798 | tmp = le32_to_cpu(dev->adapter_info.monitorrev); |
796 | printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", | 799 | printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", |
797 | dev->name, dev->id, | 800 | dev->name, dev->id, |
798 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, | 801 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, |
799 | le32_to_cpu(dev->adapter_info.monitorbuild)); | 802 | le32_to_cpu(dev->adapter_info.monitorbuild)); |
800 | tmp = le32_to_cpu(dev->adapter_info.biosrev); | 803 | tmp = le32_to_cpu(dev->adapter_info.biosrev); |
801 | printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n", | 804 | printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n", |
802 | dev->name, dev->id, | 805 | dev->name, dev->id, |
803 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, | 806 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, |
804 | le32_to_cpu(dev->adapter_info.biosbuild)); | 807 | le32_to_cpu(dev->adapter_info.biosbuild)); |
805 | if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) | 808 | if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) |
806 | printk(KERN_INFO "%s%d: serial %x\n", | 809 | printk(KERN_INFO "%s%d: serial %x\n", |
807 | dev->name, dev->id, | 810 | dev->name, dev->id, |
808 | le32_to_cpu(dev->adapter_info.serial[0])); | 811 | le32_to_cpu(dev->adapter_info.serial[0])); |
812 | } | ||
809 | 813 | ||
810 | dev->nondasd_support = 0; | 814 | dev->nondasd_support = 0; |
811 | dev->raid_scsi_mode = 0; | 815 | dev->raid_scsi_mode = 0; |
@@ -1392,6 +1396,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) | |||
1392 | struct scsi_cmnd *cmd; | 1396 | struct scsi_cmnd *cmd; |
1393 | struct scsi_device *sdev = scsicmd->device; | 1397 | struct scsi_device *sdev = scsicmd->device; |
1394 | int active = 0; | 1398 | int active = 0; |
1399 | struct aac_dev *aac; | ||
1395 | unsigned long flags; | 1400 | unsigned long flags; |
1396 | 1401 | ||
1397 | /* | 1402 | /* |
@@ -1413,11 +1418,14 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) | |||
1413 | if (active) | 1418 | if (active) |
1414 | return SCSI_MLQUEUE_DEVICE_BUSY; | 1419 | return SCSI_MLQUEUE_DEVICE_BUSY; |
1415 | 1420 | ||
1421 | aac = (struct aac_dev *)scsicmd->device->host->hostdata; | ||
1422 | if (aac->in_reset) | ||
1423 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1424 | |||
1416 | /* | 1425 | /* |
1417 | * Allocate and initialize a Fib | 1426 | * Allocate and initialize a Fib |
1418 | */ | 1427 | */ |
1419 | if (!(cmd_fibcontext = | 1428 | if (!(cmd_fibcontext = aac_fib_alloc(aac))) |
1420 | aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) | ||
1421 | return SCSI_MLQUEUE_HOST_BUSY; | 1429 | return SCSI_MLQUEUE_HOST_BUSY; |
1422 | 1430 | ||
1423 | aac_fib_init(cmd_fibcontext); | 1431 | aac_fib_init(cmd_fibcontext); |
@@ -1470,6 +1478,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1470 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; | 1478 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; |
1471 | struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; | 1479 | struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; |
1472 | 1480 | ||
1481 | if (fsa_dev_ptr == NULL) | ||
1482 | return -1; | ||
1473 | /* | 1483 | /* |
1474 | * If the bus, id or lun is out of range, return fail | 1484 | * If the bus, id or lun is out of range, return fail |
1475 | * Test does not apply to ID 16, the pseudo id for the controller | 1485 | * Test does not apply to ID 16, the pseudo id for the controller |
@@ -1499,6 +1509,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1499 | case INQUIRY: | 1509 | case INQUIRY: |
1500 | case READ_CAPACITY: | 1510 | case READ_CAPACITY: |
1501 | case TEST_UNIT_READY: | 1511 | case TEST_UNIT_READY: |
1512 | if (dev->in_reset) | ||
1513 | return -1; | ||
1502 | spin_unlock_irq(host->host_lock); | 1514 | spin_unlock_irq(host->host_lock); |
1503 | aac_probe_container(dev, cid); | 1515 | aac_probe_container(dev, cid); |
1504 | if ((fsa_dev_ptr[cid].valid & 1) == 0) | 1516 | if ((fsa_dev_ptr[cid].valid & 1) == 0) |
@@ -1524,6 +1536,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1524 | } | 1536 | } |
1525 | } else { /* check for physical non-dasd devices */ | 1537 | } else { /* check for physical non-dasd devices */ |
1526 | if(dev->nondasd_support == 1){ | 1538 | if(dev->nondasd_support == 1){ |
1539 | if (dev->in_reset) | ||
1540 | return -1; | ||
1527 | return aac_send_srb_fib(scsicmd); | 1541 | return aac_send_srb_fib(scsicmd); |
1528 | } else { | 1542 | } else { |
1529 | scsicmd->result = DID_NO_CONNECT << 16; | 1543 | scsicmd->result = DID_NO_CONNECT << 16; |
@@ -1579,6 +1593,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1579 | scsicmd->scsi_done(scsicmd); | 1593 | scsicmd->scsi_done(scsicmd); |
1580 | return 0; | 1594 | return 0; |
1581 | } | 1595 | } |
1596 | if (dev->in_reset) | ||
1597 | return -1; | ||
1582 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); | 1598 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); |
1583 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ | 1599 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ |
1584 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | 1600 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); |
@@ -1734,6 +1750,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1734 | case READ_10: | 1750 | case READ_10: |
1735 | case READ_12: | 1751 | case READ_12: |
1736 | case READ_16: | 1752 | case READ_16: |
1753 | if (dev->in_reset) | ||
1754 | return -1; | ||
1737 | /* | 1755 | /* |
1738 | * Hack to keep track of ordinal number of the device that | 1756 | * Hack to keep track of ordinal number of the device that |
1739 | * corresponds to a container. Needed to convert | 1757 | * corresponds to a container. Needed to convert |
@@ -1752,6 +1770,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1752 | case WRITE_10: | 1770 | case WRITE_10: |
1753 | case WRITE_12: | 1771 | case WRITE_12: |
1754 | case WRITE_16: | 1772 | case WRITE_16: |
1773 | if (dev->in_reset) | ||
1774 | return -1; | ||
1755 | return aac_write(scsicmd, cid); | 1775 | return aac_write(scsicmd, cid); |
1756 | 1776 | ||
1757 | case SYNCHRONIZE_CACHE: | 1777 | case SYNCHRONIZE_CACHE: |
@@ -1782,6 +1802,8 @@ static int query_disk(struct aac_dev *dev, void __user *arg) | |||
1782 | struct fsa_dev_info *fsa_dev_ptr; | 1802 | struct fsa_dev_info *fsa_dev_ptr; |
1783 | 1803 | ||
1784 | fsa_dev_ptr = dev->fsa_dev; | 1804 | fsa_dev_ptr = dev->fsa_dev; |
1805 | if (!fsa_dev_ptr) | ||
1806 | return -ENODEV; | ||
1785 | if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) | 1807 | if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk))) |
1786 | return -EFAULT; | 1808 | return -EFAULT; |
1787 | if (qd.cnum == -1) | 1809 | if (qd.cnum == -1) |
@@ -1843,6 +1865,10 @@ static int delete_disk(struct aac_dev *dev, void __user *arg) | |||
1843 | struct fsa_dev_info *fsa_dev_ptr; | 1865 | struct fsa_dev_info *fsa_dev_ptr; |
1844 | 1866 | ||
1845 | fsa_dev_ptr = dev->fsa_dev; | 1867 | fsa_dev_ptr = dev->fsa_dev; |
1868 | if (!fsa_dev_ptr) | ||
1869 | return -ENODEV; | ||
1870 | if (!fsa_dev_ptr) | ||
1871 | return -ENODEV; | ||
1846 | 1872 | ||
1847 | if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) | 1873 | if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk))) |
1848 | return -EFAULT; | 1874 | return -EFAULT; |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index d0eecd4bec83..8924c183d9c3 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -1029,6 +1029,7 @@ struct aac_dev | |||
1029 | init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) | 1029 | init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) |
1030 | u8 raw_io_64; | 1030 | u8 raw_io_64; |
1031 | u8 printf_enabled; | 1031 | u8 printf_enabled; |
1032 | u8 in_reset; | ||
1032 | }; | 1033 | }; |
1033 | 1034 | ||
1034 | #define aac_adapter_interrupt(dev) \ | 1035 | #define aac_adapter_interrupt(dev) \ |
@@ -1670,6 +1671,7 @@ extern struct aac_common aac_config; | |||
1670 | #define RCV_TEMP_READINGS 0x00000025 | 1671 | #define RCV_TEMP_READINGS 0x00000025 |
1671 | #define GET_COMM_PREFERRED_SETTINGS 0x00000026 | 1672 | #define GET_COMM_PREFERRED_SETTINGS 0x00000026 |
1672 | #define IOP_RESET 0x00001000 | 1673 | #define IOP_RESET 0x00001000 |
1674 | #define IOP_RESET_ALWAYS 0x00001001 | ||
1673 | #define RE_INIT_ADAPTER 0x000000ee | 1675 | #define RE_INIT_ADAPTER 0x000000ee |
1674 | 1676 | ||
1675 | /* | 1677 | /* |
@@ -1788,7 +1790,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); | |||
1788 | int aac_fib_complete(struct fib * context); | 1790 | int aac_fib_complete(struct fib * context); |
1789 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) | 1791 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data) |
1790 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); | 1792 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); |
1791 | int aac_get_config_status(struct aac_dev *dev); | 1793 | int aac_get_config_status(struct aac_dev *dev, int commit_flag); |
1792 | int aac_get_containers(struct aac_dev *dev); | 1794 | int aac_get_containers(struct aac_dev *dev); |
1793 | int aac_scsi_cmd(struct scsi_cmnd *cmd); | 1795 | int aac_scsi_cmd(struct scsi_cmnd *cmd); |
1794 | int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); | 1796 | int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); |
@@ -1799,6 +1801,7 @@ int aac_sa_init(struct aac_dev *dev); | |||
1799 | unsigned int aac_response_normal(struct aac_queue * q); | 1801 | unsigned int aac_response_normal(struct aac_queue * q); |
1800 | unsigned int aac_command_normal(struct aac_queue * q); | 1802 | unsigned int aac_command_normal(struct aac_queue * q); |
1801 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); | 1803 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); |
1804 | int aac_check_health(struct aac_dev * dev); | ||
1802 | int aac_command_thread(void *data); | 1805 | int aac_command_thread(void *data); |
1803 | int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); | 1806 | int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); |
1804 | int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size); | 1807 | int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size); |
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 255421de9d1a..da1d3a9212f8 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include <linux/completion.h> | 38 | #include <linux/completion.h> |
39 | #include <linux/dma-mapping.h> | 39 | #include <linux/dma-mapping.h> |
40 | #include <linux/blkdev.h> | 40 | #include <linux/blkdev.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> /* ssleep prototype */ |
42 | #include <linux/kthread.h> | 42 | #include <linux/kthread.h> |
43 | #include <asm/semaphore.h> | 43 | #include <asm/semaphore.h> |
44 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
@@ -140,7 +140,8 @@ cleanup: | |||
140 | fibptr->hw_fib_pa = hw_fib_pa; | 140 | fibptr->hw_fib_pa = hw_fib_pa; |
141 | fibptr->hw_fib = hw_fib; | 141 | fibptr->hw_fib = hw_fib; |
142 | } | 142 | } |
143 | aac_fib_free(fibptr); | 143 | if (retval != -EINTR) |
144 | aac_fib_free(fibptr); | ||
144 | return retval; | 145 | return retval; |
145 | } | 146 | } |
146 | 147 | ||
@@ -297,7 +298,7 @@ return_fib: | |||
297 | spin_unlock_irqrestore(&dev->fib_lock, flags); | 298 | spin_unlock_irqrestore(&dev->fib_lock, flags); |
298 | /* If someone killed the AIF aacraid thread, restart it */ | 299 | /* If someone killed the AIF aacraid thread, restart it */ |
299 | status = !dev->aif_thread; | 300 | status = !dev->aif_thread; |
300 | if (status && dev->queues && dev->fsa_dev) { | 301 | if (status && !dev->in_reset && dev->queues && dev->fsa_dev) { |
301 | /* Be paranoid, be very paranoid! */ | 302 | /* Be paranoid, be very paranoid! */ |
302 | kthread_stop(dev->thread); | 303 | kthread_stop(dev->thread); |
303 | ssleep(1); | 304 | ssleep(1); |
@@ -621,7 +622,13 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
621 | 622 | ||
622 | actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); | 623 | actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry)); |
623 | if(actual_fibsize != fibsize){ // User made a mistake - should not continue | 624 | if(actual_fibsize != fibsize){ // User made a mistake - should not continue |
624 | dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n")); | 625 | dprintk((KERN_DEBUG"aacraid: Bad Size specified in " |
626 | "Raw SRB command calculated fibsize=%d " | ||
627 | "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d " | ||
628 | "issued fibsize=%d\n", | ||
629 | actual_fibsize, user_srbcmd->sg.count, | ||
630 | sizeof(struct aac_srb), sizeof(struct sgentry), | ||
631 | fibsize)); | ||
625 | rcode = -EINVAL; | 632 | rcode = -EINVAL; |
626 | goto cleanup; | 633 | goto cleanup; |
627 | } | 634 | } |
@@ -663,6 +670,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
663 | psg->count = cpu_to_le32(sg_indx+1); | 670 | psg->count = cpu_to_le32(sg_indx+1); |
664 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); | 671 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); |
665 | } | 672 | } |
673 | if (status == -EINTR) { | ||
674 | rcode = -EINTR; | ||
675 | goto cleanup; | ||
676 | } | ||
666 | 677 | ||
667 | if (status != 0){ | 678 | if (status != 0){ |
668 | dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); | 679 | dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n")); |
@@ -696,8 +707,10 @@ cleanup: | |||
696 | for(i=0; i <= sg_indx; i++){ | 707 | for(i=0; i <= sg_indx; i++){ |
697 | kfree(sg_list[i]); | 708 | kfree(sg_list[i]); |
698 | } | 709 | } |
699 | aac_fib_complete(srbfib); | 710 | if (rcode != -EINTR) { |
700 | aac_fib_free(srbfib); | 711 | aac_fib_complete(srbfib); |
712 | aac_fib_free(srbfib); | ||
713 | } | ||
701 | 714 | ||
702 | return rcode; | 715 | return rcode; |
703 | } | 716 | } |
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 1cd3584ba7ff..87a955096761 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -180,7 +180,7 @@ int aac_send_shutdown(struct aac_dev * dev) | |||
180 | -2 /* Timeout silently */, 1, | 180 | -2 /* Timeout silently */, 1, |
181 | NULL, NULL); | 181 | NULL, NULL); |
182 | 182 | ||
183 | if (status == 0) | 183 | if (status >= 0) |
184 | aac_fib_complete(fibctx); | 184 | aac_fib_complete(fibctx); |
185 | aac_fib_free(fibctx); | 185 | aac_fib_free(fibctx); |
186 | return status; | 186 | return status; |
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 3f27419c66af..53add53be0bd 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -40,8 +40,10 @@ | |||
40 | #include <linux/blkdev.h> | 40 | #include <linux/blkdev.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/kthread.h> | 42 | #include <linux/kthread.h> |
43 | #include <scsi/scsi.h> | ||
43 | #include <scsi/scsi_host.h> | 44 | #include <scsi/scsi_host.h> |
44 | #include <scsi/scsi_device.h> | 45 | #include <scsi/scsi_device.h> |
46 | #include <scsi/scsi_cmnd.h> | ||
45 | #include <asm/semaphore.h> | 47 | #include <asm/semaphore.h> |
46 | 48 | ||
47 | #include "aacraid.h" | 49 | #include "aacraid.h" |
@@ -464,6 +466,8 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
464 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); | 466 | dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa)); |
465 | dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); | 467 | dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); |
466 | 468 | ||
469 | if (!dev->queues) | ||
470 | return -ENODEV; | ||
467 | q = &dev->queues->queue[AdapNormCmdQueue]; | 471 | q = &dev->queues->queue[AdapNormCmdQueue]; |
468 | 472 | ||
469 | if(wait) | 473 | if(wait) |
@@ -527,8 +531,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
527 | } | 531 | } |
528 | udelay(5); | 532 | udelay(5); |
529 | } | 533 | } |
530 | } else | 534 | } else if (down_interruptible(&fibptr->event_wait)) { |
531 | down(&fibptr->event_wait); | 535 | spin_lock_irqsave(&fibptr->event_lock, flags); |
536 | if (fibptr->done == 0) { | ||
537 | fibptr->done = 2; /* Tell interrupt we aborted */ | ||
538 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
539 | return -EINTR; | ||
540 | } | ||
541 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
542 | } | ||
532 | BUG_ON(fibptr->done == 0); | 543 | BUG_ON(fibptr->done == 0); |
533 | 544 | ||
534 | if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ | 545 | if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){ |
@@ -795,7 +806,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
795 | 806 | ||
796 | /* Sniff for container changes */ | 807 | /* Sniff for container changes */ |
797 | 808 | ||
798 | if (!dev) | 809 | if (!dev || !dev->fsa_dev) |
799 | return; | 810 | return; |
800 | container = (u32)-1; | 811 | container = (u32)-1; |
801 | 812 | ||
@@ -1045,6 +1056,262 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
1045 | 1056 | ||
1046 | } | 1057 | } |
1047 | 1058 | ||
1059 | static int _aac_reset_adapter(struct aac_dev *aac) | ||
1060 | { | ||
1061 | int index, quirks; | ||
1062 | u32 ret; | ||
1063 | int retval; | ||
1064 | struct Scsi_Host *host; | ||
1065 | struct scsi_device *dev; | ||
1066 | struct scsi_cmnd *command; | ||
1067 | struct scsi_cmnd *command_list; | ||
1068 | |||
1069 | /* | ||
1070 | * Assumptions: | ||
1071 | * - host is locked. | ||
1072 | * - in_reset is asserted, so no new i/o is getting to the | ||
1073 | * card. | ||
1074 | * - The card is dead. | ||
1075 | */ | ||
1076 | host = aac->scsi_host_ptr; | ||
1077 | scsi_block_requests(host); | ||
1078 | aac_adapter_disable_int(aac); | ||
1079 | spin_unlock_irq(host->host_lock); | ||
1080 | kthread_stop(aac->thread); | ||
1081 | |||
1082 | /* | ||
1083 | * If a positive health, means in a known DEAD PANIC | ||
1084 | * state and the adapter could be reset to `try again'. | ||
1085 | */ | ||
1086 | retval = aac_adapter_check_health(aac); | ||
1087 | if (retval == 0) | ||
1088 | retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS, | ||
1089 | 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); | ||
1090 | if (retval) | ||
1091 | retval = aac_adapter_sync_cmd(aac, IOP_RESET, | ||
1092 | 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL); | ||
1093 | |||
1094 | if (retval) | ||
1095 | goto out; | ||
1096 | if (ret != 0x00000001) { | ||
1097 | retval = -ENODEV; | ||
1098 | goto out; | ||
1099 | } | ||
1100 | |||
1101 | index = aac->cardtype; | ||
1102 | |||
1103 | /* | ||
1104 | * Re-initialize the adapter, first free resources, then carefully | ||
1105 | * apply the initialization sequence to come back again. Only risk | ||
1106 | * is a change in Firmware dropping cache, it is assumed the caller | ||
1107 | * will ensure that i/o is queisced and the card is flushed in that | ||
1108 | * case. | ||
1109 | */ | ||
1110 | aac_fib_map_free(aac); | ||
1111 | aac->hw_fib_va = NULL; | ||
1112 | aac->hw_fib_pa = 0; | ||
1113 | pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); | ||
1114 | aac->comm_addr = NULL; | ||
1115 | aac->comm_phys = 0; | ||
1116 | kfree(aac->queues); | ||
1117 | aac->queues = NULL; | ||
1118 | free_irq(aac->pdev->irq, aac); | ||
1119 | kfree(aac->fsa_dev); | ||
1120 | aac->fsa_dev = NULL; | ||
1121 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) { | ||
1122 | if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) || | ||
1123 | ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK)))) | ||
1124 | goto out; | ||
1125 | } else { | ||
1126 | if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) || | ||
1127 | ((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL)))) | ||
1128 | goto out; | ||
1129 | } | ||
1130 | if ((retval = (*(aac_get_driver_ident(index)->init))(aac))) | ||
1131 | goto out; | ||
1132 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) | ||
1133 | if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) | ||
1134 | goto out; | ||
1135 | aac->thread = kthread_run(aac_command_thread, aac, aac->name); | ||
1136 | if (IS_ERR(aac->thread)) { | ||
1137 | retval = PTR_ERR(aac->thread); | ||
1138 | goto out; | ||
1139 | } | ||
1140 | (void)aac_get_adapter_info(aac); | ||
1141 | quirks = aac_get_driver_ident(index)->quirks; | ||
1142 | if ((quirks & AAC_QUIRK_34SG) && (host->sg_tablesize > 34)) { | ||
1143 | host->sg_tablesize = 34; | ||
1144 | host->max_sectors = (host->sg_tablesize * 8) + 112; | ||
1145 | } | ||
1146 | if ((quirks & AAC_QUIRK_17SG) && (host->sg_tablesize > 17)) { | ||
1147 | host->sg_tablesize = 17; | ||
1148 | host->max_sectors = (host->sg_tablesize * 8) + 112; | ||
1149 | } | ||
1150 | aac_get_config_status(aac, 1); | ||
1151 | aac_get_containers(aac); | ||
1152 | /* | ||
1153 | * This is where the assumption that the Adapter is quiesced | ||
1154 | * is important. | ||
1155 | */ | ||
1156 | command_list = NULL; | ||
1157 | __shost_for_each_device(dev, host) { | ||
1158 | unsigned long flags; | ||
1159 | spin_lock_irqsave(&dev->list_lock, flags); | ||
1160 | list_for_each_entry(command, &dev->cmd_list, list) | ||
1161 | if (command->SCp.phase == AAC_OWNER_FIRMWARE) { | ||
1162 | command->SCp.buffer = (struct scatterlist *)command_list; | ||
1163 | command_list = command; | ||
1164 | } | ||
1165 | spin_unlock_irqrestore(&dev->list_lock, flags); | ||
1166 | } | ||
1167 | while ((command = command_list)) { | ||
1168 | command_list = (struct scsi_cmnd *)command->SCp.buffer; | ||
1169 | command->SCp.buffer = NULL; | ||
1170 | command->result = DID_OK << 16 | ||
1171 | | COMMAND_COMPLETE << 8 | ||
1172 | | SAM_STAT_TASK_SET_FULL; | ||
1173 | command->SCp.phase = AAC_OWNER_ERROR_HANDLER; | ||
1174 | command->scsi_done(command); | ||
1175 | } | ||
1176 | retval = 0; | ||
1177 | |||
1178 | out: | ||
1179 | aac->in_reset = 0; | ||
1180 | scsi_unblock_requests(host); | ||
1181 | spin_lock_irq(host->host_lock); | ||
1182 | return retval; | ||
1183 | } | ||
1184 | |||
1185 | int aac_check_health(struct aac_dev * aac) | ||
1186 | { | ||
1187 | int BlinkLED; | ||
1188 | unsigned long time_now, flagv = 0; | ||
1189 | struct list_head * entry; | ||
1190 | struct Scsi_Host * host; | ||
1191 | |||
1192 | /* Extending the scope of fib_lock slightly to protect aac->in_reset */ | ||
1193 | if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) | ||
1194 | return 0; | ||
1195 | |||
1196 | if (aac->in_reset || !(BlinkLED = aac_adapter_check_health(aac))) { | ||
1197 | spin_unlock_irqrestore(&aac->fib_lock, flagv); | ||
1198 | return 0; /* OK */ | ||
1199 | } | ||
1200 | |||
1201 | aac->in_reset = 1; | ||
1202 | |||
1203 | /* Fake up an AIF: | ||
1204 | * aac_aifcmd.command = AifCmdEventNotify = 1 | ||
1205 | * aac_aifcmd.seqnum = 0xFFFFFFFF | ||
1206 | * aac_aifcmd.data[0] = AifEnExpEvent = 23 | ||
1207 | * aac_aifcmd.data[1] = AifExeFirmwarePanic = 3 | ||
1208 | * aac.aifcmd.data[2] = AifHighPriority = 3 | ||
1209 | * aac.aifcmd.data[3] = BlinkLED | ||
1210 | */ | ||
1211 | |||
1212 | time_now = jiffies/HZ; | ||
1213 | entry = aac->fib_list.next; | ||
1214 | |||
1215 | /* | ||
1216 | * For each Context that is on the | ||
1217 | * fibctxList, make a copy of the | ||
1218 | * fib, and then set the event to wake up the | ||
1219 | * thread that is waiting for it. | ||
1220 | */ | ||
1221 | while (entry != &aac->fib_list) { | ||
1222 | /* | ||
1223 | * Extract the fibctx | ||
1224 | */ | ||
1225 | struct aac_fib_context *fibctx = list_entry(entry, struct aac_fib_context, next); | ||
1226 | struct hw_fib * hw_fib; | ||
1227 | struct fib * fib; | ||
1228 | /* | ||
1229 | * Check if the queue is getting | ||
1230 | * backlogged | ||
1231 | */ | ||
1232 | if (fibctx->count > 20) { | ||
1233 | /* | ||
1234 | * It's *not* jiffies folks, | ||
1235 | * but jiffies / HZ, so do not | ||
1236 | * panic ... | ||
1237 | */ | ||
1238 | u32 time_last = fibctx->jiffies; | ||
1239 | /* | ||
1240 | * Has it been > 2 minutes | ||
1241 | * since the last read off | ||
1242 | * the queue? | ||
1243 | */ | ||
1244 | if ((time_now - time_last) > aif_timeout) { | ||
1245 | entry = entry->next; | ||
1246 | aac_close_fib_context(aac, fibctx); | ||
1247 | continue; | ||
1248 | } | ||
1249 | } | ||
1250 | /* | ||
1251 | * Warning: no sleep allowed while | ||
1252 | * holding spinlock | ||
1253 | */ | ||
1254 | hw_fib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); | ||
1255 | fib = kmalloc(sizeof(struct fib), GFP_ATOMIC); | ||
1256 | if (fib && hw_fib) { | ||
1257 | struct aac_aifcmd * aif; | ||
1258 | |||
1259 | memset(hw_fib, 0, sizeof(struct hw_fib)); | ||
1260 | memset(fib, 0, sizeof(struct fib)); | ||
1261 | fib->hw_fib = hw_fib; | ||
1262 | fib->dev = aac; | ||
1263 | aac_fib_init(fib); | ||
1264 | fib->type = FSAFS_NTC_FIB_CONTEXT; | ||
1265 | fib->size = sizeof (struct fib); | ||
1266 | fib->data = hw_fib->data; | ||
1267 | aif = (struct aac_aifcmd *)hw_fib->data; | ||
1268 | aif->command = cpu_to_le32(AifCmdEventNotify); | ||
1269 | aif->seqnum = cpu_to_le32(0xFFFFFFFF); | ||
1270 | aif->data[0] = cpu_to_le32(AifEnExpEvent); | ||
1271 | aif->data[1] = cpu_to_le32(AifExeFirmwarePanic); | ||
1272 | aif->data[2] = cpu_to_le32(AifHighPriority); | ||
1273 | aif->data[3] = cpu_to_le32(BlinkLED); | ||
1274 | |||
1275 | /* | ||
1276 | * Put the FIB onto the | ||
1277 | * fibctx's fibs | ||
1278 | */ | ||
1279 | list_add_tail(&fib->fiblink, &fibctx->fib_list); | ||
1280 | fibctx->count++; | ||
1281 | /* | ||
1282 | * Set the event to wake up the | ||
1283 | * thread that will waiting. | ||
1284 | */ | ||
1285 | up(&fibctx->wait_sem); | ||
1286 | } else { | ||
1287 | printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); | ||
1288 | kfree(fib); | ||
1289 | kfree(hw_fib); | ||
1290 | } | ||
1291 | entry = entry->next; | ||
1292 | } | ||
1293 | |||
1294 | spin_unlock_irqrestore(&aac->fib_lock, flagv); | ||
1295 | |||
1296 | if (BlinkLED < 0) { | ||
1297 | printk(KERN_ERR "%s: Host adapter dead %d\n", aac->name, BlinkLED); | ||
1298 | goto out; | ||
1299 | } | ||
1300 | |||
1301 | printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED); | ||
1302 | |||
1303 | host = aac->scsi_host_ptr; | ||
1304 | spin_lock_irqsave(host->host_lock, flagv); | ||
1305 | BlinkLED = _aac_reset_adapter(aac); | ||
1306 | spin_unlock_irqrestore(host->host_lock, flagv); | ||
1307 | return BlinkLED; | ||
1308 | |||
1309 | out: | ||
1310 | aac->in_reset = 0; | ||
1311 | return BlinkLED; | ||
1312 | } | ||
1313 | |||
1314 | |||
1048 | /** | 1315 | /** |
1049 | * aac_command_thread - command processing thread | 1316 | * aac_command_thread - command processing thread |
1050 | * @dev: Adapter to monitor | 1317 | * @dev: Adapter to monitor |
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index b2a5c7262f36..8335f07b7720 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c | |||
@@ -124,10 +124,15 @@ unsigned int aac_response_normal(struct aac_queue * q) | |||
124 | } else { | 124 | } else { |
125 | unsigned long flagv; | 125 | unsigned long flagv; |
126 | spin_lock_irqsave(&fib->event_lock, flagv); | 126 | spin_lock_irqsave(&fib->event_lock, flagv); |
127 | fib->done = 1; | 127 | if (!fib->done) |
128 | fib->done = 1; | ||
128 | up(&fib->event_wait); | 129 | up(&fib->event_wait); |
129 | spin_unlock_irqrestore(&fib->event_lock, flagv); | 130 | spin_unlock_irqrestore(&fib->event_lock, flagv); |
130 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | 131 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); |
132 | if (fib->done == 2) { | ||
133 | aac_fib_complete(fib); | ||
134 | aac_fib_free(fib); | ||
135 | } | ||
131 | } | 136 | } |
132 | consumed++; | 137 | consumed++; |
133 | spin_lock_irqsave(q->lock, flags); | 138 | spin_lock_irqsave(q->lock, flags); |
@@ -316,7 +321,8 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) | |||
316 | unsigned long flagv; | 321 | unsigned long flagv; |
317 | dprintk((KERN_INFO "event_wait up\n")); | 322 | dprintk((KERN_INFO "event_wait up\n")); |
318 | spin_lock_irqsave(&fib->event_lock, flagv); | 323 | spin_lock_irqsave(&fib->event_lock, flagv); |
319 | fib->done = 1; | 324 | if (!fib->done) |
325 | fib->done = 1; | ||
320 | up(&fib->event_wait); | 326 | up(&fib->event_wait); |
321 | spin_unlock_irqrestore(&fib->event_lock, flagv); | 327 | spin_unlock_irqrestore(&fib->event_lock, flagv); |
322 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); | 328 | FIB_COUNTER_INCREMENT(aac_config.NormalRecved); |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index e42a479ce64a..d67058f80816 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -454,17 +454,17 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) | |||
454 | printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", | 454 | printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", |
455 | AAC_DRIVERNAME); | 455 | AAC_DRIVERNAME); |
456 | aac = (struct aac_dev *)host->hostdata; | 456 | aac = (struct aac_dev *)host->hostdata; |
457 | if (aac_adapter_check_health(aac)) { | 457 | |
458 | printk(KERN_ERR "%s: Host adapter appears dead\n", | 458 | if ((count = aac_check_health(aac))) |
459 | AAC_DRIVERNAME); | 459 | return count; |
460 | return -ENODEV; | ||
461 | } | ||
462 | /* | 460 | /* |
463 | * Wait for all commands to complete to this specific | 461 | * Wait for all commands to complete to this specific |
464 | * target (block maximum 60 seconds). | 462 | * target (block maximum 60 seconds). |
465 | */ | 463 | */ |
466 | for (count = 60; count; --count) { | 464 | for (count = 60; count; --count) { |
467 | int active = 0; | 465 | int active = aac->in_reset; |
466 | |||
467 | if (active == 0) | ||
468 | __shost_for_each_device(dev, host) { | 468 | __shost_for_each_device(dev, host) { |
469 | spin_lock_irqsave(&dev->list_lock, flags); | 469 | spin_lock_irqsave(&dev->list_lock, flags); |
470 | list_for_each_entry(command, &dev->cmd_list, list) { | 470 | list_for_each_entry(command, &dev->cmd_list, list) { |
@@ -933,7 +933,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, | |||
933 | else | 933 | else |
934 | shost->max_channel = 0; | 934 | shost->max_channel = 0; |
935 | 935 | ||
936 | aac_get_config_status(aac); | 936 | aac_get_config_status(aac, 0); |
937 | aac_get_containers(aac); | 937 | aac_get_containers(aac); |
938 | list_add(&aac->entry, insert); | 938 | list_add(&aac->entry, insert); |
939 | 939 | ||
@@ -1013,6 +1013,10 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) | |||
1013 | list_del(&aac->entry); | 1013 | list_del(&aac->entry); |
1014 | scsi_host_put(shost); | 1014 | scsi_host_put(shost); |
1015 | pci_disable_device(pdev); | 1015 | pci_disable_device(pdev); |
1016 | if (list_empty(&aac_devices)) { | ||
1017 | unregister_chrdev(aac_cfg_major, "aac"); | ||
1018 | aac_cfg_major = -1; | ||
1019 | } | ||
1016 | } | 1020 | } |
1017 | 1021 | ||
1018 | static struct pci_driver aac_pci_driver = { | 1022 | static struct pci_driver aac_pci_driver = { |
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c index 458ea897fd72..f850c3a7cce9 100644 --- a/drivers/scsi/aacraid/rkt.c +++ b/drivers/scsi/aacraid/rkt.c | |||
@@ -395,6 +395,25 @@ static int aac_rkt_send(struct fib * fib) | |||
395 | return 0; | 395 | return 0; |
396 | } | 396 | } |
397 | 397 | ||
398 | static int aac_rkt_restart_adapter(struct aac_dev *dev) | ||
399 | { | ||
400 | u32 var; | ||
401 | |||
402 | printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", | ||
403 | dev->name, dev->id); | ||
404 | |||
405 | if (aac_rkt_check_health(dev) <= 0) | ||
406 | return 1; | ||
407 | if (rkt_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, | ||
408 | &var, NULL, NULL, NULL, NULL)) | ||
409 | return 1; | ||
410 | if (var != 0x00000001) | ||
411 | return 1; | ||
412 | if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
413 | return 1; | ||
414 | return 0; | ||
415 | } | ||
416 | |||
398 | /** | 417 | /** |
399 | * aac_rkt_init - initialize an i960 based AAC card | 418 | * aac_rkt_init - initialize an i960 based AAC card |
400 | * @dev: device to configure | 419 | * @dev: device to configure |
@@ -417,6 +436,9 @@ int aac_rkt_init(struct aac_dev *dev) | |||
417 | /* | 436 | /* |
418 | * Check to see if the board panic'd while booting. | 437 | * Check to see if the board panic'd while booting. |
419 | */ | 438 | */ |
439 | if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
440 | if (aac_rkt_restart_adapter(dev)) | ||
441 | goto error_iounmap; | ||
420 | /* | 442 | /* |
421 | * Check to see if the board failed any self tests. | 443 | * Check to see if the board failed any self tests. |
422 | */ | 444 | */ |
@@ -431,13 +453,6 @@ int aac_rkt_init(struct aac_dev *dev) | |||
431 | printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); | 453 | printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance); |
432 | goto error_iounmap; | 454 | goto error_iounmap; |
433 | } | 455 | } |
434 | /* | ||
435 | * Check to see if the board panic'd while booting. | ||
436 | */ | ||
437 | if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) { | ||
438 | printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance); | ||
439 | goto error_iounmap; | ||
440 | } | ||
441 | start = jiffies; | 456 | start = jiffies; |
442 | /* | 457 | /* |
443 | * Wait for the adapter to be up and running. Wait up to 3 minutes | 458 | * Wait for the adapter to be up and running. Wait up to 3 minutes |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 035018db69b1..c715c4b2442d 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -394,6 +394,25 @@ static int aac_rx_send(struct fib * fib) | |||
394 | return 0; | 394 | return 0; |
395 | } | 395 | } |
396 | 396 | ||
397 | static int aac_rx_restart_adapter(struct aac_dev *dev) | ||
398 | { | ||
399 | u32 var; | ||
400 | |||
401 | printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", | ||
402 | dev->name, dev->id); | ||
403 | |||
404 | if (aac_rx_check_health(dev) <= 0) | ||
405 | return 1; | ||
406 | if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0, | ||
407 | &var, NULL, NULL, NULL, NULL)) | ||
408 | return 1; | ||
409 | if (var != 0x00000001) | ||
410 | return 1; | ||
411 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
412 | return 1; | ||
413 | return 0; | ||
414 | } | ||
415 | |||
397 | /** | 416 | /** |
398 | * aac_rx_init - initialize an i960 based AAC card | 417 | * aac_rx_init - initialize an i960 based AAC card |
399 | * @dev: device to configure | 418 | * @dev: device to configure |
@@ -416,6 +435,9 @@ int aac_rx_init(struct aac_dev *dev) | |||
416 | /* | 435 | /* |
417 | * Check to see if the board panic'd while booting. | 436 | * Check to see if the board panic'd while booting. |
418 | */ | 437 | */ |
438 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) | ||
439 | if (aac_rx_restart_adapter(dev)) | ||
440 | goto error_iounmap; | ||
419 | /* | 441 | /* |
420 | * Check to see if the board failed any self tests. | 442 | * Check to see if the board failed any self tests. |
421 | */ | 443 | */ |
@@ -424,13 +446,6 @@ int aac_rx_init(struct aac_dev *dev) | |||
424 | goto error_iounmap; | 446 | goto error_iounmap; |
425 | } | 447 | } |
426 | /* | 448 | /* |
427 | * Check to see if the board panic'd while booting. | ||
428 | */ | ||
429 | if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) { | ||
430 | printk(KERN_ERR "%s%d: adapter kernel panic.\n", dev->name, instance); | ||
431 | goto error_iounmap; | ||
432 | } | ||
433 | /* | ||
434 | * Check to see if the monitor panic'd while booting. | 449 | * Check to see if the monitor panic'd while booting. |
435 | */ | 450 | */ |
436 | if (rx_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) { | 451 | if (rx_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) { |