diff options
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 122 |
1 files changed, 58 insertions, 64 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 5890e5f92d82..8b80e59c8c52 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -164,29 +164,6 @@ MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when init | |||
164 | MODULE_LICENSE("GPL"); | 164 | MODULE_LICENSE("GPL"); |
165 | MODULE_VERSION(IPR_DRIVER_VERSION); | 165 | MODULE_VERSION(IPR_DRIVER_VERSION); |
166 | 166 | ||
167 | static const char *ipr_gpdd_dev_end_states[] = { | ||
168 | "Command complete", | ||
169 | "Terminated by host", | ||
170 | "Terminated by device reset", | ||
171 | "Terminated by bus reset", | ||
172 | "Unknown", | ||
173 | "Command not started" | ||
174 | }; | ||
175 | |||
176 | static const char *ipr_gpdd_dev_bus_phases[] = { | ||
177 | "Bus free", | ||
178 | "Arbitration", | ||
179 | "Selection", | ||
180 | "Message out", | ||
181 | "Command", | ||
182 | "Message in", | ||
183 | "Data out", | ||
184 | "Data in", | ||
185 | "Status", | ||
186 | "Reselection", | ||
187 | "Unknown" | ||
188 | }; | ||
189 | |||
190 | /* A constant array of IOASCs/URCs/Error Messages */ | 167 | /* A constant array of IOASCs/URCs/Error Messages */ |
191 | static const | 168 | static const |
192 | struct ipr_error_table_t ipr_error_table[] = { | 169 | struct ipr_error_table_t ipr_error_table[] = { |
@@ -869,8 +846,8 @@ static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg, | |||
869 | 846 | ||
870 | if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) { | 847 | if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) { |
871 | if (res->sdev) { | 848 | if (res->sdev) { |
872 | res->sdev->hostdata = NULL; | ||
873 | res->del_from_ml = 1; | 849 | res->del_from_ml = 1; |
850 | res->cfgte.res_handle = IPR_INVALID_RES_HANDLE; | ||
874 | if (ioa_cfg->allow_ml_add_del) | 851 | if (ioa_cfg->allow_ml_add_del) |
875 | schedule_work(&ioa_cfg->work_q); | 852 | schedule_work(&ioa_cfg->work_q); |
876 | } else | 853 | } else |
@@ -1356,8 +1333,8 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, | |||
1356 | return; | 1333 | return; |
1357 | 1334 | ||
1358 | if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { | 1335 | if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { |
1359 | ipr_res_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, | 1336 | ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, |
1360 | "%s\n", ipr_error_table[error_index].error); | 1337 | "%s\n", ipr_error_table[error_index].error); |
1361 | } else { | 1338 | } else { |
1362 | dev_err(&ioa_cfg->pdev->dev, "%s\n", | 1339 | dev_err(&ioa_cfg->pdev->dev, "%s\n", |
1363 | ipr_error_table[error_index].error); | 1340 | ipr_error_table[error_index].error); |
@@ -2107,7 +2084,6 @@ restart: | |||
2107 | did_work = 1; | 2084 | did_work = 1; |
2108 | sdev = res->sdev; | 2085 | sdev = res->sdev; |
2109 | if (!scsi_device_get(sdev)) { | 2086 | if (!scsi_device_get(sdev)) { |
2110 | res->sdev = NULL; | ||
2111 | list_move_tail(&res->queue, &ioa_cfg->free_res_q); | 2087 | list_move_tail(&res->queue, &ioa_cfg->free_res_q); |
2112 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 2088 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
2113 | scsi_remove_device(sdev); | 2089 | scsi_remove_device(sdev); |
@@ -2124,6 +2100,7 @@ restart: | |||
2124 | bus = res->cfgte.res_addr.bus; | 2100 | bus = res->cfgte.res_addr.bus; |
2125 | target = res->cfgte.res_addr.target; | 2101 | target = res->cfgte.res_addr.target; |
2126 | lun = res->cfgte.res_addr.lun; | 2102 | lun = res->cfgte.res_addr.lun; |
2103 | res->add_to_ml = 0; | ||
2127 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 2104 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
2128 | scsi_add_device(ioa_cfg->host, bus, target, lun); | 2105 | scsi_add_device(ioa_cfg->host, bus, target, lun); |
2129 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 2106 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
@@ -3214,7 +3191,7 @@ static int ipr_slave_configure(struct scsi_device *sdev) | |||
3214 | sdev->timeout = IPR_VSET_RW_TIMEOUT; | 3191 | sdev->timeout = IPR_VSET_RW_TIMEOUT; |
3215 | blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS); | 3192 | blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS); |
3216 | } | 3193 | } |
3217 | if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)) | 3194 | if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)) |
3218 | sdev->allow_restart = 1; | 3195 | sdev->allow_restart = 1; |
3219 | scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); | 3196 | scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); |
3220 | } | 3197 | } |
@@ -3304,6 +3281,44 @@ static int ipr_eh_host_reset(struct scsi_cmnd * cmd) | |||
3304 | } | 3281 | } |
3305 | 3282 | ||
3306 | /** | 3283 | /** |
3284 | * ipr_device_reset - Reset the device | ||
3285 | * @ioa_cfg: ioa config struct | ||
3286 | * @res: resource entry struct | ||
3287 | * | ||
3288 | * This function issues a device reset to the affected device. | ||
3289 | * If the device is a SCSI device, a LUN reset will be sent | ||
3290 | * to the device first. If that does not work, a target reset | ||
3291 | * will be sent. | ||
3292 | * | ||
3293 | * Return value: | ||
3294 | * 0 on success / non-zero on failure | ||
3295 | **/ | ||
3296 | static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, | ||
3297 | struct ipr_resource_entry *res) | ||
3298 | { | ||
3299 | struct ipr_cmnd *ipr_cmd; | ||
3300 | struct ipr_ioarcb *ioarcb; | ||
3301 | struct ipr_cmd_pkt *cmd_pkt; | ||
3302 | u32 ioasc; | ||
3303 | |||
3304 | ENTER; | ||
3305 | ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); | ||
3306 | ioarcb = &ipr_cmd->ioarcb; | ||
3307 | cmd_pkt = &ioarcb->cmd_pkt; | ||
3308 | |||
3309 | ioarcb->res_handle = res->cfgte.res_handle; | ||
3310 | cmd_pkt->request_type = IPR_RQTYPE_IOACMD; | ||
3311 | cmd_pkt->cdb[0] = IPR_RESET_DEVICE; | ||
3312 | |||
3313 | ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); | ||
3314 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | ||
3315 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); | ||
3316 | |||
3317 | LEAVE; | ||
3318 | return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0); | ||
3319 | } | ||
3320 | |||
3321 | /** | ||
3307 | * ipr_eh_dev_reset - Reset the device | 3322 | * ipr_eh_dev_reset - Reset the device |
3308 | * @scsi_cmd: scsi command struct | 3323 | * @scsi_cmd: scsi command struct |
3309 | * | 3324 | * |
@@ -3319,8 +3334,7 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) | |||
3319 | struct ipr_cmnd *ipr_cmd; | 3334 | struct ipr_cmnd *ipr_cmd; |
3320 | struct ipr_ioa_cfg *ioa_cfg; | 3335 | struct ipr_ioa_cfg *ioa_cfg; |
3321 | struct ipr_resource_entry *res; | 3336 | struct ipr_resource_entry *res; |
3322 | struct ipr_cmd_pkt *cmd_pkt; | 3337 | int rc; |
3323 | u32 ioasc; | ||
3324 | 3338 | ||
3325 | ENTER; | 3339 | ENTER; |
3326 | ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata; | 3340 | ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata; |
@@ -3347,25 +3361,12 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) | |||
3347 | } | 3361 | } |
3348 | 3362 | ||
3349 | res->resetting_device = 1; | 3363 | res->resetting_device = 1; |
3350 | 3364 | scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n"); | |
3351 | ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); | 3365 | rc = ipr_device_reset(ioa_cfg, res); |
3352 | |||
3353 | ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle; | ||
3354 | cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; | ||
3355 | cmd_pkt->request_type = IPR_RQTYPE_IOACMD; | ||
3356 | cmd_pkt->cdb[0] = IPR_RESET_DEVICE; | ||
3357 | |||
3358 | ipr_sdev_err(scsi_cmd->device, "Resetting device\n"); | ||
3359 | ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); | ||
3360 | |||
3361 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | ||
3362 | |||
3363 | res->resetting_device = 0; | 3366 | res->resetting_device = 0; |
3364 | 3367 | ||
3365 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); | ||
3366 | |||
3367 | LEAVE; | 3368 | LEAVE; |
3368 | return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS); | 3369 | return (rc ? FAILED : SUCCESS); |
3369 | } | 3370 | } |
3370 | 3371 | ||
3371 | static int ipr_eh_dev_reset(struct scsi_cmnd * cmd) | 3372 | static int ipr_eh_dev_reset(struct scsi_cmnd * cmd) |
@@ -3440,7 +3441,7 @@ static void ipr_abort_timeout(struct ipr_cmnd *ipr_cmd) | |||
3440 | return; | 3441 | return; |
3441 | } | 3442 | } |
3442 | 3443 | ||
3443 | ipr_sdev_err(ipr_cmd->u.sdev, "Abort timed out. Resetting bus\n"); | 3444 | sdev_printk(KERN_ERR, ipr_cmd->u.sdev, "Abort timed out. Resetting bus.\n"); |
3444 | reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); | 3445 | reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); |
3445 | ipr_cmd->sibling = reset_cmd; | 3446 | ipr_cmd->sibling = reset_cmd; |
3446 | reset_cmd->sibling = ipr_cmd; | 3447 | reset_cmd->sibling = ipr_cmd; |
@@ -3504,7 +3505,8 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) | |||
3504 | cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS; | 3505 | cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS; |
3505 | ipr_cmd->u.sdev = scsi_cmd->device; | 3506 | ipr_cmd->u.sdev = scsi_cmd->device; |
3506 | 3507 | ||
3507 | ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]); | 3508 | scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n", |
3509 | scsi_cmd->cmnd[0]); | ||
3508 | ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); | 3510 | ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); |
3509 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 3511 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); |
3510 | 3512 | ||
@@ -3815,8 +3817,8 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) | |||
3815 | 3817 | ||
3816 | if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { | 3818 | if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { |
3817 | scsi_cmd->result |= (DID_ERROR << 16); | 3819 | scsi_cmd->result |= (DID_ERROR << 16); |
3818 | ipr_sdev_err(scsi_cmd->device, | 3820 | scmd_printk(KERN_ERR, scsi_cmd, |
3819 | "Request Sense failed with IOASC: 0x%08X\n", ioasc); | 3821 | "Request Sense failed with IOASC: 0x%08X\n", ioasc); |
3820 | } else { | 3822 | } else { |
3821 | memcpy(scsi_cmd->sense_buffer, ipr_cmd->sense_buffer, | 3823 | memcpy(scsi_cmd->sense_buffer, ipr_cmd->sense_buffer, |
3822 | SCSI_SENSE_BUFFERSIZE); | 3824 | SCSI_SENSE_BUFFERSIZE); |
@@ -3938,6 +3940,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd) | |||
3938 | * ipr_dump_ioasa - Dump contents of IOASA | 3940 | * ipr_dump_ioasa - Dump contents of IOASA |
3939 | * @ioa_cfg: ioa config struct | 3941 | * @ioa_cfg: ioa config struct |
3940 | * @ipr_cmd: ipr command struct | 3942 | * @ipr_cmd: ipr command struct |
3943 | * @res: resource entry struct | ||
3941 | * | 3944 | * |
3942 | * This function is invoked by the interrupt handler when ops | 3945 | * This function is invoked by the interrupt handler when ops |
3943 | * fail. It will log the IOASA if appropriate. Only called | 3946 | * fail. It will log the IOASA if appropriate. Only called |
@@ -3947,7 +3950,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd) | |||
3947 | * none | 3950 | * none |
3948 | **/ | 3951 | **/ |
3949 | static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, | 3952 | static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, |
3950 | struct ipr_cmnd *ipr_cmd) | 3953 | struct ipr_cmnd *ipr_cmd, struct ipr_resource_entry *res) |
3951 | { | 3954 | { |
3952 | int i; | 3955 | int i; |
3953 | u16 data_len; | 3956 | u16 data_len; |
@@ -3975,16 +3978,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, | |||
3975 | return; | 3978 | return; |
3976 | } | 3979 | } |
3977 | 3980 | ||
3978 | ipr_sdev_err(ipr_cmd->scsi_cmd->device, "%s\n", | 3981 | ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error); |
3979 | ipr_error_table[error_index].error); | ||
3980 | |||
3981 | if ((ioasa->u.gpdd.end_state <= ARRAY_SIZE(ipr_gpdd_dev_end_states)) && | ||
3982 | (ioasa->u.gpdd.bus_phase <= ARRAY_SIZE(ipr_gpdd_dev_bus_phases))) { | ||
3983 | ipr_sdev_err(ipr_cmd->scsi_cmd->device, | ||
3984 | "Device End state: %s Phase: %s\n", | ||
3985 | ipr_gpdd_dev_end_states[ioasa->u.gpdd.end_state], | ||
3986 | ipr_gpdd_dev_bus_phases[ioasa->u.gpdd.bus_phase]); | ||
3987 | } | ||
3988 | 3982 | ||
3989 | if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len)) | 3983 | if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len)) |
3990 | data_len = sizeof(struct ipr_ioasa); | 3984 | data_len = sizeof(struct ipr_ioasa); |
@@ -4141,7 +4135,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, | |||
4141 | } | 4135 | } |
4142 | 4136 | ||
4143 | if (ipr_is_gscsi(res)) | 4137 | if (ipr_is_gscsi(res)) |
4144 | ipr_dump_ioasa(ioa_cfg, ipr_cmd); | 4138 | ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); |
4145 | else | 4139 | else |
4146 | ipr_gen_sense(ipr_cmd); | 4140 | ipr_gen_sense(ipr_cmd); |
4147 | 4141 | ||
@@ -4540,7 +4534,7 @@ static int ipr_set_supported_devs(struct ipr_cmnd *ipr_cmd) | |||
4540 | ipr_cmd->job_step = ipr_ioa_reset_done; | 4534 | ipr_cmd->job_step = ipr_ioa_reset_done; |
4541 | 4535 | ||
4542 | list_for_each_entry_continue(res, &ioa_cfg->used_res_q, queue) { | 4536 | list_for_each_entry_continue(res, &ioa_cfg->used_res_q, queue) { |
4543 | if (!IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)) | 4537 | if (!ipr_is_scsi_disk(res)) |
4544 | continue; | 4538 | continue; |
4545 | 4539 | ||
4546 | ipr_cmd->u.res = res; | 4540 | ipr_cmd->u.res = res; |
@@ -4980,7 +4974,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) | |||
4980 | list_for_each_entry_safe(res, temp, &old_res, queue) { | 4974 | list_for_each_entry_safe(res, temp, &old_res, queue) { |
4981 | if (res->sdev) { | 4975 | if (res->sdev) { |
4982 | res->del_from_ml = 1; | 4976 | res->del_from_ml = 1; |
4983 | res->sdev->hostdata = NULL; | 4977 | res->cfgte.res_handle = IPR_INVALID_RES_HANDLE; |
4984 | list_move_tail(&res->queue, &ioa_cfg->used_res_q); | 4978 | list_move_tail(&res->queue, &ioa_cfg->used_res_q); |
4985 | } else { | 4979 | } else { |
4986 | list_move_tail(&res->queue, &ioa_cfg->free_res_q); | 4980 | list_move_tail(&res->queue, &ioa_cfg->free_res_q); |