diff options
author | Don Brace <don.brace@microsemi.com> | 2017-05-04 17:51:49 -0500 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-06-12 20:48:01 -0400 |
commit | 08ec46f673369f65dfc6fc52fb7fadb39776e81f (patch) | |
tree | 09681df625093c7afd143cc4814838f147b4b831 /drivers/scsi/hpsa.c | |
parent | b63c64ac5a5ccb6ee56e0d906f2f5d2b7e54cbd9 (diff) | |
download | linux-08ec46f673369f65dfc6fc52fb7fadb39776e81f.tar.bz2 |
scsi: hpsa: remove abort handler
- simplify the driver
- there are a lot of quirky racy conditions not handled
- causes more aborts/resets when the number of commands to be aborted is
large, such as in multi-path fail-overs.
- has been turned off in our internal driver since 8/31/2015
Reviewed-by: Scott Benesh <scott.benesh@microsemi.com>
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Reviewed-by: Kevin Barnett <kevin.barnett@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/hpsa.c')
-rw-r--r-- | drivers/scsi/hpsa.c | 621 |
1 files changed, 8 insertions, 613 deletions
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index ea778cc453dc..9a631e399169 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -258,7 +258,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh, static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth); static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd); -static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd); static int hpsa_slave_alloc(struct scsi_device *sdev); static int hpsa_slave_configure(struct scsi_device *sdev); static void hpsa_slave_destroy(struct scsi_device *sdev); @@ -326,7 +325,7 @@ static inline bool hpsa_is_cmd_idle(struct CommandList *c) static inline bool hpsa_is_pending_event(struct CommandList *c) { - return c->abort_pending || c->reset_pending; + return c->reset_pending; } /* extract sense key, asc, and ascq from sense data. -1 means invalid. */ @@ -581,12 +580,6 @@ static u32 soft_unresettable_controller[] = { 0x409D0E11, /* Smart Array 6400 EM */ }; -static u32 needs_abort_tags_swizzled[] = { - 0x323D103C, /* Smart Array P700m */ - 0x324a103C, /* Smart Array P712m */ - 0x324b103C, /* SmartArray P711m */ -}; - static int board_id_in_array(u32 a[], int nelems, u32 board_id) { int i; @@ -615,12 +608,6 @@ static int ctlr_is_resettable(u32 board_id) ctlr_is_soft_resettable(board_id); } -static int ctlr_needs_abort_tags_swizzled(u32 board_id) -{ - return board_id_in_array(needs_abort_tags_swizzled, - ARRAY_SIZE(needs_abort_tags_swizzled), board_id); -} - static ssize_t host_show_resettable(struct device *dev, struct device_attribute *attr, char *buf) { @@ -928,8 +915,8 @@ static struct device_attribute *hpsa_shost_attrs[] = { NULL, }; -#define HPSA_NRESERVED_CMDS (HPSA_CMDS_RESERVED_FOR_ABORTS + \ - HPSA_CMDS_RESERVED_FOR_DRIVER + HPSA_MAX_CONCURRENT_PASSTHRUS) +#define HPSA_NRESERVED_CMDS (HPSA_CMDS_RESERVED_FOR_DRIVER +\ + HPSA_MAX_CONCURRENT_PASSTHRUS) static struct scsi_host_template hpsa_driver_template = { .module = THIS_MODULE, @@ -941,7 +928,6 @@ static struct scsi_host_template hpsa_driver_template = { .change_queue_depth = hpsa_change_queue_depth, .this_id = -1, .use_clustering = ENABLE_CLUSTERING, - .eh_abort_handler = hpsa_eh_abort_handler, .eh_device_reset_handler = hpsa_eh_device_reset_handler, .ioctl = hpsa_ioctl, .slave_alloc = hpsa_slave_alloc, @@ -2361,26 +2347,12 @@ static void hpsa_cmd_resolve_events(struct ctlr_info *h, bool do_wake = false; /* - * Prevent the following race in the abort handler: - * - * 1. LLD is requested to abort a SCSI command - * 2. The SCSI command completes - * 3. The struct CommandList associated with step 2 is made available - * 4. New I/O request to LLD to another LUN re-uses struct CommandList - * 5. Abort handler follows scsi_cmnd->host_scribble and - * finds struct CommandList and tries to aborts it - * Now we have aborted the wrong command. - * - * Reset c->scsi_cmd here so that the abort or reset handler will know + * Reset c->scsi_cmd here so that the reset handler will know * this command has completed. Then, check to see if the handler is * waiting for this command, and, if so, wake it. */ c->scsi_cmd = SCSI_CMD_IDLE; mb(); /* Declare command idle before checking for pending events. */ - if (c->abort_pending) { - do_wake = true; - c->abort_pending = false; - } if (c->reset_pending) { unsigned long flags; struct hpsa_scsi_dev_t *dev; @@ -2423,20 +2395,6 @@ static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c) queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work); } -static void hpsa_set_scsi_cmd_aborted(struct scsi_cmnd *cmd) -{ - cmd->result = DID_ABORT << 16; -} - -static void hpsa_cmd_abort_and_free(struct ctlr_info *h, struct CommandList *c, - struct scsi_cmnd *cmd) -{ - hpsa_set_scsi_cmd_aborted(cmd); - dev_warn(&h->pdev->dev, "CDB %16phN was aborted with status 0x%x\n", - c->Request.CDB, c->err_info->ScsiStatus); - hpsa_cmd_resolve_and_free(h, c); -} - static void process_ioaccel2_completion(struct ctlr_info *h, struct CommandList *c, struct scsi_cmnd *cmd, struct hpsa_scsi_dev_t *dev) @@ -2561,12 +2519,9 @@ static void complete_scsi_command(struct CommandList *cp) return hpsa_cmd_free_and_done(h, cp, cmd); } - if ((unlikely(hpsa_is_pending_event(cp)))) { + if ((unlikely(hpsa_is_pending_event(cp)))) if (cp->reset_pending) return hpsa_cmd_free_and_done(h, cp, cmd); - if (cp->abort_pending) - return hpsa_cmd_abort_and_free(h, cp, cmd); - } if (cp->cmd_type == CMD_IOACCEL2) return process_ioaccel2_completion(h, cp, cmd, dev); @@ -2686,8 +2641,8 @@ static void complete_scsi_command(struct CommandList *cp) cp->Request.CDB); break; case CMD_ABORTED: - /* Return now to avoid calling scsi_done(). */ - return hpsa_cmd_abort_and_free(h, cp, cmd); + cmd->result = DID_ABORT << 16; + break; case CMD_ABORT_FAILED: cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "CDB %16phN : abort failed\n", @@ -3793,53 +3748,6 @@ static unsigned char hpsa_volume_offline(struct ctlr_info *h, return HPSA_LV_OK; } -/* - * Find out if a logical device supports aborts by simply trying one. - * Smart Array may claim not to support aborts on logical drives, but - * if a MSA2000 * is connected, the drives on that will be presented - * by the Smart Array as logical drives, and aborts may be sent to - * those devices successfully. So the simplest way to find out is - * to simply try an abort and see how the device responds. - */ -static int hpsa_device_supports_aborts(struct ctlr_info *h, - unsigned char *scsi3addr) -{ - struct CommandList *c; - struct ErrorInfo *ei; - int rc = 0; - - u64 tag = (u64) -1; /* bogus tag */ - - /* Assume that physical devices support aborts */ - if (!is_logical_dev_addr_mode(scsi3addr)) - return 1; - - c = cmd_alloc(h); - - (void) fill_cmd(c, HPSA_ABORT_MSG, h, &tag, 0, 0, scsi3addr, TYPE_MSG); - (void) hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, - DEFAULT_TIMEOUT); - /* no unmap needed here because no data xfer. */ - ei = c->err_info; - switch (ei->CommandStatus) { - case CMD_INVALID: - rc = 0; - break; - case CMD_UNABORTABLE: - case CMD_ABORT_FAILED: - rc = 1; - break; - case CMD_TMF_STATUS: - rc = hpsa_evaluate_tmf_status(h, c); - break; - default: - rc = 0; - break; - } - cmd_free(h, c); - return rc; -} - static int hpsa_update_device_info(struct ctlr_info *h, unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device, unsigned char *is_OBDR_device) @@ -3939,31 +3847,6 @@ bail_out: return rc; } -static void hpsa_update_device_supports_aborts(struct ctlr_info *h, - struct hpsa_scsi_dev_t *dev, u8 *scsi3addr) -{ - unsigned long flags; - int rc, entry; - /* - * See if this device supports aborts. If we already know - * the device, we already know if it supports aborts, otherwise - * we have to find out if it supports aborts by trying one. - */ - spin_lock_irqsave(&h->devlock, flags); - rc = hpsa_scsi_find_entry(dev, h->dev, h->ndevices, &entry); - if ((rc == DEVICE_SAME || rc == DEVICE_UPDATED) && - entry >= 0 && entry < h->ndevices) { - dev->supports_aborts = h->dev[entry]->supports_aborts; - spin_unlock_irqrestore(&h->devlock, flags); - } else { - spin_unlock_irqrestore(&h->devlock, flags); - dev->supports_aborts = - hpsa_device_supports_aborts(h, scsi3addr); - if (dev->supports_aborts < 0) - dev->supports_aborts = 0; - } -} - /* * Helper function to assign bus, target, lun mapping of devices. * Logical drive target and lun are assigned at this time, but @@ -4001,35 +3884,6 @@ static void figure_bus_target_lun(struct ctlr_info *h, 0, lunid & 0x3fff); } - -/* - * Get address of physical disk used for an ioaccel2 mode command: - * 1. Extract ioaccel2 handle from the command. - * 2. Find a matching ioaccel2 handle from list of physical disks. - * 3. Return: - * 1 and set scsi3addr to address of matching physical - * 0 if no matching physical disk was found. - */ -static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h, - struct CommandList *ioaccel2_cmd_to_abort, unsigned char *scsi3addr) -{ - struct io_accel2_cmd *c2 = - &h->ioaccel2_cmd_pool[ioaccel2_cmd_to_abort->cmdindex]; - unsigned long flags; - int i; - - spin_lock_irqsave(&h->devlock, flags); - for (i = 0; i < h->ndevices; i++) - if (h->dev[i]->ioaccel_handle == le32_to_cpu(c2->scsi_nexus)) { - memcpy(scsi3addr, h->dev[i]->scsi3addr, - sizeof(h->dev[i]->scsi3addr)); - spin_unlock_irqrestore(&h->devlock, flags); - return 1; - } - spin_unlock_irqrestore(&h->devlock, flags); - return 0; -} - static int figure_external_status(struct ctlr_info *h, int raid_ctlr_position, int i, int nphysicals, int nlocal_logicals) { @@ -4394,7 +4248,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) } figure_bus_target_lun(h, lunaddrbytes, tmpdevice); - hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes); this_device = currentsd[ncurrent]; /* Turn on discovery_polling if there are ext target devices. @@ -5528,8 +5381,6 @@ static void hpsa_command_resubmit_worker(struct work_struct *work) } if (c->reset_pending) return hpsa_cmd_free_and_done(c->h, c, cmd); - if (c->abort_pending) - return hpsa_cmd_abort_and_free(c->h, c, cmd); if (c->cmd_type == CMD_IOACCEL2) { struct ctlr_info *h = c->h; struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; @@ -5987,433 +5838,6 @@ return_reset_status: return rc; } -static void swizzle_abort_tag(u8 *tag) -{ - u8 original_tag[8]; - - memcpy(original_tag, tag, 8); - tag[0] = original_tag[3]; - tag[1] = original_tag[2]; - tag[2] = original_tag[1]; - tag[3] = original_tag[0]; - tag[4] = original_tag[7]; - tag[5] = original_tag[6]; - tag[6] = original_tag[5]; - tag[7] = original_tag[4]; -} - -static void hpsa_get_tag(struct ctlr_info *h, - struct CommandList *c, __le32 *taglower, __le32 *tagupper) -{ - u64 tag; - if (c->cmd_type == CMD_IOACCEL1) { - struct io_accel1_cmd *cm1 = (struct io_accel1_cmd *) - &h->ioaccel_cmd_pool[c->cmdindex]; - tag = le64_to_cpu(cm1->tag); - *tagupper = cpu_to_le32(tag >> 32); - *taglower = cpu_to_le32(tag); - return; - } - if (c->cmd_type == CMD_IOACCEL2) { - struct io_accel2_cmd *cm2 = (struct io_accel2_cmd *) - &h->ioaccel2_cmd_pool[c->cmdindex]; - /* upper tag not used in ioaccel2 mode */ - memset(tagupper, 0, sizeof(*tagupper)); - *taglower = cm2->Tag; - return; - } - tag = le64_to_cpu(c->Header.tag); - *tagupper = cpu_to_le32(tag >> 32); - *taglower = cpu_to_le32(tag); -} - -static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr, - struct CommandList *abort, int reply_queue) -{ - int rc = IO_OK; - struct CommandList *c; - struct ErrorInfo *ei; - __le32 tagupper, taglower; - - c = cmd_alloc(h); - - /* fill_cmd can't fail here, no buffer to map */ - (void) fill_cmd(c, HPSA_ABORT_MSG, h, &abort->Header.tag, - 0, 0, scsi3addr, TYPE_MSG); - if (h->needs_abort_tags_swizzled) - swizzle_abort_tag(&c->Request.CDB[4]); - (void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT); - hpsa_get_tag(h, abort, &taglower, &tagupper); - dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: do_simple_cmd(abort) completed.\n", - __func__, tagupper, taglower); - /* no unmap needed here because no data xfer. */ - - ei = c->err_info; - switch (ei->CommandStatus) { - case CMD_SUCCESS: - break; - case CMD_TMF_STATUS: - rc = hpsa_evaluate_tmf_status(h, c); - break; - case CMD_UNABORTABLE: /* Very common, don't make noise. */ - rc = -1; - break; - default: - dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: interpreting error.\n", - __func__, tagupper, taglower); - hpsa_scsi_interpret_error(h, c); - rc = -1; - break; - } - cmd_free(h, c); - dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n", - __func__, tagupper, taglower); - return rc; -} - -static void setup_ioaccel2_abort_cmd(struct CommandList *c, struct ctlr_info *h, - struct CommandList *command_to_abort, int reply_queue) -{ - struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; - struct hpsa_tmf_struct *ac = (struct hpsa_tmf_struct *) c2; - struct io_accel2_cmd *c2a = - &h->ioaccel2_cmd_pool[command_to_abort->cmdindex]; - struct scsi_cmnd *scmd = command_to_abort->scsi_cmd; - struct hpsa_scsi_dev_t *dev = scmd->device->hostdata; - - if (!dev) - return; - - /* - * We're overlaying struct hpsa_tmf_struct on top of something which - * was allocated as a struct io_accel2_cmd, so we better be sure it - * actually fits, and doesn't overrun the error info space. - */ - BUILD_BUG_ON(sizeof(struct hpsa_tmf_struct) > - sizeof(struct io_accel2_cmd)); - BUG_ON(offsetof(struct io_accel2_cmd, error_data) < - offsetof(struct hpsa_tmf_struct, error_len) + - sizeof(ac->error_len)); - - c->cmd_type = IOACCEL2_TMF; - c->scsi_cmd = SCSI_CMD_BUSY; - - /* Adjust the DMA address to point to the accelerated command buffer */ - c->busaddr = (u32) h->ioaccel2_cmd_pool_dhandle + - (c->cmdindex * sizeof(struct io_accel2_cmd)); - BUG_ON(c->busaddr & 0x0000007F); - - memset(ac, 0, sizeof(*c2)); /* yes this is correct */ - ac->iu_type = IOACCEL2_IU_TMF_TYPE; - ac->reply_queue = reply_queue; - ac->tmf = IOACCEL2_TMF_ABORT; - ac->it_nexus = cpu_to_le32(dev->ioaccel_handle); - memset(ac->lun_id, 0, sizeof(ac->lun_id)); - ac->tag = cpu_to_le64(c->cmdindex << DIRECT_LOOKUP_SHIFT); - ac->abort_tag = cpu_to_le64(le32_to_cpu(c2a->Tag)); - ac->error_ptr = cpu_to_le64(c->busaddr + - offsetof(struct io_accel2_cmd, error_data)); - ac->error_len = cpu_to_le32(sizeof(c2->error_data)); -} - -/* ioaccel2 path firmware cannot handle abort task requests. - * Change abort requests to physical target reset, and send to the - * address of the physical disk used for the ioaccel 2 command. - * Return 0 on success (IO_OK) - * -1 on failure - */ - -static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h, - unsigned char *scsi3addr, struct CommandList *abort, int reply_queue) -{ - int rc = IO_OK; - struct scsi_cmnd *scmd; /* scsi command within request being aborted */ - struct hpsa_scsi_dev_t *dev; /* device to which scsi cmd was sent */ - unsigned char phys_scsi3addr[8]; /* addr of phys disk with volume */ - unsigned char *psa = &phys_scsi3addr[0]; - - /* Get a pointer to the hpsa logical device. */ - scmd = abort->scsi_cmd; - dev = (struct hpsa_scsi_dev_t *)(scmd->device->hostdata); - if (dev == NULL) { - dev_warn(&h->pdev->dev, - "Cannot abort: no device pointer for command.\n"); - return -1; /* not abortable */ - } - - if (h->raid_offload_debug > 0) - dev_info(&h->pdev->dev, - "scsi %d:%d:%d:%d %s scsi3addr 0x%8phN\n", - h->scsi_host->host_no, dev->bus, dev->target, dev->lun, - "Reset as abort", scsi3addr); - - if (!dev->offload_enabled) { - dev_warn(&h->pdev->dev, - "Can't abort: device is not operating in HP SSD Smart Path mode.\n"); - return -1; /* not abortable */ - } - - /* Incoming scsi3addr is logical addr. We need physical disk addr. */ - if (!hpsa_get_pdisk_of_ioaccel2(h, abort, psa)) { - dev_warn(&h->pdev->dev, "Can't abort: Failed lookup of physical address.\n"); - return -1; /* not abortable */ - } - - /* send the reset */ - if (h->raid_offload_debug > 0) - dev_info(&h->pdev->dev, - "Reset as abort: Resetting physical device at scsi3addr 0x%8phN\n", - psa); - rc = hpsa_do_reset(h, dev, psa, HPSA_PHYS_TARGET_RESET, reply_queue); - if (rc != 0) { - dev_warn(&h->pdev->dev, - "Reset as abort: Failed on physical device at scsi3addr 0x%8phN\n", - psa); - return rc; /* failed to reset */ - } - - /* wait for device to recover */ - if (wait_for_device_to_become_ready(h, psa, reply_queue) != 0) { - dev_warn(&h->pdev->dev, - "Reset as abort: Failed: Device never recovered from reset: 0x%8phN\n", - psa); - return -1; /* failed to recover */ - } - - /* device recovered */ - dev_info(&h->pdev->dev, - "Reset as abort: Device recovered from reset: scsi3addr 0x%8phN\n", - psa); - - return rc; /* success */ -} - -static int hpsa_send_abort_ioaccel2(struct ctlr_info *h, - struct CommandList *abort, int reply_queue) -{ - int rc = IO_OK; - struct CommandList *c; - __le32 taglower, tagupper; - struct hpsa_scsi_dev_t *dev; - struct io_accel2_cmd *c2; - - dev = abort->scsi_cmd->device->hostdata; - if (!dev) - return -1; - - if (!dev->offload_enabled && !dev->hba_ioaccel_enabled) - return -1; - - c = cmd_alloc(h); - setup_ioaccel2_abort_cmd(c, h, abort, reply_queue); - c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; - (void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT); - hpsa_get_tag(h, abort, &taglower, &tagupper); - dev_dbg(&h->pdev->dev, - "%s: Tag:0x%08x:%08x: do_simple_cmd(ioaccel2 abort) completed.\n", - __func__, tagupper, taglower); - /* no unmap needed here because no data xfer. */ - - dev_dbg(&h->pdev->dev, - "%s: Tag:0x%08x:%08x: abort service response = 0x%02x.\n", - __func__, tagupper, taglower, c2->error_data.serv_response); - switch (c2->error_data.serv_response) { - case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE: - case IOACCEL2_SERV_RESPONSE_TMF_SUCCESS: - rc = 0; - break; - case IOACCEL2_SERV_RESPONSE_TMF_REJECTED: - case IOACCEL2_SERV_RESPONSE_FAILURE: - case IOACCEL2_SERV_RESPONSE_TMF_WRONG_LUN: - rc = -1; - break; - default: - dev_warn(&h->pdev->dev, - "%s: Tag:0x%08x:%08x: unknown abort service response 0x%02x\n", - __func__, tagupper, taglower, - c2->error_data.serv_response); - rc = -1; - } - cmd_free(h, c); - dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n", __func__, - tagupper, taglower); - return rc; -} - -static int hpsa_send_abort_both_ways(struct ctlr_info *h, - struct hpsa_scsi_dev_t *dev, struct CommandList *abort, int reply_queue) -{ - /* - * ioccelerator mode 2 commands should be aborted via the - * accelerated path, since RAID path is unaware of these commands, - * but not all underlying firmware can handle abort TMF. - * Change abort to physical device reset when abort TMF is unsupported. - */ - if (abort->cmd_type == CMD_IOACCEL2) { - if ((HPSATMF_IOACCEL_ENABLED & h->TMFSupportFlags) || - dev->physical_device) - return hpsa_send_abort_ioaccel2(h, abort, - reply_queue); - else - return hpsa_send_reset_as_abort_ioaccel2(h, - dev->scsi3addr, - abort, reply_queue); - } - return hpsa_send_abort(h, dev->scsi3addr, abort, reply_queue); -} - -/* Find out which reply queue a command was meant to return on */ -static int hpsa_extract_reply_queue(struct ctlr_info *h, - struct CommandList *c) -{ - if (c->cmd_type == CMD_IOACCEL2) - return h->ioaccel2_cmd_pool[c->cmdindex].reply_queue; - return c->Header.ReplyQueue; -} - -/* - * Limit concurrency of abort commands to prevent - * over-subscription of commands - */ -static inline int wait_for_available_abort_cmd(struct ctlr_info *h) -{ -#define ABORT_CMD_WAIT_MSECS 5000 - return !wait_event_timeout(h->abort_cmd_wait_queue, - atomic_dec_if_positive(&h->abort_cmds_available) >= 0, - msecs_to_jiffies(ABORT_CMD_WAIT_MSECS)); -} - -/* Send an abort for the specified command. - * If the device and controller support it, - * send a task abort request. - */ -static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) -{ - - int rc; - struct ctlr_info *h; - struct hpsa_scsi_dev_t *dev; - struct CommandList *abort; /* pointer to command to be aborted */ - struct scsi_cmnd *as; /* ptr to scsi cmd inside aborted command. */ - char msg[256]; /* For debug messaging. */ - int ml = 0; - __le32 tagupper, taglower; - int refcount, reply_queue; - - if (sc == NULL) - return FAILED; - - if (sc->device == NULL) - return FAILED; - - /* Find the controller of the command to be aborted */ - h = sdev_to_hba(sc->device); - if (h == NULL) - return FAILED; - - /* Find the device of the command to be aborted */ - dev = sc->device->hostdata; - if (!dev) { - dev_err(&h->pdev->dev, "%s FAILED, Device lookup failed.\n", - msg); - return FAILED; - } - - /* If controller locked up, we can guarantee command won't complete */ - if (lockup_detected(h)) { - hpsa_show_dev_msg(KERN_WARNING, h, dev, - "ABORT FAILED, lockup detected"); - return FAILED; - } - - /* This is a good time to check if controller lockup has occurred */ - if (detect_controller_lockup(h)) { - hpsa_show_dev_msg(KERN_WARNING, h, dev, - "ABORT FAILED, new lockup detected"); - return FAILED; - } - - /* Check that controller supports some kind of task abort */ - if (!(HPSATMF_PHYS_TASK_ABORT & h->TMFSupportFlags) && - !(HPSATMF_LOG_TASK_ABORT & h->TMFSupportFlags)) - return FAILED; - - memset(msg, 0, sizeof(msg)); - ml += sprintf(msg+ml, "scsi %d:%d:%d:%llu %s %p", - h->scsi_host->host_no, sc->device->channel, - sc->device->id, sc->device->lun, - "Aborting command", sc); - - /* Get SCSI command to be aborted */ - abort = (struct CommandList *) sc->host_scribble; - if (abort == NULL) { - /* This can happen if the command already completed. */ - return SUCCESS; - } - refcount = atomic_inc_return(&abort->refcount); - if (refcount == 1) { /* Command is done already. */ - cmd_free(h, abort); - return SUCCESS; - } - - /* Don't bother trying the abort if we know it won't work. */ - if (abort->cmd_type != CMD_IOACCEL2 && - abort->cmd_type != CMD_IOACCEL1 && !dev->supports_aborts) { - cmd_free(h, abort); - return FAILED; - } - - /* - * Check that we're aborting the right command. - * It's possible the CommandList already completed and got re-used. - */ - if (abort->scsi_cmd != sc) { - cmd_free(h, abort); - return SUCCESS; - } - - abort->abort_pending = true; - hpsa_get_tag(h, abort, &taglower, &tagupper); - reply_queue = hpsa_extract_reply_queue(h, abort); - ml += sprintf(msg+ml, "Tag:0x%08x:%08x ", tagupper, taglower); - as = abort->scsi_cmd; - if (as != NULL) - ml += sprintf(msg+ml, - "CDBLen: %d CDB: 0x%02x%02x... SN: 0x%lx ", - as->cmd_len, as->cmnd[0], as->cmnd[1], - as->serial_number); - dev_warn(&h->pdev->dev, "%s BEING SENT\n", msg); - hpsa_show_dev_msg(KERN_WARNING, h, dev, "Aborting command"); - - /* - * Command is in flight, or possibly already completed - * by the firmware (but not to the scsi mid layer) but we can't - * distinguish which. Send the abort down. - */ - if (wait_for_available_abort_cmd(h)) { - dev_warn(&h->pdev->dev, - "%s FAILED, timeout waiting for an abort command to become available.\n", - msg); - cmd_free(h, abort); - return FAILED; - } - rc = hpsa_send_abort_both_ways(h, dev, abort, reply_queue); - atomic_inc(&h->abort_cmds_available); - wake_up_all(&h->abort_cmd_wait_queue); - if (rc != 0) { - dev_warn(&h->pdev->dev, "%s SENT, FAILED\n", msg); - hpsa_show_dev_msg(KERN_WARNING, h, dev, - "FAILED to abort command"); - cmd_free(h, abort); - return FAILED; - } - dev_info(&h->pdev->dev, "%s SENT, SUCCESS\n", msg); - wait_event(h->event_sync_wait_queue, - abort->scsi_cmd != sc || lockup_detected(h)); - cmd_free(h, abort); - return !lockup_detected(h) ? SUCCESS : FAILED; -} - /* * For operations with an associated SCSI command, a command block is allocated * at init, and managed by cmd_tagged_alloc() and cmd_tagged_free() using the @@ -6459,9 +5883,7 @@ static void cmd_tagged_free(struct ctlr_info *h, struct CommandList *c) { /* * Release our reference to the block. We don't need to do anything - * else to free it, because it is accessed by index. (There's no point - * in checking the result of the decrement, since we cannot guarantee - * that there isn't a concurrent abort which is also accessing it.) + * else to free it, because it is accessed by index. */ (void)atomic_dec(&c->refcount); } @@ -7000,7 +6422,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, int cmd_type) { int pci_dir = XFER_NONE; - u64 tag; /* for commands to be aborted */ c->cmd_type = CMD_IOCTL_PEND; c->scsi_cmd = SCSI_CMD_BUSY; @@ -7184,27 +6605,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[6] = 0x00; c->Request.CDB[7] = 0x00; break; - case HPSA_ABORT_MSG: - memcpy(&tag, buff, sizeof(tag)); - dev_dbg(&h->pdev->dev, - "Abort Tag:0x%016llx using rqst Tag:0x%016llx", - tag, c->Header.tag); - c->Request.CDBLen = 16; - c->Request.type_attr_dir = - TYPE_ATTR_DIR(cmd_type, - ATTR_SIMPLE, XFER_WRITE); - c->Request.Timeout = 0; /* Don't time out */ - c->Request.CDB[0] = HPSA_TASK_MANAGEMENT; - c->Request.CDB[1] = HPSA_TMF_ABORT_TASK; - c->Request.CDB[2] = 0x00; /* reserved */ - c->Request.CDB[3] = 0x00; /* reserved */ - /* Tag to abort goes in CDB[4]-CDB[11] */ - memcpy(&c->Request.CDB[4], &tag, sizeof(tag)); - c->Request.CDB[12] = 0x00; /* reserved */ - c->Request.CDB[13] = 0x00; /* reserved */ - c->Request.CDB[14] = 0x00; /* reserved */ - c->Request.CDB[15] = 0x00; /* reserved */ - break; default: dev_warn(&h->pdev->dev, "unknown message type %d\n", cmd); @@ -8162,9 +7562,6 @@ static int hpsa_pci_init(struct ctlr_info *h) h->product_name = products[prod_index].product_name; h->access = *(products[prod_index].access); - h->needs_abort_tags_swizzled = - ctlr_needs_abort_tags_swizzled(h->board_id); - pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); @@ -8885,7 +8282,6 @@ reinit_after_soft_reset: spin_lock_init(&h->scan_lock); spin_lock_init(&h->reset_lock); atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS); - atomic_set(&h->abort_cmds_available, HPSA_CMDS_RESERVED_FOR_ABORTS); /* Allocate and clear per-cpu variable lockup_detected */ h->lockup_detected = alloc_percpu(u32); @@ -8937,7 +8333,6 @@ reinit_after_soft_reset: if (rc) goto clean5; /* cmd, irq, shost, pci, lu, aer/h */ init_waitqueue_head(&h->scan_wait_queue); - init_waitqueue_head(&h->abort_cmd_wait_queue); init_waitqueue_head(&h->event_sync_wait_queue); mutex_init(&h->reset_mutex); h->scan_finished = 1; /* no scan currently in progress */ |