PageRenderTime 122ms CodeModel.GetById 7ms app.highlight 95ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/scsi/ipr.c

https://bitbucket.org/jdstroy/ipaq214
C | 7895 lines | 4946 code | 1038 blank | 1911 comment | 633 complexity | dd8555b13f6f168ae51d9a240df0c8ff MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2 * ipr.c -- driver for IBM Power Linux RAID adapters
   3 *
   4 * Written By: Brian King <brking@us.ibm.com>, IBM Corporation
   5 *
   6 * Copyright (C) 2003, 2004 IBM Corporation
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  21 *
  22 */
  23
  24/*
  25 * Notes:
  26 *
  27 * This driver is used to control the following SCSI adapters:
  28 *
  29 * IBM iSeries: 5702, 5703, 2780, 5709, 570A, 570B
  30 *
  31 * IBM pSeries: PCI-X Dual Channel Ultra 320 SCSI RAID Adapter
  32 *              PCI-X Dual Channel Ultra 320 SCSI Adapter
  33 *              PCI-X Dual Channel Ultra 320 SCSI RAID Enablement Card
  34 *              Embedded SCSI adapter on p615 and p655 systems
  35 *
  36 * Supported Hardware Features:
  37 *	- Ultra 320 SCSI controller
  38 *	- PCI-X host interface
  39 *	- Embedded PowerPC RISC Processor and Hardware XOR DMA Engine
  40 *	- Non-Volatile Write Cache
  41 *	- Supports attachment of non-RAID disks, tape, and optical devices
  42 *	- RAID Levels 0, 5, 10
  43 *	- Hot spare
  44 *	- Background Parity Checking
  45 *	- Background Data Scrubbing
  46 *	- Ability to increase the capacity of an existing RAID 5 disk array
  47 *		by adding disks
  48 *
  49 * Driver Features:
  50 *	- Tagged command queuing
  51 *	- Adapter microcode download
  52 *	- PCI hot plug
  53 *	- SCSI device hot plug
  54 *
  55 */
  56
  57#include <linux/fs.h>
  58#include <linux/init.h>
  59#include <linux/types.h>
  60#include <linux/errno.h>
  61#include <linux/kernel.h>
  62#include <linux/ioport.h>
  63#include <linux/delay.h>
  64#include <linux/pci.h>
  65#include <linux/wait.h>
  66#include <linux/spinlock.h>
  67#include <linux/sched.h>
  68#include <linux/interrupt.h>
  69#include <linux/blkdev.h>
  70#include <linux/firmware.h>
  71#include <linux/module.h>
  72#include <linux/moduleparam.h>
  73#include <linux/libata.h>
  74#include <linux/hdreg.h>
  75#include <asm/io.h>
  76#include <asm/irq.h>
  77#include <asm/processor.h>
  78#include <scsi/scsi.h>
  79#include <scsi/scsi_host.h>
  80#include <scsi/scsi_tcq.h>
  81#include <scsi/scsi_eh.h>
  82#include <scsi/scsi_cmnd.h>
  83#include "ipr.h"
  84
  85/*
  86 *   Global Data
  87 */
  88static LIST_HEAD(ipr_ioa_head);
  89static unsigned int ipr_log_level = IPR_DEFAULT_LOG_LEVEL;
  90static unsigned int ipr_max_speed = 1;
  91static int ipr_testmode = 0;
  92static unsigned int ipr_fastfail = 0;
  93static unsigned int ipr_transop_timeout = 0;
  94static unsigned int ipr_enable_cache = 1;
  95static unsigned int ipr_debug = 0;
  96static unsigned int ipr_dual_ioa_raid = 1;
  97static DEFINE_SPINLOCK(ipr_driver_lock);
  98
  99/* This table describes the differences between DMA controller chips */
 100static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
 101	{ /* Gemstone, Citrine, Obsidian, and Obsidian-E */
 102		.mailbox = 0x0042C,
 103		.cache_line_size = 0x20,
 104		{
 105			.set_interrupt_mask_reg = 0x0022C,
 106			.clr_interrupt_mask_reg = 0x00230,
 107			.sense_interrupt_mask_reg = 0x0022C,
 108			.clr_interrupt_reg = 0x00228,
 109			.sense_interrupt_reg = 0x00224,
 110			.ioarrin_reg = 0x00404,
 111			.sense_uproc_interrupt_reg = 0x00214,
 112			.set_uproc_interrupt_reg = 0x00214,
 113			.clr_uproc_interrupt_reg = 0x00218
 114		}
 115	},
 116	{ /* Snipe and Scamp */
 117		.mailbox = 0x0052C,
 118		.cache_line_size = 0x20,
 119		{
 120			.set_interrupt_mask_reg = 0x00288,
 121			.clr_interrupt_mask_reg = 0x0028C,
 122			.sense_interrupt_mask_reg = 0x00288,
 123			.clr_interrupt_reg = 0x00284,
 124			.sense_interrupt_reg = 0x00280,
 125			.ioarrin_reg = 0x00504,
 126			.sense_uproc_interrupt_reg = 0x00290,
 127			.set_uproc_interrupt_reg = 0x00290,
 128			.clr_uproc_interrupt_reg = 0x00294
 129		}
 130	},
 131};
 132
 133static const struct ipr_chip_t ipr_chip[] = {
 134	{ PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, &ipr_chip_cfg[0] },
 135	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] },
 136	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] },
 137	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] },
 138	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] },
 139	{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] },
 140	{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] }
 141};
 142
 143static int ipr_max_bus_speeds [] = {
 144	IPR_80MBs_SCSI_RATE, IPR_U160_SCSI_RATE, IPR_U320_SCSI_RATE
 145};
 146
 147MODULE_AUTHOR("Brian King <brking@us.ibm.com>");
 148MODULE_DESCRIPTION("IBM Power RAID SCSI Adapter Driver");
 149module_param_named(max_speed, ipr_max_speed, uint, 0);
 150MODULE_PARM_DESC(max_speed, "Maximum bus speed (0-2). Default: 1=U160. Speeds: 0=80 MB/s, 1=U160, 2=U320");
 151module_param_named(log_level, ipr_log_level, uint, 0);
 152MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver");
 153module_param_named(testmode, ipr_testmode, int, 0);
 154MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations");
 155module_param_named(fastfail, ipr_fastfail, int, S_IRUGO | S_IWUSR);
 156MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries");
 157module_param_named(transop_timeout, ipr_transop_timeout, int, 0);
 158MODULE_PARM_DESC(transop_timeout, "Time in seconds to wait for adapter to come operational (default: 300)");
 159module_param_named(enable_cache, ipr_enable_cache, int, 0);
 160MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
 161module_param_named(debug, ipr_debug, int, S_IRUGO | S_IWUSR);
 162MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
 163module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0);
 164MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)");
 165MODULE_LICENSE("GPL");
 166MODULE_VERSION(IPR_DRIVER_VERSION);
 167
 168/*  A constant array of IOASCs/URCs/Error Messages */
 169static const
 170struct ipr_error_table_t ipr_error_table[] = {
 171	{0x00000000, 1, IPR_DEFAULT_LOG_LEVEL,
 172	"8155: An unknown error was received"},
 173	{0x00330000, 0, 0,
 174	"Soft underlength error"},
 175	{0x005A0000, 0, 0,
 176	"Command to be cancelled not found"},
 177	{0x00808000, 0, 0,
 178	"Qualified success"},
 179	{0x01080000, 1, IPR_DEFAULT_LOG_LEVEL,
 180	"FFFE: Soft device bus error recovered by the IOA"},
 181	{0x01088100, 0, IPR_DEFAULT_LOG_LEVEL,
 182	"4101: Soft device bus fabric error"},
 183	{0x01170600, 0, IPR_DEFAULT_LOG_LEVEL,
 184	"FFF9: Device sector reassign successful"},
 185	{0x01170900, 0, IPR_DEFAULT_LOG_LEVEL,
 186	"FFF7: Media error recovered by device rewrite procedures"},
 187	{0x01180200, 0, IPR_DEFAULT_LOG_LEVEL,
 188	"7001: IOA sector reassignment successful"},
 189	{0x01180500, 0, IPR_DEFAULT_LOG_LEVEL,
 190	"FFF9: Soft media error. Sector reassignment recommended"},
 191	{0x01180600, 0, IPR_DEFAULT_LOG_LEVEL,
 192	"FFF7: Media error recovered by IOA rewrite procedures"},
 193	{0x01418000, 0, IPR_DEFAULT_LOG_LEVEL,
 194	"FF3D: Soft PCI bus error recovered by the IOA"},
 195	{0x01440000, 1, IPR_DEFAULT_LOG_LEVEL,
 196	"FFF6: Device hardware error recovered by the IOA"},
 197	{0x01448100, 0, IPR_DEFAULT_LOG_LEVEL,
 198	"FFF6: Device hardware error recovered by the device"},
 199	{0x01448200, 1, IPR_DEFAULT_LOG_LEVEL,
 200	"FF3D: Soft IOA error recovered by the IOA"},
 201	{0x01448300, 0, IPR_DEFAULT_LOG_LEVEL,
 202	"FFFA: Undefined device response recovered by the IOA"},
 203	{0x014A0000, 1, IPR_DEFAULT_LOG_LEVEL,
 204	"FFF6: Device bus error, message or command phase"},
 205	{0x014A8000, 0, IPR_DEFAULT_LOG_LEVEL,
 206	"FFFE: Task Management Function failed"},
 207	{0x015D0000, 0, IPR_DEFAULT_LOG_LEVEL,
 208	"FFF6: Failure prediction threshold exceeded"},
 209	{0x015D9200, 0, IPR_DEFAULT_LOG_LEVEL,
 210	"8009: Impending cache battery pack failure"},
 211	{0x02040400, 0, 0,
 212	"34FF: Disk device format in progress"},
 213	{0x02048000, 0, IPR_DEFAULT_LOG_LEVEL,
 214	"9070: IOA requested reset"},
 215	{0x023F0000, 0, 0,
 216	"Synchronization required"},
 217	{0x024E0000, 0, 0,
 218	"No ready, IOA shutdown"},
 219	{0x025A0000, 0, 0,
 220	"Not ready, IOA has been shutdown"},
 221	{0x02670100, 0, IPR_DEFAULT_LOG_LEVEL,
 222	"3020: Storage subsystem configuration error"},
 223	{0x03110B00, 0, 0,
 224	"FFF5: Medium error, data unreadable, recommend reassign"},
 225	{0x03110C00, 0, 0,
 226	"7000: Medium error, data unreadable, do not reassign"},
 227	{0x03310000, 0, IPR_DEFAULT_LOG_LEVEL,
 228	"FFF3: Disk media format bad"},
 229	{0x04050000, 0, IPR_DEFAULT_LOG_LEVEL,
 230	"3002: Addressed device failed to respond to selection"},
 231	{0x04080000, 1, IPR_DEFAULT_LOG_LEVEL,
 232	"3100: Device bus error"},
 233	{0x04080100, 0, IPR_DEFAULT_LOG_LEVEL,
 234	"3109: IOA timed out a device command"},
 235	{0x04088000, 0, 0,
 236	"3120: SCSI bus is not operational"},
 237	{0x04088100, 0, IPR_DEFAULT_LOG_LEVEL,
 238	"4100: Hard device bus fabric error"},
 239	{0x04118000, 0, IPR_DEFAULT_LOG_LEVEL,
 240	"9000: IOA reserved area data check"},
 241	{0x04118100, 0, IPR_DEFAULT_LOG_LEVEL,
 242	"9001: IOA reserved area invalid data pattern"},
 243	{0x04118200, 0, IPR_DEFAULT_LOG_LEVEL,
 244	"9002: IOA reserved area LRC error"},
 245	{0x04320000, 0, IPR_DEFAULT_LOG_LEVEL,
 246	"102E: Out of alternate sectors for disk storage"},
 247	{0x04330000, 1, IPR_DEFAULT_LOG_LEVEL,
 248	"FFF4: Data transfer underlength error"},
 249	{0x04338000, 1, IPR_DEFAULT_LOG_LEVEL,
 250	"FFF4: Data transfer overlength error"},
 251	{0x043E0100, 0, IPR_DEFAULT_LOG_LEVEL,
 252	"3400: Logical unit failure"},
 253	{0x04408500, 0, IPR_DEFAULT_LOG_LEVEL,
 254	"FFF4: Device microcode is corrupt"},
 255	{0x04418000, 1, IPR_DEFAULT_LOG_LEVEL,
 256	"8150: PCI bus error"},
 257	{0x04430000, 1, 0,
 258	"Unsupported device bus message received"},
 259	{0x04440000, 1, IPR_DEFAULT_LOG_LEVEL,
 260	"FFF4: Disk device problem"},
 261	{0x04448200, 1, IPR_DEFAULT_LOG_LEVEL,
 262	"8150: Permanent IOA failure"},
 263	{0x04448300, 0, IPR_DEFAULT_LOG_LEVEL,
 264	"3010: Disk device returned wrong response to IOA"},
 265	{0x04448400, 0, IPR_DEFAULT_LOG_LEVEL,
 266	"8151: IOA microcode error"},
 267	{0x04448500, 0, 0,
 268	"Device bus status error"},
 269	{0x04448600, 0, IPR_DEFAULT_LOG_LEVEL,
 270	"8157: IOA error requiring IOA reset to recover"},
 271	{0x04448700, 0, 0,
 272	"ATA device status error"},
 273	{0x04490000, 0, 0,
 274	"Message reject received from the device"},
 275	{0x04449200, 0, IPR_DEFAULT_LOG_LEVEL,
 276	"8008: A permanent cache battery pack failure occurred"},
 277	{0x0444A000, 0, IPR_DEFAULT_LOG_LEVEL,
 278	"9090: Disk unit has been modified after the last known status"},
 279	{0x0444A200, 0, IPR_DEFAULT_LOG_LEVEL,
 280	"9081: IOA detected device error"},
 281	{0x0444A300, 0, IPR_DEFAULT_LOG_LEVEL,
 282	"9082: IOA detected device error"},
 283	{0x044A0000, 1, IPR_DEFAULT_LOG_LEVEL,
 284	"3110: Device bus error, message or command phase"},
 285	{0x044A8000, 1, IPR_DEFAULT_LOG_LEVEL,
 286	"3110: SAS Command / Task Management Function failed"},
 287	{0x04670400, 0, IPR_DEFAULT_LOG_LEVEL,
 288	"9091: Incorrect hardware configuration change has been detected"},
 289	{0x04678000, 0, IPR_DEFAULT_LOG_LEVEL,
 290	"9073: Invalid multi-adapter configuration"},
 291	{0x04678100, 0, IPR_DEFAULT_LOG_LEVEL,
 292	"4010: Incorrect connection between cascaded expanders"},
 293	{0x04678200, 0, IPR_DEFAULT_LOG_LEVEL,
 294	"4020: Connections exceed IOA design limits"},
 295	{0x04678300, 0, IPR_DEFAULT_LOG_LEVEL,
 296	"4030: Incorrect multipath connection"},
 297	{0x04679000, 0, IPR_DEFAULT_LOG_LEVEL,
 298	"4110: Unsupported enclosure function"},
 299	{0x046E0000, 0, IPR_DEFAULT_LOG_LEVEL,
 300	"FFF4: Command to logical unit failed"},
 301	{0x05240000, 1, 0,
 302	"Illegal request, invalid request type or request packet"},
 303	{0x05250000, 0, 0,
 304	"Illegal request, invalid resource handle"},
 305	{0x05258000, 0, 0,
 306	"Illegal request, commands not allowed to this device"},
 307	{0x05258100, 0, 0,
 308	"Illegal request, command not allowed to a secondary adapter"},
 309	{0x05260000, 0, 0,
 310	"Illegal request, invalid field in parameter list"},
 311	{0x05260100, 0, 0,
 312	"Illegal request, parameter not supported"},
 313	{0x05260200, 0, 0,
 314	"Illegal request, parameter value invalid"},
 315	{0x052C0000, 0, 0,
 316	"Illegal request, command sequence error"},
 317	{0x052C8000, 1, 0,
 318	"Illegal request, dual adapter support not enabled"},
 319	{0x06040500, 0, IPR_DEFAULT_LOG_LEVEL,
 320	"9031: Array protection temporarily suspended, protection resuming"},
 321	{0x06040600, 0, IPR_DEFAULT_LOG_LEVEL,
 322	"9040: Array protection temporarily suspended, protection resuming"},
 323	{0x06288000, 0, IPR_DEFAULT_LOG_LEVEL,
 324	"3140: Device bus not ready to ready transition"},
 325	{0x06290000, 0, IPR_DEFAULT_LOG_LEVEL,
 326	"FFFB: SCSI bus was reset"},
 327	{0x06290500, 0, 0,
 328	"FFFE: SCSI bus transition to single ended"},
 329	{0x06290600, 0, 0,
 330	"FFFE: SCSI bus transition to LVD"},
 331	{0x06298000, 0, IPR_DEFAULT_LOG_LEVEL,
 332	"FFFB: SCSI bus was reset by another initiator"},
 333	{0x063F0300, 0, IPR_DEFAULT_LOG_LEVEL,
 334	"3029: A device replacement has occurred"},
 335	{0x064C8000, 0, IPR_DEFAULT_LOG_LEVEL,
 336	"9051: IOA cache data exists for a missing or failed device"},
 337	{0x064C8100, 0, IPR_DEFAULT_LOG_LEVEL,
 338	"9055: Auxiliary cache IOA contains cache data needed by the primary IOA"},
 339	{0x06670100, 0, IPR_DEFAULT_LOG_LEVEL,
 340	"9025: Disk unit is not supported at its physical location"},
 341	{0x06670600, 0, IPR_DEFAULT_LOG_LEVEL,
 342	"3020: IOA detected a SCSI bus configuration error"},
 343	{0x06678000, 0, IPR_DEFAULT_LOG_LEVEL,
 344	"3150: SCSI bus configuration error"},
 345	{0x06678100, 0, IPR_DEFAULT_LOG_LEVEL,
 346	"9074: Asymmetric advanced function disk configuration"},
 347	{0x06678300, 0, IPR_DEFAULT_LOG_LEVEL,
 348	"4040: Incomplete multipath connection between IOA and enclosure"},
 349	{0x06678400, 0, IPR_DEFAULT_LOG_LEVEL,
 350	"4041: Incomplete multipath connection between enclosure and device"},
 351	{0x06678500, 0, IPR_DEFAULT_LOG_LEVEL,
 352	"9075: Incomplete multipath connection between IOA and remote IOA"},
 353	{0x06678600, 0, IPR_DEFAULT_LOG_LEVEL,
 354	"9076: Configuration error, missing remote IOA"},
 355	{0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
 356	"4050: Enclosure does not support a required multipath function"},
 357	{0x06690000, 0, IPR_DEFAULT_LOG_LEVEL,
 358	"4070: Logically bad block written on device"},
 359	{0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
 360	"9041: Array protection temporarily suspended"},
 361	{0x06698200, 0, IPR_DEFAULT_LOG_LEVEL,
 362	"9042: Corrupt array parity detected on specified device"},
 363	{0x066B0200, 0, IPR_DEFAULT_LOG_LEVEL,
 364	"9030: Array no longer protected due to missing or failed disk unit"},
 365	{0x066B8000, 0, IPR_DEFAULT_LOG_LEVEL,
 366	"9071: Link operational transition"},
 367	{0x066B8100, 0, IPR_DEFAULT_LOG_LEVEL,
 368	"9072: Link not operational transition"},
 369	{0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL,
 370	"9032: Array exposed but still protected"},
 371	{0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1,
 372	"70DD: Device forced failed by disrupt device command"},
 373	{0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL,
 374	"4061: Multipath redundancy level got better"},
 375	{0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL,
 376	"4060: Multipath redundancy level got worse"},
 377	{0x07270000, 0, 0,
 378	"Failure due to other device"},
 379	{0x07278000, 0, IPR_DEFAULT_LOG_LEVEL,
 380	"9008: IOA does not support functions expected by devices"},
 381	{0x07278100, 0, IPR_DEFAULT_LOG_LEVEL,
 382	"9010: Cache data associated with attached devices cannot be found"},
 383	{0x07278200, 0, IPR_DEFAULT_LOG_LEVEL,
 384	"9011: Cache data belongs to devices other than those attached"},
 385	{0x07278400, 0, IPR_DEFAULT_LOG_LEVEL,
 386	"9020: Array missing 2 or more devices with only 1 device present"},
 387	{0x07278500, 0, IPR_DEFAULT_LOG_LEVEL,
 388	"9021: Array missing 2 or more devices with 2 or more devices present"},
 389	{0x07278600, 0, IPR_DEFAULT_LOG_LEVEL,
 390	"9022: Exposed array is missing a required device"},
 391	{0x07278700, 0, IPR_DEFAULT_LOG_LEVEL,
 392	"9023: Array member(s) not at required physical locations"},
 393	{0x07278800, 0, IPR_DEFAULT_LOG_LEVEL,
 394	"9024: Array not functional due to present hardware configuration"},
 395	{0x07278900, 0, IPR_DEFAULT_LOG_LEVEL,
 396	"9026: Array not functional due to present hardware configuration"},
 397	{0x07278A00, 0, IPR_DEFAULT_LOG_LEVEL,
 398	"9027: Array is missing a device and parity is out of sync"},
 399	{0x07278B00, 0, IPR_DEFAULT_LOG_LEVEL,
 400	"9028: Maximum number of arrays already exist"},
 401	{0x07278C00, 0, IPR_DEFAULT_LOG_LEVEL,
 402	"9050: Required cache data cannot be located for a disk unit"},
 403	{0x07278D00, 0, IPR_DEFAULT_LOG_LEVEL,
 404	"9052: Cache data exists for a device that has been modified"},
 405	{0x07278F00, 0, IPR_DEFAULT_LOG_LEVEL,
 406	"9054: IOA resources not available due to previous problems"},
 407	{0x07279100, 0, IPR_DEFAULT_LOG_LEVEL,
 408	"9092: Disk unit requires initialization before use"},
 409	{0x07279200, 0, IPR_DEFAULT_LOG_LEVEL,
 410	"9029: Incorrect hardware configuration change has been detected"},
 411	{0x07279600, 0, IPR_DEFAULT_LOG_LEVEL,
 412	"9060: One or more disk pairs are missing from an array"},
 413	{0x07279700, 0, IPR_DEFAULT_LOG_LEVEL,
 414	"9061: One or more disks are missing from an array"},
 415	{0x07279800, 0, IPR_DEFAULT_LOG_LEVEL,
 416	"9062: One or more disks are missing from an array"},
 417	{0x07279900, 0, IPR_DEFAULT_LOG_LEVEL,
 418	"9063: Maximum number of functional arrays has been exceeded"},
 419	{0x0B260000, 0, 0,
 420	"Aborted command, invalid descriptor"},
 421	{0x0B5A0000, 0, 0,
 422	"Command terminated by host"}
 423};
 424
 425static const struct ipr_ses_table_entry ipr_ses_table[] = {
 426	{ "2104-DL1        ", "XXXXXXXXXXXXXXXX", 80 },
 427	{ "2104-TL1        ", "XXXXXXXXXXXXXXXX", 80 },
 428	{ "HSBP07M P U2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* Hidive 7 slot */
 429	{ "HSBP05M P U2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* Hidive 5 slot */
 430	{ "HSBP05M S U2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* Bowtie */
 431	{ "HSBP06E ASU2SCSI", "XXXXXXXXXXXXXXXX", 80 }, /* MartinFenning */
 432	{ "2104-DU3        ", "XXXXXXXXXXXXXXXX", 160 },
 433	{ "2104-TU3        ", "XXXXXXXXXXXXXXXX", 160 },
 434	{ "HSBP04C RSU2SCSI", "XXXXXXX*XXXXXXXX", 160 },
 435	{ "HSBP06E RSU2SCSI", "XXXXXXX*XXXXXXXX", 160 },
 436	{ "St  V1S2        ", "XXXXXXXXXXXXXXXX", 160 },
 437	{ "HSBPD4M  PU3SCSI", "XXXXXXX*XXXXXXXX", 160 },
 438	{ "VSBPD1H   U3SCSI", "XXXXXXX*XXXXXXXX", 160 }
 439};
 440
 441/*
 442 *  Function Prototypes
 443 */
 444static int ipr_reset_alert(struct ipr_cmnd *);
 445static void ipr_process_ccn(struct ipr_cmnd *);
 446static void ipr_process_error(struct ipr_cmnd *);
 447static void ipr_reset_ioa_job(struct ipr_cmnd *);
 448static void ipr_initiate_ioa_reset(struct ipr_ioa_cfg *,
 449				   enum ipr_shutdown_type);
 450
 451#ifdef CONFIG_SCSI_IPR_TRACE
 452/**
 453 * ipr_trc_hook - Add a trace entry to the driver trace
 454 * @ipr_cmd:	ipr command struct
 455 * @type:		trace type
 456 * @add_data:	additional data
 457 *
 458 * Return value:
 459 * 	none
 460 **/
 461static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd,
 462			 u8 type, u32 add_data)
 463{
 464	struct ipr_trace_entry *trace_entry;
 465	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 466
 467	trace_entry = &ioa_cfg->trace[ioa_cfg->trace_index++];
 468	trace_entry->time = jiffies;
 469	trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0];
 470	trace_entry->type = type;
 471	trace_entry->ata_op_code = ipr_cmd->ioarcb.add_data.u.regs.command;
 472	trace_entry->cmd_index = ipr_cmd->cmd_index & 0xff;
 473	trace_entry->res_handle = ipr_cmd->ioarcb.res_handle;
 474	trace_entry->u.add_data = add_data;
 475}
 476#else
 477#define ipr_trc_hook(ipr_cmd, type, add_data) do { } while(0)
 478#endif
 479
 480/**
 481 * ipr_reinit_ipr_cmnd - Re-initialize an IPR Cmnd block for reuse
 482 * @ipr_cmd:	ipr command struct
 483 *
 484 * Return value:
 485 * 	none
 486 **/
 487static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
 488{
 489	struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
 490	struct ipr_ioasa *ioasa = &ipr_cmd->ioasa;
 491	dma_addr_t dma_addr = be32_to_cpu(ioarcb->ioarcb_host_pci_addr);
 492
 493	memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt));
 494	ioarcb->write_data_transfer_length = 0;
 495	ioarcb->read_data_transfer_length = 0;
 496	ioarcb->write_ioadl_len = 0;
 497	ioarcb->read_ioadl_len = 0;
 498	ioarcb->write_ioadl_addr =
 499		cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioadl));
 500	ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr;
 501	ioasa->ioasc = 0;
 502	ioasa->residual_data_len = 0;
 503	ioasa->u.gata.status = 0;
 504
 505	ipr_cmd->scsi_cmd = NULL;
 506	ipr_cmd->qc = NULL;
 507	ipr_cmd->sense_buffer[0] = 0;
 508	ipr_cmd->dma_use_sg = 0;
 509}
 510
 511/**
 512 * ipr_init_ipr_cmnd - Initialize an IPR Cmnd block
 513 * @ipr_cmd:	ipr command struct
 514 *
 515 * Return value:
 516 * 	none
 517 **/
 518static void ipr_init_ipr_cmnd(struct ipr_cmnd *ipr_cmd)
 519{
 520	ipr_reinit_ipr_cmnd(ipr_cmd);
 521	ipr_cmd->u.scratch = 0;
 522	ipr_cmd->sibling = NULL;
 523	init_timer(&ipr_cmd->timer);
 524}
 525
 526/**
 527 * ipr_get_free_ipr_cmnd - Get a free IPR Cmnd block
 528 * @ioa_cfg:	ioa config struct
 529 *
 530 * Return value:
 531 * 	pointer to ipr command struct
 532 **/
 533static
 534struct ipr_cmnd *ipr_get_free_ipr_cmnd(struct ipr_ioa_cfg *ioa_cfg)
 535{
 536	struct ipr_cmnd *ipr_cmd;
 537
 538	ipr_cmd = list_entry(ioa_cfg->free_q.next, struct ipr_cmnd, queue);
 539	list_del(&ipr_cmd->queue);
 540	ipr_init_ipr_cmnd(ipr_cmd);
 541
 542	return ipr_cmd;
 543}
 544
 545/**
 546 * ipr_mask_and_clear_interrupts - Mask all and clear specified interrupts
 547 * @ioa_cfg:	ioa config struct
 548 * @clr_ints:     interrupts to clear
 549 *
 550 * This function masks all interrupts on the adapter, then clears the
 551 * interrupts specified in the mask
 552 *
 553 * Return value:
 554 * 	none
 555 **/
 556static void ipr_mask_and_clear_interrupts(struct ipr_ioa_cfg *ioa_cfg,
 557					  u32 clr_ints)
 558{
 559	volatile u32 int_reg;
 560
 561	/* Stop new interrupts */
 562	ioa_cfg->allow_interrupts = 0;
 563
 564	/* Set interrupt mask to stop all new interrupts */
 565	writel(~0, ioa_cfg->regs.set_interrupt_mask_reg);
 566
 567	/* Clear any pending interrupts */
 568	writel(clr_ints, ioa_cfg->regs.clr_interrupt_reg);
 569	int_reg = readl(ioa_cfg->regs.sense_interrupt_reg);
 570}
 571
 572/**
 573 * ipr_save_pcix_cmd_reg - Save PCI-X command register
 574 * @ioa_cfg:	ioa config struct
 575 *
 576 * Return value:
 577 * 	0 on success / -EIO on failure
 578 **/
 579static int ipr_save_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
 580{
 581	int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX);
 582
 583	if (pcix_cmd_reg == 0)
 584		return 0;
 585
 586	if (pci_read_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,
 587				 &ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) {
 588		dev_err(&ioa_cfg->pdev->dev, "Failed to save PCI-X command register\n");
 589		return -EIO;
 590	}
 591
 592	ioa_cfg->saved_pcix_cmd_reg |= PCI_X_CMD_DPERR_E | PCI_X_CMD_ERO;
 593	return 0;
 594}
 595
 596/**
 597 * ipr_set_pcix_cmd_reg - Setup PCI-X command register
 598 * @ioa_cfg:	ioa config struct
 599 *
 600 * Return value:
 601 * 	0 on success / -EIO on failure
 602 **/
 603static int ipr_set_pcix_cmd_reg(struct ipr_ioa_cfg *ioa_cfg)
 604{
 605	int pcix_cmd_reg = pci_find_capability(ioa_cfg->pdev, PCI_CAP_ID_PCIX);
 606
 607	if (pcix_cmd_reg) {
 608		if (pci_write_config_word(ioa_cfg->pdev, pcix_cmd_reg + PCI_X_CMD,
 609					  ioa_cfg->saved_pcix_cmd_reg) != PCIBIOS_SUCCESSFUL) {
 610			dev_err(&ioa_cfg->pdev->dev, "Failed to setup PCI-X command register\n");
 611			return -EIO;
 612		}
 613	}
 614
 615	return 0;
 616}
 617
 618/**
 619 * ipr_sata_eh_done - done function for aborted SATA commands
 620 * @ipr_cmd:	ipr command struct
 621 *
 622 * This function is invoked for ops generated to SATA
 623 * devices which are being aborted.
 624 *
 625 * Return value:
 626 * 	none
 627 **/
 628static void ipr_sata_eh_done(struct ipr_cmnd *ipr_cmd)
 629{
 630	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 631	struct ata_queued_cmd *qc = ipr_cmd->qc;
 632	struct ipr_sata_port *sata_port = qc->ap->private_data;
 633
 634	qc->err_mask |= AC_ERR_OTHER;
 635	sata_port->ioasa.status |= ATA_BUSY;
 636	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 637	ata_qc_complete(qc);
 638}
 639
 640/**
 641 * ipr_scsi_eh_done - mid-layer done function for aborted ops
 642 * @ipr_cmd:	ipr command struct
 643 *
 644 * This function is invoked by the interrupt handler for
 645 * ops generated by the SCSI mid-layer which are being aborted.
 646 *
 647 * Return value:
 648 * 	none
 649 **/
 650static void ipr_scsi_eh_done(struct ipr_cmnd *ipr_cmd)
 651{
 652	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 653	struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
 654
 655	scsi_cmd->result |= (DID_ERROR << 16);
 656
 657	scsi_dma_unmap(ipr_cmd->scsi_cmd);
 658	scsi_cmd->scsi_done(scsi_cmd);
 659	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 660}
 661
 662/**
 663 * ipr_fail_all_ops - Fails all outstanding ops.
 664 * @ioa_cfg:	ioa config struct
 665 *
 666 * This function fails all outstanding ops.
 667 *
 668 * Return value:
 669 * 	none
 670 **/
 671static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg)
 672{
 673	struct ipr_cmnd *ipr_cmd, *temp;
 674
 675	ENTER;
 676	list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) {
 677		list_del(&ipr_cmd->queue);
 678
 679		ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET);
 680		ipr_cmd->ioasa.ilid = cpu_to_be32(IPR_DRIVER_ILID);
 681
 682		if (ipr_cmd->scsi_cmd)
 683			ipr_cmd->done = ipr_scsi_eh_done;
 684		else if (ipr_cmd->qc)
 685			ipr_cmd->done = ipr_sata_eh_done;
 686
 687		ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, IPR_IOASC_IOA_WAS_RESET);
 688		del_timer(&ipr_cmd->timer);
 689		ipr_cmd->done(ipr_cmd);
 690	}
 691
 692	LEAVE;
 693}
 694
 695/**
 696 * ipr_do_req -  Send driver initiated requests.
 697 * @ipr_cmd:		ipr command struct
 698 * @done:			done function
 699 * @timeout_func:	timeout function
 700 * @timeout:		timeout value
 701 *
 702 * This function sends the specified command to the adapter with the
 703 * timeout given. The done function is invoked on command completion.
 704 *
 705 * Return value:
 706 * 	none
 707 **/
 708static void ipr_do_req(struct ipr_cmnd *ipr_cmd,
 709		       void (*done) (struct ipr_cmnd *),
 710		       void (*timeout_func) (struct ipr_cmnd *), u32 timeout)
 711{
 712	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 713
 714	list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
 715
 716	ipr_cmd->done = done;
 717
 718	ipr_cmd->timer.data = (unsigned long) ipr_cmd;
 719	ipr_cmd->timer.expires = jiffies + timeout;
 720	ipr_cmd->timer.function = (void (*)(unsigned long))timeout_func;
 721
 722	add_timer(&ipr_cmd->timer);
 723
 724	ipr_trc_hook(ipr_cmd, IPR_TRACE_START, 0);
 725
 726	mb();
 727	writel(be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr),
 728	       ioa_cfg->regs.ioarrin_reg);
 729}
 730
 731/**
 732 * ipr_internal_cmd_done - Op done function for an internally generated op.
 733 * @ipr_cmd:	ipr command struct
 734 *
 735 * This function is the op done function for an internally generated,
 736 * blocking op. It simply wakes the sleeping thread.
 737 *
 738 * Return value:
 739 * 	none
 740 **/
 741static void ipr_internal_cmd_done(struct ipr_cmnd *ipr_cmd)
 742{
 743	if (ipr_cmd->sibling)
 744		ipr_cmd->sibling = NULL;
 745	else
 746		complete(&ipr_cmd->completion);
 747}
 748
 749/**
 750 * ipr_send_blocking_cmd - Send command and sleep on its completion.
 751 * @ipr_cmd:	ipr command struct
 752 * @timeout_func:	function to invoke if command times out
 753 * @timeout:	timeout
 754 *
 755 * Return value:
 756 * 	none
 757 **/
 758static void ipr_send_blocking_cmd(struct ipr_cmnd *ipr_cmd,
 759				  void (*timeout_func) (struct ipr_cmnd *ipr_cmd),
 760				  u32 timeout)
 761{
 762	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 763
 764	init_completion(&ipr_cmd->completion);
 765	ipr_do_req(ipr_cmd, ipr_internal_cmd_done, timeout_func, timeout);
 766
 767	spin_unlock_irq(ioa_cfg->host->host_lock);
 768	wait_for_completion(&ipr_cmd->completion);
 769	spin_lock_irq(ioa_cfg->host->host_lock);
 770}
 771
 772/**
 773 * ipr_send_hcam - Send an HCAM to the adapter.
 774 * @ioa_cfg:	ioa config struct
 775 * @type:		HCAM type
 776 * @hostrcb:	hostrcb struct
 777 *
 778 * This function will send a Host Controlled Async command to the adapter.
 779 * If HCAMs are currently not allowed to be issued to the adapter, it will
 780 * place the hostrcb on the free queue.
 781 *
 782 * Return value:
 783 * 	none
 784 **/
 785static void ipr_send_hcam(struct ipr_ioa_cfg *ioa_cfg, u8 type,
 786			  struct ipr_hostrcb *hostrcb)
 787{
 788	struct ipr_cmnd *ipr_cmd;
 789	struct ipr_ioarcb *ioarcb;
 790
 791	if (ioa_cfg->allow_cmds) {
 792		ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg);
 793		list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q);
 794		list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_pending_q);
 795
 796		ipr_cmd->u.hostrcb = hostrcb;
 797		ioarcb = &ipr_cmd->ioarcb;
 798
 799		ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE);
 800		ioarcb->cmd_pkt.request_type = IPR_RQTYPE_HCAM;
 801		ioarcb->cmd_pkt.cdb[0] = IPR_HOST_CONTROLLED_ASYNC;
 802		ioarcb->cmd_pkt.cdb[1] = type;
 803		ioarcb->cmd_pkt.cdb[7] = (sizeof(hostrcb->hcam) >> 8) & 0xff;
 804		ioarcb->cmd_pkt.cdb[8] = sizeof(hostrcb->hcam) & 0xff;
 805
 806		ioarcb->read_data_transfer_length = cpu_to_be32(sizeof(hostrcb->hcam));
 807		ioarcb->read_ioadl_len = cpu_to_be32(sizeof(struct ipr_ioadl_desc));
 808		ipr_cmd->ioadl[0].flags_and_data_len =
 809			cpu_to_be32(IPR_IOADL_FLAGS_READ_LAST | sizeof(hostrcb->hcam));
 810		ipr_cmd->ioadl[0].address = cpu_to_be32(hostrcb->hostrcb_dma);
 811
 812		if (type == IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE)
 813			ipr_cmd->done = ipr_process_ccn;
 814		else
 815			ipr_cmd->done = ipr_process_error;
 816
 817		ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_IOA_RES_ADDR);
 818
 819		mb();
 820		writel(be32_to_cpu(ipr_cmd->ioarcb.ioarcb_host_pci_addr),
 821		       ioa_cfg->regs.ioarrin_reg);
 822	} else {
 823		list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q);
 824	}
 825}
 826
 827/**
 828 * ipr_init_res_entry - Initialize a resource entry struct.
 829 * @res:	resource entry struct
 830 *
 831 * Return value:
 832 * 	none
 833 **/
 834static void ipr_init_res_entry(struct ipr_resource_entry *res)
 835{
 836	res->needs_sync_complete = 0;
 837	res->in_erp = 0;
 838	res->add_to_ml = 0;
 839	res->del_from_ml = 0;
 840	res->resetting_device = 0;
 841	res->sdev = NULL;
 842	res->sata_port = NULL;
 843}
 844
 845/**
 846 * ipr_handle_config_change - Handle a config change from the adapter
 847 * @ioa_cfg:	ioa config struct
 848 * @hostrcb:	hostrcb
 849 *
 850 * Return value:
 851 * 	none
 852 **/
 853static void ipr_handle_config_change(struct ipr_ioa_cfg *ioa_cfg,
 854			      struct ipr_hostrcb *hostrcb)
 855{
 856	struct ipr_resource_entry *res = NULL;
 857	struct ipr_config_table_entry *cfgte;
 858	u32 is_ndn = 1;
 859
 860	cfgte = &hostrcb->hcam.u.ccn.cfgte;
 861
 862	list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
 863		if (!memcmp(&res->cfgte.res_addr, &cfgte->res_addr,
 864			    sizeof(cfgte->res_addr))) {
 865			is_ndn = 0;
 866			break;
 867		}
 868	}
 869
 870	if (is_ndn) {
 871		if (list_empty(&ioa_cfg->free_res_q)) {
 872			ipr_send_hcam(ioa_cfg,
 873				      IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE,
 874				      hostrcb);
 875			return;
 876		}
 877
 878		res = list_entry(ioa_cfg->free_res_q.next,
 879				 struct ipr_resource_entry, queue);
 880
 881		list_del(&res->queue);
 882		ipr_init_res_entry(res);
 883		list_add_tail(&res->queue, &ioa_cfg->used_res_q);
 884	}
 885
 886	memcpy(&res->cfgte, cfgte, sizeof(struct ipr_config_table_entry));
 887
 888	if (hostrcb->hcam.notify_type == IPR_HOST_RCB_NOTIF_TYPE_REM_ENTRY) {
 889		if (res->sdev) {
 890			res->del_from_ml = 1;
 891			res->cfgte.res_handle = IPR_INVALID_RES_HANDLE;
 892			if (ioa_cfg->allow_ml_add_del)
 893				schedule_work(&ioa_cfg->work_q);
 894		} else
 895			list_move_tail(&res->queue, &ioa_cfg->free_res_q);
 896	} else if (!res->sdev) {
 897		res->add_to_ml = 1;
 898		if (ioa_cfg->allow_ml_add_del)
 899			schedule_work(&ioa_cfg->work_q);
 900	}
 901
 902	ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb);
 903}
 904
 905/**
 906 * ipr_process_ccn - Op done function for a CCN.
 907 * @ipr_cmd:	ipr command struct
 908 *
 909 * This function is the op done function for a configuration
 910 * change notification host controlled async from the adapter.
 911 *
 912 * Return value:
 913 * 	none
 914 **/
 915static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
 916{
 917	struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
 918	struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
 919	u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
 920
 921	list_del(&hostrcb->queue);
 922	list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
 923
 924	if (ioasc) {
 925		if (ioasc != IPR_IOASC_IOA_WAS_RESET)
 926			dev_err(&ioa_cfg->pdev->dev,
 927				"Host RCB failed with IOASC: 0x%08X\n", ioasc);
 928
 929		ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb);
 930	} else {
 931		ipr_handle_config_change(ioa_cfg, hostrcb);
 932	}
 933}
 934
 935/**
 936 * strip_and_pad_whitespace - Strip and pad trailing whitespace.
 937 * @i:		index into buffer
 938 * @buf:		string to modify
 939 *
 940 * This function will strip all trailing whitespace, pad the end
 941 * of the string with a single space, and NULL terminate the string.
 942 *
 943 * Return value:
 944 * 	new length of string
 945 **/
 946static int strip_and_pad_whitespace(int i, char *buf)
 947{
 948	while (i && buf[i] == ' ')
 949		i--;
 950	buf[i+1] = ' ';
 951	buf[i+2] = '\0';
 952	return i + 2;
 953}
 954
 955/**
 956 * ipr_log_vpd_compact - Log the passed extended VPD compactly.
 957 * @prefix:		string to print at start of printk
 958 * @hostrcb:	hostrcb pointer
 959 * @vpd:		vendor/product id/sn struct
 960 *
 961 * Return value:
 962 * 	none
 963 **/
 964static void ipr_log_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
 965				struct ipr_vpd *vpd)
 966{
 967	char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + IPR_SERIAL_NUM_LEN + 3];
 968	int i = 0;
 969
 970	memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
 971	i = strip_and_pad_whitespace(IPR_VENDOR_ID_LEN - 1, buffer);
 972
 973	memcpy(&buffer[i], vpd->vpids.product_id, IPR_PROD_ID_LEN);
 974	i = strip_and_pad_whitespace(i + IPR_PROD_ID_LEN - 1, buffer);
 975
 976	memcpy(&buffer[i], vpd->sn, IPR_SERIAL_NUM_LEN);
 977	buffer[IPR_SERIAL_NUM_LEN + i] = '\0';
 978
 979	ipr_hcam_err(hostrcb, "%s VPID/SN: %s\n", prefix, buffer);
 980}
 981
 982/**
 983 * ipr_log_vpd - Log the passed VPD to the error log.
 984 * @vpd:		vendor/product id/sn struct
 985 *
 986 * Return value:
 987 * 	none
 988 **/
 989static void ipr_log_vpd(struct ipr_vpd *vpd)
 990{
 991	char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN
 992		    + IPR_SERIAL_NUM_LEN];
 993
 994	memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
 995	memcpy(buffer + IPR_VENDOR_ID_LEN, vpd->vpids.product_id,
 996	       IPR_PROD_ID_LEN);
 997	buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN] = '\0';
 998	ipr_err("Vendor/Product ID: %s\n", buffer);
 999
1000	memcpy(buffer, vpd->sn, IPR_SERIAL_NUM_LEN);
1001	buffer[IPR_SERIAL_NUM_LEN] = '\0';
1002	ipr_err("    Serial Number: %s\n", buffer);
1003}
1004
1005/**
1006 * ipr_log_ext_vpd_compact - Log the passed extended VPD compactly.
1007 * @prefix:		string to print at start of printk
1008 * @hostrcb:	hostrcb pointer
1009 * @vpd:		vendor/product id/sn/wwn struct
1010 *
1011 * Return value:
1012 * 	none
1013 **/
1014static void ipr_log_ext_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
1015				    struct ipr_ext_vpd *vpd)
1016{
1017	ipr_log_vpd_compact(prefix, hostrcb, &vpd->vpd);
1018	ipr_hcam_err(hostrcb, "%s WWN: %08X%08X\n", prefix,
1019		     be32_to_cpu(vpd->wwid[0]), be32_to_cpu(vpd->wwid[1]));
1020}
1021
1022/**
1023 * ipr_log_ext_vpd - Log the passed extended VPD to the error log.
1024 * @vpd:		vendor/product id/sn/wwn struct
1025 *
1026 * Return value:
1027 * 	none
1028 **/
1029static void ipr_log_ext_vpd(struct ipr_ext_vpd *vpd)
1030{
1031	ipr_log_vpd(&vpd->vpd);
1032	ipr_err("    WWN: %08X%08X\n", be32_to_cpu(vpd->wwid[0]),
1033		be32_to_cpu(vpd->wwid[1]));
1034}
1035
1036/**
1037 * ipr_log_enhanced_cache_error - Log a cache error.
1038 * @ioa_cfg:	ioa config struct
1039 * @hostrcb:	hostrcb struct
1040 *
1041 * Return value:
1042 * 	none
1043 **/
1044static void ipr_log_enhanced_cache_error(struct ipr_ioa_cfg *ioa_cfg,
1045					 struct ipr_hostrcb *hostrcb)
1046{
1047	struct ipr_hostrcb_type_12_error *error =
1048		&hostrcb->hcam.u.error.u.type_12_error;
1049
1050	ipr_err("-----Current Configuration-----\n");
1051	ipr_err("Cache Directory Card Information:\n");
1052	ipr_log_ext_vpd(&error->ioa_vpd);
1053	ipr_err("Adapter Card Information:\n");
1054	ipr_log_ext_vpd(&error->cfc_vpd);
1055
1056	ipr_err("-----Expected Configuration-----\n");
1057	ipr_err("Cache Directory Card Information:\n");
1058	ipr_log_ext_vpd(&error->ioa_last_attached_to_cfc_vpd);
1059	ipr_err("Adapter Card Information:\n");
1060	ipr_log_ext_vpd(&error->cfc_last_attached_to_ioa_vpd);
1061
1062	ipr_err("Additional IOA Data: %08X %08X %08X\n",
1063		     be32_to_cpu(error->ioa_data[0]),
1064		     be32_to_cpu(error->ioa_data[1]),
1065		     be32_to_cpu(error->ioa_data[2]));
1066}
1067
1068/**
1069 * ipr_log_cache_error - Log a cache error.
1070 * @ioa_cfg:	ioa config struct
1071 * @hostrcb:	hostrcb struct
1072 *
1073 * Return value:
1074 * 	none
1075 **/
1076static void ipr_log_cache_error(struct ipr_ioa_cfg *ioa_cfg,
1077				struct ipr_hostrcb *hostrcb)
1078{
1079	struct ipr_hostrcb_type_02_error *error =
1080		&hostrcb->hcam.u.error.u.type_02_error;
1081
1082	ipr_err("-----Current Configuration-----\n");
1083	ipr_err("Cache Directory Card Information:\n");
1084	ipr_log_vpd(&error->ioa_vpd);
1085	ipr_err("Adapter Card Information:\n");
1086	ipr_log_vpd(&error->cfc_vpd);
1087
1088	ipr_err("-----Expected Configuration-----\n");
1089	ipr_err("Cache Directory Card Information:\n");
1090	ipr_log_vpd(&error->ioa_last_attached_to_cfc_vpd);
1091	ipr_err("Adapter Card Information:\n");
1092	ipr_log_vpd(&error->cfc_last_attached_to_ioa_vpd);
1093
1094	ipr_err("Additional IOA Data: %08X %08X %08X\n",
1095		     be32_to_cpu(error->ioa_data[0]),
1096		     be32_to_cpu(error->ioa_data[1]),
1097		     be32_to_cpu(error->ioa_data[2]));
1098}
1099
1100/**
1101 * ipr_log_enhanced_config_error - Log a configuration error.
1102 * @ioa_cfg:	ioa config struct
1103 * @hostrcb:	hostrcb struct
1104 *
1105 * Return value:
1106 * 	none
1107 **/
1108static void ipr_log_enhanced_config_error(struct ipr_ioa_cfg *ioa_cfg,
1109					  struct ipr_hostrcb *hostrcb)
1110{
1111	int errors_logged, i;
1112	struct ipr_hostrcb_device_data_entry_enhanced *dev_entry;
1113	struct ipr_hostrcb_type_13_error *error;
1114
1115	error = &hostrcb->hcam.u.error.u.type_13_error;
1116	errors_logged = be32_to_cpu(error->errors_logged);
1117
1118	ipr_err("Device Errors Detected/Logged: %d/%d\n",
1119		be32_to_cpu(error->errors_detected), errors_logged);
1120
1121	dev_entry = error->dev;
1122
1123	for (i = 0; i < errors_logged; i++, dev_entry++) {
1124		ipr_err_separator;
1125
1126		ipr_phys_res_err(ioa_cfg, dev_entry->dev_res_addr, "Device %d", i + 1);
1127		ipr_log_ext_vpd(&dev_entry->vpd);
1128
1129		ipr_err("-----New Device Information-----\n");
1130		ipr_log_ext_vpd(&dev_entry->new_vpd);
1131
1132		ipr_err("Cache Directory Card Information:\n");
1133		ipr_log_ext_vpd(&dev_entry->ioa_last_with_dev_vpd);
1134
1135		ipr_err("Adapter Card Information:\n");
1136		ipr_log_ext_vpd(&dev_entry->cfc_last_with_dev_vpd);
1137	}
1138}
1139
1140/**
1141 * ipr_log_config_error - Log a configuration error.
1142 * @ioa_cfg:	ioa config struct
1143 * @hostrcb:	hostrcb struct
1144 *
1145 * Return value:
1146 * 	none
1147 **/
1148static void ipr_log_config_error(struct ipr_ioa_cfg *ioa_cfg,
1149				 struct ipr_hostrcb *hostrcb)
1150{
1151	int errors_logged, i;
1152	struct ipr_hostrcb_device_data_entry *dev_entry;
1153	struct ipr_hostrcb_type_03_error *error;
1154
1155	error = &hostrcb->hcam.u.error.u.type_03_error;
1156	errors_logged = be32_to_cpu(error->errors_logged);
1157
1158	ipr_err("Device Errors Detected/Logged: %d/%d\n",
1159		be32_to_cpu(error->errors_detected), errors_logged);
1160
1161	dev_entry = error->dev;
1162
1163	for (i = 0; i < errors_logged; i++, dev_entry++) {
1164		ipr_err_separator;
1165
1166		ipr_phys_res_err(ioa_cfg, dev_entry->dev_res_addr, "Device %d", i + 1);
1167		ipr_log_vpd(&dev_entry->vpd);
1168
1169		ipr_err("-----New Device Information-----\n");
1170		ipr_log_vpd(&dev_entry->new_vpd);
1171
1172		ipr_err("Cache Directory Card Information:\n");
1173		ipr_log_vpd(&dev_entry->ioa_last_with_dev_vpd);
1174
1175		ipr_err("Adapter Card Information:\n");
1176		ipr_log_vpd(&dev_entry->cfc_last_with_dev_vpd);
1177
1178		ipr_err("Additional IOA Data: %08X %08X %08X %08X %08X\n",
1179			be32_to_cpu(dev_entry->ioa_data[0]),
1180			be32_to_cpu(dev_entry->ioa_data[1]),
1181			be32_to_cpu(dev_entry->ioa_data[2]),
1182			be32_to_cpu(dev_entry->ioa_data[3]),
1183			be32_to_cpu(dev_entry->ioa_data[4]));
1184	}
1185}
1186
1187/**
1188 * ipr_log_enhanced_array_error - Log an array configuration error.
1189 * @ioa_cfg:	ioa config struct
1190 * @hostrcb:	hostrcb struct
1191 *
1192 * Return value:
1193 * 	none
1194 **/
1195static void ipr_log_enhanced_array_error(struct ipr_ioa_cfg *ioa_cfg,
1196					 struct ipr_hostrcb *hostrcb)
1197{
1198	int i, num_entries;
1199	struct ipr_hostrcb_type_14_error *error;
1200	struct ipr_hostrcb_array_data_entry_enhanced *array_entry;
1201	const u8 zero_sn[IPR_SERIAL_NUM_LEN] = { [0 ... IPR_SERIAL_NUM_LEN-1] = '0' };
1202
1203	error = &hostrcb->hcam.u.error.u.type_14_error;
1204
1205	ipr_err_separator;
1206
1207	ipr_err("RAID %s Array Configuration: %d:%d:%d:%d\n",
1208		error->protection_level,
1209		ioa_cfg->host->host_no,
1210		error->last_func_vset_res_addr.bus,
1211		error->last_func_vset_res_addr.target,
1212		error->last_func_vset_res_addr.lun);
1213
1214	ipr_err_separator;
1215
1216	array_entry = error->array_member;
1217	num_entries = min_t(u32, be32_to_cpu(error->num_entries),
1218			    sizeof(error->array_member));
1219
1220	for (i = 0; i < num_entries; i++, array_entry++) {
1221		if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN))
1222			continue;
1223
1224		if (be32_to_cpu(error->exposed_mode_adn) == i)
1225			ipr_err("Exposed Array Member %d:\n", i);
1226		else
1227			ipr_err("Array Member %d:\n", i);
1228
1229		ipr_log_ext_vpd(&array_entry->vpd);
1230		ipr_phys_res_err(ioa_cfg, array_entry->dev_res_addr, "Current Location");
1231		ipr_phys_res_err(ioa_cfg, array_entry->expected_dev_res_addr,
1232				 "Expected Location");
1233
1234		ipr_err_separator;
1235	}
1236}
1237
1238/**
1239 * ipr_log_array_error - Log an array configuration error.
1240 * @ioa_cfg:	ioa config struct
1241 * @hostrcb:	hostrcb struct
1242 *
1243 * Return value:
1244 * 	none
1245 **/
1246static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg,
1247				struct ipr_hostrcb *hostrcb)
1248{
1249	int i;
1250	struct ipr_hostrcb_type_04_error *error;
1251	struct ipr_hostrcb_array_data_entry *array_entry;
1252	const u8 zero_sn[IPR_SERIAL_NUM_LEN] = { [0 ... IPR_SERIAL_NUM_LEN-1] = '0' };
1253
1254	error = &hostrcb->hcam.u.error.u.type_04_error;
1255
1256	ipr_err_separator;
1257
1258	ipr_err("RAID %s Array Configuration: %d:%d:%d:%d\n",
1259		error->protection_level,
1260		ioa_cfg->host->host_no,
1261		error->last_func_vset_res_addr.bus,
1262		error->last_func_vset_res_addr.target,
1263		error->last_func_vset_res_addr.lun);
1264
1265	ipr_err_separator;
1266
1267	array_entry = error->array_member;
1268
1269	for (i = 0; i < 18; i++) {
1270		if (!memcmp(array_entry->vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN))
1271			continue;
1272
1273		if (be32_to_cpu(error->exposed_mode_adn) == i)
1274			ipr_err("Exposed Array Member %d:\n", i);
1275		else
1276			ipr_err("Array Member %d:\n", i);
1277
1278		ipr_log_vpd(&array_entry->vpd);
1279
1280		ipr_phys_res_err(ioa_cfg, array_entry->dev_res_addr, "Current Location");
1281		ipr_phys_res_err(ioa_cfg, array_entry->expected_dev_res_addr,
1282				 "Expected Location");
1283
1284		ipr_err_separator;
1285
1286		if (i == 9)
1287			array_entry = error->array_member2;
1288		else
1289			array_entry++;
1290	}
1291}
1292
1293/**
1294 * ipr_log_hex_data - Log additional hex IOA error data.
1295 * @ioa_cfg:	ioa config struct
1296 * @data:		IOA error data
1297 * @len:		data length
1298 *
1299 * Return value:
1300 * 	none
1301 **/
1302static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, u32 *data, int len)
1303{
1304	int i;
1305
1306	if (len == 0)
1307		return;
1308
1309	if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL)
1310		len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP);
1311
1312	for (i = 0; i < len / 4; i += 4) {
1313		ipr_err("%08X: %08X %08X %08X %08X\n", i*4,
1314			be32_to_cpu(data[i]),
1315			be32_to_cpu(data[i+1]),
1316			be32_to_cpu(data[i+2]),
1317			be32_to_cpu(data[i+3]));
1318	}
1319}
1320
1321/**
1322 * ipr_log_enhanced_dual_ioa_error - Log an enhanced dual adapter error.
1323 * @ioa_cfg:	ioa config struct
1324 * @hostrcb:	hostrcb struct
1325 *
1326 * Return value:
1327 * 	none
1328 **/
1329static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
1330					    struct ipr_hostrcb *hostrcb)
1331{
1332	struct ipr_hostrcb_type_17_error *error;
1333
1334	error = &hostrcb->hcam.u.error.u.type_17_error;
1335	error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
1336	strstrip(error->failure_reason);
1337
1338	ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason,
1339		     be32_to_cpu(hostrcb->hcam.u.error.prc));
1340	ipr_log_ext_vpd_compact("Remote IOA", hostrcb, &error->vpd);
1341	ipr_log_hex_data(ioa_cfg, error->data,
1342			 be32_to_cpu(hostrcb->hcam.length) -
1343			 (offsetof(struct ipr_hostrcb_error, u) +
1344			  offsetof(struct ipr_hostrcb_type_17_error, data)));
1345}
1346
1347/**
1348 * ipr_log_dual_ioa_error - Log a dual adapter error.
1349 * @ioa_cfg:	ioa config struct
1350 * @hostrcb:	hostrcb struct
1351 *
1352 * Return value:
1353 * 	none
1354 **/
1355static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
1356				   struct ipr_hostrcb *hostrcb)
1357{
1358	struct ipr_hostrcb_type_07_error *error;
1359
1360	error = &hostrcb->hcam.u.error.u.type_07_error;
1361	error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
1362	strstrip(error->failure_reason);
1363
1364	ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason,
1365		     be32_to_cpu(hostrcb->hcam.u.error.prc));
1366	ipr_log_vpd_compact("Remote IOA", hostrcb, &error->vpd);
1367	ipr_log_hex_data(ioa_cfg, error->data,
1368			 be32_to_cpu(hostrcb->hcam.length) -
1369			 (offsetof(struct ipr_hostrcb_error, u) +
1370			  offsetof(struct ipr_hostrcb_type_07_error, data)));
1371}
1372
1373static const struct {
1374	u8 active;
1375	char *desc;
1376} path_active_desc[] = {
1377	{ IPR_PATH_NO_INFO, "Path" },
1378	{ IPR_PATH_ACTIVE, "Active path" },
1379	{ IPR_PATH_NOT_ACTIVE, "Inactive path" }
1380};
1381
1382static const struct {
1383	u8 state;
1384	char *desc;
1385} path_state_desc[] = {
1386	{ IPR_PATH_STATE_NO_INFO, "has no path state information available" },
1387	{ IPR_PATH_HEALTHY, "is healthy" },
1388	{ IPR_PATH_DEGRADED, "is degraded" },
1389	{ IPR_PATH_FAILED, "is failed" }
1390};
1391
1392/**
1393 * ipr_log_fabric_path - Log a fabric path error
1394 * @hostrcb:	hostrcb struct
1395 * @fabric:		fabric descriptor
1396 *
1397 * Return value:
1398 * 	none
1399 **/
1400static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb,
1401				struct ipr_hostrcb_fabric_desc *fabric)
1402{
1403	int i, j;
1404	u8 path_state = fabric->path_state;
1405	u8 active = path_state & IPR_PATH_ACTIVE_MASK;
1406	u8 state = path_state & IPR_PATH_STATE_MASK;
1407
1408	for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) {
1409		if (path_active_desc[i].active != active)
1410			continue;
1411
1412		for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) {
1413			if (path_state_desc[j].state != state)
1414				continue;
1415
1416			if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) {
1417				ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n",
1418					     path_active_desc[i].desc, path_state_desc[j].desc,
1419					     fabric->ioa_port);
1420			} else if (fabric->cascaded_expander == 0xff) {
1421				ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n",
1422					     path_active_desc[i].desc, path_state_desc[j].desc,
1423					     fabric->ioa_port, fabric->phy);
1424			} else if (fabric->phy == 0xff) {
1425				ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n",
1426					     path_active_desc[i].desc, path_state_desc[j].desc,
1427					     fabric->ioa_port, fabric->cascaded_expander);
1428			} else {
1429				ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n",
1430					     path_active_desc[i].desc, path_state_desc[j].desc,
1431					     fabric->ioa_port, fabric->cascaded_expander, fabric->phy);
1432			}
1433			return;
1434		}
1435	}
1436
1437	ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state,
1438		fabric->ioa_port, fabric->cascaded_expander, fabric->phy);
1439}
1440
1441static const struct {
1442	u8 type;
1443	char *desc;
1444} path_type_desc[] = {
1445	{ IPR_PATH_CFG_IOA_PORT, "IOA port" },
1446	{ IPR_PATH_CFG_EXP_PORT, "Expander port" },
1447	{ IPR_PATH_CFG_DEVICE_PORT, "Device port" },
1448	{ IPR_PATH_CFG_DEVICE_LUN, "Device LUN" }
1449};
1450
1451static const struct {
1452	u8 status;
1453	char *desc;
1454} path_status_desc[] = {
1455	{ IPR_PATH_CFG_NO_PROB, "Functional" },
1456	{ IPR_PATH_CFG_DEGRADED, "Degraded" },
1457	{ IPR_PATH_CFG_FAILED, "Failed" },
1458	{ IPR_PATH_CFG_SUSPECT, "Suspect" },
1459	{ IPR_PATH_NOT_DETECTED, "Missing" },
1460	{ IPR_PATH_INCORRECT_CONN, "Incorrectly connected" }
1461};
1462
1463static const char *link_rate[] = {
1464	"unknown",
1465	"disabled",
1466	"phy reset problem",
1467	"spinup hold",
1468	"port selector",
1469	"unknown",
1470	"unknown",
1471	"unknown",
1472	"1.5Gbps",
1473	"3.0Gbps",
1474	"unknown",
1475	"unknown",
1476	"unknown",
1477	"unknown",
1478	"unknown",
1479	"unknown"
1480};
1481
1482/**
1483 * ipr_log_path_elem - Log a fabric path element.
1484 * @hostrcb:	hostrcb struct
1485 * @cfg:		fabric path element struct
1486 *
1487 * Return value:
1488 * 	none
1489 **/
1490static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb,
1491			      struct ipr_hostrcb_config_element *cfg)
1492{
1493	int i, j;
1494	u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK;
1495	u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK;
1496
1497	if (type == IPR_PATH_CFG_NOT_EXIST)
1498		return;
1499
1500	for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) {
1501		if (path_type_desc[i].type != type)
1502			continue;
1503
1504		for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) {
1505			if (path_status_desc[j].status != status)
1506				continue;
1507
1508			if (type == IPR_PATH_CFG_IOA_PORT) {
1509				ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n",
1510					     path_status_desc[j].desc, path_type_desc[i].desc,
1511					     cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1512					     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1513			} else {
1514				if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) {
1515					ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n",
1516						     path_status_desc[j].desc, path_type_desc[i].desc,
1517						     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1518						     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1519				} else if (cfg->cascaded_expander == 0xff) {
1520					ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, "
1521						     "WWN=%08X%08X\n", path_status_desc[j].desc,
1522						     path_type_desc[i].desc, cfg->phy,
1523						     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1524						     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1525				} else if (cfg->phy == 0xff) {
1526					ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, "
1527						     "WWN=%08X%08X\n", path_status_desc[j].desc,
1528						     path_type_desc[i].desc, cfg->cascaded_expander,
1529						     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1530						     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1531				} else {
1532					ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s "
1533						     "WWN=%08X%08X\n", path_status_desc[j].desc,
1534						     path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy,
1535						     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1536						     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1537				}
1538			}
1539			return;
1540		}
1541	}
1542
1543	ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s "
1544		     "WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy,
1545		     link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1546		     be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1547}
1548
1549/**
1550 * ipr_log_fabric_error - Log a fabric error.
1551 * @ioa_cfg:	ioa config struct
1552 * @hostrcb:	hostrcb struct
1553 *
1554 * Return value:
1555 * 	none
1556 **/
1557static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg,
1558				 struct ipr_hostrcb *hostrcb)
1559{
1560	struct ipr_hostrcb_type_20_error *error;
1561	struct ipr_hostrcb_fabric_desc *fabric;
1562	struct ipr_hostrcb_config_element *cfg;
1563	int i, add_len;
1564
1565	error = &hostrcb->hcam.u.error.u.type_20_error;
1566	error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
1567	ipr_hcam_err(hostrcb, "%s\n", error->failure_reason);
1568
1569	add_len = be32_to_cpu(hostrcb->hcam.length) -
1570		(offsetof(struct ipr_hostrcb_error, u) +
1571		 offsetof(struct ipr_hostrcb_type_20_error, desc));
1572
1573	for (i = 0, fabric = error->desc; i < error->num_entries; i++) {
1574		ipr_log_fabric_path(hostrcb, fabric);
1575		for_each_fabric_cfg(fabric, cfg)
1576			ipr_log_path_elem(hostrcb, cfg);
1577
1578		add_len -= be16_to_cpu(fabric->length);
1579		fabric = (struct ipr_hostrcb_fabric_desc *)
1580			((unsigned long)fabric + be16_to_cpu(fabric->length));
1581	}
1582
1583	ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len);
1584}
1585
1586/**
1587 * ipr_log_generic_error - Log an adapter error.
1588 * @ioa_cfg:	ioa config struct
1589 * @hostrcb:	hostrcb struct
1590 *
1591 * Return value:
1592 * 	none
1593 **/
1594static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg,
1595				  struct ipr_hostrcb *hostrcb)
1596{
1597	ipr_log_hex_data(ioa_cfg, hostrcb->hcam.u.raw.data,
1598			 be32_to_cpu(hostrcb->hcam.length));
1599}
1600
1601/**
1602 * ipr_get_error - Find the specfied IOASC in the ipr_error_table.
1603 * @ioasc:	IOASC
1604 *
1605 * This function will return the index of into the ipr_error_table
1606 * for the specified IOASC. If the IOASC is not in the table,
1607

Large files files are truncated, but you can click here to view the full file