diff -ur linux-2.6.17-rc4/drivers/scsi/megaraid/megaraid_mbox.c linux-2.6.17-rc4.new/drivers/scsi/megaraid/megaraid_mbox.c --- linux-2.6.17-rc4/drivers/scsi/megaraid/megaraid_mbox.c 2006-05-11 16:31:53.000000000 -0700 +++ linux-2.6.17-rc4.new/drivers/scsi/megaraid/megaraid_mbox.c 2006-05-16 11:18:56.263708705 -0700 @@ -94,6 +94,8 @@ static int megaraid_sysfs_alloc_resources(adapter_t *); static void megaraid_sysfs_free_resources(adapter_t *); +static int megaraid_pci_master_abort(struct pci_dev *); + static int megaraid_abort_handler(struct scsi_cmnd *); static int megaraid_reset_handler(struct scsi_cmnd *); @@ -1276,7 +1278,7 @@ // detach scb from free pool spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags); - if (list_empty(head)) { + if (list_empty_careful(head)) { spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); return NULL; } @@ -1314,7 +1316,7 @@ scb->scp = NULL; spin_lock_irqsave(SCSI_FREE_LIST_LOCK(adapter), flags); - list_add(&scb->list, &adapter->kscb_pool); + list_move(&scb->list, &adapter->kscb_pool); spin_unlock_irqrestore(SCSI_FREE_LIST_LOCK(adapter), flags); @@ -1911,7 +1913,7 @@ if (scb_q) { scb_q->state = SCB_PENDQ; - list_add_tail(&scb_q->list, &adapter->pend_list); + list_move_tail(&scb_q->list, &adapter->pend_list); } // if the adapter in not in quiescent mode, post the commands to FW @@ -1920,7 +1922,7 @@ return; } - while (!list_empty(&adapter->pend_list)) { + while (!list_empty_careful(&adapter->pend_list)) { assert_spin_locked(PENDING_LIST_LOCK(adapter)); @@ -1946,7 +1948,7 @@ scb->state = SCB_PENDQ; - list_add(&scb->list, &adapter->pend_list); + list_move(&scb->list, &adapter->pend_list); spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags); @@ -2148,7 +2150,7 @@ } scb->status = mbox->status; - list_add_tail(&scb->list, &clist); + list_move_tail(&scb->list, &clist); } // Acknowledge interrupt @@ -2477,6 +2479,28 @@ /** + * megaraid_pci_master_abort + * @dev : pci device structure + * + * Tests for PCI Master Abort on the host adapter and clears state + * Returns state of error with inverted logic test to give proper + * state of the pci statuts bit describing master_abort. + */ +static int megaraid_pci_master_abort(struct pci_dev* dev) +{ + u16 status, error_bits; + + pci_read_config_word(dev, PCI_STATUS, &status); + error_bits = (status & PCI_STATUS_REC_MASTER_ABORT); + if (error_bits) + pci_write_config_word(dev, PCI_STATUS, error_bits); + pci_read_config_word(dev, PCI_STATUS, &status); + error_bits = (status & PCI_STATUS_REC_MASTER_ABORT); + return (!error_bits) ? 0 : 1; +} + + +/** * megaraid_abort_handler - abort the scsi command * @scp : command to be aborted * @@ -2505,9 +2529,13 @@ // If FW has stopped responding, simply return failure if (raid_dev->hw_error) { - con_log(CL_ANN, (KERN_NOTICE - "megaraid: hw error, not aborting\n")); - return FAILED; + // test if adapter is locked up because of pci master abort + if (megaraid_pci_master_abort(adapter->pdev)) { + con_log(CL_ANN, (KERN_NOTICE + "megaraid: hw error, cannot reset\n")); + return FAILED; + } + raid_dev->hw_error = 0; } // There might a race here, where the command was completed by the @@ -2519,14 +2547,13 @@ list_for_each_entry_safe(scb, tmp, &adapter->completed_list, list) { if (scb->scp == scp) { // Found command - - list_del_init(&scb->list); // from completed list - con_log(CL_ANN, (KERN_WARNING "megaraid: %ld:%d[%d:%d], abort from completed list\n", scp->serial_number, scb->sno, scb->dev_channel, scb->dev_target)); + list_del_init(&scb->list); // from completed list + scp->result = (DID_ABORT << 16); scp->scsi_done(scp); @@ -2549,8 +2576,6 @@ if (scb->scp == scp) { // Found command - list_del_init(&scb->list); // from pending list - ASSERT(!(scb->state & SCB_ISSUED)); con_log(CL_ANN, (KERN_WARNING @@ -2558,6 +2583,8 @@ scp->serial_number, scb->dev_channel, scb->dev_target)); + list_del_init(&scb->list); // from pending list + scp->result = (DID_ABORT << 16); scp->scsi_done(scp); @@ -3606,7 +3633,7 @@ // detach one scb from free pool spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags); - if (list_empty(head)) { // should never happen because of CMM + if (list_empty_careful(head)) { // should never happen because of CMM con_log(CL_ANN, (KERN_WARNING "megaraid mbox: bug in cmm handler, lost resources\n")); @@ -3737,7 +3764,7 @@ spin_lock_irqsave(USER_FREE_LIST_LOCK(adapter), flags); - list_add(&scb->list, &adapter->uscb_pool); + list_move(&scb->list, &adapter->uscb_pool); spin_unlock_irqrestore(USER_FREE_LIST_LOCK(adapter), flags); diff -ur linux-2.6.17-rc4/drivers/scsi/megaraid/megaraid_mm.c linux-2.6.17-rc4.new/drivers/scsi/megaraid/megaraid_mm.c --- linux-2.6.17-rc4/drivers/scsi/megaraid/megaraid_mm.c 2006-05-11 16:31:53.000000000 -0700 +++ linux-2.6.17-rc4.new/drivers/scsi/megaraid/megaraid_mm.c 2006-05-16 10:16:19.461954269 -0700 @@ -577,7 +577,7 @@ head = &adp->kioc_pool; - if (list_empty(head)) { + if (list_empty_careful(head)) { up(&adp->kioc_semaphore); spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); @@ -641,7 +641,7 @@ /* Return the kioc to the free pool */ spin_lock_irqsave(&adp->kioc_pool_lock, flags); - list_add(&kioc->list, &adp->kioc_pool); + list_move(&kioc->list, &adp->kioc_pool); spin_unlock_irqrestore(&adp->kioc_pool_lock, flags); /* increment the free kioc count */ diff -ur linux-2.6.17-rc4/drivers/scsi/megaraid/megaraid_sas.c linux-2.6.17-rc4.new/drivers/scsi/megaraid/megaraid_sas.c --- linux-2.6.17-rc4/drivers/scsi/megaraid/megaraid_sas.c 2006-05-11 16:31:53.000000000 -0700 +++ linux-2.6.17-rc4.new/drivers/scsi/megaraid/megaraid_sas.c 2006-05-16 10:25:54.562822089 -0700 @@ -95,7 +95,7 @@ spin_lock_irqsave(&instance->cmd_pool_lock, flags); - if (!list_empty(&instance->cmd_pool)) { + if (!list_empty_careful(&instance->cmd_pool)) { cmd = list_entry((&instance->cmd_pool)->next, struct megasas_cmd, list); list_del_init(&cmd->list); @@ -120,7 +120,7 @@ spin_lock_irqsave(&instance->cmd_pool_lock, flags); cmd->scmd = NULL; - list_add_tail(&cmd->list, &instance->cmd_pool); + list_move_tail(&cmd->list, &instance->cmd_pool); spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); }