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

scsi: hpsa: correct device resets

Correct a race condition that occurs between the reset handler and the
completion handler. There are times when the wait_event condition is
never met due to this race condition and the reset never completes.

The reset_pending field is NULL initially.

t Reset Handler Thread Completion Thread
-- -------------------- -----------------
t1 if (c->reset_pending)
t2 c->reset_pending = dev; if (atomic_dev_and_test(counter))
t3 atomic_inc(counter) wait_up_all(event_sync_wait_queue)
t4
t5 wait_event(...counter == 0)

Kernel.org Bugzilla:
https://bugzilla.kernel.org/show_bug.cgi?id=1994350
Bug 199435 - HPSA + P420i resetting logical Direct-Access
never complete

Reviewed-by: Justin Lindley <justin.lindley@microsemi.com>
Reviewed-by: David Carroll <david.carroll@microsemi.com>
Reviewed-by: Scott Teel <scott.teel@microsemi.com>
Signed-off-by: Don Brace <don.brace@microsemi.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Don Brace and committed by
Martin K. Petersen
c5dfd106 9e33f0d5

+88 -90
+85 -88
drivers/scsi/hpsa.c
··· 346 346 return c->scsi_cmd == SCSI_CMD_IDLE; 347 347 } 348 348 349 - static inline bool hpsa_is_pending_event(struct CommandList *c) 350 - { 351 - return c->reset_pending; 352 - } 353 - 354 349 /* extract sense key, asc, and ascq from sense data. -1 means invalid. */ 355 350 static void decode_sense_data(const u8 *sense_data, int sense_data_len, 356 351 u8 *sense_key, u8 *asc, u8 *ascq) ··· 1141 1146 { 1142 1147 dial_down_lockup_detection_during_fw_flash(h, c); 1143 1148 atomic_inc(&h->commands_outstanding); 1149 + if (c->device) 1150 + atomic_inc(&c->device->commands_outstanding); 1144 1151 1145 1152 reply_queue = h->reply_map[raw_smp_processor_id()]; 1146 1153 switch (c->cmd_type) { ··· 1166 1169 1167 1170 static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) 1168 1171 { 1169 - if (unlikely(hpsa_is_pending_event(c))) 1170 - return finish_cmd(c); 1171 - 1172 1172 __enqueue_cmd_and_start_io(h, c, DEFAULT_REPLY_QUEUE); 1173 1173 } 1174 1174 ··· 2428 2434 break; 2429 2435 } 2430 2436 2437 + if (dev->in_reset) 2438 + retry = 0; 2439 + 2431 2440 return retry; /* retry on raid path? */ 2432 2441 } 2433 2442 2434 2443 static void hpsa_cmd_resolve_events(struct ctlr_info *h, 2435 2444 struct CommandList *c) 2436 2445 { 2437 - bool do_wake = false; 2446 + struct hpsa_scsi_dev_t *dev = c->device; 2438 2447 2439 2448 /* 2440 2449 * Reset c->scsi_cmd here so that the reset handler will know ··· 2446 2449 */ 2447 2450 c->scsi_cmd = SCSI_CMD_IDLE; 2448 2451 mb(); /* Declare command idle before checking for pending events. */ 2449 - if (c->reset_pending) { 2450 - unsigned long flags; 2451 - struct hpsa_scsi_dev_t *dev; 2452 - 2453 - /* 2454 - * There appears to be a reset pending; lock the lock and 2455 - * reconfirm. If so, then decrement the count of outstanding 2456 - * commands and wake the reset command if this is the last one. 2457 - */ 2458 - spin_lock_irqsave(&h->lock, flags); 2459 - dev = c->reset_pending; /* Re-fetch under the lock. */ 2460 - if (dev && atomic_dec_and_test(&dev->reset_cmds_out)) 2461 - do_wake = true; 2462 - c->reset_pending = NULL; 2463 - spin_unlock_irqrestore(&h->lock, flags); 2452 + if (dev) { 2453 + atomic_dec(&dev->commands_outstanding); 2454 + if (dev->in_reset && 2455 + atomic_read(&dev->commands_outstanding) <= 0) 2456 + wake_up_all(&h->event_sync_wait_queue); 2464 2457 } 2465 - 2466 - if (do_wake) 2467 - wake_up_all(&h->event_sync_wait_queue); 2468 2458 } 2469 2459 2470 2460 static void hpsa_cmd_resolve_and_free(struct ctlr_info *h, ··· 2498 2514 IOACCEL2_STATUS_SR_IOACCEL_DISABLED) { 2499 2515 dev->offload_enabled = 0; 2500 2516 dev->offload_to_be_enabled = 0; 2517 + } 2518 + 2519 + if (dev->in_reset) { 2520 + cmd->result = DID_RESET << 16; 2521 + return hpsa_cmd_free_and_done(h, c, cmd); 2501 2522 } 2502 2523 2503 2524 return hpsa_retry_cmd(h, c); ··· 2609 2620 cmd->result = DID_NO_CONNECT << 16; 2610 2621 return hpsa_cmd_free_and_done(h, cp, cmd); 2611 2622 } 2612 - 2613 - if ((unlikely(hpsa_is_pending_event(cp)))) 2614 - if (cp->reset_pending) 2615 - return hpsa_cmd_free_and_done(h, cp, cmd); 2616 2623 2617 2624 if (cp->cmd_type == CMD_IOACCEL2) 2618 2625 return process_ioaccel2_completion(h, cp, cmd, dev); ··· 3059 3074 return rc; 3060 3075 } 3061 3076 3062 - static int hpsa_send_reset(struct ctlr_info *h, unsigned char *scsi3addr, 3077 + static int hpsa_send_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, 3063 3078 u8 reset_type, int reply_queue) 3064 3079 { 3065 3080 int rc = IO_OK; ··· 3067 3082 struct ErrorInfo *ei; 3068 3083 3069 3084 c = cmd_alloc(h); 3070 - 3085 + c->device = dev; 3071 3086 3072 3087 /* fill_cmd can't fail here, no data buffer to map. */ 3073 - (void) fill_cmd(c, reset_type, h, NULL, 0, 0, 3074 - scsi3addr, TYPE_MSG); 3088 + (void) fill_cmd(c, reset_type, h, NULL, 0, 0, dev->scsi3addr, TYPE_MSG); 3075 3089 rc = hpsa_scsi_do_simple_cmd(h, c, reply_queue, NO_TIMEOUT); 3076 3090 if (rc) { 3077 3091 dev_warn(&h->pdev->dev, "Failed to send reset command\n"); ··· 3148 3164 } 3149 3165 3150 3166 static int hpsa_do_reset(struct ctlr_info *h, struct hpsa_scsi_dev_t *dev, 3151 - unsigned char *scsi3addr, u8 reset_type, int reply_queue) 3167 + u8 reset_type, int reply_queue) 3152 3168 { 3153 - int i; 3154 3169 int rc = 0; 3155 3170 3156 3171 /* We can really only handle one reset at a time */ ··· 3158 3175 return -EINTR; 3159 3176 } 3160 3177 3161 - BUG_ON(atomic_read(&dev->reset_cmds_out) != 0); 3162 - 3163 - for (i = 0; i < h->nr_cmds; i++) { 3164 - struct CommandList *c = h->cmd_pool + i; 3165 - int refcount = atomic_inc_return(&c->refcount); 3166 - 3167 - if (refcount > 1 && hpsa_cmd_dev_match(h, c, dev, scsi3addr)) { 3168 - unsigned long flags; 3169 - 3170 - /* 3171 - * Mark the target command as having a reset pending, 3172 - * then lock a lock so that the command cannot complete 3173 - * while we're considering it. If the command is not 3174 - * idle then count it; otherwise revoke the event. 3175 - */ 3176 - c->reset_pending = dev; 3177 - spin_lock_irqsave(&h->lock, flags); /* Implied MB */ 3178 - if (!hpsa_is_cmd_idle(c)) 3179 - atomic_inc(&dev->reset_cmds_out); 3180 - else 3181 - c->reset_pending = NULL; 3182 - spin_unlock_irqrestore(&h->lock, flags); 3183 - } 3184 - 3185 - cmd_free(h, c); 3186 - } 3187 - 3188 - rc = hpsa_send_reset(h, scsi3addr, reset_type, reply_queue); 3189 - if (!rc) 3178 + rc = hpsa_send_reset(h, dev, reset_type, reply_queue); 3179 + if (!rc) { 3180 + /* incremented by sending the reset request */ 3181 + atomic_dec(&dev->commands_outstanding); 3190 3182 wait_event(h->event_sync_wait_queue, 3191 - atomic_read(&dev->reset_cmds_out) == 0 || 3183 + atomic_read(&dev->commands_outstanding) <= 0 || 3192 3184 lockup_detected(h)); 3185 + } 3193 3186 3194 3187 if (unlikely(lockup_detected(h))) { 3195 3188 dev_warn(&h->pdev->dev, ··· 3173 3214 rc = -ENODEV; 3174 3215 } 3175 3216 3176 - if (unlikely(rc)) 3177 - atomic_set(&dev->reset_cmds_out, 0); 3178 - else 3179 - rc = wait_for_device_to_become_ready(h, scsi3addr, 0); 3217 + if (!rc) 3218 + rc = wait_for_device_to_become_ready(h, dev->scsi3addr, 0); 3180 3219 3181 3220 mutex_unlock(&h->reset_mutex); 3182 3221 return rc; ··· 4803 4846 4804 4847 c->phys_disk = dev; 4805 4848 4849 + if (dev->in_reset) 4850 + return -1; 4851 + 4806 4852 return hpsa_scsi_ioaccel_queue_command(h, c, dev->ioaccel_handle, 4807 4853 cmd->cmnd, cmd->cmd_len, dev->scsi3addr, dev); 4808 4854 } ··· 4991 5031 } else 4992 5032 cp->sg_count = (u8) use_sg; 4993 5033 5034 + if (phys_disk->in_reset) { 5035 + cmd->result = DID_RESET << 16; 5036 + return -1; 5037 + } 5038 + 4994 5039 enqueue_cmd_and_start_io(h, c); 4995 5040 return 0; 4996 5041 } ··· 5011 5046 return -1; 5012 5047 5013 5048 if (!c->scsi_cmd->device->hostdata) 5049 + return -1; 5050 + 5051 + if (phys_disk->in_reset) 5014 5052 return -1; 5015 5053 5016 5054 /* Try to honor the device's queue depth */ ··· 5097 5129 int offload_to_mirror; 5098 5130 5099 5131 if (!dev) 5132 + return -1; 5133 + 5134 + if (dev->in_reset) 5100 5135 return -1; 5101 5136 5102 5137 /* check for valid opcode, get LBA and block count */ ··· 5406 5435 */ 5407 5436 static int hpsa_ciss_submit(struct ctlr_info *h, 5408 5437 struct CommandList *c, struct scsi_cmnd *cmd, 5409 - unsigned char scsi3addr[]) 5438 + struct hpsa_scsi_dev_t *dev) 5410 5439 { 5411 5440 cmd->host_scribble = (unsigned char *) c; 5412 5441 c->cmd_type = CMD_SCSI; 5413 5442 c->scsi_cmd = cmd; 5414 5443 c->Header.ReplyQueue = 0; /* unused in simple mode */ 5415 - memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8); 5444 + memcpy(&c->Header.LUN.LunAddrBytes[0], &dev->scsi3addr[0], 8); 5416 5445 c->Header.tag = cpu_to_le64((c->cmdindex << DIRECT_LOOKUP_SHIFT)); 5417 5446 5418 5447 /* Fill in the request block... */ ··· 5463 5492 hpsa_cmd_resolve_and_free(h, c); 5464 5493 return SCSI_MLQUEUE_HOST_BUSY; 5465 5494 } 5495 + 5496 + if (dev->in_reset) { 5497 + hpsa_cmd_resolve_and_free(h, c); 5498 + return SCSI_MLQUEUE_HOST_BUSY; 5499 + } 5500 + 5466 5501 enqueue_cmd_and_start_io(h, c); 5467 5502 /* the cmd'll come back via intr handler in complete_scsi_command() */ 5468 5503 return 0; ··· 5520 5543 } 5521 5544 5522 5545 static int hpsa_ioaccel_submit(struct ctlr_info *h, 5523 - struct CommandList *c, struct scsi_cmnd *cmd, 5524 - unsigned char *scsi3addr) 5546 + struct CommandList *c, struct scsi_cmnd *cmd) 5525 5547 { 5526 5548 struct hpsa_scsi_dev_t *dev = cmd->device->hostdata; 5527 5549 int rc = IO_ACCEL_INELIGIBLE; 5528 5550 5529 5551 if (!dev) 5552 + return SCSI_MLQUEUE_HOST_BUSY; 5553 + 5554 + if (dev->in_reset) 5530 5555 return SCSI_MLQUEUE_HOST_BUSY; 5531 5556 5532 5557 if (hpsa_simple_mode) ··· 5566 5587 cmd->result = DID_NO_CONNECT << 16; 5567 5588 return hpsa_cmd_free_and_done(c->h, c, cmd); 5568 5589 } 5569 - if (c->reset_pending) 5590 + 5591 + if (dev->in_reset) { 5592 + cmd->result = DID_RESET << 16; 5570 5593 return hpsa_cmd_free_and_done(c->h, c, cmd); 5594 + } 5595 + 5571 5596 if (c->cmd_type == CMD_IOACCEL2) { 5572 5597 struct ctlr_info *h = c->h; 5573 5598 struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex]; ··· 5579 5596 5580 5597 if (c2->error_data.serv_response == 5581 5598 IOACCEL2_STATUS_SR_TASK_COMP_SET_FULL) { 5582 - rc = hpsa_ioaccel_submit(h, c, cmd, dev->scsi3addr); 5599 + rc = hpsa_ioaccel_submit(h, c, cmd); 5583 5600 if (rc == 0) 5584 5601 return; 5585 5602 if (rc == SCSI_MLQUEUE_HOST_BUSY) { ··· 5595 5612 } 5596 5613 } 5597 5614 hpsa_cmd_partial_init(c->h, c->cmdindex, c); 5598 - if (hpsa_ciss_submit(c->h, c, cmd, dev->scsi3addr)) { 5615 + if (hpsa_ciss_submit(c->h, c, cmd, dev)) { 5599 5616 /* 5600 5617 * If we get here, it means dma mapping failed. Try 5601 5618 * again via scsi mid layer, which will then get ··· 5614 5631 { 5615 5632 struct ctlr_info *h; 5616 5633 struct hpsa_scsi_dev_t *dev; 5617 - unsigned char scsi3addr[8]; 5618 5634 struct CommandList *c; 5619 5635 int rc = 0; 5620 5636 ··· 5635 5653 return 0; 5636 5654 } 5637 5655 5638 - memcpy(scsi3addr, dev->scsi3addr, sizeof(scsi3addr)); 5639 - 5640 5656 if (unlikely(lockup_detected(h))) { 5641 5657 cmd->result = DID_NO_CONNECT << 16; 5642 5658 cmd->scsi_done(cmd); 5643 5659 return 0; 5644 5660 } 5661 + 5662 + if (dev->in_reset) 5663 + return SCSI_MLQUEUE_DEVICE_BUSY; 5664 + 5645 5665 c = cmd_tagged_alloc(h, cmd); 5646 5666 if (c == NULL) 5647 5667 return SCSI_MLQUEUE_DEVICE_BUSY; ··· 5655 5671 if (likely(cmd->retries == 0 && 5656 5672 !blk_rq_is_passthrough(cmd->request) && 5657 5673 h->acciopath_status)) { 5658 - rc = hpsa_ioaccel_submit(h, c, cmd, scsi3addr); 5674 + rc = hpsa_ioaccel_submit(h, c, cmd); 5659 5675 if (rc == 0) 5660 5676 return 0; 5661 5677 if (rc == SCSI_MLQUEUE_HOST_BUSY) { ··· 5663 5679 return SCSI_MLQUEUE_HOST_BUSY; 5664 5680 } 5665 5681 } 5666 - return hpsa_ciss_submit(h, c, cmd, scsi3addr); 5682 + return hpsa_ciss_submit(h, c, cmd, dev); 5667 5683 } 5668 5684 5669 5685 static void hpsa_scan_complete(struct ctlr_info *h) ··· 5945 5961 static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd) 5946 5962 { 5947 5963 int rc = SUCCESS; 5964 + int i; 5948 5965 struct ctlr_info *h; 5949 5966 struct hpsa_scsi_dev_t *dev; 5950 5967 u8 reset_type; ··· 6013 6028 reset_type == HPSA_DEVICE_RESET_MSG ? "logical " : "physical "); 6014 6029 hpsa_show_dev_msg(KERN_WARNING, h, dev, msg); 6015 6030 6031 + /* 6032 + * wait to see if any commands will complete before sending reset 6033 + */ 6034 + dev->in_reset = true; /* block any new cmds from OS for this device */ 6035 + for (i = 0; i < 10; i++) { 6036 + if (atomic_read(&dev->commands_outstanding) > 0) 6037 + msleep(1000); 6038 + else 6039 + break; 6040 + } 6041 + 6016 6042 /* send a reset to the SCSI LUN which the command was sent to */ 6017 - rc = hpsa_do_reset(h, dev, dev->scsi3addr, reset_type, 6018 - DEFAULT_REPLY_QUEUE); 6043 + rc = hpsa_do_reset(h, dev, reset_type, DEFAULT_REPLY_QUEUE); 6019 6044 if (rc == 0) 6020 6045 rc = SUCCESS; 6021 6046 else ··· 6039 6044 return_reset_status: 6040 6045 spin_lock_irqsave(&h->reset_lock, flags); 6041 6046 h->reset_in_progress = 0; 6047 + if (dev) 6048 + dev->in_reset = false; 6042 6049 spin_unlock_irqrestore(&h->reset_lock, flags); 6043 6050 return rc; 6044 6051 } ··· 6154 6157 break; /* it's ours now. */ 6155 6158 } 6156 6159 hpsa_cmd_partial_init(h, i, c); 6160 + c->device = NULL; 6157 6161 return c; 6158 6162 } 6159 6163 ··· 6608 6610 } 6609 6611 } 6610 6612 6611 - static void hpsa_send_host_reset(struct ctlr_info *h, unsigned char *scsi3addr, 6612 - u8 reset_type) 6613 + static void hpsa_send_host_reset(struct ctlr_info *h, u8 reset_type) 6613 6614 { 6614 6615 struct CommandList *c; 6615 6616 ··· 8102 8105 static int hpsa_kdump_soft_reset(struct ctlr_info *h) 8103 8106 { 8104 8107 int rc; 8105 - hpsa_send_host_reset(h, RAID_CTLR_LUNID, HPSA_RESET_TYPE_CONTROLLER); 8108 + hpsa_send_host_reset(h, HPSA_RESET_TYPE_CONTROLLER); 8106 8109 8107 8110 dev_info(&h->pdev->dev, "Waiting for board to soft reset.\n"); 8108 8111 rc = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_NOT_READY);
+2 -1
drivers/scsi/hpsa.h
··· 76 76 unsigned char raid_level; /* from inquiry page 0xC1 */ 77 77 unsigned char volume_offline; /* discovered via TUR or VPD */ 78 78 u16 queue_depth; /* max queue_depth for this device */ 79 - atomic_t reset_cmds_out; /* Count of commands to-be affected */ 79 + atomic_t commands_outstanding; /* track commands sent to device */ 80 80 atomic_t ioaccel_cmds_out; /* Only used for physical devices 81 81 * counts commands sent to physical 82 82 * device via "ioaccel" path. 83 83 */ 84 + bool in_reset; 84 85 u32 ioaccel_handle; 85 86 u8 active_path_index; 86 87 u8 path_map;
+1 -1
drivers/scsi/hpsa_cmd.h
··· 448 448 struct hpsa_scsi_dev_t *phys_disk; 449 449 450 450 int abort_pending; 451 - struct hpsa_scsi_dev_t *reset_pending; 451 + struct hpsa_scsi_dev_t *device; 452 452 atomic_t refcount; /* Must be last to avoid memset in hpsa_cmd_init() */ 453 453 } __aligned(COMMANDLIST_ALIGNMENT); 454 454