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 | |
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')
-rw-r--r-- | drivers/scsi/ipr.c | 257 | ||||
-rw-r--r-- | drivers/scsi/ipr.h | 160 |
2 files changed, 388 insertions, 29 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; |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index f10c57b3d215..e6e90179e45e 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -754,12 +754,29 @@ struct ipr_hostrcb_device_data_entry_enhanced { | |||
754 | struct ipr_ext_vpd cfc_last_with_dev_vpd; | 754 | struct ipr_ext_vpd cfc_last_with_dev_vpd; |
755 | }__attribute__((packed, aligned (4))); | 755 | }__attribute__((packed, aligned (4))); |
756 | 756 | ||
757 | struct ipr_hostrcb64_device_data_entry_enhanced { | ||
758 | struct ipr_ext_vpd vpd; | ||
759 | u8 ccin[4]; | ||
760 | u8 res_path[8]; | ||
761 | struct ipr_ext_vpd new_vpd; | ||
762 | u8 new_ccin[4]; | ||
763 | struct ipr_ext_vpd ioa_last_with_dev_vpd; | ||
764 | struct ipr_ext_vpd cfc_last_with_dev_vpd; | ||
765 | }__attribute__((packed, aligned (4))); | ||
766 | |||
757 | struct ipr_hostrcb_array_data_entry { | 767 | struct ipr_hostrcb_array_data_entry { |
758 | struct ipr_vpd vpd; | 768 | struct ipr_vpd vpd; |
759 | struct ipr_res_addr expected_dev_res_addr; | 769 | struct ipr_res_addr expected_dev_res_addr; |
760 | struct ipr_res_addr dev_res_addr; | 770 | struct ipr_res_addr dev_res_addr; |
761 | }__attribute__((packed, aligned (4))); | 771 | }__attribute__((packed, aligned (4))); |
762 | 772 | ||
773 | struct ipr_hostrcb64_array_data_entry { | ||
774 | struct ipr_ext_vpd vpd; | ||
775 | u8 ccin[4]; | ||
776 | u8 expected_res_path[8]; | ||
777 | u8 res_path[8]; | ||
778 | }__attribute__((packed, aligned (4))); | ||
779 | |||
763 | struct ipr_hostrcb_array_data_entry_enhanced { | 780 | struct ipr_hostrcb_array_data_entry_enhanced { |
764 | struct ipr_ext_vpd vpd; | 781 | struct ipr_ext_vpd vpd; |
765 | u8 ccin[4]; | 782 | u8 ccin[4]; |
@@ -811,6 +828,14 @@ struct ipr_hostrcb_type_13_error { | |||
811 | struct ipr_hostrcb_device_data_entry_enhanced dev[3]; | 828 | struct ipr_hostrcb_device_data_entry_enhanced dev[3]; |
812 | }__attribute__((packed, aligned (4))); | 829 | }__attribute__((packed, aligned (4))); |
813 | 830 | ||
831 | struct ipr_hostrcb_type_23_error { | ||
832 | struct ipr_ext_vpd ioa_vpd; | ||
833 | struct ipr_ext_vpd cfc_vpd; | ||
834 | __be32 errors_detected; | ||
835 | __be32 errors_logged; | ||
836 | struct ipr_hostrcb64_device_data_entry_enhanced dev[3]; | ||
837 | }__attribute__((packed, aligned (4))); | ||
838 | |||
814 | struct ipr_hostrcb_type_04_error { | 839 | struct ipr_hostrcb_type_04_error { |
815 | struct ipr_vpd ioa_vpd; | 840 | struct ipr_vpd ioa_vpd; |
816 | struct ipr_vpd cfc_vpd; | 841 | struct ipr_vpd cfc_vpd; |
@@ -838,6 +863,22 @@ struct ipr_hostrcb_type_14_error { | |||
838 | struct ipr_hostrcb_array_data_entry_enhanced array_member[18]; | 863 | struct ipr_hostrcb_array_data_entry_enhanced array_member[18]; |
839 | }__attribute__((packed, aligned (4))); | 864 | }__attribute__((packed, aligned (4))); |
840 | 865 | ||
866 | struct ipr_hostrcb_type_24_error { | ||
867 | struct ipr_ext_vpd ioa_vpd; | ||
868 | struct ipr_ext_vpd cfc_vpd; | ||
869 | u8 reserved[2]; | ||
870 | u8 exposed_mode_adn; | ||
871 | #define IPR_INVALID_ARRAY_DEV_NUM 0xff | ||
872 | u8 array_id; | ||
873 | u8 last_res_path[8]; | ||
874 | u8 protection_level[8]; | ||
875 | struct ipr_ext_vpd array_vpd; | ||
876 | u8 description[16]; | ||
877 | u8 reserved2[3]; | ||
878 | u8 num_entries; | ||
879 | struct ipr_hostrcb64_array_data_entry array_member[32]; | ||
880 | }__attribute__((packed, aligned (4))); | ||
881 | |||
841 | struct ipr_hostrcb_type_07_error { | 882 | struct ipr_hostrcb_type_07_error { |
842 | u8 failure_reason[64]; | 883 | u8 failure_reason[64]; |
843 | struct ipr_vpd vpd; | 884 | struct ipr_vpd vpd; |
@@ -875,6 +916,22 @@ struct ipr_hostrcb_config_element { | |||
875 | __be32 wwid[2]; | 916 | __be32 wwid[2]; |
876 | }__attribute__((packed, aligned (4))); | 917 | }__attribute__((packed, aligned (4))); |
877 | 918 | ||
919 | struct ipr_hostrcb64_config_element { | ||
920 | __be16 length; | ||
921 | u8 descriptor_id; | ||
922 | #define IPR_DESCRIPTOR_MASK 0xC0 | ||
923 | #define IPR_DESCRIPTOR_SIS64 0x00 | ||
924 | |||
925 | u8 reserved; | ||
926 | u8 type_status; | ||
927 | |||
928 | u8 reserved2[2]; | ||
929 | u8 link_rate; | ||
930 | |||
931 | u8 res_path[8]; | ||
932 | __be32 wwid[2]; | ||
933 | }__attribute__((packed, aligned (8))); | ||
934 | |||
878 | struct ipr_hostrcb_fabric_desc { | 935 | struct ipr_hostrcb_fabric_desc { |
879 | __be16 length; | 936 | __be16 length; |
880 | u8 ioa_port; | 937 | u8 ioa_port; |
@@ -896,6 +953,20 @@ struct ipr_hostrcb_fabric_desc { | |||
896 | struct ipr_hostrcb_config_element elem[1]; | 953 | struct ipr_hostrcb_config_element elem[1]; |
897 | }__attribute__((packed, aligned (4))); | 954 | }__attribute__((packed, aligned (4))); |
898 | 955 | ||
956 | struct ipr_hostrcb64_fabric_desc { | ||
957 | __be16 length; | ||
958 | u8 descriptor_id; | ||
959 | |||
960 | u8 reserved; | ||
961 | u8 path_state; | ||
962 | |||
963 | u8 reserved2[2]; | ||
964 | u8 res_path[8]; | ||
965 | u8 reserved3[6]; | ||
966 | __be16 num_entries; | ||
967 | struct ipr_hostrcb64_config_element elem[1]; | ||
968 | }__attribute__((packed, aligned (8))); | ||
969 | |||
899 | #define for_each_fabric_cfg(fabric, cfg) \ | 970 | #define for_each_fabric_cfg(fabric, cfg) \ |
900 | for (cfg = (fabric)->elem; \ | 971 | for (cfg = (fabric)->elem; \ |
901 | cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \ | 972 | cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \ |
@@ -908,10 +979,17 @@ struct ipr_hostrcb_type_20_error { | |||
908 | struct ipr_hostrcb_fabric_desc desc[1]; | 979 | struct ipr_hostrcb_fabric_desc desc[1]; |
909 | }__attribute__((packed, aligned (4))); | 980 | }__attribute__((packed, aligned (4))); |
910 | 981 | ||
982 | struct ipr_hostrcb_type_30_error { | ||
983 | u8 failure_reason[64]; | ||
984 | u8 reserved[3]; | ||
985 | u8 num_entries; | ||
986 | struct ipr_hostrcb64_fabric_desc desc[1]; | ||
987 | }__attribute__((packed, aligned (4))); | ||
988 | |||
911 | struct ipr_hostrcb_error { | 989 | struct ipr_hostrcb_error { |
912 | __be32 failing_dev_ioasc; | 990 | __be32 fd_ioasc; |
913 | struct ipr_res_addr failing_dev_res_addr; | 991 | struct ipr_res_addr fd_res_addr; |
914 | __be32 failing_dev_res_handle; | 992 | __be32 fd_res_handle; |
915 | __be32 prc; | 993 | __be32 prc; |
916 | union { | 994 | union { |
917 | struct ipr_hostrcb_type_ff_error type_ff_error; | 995 | struct ipr_hostrcb_type_ff_error type_ff_error; |
@@ -928,6 +1006,26 @@ struct ipr_hostrcb_error { | |||
928 | } u; | 1006 | } u; |
929 | }__attribute__((packed, aligned (4))); | 1007 | }__attribute__((packed, aligned (4))); |
930 | 1008 | ||
1009 | struct ipr_hostrcb64_error { | ||
1010 | __be32 fd_ioasc; | ||
1011 | __be32 ioa_fw_level; | ||
1012 | __be32 fd_res_handle; | ||
1013 | __be32 prc; | ||
1014 | __be64 fd_dev_id; | ||
1015 | __be64 fd_lun; | ||
1016 | u8 fd_res_path[8]; | ||
1017 | __be64 time_stamp; | ||
1018 | u8 reserved[2]; | ||
1019 | union { | ||
1020 | struct ipr_hostrcb_type_ff_error type_ff_error; | ||
1021 | struct ipr_hostrcb_type_12_error type_12_error; | ||
1022 | struct ipr_hostrcb_type_17_error type_17_error; | ||
1023 | struct ipr_hostrcb_type_23_error type_23_error; | ||
1024 | struct ipr_hostrcb_type_24_error type_24_error; | ||
1025 | struct ipr_hostrcb_type_30_error type_30_error; | ||
1026 | } u; | ||
1027 | }__attribute__((packed, aligned (8))); | ||
1028 | |||
931 | struct ipr_hostrcb_raw { | 1029 | struct ipr_hostrcb_raw { |
932 | __be32 data[sizeof(struct ipr_hostrcb_error)/sizeof(__be32)]; | 1030 | __be32 data[sizeof(struct ipr_hostrcb_error)/sizeof(__be32)]; |
933 | }__attribute__((packed, aligned (4))); | 1031 | }__attribute__((packed, aligned (4))); |
@@ -965,7 +1063,11 @@ struct ipr_hcam { | |||
965 | #define IPR_HOST_RCB_OVERLAY_ID_16 0x16 | 1063 | #define IPR_HOST_RCB_OVERLAY_ID_16 0x16 |
966 | #define IPR_HOST_RCB_OVERLAY_ID_17 0x17 | 1064 | #define IPR_HOST_RCB_OVERLAY_ID_17 0x17 |
967 | #define IPR_HOST_RCB_OVERLAY_ID_20 0x20 | 1065 | #define IPR_HOST_RCB_OVERLAY_ID_20 0x20 |
968 | #define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF | 1066 | #define IPR_HOST_RCB_OVERLAY_ID_23 0x23 |
1067 | #define IPR_HOST_RCB_OVERLAY_ID_24 0x24 | ||
1068 | #define IPR_HOST_RCB_OVERLAY_ID_26 0x26 | ||
1069 | #define IPR_HOST_RCB_OVERLAY_ID_30 0x30 | ||
1070 | #define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF | ||
969 | 1071 | ||
970 | u8 reserved1[3]; | 1072 | u8 reserved1[3]; |
971 | __be32 ilid; | 1073 | __be32 ilid; |
@@ -975,6 +1077,7 @@ struct ipr_hcam { | |||
975 | 1077 | ||
976 | union { | 1078 | union { |
977 | struct ipr_hostrcb_error error; | 1079 | struct ipr_hostrcb_error error; |
1080 | struct ipr_hostrcb64_error error64; | ||
978 | struct ipr_hostrcb_cfg_ch_not ccn; | 1081 | struct ipr_hostrcb_cfg_ch_not ccn; |
979 | struct ipr_hostrcb_raw raw; | 1082 | struct ipr_hostrcb_raw raw; |
980 | } u; | 1083 | } u; |
@@ -985,6 +1088,7 @@ struct ipr_hostrcb { | |||
985 | dma_addr_t hostrcb_dma; | 1088 | dma_addr_t hostrcb_dma; |
986 | struct list_head queue; | 1089 | struct list_head queue; |
987 | struct ipr_ioa_cfg *ioa_cfg; | 1090 | struct ipr_ioa_cfg *ioa_cfg; |
1091 | char rp_buffer[IPR_MAX_RES_PATH_LENGTH]; | ||
988 | }; | 1092 | }; |
989 | 1093 | ||
990 | /* IPR smart dump table structures */ | 1094 | /* IPR smart dump table structures */ |
@@ -1521,14 +1625,21 @@ struct ipr_ucode_image_header { | |||
1521 | } | 1625 | } |
1522 | 1626 | ||
1523 | #define ipr_hcam_err(hostrcb, fmt, ...) \ | 1627 | #define ipr_hcam_err(hostrcb, fmt, ...) \ |
1524 | { \ | 1628 | { \ |
1525 | if (ipr_is_device(&(hostrcb)->hcam.u.error.failing_dev_res_addr)) { \ | 1629 | if (ipr_is_device(hostrcb)) { \ |
1526 | ipr_ra_err((hostrcb)->ioa_cfg, \ | 1630 | if ((hostrcb)->ioa_cfg->sis64) { \ |
1527 | (hostrcb)->hcam.u.error.failing_dev_res_addr, \ | 1631 | printk(KERN_ERR IPR_NAME ": %s: " fmt, \ |
1528 | fmt, ##__VA_ARGS__); \ | 1632 | ipr_format_resource_path(&hostrcb->hcam.u.error64.fd_res_path[0], \ |
1529 | } else { \ | 1633 | &hostrcb->rp_buffer[0]), \ |
1530 | dev_err(&(hostrcb)->ioa_cfg->pdev->dev, fmt, ##__VA_ARGS__); \ | 1634 | __VA_ARGS__); \ |
1531 | } \ | 1635 | } else { \ |
1636 | ipr_ra_err((hostrcb)->ioa_cfg, \ | ||
1637 | (hostrcb)->hcam.u.error.fd_res_addr, \ | ||
1638 | fmt, __VA_ARGS__); \ | ||
1639 | } \ | ||
1640 | } else { \ | ||
1641 | dev_err(&(hostrcb)->ioa_cfg->pdev->dev, fmt, __VA_ARGS__); \ | ||
1642 | } \ | ||
1532 | } | 1643 | } |
1533 | 1644 | ||
1534 | #define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\ | 1645 | #define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\ |
@@ -1637,18 +1748,29 @@ static inline int ipr_is_naca_model(struct ipr_resource_entry *res) | |||
1637 | } | 1748 | } |
1638 | 1749 | ||
1639 | /** | 1750 | /** |
1640 | * ipr_is_device - Determine if resource address is that of a device | 1751 | * ipr_is_device - Determine if the hostrcb structure is related to a device |
1641 | * @res_addr: resource address struct | 1752 | * @hostrcb: host resource control blocks struct |
1642 | * | 1753 | * |
1643 | * Return value: | 1754 | * Return value: |
1644 | * 1 if AF / 0 if not AF | 1755 | * 1 if AF / 0 if not AF |
1645 | **/ | 1756 | **/ |
1646 | static inline int ipr_is_device(struct ipr_res_addr *res_addr) | 1757 | static inline int ipr_is_device(struct ipr_hostrcb *hostrcb) |
1647 | { | 1758 | { |
1648 | if ((res_addr->bus < IPR_MAX_NUM_BUSES) && | 1759 | struct ipr_res_addr *res_addr; |
1649 | (res_addr->target < (IPR_MAX_NUM_TARGETS_PER_BUS - 1))) | 1760 | u8 *res_path; |
1650 | return 1; | 1761 | |
1651 | 1762 | if (hostrcb->ioa_cfg->sis64) { | |
1763 | res_path = &hostrcb->hcam.u.error64.fd_res_path[0]; | ||
1764 | if ((res_path[0] == 0x00 || res_path[0] == 0x80 || | ||
1765 | res_path[0] == 0x81) && res_path[2] != 0xFF) | ||
1766 | return 1; | ||
1767 | } else { | ||
1768 | res_addr = &hostrcb->hcam.u.error.fd_res_addr; | ||
1769 | |||
1770 | if ((res_addr->bus < IPR_MAX_NUM_BUSES) && | ||
1771 | (res_addr->target < (IPR_MAX_NUM_TARGETS_PER_BUS - 1))) | ||
1772 | return 1; | ||
1773 | } | ||
1652 | return 0; | 1774 | return 0; |
1653 | } | 1775 | } |
1654 | 1776 | ||