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

Commit 23853a0a authored by Hariprasad Shenai's avatar Hariprasad Shenai Committed by David S. Miller
Browse files

cxgb4: Don't assume FW_PORT_CMD reply is always port info msg



The firmware can send a set of asynchronous replies through FW_PORT_CMD
with DCBX information when that's negotiated with the Link Peer. The old
code always assumed that a FW_PORT_CMD reply was always a Get Port
Information message. This change conditionalizes the code to only handle
the Get Port Information messages and throws a warning if we don't
understand what we've been given.

Also refactor t4_handle_fw_rpl() so that core functionality performed by
t4_handle_get_port_info() for a specified port.

Signed-off-by: default avatarHariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 134491fd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1470,6 +1470,7 @@ int t4_ctrl_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
		    unsigned int vf, unsigned int eqid);
int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox);
void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl);
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
void t4_db_full(struct adapter *adapter);
void t4_db_dropped(struct adapter *adapter);
+73 −37
Original line number Diff line number Diff line
@@ -7103,23 +7103,20 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
}

/**
 *	t4_handle_fw_rpl - process a FW reply message
 *	@adap: the adapter
 *	t4_handle_get_port_info - process a FW reply message
 *	@pi: the port info
 *	@rpl: start of the FW message
 *
 *	Processes a FW message, such as link state change messages.
 *	Processes a GET_PORT_INFO FW reply message.
 */
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
{
	u8 opcode = *(const u8 *)rpl;
	const struct fw_port_cmd *p = (const void *)rpl;
	struct adapter *adap = pi->adapter;

	if (opcode == FW_PORT_CMD) {    /* link/module state change message */
	/* link/module state change message */
	int speed = 0, fc = 0;
		const struct fw_port_cmd *p = (void *)rpl;
		int chan = FW_PORT_CMD_PORTID_G(be32_to_cpu(p->op_to_portid));
		int port = adap->chan_map[chan];
		struct port_info *pi = adap2pinfo(adap, port);
		struct link_config *lc = &pi->link_cfg;
	struct link_config *lc;
	u32 stat = be32_to_cpu(p->u.info.lstatus_to_modtype);
	int link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0;
	u32 mod = FW_PORT_CMD_MODTYPE_G(stat);
@@ -7137,18 +7134,57 @@ int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
	else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G))
		speed = 40000;

	lc = &pi->link_cfg;

	if (mod != pi->mod_type) {
		pi->mod_type = mod;
		t4_os_portmod_changed(adap, pi->port_id);
	}
	if (link_ok != lc->link_ok || speed != lc->speed ||
	    fc != lc->fc) {	/* something changed */
		lc->link_ok = link_ok;
		lc->speed = speed;
		lc->fc = fc;
		lc->supported = be16_to_cpu(p->u.info.pcap);
			t4_os_link_changed(adap, port, link_ok);
		t4_os_link_changed(adap, pi->port_id, link_ok);
	}
		if (mod != pi->mod_type) {
			pi->mod_type = mod;
			t4_os_portmod_changed(adap, port);
}

/**
 *      t4_handle_fw_rpl - process a FW reply message
 *      @adap: the adapter
 *      @rpl: start of the FW message
 *
 *      Processes a FW message, such as link state change messages.
 */
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl)
{
	u8 opcode = *(const u8 *)rpl;

	/* This might be a port command ... this simplifies the following
	 * conditionals ...  We can get away with pre-dereferencing
	 * action_to_len16 because it's in the first 16 bytes and all messages
	 * will be at least that long.
	 */
	const struct fw_port_cmd *p = (const void *)rpl;
	unsigned int action =
		FW_PORT_CMD_ACTION_G(be32_to_cpu(p->action_to_len16));

	if (opcode == FW_PORT_CMD && action == FW_PORT_ACTION_GET_PORT_INFO) {
		int i;
		int chan = FW_PORT_CMD_PORTID_G(be32_to_cpu(p->op_to_portid));
		struct port_info *pi = NULL;

		for_each_port(adap, i) {
			pi = adap2pinfo(adap, i);
			if (pi->tx_chan == chan)
				break;
		}

		t4_handle_get_port_info(pi, rpl);
	} else {
		dev_warn(adap->pdev_dev, "Unknown firmware reply %d\n", opcode);
		return -EINVAL;
	}
	return 0;
}