X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fipr.c;fp=drivers%2Fscsi%2Fipr.c;h=2bba5e55d7bc6110d44aa6720280e12d4b79cbe6;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=01080b3acf5e7a7f0d97cc6a409f72cb15aaa236;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 01080b3ac..2bba5e55d 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -54,6 +54,7 @@ * */ +#include #include #include #include @@ -78,6 +79,7 @@ #include #include #include +#include #include "ipr.h" /* @@ -162,6 +164,29 @@ MODULE_PARM_DESC(auto_create, "Auto-create single device RAID 0 arrays when init MODULE_LICENSE("GPL"); MODULE_VERSION(IPR_DRIVER_VERSION); +static const char *ipr_gpdd_dev_end_states[] = { + "Command complete", + "Terminated by host", + "Terminated by device reset", + "Terminated by bus reset", + "Unknown", + "Command not started" +}; + +static const char *ipr_gpdd_dev_bus_phases[] = { + "Bus free", + "Arbitration", + "Selection", + "Message out", + "Command", + "Message in", + "Data out", + "Data in", + "Status", + "Reselection", + "Unknown" +}; + /* A constant array of IOASCs/URCs/Error Messages */ static const struct ipr_error_table_t ipr_error_table[] = { @@ -844,8 +869,8 @@ static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg, if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) { if (res->sdev) { + res->sdev->hostdata = NULL; res->del_from_ml = 1; - res->cfgte.res_handle = IPR_INVALID_RES_HANDLE; if (ioa_cfg->allow_ml_add_del) schedule_work(&ioa_cfg->work_q); } else @@ -1331,8 +1356,8 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, return; if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { - ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, - "%s\n", ipr_error_table[error_index].error); + ipr_res_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr, + "%s\n", ipr_error_table[error_index].error); } else { dev_err(&ioa_cfg->pdev->dev, "%s\n", ipr_error_table[error_index].error); @@ -2082,6 +2107,7 @@ restart: did_work = 1; sdev = res->sdev; if (!scsi_device_get(sdev)) { + res->sdev = NULL; list_move_tail(&res->queue, &ioa_cfg->free_res_q); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); scsi_remove_device(sdev); @@ -2098,7 +2124,6 @@ restart: bus = res->cfgte.res_addr.bus; target = res->cfgte.res_addr.target; lun = res->cfgte.res_addr.lun; - res->add_to_ml = 0; spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); scsi_add_device(ioa_cfg->host, bus, target, lun); spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); @@ -3189,7 +3214,7 @@ static int ipr_slave_configure(struct scsi_device *sdev) sdev->timeout = IPR_VSET_RW_TIMEOUT; blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS); } - if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res)) + if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)) sdev->allow_restart = 1; scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); } @@ -3278,44 +3303,6 @@ static int ipr_eh_host_reset(struct scsi_cmnd * cmd) return rc; } -/** - * ipr_device_reset - Reset the device - * @ioa_cfg: ioa config struct - * @res: resource entry struct - * - * This function issues a device reset to the affected device. - * If the device is a SCSI device, a LUN reset will be sent - * to the device first. If that does not work, a target reset - * will be sent. - * - * Return value: - * 0 on success / non-zero on failure - **/ -static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, - struct ipr_resource_entry *res) -{ - struct ipr_cmnd *ipr_cmd; - struct ipr_ioarcb *ioarcb; - struct ipr_cmd_pkt *cmd_pkt; - u32 ioasc; - - ENTER; - ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); - ioarcb = &ipr_cmd->ioarcb; - cmd_pkt = &ioarcb->cmd_pkt; - - ioarcb->res_handle = res->cfgte.res_handle; - cmd_pkt->request_type = IPR_RQTYPE_IOACMD; - cmd_pkt->cdb[0] = IPR_RESET_DEVICE; - - ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); - ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); - list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); - - LEAVE; - return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0); -} - /** * ipr_eh_dev_reset - Reset the device * @scsi_cmd: scsi command struct @@ -3332,7 +3319,8 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) struct ipr_cmnd *ipr_cmd; struct ipr_ioa_cfg *ioa_cfg; struct ipr_resource_entry *res; - int rc; + struct ipr_cmd_pkt *cmd_pkt; + u32 ioasc; ENTER; ioa_cfg = (struct ipr_ioa_cfg *) scsi_cmd->device->host->hostdata; @@ -3359,12 +3347,25 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd) } res->resetting_device = 1; - scmd_printk(KERN_ERR, scsi_cmd, "Resetting device\n"); - rc = ipr_device_reset(ioa_cfg, res); + + ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); + + ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle; + cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; + cmd_pkt->request_type = IPR_RQTYPE_IOACMD; + cmd_pkt->cdb[0] = IPR_RESET_DEVICE; + + ipr_sdev_err(scsi_cmd->device, "Resetting device\n"); + ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); + + ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + res->resetting_device = 0; + list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); + LEAVE; - return (rc ? FAILED : SUCCESS); + return (IPR_IOASC_SENSE_KEY(ioasc) ? FAILED : SUCCESS); } static int ipr_eh_dev_reset(struct scsi_cmnd * cmd) @@ -3439,7 +3440,7 @@ static void ipr_abort_timeout(struct ipr_cmnd *ipr_cmd) return; } - sdev_printk(KERN_ERR, ipr_cmd->u.sdev, "Abort timed out. Resetting bus.\n"); + ipr_sdev_err(ipr_cmd->u.sdev, "Abort timed out. Resetting bus\n"); reset_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); ipr_cmd->sibling = reset_cmd; reset_cmd->sibling = ipr_cmd; @@ -3503,8 +3504,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) cmd_pkt->cdb[0] = IPR_CANCEL_ALL_REQUESTS; ipr_cmd->u.sdev = scsi_cmd->device; - scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n", - scsi_cmd->cmnd[0]); + ipr_sdev_err(scsi_cmd->device, "Aborting command: %02X\n", scsi_cmd->cmnd[0]); ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); @@ -3815,8 +3815,8 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { scsi_cmd->result |= (DID_ERROR << 16); - scmd_printk(KERN_ERR, scsi_cmd, - "Request Sense failed with IOASC: 0x%08X\n", ioasc); + ipr_sdev_err(scsi_cmd->device, + "Request Sense failed with IOASC: 0x%08X\n", ioasc); } else { memcpy(scsi_cmd->sense_buffer, ipr_cmd->sense_buffer, SCSI_SENSE_BUFFERSIZE); @@ -3938,7 +3938,6 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd) * ipr_dump_ioasa - Dump contents of IOASA * @ioa_cfg: ioa config struct * @ipr_cmd: ipr command struct - * @res: resource entry struct * * This function is invoked by the interrupt handler when ops * fail. It will log the IOASA if appropriate. Only called @@ -3948,7 +3947,7 @@ static void ipr_erp_cancel_all(struct ipr_cmnd *ipr_cmd) * none **/ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, - struct ipr_cmnd *ipr_cmd, struct ipr_resource_entry *res) + struct ipr_cmnd *ipr_cmd) { int i; u16 data_len; @@ -3976,7 +3975,16 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, return; } - ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error); + ipr_sdev_err(ipr_cmd->scsi_cmd->device, "%s\n", + ipr_error_table[error_index].error); + + if ((ioasa->u.gpdd.end_state <= ARRAY_SIZE(ipr_gpdd_dev_end_states)) && + (ioasa->u.gpdd.bus_phase <= ARRAY_SIZE(ipr_gpdd_dev_bus_phases))) { + ipr_sdev_err(ipr_cmd->scsi_cmd->device, + "Device End state: %s Phase: %s\n", + ipr_gpdd_dev_end_states[ioasa->u.gpdd.end_state], + ipr_gpdd_dev_bus_phases[ioasa->u.gpdd.bus_phase]); + } if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len)) data_len = sizeof(struct ipr_ioasa); @@ -4133,7 +4141,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, } if (ipr_is_gscsi(res)) - ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); + ipr_dump_ioasa(ioa_cfg, ipr_cmd); else ipr_gen_sense(ipr_cmd); @@ -4532,7 +4540,7 @@ static int ipr_set_supported_devs(struct ipr_cmnd *ipr_cmd) ipr_cmd->job_step = ipr_ioa_reset_done; list_for_each_entry_continue(res, &ioa_cfg->used_res_q, queue) { - if (!ipr_is_scsi_disk(res)) + if (!IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)) continue; ipr_cmd->u.res = res; @@ -4972,7 +4980,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) list_for_each_entry_safe(res, temp, &old_res, queue) { if (res->sdev) { res->del_from_ml = 1; - res->cfgte.res_handle = IPR_INVALID_RES_HANDLE; + res->sdev->hostdata = NULL; list_move_tail(&res->queue, &ioa_cfg->used_res_q); } else { list_move_tail(&res->queue, &ioa_cfg->free_res_q); @@ -5822,109 +5830,6 @@ static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *ioa_cfg, shutdown_type); } -/** - * ipr_reset_freeze - Hold off all I/O activity - * @ipr_cmd: ipr command struct - * - * Description: If the PCI slot is frozen, hold off all I/O - * activity; then, as soon as the slot is available again, - * initiate an adapter reset. - */ -static int ipr_reset_freeze(struct ipr_cmnd *ipr_cmd) -{ - /* Disallow new interrupts, avoid loop */ - ipr_cmd->ioa_cfg->allow_interrupts = 0; - list_add_tail(&ipr_cmd->queue, &ipr_cmd->ioa_cfg->pending_q); - ipr_cmd->done = ipr_reset_ioa_job; - return IPR_RC_JOB_RETURN; -} - -/** - * ipr_pci_frozen - Called when slot has experienced a PCI bus error. - * @pdev: PCI device struct - * - * Description: This routine is called to tell us that the PCI bus - * is down. Can't do anything here, except put the device driver - * into a holding pattern, waiting for the PCI bus to come back. - */ -static void ipr_pci_frozen(struct pci_dev *pdev) -{ - unsigned long flags = 0; - struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); - - spin_lock_irqsave(ioa_cfg->host->host_lock, flags); - _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_freeze, IPR_SHUTDOWN_NONE); - spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); -} - -/** - * ipr_pci_slot_reset - Called when PCI slot has been reset. - * @pdev: PCI device struct - * - * Description: This routine is called by the pci error recovery - * code after the PCI slot has been reset, just before we - * should resume normal operations. - */ -static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev) -{ - unsigned long flags = 0; - struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); - - spin_lock_irqsave(ioa_cfg->host->host_lock, flags); - _ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space, - IPR_SHUTDOWN_NONE); - spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * ipr_pci_perm_failure - Called when PCI slot is dead for good. - * @pdev: PCI device struct - * - * Description: This routine is called when the PCI bus has - * permanently failed. - */ -static void ipr_pci_perm_failure(struct pci_dev *pdev) -{ - unsigned long flags = 0; - struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); - - spin_lock_irqsave(ioa_cfg->host->host_lock, flags); - if (ioa_cfg->sdt_state == WAIT_FOR_DUMP) - ioa_cfg->sdt_state = ABORT_DUMP; - ioa_cfg->reset_retries = IPR_NUM_RESET_RELOAD_RETRIES; - ioa_cfg->in_ioa_bringdown = 1; - ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); - spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); -} - -/** - * ipr_pci_error_detected - Called when a PCI error is detected. - * @pdev: PCI device struct - * @state: PCI channel state - * - * Description: Called when a PCI error is detected. - * - * Return value: - * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT - */ -static pci_ers_result_t ipr_pci_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - switch (state) { - case pci_channel_io_frozen: - ipr_pci_frozen(pdev); - return PCI_ERS_RESULT_NEED_RESET; - case pci_channel_io_perm_failure: - ipr_pci_perm_failure(pdev); - return PCI_ERS_RESULT_DISCONNECT; - break; - default: - break; - } - return PCI_ERS_RESULT_NEED_RESET; -} - /** * ipr_probe_ioa_part2 - Initializes IOAs found in ipr_probe_ioa(..) * @ioa_cfg: ioa cfg struct @@ -6428,7 +6333,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, ioa_cfg->needs_hard_reset = 1; ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); - rc = request_irq(pdev->irq, ipr_isr, IRQF_SHARED, IPR_NAME, ioa_cfg); + rc = request_irq(pdev->irq, ipr_isr, SA_SHIRQ, IPR_NAME, ioa_cfg); if (rc) { dev_err(&pdev->dev, "Couldn't register IRQ %d! rc=%d\n", @@ -6696,18 +6601,12 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = { }; MODULE_DEVICE_TABLE(pci, ipr_pci_table); -static struct pci_error_handlers ipr_err_handler = { - .error_detected = ipr_pci_error_detected, - .slot_reset = ipr_pci_slot_reset, -}; - static struct pci_driver ipr_driver = { .name = IPR_NAME, .id_table = ipr_pci_table, .probe = ipr_probe, .remove = ipr_remove, .shutdown = ipr_shutdown, - .err_handler = &ipr_err_handler, }; /**