aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
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
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')
-rw-r--r--drivers/scsi/ipr.c225
-rw-r--r--drivers/scsi/ipr.h72
2 files changed, 290 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
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 75669251fb63..44b15e4b6edf 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -737,6 +737,64 @@ struct ipr_hostrcb_type_17_error {
737 u32 data[476]; 737 u32 data[476];
738}__attribute__((packed, aligned (4))); 738}__attribute__((packed, aligned (4)));
739 739
740struct ipr_hostrcb_config_element {
741 u8 type_status;
742#define IPR_PATH_CFG_TYPE_MASK 0xF0
743#define IPR_PATH_CFG_NOT_EXIST 0x00
744#define IPR_PATH_CFG_IOA_PORT 0x10
745#define IPR_PATH_CFG_EXP_PORT 0x20
746#define IPR_PATH_CFG_DEVICE_PORT 0x30
747#define IPR_PATH_CFG_DEVICE_LUN 0x40
748
749#define IPR_PATH_CFG_STATUS_MASK 0x0F
750#define IPR_PATH_CFG_NO_PROB 0x00
751#define IPR_PATH_CFG_DEGRADED 0x01
752#define IPR_PATH_CFG_FAILED 0x02
753#define IPR_PATH_CFG_SUSPECT 0x03
754#define IPR_PATH_NOT_DETECTED 0x04
755#define IPR_PATH_INCORRECT_CONN 0x05
756
757 u8 cascaded_expander;
758 u8 phy;
759 u8 link_rate;
760#define IPR_PHY_LINK_RATE_MASK 0x0F
761
762 __be32 wwid[2];
763}__attribute__((packed, aligned (4)));
764
765struct ipr_hostrcb_fabric_desc {
766 __be16 length;
767 u8 ioa_port;
768 u8 cascaded_expander;
769 u8 phy;
770 u8 path_state;
771#define IPR_PATH_ACTIVE_MASK 0xC0
772#define IPR_PATH_NO_INFO 0x00
773#define IPR_PATH_ACTIVE 0x40
774#define IPR_PATH_NOT_ACTIVE 0x80
775
776#define IPR_PATH_STATE_MASK 0x0F
777#define IPR_PATH_STATE_NO_INFO 0x00
778#define IPR_PATH_HEALTHY 0x01
779#define IPR_PATH_DEGRADED 0x02
780#define IPR_PATH_FAILED 0x03
781
782 __be16 num_entries;
783 struct ipr_hostrcb_config_element elem[1];
784}__attribute__((packed, aligned (4)));
785
786#define for_each_fabric_cfg(fabric, cfg) \
787 for (cfg = (fabric)->elem; \
788 cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \
789 cfg++)
790
791struct ipr_hostrcb_type_20_error {
792 u8 failure_reason[64];
793 u8 reserved[3];
794 u8 num_entries;
795 struct ipr_hostrcb_fabric_desc desc[1];
796}__attribute__((packed, aligned (4)));
797
740struct ipr_hostrcb_error { 798struct ipr_hostrcb_error {
741 __be32 failing_dev_ioasc; 799 __be32 failing_dev_ioasc;
742 struct ipr_res_addr failing_dev_res_addr; 800 struct ipr_res_addr failing_dev_res_addr;
@@ -753,6 +811,7 @@ struct ipr_hostrcb_error {
753 struct ipr_hostrcb_type_13_error type_13_error; 811 struct ipr_hostrcb_type_13_error type_13_error;
754 struct ipr_hostrcb_type_14_error type_14_error; 812 struct ipr_hostrcb_type_14_error type_14_error;
755 struct ipr_hostrcb_type_17_error type_17_error; 813 struct ipr_hostrcb_type_17_error type_17_error;
814 struct ipr_hostrcb_type_20_error type_20_error;
756 } u; 815 } u;
757}__attribute__((packed, aligned (4))); 816}__attribute__((packed, aligned (4)));
758 817
@@ -792,6 +851,7 @@ struct ipr_hcam {
792#define IPR_HOST_RCB_OVERLAY_ID_14 0x14 851#define IPR_HOST_RCB_OVERLAY_ID_14 0x14
793#define IPR_HOST_RCB_OVERLAY_ID_16 0x16 852#define IPR_HOST_RCB_OVERLAY_ID_16 0x16
794#define IPR_HOST_RCB_OVERLAY_ID_17 0x17 853#define IPR_HOST_RCB_OVERLAY_ID_17 0x17
854#define IPR_HOST_RCB_OVERLAY_ID_20 0x20
795#define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF 855#define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF
796 856
797 u8 reserved1[3]; 857 u8 reserved1[3];
@@ -811,6 +871,7 @@ struct ipr_hostrcb {
811 struct ipr_hcam hcam; 871 struct ipr_hcam hcam;
812 dma_addr_t hostrcb_dma; 872 dma_addr_t hostrcb_dma;
813 struct list_head queue; 873 struct list_head queue;
874 struct ipr_ioa_cfg *ioa_cfg;
814}; 875};
815 876
816/* IPR smart dump table structures */ 877/* IPR smart dump table structures */
@@ -1289,6 +1350,17 @@ struct ipr_ucode_image_header {
1289 } \ 1350 } \
1290} 1351}
1291 1352
1353#define ipr_hcam_err(hostrcb, fmt, ...) \
1354{ \
1355 if (ipr_is_device(&(hostrcb)->hcam.u.error.failing_dev_res_addr)) { \
1356 ipr_ra_err((hostrcb)->ioa_cfg, \
1357 (hostrcb)->hcam.u.error.failing_dev_res_addr, \
1358 fmt, ##__VA_ARGS__); \
1359 } else { \
1360 dev_err(&(hostrcb)->ioa_cfg->pdev->dev, fmt, ##__VA_ARGS__); \
1361 } \
1362}
1363
1292#define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\ 1364#define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\
1293 __FILE__, __FUNCTION__, __LINE__) 1365 __FILE__, __FUNCTION__, __LINE__)
1294 1366