📄 ipr.c
字号:
if (len == 0) return; if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL) len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP); for (i = 0; i < len / 4; i += 4) { ipr_err("%08X: %08X %08X %08X %08X\n", i*4, be32_to_cpu(data[i]), be32_to_cpu(data[i+1]), be32_to_cpu(data[i+2]), be32_to_cpu(data[i+3])); }}/** * ipr_log_enhanced_dual_ioa_error - Log an enhanced dual adapter error. * @ioa_cfg: ioa config struct * @hostrcb: hostrcb struct * * Return value: * none **/static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb){ struct ipr_hostrcb_type_17_error *error; error = &hostrcb->hcam.u.error.u.type_17_error; error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; strstrip(error->failure_reason); ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, be32_to_cpu(hostrcb->hcam.u.error.prc)); ipr_log_ext_vpd_compact("Remote IOA", hostrcb, &error->vpd); ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + offsetof(struct ipr_hostrcb_type_17_error, data)));}/** * ipr_log_dual_ioa_error - Log a dual adapter error. * @ioa_cfg: ioa config struct * @hostrcb: hostrcb struct * * Return value: * none **/static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb){ struct ipr_hostrcb_type_07_error *error; error = &hostrcb->hcam.u.error.u.type_07_error; error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; strstrip(error->failure_reason); ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason, be32_to_cpu(hostrcb->hcam.u.error.prc)); ipr_log_vpd_compact("Remote IOA", hostrcb, &error->vpd); ipr_log_hex_data(ioa_cfg, error->data, be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + offsetof(struct ipr_hostrcb_type_07_error, data)));}static const struct { u8 active; char *desc;} path_active_desc[] = { { IPR_PATH_NO_INFO, "Path" }, { IPR_PATH_ACTIVE, "Active path" }, { IPR_PATH_NOT_ACTIVE, "Inactive path" }};static const struct { u8 state; char *desc;} path_state_desc[] = { { IPR_PATH_STATE_NO_INFO, "has no path state information available" }, { IPR_PATH_HEALTHY, "is healthy" }, { IPR_PATH_DEGRADED, "is degraded" }, { IPR_PATH_FAILED, "is failed" }};/** * ipr_log_fabric_path - Log a fabric path error * @hostrcb: hostrcb struct * @fabric: fabric descriptor * * Return value: * none **/static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb, struct ipr_hostrcb_fabric_desc *fabric){ int i, j; u8 path_state = fabric->path_state; u8 active = path_state & IPR_PATH_ACTIVE_MASK; u8 state = path_state & IPR_PATH_STATE_MASK; for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) { if (path_active_desc[i].active != active) continue; for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) { if (path_state_desc[j].state != state) continue; if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) { ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n", path_active_desc[i].desc, path_state_desc[j].desc, fabric->ioa_port); } else if (fabric->cascaded_expander == 0xff) { ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n", path_active_desc[i].desc, path_state_desc[j].desc, fabric->ioa_port, fabric->phy); } else if (fabric->phy == 0xff) { ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n", path_active_desc[i].desc, path_state_desc[j].desc, fabric->ioa_port, fabric->cascaded_expander); } else { ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n", path_active_desc[i].desc, path_state_desc[j].desc, fabric->ioa_port, fabric->cascaded_expander, fabric->phy); } return; } } ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state, fabric->ioa_port, fabric->cascaded_expander, fabric->phy);}static const struct { u8 type; char *desc;} path_type_desc[] = { { IPR_PATH_CFG_IOA_PORT, "IOA port" }, { IPR_PATH_CFG_EXP_PORT, "Expander port" }, { IPR_PATH_CFG_DEVICE_PORT, "Device port" }, { IPR_PATH_CFG_DEVICE_LUN, "Device LUN" }};static const struct { u8 status; char *desc;} path_status_desc[] = { { IPR_PATH_CFG_NO_PROB, "Functional" }, { IPR_PATH_CFG_DEGRADED, "Degraded" }, { IPR_PATH_CFG_FAILED, "Failed" }, { IPR_PATH_CFG_SUSPECT, "Suspect" }, { IPR_PATH_NOT_DETECTED, "Missing" }, { IPR_PATH_INCORRECT_CONN, "Incorrectly connected" }};static const char *link_rate[] = { "unknown", "disabled", "phy reset problem", "spinup hold", "port selector", "unknown", "unknown", "unknown", "1.5Gbps", "3.0Gbps", "unknown", "unknown", "unknown", "unknown", "unknown", "unknown"};/** * ipr_log_path_elem - Log a fabric path element. * @hostrcb: hostrcb struct * @cfg: fabric path element struct * * Return value: * none **/static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb, struct ipr_hostrcb_config_element *cfg){ int i, j; u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK; u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK; if (type == IPR_PATH_CFG_NOT_EXIST) return; for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) { if (path_type_desc[i].type != type) continue; for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) { if (path_status_desc[j].status != status) continue; if (type == IPR_PATH_CFG_IOA_PORT) { ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n", path_status_desc[j].desc, path_type_desc[i].desc, cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); } else { if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) { ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n", path_status_desc[j].desc, path_type_desc[i].desc, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); } else if (cfg->cascaded_expander == 0xff) { ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, " "WWN=%08X%08X\n", path_status_desc[j].desc, path_type_desc[i].desc, cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); } else if (cfg->phy == 0xff) { ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, " "WWN=%08X%08X\n", path_status_desc[j].desc, path_type_desc[i].desc, cfg->cascaded_expander, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); } else { ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s " "WWN=%08X%08X\n", path_status_desc[j].desc, path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1])); } } return; } } ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s " "WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK], be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));}/** * ipr_log_fabric_error - Log a fabric error. * @ioa_cfg: ioa config struct * @hostrcb: hostrcb struct * * Return value: * none **/static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb){ struct ipr_hostrcb_type_20_error *error; struct ipr_hostrcb_fabric_desc *fabric; struct ipr_hostrcb_config_element *cfg; int i, add_len; error = &hostrcb->hcam.u.error.u.type_20_error; error->failure_reason[sizeof(error->failure_reason) - 1] = '\0'; ipr_hcam_err(hostrcb, "%s\n", error->failure_reason); add_len = be32_to_cpu(hostrcb->hcam.length) - (offsetof(struct ipr_hostrcb_error, u) + offsetof(struct ipr_hostrcb_type_20_error, desc)); for (i = 0, fabric = error->desc; i < error->num_entries; i++) { ipr_log_fabric_path(hostrcb, fabric); for_each_fabric_cfg(fabric, cfg) ipr_log_path_elem(hostrcb, cfg); add_len -= be16_to_cpu(fabric->length); fabric = (struct ipr_hostrcb_fabric_desc *) ((unsigned long)fabric + be16_to_cpu(fabric->length)); } ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len);}/** * ipr_log_generic_error - Log an adapter error. * @ioa_cfg: ioa config struct * @hostrcb: hostrcb struct * * Return value: * none **/static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb){ ipr_log_hex_data(ioa_cfg, hostrcb->hcam.u.raw.data, be32_to_cpu(hostrcb->hcam.length));}/** * ipr_get_error - Find the specfied IOASC in the ipr_error_table. * @ioasc: IOASC * * This function will return the index of into the ipr_error_table * for the specified IOASC. If the IOASC is not in the table, * 0 will be returned, which points to the entry used for unknown errors. * * Return value: * index into the ipr_error_table **/static u32 ipr_get_error(u32 ioasc){ int i; for (i = 0; i < ARRAY_SIZE(ipr_error_table); i++) if (ipr_error_table[i].ioasc == (ioasc & IPR_IOASC_IOASC_MASK)) return i; return 0;}/** * ipr_handle_log_data - Log an adapter error. * @ioa_cfg: ioa config struct * @hostrcb: hostrcb struct * * This function logs an adapter error to the system. * * Return value: * none **/static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, struct ipr_hostrcb *hostrcb){ u32 ioasc; int error_index; if (hostrcb->hcam.notify_type != IPR_HOST_RCB_NOTIF_TYPE_ERROR_LOG_ENTRY) return; if (hostrcb->hcam.notifications_lost == IPR_HOST_RCB_NOTIFICATIONS_LOST) dev_err(&ioa_cfg->pdev->dev, "Error notifications lost\n"); ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); if (ioasc == IPR_IOASC_BUS_WAS_RESET || ioasc == IPR_IOASC_BUS_WAS_RESET_BY_OTHER) { /* Tell the midlayer we had a bus reset so it will handle the UA properly */ scsi_report_bus_reset(ioa_cfg->host, hostrcb->hcam.u.error.failing_dev_res_addr.bus); } error_index = ipr_get_error(ioasc); if (!ipr_error_table[error_index].log_hcam) return; ipr_hcam_err(hostrcb, "%s\n", ipr_error_table[error_index].error); /* Set indication we have logged an error */ ioa_cfg->errors_logged++; if (ioa_cfg->log_level < ipr_error_table[error_index].log_hcam) return; if (be32_to_cpu(hostrcb->hcam.length) > sizeof(hostrcb->hcam.u.raw)) hostrcb->hcam.length = cpu_to_be32(sizeof(hostrcb->hcam.u.raw)); switch (hostrcb->hcam.overlay_id) { case IPR_HOST_RCB_OVERLAY_ID_2: ipr_log_cache_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_3: ipr_log_config_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_4: case IPR_HOST_RCB_OVERLAY_ID_6: ipr_log_array_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_7: ipr_log_dual_ioa_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_12: ipr_log_enhanced_cache_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_13: ipr_log_enhanced_config_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_14: case IPR_HOST_RCB_OVERLAY_ID_16: ipr_log_enhanced_array_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_17: ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_20: ipr_log_fabric_error(ioa_cfg, hostrcb); break; case IPR_HOST_RCB_OVERLAY_ID_1: case IPR_HOST_RCB_OVERLAY_ID_DEFAULT: default: ipr_log_generic_error(ioa_cfg, hostrcb); break; }}/** * ipr_process_error - Op done function for an adapter error log. * @ipr_cmd: ipr command struct * * This function is the op done function for an error log host * controlled async from the adapter. It will log the error and * send the HCAM back to the adapter. * * Return value: * none **/static void ipr_process_error(struct ipr_cmnd *ipr_cmd){ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); u32 fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc); list_del(&hostrcb->queue); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); if (!ioasc) { ipr_handle_log_data(ioa_cfg, hostrcb); if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED) ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); } else if (ioasc != IPR_IOASC_IOA_WAS_RESET) { dev_err(&ioa_cfg->pdev->dev, "Host RCB failed with IOASC: 0x%08X\n", ioasc); } ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -