diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qed/qed_debug.c')
| -rw-r--r-- | drivers/net/ethernet/qlogic/qed/qed_debug.c | 248 | 
1 files changed, 143 insertions, 105 deletions
| diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c index 1aa9fc1c5890..78a638ec7c0a 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_debug.c +++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c @@ -3454,7 +3454,8 @@ static u32 qed_grc_dump_iors(struct qed_hwfn *p_hwfn,  			addr = BYTES_TO_DWORDS(storm->sem_fast_mem_addr +  					       SEM_FAST_REG_STORM_REG_FILE) +  			       IOR_SET_OFFSET(set_id); -			buf[strlen(buf) - 1] = '0' + set_id; +			if (strlen(buf) > 0) +				buf[strlen(buf) - 1] = '0' + set_id;  			offset += qed_grc_dump_mem(p_hwfn,  						   p_ptt,  						   dump_buf + offset, @@ -5563,35 +5564,6 @@ struct block_info {  	enum block_id id;  }; -struct mcp_trace_format { -	u32 data; -#define MCP_TRACE_FORMAT_MODULE_MASK	0x0000ffff -#define MCP_TRACE_FORMAT_MODULE_SHIFT	0 -#define MCP_TRACE_FORMAT_LEVEL_MASK	0x00030000 -#define MCP_TRACE_FORMAT_LEVEL_SHIFT	16 -#define MCP_TRACE_FORMAT_P1_SIZE_MASK	0x000c0000 -#define MCP_TRACE_FORMAT_P1_SIZE_SHIFT	18 -#define MCP_TRACE_FORMAT_P2_SIZE_MASK	0x00300000 -#define MCP_TRACE_FORMAT_P2_SIZE_SHIFT	20 -#define MCP_TRACE_FORMAT_P3_SIZE_MASK	0x00c00000 -#define MCP_TRACE_FORMAT_P3_SIZE_SHIFT	22 -#define MCP_TRACE_FORMAT_LEN_MASK	0xff000000 -#define MCP_TRACE_FORMAT_LEN_SHIFT	24 - -	char *format_str; -}; - -/* Meta data structure, generated by a perl script during MFW build. therefore, - * the structs mcp_trace_meta and mcp_trace_format are duplicated in the perl - * script. - */ -struct mcp_trace_meta { -	u32 modules_num; -	char **modules; -	u32 formats_num; -	struct mcp_trace_format *formats; -}; -  /* REG fifo element */  struct reg_fifo_element {  	u64 data; @@ -5714,6 +5686,20 @@ struct igu_fifo_addr_data {  	enum igu_fifo_addr_types type;  }; +struct mcp_trace_meta { +	u32 modules_num; +	char **modules; +	u32 formats_num; +	struct mcp_trace_format *formats; +	bool is_allocated; +}; + +/* Debug Tools user data */ +struct dbg_tools_user_data { +	struct mcp_trace_meta mcp_trace_meta; +	const u32 *mcp_trace_user_meta_buf; +}; +  /******************************** Constants **********************************/  #define MAX_MSG_LEN				1024 @@ -6137,15 +6123,6 @@ static const struct igu_fifo_addr_data s_igu_fifo_addr_data[] = {  /******************************** Variables **********************************/ -/* MCP Trace meta data array - used in case the dump doesn't contain the - * meta data (e.g. due to no NVRAM access). - */ -static struct user_dbg_array s_mcp_trace_meta_arr = { NULL, 0 }; - -/* Parsed MCP Trace meta data info, based on MCP trace meta array */ -static struct mcp_trace_meta s_mcp_trace_meta; -static bool s_mcp_trace_meta_valid; -  /* Temporary buffer, used for print size calculations */  static char s_temp_buf[MAX_MSG_LEN]; @@ -6311,6 +6288,12 @@ static u32 qed_print_section_params(u32 *dump_buf,  	return dump_offset;  } +static struct dbg_tools_user_data * +qed_dbg_get_user_data(struct qed_hwfn *p_hwfn) +{ +	return (struct dbg_tools_user_data *)p_hwfn->dbg_user_info; +} +  /* Parses the idle check rules and returns the number of characters printed.   * In case of parsing error, returns 0.   */ @@ -6570,43 +6553,26 @@ static enum dbg_status qed_parse_idle_chk_dump(u32 *dump_buf,  	return DBG_STATUS_OK;  } -/* Frees the specified MCP Trace meta data */ -static void qed_mcp_trace_free_meta(struct qed_hwfn *p_hwfn, -				    struct mcp_trace_meta *meta) -{ -	u32 i; - -	s_mcp_trace_meta_valid = false; - -	/* Release modules */ -	if (meta->modules) { -		for (i = 0; i < meta->modules_num; i++) -			kfree(meta->modules[i]); -		kfree(meta->modules); -	} - -	/* Release formats */ -	if (meta->formats) { -		for (i = 0; i < meta->formats_num; i++) -			kfree(meta->formats[i].format_str); -		kfree(meta->formats); -	} -} -  /* Allocates and fills MCP Trace meta data based on the specified meta data   * dump buffer.   * Returns debug status code.   */ -static enum dbg_status qed_mcp_trace_alloc_meta(struct qed_hwfn *p_hwfn, -						const u32 *meta_buf, -						struct mcp_trace_meta *meta) +static enum dbg_status +qed_mcp_trace_alloc_meta_data(struct qed_hwfn *p_hwfn, +			      const u32 *meta_buf)  { -	u8 *meta_buf_bytes = (u8 *)meta_buf; +	struct dbg_tools_user_data *dev_user_data;  	u32 offset = 0, signature, i; +	struct mcp_trace_meta *meta; +	u8 *meta_buf_bytes; + +	dev_user_data = qed_dbg_get_user_data(p_hwfn); +	meta = &dev_user_data->mcp_trace_meta; +	meta_buf_bytes = (u8 *)meta_buf;  	/* Free the previous meta before loading a new one. */ -	if (s_mcp_trace_meta_valid) -		qed_mcp_trace_free_meta(p_hwfn, meta); +	if (meta->is_allocated) +		qed_mcp_trace_free_meta_data(p_hwfn);  	memset(meta, 0, sizeof(*meta)); @@ -6674,7 +6640,7 @@ static enum dbg_status qed_mcp_trace_alloc_meta(struct qed_hwfn *p_hwfn,  				      format_len, format_ptr->format_str);  	} -	s_mcp_trace_meta_valid = true; +	meta->is_allocated = true;  	return DBG_STATUS_OK;  } @@ -6687,21 +6653,26 @@ static enum dbg_status qed_mcp_trace_alloc_meta(struct qed_hwfn *p_hwfn,   *               buffer.   * data_size - size in bytes of data to parse.   * parsed_buf - destination buffer for parsed data. - * parsed_bytes - size of parsed data in bytes. + * parsed_results_bytes - size of parsed data in bytes.   */ -static enum dbg_status qed_parse_mcp_trace_buf(u8 *trace_buf, +static enum dbg_status qed_parse_mcp_trace_buf(struct qed_hwfn *p_hwfn, +					       u8 *trace_buf,  					       u32 trace_buf_size,  					       u32 data_offset,  					       u32 data_size,  					       char *parsed_buf, -					       u32 *parsed_bytes) +					       u32 *parsed_results_bytes)  { +	struct dbg_tools_user_data *dev_user_data; +	struct mcp_trace_meta *meta;  	u32 param_mask, param_shift;  	enum dbg_status status; -	*parsed_bytes = 0; +	dev_user_data = qed_dbg_get_user_data(p_hwfn); +	meta = &dev_user_data->mcp_trace_meta; +	*parsed_results_bytes = 0; -	if (!s_mcp_trace_meta_valid) +	if (!meta->is_allocated)  		return DBG_STATUS_MCP_TRACE_BAD_DATA;  	status = DBG_STATUS_OK; @@ -6723,7 +6694,7 @@ static enum dbg_status qed_parse_mcp_trace_buf(u8 *trace_buf,  		format_idx = header & MFW_TRACE_EVENTID_MASK;  		/* Skip message if its index doesn't exist in the meta data */ -		if (format_idx >= s_mcp_trace_meta.formats_num) { +		if (format_idx >= meta->formats_num) {  			u8 format_size =  				(u8)((header & MFW_TRACE_PRM_SIZE_MASK) >>  				     MFW_TRACE_PRM_SIZE_SHIFT); @@ -6738,7 +6709,7 @@ static enum dbg_status qed_parse_mcp_trace_buf(u8 *trace_buf,  			continue;  		} -		format_ptr = &s_mcp_trace_meta.formats[format_idx]; +		format_ptr = &meta->formats[format_idx];  		for (i = 0,  		     param_mask = MCP_TRACE_FORMAT_P1_SIZE_MASK, @@ -6783,19 +6754,20 @@ static enum dbg_status qed_parse_mcp_trace_buf(u8 *trace_buf,  			return DBG_STATUS_MCP_TRACE_BAD_DATA;  		/* Print current message to results buffer */ -		*parsed_bytes += -			sprintf(qed_get_buf_ptr(parsed_buf, *parsed_bytes), +		*parsed_results_bytes += +			sprintf(qed_get_buf_ptr(parsed_buf, +						*parsed_results_bytes),  				"%s %-8s: ",  				s_mcp_trace_level_str[format_level], -				s_mcp_trace_meta.modules[format_module]); -		*parsed_bytes += -		    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_bytes), +				meta->modules[format_module]); +		*parsed_results_bytes += +		    sprintf(qed_get_buf_ptr(parsed_buf, *parsed_results_bytes),  			    format_ptr->format_str,  			    params[0], params[1], params[2]);  	}  	/* Add string NULL terminator */ -	(*parsed_bytes)++; +	(*parsed_results_bytes)++;  	return status;  } @@ -6803,24 +6775,25 @@ static enum dbg_status qed_parse_mcp_trace_buf(u8 *trace_buf,  /* Parses an MCP Trace dump buffer.   * If result_buf is not NULL, the MCP Trace results are printed to it.   * In any case, the required results buffer size is assigned to - * parsed_bytes. + * parsed_results_bytes.   * The parsing status is returned.   */  static enum dbg_status qed_parse_mcp_trace_dump(struct qed_hwfn *p_hwfn,  						u32 *dump_buf, -						char *parsed_buf, -						u32 *parsed_bytes) +						char *results_buf, +						u32 *parsed_results_bytes, +						bool free_meta_data)  {  	const char *section_name, *param_name, *param_str_val;  	u32 data_size, trace_data_dwords, trace_meta_dwords; -	u32 offset, results_offset, parsed_buf_bytes; +	u32 offset, results_offset, results_buf_bytes;  	u32 param_num_val, num_section_params;  	struct mcp_trace *trace;  	enum dbg_status status;  	const u32 *meta_buf;  	u8 *trace_buf; -	*parsed_bytes = 0; +	*parsed_results_bytes = 0;  	/* Read global_params section */  	dump_buf += qed_read_section_hdr(dump_buf, @@ -6831,7 +6804,7 @@ static enum dbg_status qed_parse_mcp_trace_dump(struct qed_hwfn *p_hwfn,  	/* Print global params */  	dump_buf += qed_print_section_params(dump_buf,  					     num_section_params, -					     parsed_buf, &results_offset); +					     results_buf, &results_offset);  	/* Read trace_data section */  	dump_buf += qed_read_section_hdr(dump_buf, @@ -6846,6 +6819,9 @@ static enum dbg_status qed_parse_mcp_trace_dump(struct qed_hwfn *p_hwfn,  	/* Prepare trace info */  	trace = (struct mcp_trace *)dump_buf; +	if (trace->signature != MFW_TRACE_SIGNATURE || !trace->size) +		return DBG_STATUS_MCP_TRACE_BAD_DATA; +  	trace_buf = (u8 *)dump_buf + sizeof(*trace);  	offset = trace->trace_oldest;  	data_size = qed_cyclic_sub(trace->trace_prod, offset, trace->size); @@ -6865,31 +6841,39 @@ static enum dbg_status qed_parse_mcp_trace_dump(struct qed_hwfn *p_hwfn,  	/* Choose meta data buffer */  	if (!trace_meta_dwords) {  		/* Dump doesn't include meta data */ -		if (!s_mcp_trace_meta_arr.ptr) +		struct dbg_tools_user_data *dev_user_data = +			qed_dbg_get_user_data(p_hwfn); + +		if (!dev_user_data->mcp_trace_user_meta_buf)  			return DBG_STATUS_MCP_TRACE_NO_META; -		meta_buf = s_mcp_trace_meta_arr.ptr; + +		meta_buf = dev_user_data->mcp_trace_user_meta_buf;  	} else {  		/* Dump includes meta data */  		meta_buf = dump_buf;  	}  	/* Allocate meta data memory */ -	status = qed_mcp_trace_alloc_meta(p_hwfn, meta_buf, &s_mcp_trace_meta); +	status = qed_mcp_trace_alloc_meta_data(p_hwfn, meta_buf);  	if (status != DBG_STATUS_OK)  		return status; -	status = qed_parse_mcp_trace_buf(trace_buf, +	status = qed_parse_mcp_trace_buf(p_hwfn, +					 trace_buf,  					 trace->size,  					 offset,  					 data_size, -					 parsed_buf ? -					 parsed_buf + results_offset : +					 results_buf ? +					 results_buf + results_offset :  					 NULL, -					 &parsed_buf_bytes); +					 &results_buf_bytes);  	if (status != DBG_STATUS_OK)  		return status; -	*parsed_bytes = results_offset + parsed_buf_bytes; +	if (free_meta_data) +		qed_mcp_trace_free_meta_data(p_hwfn); + +	*parsed_results_bytes = results_offset + results_buf_bytes;  	return DBG_STATUS_OK;  } @@ -7361,6 +7345,16 @@ enum dbg_status qed_dbg_user_set_bin_ptr(const u8 * const bin_ptr)  	return DBG_STATUS_OK;  } +enum dbg_status qed_dbg_alloc_user_data(struct qed_hwfn *p_hwfn) +{ +	p_hwfn->dbg_user_info = kzalloc(sizeof(struct dbg_tools_user_data), +					GFP_KERNEL); +	if (!p_hwfn->dbg_user_info) +		return DBG_STATUS_VIRT_MEM_ALLOC_FAILED; + +	return DBG_STATUS_OK; +} +  const char *qed_dbg_get_status_str(enum dbg_status status)  {  	return (status < @@ -7397,10 +7391,13 @@ enum dbg_status qed_print_idle_chk_results(struct qed_hwfn *p_hwfn,  				       num_errors, num_warnings);  } -void qed_dbg_mcp_trace_set_meta_data(u32 *data, u32 size) +void qed_dbg_mcp_trace_set_meta_data(struct qed_hwfn *p_hwfn, +				     const u32 *meta_buf)  { -	s_mcp_trace_meta_arr.ptr = data; -	s_mcp_trace_meta_arr.size_in_dwords = size; +	struct dbg_tools_user_data *dev_user_data = +		qed_dbg_get_user_data(p_hwfn); + +	dev_user_data->mcp_trace_user_meta_buf = meta_buf;  }  enum dbg_status qed_get_mcp_trace_results_buf_size(struct qed_hwfn *p_hwfn, @@ -7409,7 +7406,7 @@ enum dbg_status qed_get_mcp_trace_results_buf_size(struct qed_hwfn *p_hwfn,  						   u32 *results_buf_size)  {  	return qed_parse_mcp_trace_dump(p_hwfn, -					dump_buf, NULL, results_buf_size); +					dump_buf, NULL, results_buf_size, true);  }  enum dbg_status qed_print_mcp_trace_results(struct qed_hwfn *p_hwfn, @@ -7421,20 +7418,61 @@ enum dbg_status qed_print_mcp_trace_results(struct qed_hwfn *p_hwfn,  	return qed_parse_mcp_trace_dump(p_hwfn,  					dump_buf, -					results_buf, &parsed_buf_size); +					results_buf, &parsed_buf_size, true); +} + +enum dbg_status qed_print_mcp_trace_results_cont(struct qed_hwfn *p_hwfn, +						 u32 *dump_buf, +						 char *results_buf) +{ +	u32 parsed_buf_size; + +	return qed_parse_mcp_trace_dump(p_hwfn, dump_buf, results_buf, +					&parsed_buf_size, false);  } -enum dbg_status qed_print_mcp_trace_line(u8 *dump_buf, +enum dbg_status qed_print_mcp_trace_line(struct qed_hwfn *p_hwfn, +					 u8 *dump_buf,  					 u32 num_dumped_bytes,  					 char *results_buf)  { -	u32 parsed_bytes; +	u32 parsed_results_bytes; -	return qed_parse_mcp_trace_buf(dump_buf, +	return qed_parse_mcp_trace_buf(p_hwfn, +				       dump_buf,  				       num_dumped_bytes,  				       0,  				       num_dumped_bytes, -				       results_buf, &parsed_bytes); +				       results_buf, &parsed_results_bytes); +} + +/* Frees the specified MCP Trace meta data */ +void qed_mcp_trace_free_meta_data(struct qed_hwfn *p_hwfn) +{ +	struct dbg_tools_user_data *dev_user_data; +	struct mcp_trace_meta *meta; +	u32 i; + +	dev_user_data = qed_dbg_get_user_data(p_hwfn); +	meta = &dev_user_data->mcp_trace_meta; +	if (!meta->is_allocated) +		return; + +	/* Release modules */ +	if (meta->modules) { +		for (i = 0; i < meta->modules_num; i++) +			kfree(meta->modules[i]); +		kfree(meta->modules); +	} + +	/* Release formats */ +	if (meta->formats) { +		for (i = 0; i < meta->formats_num; i++) +			kfree(meta->formats[i].format_str); +		kfree(meta->formats); +	} + +	meta->is_allocated = false;  }  enum dbg_status qed_get_reg_fifo_results_buf_size(struct qed_hwfn *p_hwfn, |