Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hpsa: cleanup reset

Synchronize completion the reset with completion of outstanding commands

Extending the newly-added synchronous abort functionality,
now also synchronize resets with the completion of outstanding commands.
Rename the wait queue to reflect the fact that it's being used for both
types of waits. Also, don't complete commands which are terminated
due to a reset operation.

fix for controller lockup during reset

Reviewed-by: Scott Teel <scott.teel@pmcs.com>
Reviewed-by: Kevin Barnett <kevin.barnett@pmcs.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Reviewed-by: Hannes Reinecke <hare@Suse.de>
Signed-off-by: Webb Scales <webbnh@hp.com>
Signed-off-by: Don Brace <don.brace@pmcs.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: James Bottomley <JBottomley@Odin.com>

authored by

Webb Scales and committed by
James Bottomley
d604f533 39c53f55

+181 -29
+176 -28
drivers/scsi/hpsa.c
··· 283 283 return c->scsi_cmd == SCSI_CMD_IDLE; 284 284 } 285 285 286 + static inline bool hpsa_is_pending_event(struct CommandList *c) 287 + { 288 + return c->abort_pending || c->reset_pending; 289 + } 290 + 286 291 /* extract sense key, asc, and ascq from sense data. -1 means invalid. */ 287 292 static void decode_sense_data(const u8 *sense_data, int sense_data_len, 288 293 u8 *sense_key, u8 *asc, u8 *ascq) ··· 982 977 983 978 static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) 984 979 { 985 - if (unlikely(c->abort_pending)) 980 + if (unlikely(hpsa_is_pending_event(c))) 986 981 return finish_cmd(c); 987 982 988 983 __enqueue_cmd_and_start_io(h, c, DEFAULT_REPLY_QUEUE); ··· 1453 1448 1454 1449 if (nraid_map_entries > RAID_MAP_MAX_ENTRIES) 1455 1450 nraid_map_entries = RAID_MAP_MAX_ENTRIES; 1451 + 1452 + logical_drive->nphysical_disks = nraid_map_entries; 1456 1453 1457 1454 qdepth = 0; 1458 1455 for (i = 0; i < nraid_map_entries; i++) { ··· 2001 1994 static void hpsa_cmd_resolve_events(struct ctlr_info *h, 2002 1995 struct CommandList *c) 2003 1996 { 1997 + bool do_wake = false; 1998 + 2004 1999 /* 2005 2000 * Prevent the following race in the abort handler: 2006 2001 * ··· 2014 2005 * finds struct CommandList and tries to aborts it 2015 2006 * Now we have aborted the wrong command. 2016 2007 * 2017 - * Clear c->scsi_cmd here so that the abort handler will know this 2018 - * command has completed. Then, check to see if the abort handler is 2008 + * Reset c->scsi_cmd here so that the abort or reset handler will know 2009 + * this command has completed. Then, check to see if the handler is 2019 2010 * waiting for this command, and, if so, wake it. 2020 2011 */ 2021 2012 c->scsi_cmd = SCSI_CMD_IDLE; 2022 - mb(); /* Ensure c->scsi_cmd is set to SCSI_CMD_IDLE */ 2013 + mb(); /* Declare command idle before checking for pending events. */ 2023 2014 if (c->abort_pending) { 2015 + do_wake = true; 2024 2016 c->abort_pending = false; 2025 - wake_up_all(&h->abort_sync_wait_queue); 2026 2017 } 2018 + if (c->reset_pending) { 2019 + unsigned long flags; 2020 + struct hpsa_scsi_dev_t *dev; 2021 + 2022 + /* 2023 + * There appears to be a reset pending; lock the lock and 2024 + * reconfirm. If so, then decrement the count of outstanding 2025 + * commands and wake the reset command if this is the last one. 2026 + */ 2027 + spin_lock_irqsave(&h->lock, flags); 2028 + dev = c->reset_pending; /* Re-fetch under the lock. */ 2029 + if (dev && atomic_dec_and_test(&dev->reset_cmds_out)) 2030 + do_wake = true; 2031 + c->reset_pending = NULL; 2032 + spin_unlock_irqrestore(&h->lock, flags); 2033 + } 2034 + 2035 + if (do_wake) 2036 + wake_up_all(&h->event_sync_wait_queue); 2027 2037 } 2028 2038 2029 2039 static void hpsa_cmd_resolve_and_free(struct ctlr_info *h, ··· 2089 2061 if (likely(c2->error_data.serv_response == 0 && 2090 2062 c2->error_data.status == 0)) 2091 2063 return hpsa_cmd_free_and_done(h, c, cmd); 2092 - 2093 - /* don't requeue a command which is being aborted */ 2094 - if (unlikely(c->abort_pending)) 2095 - return hpsa_cmd_abort_and_free(h, c, cmd); 2096 2064 2097 2065 /* 2098 2066 * Any RAID offload error results in retry which will use ··· 2184 2160 return hpsa_cmd_free_and_done(h, cp, cmd); 2185 2161 } 2186 2162 2163 + if ((unlikely(hpsa_is_pending_event(cp)))) { 2164 + if (cp->reset_pending) 2165 + return hpsa_cmd_resolve_and_free(h, cp); 2166 + if (cp->abort_pending) 2167 + return hpsa_cmd_abort_and_free(h, cp, cmd); 2168 + } 2169 + 2187 2170 if (cp->cmd_type == CMD_IOACCEL2) 2188 2171 return process_ioaccel2_completion(h, cp, cmd, dev); 2189 2172 ··· 2218 2187 if (is_logical_dev_addr_mode(dev->scsi3addr)) { 2219 2188 if (ei->CommandStatus == CMD_IOACCEL_DISABLED) 2220 2189 dev->offload_enabled = 0; 2221 - if (!cp->abort_pending) 2222 - return hpsa_retry_cmd(h, cp); 2190 + return hpsa_retry_cmd(h, cp); 2223 2191 } 2224 2192 } 2225 - 2226 - if (cp->abort_pending) 2227 - ei->CommandStatus = CMD_ABORTED; 2228 2193 2229 2194 /* an error has occurred */ 2230 2195 switch (ei->CommandStatus) { ··· 2639 2612 } 2640 2613 out: 2641 2614 cmd_free(h, c); 2615 + return rc; 2616 + } 2617 + 2618 + static bool hpsa_cmd_dev_match(struct ctlr_info *h, struct CommandList *c, 2619 + struct hpsa_scsi_dev_t *dev, 2620 + unsigned char *scsi3addr) 2621 + { 2622 + int i; 2623 + bool match = false; 2624 + struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; 2625 + struct hpsa_tmf_struct *ac = (struct hpsa_tmf_struct *) c2; 2626 + 2627 + if (hpsa_is_cmd_idle(c)) 2628 + return false; 2629 + 2630 + switch (c->cmd_type) { 2631 + case CMD_SCSI: 2632 + case CMD_IOCTL_PEND: 2633 + match = !memcmp(scsi3addr, &c->Header.LUN.LunAddrBytes, 2634 + sizeof(c->Header.LUN.LunAddrBytes)); 2635 + break; 2636 + 2637 + case CMD_IOACCEL1: 2638 + case CMD_IOACCEL2: 2639 + if (c->phys_disk == dev) { 2640 + /* HBA mode match */ 2641 + match = true; 2642 + } else { 2643 + /* Possible RAID mode -- check each phys dev. */ 2644 + /* FIXME: Do we need to take out a lock here? If 2645 + * so, we could just call hpsa_get_pdisk_of_ioaccel2() 2646 + * instead. */ 2647 + for (i = 0; i < dev->nphysical_disks && !match; i++) { 2648 + /* FIXME: an alternate test might be 2649 + * 2650 + * match = dev->phys_disk[i]->ioaccel_handle 2651 + * == c2->scsi_nexus; */ 2652 + match = dev->phys_disk[i] == c->phys_disk; 2653 + } 2654 + } 2655 + break; 2656 + 2657 + case IOACCEL2_TMF: 2658 + for (i = 0; i < dev->nphysical_disks && !match; i++) { 2659 + match = dev->phys_disk[i]->ioaccel_handle == 2660 + le32_to_cpu(ac->it_nexus); 2661 + } 2662 + break; 2663 + 2664 + case 0: /* The command is in the middle of being initialized. */ 2665 + match = false; 2666 + break; 2667 + 2668 + default: 2669 + dev_err(&h->pdev->dev, "unexpected cmd_type: %d\n", 2670 + c->cmd_type); 2671 + BUG(); 2672 + } 2673 + 2674 + return match; 2675 + } 2676 + 2677 + static int hpsa_do_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, 2678 + unsigned char *scsi3addr, u8 reset_type, int reply_queue) 2679 + { 2680 + int i; 2681 + int rc = 0; 2682 + 2683 + /* We can really only handle one reset at a time */ 2684 + if (mutex_lock_interruptible(&h->reset_mutex) == -EINTR) { 2685 + dev_warn(&h->pdev->dev, "concurrent reset wait interrupted.\n"); 2686 + return -EINTR; 2687 + } 2688 + 2689 + BUG_ON(atomic_read(&dev->reset_cmds_out) != 0); 2690 + 2691 + for (i = 0; i < h->nr_cmds; i++) { 2692 + struct CommandList *c = h->cmd_pool + i; 2693 + int refcount = atomic_inc_return(&c->refcount); 2694 + 2695 + if (refcount > 1 && hpsa_cmd_dev_match(h, c, dev, scsi3addr)) { 2696 + unsigned long flags; 2697 + 2698 + /* 2699 + * Mark the target command as having a reset pending, 2700 + * then lock a lock so that the command cannot complete 2701 + * while we're considering it. If the command is not 2702 + * idle then count it; otherwise revoke the event. 2703 + */ 2704 + c->reset_pending = dev; 2705 + spin_lock_irqsave(&h->lock, flags); /* Implied MB */ 2706 + if (!hpsa_is_cmd_idle(c)) 2707 + atomic_inc(&dev->reset_cmds_out); 2708 + else 2709 + c->reset_pending = NULL; 2710 + spin_unlock_irqrestore(&h->lock, flags); 2711 + } 2712 + 2713 + cmd_free(h, c); 2714 + } 2715 + 2716 + rc = hpsa_send_reset(h, scsi3addr, reset_type, reply_queue); 2717 + if (!rc) 2718 + wait_event(h->event_sync_wait_queue, 2719 + atomic_read(&dev->reset_cmds_out) == 0 || 2720 + lockup_detected(h)); 2721 + 2722 + if (unlikely(lockup_detected(h))) { 2723 + dev_warn(&h->pdev->dev, 2724 + "Controller lockup detected during reset wait\n"); 2725 + mutex_unlock(&h->reset_mutex); 2726 + rc = -ENODEV; 2727 + } 2728 + 2729 + if (unlikely(rc)) 2730 + atomic_set(&dev->reset_cmds_out, 0); 2731 + 2732 + mutex_unlock(&h->reset_mutex); 2642 2733 return rc; 2643 2734 } 2644 2735 ··· 3610 3465 else 3611 3466 dev->queue_depth = DRIVE_QUEUE_DEPTH; /* conservative */ 3612 3467 atomic_set(&dev->ioaccel_cmds_out, 0); 3468 + atomic_set(&dev->reset_cmds_out, 0); 3613 3469 } 3614 3470 3615 3471 static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno) ··· 4750 4604 cmd->result = DID_NO_CONNECT << 16; 4751 4605 return hpsa_cmd_free_and_done(c->h, c, cmd); 4752 4606 } 4607 + if (c->reset_pending) 4608 + return hpsa_cmd_resolve_and_free(c->h, c); 4753 4609 if (c->abort_pending) 4754 4610 return hpsa_cmd_abort_and_free(c->h, c, cmd); 4755 4611 if (c->cmd_type == CMD_IOACCEL2) { ··· 5114 4966 5115 4967 dev = scsicmd->device->hostdata; 5116 4968 if (!dev) { 5117 - dev_err(&h->pdev->dev, "hpsa_eh_device_reset_handler: " 5118 - "device lookup failed.\n"); 4969 + dev_err(&h->pdev->dev, "%s: device lookup failed\n", __func__); 5119 4970 return FAILED; 5120 4971 } 5121 4972 ··· 5134 4987 return FAILED; 5135 4988 } 5136 4989 4990 + /* Do not attempt on controller */ 4991 + if (is_hba_lunid(dev->scsi3addr)) 4992 + return SUCCESS; 4993 + 5137 4994 hpsa_show_dev_msg(KERN_WARNING, h, dev, "resetting"); 5138 4995 5139 4996 /* send a reset to the SCSI LUN which the command was sent to */ 5140 - rc = hpsa_send_reset(h, dev->scsi3addr, HPSA_RESET_TYPE_LUN, 5141 - DEFAULT_REPLY_QUEUE); 5142 - if (rc == 0) 5143 - return SUCCESS; 5144 - 5145 - dev_warn(&h->pdev->dev, 5146 - "scsi %d:%d:%d:%d reset failed\n", 5147 - h->scsi_host->host_no, dev->bus, dev->target, dev->lun); 5148 - return FAILED; 4997 + rc = hpsa_do_reset(h, dev, dev->scsi3addr, HPSA_RESET_TYPE_LUN, 4998 + DEFAULT_REPLY_QUEUE); 4999 + sprintf(msg, "reset %s", rc == 0 ? "completed successfully" : "failed"); 5000 + hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); 5001 + return rc == 0 ? SUCCESS : FAILED; 5149 5002 } 5150 5003 5151 5004 static void swizzle_abort_tag(u8 *tag) ··· 5325 5178 "Reset as abort: Resetting physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", 5326 5179 psa[0], psa[1], psa[2], psa[3], 5327 5180 psa[4], psa[5], psa[6], psa[7]); 5328 - rc = hpsa_send_reset(h, psa, HPSA_RESET_TYPE_TARGET, reply_queue); 5181 + rc = hpsa_do_reset(h, dev, psa, HPSA_RESET_TYPE_TARGET, reply_queue); 5329 5182 if (rc != 0) { 5330 5183 dev_warn(&h->pdev->dev, 5331 5184 "Reset as abort: Failed on physical device at scsi3addr 0x%02x%02x%02x%02x%02x%02x%02x%02x\n", ··· 5567 5420 return FAILED; 5568 5421 } 5569 5422 dev_info(&h->pdev->dev, "%s SENT, SUCCESS\n", msg); 5570 - wait_event(h->abort_sync_wait_queue, 5423 + wait_event(h->event_sync_wait_queue, 5571 5424 abort->scsi_cmd != sc || lockup_detected(h)); 5572 5425 cmd_free(h, abort); 5573 5426 return !lockup_detected(h) ? SUCCESS : FAILED; ··· 7981 7834 goto clean5; /* cmd, irq, shost, pci, lu, aer/h */ 7982 7835 init_waitqueue_head(&h->scan_wait_queue); 7983 7836 init_waitqueue_head(&h->abort_cmd_wait_queue); 7984 - init_waitqueue_head(&h->abort_sync_wait_queue); 7837 + init_waitqueue_head(&h->event_sync_wait_queue); 7838 + mutex_init(&h->reset_mutex); 7985 7839 h->scan_finished = 1; /* no scan currently in progress */ 7986 7840 7987 7841 pci_set_drvdata(pdev, h);
+4 -1
drivers/scsi/hpsa.h
··· 47 47 unsigned char raid_level; /* from inquiry page 0xC1 */ 48 48 unsigned char volume_offline; /* discovered via TUR or VPD */ 49 49 u16 queue_depth; /* max queue_depth for this device */ 50 + atomic_t reset_cmds_out; /* Count of commands to-be affected */ 50 51 atomic_t ioaccel_cmds_out; /* Only used for physical devices 51 52 * counts commands sent to physical 52 53 * device via "ioaccel" path. ··· 71 70 * devices in order to honor physical device queue depth limits. 72 71 */ 73 72 struct hpsa_scsi_dev_t *phys_disk[RAID_MAP_MAX_ENTRIES]; 73 + int nphysical_disks; 74 74 int supports_aborts; 75 75 #define HPSA_DO_NOT_EXPOSE 0x0 76 76 #define HPSA_SG_ATTACH 0x1 ··· 268 266 struct workqueue_struct *rescan_ctlr_wq; 269 267 atomic_t abort_cmds_available; 270 268 wait_queue_head_t abort_cmd_wait_queue; 271 - wait_queue_head_t abort_sync_wait_queue; 269 + wait_queue_head_t event_sync_wait_queue; 270 + struct mutex reset_mutex; 272 271 }; 273 272 274 273 struct offline_device_entry {
+1
drivers/scsi/hpsa_cmd.h
··· 441 441 struct hpsa_scsi_dev_t *phys_disk; 442 442 443 443 int abort_pending; 444 + struct hpsa_scsi_dev_t *reset_pending; 444 445 atomic_t refcount; /* Must be last to avoid memset in hpsa_cmd_init() */ 445 446 } __aligned(COMMANDLIST_ALIGNMENT); 446 447