Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c23846c1 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'cxgb4-mbox-cmd-logging'



Hariprasad Shenai says:

====================
cxgb4/cxgb4vf: add support for mbox cmd logging

This patch series adds support for logging mailbox commands and
replies for debugging purpose for both PF and VF driver.

This patch series has been created against net-next tree and includes
patches on cxgb4 and cxgb4vf driver.

We have included all the maintainers of respective drivers. Kindly
review the change and let us know in case of any review comments.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 482f13aa ae7b7576
Loading
Loading
Loading
Loading
+32 −0
Original line number Original line Diff line number Diff line
@@ -359,6 +359,34 @@ struct sge_idma_monitor_state {
	unsigned int idma_warn[2];	/* time to warning in HZ */
	unsigned int idma_warn[2];	/* time to warning in HZ */
};
};


/* Firmware Mailbox Command/Reply log.  All values are in Host-Endian format.
 * The access and execute times are signed in order to accommodate negative
 * error returns.
 */
struct mbox_cmd {
	u64 cmd[MBOX_LEN / 8];		/* a Firmware Mailbox Command/Reply */
	u64 timestamp;			/* OS-dependent timestamp */
	u32 seqno;			/* sequence number */
	s16 access;			/* time (ms) to access mailbox */
	s16 execute;			/* time (ms) to execute */
};

struct mbox_cmd_log {
	unsigned int size;		/* number of entries in the log */
	unsigned int cursor;		/* next position in the log to write */
	u32 seqno;			/* next sequence number */
	/* variable length mailbox command log starts here */
};

/* Given a pointer to a Firmware Mailbox Command Log and a log entry index,
 * return a pointer to the specified entry.
 */
static inline struct mbox_cmd *mbox_cmd_log_entry(struct mbox_cmd_log *log,
						  unsigned int entry_idx)
{
	return &((struct mbox_cmd *)&(log)[1])[entry_idx];
}

#include "t4fw_api.h"
#include "t4fw_api.h"


#define FW_VERSION(chip) ( \
#define FW_VERSION(chip) ( \
@@ -780,6 +808,10 @@ struct adapter {
	struct work_struct db_drop_task;
	struct work_struct db_drop_task;
	bool tid_release_task_busy;
	bool tid_release_task_busy;


	/* support for mailbox command/reply logging */
#define T4_OS_LOG_MBOX_CMDS 256
	struct mbox_cmd_log *mbox_log;

	struct dentry *debugfs_root;
	struct dentry *debugfs_root;
	bool use_bd;     /* Use SGE Back Door intfc for reading SGE Contexts */
	bool use_bd;     /* Use SGE Back Door intfc for reading SGE Contexts */
	bool trace_rss;	/* 1 implies that different RSS flit per filter is
	bool trace_rss;	/* 1 implies that different RSS flit per filter is
+99 −0
Original line number Original line Diff line number Diff line
@@ -1152,6 +1152,104 @@ static const struct file_operations devlog_fops = {
	.release = seq_release_private
	.release = seq_release_private
};
};


/* Show Firmware Mailbox Command/Reply Log
 *
 * Note that we don't do any locking when dumping the Firmware Mailbox Log so
 * it's possible that we can catch things during a log update and therefore
 * see partially corrupted log entries.  But it's probably Good Enough(tm).
 * If we ever decide that we want to make sure that we're dumping a coherent
 * log, we'd need to perform locking in the mailbox logging and in
 * mboxlog_open() where we'd need to grab the entire mailbox log in one go
 * like we do for the Firmware Device Log.
 */
static int mboxlog_show(struct seq_file *seq, void *v)
{
	struct adapter *adapter = seq->private;
	struct mbox_cmd_log *log = adapter->mbox_log;
	struct mbox_cmd *entry;
	int entry_idx, i;

	if (v == SEQ_START_TOKEN) {
		seq_printf(seq,
			   "%10s  %15s  %5s  %5s  %s\n",
			   "Seq#", "Tstamp", "Atime", "Etime",
			   "Command/Reply");
		return 0;
	}

	entry_idx = log->cursor + ((uintptr_t)v - 2);
	if (entry_idx >= log->size)
		entry_idx -= log->size;
	entry = mbox_cmd_log_entry(log, entry_idx);

	/* skip over unused entries */
	if (entry->timestamp == 0)
		return 0;

	seq_printf(seq, "%10u  %15llu  %5d  %5d",
		   entry->seqno, entry->timestamp,
		   entry->access, entry->execute);
	for (i = 0; i < MBOX_LEN / 8; i++) {
		u64 flit = entry->cmd[i];
		u32 hi = (u32)(flit >> 32);
		u32 lo = (u32)flit;

		seq_printf(seq, "  %08x %08x", hi, lo);
	}
	seq_puts(seq, "\n");
	return 0;
}

static inline void *mboxlog_get_idx(struct seq_file *seq, loff_t pos)
{
	struct adapter *adapter = seq->private;
	struct mbox_cmd_log *log = adapter->mbox_log;

	return ((pos <= log->size) ? (void *)(uintptr_t)(pos + 1) : NULL);
}

static void *mboxlog_start(struct seq_file *seq, loff_t *pos)
{
	return *pos ? mboxlog_get_idx(seq, *pos) : SEQ_START_TOKEN;
}

static void *mboxlog_next(struct seq_file *seq, void *v, loff_t *pos)
{
	++*pos;
	return mboxlog_get_idx(seq, *pos);
}

static void mboxlog_stop(struct seq_file *seq, void *v)
{
}

static const struct seq_operations mboxlog_seq_ops = {
	.start = mboxlog_start,
	.next  = mboxlog_next,
	.stop  = mboxlog_stop,
	.show  = mboxlog_show
};

static int mboxlog_open(struct inode *inode, struct file *file)
{
	int res = seq_open(file, &mboxlog_seq_ops);

	if (!res) {
		struct seq_file *seq = file->private_data;

		seq->private = inode->i_private;
	}
	return res;
}

static const struct file_operations mboxlog_fops = {
	.owner   = THIS_MODULE,
	.open    = mboxlog_open,
	.read    = seq_read,
	.llseek  = seq_lseek,
	.release = seq_release,
};

static int mbox_show(struct seq_file *seq, void *v)
static int mbox_show(struct seq_file *seq, void *v)
{
{
	static const char * const owner[] = { "none", "FW", "driver",
	static const char * const owner[] = { "none", "FW", "driver",
@@ -3129,6 +3227,7 @@ int t4_setup_debugfs(struct adapter *adap)
		{ "cim_qcfg", &cim_qcfg_fops, S_IRUSR, 0 },
		{ "cim_qcfg", &cim_qcfg_fops, S_IRUSR, 0 },
		{ "clk", &clk_debugfs_fops, S_IRUSR, 0 },
		{ "clk", &clk_debugfs_fops, S_IRUSR, 0 },
		{ "devlog", &devlog_fops, S_IRUSR, 0 },
		{ "devlog", &devlog_fops, S_IRUSR, 0 },
		{ "mboxlog", &mboxlog_fops, S_IRUSR, 0 },
		{ "mbox0", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 0 },
		{ "mbox0", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 0 },
		{ "mbox1", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 1 },
		{ "mbox1", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 1 },
		{ "mbox2", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 2 },
		{ "mbox2", &mbox_debugfs_fops, S_IRUSR | S_IWUSR, 2 },
+12 −0
Original line number Original line Diff line number Diff line
@@ -4909,6 +4909,16 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
		goto out_free_adapter;
		goto out_free_adapter;
	}
	}


	adapter->mbox_log = kzalloc(sizeof(*adapter->mbox_log) +
				    (sizeof(struct mbox_cmd) *
				     T4_OS_LOG_MBOX_CMDS),
				    GFP_KERNEL);
	if (!adapter->mbox_log) {
		err = -ENOMEM;
		goto out_free_adapter;
	}
	adapter->mbox_log->size = T4_OS_LOG_MBOX_CMDS;

	/* PCI device has been enabled */
	/* PCI device has been enabled */
	adapter->flags |= DEV_ENABLED;
	adapter->flags |= DEV_ENABLED;


@@ -5167,6 +5177,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
	if (adapter->workq)
	if (adapter->workq)
		destroy_workqueue(adapter->workq);
		destroy_workqueue(adapter->workq);


	kfree(adapter->mbox_log);
	kfree(adapter);
	kfree(adapter);
 out_unmap_bar0:
 out_unmap_bar0:
	iounmap(regs);
	iounmap(regs);
@@ -5233,6 +5244,7 @@ static void remove_one(struct pci_dev *pdev)
			adapter->flags &= ~DEV_ENABLED;
			adapter->flags &= ~DEV_ENABLED;
		}
		}
		pci_release_regions(pdev);
		pci_release_regions(pdev);
		kfree(adapter->mbox_log);
		synchronize_rcu();
		synchronize_rcu();
		kfree(adapter);
		kfree(adapter);
	} else
	} else
+49 −20
Original line number Original line Diff line number Diff line
@@ -224,18 +224,34 @@ static void fw_asrt(struct adapter *adap, u32 mbox_addr)
		  be32_to_cpu(asrt.u.assert.x), be32_to_cpu(asrt.u.assert.y));
		  be32_to_cpu(asrt.u.assert.x), be32_to_cpu(asrt.u.assert.y));
}
}


static void dump_mbox(struct adapter *adap, int mbox, u32 data_reg)
/**
 *	t4_record_mbox - record a Firmware Mailbox Command/Reply in the log
 *	@adapter: the adapter
 *	@cmd: the Firmware Mailbox Command or Reply
 *	@size: command length in bytes
 *	@access: the time (ms) needed to access the Firmware Mailbox
 *	@execute: the time (ms) the command spent being executed
 */
static void t4_record_mbox(struct adapter *adapter,
			   const __be64 *cmd, unsigned int size,
			   int access, int execute)
{
{
	dev_err(adap->pdev_dev,
	struct mbox_cmd_log *log = adapter->mbox_log;
		"mbox %d: %llx %llx %llx %llx %llx %llx %llx %llx\n", mbox,
	struct mbox_cmd *entry;
		(unsigned long long)t4_read_reg64(adap, data_reg),
	int i;
		(unsigned long long)t4_read_reg64(adap, data_reg + 8),

		(unsigned long long)t4_read_reg64(adap, data_reg + 16),
	entry = mbox_cmd_log_entry(log, log->cursor++);
		(unsigned long long)t4_read_reg64(adap, data_reg + 24),
	if (log->cursor == log->size)
		(unsigned long long)t4_read_reg64(adap, data_reg + 32),
		log->cursor = 0;
		(unsigned long long)t4_read_reg64(adap, data_reg + 40),

		(unsigned long long)t4_read_reg64(adap, data_reg + 48),
	for (i = 0; i < size / 8; i++)
		(unsigned long long)t4_read_reg64(adap, data_reg + 56));
		entry->cmd[i] = be64_to_cpu(cmd[i]);
	while (i < MBOX_LEN / 8)
		entry->cmd[i++] = 0;
	entry->timestamp = jiffies;
	entry->seqno = log->seqno++;
	entry->access = access;
	entry->execute = execute;
}
}


/**
/**
@@ -268,12 +284,15 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
		1, 1, 3, 5, 10, 10, 20, 50, 100, 200
		1, 1, 3, 5, 10, 10, 20, 50, 100, 200
	};
	};


	u16 access = 0;
	u16 execute = 0;
	u32 v;
	u32 v;
	u64 res;
	u64 res;
	int i, ms, delay_idx;
	int i, ms, delay_idx, ret;
	const __be64 *p = cmd;
	const __be64 *p = cmd;
	u32 data_reg = PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
	u32 data_reg = PF_REG(mbox, CIM_PF_MAILBOX_DATA_A);
	u32 ctl_reg = PF_REG(mbox, CIM_PF_MAILBOX_CTRL_A);
	u32 ctl_reg = PF_REG(mbox, CIM_PF_MAILBOX_CTRL_A);
	__be64 cmd_rpl[MBOX_LEN / 8];


	if ((size & 15) || size > MBOX_LEN)
	if ((size & 15) || size > MBOX_LEN)
		return -EINVAL;
		return -EINVAL;
@@ -289,9 +308,14 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
	for (i = 0; v == MBOX_OWNER_NONE && i < 3; i++)
	for (i = 0; v == MBOX_OWNER_NONE && i < 3; i++)
		v = MBOWNER_G(t4_read_reg(adap, ctl_reg));
		v = MBOWNER_G(t4_read_reg(adap, ctl_reg));


	if (v != MBOX_OWNER_DRV)
	if (v != MBOX_OWNER_DRV) {
		return v ? -EBUSY : -ETIMEDOUT;
		ret = (v == MBOX_OWNER_FW) ? -EBUSY : -ETIMEDOUT;
		t4_record_mbox(adap, cmd, MBOX_LEN, access, ret);
		return ret;
	}


	/* Copy in the new mailbox command and send it on its way ... */
	t4_record_mbox(adap, cmd, MBOX_LEN, access, 0);
	for (i = 0; i < size; i += 8)
	for (i = 0; i < size; i += 8)
		t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p++));
		t4_write_reg64(adap, data_reg + i, be64_to_cpu(*p++));


@@ -317,26 +341,31 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
				continue;
				continue;
			}
			}


			res = t4_read_reg64(adap, data_reg);
			get_mbox_rpl(adap, cmd_rpl, MBOX_LEN / 8, data_reg);
			res = be64_to_cpu(cmd_rpl[0]);

			if (FW_CMD_OP_G(res >> 32) == FW_DEBUG_CMD) {
			if (FW_CMD_OP_G(res >> 32) == FW_DEBUG_CMD) {
				fw_asrt(adap, data_reg);
				fw_asrt(adap, data_reg);
				res = FW_CMD_RETVAL_V(EIO);
				res = FW_CMD_RETVAL_V(EIO);
			} else if (rpl) {
			} else if (rpl) {
				get_mbox_rpl(adap, rpl, size / 8, data_reg);
				memcpy(rpl, cmd_rpl, size);
			}
			}


			if (FW_CMD_RETVAL_G((int)res))
				dump_mbox(adap, mbox, data_reg);
			t4_write_reg(adap, ctl_reg, 0);
			t4_write_reg(adap, ctl_reg, 0);

			execute = i + ms;
			t4_record_mbox(adap, cmd_rpl,
				       MBOX_LEN, access, execute);
			return -FW_CMD_RETVAL_G((int)res);
			return -FW_CMD_RETVAL_G((int)res);
		}
		}
	}
	}


	dump_mbox(adap, mbox, data_reg);
	ret = -ETIMEDOUT;
	t4_record_mbox(adap, cmd, MBOX_LEN, access, ret);
	dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
	dev_err(adap->pdev_dev, "command %#x in mailbox %d timed out\n",
		*(const u8 *)cmd, mbox);
		*(const u8 *)cmd, mbox);
	t4_report_fw_error(adap);
	t4_report_fw_error(adap);
	return -ETIMEDOUT;
	return ret;
}
}


int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
int t4_wr_mbox_meat(struct adapter *adap, int mbox, const void *cmd, int size,
+4 −0
Original line number Original line Diff line number Diff line
@@ -387,6 +387,10 @@ struct adapter {
	/* various locks */
	/* various locks */
	spinlock_t stats_lock;
	spinlock_t stats_lock;


	/* support for mailbox command/reply logging */
#define T4VF_OS_LOG_MBOX_CMDS 256
	struct mbox_cmd_log *mbox_log;

	/* list of MAC addresses in MPS Hash */
	/* list of MAC addresses in MPS Hash */
	struct list_head mac_hlist;
	struct list_head mac_hlist;
};
};
Loading