// SPDX-License-Identifier: GPL-2.0-or-later /* * ipr.c -- driver for IBM Power Linux RAID adapters * * Written By: Brian King <brking@us.ibm.com>, IBM Corporation * * Copyright (C) 2003, 2004 IBM Corporation
*/
/* * Notes: * * This driver is used to control the following SCSI adapters: * * IBM iSeries: 5702, 5703, 2780, 5709, 570A, 570B * * IBM pSeries: PCI-X Dual Channel Ultra 320 SCSI RAID Adapter * PCI-X Dual Channel Ultra 320 SCSI Adapter * PCI-X Dual Channel Ultra 320 SCSI RAID Enablement Card * Embedded SCSI adapter on p615 and p655 systems * * Supported Hardware Features: * - Ultra 320 SCSI controller * - PCI-X host interface * - Embedded PowerPC RISC Processor and Hardware XOR DMA Engine * - Non-Volatile Write Cache * - Supports attachment of non-RAID disks, tape, and optical devices * - RAID Levels 0, 5, 10 * - Hot spare * - Background Parity Checking * - Background Data Scrubbing * - Ability to increase the capacity of an existing RAID 5 disk array * by adding disks * * Driver Features: * - Tagged command queuing * - Adapter microcode download * - PCI hot plug * - SCSI device hot plug *
*/
MODULE_AUTHOR("Brian King ");
MODULE_DESCRIPTION("IBM Power RAID SCSI Adapter Driver");
module_param_named(max_speed, ipr_max_speed, uint, 0);
MODULE_PARM_DESC(max_speed, "Maximum bus speed (0-2). Default: 1=U160. Speeds: 0=80 MB/s, 1=U160, 2=U320");
module_param_named(log_level, ipr_log_level, uint, 0);
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver");
module_param_named(fastfail, ipr_fastfail, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries");
module_param_named(transop_timeout, ipr_transop_timeout, int, 0);
MODULE_PARM_DESC(transop_timeout, "Time in seconds to wait for adapter to come operational (default: 300)");
module_param_named(debug, ipr_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0);
MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)");
module_param_named(max_devs, ipr_max_devs, int, 0);
MODULE_PARM_DESC(max_devs, "Specify the maximum number of physical devices. " "[Default=" __stringify(IPR_DEFAULT_SIS64_DEVS) "]");
module_param_named(number_of_msix, ipr_number_of_msix, int, 0);
MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:16)");
module_param_named(fast_reboot, ipr_fast_reboot, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(fast_reboot, "Skip adapter shutdown during reboot. Set to 1 to enable. (default: 0)");
MODULE_LICENSE("GPL");
MODULE_VERSION(IPR_DRIVER_VERSION);
/* A constant array of IOASCs/URCs/Error Messages */ staticconst struct ipr_error_table_t ipr_error_table[] = {
{0x00000000, 1, IPR_DEFAULT_LOG_LEVEL, "8155: An unknown error was received"},
{0x00330000, 0, 0, "Soft underlength error"},
{0x005A0000, 0, 0, "Command to be cancelled not found"},
{0x00808000, 0, 0, "Qualified success"},
{0x01080000, 1, IPR_DEFAULT_LOG_LEVEL, "FFFE: Soft device bus error recovered by the IOA"},
{0x01088100, 0, IPR_DEFAULT_LOG_LEVEL, "4101: Soft device bus fabric error"},
{0x01100100, 0, IPR_DEFAULT_LOG_LEVEL, "FFFC: Logical block guard error recovered by the device"},
{0x01100300, 0, IPR_DEFAULT_LOG_LEVEL, "FFFC: Logical block reference tag error recovered by the device"},
{0x01108300, 0, IPR_DEFAULT_LOG_LEVEL, "4171: Recovered scatter list tag / sequence number error"},
{0x01109000, 0, IPR_DEFAULT_LOG_LEVEL, "FF3D: Recovered logical block CRC error on IOA to Host transfer"},
{0x01109200, 0, IPR_DEFAULT_LOG_LEVEL, "4171: Recovered logical block sequence number error on IOA to Host transfer"},
{0x0110A000, 0, IPR_DEFAULT_LOG_LEVEL, "FFFD: Recovered logical block reference tag error detected by the IOA"},
{0x0110A100, 0, IPR_DEFAULT_LOG_LEVEL, "FFFD: Logical block guard error recovered by the IOA"},
{0x01170600, 0, IPR_DEFAULT_LOG_LEVEL, "FFF9: Device sector reassign successful"},
{0x01170900, 0, IPR_DEFAULT_LOG_LEVEL, "FFF7: Media error recovered by device rewrite procedures"},
{0x01180200, 0, IPR_DEFAULT_LOG_LEVEL, "7001: IOA sector reassignment successful"},
{0x01180500, 0, IPR_DEFAULT_LOG_LEVEL, "FFF9: Soft media error. Sector reassignment recommended"},
{0x01180600, 0, IPR_DEFAULT_LOG_LEVEL, "FFF7: Media error recovered by IOA rewrite procedures"},
{0x01418000, 0, IPR_DEFAULT_LOG_LEVEL, "FF3D: Soft PCI bus error recovered by the IOA"},
{0x01440000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF6: Device hardware error recovered by the IOA"},
{0x01448100, 0, IPR_DEFAULT_LOG_LEVEL, "FFF6: Device hardware error recovered by the device"},
{0x01448200, 1, IPR_DEFAULT_LOG_LEVEL, "FF3D: Soft IOA error recovered by the IOA"},
{0x01448300, 0, IPR_DEFAULT_LOG_LEVEL, "FFFA: Undefined device response recovered by the IOA"},
{0x014A0000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF6: Device bus error, message or command phase"},
{0x014A8000, 0, IPR_DEFAULT_LOG_LEVEL, "FFFE: Task Management Function failed"},
{0x015D0000, 0, IPR_DEFAULT_LOG_LEVEL, "FFF6: Failure prediction threshold exceeded"},
{0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL, "8009: Impending cache battery pack failure"},
{0x02040100, 0, 0, "Logical Unit in process of becoming ready"},
{0x02040200, 0, 0, "Initializing command required"},
{0x02040400, 0, 0, "34FF: Disk device format in progress"},
{0x02040C00, 0, 0, "Logical unit not accessible, target port in unavailable state"},
{0x02048000, 0, IPR_DEFAULT_LOG_LEVEL, "9070: IOA requested reset"},
{0x023F0000, 0, 0, "Synchronization required"},
{0x02408500, 0, 0, "IOA microcode download required"},
{0x02408600, 0, 0, "Device bus connection is prohibited by host"},
{0x024E0000, 0, 0, "No ready, IOA shutdown"},
{0x025A0000, 0, 0, "Not ready, IOA has been shutdown"},
{0x02670100, 0, IPR_DEFAULT_LOG_LEVEL, "3020: Storage subsystem configuration error"},
{0x03110B00, 0, 0, "FFF5: Medium error, data unreadable, recommend reassign"},
{0x03110C00, 0, 0, "7000: Medium error, data unreadable, do not reassign"},
{0x03310000, 0, IPR_DEFAULT_LOG_LEVEL, "FFF3: Disk media format bad"},
{0x04050000, 0, IPR_DEFAULT_LOG_LEVEL, "3002: Addressed device failed to respond to selection"},
{0x04080000, 1, IPR_DEFAULT_LOG_LEVEL, "3100: Device bus error"},
{0x04080100, 0, IPR_DEFAULT_LOG_LEVEL, "3109: IOA timed out a device command"},
{0x04088000, 0, 0, "3120: SCSI bus is not operational"},
{0x04088100, 0, IPR_DEFAULT_LOG_LEVEL, "4100: Hard device bus fabric error"},
{0x04100100, 0, IPR_DEFAULT_LOG_LEVEL, "310C: Logical block guard error detected by the device"},
{0x04100300, 0, IPR_DEFAULT_LOG_LEVEL, "310C: Logical block reference tag error detected by the device"},
{0x04108300, 1, IPR_DEFAULT_LOG_LEVEL, "4170: Scatter list tag / sequence number error"},
{0x04109000, 1, IPR_DEFAULT_LOG_LEVEL, "8150: Logical block CRC error on IOA to Host transfer"},
{0x04109200, 1, IPR_DEFAULT_LOG_LEVEL, "4170: Logical block sequence number error on IOA to Host transfer"},
{0x0410A000, 0, IPR_DEFAULT_LOG_LEVEL, "310D: Logical block reference tag error detected by the IOA"},
{0x0410A100, 0, IPR_DEFAULT_LOG_LEVEL, "310D: Logical block guard error detected by the IOA"},
{0x04118000, 0, IPR_DEFAULT_LOG_LEVEL, "9000: IOA reserved area data check"},
{0x04118100, 0, IPR_DEFAULT_LOG_LEVEL, "9001: IOA reserved area invalid data pattern"},
{0x04118200, 0, IPR_DEFAULT_LOG_LEVEL, "9002: IOA reserved area LRC error"},
{0x04118300, 1, IPR_DEFAULT_LOG_LEVEL, "Hardware Error, IOA metadata access error"},
{0x04320000, 0, IPR_DEFAULT_LOG_LEVEL, "102E: Out of alternate sectors for disk storage"},
{0x04330000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF4: Data transfer underlength error"},
{0x04338000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF4: Data transfer overlength error"},
{0x043E0100, 0, IPR_DEFAULT_LOG_LEVEL, "3400: Logical unit failure"},
{0x04408500, 0, IPR_DEFAULT_LOG_LEVEL, "FFF4: Device microcode is corrupt"},
{0x04418000, 1, IPR_DEFAULT_LOG_LEVEL, "8150: PCI bus error"},
{0x04430000, 1, 0, "Unsupported device bus message received"},
{0x04440000, 1, IPR_DEFAULT_LOG_LEVEL, "FFF4: Disk device problem"},
{0x04448200, 1, IPR_DEFAULT_LOG_LEVEL, "8150: Permanent IOA failure"},
{0x04448300, 0, IPR_DEFAULT_LOG_LEVEL, "3010: Disk device returned wrong response to IOA"},
{0x04448400, 0, IPR_DEFAULT_LOG_LEVEL, "8151: IOA microcode error"},
{0x04448500, 0, 0, "Device bus status error"},
{0x04448600, 0, IPR_DEFAULT_LOG_LEVEL, "8157: IOA error requiring IOA reset to recover"},
{0x04448700, 0, 0, "ATA device status error"},
{0x04490000, 0, 0, "Message reject received from the device"},
{0x04449200, 0, IPR_DEFAULT_LOG_LEVEL, "8008: A permanent cache battery pack failure occurred"},
{0x0444A000, 0, IPR_DEFAULT_LOG_LEVEL, "9090: Disk unit has been modified after the last known status"},
{0x0444A200, 0, IPR_DEFAULT_LOG_LEVEL, "9081: IOA detected device error"},
{0x0444A300, 0, IPR_DEFAULT_LOG_LEVEL, "9082: IOA detected device error"},
{0x044A0000, 1, IPR_DEFAULT_LOG_LEVEL, "3110: Device bus error, message or command phase"},
{0x044A8000, 1, IPR_DEFAULT_LOG_LEVEL, "3110: SAS Command / Task Management Function failed"},
{0x04670400, 0, IPR_DEFAULT_LOG_LEVEL, "9091: Incorrect hardware configuration change has been detected"},
{0x04678000, 0, IPR_DEFAULT_LOG_LEVEL, "9073: Invalid multi-adapter configuration"},
{0x04678100, 0, IPR_DEFAULT_LOG_LEVEL, "4010: Incorrect connection between cascaded expanders"},
{0x04678200, 0, IPR_DEFAULT_LOG_LEVEL, "4020: Connections exceed IOA design limits"},
{0x04678300, 0, IPR_DEFAULT_LOG_LEVEL, "4030: Incorrect multipath connection"},
{0x04679000, 0, IPR_DEFAULT_LOG_LEVEL, "4110: Unsupported enclosure function"},
{0x04679800, 0, IPR_DEFAULT_LOG_LEVEL, "4120: SAS cable VPD cannot be read"},
{0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL, "FFF4: Command to logical unit failed"},
{0x05240000, 1, 0, "Illegal request, invalid request type or request packet"},
{0x05250000, 0, 0, "Illegal request, invalid resource handle"},
{0x05258000, 0, 0, "Illegal request, commands not allowed to this device"},
{0x05258100, 0, 0, "Illegal request, command not allowed to a secondary adapter"},
{0x05258200, 0, 0, "Illegal request, command not allowed to a non-optimized resource"},
{0x05260000, 0, 0, "Illegal request, invalid field in parameter list"},
{0x05260100, 0, 0, "Illegal request, parameter not supported"},
{0x05260200, 0, 0, "Illegal request, parameter value invalid"},
{0x052C0000, 0, 0, "Illegal request, command sequence error"},
{0x052C8000, 1, 0, "Illegal request, dual adapter support not enabled"},
{0x052C8100, 1, 0, "Illegal request, another cable connector was physically disabled"},
{0x054E8000, 1, 0, "Illegal request, inconsistent group id/group count"},
{0x06040500, 0, IPR_DEFAULT_LOG_LEVEL, "9031: Array protection temporarily suspended, protection resuming"},
{0x06040600, 0, IPR_DEFAULT_LOG_LEVEL, "9040: Array protection temporarily suspended, protection resuming"},
{0x060B0100, 0, IPR_DEFAULT_LOG_LEVEL, "4080: IOA exceeded maximum operating temperature"},
{0x060B8000, 0, IPR_DEFAULT_LOG_LEVEL, "4085: Service required"},
{0x060B8100, 0, IPR_DEFAULT_LOG_LEVEL, "4086: SAS Adapter Hardware Configuration Error"},
{0x06288000, 0, IPR_DEFAULT_LOG_LEVEL, "3140: Device bus not ready to ready transition"},
{0x06290000, 0, IPR_DEFAULT_LOG_LEVEL, "FFFB: SCSI bus was reset"},
{0x06290500, 0, 0, "FFFE: SCSI bus transition to single ended"},
{0x06290600, 0, 0, "FFFE: SCSI bus transition to LVD"},
{0x06298000, 0, IPR_DEFAULT_LOG_LEVEL, "FFFB: SCSI bus was reset by another initiator"},
{0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL, "3029: A device replacement has occurred"},
{0x063F8300, 0, IPR_DEFAULT_LOG_LEVEL, "4102: Device bus fabric performance degradation"},
{0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL, "9051: IOA cache data exists for a missing or failed device"},
{0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL, "9055: Auxiliary cache IOA contains cache data needed by the primary IOA"},
{0x06670100, 0, IPR_DEFAULT_LOG_LEVEL, "9025: Disk unit is not supported at its physical location"},
{0x06670600, 0, IPR_DEFAULT_LOG_LEVEL, "3020: IOA detected a SCSI bus configuration error"},
{0x06678000, 0, IPR_DEFAULT_LOG_LEVEL, "3150: SCSI bus configuration error"},
{0x06678100, 0, IPR_DEFAULT_LOG_LEVEL, "9074: Asymmetric advanced function disk configuration"},
{0x06678300, 0, IPR_DEFAULT_LOG_LEVEL, "4040: Incomplete multipath connection between IOA and enclosure"},
{0x06678400, 0, IPR_DEFAULT_LOG_LEVEL, "4041: Incomplete multipath connection between enclosure and device"},
{0x06678500, 0, IPR_DEFAULT_LOG_LEVEL, "9075: Incomplete multipath connection between IOA and remote IOA"},
{0x06678600, 0, IPR_DEFAULT_LOG_LEVEL, "9076: Configuration error, missing remote IOA"},
{0x06679100, 0, IPR_DEFAULT_LOG_LEVEL, "4050: Enclosure does not support a required multipath function"},
{0x06679800, 0, IPR_DEFAULT_LOG_LEVEL, "4121: Configuration error, required cable is missing"},
{0x06679900, 0, IPR_DEFAULT_LOG_LEVEL, "4122: Cable is not plugged into the correct location on remote IOA"},
{0x06679A00, 0, IPR_DEFAULT_LOG_LEVEL, "4123: Configuration error, invalid cable vital product data"},
{0x06679B00, 0, IPR_DEFAULT_LOG_LEVEL, "4124: Configuration error, both cable ends are plugged into the same IOA"},
{0x06690000, 0, IPR_DEFAULT_LOG_LEVEL, "4070: Logically bad block written on device"},
{0x06690200, 0, IPR_DEFAULT_LOG_LEVEL, "9041: Array protection temporarily suspended"},
{0x06698200, 0, IPR_DEFAULT_LOG_LEVEL, "9042: Corrupt array parity detected on specified device"},
{0x066B0200, 0, IPR_DEFAULT_LOG_LEVEL, "9030: Array no longer protected due to missing or failed disk unit"},
{0x066B8000, 0, IPR_DEFAULT_LOG_LEVEL, "9071: Link operational transition"},
{0x066B8100, 0, IPR_DEFAULT_LOG_LEVEL, "9072: Link not operational transition"},
{0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL, "9032: Array exposed but still protected"},
{0x066B8300, 0, IPR_DEBUG_LOG_LEVEL, "70DD: Device forced failed by disrupt device command"},
{0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL, "4061: Multipath redundancy level got better"},
{0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, "4060: Multipath redundancy level got worse"},
{0x06808100, 0, IPR_DEBUG_LOG_LEVEL, "9083: Device raw mode enabled"},
{0x06808200, 0, IPR_DEBUG_LOG_LEVEL, "9084: Device raw mode disabled"},
{0x07270000, 0, 0, "Failure due to other device"},
{0x07278000, 0, IPR_DEFAULT_LOG_LEVEL, "9008: IOA does not support functions expected by devices"},
{0x07278100, 0, IPR_DEFAULT_LOG_LEVEL, "9010: Cache data associated with attached devices cannot be found"},
{0x07278200, 0, IPR_DEFAULT_LOG_LEVEL, "9011: Cache data belongs to devices other than those attached"},
{0x07278400, 0, IPR_DEFAULT_LOG_LEVEL, "9020: Array missing 2 or more devices with only 1 device present"},
{0x07278500, 0, IPR_DEFAULT_LOG_LEVEL, "9021: Array missing 2 or more devices with 2 or more devices present"},
{0x07278600, 0, IPR_DEFAULT_LOG_LEVEL, "9022: Exposed array is missing a required device"},
{0x07278700, 0, IPR_DEFAULT_LOG_LEVEL, "9023: Array member(s) not at required physical locations"},
{0x07278800, 0, IPR_DEFAULT_LOG_LEVEL, "9024: Array not functional due to present hardware configuration"},
{0x07278900, 0, IPR_DEFAULT_LOG_LEVEL, "9026: Array not functional due to present hardware configuration"},
{0x07278A00, 0, IPR_DEFAULT_LOG_LEVEL, "9027: Array is missing a device and parity is out of sync"},
{0x07278B00, 0, IPR_DEFAULT_LOG_LEVEL, "9028: Maximum number of arrays already exist"},
{0x07278C00, 0, IPR_DEFAULT_LOG_LEVEL, "9050: Required cache data cannot be located for a disk unit"},
{0x07278D00, 0, IPR_DEFAULT_LOG_LEVEL, "9052: Cache data exists for a device that has been modified"},
{0x07278F00, 0, IPR_DEFAULT_LOG_LEVEL, "9054: IOA resources not available due to previous problems"},
{0x07279100, 0, IPR_DEFAULT_LOG_LEVEL, "9092: Disk unit requires initialization before use"},
{0x07279200, 0, IPR_DEFAULT_LOG_LEVEL, "9029: Incorrect hardware configuration change has been detected"},
{0x07279600, 0, IPR_DEFAULT_LOG_LEVEL, "9060: One or more disk pairs are missing from an array"},
{0x07279700, 0, IPR_DEFAULT_LOG_LEVEL, "9061: One or more disks are missing from an array"},
{0x07279800, 0, IPR_DEFAULT_LOG_LEVEL, "9062: One or more disks are missing from an array"},
{0x07279900, 0, IPR_DEFAULT_LOG_LEVEL, "9063: Maximum number of functional arrays has been exceeded"},
{0x07279A00, 0, 0, "Data protect, other volume set problem"},
{0x0B260000, 0, 0, "Aborted command, invalid descriptor"},
{0x0B3F9000, 0, 0, "Target operating conditions have changed, dual adapter takeover"},
{0x0B530200, 0, 0, "Aborted command, medium removal prevented"},
{0x0B5A0000, 0, 0, "Command terminated by host"},
{0x0B5B8000, 0, 0, "Aborted command, command terminated by host"}
};
/** * ipr_get_free_ipr_cmnd - Get a free IPR Cmnd block and initialize it * @ioa_cfg: ioa config struct * * Return value: * pointer to ipr command struct
**/ static struct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg)
{ struct ipr_cmnd *ipr_cmd =
__ipr_get_free_ipr_cmnd(&ioa_cfg->hrrq[IPR_INIT_HRRQ]);
ipr_init_ipr_cmnd(ipr_cmd, ipr_lock_and_done); return ipr_cmd;
}
/** * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts * @ioa_cfg: ioa config struct * @clr_ints: interrupts to clear * * This function masks all interrupts on the adapter, then clears the * interrupts specified in the mask * * Return value: * none
**/ staticvoid ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg,
u32 clr_ints)
{ int i;
/* Stop new interrupts */ for (i = 0; i < ioa_cfg->hrrq_num; i++) {
spin_lock(&ioa_cfg->hrrq[i]._lock);
ioa_cfg->hrrq[i].allow_interrupts = 0;
spin_unlock(&ioa_cfg->hrrq[i]._lock);
}
/* Set interrupt mask to stop all new interrupts */ if (ioa_cfg->sis64)
writeq(~0, ioa_cfg->regs.set_interrupt_mask_reg); else
writel(~0, ioa_cfg->regs.set_interrupt_mask_reg);
/* Clear any pending interrupts */ if (ioa_cfg->sis64)
writel(~0, ioa_cfg->regs.clr_interrupt_reg);
writel(clr_ints, ioa_cfg->regs.clr_interrupt_reg32);
readl(ioa_cfg->regs.sense_interrupt_reg);
}
/** * ipr_save_pcix_cmd_reg - Save PCI-X command register * @ioa_cfg: ioa config struct * * Return value: * 0 on success / -EIO on failure
**/ staticint ipr_save_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
{ int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX); int rc;
if (pcix_cmd_reg == 0) return 0;
rc = pci_read_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,
&ioa_cfg->saved_pcix_cmd_reg); if (rc != PCIBIOS_SUCCESSFUL) {
dev_err(&ioa_cfg->pdev->dev, "Failed to save PCI-X command register\n"); return -EIO;
}
/** * ipr_set_pcix_cmd_reg - Setup PCI-X command register * @ioa_cfg: ioa config struct * * Return value: * 0 on success / -EIO on failure
**/ staticint ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
{ int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX); int rc;
if (pcix_cmd_reg) {
rc = pci_write_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,
ioa_cfg->saved_pcix_cmd_reg); if (rc != PCIBIOS_SUCCESSFUL) {
dev_err(&ioa_cfg->pdev->dev, "Failed to setup PCI-X command register\n"); return -EIO;
}
}
return 0;
}
/** * __ipr_scsi_eh_done - mid-layer done function for aborted ops * @ipr_cmd: ipr command struct * * This function is invoked by the interrupt handler for * ops generated by the SCSI mid-layer which are being aborted. * * Return value: * none
**/ staticvoid __ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
{ struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
scsi_cmd->result |= (DID_ERROR << 16);
scsi_dma_unmap(ipr_cmd->scsi_cmd);
scsi_done(scsi_cmd); if (ipr_cmd->eh_comp)
complete(ipr_cmd->eh_comp);
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
}
/** * ipr_scsi_eh_done - mid-layer done function for aborted ops * @ipr_cmd: ipr command struct * * This function is invoked by the interrupt handler for * ops generated by the SCSI mid-layer which are being aborted. * * Return value: * none
**/ staticvoid ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
{ unsignedlong hrrq_flags; struct ipr_hrr_queue *hrrq = ipr_cmd->hrrq;
/** * ipr_send_command - Send driver initiated requests. * @ipr_cmd: ipr command struct * * This function sends a command to the adapter using the correct write call. * In the case of sis64, calculate the ioarcb size required. Then or in the * appropriate bits. * * Return value: * none
**/ staticvoid ipr_send_command(struct ipr_cmnd *ipr_cmd)
{ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
dma_addr_t send_dma_addr = ipr_cmd->dma_addr;
if (ioa_cfg->sis64) { /* The default size is 256 bytes */
send_dma_addr |= 0x1;
/* If the number of ioadls * size of ioadl > 128 bytes,
then use a 512 byte ioarcb */ if (ipr_cmd->dma_use_sg * sizeof(struct ipr_ioadl64_desc) > 128 )
send_dma_addr |= 0x4;
writeq(send_dma_addr, ioa_cfg->regs.ioarrin_reg);
} else
writel(send_dma_addr, ioa_cfg->regs.ioarrin_reg);
}
/** * ipr_do_req - Send driver initiated requests. * @ipr_cmd: ipr command struct * @done: done function * @timeout_func: timeout function * @timeout: timeout value * * This function sends the specified command to the adapter with the * timeout given. The done function is invoked on command completion. * * Return value: * none
**/ staticvoid ipr_do_req(struct ipr_cmnd *ipr_cmd, void (*done) (struct ipr_cmnd *), void (*timeout_func) (struct timer_list *), u32 timeout)
{
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
/** * ipr_internal_cmd_done - Op done function for an internally generated op. * @ipr_cmd: ipr command struct * * This function is the op done function for an internally generated, * blocking op. It simply wakes the sleeping thread. * * Return value: * none
**/ staticvoid ipr_internal_cmd_done(struct ipr_cmnd *ipr_cmd)
{ if (ipr_cmd->sibling)
ipr_cmd->sibling = NULL; else
complete(&ipr_cmd->completion);
}
/** * ipr_init_ioadl - initialize the ioadl for the correct SIS type * @ipr_cmd: ipr command struct * @dma_addr: dma address * @len: transfer length * @flags: ioadl flag value * * This function initializes an ioadl in the case where there is only a single * descriptor. * * Return value: * nothing
**/ staticvoid ipr_init_ioadl(struct ipr_cmnd *ipr_cmd, dma_addr_t dma_addr,
u32 len, int flags)
{ struct ipr_ioadl_desc *ioadl = ipr_cmd->i.ioadl; struct ipr_ioadl64_desc *ioadl64 = ipr_cmd->i.ioadl64;
/** * ipr_send_hcam - Send an HCAM to the adapter. * @ioa_cfg: ioa config struct * @type: HCAM type * @hostrcb: hostrcb struct * * This function will send a Host Controlled Async command to the adapter. * If HCAMs are currently not allowed to be issued to the adapter, it will * place the hostrcb on the free queue. * * Return value: * none
**/ staticvoid ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type, struct ipr_hostrcb *hostrcb)
{ struct ipr_cmnd *ipr_cmd; struct ipr_ioarcb *ioarcb;
if (ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_pending_q);
list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_pending_q);
/** * ipr_is_same_device - Determine if two devices are the same. * @res: resource entry struct * @cfgtew: config table entry wrapper struct * * Return value: * 1 if the devices are the same / 0 otherwise
**/ staticint ipr_is_same_device(struct ipr_resource_entry *res, struct ipr_config_table_entry_wrapper *cfgtew)
{ if (res->ioa_cfg->sis64) { if (!memcmp(&res->dev_id, &cfgtew->u.cfgte64->dev_id, sizeof(cfgtew->u.cfgte64->dev_id)) &&
!memcmp(&res->dev_lun.scsi_lun, &cfgtew->u.cfgte64->lun, sizeof(cfgtew->u.cfgte64->lun))) { return 1;
}
} else { if (res->bus == cfgtew->u.cfgte->res_addr.bus &&
res->target == cfgtew->u.cfgte->res_addr.target &&
res->lun == cfgtew->u.cfgte->res_addr.lun) return 1;
}
return 0;
}
/** * __ipr_format_res_path - Format the resource path for printing. * @res_path: resource path * @buffer: buffer * @len: length of buffer provided * * Return value: * pointer to buffer
**/ staticchar *__ipr_format_res_path(u8 *res_path, char *buffer, int len)
{ int i; char *p = buffer;
*p = '\0';
p += scnprintf(p, buffer + len - p, "%02X", res_path[0]); for (i = 1; res_path[i] != 0xff && i < IPR_RES_PATH_BYTES; i++)
p += scnprintf(p, buffer + len - p, "-%02X", res_path[i]);
return buffer;
}
/** * ipr_format_res_path - Format the resource path for printing. * @ioa_cfg: ioa config struct * @res_path: resource path * @buffer: buffer * @len: length of buffer provided * * Return value: * pointer to buffer
**/ staticchar *ipr_format_res_path(struct ipr_ioa_cfg *ioa_cfg,
u8 *res_path, char *buffer, int len)
{ char *p = buffer;
*p = '\0';
p += scnprintf(p, buffer + len - p, "%d/", ioa_cfg->host->host_no);
__ipr_format_res_path(res_path, p, len - (p - buffer)); return buffer;
}
/** * ipr_process_ccn - Op done function for a CCN. * @ipr_cmd: ipr command struct * * This function is the op done function for a configuration * change notification host controlled async from the adapter. * * Return value: * none
**/ staticvoid ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
{ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
/** * strip_whitespace - Strip and pad trailing whitespace. * @i: size of buffer * @buf: string to modify * * This function will strip all trailing whitespace and * NUL terminate the string. *
**/ staticvoid strip_whitespace(int i, char *buf)
{ if (i < 1) return;
i--; while (i && buf[i] == ' ')
i--;
buf[i+1] = '\0';
}
if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL)
len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP);
for (i = 0; i < len / 4; i += 4) {
ipr_err("%08X: %08X %08X %08X %08X\n", i*4,
be32_to_cpu(data[i]),
be32_to_cpu(data[i+1]),
be32_to_cpu(data[i+2]),
be32_to_cpu(data[i+3]));
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.