diff options
Diffstat (limited to 'drivers/scsi/smartpqi/smartpqi_init.c')
-rw-r--r-- | drivers/scsi/smartpqi/smartpqi_init.c | 160 |
1 files changed, 97 insertions, 63 deletions
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index b78d20b74ed8..2112ea6723c6 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -40,11 +40,11 @@ #define BUILD_TIMESTAMP #endif -#define DRIVER_VERSION "1.1.4-115" +#define DRIVER_VERSION "1.1.4-130" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 1 #define DRIVER_RELEASE 4 -#define DRIVER_REVISION 115 +#define DRIVER_REVISION 130 #define DRIVER_NAME "Microsemi PQI Driver (v" \ DRIVER_VERSION BUILD_TIMESTAMP ")" @@ -1197,20 +1197,30 @@ no_buffer: device->volume_offline = volume_offline; } +#define PQI_INQUIRY_PAGE0_RETRIES 3 + static int pqi_get_device_info(struct pqi_ctrl_info *ctrl_info, struct pqi_scsi_dev *device) { int rc; u8 *buffer; + unsigned int retries; buffer = kmalloc(64, GFP_KERNEL); if (!buffer) return -ENOMEM; /* Send an inquiry to the device to see what it is. */ - rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0, buffer, 64); - if (rc) - goto out; + for (retries = 0;;) { + rc = pqi_scsi_inquiry(ctrl_info, device->scsi3addr, 0, + buffer, 64); + if (rc == 0) + break; + if (pqi_is_logical_device(device) || + rc != PQI_CMD_STATUS_ABORTED || + ++retries > PQI_INQUIRY_PAGE0_RETRIES) + goto out; + } scsi_sanitize_inquiry_string(&buffer[8], 8); scsi_sanitize_inquiry_string(&buffer[16], 16); @@ -2693,7 +2703,7 @@ static unsigned int pqi_process_io_intr(struct pqi_ctrl_info *ctrl_info, oq_ci = queue_group->oq_ci_copy; while (1) { - oq_pi = *queue_group->oq_pi; + oq_pi = readl(queue_group->oq_pi); if (oq_pi == oq_ci) break; @@ -2784,7 +2794,7 @@ static void pqi_send_event_ack(struct pqi_ctrl_info *ctrl_info, spin_lock_irqsave(&queue_group->submit_lock[RAID_PATH], flags); iq_pi = queue_group->iq_pi_copy[RAID_PATH]; - iq_ci = *queue_group->iq_ci[RAID_PATH]; + iq_ci = readl(queue_group->iq_ci[RAID_PATH]); if (pqi_num_elements_free(iq_pi, iq_ci, ctrl_info->num_elements_per_iq)) @@ -2943,7 +2953,7 @@ static unsigned int pqi_process_event_intr(struct pqi_ctrl_info *ctrl_info) oq_ci = event_queue->oq_ci_copy; while (1) { - oq_pi = *event_queue->oq_pi; + oq_pi = readl(event_queue->oq_pi); if (oq_pi == oq_ci) break; @@ -3167,7 +3177,7 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info) size_t element_array_length_per_iq; size_t element_array_length_per_oq; void *element_array; - void *next_queue_index; + void __iomem *next_queue_index; void *aligned_pointer; unsigned int num_inbound_queues; unsigned int num_outbound_queues; @@ -3263,7 +3273,7 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info) element_array += PQI_NUM_EVENT_QUEUE_ELEMENTS * PQI_EVENT_OQ_ELEMENT_LENGTH; - next_queue_index = PTR_ALIGN(element_array, + next_queue_index = (void __iomem *)PTR_ALIGN(element_array, PQI_OPERATIONAL_INDEX_ALIGNMENT); for (i = 0; i < ctrl_info->num_queue_groups; i++) { @@ -3271,21 +3281,24 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info) queue_group->iq_ci[RAID_PATH] = next_queue_index; queue_group->iq_ci_bus_addr[RAID_PATH] = ctrl_info->queue_memory_base_dma_handle + - (next_queue_index - ctrl_info->queue_memory_base); + (next_queue_index - + (void __iomem *)ctrl_info->queue_memory_base); next_queue_index += sizeof(pqi_index_t); next_queue_index = PTR_ALIGN(next_queue_index, PQI_OPERATIONAL_INDEX_ALIGNMENT); queue_group->iq_ci[AIO_PATH] = next_queue_index; queue_group->iq_ci_bus_addr[AIO_PATH] = ctrl_info->queue_memory_base_dma_handle + - (next_queue_index - ctrl_info->queue_memory_base); + (next_queue_index - + (void __iomem *)ctrl_info->queue_memory_base); next_queue_index += sizeof(pqi_index_t); next_queue_index = PTR_ALIGN(next_queue_index, PQI_OPERATIONAL_INDEX_ALIGNMENT); queue_group->oq_pi = next_queue_index; queue_group->oq_pi_bus_addr = ctrl_info->queue_memory_base_dma_handle + - (next_queue_index - ctrl_info->queue_memory_base); + (next_queue_index - + (void __iomem *)ctrl_info->queue_memory_base); next_queue_index += sizeof(pqi_index_t); next_queue_index = PTR_ALIGN(next_queue_index, PQI_OPERATIONAL_INDEX_ALIGNMENT); @@ -3294,7 +3307,8 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info) ctrl_info->event_queue.oq_pi = next_queue_index; ctrl_info->event_queue.oq_pi_bus_addr = ctrl_info->queue_memory_base_dma_handle + - (next_queue_index - ctrl_info->queue_memory_base); + (next_queue_index - + (void __iomem *)ctrl_info->queue_memory_base); return 0; } @@ -3368,7 +3382,8 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info) admin_queues->oq_element_array = &admin_queues_aligned->oq_element_array; admin_queues->iq_ci = &admin_queues_aligned->iq_ci; - admin_queues->oq_pi = &admin_queues_aligned->oq_pi; + admin_queues->oq_pi = + (pqi_index_t __iomem *)&admin_queues_aligned->oq_pi; admin_queues->iq_element_array_bus_addr = ctrl_info->admin_queue_memory_base_dma_handle + @@ -3384,8 +3399,8 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info) ctrl_info->admin_queue_memory_base); admin_queues->oq_pi_bus_addr = ctrl_info->admin_queue_memory_base_dma_handle + - ((void *)admin_queues->oq_pi - - ctrl_info->admin_queue_memory_base); + ((void __iomem *)admin_queues->oq_pi - + (void __iomem *)ctrl_info->admin_queue_memory_base); return 0; } @@ -3486,7 +3501,7 @@ static int pqi_poll_for_admin_response(struct pqi_ctrl_info *ctrl_info, timeout = (PQI_ADMIN_REQUEST_TIMEOUT_SECS * HZ) + jiffies; while (1) { - oq_pi = *admin_queues->oq_pi; + oq_pi = readl(admin_queues->oq_pi); if (oq_pi != oq_ci) break; if (time_after(jiffies, timeout)) { @@ -3545,7 +3560,7 @@ static void pqi_start_io(struct pqi_ctrl_info *ctrl_info, DIV_ROUND_UP(iu_length, PQI_OPERATIONAL_IQ_ELEMENT_LENGTH); - iq_ci = *queue_group->iq_ci[path]; + iq_ci = readl(queue_group->iq_ci[path]); if (num_elements_needed > pqi_num_elements_free(iq_pi, iq_ci, ctrl_info->num_elements_per_iq)) @@ -3621,29 +3636,24 @@ static void pqi_raid_synchronous_complete(struct pqi_io_request *io_request, complete(waiting); } -static int pqi_submit_raid_request_synchronous_with_io_request( - struct pqi_ctrl_info *ctrl_info, struct pqi_io_request *io_request, - unsigned long timeout_msecs) +static int pqi_process_raid_io_error_synchronous(struct pqi_raid_error_info + *error_info) { - int rc = 0; - DECLARE_COMPLETION_ONSTACK(wait); + int rc = -EIO; - io_request->io_complete_callback = pqi_raid_synchronous_complete; - io_request->context = &wait; - - pqi_start_io(ctrl_info, - &ctrl_info->queue_groups[PQI_DEFAULT_QUEUE_GROUP], RAID_PATH, - io_request); - - if (timeout_msecs == NO_TIMEOUT) { - pqi_wait_for_completion_io(ctrl_info, &wait); - } else { - if (!wait_for_completion_io_timeout(&wait, - msecs_to_jiffies(timeout_msecs))) { - dev_warn(&ctrl_info->pci_dev->dev, - "command timed out\n"); - rc = -ETIMEDOUT; - } + switch (error_info->data_out_result) { + case PQI_DATA_IN_OUT_GOOD: + if (error_info->status == SAM_STAT_GOOD) + rc = 0; + break; + case PQI_DATA_IN_OUT_UNDERFLOW: + if (error_info->status == SAM_STAT_GOOD || + error_info->status == SAM_STAT_CHECK_CONDITION) + rc = 0; + break; + case PQI_DATA_IN_OUT_ABORTED: + rc = PQI_CMD_STATUS_ABORTED; + break; } return rc; @@ -3653,11 +3663,12 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info, struct pqi_iu_header *request, unsigned int flags, struct pqi_raid_error_info *error_info, unsigned long timeout_msecs) { - int rc; + int rc = 0; struct pqi_io_request *io_request; unsigned long start_jiffies; unsigned long msecs_blocked; size_t iu_length; + DECLARE_COMPLETION_ONSTACK(wait); /* * Note that specifying PQI_SYNC_FLAGS_INTERRUPTABLE and a timeout value @@ -3686,11 +3697,13 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info, pqi_ctrl_busy(ctrl_info); timeout_msecs = pqi_wait_if_ctrl_blocked(ctrl_info, timeout_msecs); if (timeout_msecs == 0) { + pqi_ctrl_unbusy(ctrl_info); rc = -ETIMEDOUT; goto out; } if (pqi_ctrl_offline(ctrl_info)) { + pqi_ctrl_unbusy(ctrl_info); rc = -ENXIO; goto out; } @@ -3708,8 +3721,25 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info, PQI_REQUEST_HEADER_LENGTH; memcpy(io_request->iu, request, iu_length); - rc = pqi_submit_raid_request_synchronous_with_io_request(ctrl_info, - io_request, timeout_msecs); + io_request->io_complete_callback = pqi_raid_synchronous_complete; + io_request->context = &wait; + + pqi_start_io(ctrl_info, + &ctrl_info->queue_groups[PQI_DEFAULT_QUEUE_GROUP], RAID_PATH, + io_request); + + pqi_ctrl_unbusy(ctrl_info); + + if (timeout_msecs == NO_TIMEOUT) { + pqi_wait_for_completion_io(ctrl_info, &wait); + } else { + if (!wait_for_completion_io_timeout(&wait, + msecs_to_jiffies(timeout_msecs))) { + dev_warn(&ctrl_info->pci_dev->dev, + "command timed out\n"); + rc = -ETIMEDOUT; + } + } if (error_info) { if (io_request->error_info) @@ -3718,25 +3748,13 @@ static int pqi_submit_raid_request_synchronous(struct pqi_ctrl_info *ctrl_info, else memset(error_info, 0, sizeof(*error_info)); } else if (rc == 0 && io_request->error_info) { - u8 scsi_status; - struct pqi_raid_error_info *raid_error_info; - - raid_error_info = io_request->error_info; - scsi_status = raid_error_info->status; - - if (scsi_status == SAM_STAT_CHECK_CONDITION && - raid_error_info->data_out_result == - PQI_DATA_IN_OUT_UNDERFLOW) - scsi_status = SAM_STAT_GOOD; - - if (scsi_status != SAM_STAT_GOOD) - rc = -EIO; + rc = pqi_process_raid_io_error_synchronous( + io_request->error_info); } pqi_free_io_request(io_request); out: - pqi_ctrl_unbusy(ctrl_info); up(&ctrl_info->sync_request_sem); return rc; @@ -5041,7 +5059,7 @@ static int pqi_wait_until_inbound_queues_empty(struct pqi_ctrl_info *ctrl_info) iq_pi = queue_group->iq_pi_copy[path]; while (1) { - iq_ci = *queue_group->iq_ci[path]; + iq_ci = readl(queue_group->iq_ci[path]); if (iq_ci == iq_pi) break; pqi_check_ctrl_health(ctrl_info); @@ -6230,20 +6248,20 @@ static void pqi_reinit_queues(struct pqi_ctrl_info *ctrl_info) admin_queues = &ctrl_info->admin_queues; admin_queues->iq_pi_copy = 0; admin_queues->oq_ci_copy = 0; - *admin_queues->oq_pi = 0; + writel(0, admin_queues->oq_pi); for (i = 0; i < ctrl_info->num_queue_groups; i++) { ctrl_info->queue_groups[i].iq_pi_copy[RAID_PATH] = 0; ctrl_info->queue_groups[i].iq_pi_copy[AIO_PATH] = 0; ctrl_info->queue_groups[i].oq_ci_copy = 0; - *ctrl_info->queue_groups[i].iq_ci[RAID_PATH] = 0; - *ctrl_info->queue_groups[i].iq_ci[AIO_PATH] = 0; - *ctrl_info->queue_groups[i].oq_pi = 0; + writel(0, ctrl_info->queue_groups[i].iq_ci[RAID_PATH]); + writel(0, ctrl_info->queue_groups[i].iq_ci[AIO_PATH]); + writel(0, ctrl_info->queue_groups[i].oq_pi); } event_queue = &ctrl_info->event_queue; - *event_queue->oq_pi = 0; + writel(0, event_queue->oq_pi); event_queue->oq_ci_copy = 0; } @@ -6826,6 +6844,18 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x004a) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x004b) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x004c) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x0110) }, { @@ -6950,6 +6980,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADVANTECH, 0x8312) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_DELL, 0x1fe0) }, { |