aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/ipr.c
diff options
context:
space:
mode:
authorBrian King <brking@us.ibm.com>2006-11-21 11:28:35 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-22 13:21:44 -0500
commit49dc6a18185c12bae4980d17512fbe54ca6bae54 (patch)
treedc3e9dc84647d485622c42b9715dceee00ecab19 /drivers/scsi/ipr.c
parent9d66bdf81f97673b6e330a26438fcaea38c26cd5 (diff)
[SCSI] ipr: Add support for logging SAS fabric errors
Adds support for logging SAS fabric errors logged by the ipr firmware. Signed-off-by: Brian King <brking@us.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r--drivers/scsi/ipr.c225
1 files changed, 218 insertions, 7 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index e53cfbd0e076..94345e79ef1e 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -1321,6 +1321,219 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
1321 offsetof(struct ipr_hostrcb_type_07_error, data))); 1321 offsetof(struct ipr_hostrcb_type_07_error, data)));
1322} 1322}
1323 1323
1324static const struct {
1325 u8 active;
1326 char *desc;
1327} path_active_desc[] = {
1328 { IPR_PATH_NO_INFO, "Path" },
1329 { IPR_PATH_ACTIVE, "Active path" },
1330 { IPR_PATH_NOT_ACTIVE, "Inactive path" }
1331};
1332
1333static const struct {
1334 u8 state;
1335 char *desc;
1336} path_state_desc[] = {
1337 { IPR_PATH_STATE_NO_INFO, "has no path state information available" },
1338 { IPR_PATH_HEALTHY, "is healthy" },
1339 { IPR_PATH_DEGRADED, "is degraded" },
1340 { IPR_PATH_FAILED, "is failed" }
1341};
1342
1343/**
1344 * ipr_log_fabric_path - Log a fabric path error
1345 * @hostrcb: hostrcb struct
1346 * @fabric: fabric descriptor
1347 *
1348 * Return value:
1349 * none
1350 **/
1351static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb,
1352 struct ipr_hostrcb_fabric_desc *fabric)
1353{
1354 int i, j;
1355 u8 path_state = fabric->path_state;
1356 u8 active = path_state & IPR_PATH_ACTIVE_MASK;
1357 u8 state = path_state & IPR_PATH_STATE_MASK;
1358
1359 for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) {
1360 if (path_active_desc[i].active != active)
1361 continue;
1362
1363 for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) {
1364 if (path_state_desc[j].state != state)
1365 continue;
1366
1367 if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) {
1368 ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n",
1369 path_active_desc[i].desc, path_state_desc[j].desc,
1370 fabric->ioa_port);
1371 } else if (fabric->cascaded_expander == 0xff) {
1372 ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n",
1373 path_active_desc[i].desc, path_state_desc[j].desc,
1374 fabric->ioa_port, fabric->phy);
1375 } else if (fabric->phy == 0xff) {
1376 ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n",
1377 path_active_desc[i].desc, path_state_desc[j].desc,
1378 fabric->ioa_port, fabric->cascaded_expander);
1379 } else {
1380 ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n",
1381 path_active_desc[i].desc, path_state_desc[j].desc,
1382 fabric->ioa_port, fabric->cascaded_expander, fabric->phy);
1383 }
1384 return;
1385 }
1386 }
1387
1388 ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state,
1389 fabric->ioa_port, fabric->cascaded_expander, fabric->phy);
1390}
1391
1392static const struct {
1393 u8 type;
1394 char *desc;
1395} path_type_desc[] = {
1396 { IPR_PATH_CFG_IOA_PORT, "IOA port" },
1397 { IPR_PATH_CFG_EXP_PORT, "Expander port" },
1398 { IPR_PATH_CFG_DEVICE_PORT, "Device port" },
1399 { IPR_PATH_CFG_DEVICE_LUN, "Device LUN" }
1400};
1401
1402static const struct {
1403 u8 status;
1404 char *desc;
1405} path_status_desc[] = {
1406 { IPR_PATH_CFG_NO_PROB, "Functional" },
1407 { IPR_PATH_CFG_DEGRADED, "Degraded" },
1408 { IPR_PATH_CFG_FAILED, "Failed" },
1409 { IPR_PATH_CFG_SUSPECT, "Suspect" },
1410 { IPR_PATH_NOT_DETECTED, "Missing" },
1411 { IPR_PATH_INCORRECT_CONN, "Incorrectly connected" }
1412};
1413
1414static const char *link_rate[] = {
1415 "unknown",
1416 "disabled",
1417 "phy reset problem",
1418 "spinup hold",
1419 "port selector",
1420 "unknown",
1421 "unknown",
1422 "unknown",
1423 "1.5Gbps",
1424 "3.0Gbps",
1425 "unknown",
1426 "unknown",
1427 "unknown",
1428 "unknown",
1429 "unknown",
1430 "unknown"
1431};
1432
1433/**
1434 * ipr_log_path_elem - Log a fabric path element.
1435 * @hostrcb: hostrcb struct
1436 * @cfg: fabric path element struct
1437 *
1438 * Return value:
1439 * none
1440 **/
1441static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb,
1442 struct ipr_hostrcb_config_element *cfg)
1443{
1444 int i, j;
1445 u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK;
1446 u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK;
1447
1448 if (type == IPR_PATH_CFG_NOT_EXIST)
1449 return;
1450
1451 for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) {
1452 if (path_type_desc[i].type != type)
1453 continue;
1454
1455 for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) {
1456 if (path_status_desc[j].status != status)
1457 continue;
1458
1459 if (type == IPR_PATH_CFG_IOA_PORT) {
1460 ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n",
1461 path_status_desc[j].desc, path_type_desc[i].desc,
1462 cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1463 be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1464 } else {
1465 if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) {
1466 ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n",
1467 path_status_desc[j].desc, path_type_desc[i].desc,
1468 link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1469 be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1470 } else if (cfg->cascaded_expander == 0xff) {
1471 ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, "
1472 "WWN=%08X%08X\n", path_status_desc[j].desc,
1473 path_type_desc[i].desc, cfg->phy,
1474 link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1475 be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1476 } else if (cfg->phy == 0xff) {
1477 ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, "
1478 "WWN=%08X%08X\n", path_status_desc[j].desc,
1479 path_type_desc[i].desc, cfg->cascaded_expander,
1480 link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1481 be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1482 } else {
1483 ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s "
1484 "WWN=%08X%08X\n", path_status_desc[j].desc,
1485 path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy,
1486 link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1487 be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1488 }
1489 }
1490 return;
1491 }
1492 }
1493
1494 ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s "
1495 "WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy,
1496 link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
1497 be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
1498}
1499
1500/**
1501 * ipr_log_fabric_error - Log a fabric error.
1502 * @ioa_cfg: ioa config struct
1503 * @hostrcb: hostrcb struct
1504 *
1505 * Return value:
1506 * none
1507 **/
1508static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg,
1509 struct ipr_hostrcb *hostrcb)
1510{
1511 struct ipr_hostrcb_type_20_error *error;
1512 struct ipr_hostrcb_fabric_desc *fabric;
1513 struct ipr_hostrcb_config_element *cfg;
1514 int i, add_len;
1515
1516 error = &hostrcb->hcam.u.error.u.type_20_error;
1517 error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
1518 ipr_hcam_err(hostrcb, "%s\n", error->failure_reason);
1519
1520 add_len = be32_to_cpu(hostrcb->hcam.length) -
1521 (offsetof(struct ipr_hostrcb_error, u) +
1522 offsetof(struct ipr_hostrcb_type_20_error, desc));
1523
1524 for (i = 0, fabric = error->desc; i < error->num_entries; i++) {
1525 ipr_log_fabric_path(hostrcb, fabric);
1526 for_each_fabric_cfg(fabric, cfg)
1527 ipr_log_path_elem(hostrcb, cfg);
1528
1529 add_len -= be16_to_cpu(fabric->length);
1530 fabric = (struct ipr_hostrcb_fabric_desc *)
1531 ((unsigned long)fabric + be16_to_cpu(fabric->length));
1532 }
1533
1534 ipr_log_hex_data((u32 *)fabric, add_len);
1535}
1536
1324/** 1537/**
1325 * ipr_log_generic_error - Log an adapter error. 1538 * ipr_log_generic_error - Log an adapter error.
1326 * @ioa_cfg: ioa config struct 1539 * @ioa_cfg: ioa config struct
@@ -1394,13 +1607,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
1394 if (!ipr_error_table[error_index].log_hcam) 1607 if (!ipr_error_table[error_index].log_hcam)
1395 return; 1608 return;
1396 1609
1397 if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) { 1610 ipr_hcam_err(hostrcb, "%s\n", ipr_error_table[error_index].error);
1398 ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
1399 "%s\n", ipr_error_table[error_index].error);
1400 } else {
1401 dev_err(&ioa_cfg->pdev->dev, "%s\n",
1402 ipr_error_table[error_index].error);
1403 }
1404 1611
1405 /* Set indication we have logged an error */ 1612 /* Set indication we have logged an error */
1406 ioa_cfg->errors_logged++; 1613 ioa_cfg->errors_logged++;
@@ -1437,6 +1644,9 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
1437 case IPR_HOST_RCB_OVERLAY_ID_17: 1644 case IPR_HOST_RCB_OVERLAY_ID_17:
1438 ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); 1645 ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb);
1439 break; 1646 break;
1647 case IPR_HOST_RCB_OVERLAY_ID_20:
1648 ipr_log_fabric_error(ioa_cfg, hostrcb);
1649 break;
1440 case IPR_HOST_RCB_OVERLAY_ID_1: 1650 case IPR_HOST_RCB_OVERLAY_ID_1:
1441 case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: 1651 case IPR_HOST_RCB_OVERLAY_ID_DEFAULT:
1442 default: 1652 default:
@@ -6812,6 +7022,7 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
6812 7022
6813 ioa_cfg->hostrcb[i]->hostrcb_dma = 7023 ioa_cfg->hostrcb[i]->hostrcb_dma =
6814 ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam); 7024 ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam);
7025 ioa_cfg->hostrcb[i]->ioa_cfg = ioa_cfg;
6815 list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q); 7026 list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q);
6816 } 7027 }
6817 7028