diff options
author | Wayne Boyer <wayneb@linux.vnet.ibm.com> | 2010-02-19 16:24:07 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-03-03 05:34:59 -0500 |
commit | 4565e3706329f65b5e64328b5369c53b6ab2715c (patch) | |
tree | 08a226d36be5ba667bbd2e0224e77021338774b9 /drivers/scsi/ipr.c | |
parent | 3e7ebdfa58ddaef361f9538219e66a7226fb1e5d (diff) |
[SCSI] ipr: add error handling updates for the next generation chip
Add support for the new log data notification and overlay IDs.
Signed-off-by: Wayne Boyer <wayneb@linux.vnet.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 257 |
1 files changed, 247 insertions, 10 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 91e330a12721..b2e60bd4a0c6 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -1079,7 +1079,7 @@ static char *ipr_format_resource_path(u8 *res_path, char *buffer) | |||
1079 | 1079 | ||
1080 | sprintf(buffer, "%02X", res_path[0]); | 1080 | sprintf(buffer, "%02X", res_path[0]); |
1081 | for (i=1; res_path[i] != 0xff; i++) | 1081 | for (i=1; res_path[i] != 0xff; i++) |
1082 | sprintf(buffer, "%s:%02X", buffer, res_path[i]); | 1082 | sprintf(buffer, "%s-%02X", buffer, res_path[i]); |
1083 | 1083 | ||
1084 | return buffer; | 1084 | return buffer; |
1085 | } | 1085 | } |
@@ -1385,8 +1385,12 @@ static void ipr_log_ext_vpd(struct ipr_ext_vpd *vpd) | |||
1385 | static void ipr_log_enhanced_cache_error(struct ipr_ioa_cfg *ioa_cfg, | 1385 | static void ipr_log_enhanced_cache_error(struct ipr_ioa_cfg *ioa_cfg, |
1386 | struct ipr_hostrcb *hostrcb) | 1386 | struct ipr_hostrcb *hostrcb) |
1387 | { | 1387 | { |
1388 | struct ipr_hostrcb_type_12_error *error = | 1388 | struct ipr_hostrcb_type_12_error *error; |
1389 | &hostrcb->hcam.u.error.u.type_12_error; | 1389 | |
1390 | if (ioa_cfg->sis64) | ||
1391 | error = &hostrcb->hcam.u.error64.u.type_12_error; | ||
1392 | else | ||
1393 | error = &hostrcb->hcam.u.error.u.type_12_error; | ||
1390 | 1394 | ||
1391 | ipr_err("-----Current Configuration-----\n"); | 1395 | ipr_err("-----Current Configuration-----\n"); |
1392 | ipr_err("Cache Directory Card Information:\n"); | 1396 | ipr_err("Cache Directory Card Information:\n"); |
@@ -1479,6 +1483,48 @@ static void ipr_log_enhanced_config_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1479 | } | 1483 | } |
1480 | 1484 | ||
1481 | /** | 1485 | /** |
1486 | * ipr_log_sis64_config_error - Log a device error. | ||
1487 | * @ioa_cfg: ioa config struct | ||
1488 | * @hostrcb: hostrcb struct | ||
1489 | * | ||
1490 | * Return value: | ||
1491 | * none | ||
1492 | **/ | ||
1493 | static void ipr_log_sis64_config_error(struct ipr_ioa_cfg *ioa_cfg, | ||
1494 | struct ipr_hostrcb *hostrcb) | ||
1495 | { | ||
1496 | int errors_logged, i; | ||
1497 | struct ipr_hostrcb64_device_data_entry_enhanced *dev_entry; | ||
1498 | struct ipr_hostrcb_type_23_error *error; | ||
1499 | char buffer[IPR_MAX_RES_PATH_LENGTH]; | ||
1500 | |||
1501 | error = &hostrcb->hcam.u.error64.u.type_23_error; | ||
1502 | errors_logged = be32_to_cpu(error->errors_logged); | ||
1503 | |||
1504 | ipr_err("Device Errors Detected/Logged: %d/%d\n", | ||
1505 | be32_to_cpu(error->errors_detected), errors_logged); | ||
1506 | |||
1507 | dev_entry = error->dev; | ||
1508 | |||
1509 | for (i = 0; i < errors_logged; i++, dev_entry++) { | ||
1510 | ipr_err_separator; | ||
1511 | |||
1512 | ipr_err("Device %d : %s", i + 1, | ||
1513 | ipr_format_resource_path(&dev_entry->res_path[0], &buffer[0])); | ||
1514 | ipr_log_ext_vpd(&dev_entry->vpd); | ||
1515 | |||
1516 | ipr_err("-----New Device Information-----\n"); | ||
1517 | ipr_log_ext_vpd(&dev_entry->new_vpd); | ||
1518 | |||
1519 | ipr_err("Cache Directory Card Information:\n"); | ||
1520 | ipr_log_ext_vpd(&dev_entry->ioa_last_with_dev_vpd); | ||
1521 | |||
1522 | ipr_err("Adapter Card Information:\n"); | ||
1523 | ipr_log_ext_vpd(&dev_entry->cfc_last_with_dev_vpd); | ||
1524 | } | ||
1525 | } | ||
1526 | |||
1527 | /** | ||
1482 | * ipr_log_config_error - Log a configuration error. | 1528 | * ipr_log_config_error - Log a configuration error. |
1483 | * @ioa_cfg: ioa config struct | 1529 | * @ioa_cfg: ioa config struct |
1484 | * @hostrcb: hostrcb struct | 1530 | * @hostrcb: hostrcb struct |
@@ -1672,7 +1718,11 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1672 | { | 1718 | { |
1673 | struct ipr_hostrcb_type_17_error *error; | 1719 | struct ipr_hostrcb_type_17_error *error; |
1674 | 1720 | ||
1675 | error = &hostrcb->hcam.u.error.u.type_17_error; | 1721 | if (ioa_cfg->sis64) |
1722 | error = &hostrcb->hcam.u.error64.u.type_17_error; | ||
1723 | else | ||
1724 | error = &hostrcb->hcam.u.error.u.type_17_error; | ||
1725 | |||
1676 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; | 1726 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; |
1677 | strim(error->failure_reason); | 1727 | strim(error->failure_reason); |
1678 | 1728 | ||
@@ -1779,6 +1829,42 @@ static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb, | |||
1779 | fabric->ioa_port, fabric->cascaded_expander, fabric->phy); | 1829 | fabric->ioa_port, fabric->cascaded_expander, fabric->phy); |
1780 | } | 1830 | } |
1781 | 1831 | ||
1832 | /** | ||
1833 | * ipr_log64_fabric_path - Log a fabric path error | ||
1834 | * @hostrcb: hostrcb struct | ||
1835 | * @fabric: fabric descriptor | ||
1836 | * | ||
1837 | * Return value: | ||
1838 | * none | ||
1839 | **/ | ||
1840 | static void ipr_log64_fabric_path(struct ipr_hostrcb *hostrcb, | ||
1841 | struct ipr_hostrcb64_fabric_desc *fabric) | ||
1842 | { | ||
1843 | int i, j; | ||
1844 | u8 path_state = fabric->path_state; | ||
1845 | u8 active = path_state & IPR_PATH_ACTIVE_MASK; | ||
1846 | u8 state = path_state & IPR_PATH_STATE_MASK; | ||
1847 | char buffer[IPR_MAX_RES_PATH_LENGTH]; | ||
1848 | |||
1849 | for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) { | ||
1850 | if (path_active_desc[i].active != active) | ||
1851 | continue; | ||
1852 | |||
1853 | for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) { | ||
1854 | if (path_state_desc[j].state != state) | ||
1855 | continue; | ||
1856 | |||
1857 | ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s\n", | ||
1858 | path_active_desc[i].desc, path_state_desc[j].desc, | ||
1859 | ipr_format_resource_path(&fabric->res_path[0], &buffer[0])); | ||
1860 | return; | ||
1861 | } | ||
1862 | } | ||
1863 | |||
1864 | ipr_err("Path state=%02X Resource Path=%s\n", path_state, | ||
1865 | ipr_format_resource_path(&fabric->res_path[0], &buffer[0])); | ||
1866 | } | ||
1867 | |||
1782 | static const struct { | 1868 | static const struct { |
1783 | u8 type; | 1869 | u8 type; |
1784 | char *desc; | 1870 | char *desc; |
@@ -1888,6 +1974,49 @@ static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb, | |||
1888 | } | 1974 | } |
1889 | 1975 | ||
1890 | /** | 1976 | /** |
1977 | * ipr_log64_path_elem - Log a fabric path element. | ||
1978 | * @hostrcb: hostrcb struct | ||
1979 | * @cfg: fabric path element struct | ||
1980 | * | ||
1981 | * Return value: | ||
1982 | * none | ||
1983 | **/ | ||
1984 | static void ipr_log64_path_elem(struct ipr_hostrcb *hostrcb, | ||
1985 | struct ipr_hostrcb64_config_element *cfg) | ||
1986 | { | ||
1987 | int i, j; | ||
1988 | u8 desc_id = cfg->descriptor_id & IPR_DESCRIPTOR_MASK; | ||
1989 | u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK; | ||
1990 | u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK; | ||
1991 | char buffer[IPR_MAX_RES_PATH_LENGTH]; | ||
1992 | |||
1993 | if (type == IPR_PATH_CFG_NOT_EXIST || desc_id != IPR_DESCRIPTOR_SIS64) | ||
1994 | return; | ||
1995 | |||
1996 | for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) { | ||
1997 | if (path_type_desc[i].type != type) | ||
1998 | continue; | ||
1999 | |||
2000 | for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) { | ||
2001 | if (path_status_desc[j].status != status) | ||
2002 | continue; | ||
2003 | |||
2004 | ipr_hcam_err(hostrcb, "%s %s: Resource Path=%s, Link rate=%s, WWN=%08X%08X\n", | ||
2005 | path_status_desc[j].desc, path_type_desc[i].desc, | ||
2006 | ipr_format_resource_path(&cfg->res_path[0], &buffer[0]), | ||
2007 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
2008 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
2009 | return; | ||
2010 | } | ||
2011 | } | ||
2012 | ipr_hcam_err(hostrcb, "Path element=%02X: Resource Path=%s, Link rate=%s " | ||
2013 | "WWN=%08X%08X\n", cfg->type_status, | ||
2014 | ipr_format_resource_path(&cfg->res_path[0], &buffer[0]), | ||
2015 | link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], | ||
2016 | be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); | ||
2017 | } | ||
2018 | |||
2019 | /** | ||
1891 | * ipr_log_fabric_error - Log a fabric error. | 2020 | * ipr_log_fabric_error - Log a fabric error. |
1892 | * @ioa_cfg: ioa config struct | 2021 | * @ioa_cfg: ioa config struct |
1893 | * @hostrcb: hostrcb struct | 2022 | * @hostrcb: hostrcb struct |
@@ -1925,6 +2054,96 @@ static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, | |||
1925 | } | 2054 | } |
1926 | 2055 | ||
1927 | /** | 2056 | /** |
2057 | * ipr_log_sis64_array_error - Log a sis64 array error. | ||
2058 | * @ioa_cfg: ioa config struct | ||
2059 | * @hostrcb: hostrcb struct | ||
2060 | * | ||
2061 | * Return value: | ||
2062 | * none | ||
2063 | **/ | ||
2064 | static void ipr_log_sis64_array_error(struct ipr_ioa_cfg *ioa_cfg, | ||
2065 | struct ipr_hostrcb *hostrcb) | ||
2066 | { | ||
2067 | int i, num_entries; | ||
2068 | struct ipr_hostrcb_type_24_error *error; | ||
2069 | struct ipr_hostrcb64_array_data_entry *array_entry; | ||
2070 | char buffer[IPR_MAX_RES_PATH_LENGTH]; | ||
2071 | const u8 zero_sn[IPR_SERIAL_NUM_LEN] = { [0 ... IPR_SERIAL_NUM_LEN-1] = '0' }; | ||
2072 | |||
2073 | error = &hostrcb->hcam.u.error64.u.type_24_error; | ||
2074 | |||
2075 | ipr_err_separator; | ||
2076 | |||
2077 | ipr_err("RAID %s Array Configuration: %s\n", | ||
2078 | error->protection_level, | ||
2079 | ipr_format_resource_path(&error->last_res_path[0], &buffer[0])); | ||
2080 | |||
2081 | ipr_err_separator; | ||
2082 | |||
2083 | array_entry = error->array_member; | ||
2084 | num_entries = min_t(u32, be32_to_cpu(error->num_entries), | ||
2085 | sizeof(error->array_member)); | ||
2086 | |||
2087 | for (i = 0; i < num_entries; i++, array_entry++) { | ||
2088 | |||
2089 | if (!memcmp(array_entry->vpd.vpd.sn, zero_sn, IPR_SERIAL_NUM_LEN)) | ||
2090 | continue; | ||
2091 | |||
2092 | if (error->exposed_mode_adn == i) | ||
2093 | ipr_err("Exposed Array Member %d:\n", i); | ||
2094 | else | ||
2095 | ipr_err("Array Member %d:\n", i); | ||
2096 | |||
2097 | ipr_err("Array Member %d:\n", i); | ||
2098 | ipr_log_ext_vpd(&array_entry->vpd); | ||
2099 | ipr_err("Current Location: %s", | ||
2100 | ipr_format_resource_path(&array_entry->res_path[0], &buffer[0])); | ||
2101 | ipr_err("Expected Location: %s", | ||
2102 | ipr_format_resource_path(&array_entry->expected_res_path[0], &buffer[0])); | ||
2103 | |||
2104 | ipr_err_separator; | ||
2105 | } | ||
2106 | } | ||
2107 | |||
2108 | /** | ||
2109 | * ipr_log_sis64_fabric_error - Log a sis64 fabric error. | ||
2110 | * @ioa_cfg: ioa config struct | ||
2111 | * @hostrcb: hostrcb struct | ||
2112 | * | ||
2113 | * Return value: | ||
2114 | * none | ||
2115 | **/ | ||
2116 | static void ipr_log_sis64_fabric_error(struct ipr_ioa_cfg *ioa_cfg, | ||
2117 | struct ipr_hostrcb *hostrcb) | ||
2118 | { | ||
2119 | struct ipr_hostrcb_type_30_error *error; | ||
2120 | struct ipr_hostrcb64_fabric_desc *fabric; | ||
2121 | struct ipr_hostrcb64_config_element *cfg; | ||
2122 | int i, add_len; | ||
2123 | |||
2124 | error = &hostrcb->hcam.u.error64.u.type_30_error; | ||
2125 | |||
2126 | error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; | ||
2127 | ipr_hcam_err(hostrcb, "%s\n", error->failure_reason); | ||
2128 | |||
2129 | add_len = be32_to_cpu(hostrcb->hcam.length) - | ||
2130 | (offsetof(struct ipr_hostrcb64_error, u) + | ||
2131 | offsetof(struct ipr_hostrcb_type_30_error, desc)); | ||
2132 | |||
2133 | for (i = 0, fabric = error->desc; i < error->num_entries; i++) { | ||
2134 | ipr_log64_fabric_path(hostrcb, fabric); | ||
2135 | for_each_fabric_cfg(fabric, cfg) | ||
2136 | ipr_log64_path_elem(hostrcb, cfg); | ||
2137 | |||
2138 | add_len -= be16_to_cpu(fabric->length); | ||
2139 | fabric = (struct ipr_hostrcb64_fabric_desc *) | ||
2140 | ((unsigned long)fabric + be16_to_cpu(fabric->length)); | ||
2141 | } | ||
2142 | |||
2143 | ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len); | ||
2144 | } | ||
2145 | |||
2146 | /** | ||
1928 | * ipr_log_generic_error - Log an adapter error. | 2147 | * ipr_log_generic_error - Log an adapter error. |
1929 | * @ioa_cfg: ioa config struct | 2148 | * @ioa_cfg: ioa config struct |
1930 | * @hostrcb: hostrcb struct | 2149 | * @hostrcb: hostrcb struct |
@@ -1983,13 +2202,16 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, | |||
1983 | if (hostrcb->hcam.notifications_lost == IPR_HOST_RCB_NOTIFICATIONS_LOST) | 2202 | if (hostrcb->hcam.notifications_lost == IPR_HOST_RCB_NOTIFICATIONS_LOST) |
1984 | dev_err(&ioa_cfg->pdev->dev, "Error notifications lost\n"); | 2203 | dev_err(&ioa_cfg->pdev->dev, "Error notifications lost\n"); |
1985 | 2204 | ||
1986 | ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); | 2205 | if (ioa_cfg->sis64) |
2206 | ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc); | ||
2207 | else | ||
2208 | ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc); | ||
1987 | 2209 | ||
1988 | if (ioasc == IPR_IOASC_BUS_WAS_RESET || | 2210 | if (!ioa_cfg->sis64 && (ioasc == IPR_IOASC_BUS_WAS_RESET || |
1989 | ioasc == IPR_IOASC_BUS_WAS_RESET_BY_OTHER) { | 2211 | ioasc == IPR_IOASC_BUS_WAS_RESET_BY_OTHER)) { |
1990 | /* Tell the midlayer we had a bus reset so it will handle the UA properly */ | 2212 | /* Tell the midlayer we had a bus reset so it will handle the UA properly */ |
1991 | scsi_report_bus_reset(ioa_cfg->host, | 2213 | scsi_report_bus_reset(ioa_cfg->host, |
1992 | hostrcb->hcam.u.error.failing_dev_res_addr.bus); | 2214 | hostrcb->hcam.u.error.fd_res_addr.bus); |
1993 | } | 2215 | } |
1994 | 2216 | ||
1995 | error_index = ipr_get_error(ioasc); | 2217 | error_index = ipr_get_error(ioasc); |
@@ -2037,6 +2259,16 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, | |||
2037 | case IPR_HOST_RCB_OVERLAY_ID_20: | 2259 | case IPR_HOST_RCB_OVERLAY_ID_20: |
2038 | ipr_log_fabric_error(ioa_cfg, hostrcb); | 2260 | ipr_log_fabric_error(ioa_cfg, hostrcb); |
2039 | break; | 2261 | break; |
2262 | case IPR_HOST_RCB_OVERLAY_ID_23: | ||
2263 | ipr_log_sis64_config_error(ioa_cfg, hostrcb); | ||
2264 | break; | ||
2265 | case IPR_HOST_RCB_OVERLAY_ID_24: | ||
2266 | case IPR_HOST_RCB_OVERLAY_ID_26: | ||
2267 | ipr_log_sis64_array_error(ioa_cfg, hostrcb); | ||
2268 | break; | ||
2269 | case IPR_HOST_RCB_OVERLAY_ID_30: | ||
2270 | ipr_log_sis64_fabric_error(ioa_cfg, hostrcb); | ||
2271 | break; | ||
2040 | case IPR_HOST_RCB_OVERLAY_ID_1: | 2272 | case IPR_HOST_RCB_OVERLAY_ID_1: |
2041 | case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: | 2273 | case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: |
2042 | default: | 2274 | default: |
@@ -2061,7 +2293,12 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) | |||
2061 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 2293 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
2062 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; | 2294 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; |
2063 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 2295 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); |
2064 | u32 fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); | 2296 | u32 fd_ioasc; |
2297 | |||
2298 | if (ioa_cfg->sis64) | ||
2299 | fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc); | ||
2300 | else | ||
2301 | fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc); | ||
2065 | 2302 | ||
2066 | list_del(&hostrcb->queue); | 2303 | list_del(&hostrcb->queue); |
2067 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); | 2304 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); |
@@ -6996,7 +7233,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) | |||
6996 | 7233 | ||
6997 | if (!rc) { | 7234 | if (!rc) { |
6998 | ipr_handle_log_data(ioa_cfg, hostrcb); | 7235 | ipr_handle_log_data(ioa_cfg, hostrcb); |
6999 | ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); | 7236 | ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc); |
7000 | if (ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED && | 7237 | if (ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED && |
7001 | ioa_cfg->sdt_state == GET_DUMP) | 7238 | ioa_cfg->sdt_state == GET_DUMP) |
7002 | ioa_cfg->sdt_state = WAIT_FOR_DUMP; | 7239 | ioa_cfg->sdt_state = WAIT_FOR_DUMP; |