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); |
