ipr.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,336 行 · 第 1/5 页

C
2,336
字号
/* * 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 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *//* * 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 * */#include <linux/config.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/wait.h>#include <linux/spinlock.h>#include <linux/sched.h>#include <linux/interrupt.h>#include <linux/blkdev.h>#include <linux/firmware.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/processor.h>#include <scsi/scsi.h>#include <scsi/scsi_host.h>#include <scsi/scsi_tcq.h>#include <scsi/scsi_eh.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_request.h>#include "ipr.h"/* *   Global Data */static struct list_head ipr_ioa_head = LIST_HEAD_INIT(ipr_ioa_head);static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL;static unsigned int ipr_max_speed = 1;static int ipr_testmode = 0;static spinlock_t ipr_driver_lock = SPIN_LOCK_UNLOCKED;/* This table describes the differences between DMA controller chips */static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {	{ /* Gemstone and Citrine */		.mailbox = 0x0042C,		.cache_line_size = 0x20,		{			.set_interrupt_mask_reg = 0x0022C,			.clr_interrupt_mask_reg = 0x00230,			.sense_interrupt_mask_reg = 0x0022C,			.clr_interrupt_reg = 0x00228,			.sense_interrupt_reg = 0x00224,			.ioarrin_reg = 0x00404,			.sense_uproc_interrupt_reg = 0x00214,			.set_uproc_interrupt_reg = 0x00214,			.clr_uproc_interrupt_reg = 0x00218		}	},	{ /* Snipe */		.mailbox = 0x0052C,		.cache_line_size = 0x20,		{			.set_interrupt_mask_reg = 0x00288,			.clr_interrupt_mask_reg = 0x0028C,			.sense_interrupt_mask_reg = 0x00288,			.clr_interrupt_reg = 0x00284,			.sense_interrupt_reg = 0x00280,			.ioarrin_reg = 0x00504,			.sense_uproc_interrupt_reg = 0x00290,			.set_uproc_interrupt_reg = 0x00290,			.clr_uproc_interrupt_reg = 0x00294		}	},};static int ipr_max_bus_speeds [] = {	IPR_80MBs_SCSI_RATE, IPR_U160_SCSI_RATE, IPR_U320_SCSI_RATE};MODULE_AUTHOR("Brian King <brking@us.ibm.com>");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(testmode, ipr_testmode, int, 0);MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations");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 conststruct ipr_error_table_t ipr_error_table[] = {	{0x00000000, 1, 1,	"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, 1,	"FFFE: Soft device bus error recovered by the IOA"},	{0x01170600, 0, 1,	"FFF9: Device sector reassign successful"},	{0x01170900, 0, 1,	"FFF7: Media error recovered by device rewrite procedures"},	{0x01180200, 0, 1,	"7001: IOA sector reassignment successful"},	{0x01180500, 0, 1,	"FFF9: Soft media error. Sector reassignment recommended"},	{0x01180600, 0, 1,	"FFF7: Media error recovered by IOA rewrite procedures"},	{0x01418000, 0, 1,	"FF3D: Soft PCI bus error recovered by the IOA"},	{0x01440000, 1, 1,	"FFF6: Device hardware error recovered by the IOA"},	{0x01448100, 0, 1,	"FFF6: Device hardware error recovered by the device"},	{0x01448200, 1, 1,	"FF3D: Soft IOA error recovered by the IOA"},	{0x01448300, 0, 1,	"FFFA: Undefined device response recovered by the IOA"},	{0x014A0000, 1, 1,	"FFF6: Device bus error, message or command phase"},	{0x015D0000, 0, 1,	"FFF6: Failure prediction threshold exceeded"},	{0x015D9200, 0, 1,	"8009: Impending cache battery pack failure"},	{0x02040400, 0, 0,	"34FF: Disk device format in progress"},	{0x023F0000, 0, 0,	"Synchronization required"},	{0x024E0000, 0, 0,	"No ready, IOA shutdown"},	{0x025A0000, 0, 0,	"Not ready, IOA has been shutdown"},	{0x02670100, 0, 1,	"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, 1,	"FFF3: Disk media format bad"},	{0x04050000, 0, 1,	"3002: Addressed device failed to respond to selection"},	{0x04080000, 1, 1,	"3100: Device bus error"},	{0x04080100, 0, 1,	"3109: IOA timed out a device command"},	{0x04088000, 0, 0,	"3120: SCSI bus is not operational"},	{0x04118000, 0, 1,	"9000: IOA reserved area data check"},	{0x04118100, 0, 1,	"9001: IOA reserved area invalid data pattern"},	{0x04118200, 0, 1,	"9002: IOA reserved area LRC error"},	{0x04320000, 0, 1,	"102E: Out of alternate sectors for disk storage"},	{0x04330000, 1, 1,	"FFF4: Data transfer underlength error"},	{0x04338000, 1, 1,	"FFF4: Data transfer overlength error"},	{0x043E0100, 0, 1,	"3400: Logical unit failure"},	{0x04408500, 0, 1,	"FFF4: Device microcode is corrupt"},	{0x04418000, 1, 1,	"8150: PCI bus error"},	{0x04430000, 1, 0,	"Unsupported device bus message received"},	{0x04440000, 1, 1,	"FFF4: Disk device problem"},	{0x04448200, 1, 1,	"8150: Permanent IOA failure"},	{0x04448300, 0, 1,	"3010: Disk device returned wrong response to IOA"},	{0x04448400, 0, 1,	"8151: IOA microcode error"},	{0x04448500, 0, 0,	"Device bus status error"},	{0x04448600, 0, 1,	"8157: IOA error requiring IOA reset to recover"},	{0x04490000, 0, 0,	"Message reject received from the device"},	{0x04449200, 0, 1,	"8008: A permanent cache battery pack failure occurred"},	{0x0444A000, 0, 1,	"9090: Disk unit has been modified after the last known status"},	{0x0444A200, 0, 1,	"9081: IOA detected device error"},	{0x0444A300, 0, 1,	"9082: IOA detected device error"},	{0x044A0000, 1, 1,	"3110: Device bus error, message or command phase"},	{0x04670400, 0, 1,	"9091: Incorrect hardware configuration change has been detected"},	{0x046E0000, 0, 1,	"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"},	{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"},	{0x06040500, 0, 1,	"9031: Array protection temporarily suspended, protection resuming"},	{0x06040600, 0, 1,	"9040: Array protection temporarily suspended, protection resuming"},	{0x06290000, 0, 1,	"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, 1,	"FFFB: SCSI bus was reset by another initiator"},	{0x063F0300, 0, 1,	"3029: A device replacement has occurred"},	{0x064C8000, 0, 1,	"9051: IOA cache data exists for a missing or failed device"},	{0x06670100, 0, 1,	"9025: Disk unit is not supported at its physical location"},	{0x06670600, 0, 1,	"3020: IOA detected a SCSI bus configuration error"},	{0x06678000, 0, 1,	"3150: SCSI bus configuration error"},	{0x06690200, 0, 1,	"9041: Array protection temporarily suspended"},	{0x066B0200, 0, 1,	"9030: Array no longer protected due to missing or failed disk unit"},	{0x07270000, 0, 0,	"Failure due to other device"},	{0x07278000, 0, 1,	"9008: IOA does not support functions expected by devices"},	{0x07278100, 0, 1,	"9010: Cache data associated with attached devices cannot be found"},	{0x07278200, 0, 1,	"9011: Cache data belongs to devices other than those attached"},	{0x07278400, 0, 1,	"9020: Array missing 2 or more devices with only 1 device present"},	{0x07278500, 0, 1,	"9021: Array missing 2 or more devices with 2 or more devices present"},	{0x07278600, 0, 1,	"9022: Exposed array is missing a required device"},	{0x07278700, 0, 1,	"9023: Array member(s) not at required physical locations"},	{0x07278800, 0, 1,	"9024: Array not functional due to present hardware configuration"},	{0x07278900, 0, 1,	"9026: Array not functional due to present hardware configuration"},	{0x07278A00, 0, 1,	"9027: Array is missing a device and parity is out of sync"},	{0x07278B00, 0, 1,	"9028: Maximum number of arrays already exist"},	{0x07278C00, 0, 1,	"9050: Required cache data cannot be located for a disk unit"},	{0x07278D00, 0, 1,	"9052: Cache data exists for a device that has been modified"},	{0x07278F00, 0, 1,	"9054: IOA resources not available due to previous problems"},	{0x07279100, 0, 1,	"9092: Disk unit requires initialization before use"},	{0x07279200, 0, 1,	"9029: Incorrect hardware configuration change has been detected"},	{0x07279600, 0, 1,	"9060: One or more disk pairs are missing from an array"},	{0x07279700, 0, 1,	"9061: One or more disks are missing from an array"},	{0x07279800, 0, 1,	"9062: One or more disks are missing from an array"},	{0x07279900, 0, 1,	"9063: Maximum number of functional arrays has been exceeded"},	{0x0B260000, 0, 0,	"Aborted command, invalid descriptor"},	{0x0B5A0000, 0, 0,	"Command terminated by host"}};static const struct ipr_ses_table_entry ipr_ses_table[] = {	{ "2104-DL1        ", "XXXXXXXXXXXXXXXX", 80 },	{ "2104-TL1        ", "XXXXXXXXXXXXXXXX", 80 },	{ "HSBP07M P U2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* Hidive 7 slot */	{ "HSBP05M P U2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* Hidive 5 slot */	{ "HSBP05M S U2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* Bowtie */	{ "HSBP06E ASU2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* MartinFenning */	{ "2104-DU3        ", "XXXXXXXXXXXXXXXX", 160 },	{ "2104-TU3        ", "XXXXXXXXXXXXXXXX", 160 },	{ "HSBP04C RSU2SCSI", "XXXXXXX*XXXXXXXX", 160 },	{ "HSBP06E RSU2SCSI", "XXXXXXX*XXXXXXXX", 160 },	{ "St  V1S2        ", "XXXXXXXXXXXXXXXX", 160 },	{ "HSBPD4M  PU3SCSI", "XXXXXXX*XXXXXXXX", 160 },	{ "VSBPD1H   U3SCSI", "XXXXXXX*XXXXXXXX", 160 }};/* *  Function Prototypes */static int ipr_reset_alert(struct ipr_cmnd *);static void ipr_process_ccn(struct ipr_cmnd *);static void ipr_process_error(struct ipr_cmnd *);static void ipr_reset_ioa_job(struct ipr_cmnd *);static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *,				   enum ipr_shutdown_type);#ifdef CONFIG_SCSI_IPR_TRACE/** * ipr_trc_hook - Add a trace entry to the driver trace * @ipr_cmd:	ipr command struct * @type:		trace type * @add_data:	additional data * * Return value: * 	none **/static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,			 u8 type, u32 add_data){	struct ipr_trace_entry *trace_entry;	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;	trace_entry = &ioa_cfg->trace[ioa_cfg->trace_index++];	trace_entry->time = jiffies;	trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0];	trace_entry->type = type;	trace_entry->cmd_index = ipr_cmd->cmd_index;	trace_entry->res_handle = ipr_cmd->ioarcb.res_handle;	trace_entry->u.add_data = add_data;}#else#define ipr_trc_hook(ipr_cmd, type, add_data) do { } while(0)#endif/** * ipr_reinit_ipr_cmnd - Re-initialize an IPR Cmnd block for reuse * @ipr_cmd:	ipr command struct * * Return value: * 	none **/static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd){	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;	struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;	memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));	ioarcb->write_data_transfer_length = 0;	ioarcb->read_data_transfer_length = 0;	ioarcb->write_ioadl_len = 0;	ioarcb->read_ioadl_len = 0;	ioasa->ioasc = 0;	ioasa->residual_data_len = 0;	ipr_cmd->scsi_cmd = NULL;	ipr_cmd->sense_buffer[0] = 0;	ipr_cmd->dma_use_sg = 0;}/** * ipr_init_ipr_cmnd - Initialize an IPR Cmnd block * @ipr_cmd:	ipr command struct * * Return value: * 	none **/static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd){	ipr_reinit_ipr_cmnd(ipr_cmd);	ipr_cmd->u.scratch = 0;	ipr_cmd->sibling = NULL;	init_timer(&ipr_cmd->timer);}/** * ipr_get_free_ipr_cmnd - Get a free IPR Cmnd block * @ioa_cfg:	ioa config struct * * Return value: * 	pointer to ipr command struct **/staticstruct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg){	struct ipr_cmnd *ipr_cmd;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?