Skip to content

Commit 9d3535e

Browse files
pmstillwanguy11
authored andcommitted
ice: add ability to read and configure FW log data
Once logging is enabled the user should read the data from the 'data' file. The data is in the form of a binary blob that can be sent to Intel for decoding. To read the data use a command like: # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/data > log_data.bin If the user wants to clear the FW log data that has been stored in the driver then they can write any value to the 'data' file and that will clear the data. An example is: # echo 34 > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/data In addition to being able to read the data the user can configure how much memory is used to store FW log data. This allows the user to increase/decrease the amount of memory based on the users situation. The data is stored such that if the memory fills up then the oldest data will get overwritten in a circular manner. To change the amount of memory the user can write to the 'log_size' file like this: # echo <value> > /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/log_size Where <value> is one of 128K, 256K, 512K, 1M, and 2M. The default value is 1M. The user can see the current value of 'log_size' by reading the file: # cat /sys/kernel/debug/ice/0000\:18\:00.0/fwlog/log_size Signed-off-by: Paul M Stillwell Jr <[email protected]> Tested-by: Pucha Himasekhar Reddy <[email protected]> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <[email protected]>
1 parent 73671c3 commit 9d3535e

File tree

6 files changed

+405
-0
lines changed

6 files changed

+405
-0
lines changed

drivers/net/ethernet/intel/ice/ice_adminq_cmd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2395,6 +2395,7 @@ enum ice_aqc_fw_logging_mod {
23952395
/* Set FW Logging configuration (indirect 0xFF30)
23962396
* Register for FW Logging (indirect 0xFF31)
23972397
* Query FW Logging (indirect 0xFF32)
2398+
* FW Log Event (indirect 0xFF33)
23982399
*/
23992400
struct ice_aqc_fw_log {
24002401
u8 cmd_flags;
@@ -2726,6 +2727,7 @@ enum ice_adminq_opc {
27262727
ice_aqc_opc_fw_logs_config = 0xFF30,
27272728
ice_aqc_opc_fw_logs_register = 0xFF31,
27282729
ice_aqc_opc_fw_logs_query = 0xFF32,
2730+
ice_aqc_opc_fw_logs_event = 0xFF33,
27292731
};
27302732

27312733
#endif /* _ICE_ADMINQ_CMD_H_ */

drivers/net/ethernet/intel/ice/ice_debugfs.c

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ static const char * const ice_fwlog_level_string[] = {
6464
"verbose",
6565
};
6666

67+
/* the order in this array is important. it matches the ordering of the
68+
* values in the FW so the index is the same value as in ice_fwlog_level
69+
*/
70+
static const char * const ice_fwlog_log_size[] = {
71+
"128K",
72+
"256K",
73+
"512K",
74+
"1M",
75+
"2M",
76+
};
77+
6778
/**
6879
* ice_fwlog_print_module_cfg - print current FW logging module configuration
6980
* @hw: pointer to the HW structure
@@ -376,6 +387,199 @@ static const struct file_operations ice_debugfs_enable_fops = {
376387
.write = ice_debugfs_enable_write,
377388
};
378389

390+
/**
391+
* ice_debugfs_log_size_read - read from 'log_size' file
392+
* @filp: the opened file
393+
* @buffer: where to write the data for the user to read
394+
* @count: the size of the user's buffer
395+
* @ppos: file position offset
396+
*/
397+
static ssize_t ice_debugfs_log_size_read(struct file *filp,
398+
char __user *buffer, size_t count,
399+
loff_t *ppos)
400+
{
401+
struct ice_pf *pf = filp->private_data;
402+
struct ice_hw *hw = &pf->hw;
403+
char buff[32] = {};
404+
int index;
405+
406+
index = hw->fwlog_ring.index;
407+
snprintf(buff, sizeof(buff), "%s\n", ice_fwlog_log_size[index]);
408+
409+
return simple_read_from_buffer(buffer, count, ppos, buff, strlen(buff));
410+
}
411+
412+
/**
413+
* ice_debugfs_log_size_write - write into 'log_size' file
414+
* @filp: the opened file
415+
* @buf: where to find the user's data
416+
* @count: the length of the user's data
417+
* @ppos: file position offset
418+
*/
419+
static ssize_t
420+
ice_debugfs_log_size_write(struct file *filp, const char __user *buf,
421+
size_t count, loff_t *ppos)
422+
{
423+
struct ice_pf *pf = filp->private_data;
424+
struct device *dev = ice_pf_to_dev(pf);
425+
struct ice_hw *hw = &pf->hw;
426+
char user_val[8], *cmd_buf;
427+
ssize_t ret;
428+
int index;
429+
430+
/* don't allow partial writes or invalid input */
431+
if (*ppos != 0 || count > 5)
432+
return -EINVAL;
433+
434+
cmd_buf = memdup_user(buf, count);
435+
if (IS_ERR(cmd_buf))
436+
return PTR_ERR(cmd_buf);
437+
438+
ret = sscanf(cmd_buf, "%s", user_val);
439+
if (ret != 1)
440+
return -EINVAL;
441+
442+
index = sysfs_match_string(ice_fwlog_log_size, user_val);
443+
if (index < 0) {
444+
dev_info(dev, "Invalid log size '%s'. The value must be one of 128K, 256K, 512K, 1M, 2M\n",
445+
user_val);
446+
ret = -EINVAL;
447+
goto log_size_write_error;
448+
} else if (hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED) {
449+
dev_info(dev, "FW logging is currently running. Please disable FW logging to change log_size\n");
450+
ret = -EINVAL;
451+
goto log_size_write_error;
452+
}
453+
454+
/* free all the buffers and the tracking info and resize */
455+
ice_fwlog_realloc_rings(hw, index);
456+
457+
/* if we get here, nothing went wrong; return count since we didn't
458+
* really write anything
459+
*/
460+
ret = (ssize_t)count;
461+
462+
log_size_write_error:
463+
/* This function always consumes all of the written input, or produces
464+
* an error. Check and enforce this. Otherwise, the write operation
465+
* won't complete properly.
466+
*/
467+
if (WARN_ON(ret != (ssize_t)count && ret >= 0))
468+
ret = -EIO;
469+
470+
return ret;
471+
}
472+
473+
static const struct file_operations ice_debugfs_log_size_fops = {
474+
.owner = THIS_MODULE,
475+
.open = simple_open,
476+
.read = ice_debugfs_log_size_read,
477+
.write = ice_debugfs_log_size_write,
478+
};
479+
480+
/**
481+
* ice_debugfs_data_read - read from 'data' file
482+
* @filp: the opened file
483+
* @buffer: where to write the data for the user to read
484+
* @count: the size of the user's buffer
485+
* @ppos: file position offset
486+
*/
487+
static ssize_t ice_debugfs_data_read(struct file *filp, char __user *buffer,
488+
size_t count, loff_t *ppos)
489+
{
490+
struct ice_pf *pf = filp->private_data;
491+
struct ice_hw *hw = &pf->hw;
492+
int data_copied = 0;
493+
bool done = false;
494+
495+
if (ice_fwlog_ring_empty(&hw->fwlog_ring))
496+
return 0;
497+
498+
while (!ice_fwlog_ring_empty(&hw->fwlog_ring) && !done) {
499+
struct ice_fwlog_data *log;
500+
u16 cur_buf_len;
501+
502+
log = &hw->fwlog_ring.rings[hw->fwlog_ring.head];
503+
cur_buf_len = log->data_size;
504+
if (cur_buf_len >= count) {
505+
done = true;
506+
continue;
507+
}
508+
509+
if (copy_to_user(buffer, log->data, cur_buf_len)) {
510+
/* if there is an error then bail and return whatever
511+
* the driver has copied so far
512+
*/
513+
done = true;
514+
continue;
515+
}
516+
517+
data_copied += cur_buf_len;
518+
buffer += cur_buf_len;
519+
count -= cur_buf_len;
520+
*ppos += cur_buf_len;
521+
ice_fwlog_ring_increment(&hw->fwlog_ring.head,
522+
hw->fwlog_ring.size);
523+
}
524+
525+
return data_copied;
526+
}
527+
528+
/**
529+
* ice_debugfs_data_write - write into 'data' file
530+
* @filp: the opened file
531+
* @buf: where to find the user's data
532+
* @count: the length of the user's data
533+
* @ppos: file position offset
534+
*/
535+
static ssize_t
536+
ice_debugfs_data_write(struct file *filp, const char __user *buf, size_t count,
537+
loff_t *ppos)
538+
{
539+
struct ice_pf *pf = filp->private_data;
540+
struct device *dev = ice_pf_to_dev(pf);
541+
struct ice_hw *hw = &pf->hw;
542+
ssize_t ret;
543+
544+
/* don't allow partial writes */
545+
if (*ppos != 0)
546+
return 0;
547+
548+
/* any value is allowed to clear the buffer so no need to even look at
549+
* what the value is
550+
*/
551+
if (!(hw->fwlog_cfg.options & ICE_FWLOG_OPTION_IS_REGISTERED)) {
552+
hw->fwlog_ring.head = 0;
553+
hw->fwlog_ring.tail = 0;
554+
} else {
555+
dev_info(dev, "Can't clear FW log data while FW log running\n");
556+
ret = -EINVAL;
557+
goto nr_buffs_write_error;
558+
}
559+
560+
/* if we get here, nothing went wrong; return count since we didn't
561+
* really write anything
562+
*/
563+
ret = (ssize_t)count;
564+
565+
nr_buffs_write_error:
566+
/* This function always consumes all of the written input, or produces
567+
* an error. Check and enforce this. Otherwise, the write operation
568+
* won't complete properly.
569+
*/
570+
if (WARN_ON(ret != (ssize_t)count && ret >= 0))
571+
ret = -EIO;
572+
573+
return ret;
574+
}
575+
576+
static const struct file_operations ice_debugfs_data_fops = {
577+
.owner = THIS_MODULE,
578+
.open = simple_open,
579+
.read = ice_debugfs_data_read,
580+
.write = ice_debugfs_data_write,
581+
};
582+
379583
/**
380584
* ice_debugfs_fwlog_init - setup the debugfs directory
381585
* @pf: the ice that is starting up
@@ -430,6 +634,12 @@ void ice_debugfs_fwlog_init(struct ice_pf *pf)
430634
debugfs_create_file("enable", 0600, pf->ice_debugfs_pf_fwlog,
431635
pf, &ice_debugfs_enable_fops);
432636

637+
debugfs_create_file("log_size", 0600, pf->ice_debugfs_pf_fwlog,
638+
pf, &ice_debugfs_log_size_fops);
639+
640+
debugfs_create_file("data", 0600, pf->ice_debugfs_pf_fwlog,
641+
pf, &ice_debugfs_data_fops);
642+
433643
return;
434644

435645
err_create_module_files:

0 commit comments

Comments
 (0)