|
@@ -2936,6 +2936,20 @@ int t4_get_fw_version(struct adapter *adapter, u32 *vers)
|
|
|
vers, 0);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * t4_get_bs_version - read the firmware bootstrap version
|
|
|
+ * @adapter: the adapter
|
|
|
+ * @vers: where to place the version
|
|
|
+ *
|
|
|
+ * Reads the FW Bootstrap version from flash.
|
|
|
+ */
|
|
|
+int t4_get_bs_version(struct adapter *adapter, u32 *vers)
|
|
|
+{
|
|
|
+ return t4_read_flash(adapter, FLASH_FWBOOTSTRAP_START +
|
|
|
+ offsetof(struct fw_hdr, fw_ver), 1,
|
|
|
+ vers, 0);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* t4_get_tp_version - read the TP microcode version
|
|
|
* @adapter: the adapter
|
|
@@ -7089,52 +7103,122 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * t4_handle_fw_rpl - process a FW reply message
|
|
|
+ * t4_link_down_rc_str - return a string for a Link Down Reason Code
|
|
|
* @adap: the adapter
|
|
|
+ * @link_down_rc: Link Down Reason Code
|
|
|
+ *
|
|
|
+ * Returns a string representation of the Link Down Reason Code.
|
|
|
+ */
|
|
|
+static const char *t4_link_down_rc_str(unsigned char link_down_rc)
|
|
|
+{
|
|
|
+ static const char * const reason[] = {
|
|
|
+ "Link Down",
|
|
|
+ "Remote Fault",
|
|
|
+ "Auto-negotiation Failure",
|
|
|
+ "Reserved",
|
|
|
+ "Insufficient Airflow",
|
|
|
+ "Unable To Determine Reason",
|
|
|
+ "No RX Signal Detected",
|
|
|
+ "Reserved",
|
|
|
+ };
|
|
|
+
|
|
|
+ if (link_down_rc >= ARRAY_SIZE(reason))
|
|
|
+ return "Bad Reason Code";
|
|
|
+
|
|
|
+ return reason[link_down_rc];
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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.
|
|
|
+ */
|
|
|
+void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
|
|
+{
|
|
|
+ const struct fw_port_cmd *p = (const void *)rpl;
|
|
|
+ struct adapter *adap = pi->adapter;
|
|
|
+
|
|
|
+ /* link/module state change message */
|
|
|
+ int speed = 0, fc = 0;
|
|
|
+ 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);
|
|
|
+
|
|
|
+ if (stat & FW_PORT_CMD_RXPAUSE_F)
|
|
|
+ fc |= PAUSE_RX;
|
|
|
+ if (stat & FW_PORT_CMD_TXPAUSE_F)
|
|
|
+ fc |= PAUSE_TX;
|
|
|
+ if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
|
|
|
+ speed = 100;
|
|
|
+ else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
|
|
|
+ speed = 1000;
|
|
|
+ else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G))
|
|
|
+ speed = 10000;
|
|
|
+ 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 */
|
|
|
+ if (!link_ok && lc->link_ok) {
|
|
|
+ unsigned char rc = FW_PORT_CMD_LINKDNRC_G(stat);
|
|
|
+
|
|
|
+ lc->link_down_rc = rc;
|
|
|
+ dev_warn(adap->pdev_dev,
|
|
|
+ "Port %d link down, reason: %s\n",
|
|
|
+ pi->port_id, t4_link_down_rc_str(rc));
|
|
|
+ }
|
|
|
+ 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, pi->port_id, link_ok);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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;
|
|
|
|
|
|
- if (opcode == FW_PORT_CMD) { /* link/module state change message */
|
|
|
- int speed = 0, fc = 0;
|
|
|
- const struct fw_port_cmd *p = (void *)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));
|
|
|
- int port = adap->chan_map[chan];
|
|
|
- struct port_info *pi = adap2pinfo(adap, port);
|
|
|
- struct link_config *lc = &pi->link_cfg;
|
|
|
- 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);
|
|
|
-
|
|
|
- if (stat & FW_PORT_CMD_RXPAUSE_F)
|
|
|
- fc |= PAUSE_RX;
|
|
|
- if (stat & FW_PORT_CMD_TXPAUSE_F)
|
|
|
- fc |= PAUSE_TX;
|
|
|
- if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
|
|
|
- speed = 100;
|
|
|
- else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
|
|
|
- speed = 1000;
|
|
|
- else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G))
|
|
|
- speed = 10000;
|
|
|
- else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G))
|
|
|
- speed = 40000;
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
- if (mod != pi->mod_type) {
|
|
|
- pi->mod_type = mod;
|
|
|
- t4_os_portmod_changed(adap, port);
|
|
|
+ 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;
|
|
|
}
|
|
@@ -7654,61 +7738,74 @@ int t4_init_rss_mode(struct adapter *adap, int mbox)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
|
|
|
+/**
|
|
|
+ * t4_init_portinfo - allocate a virtual interface amd initialize port_info
|
|
|
+ * @pi: the port_info
|
|
|
+ * @mbox: mailbox to use for the FW command
|
|
|
+ * @port: physical port associated with the VI
|
|
|
+ * @pf: the PF owning the VI
|
|
|
+ * @vf: the VF owning the VI
|
|
|
+ * @mac: the MAC address of the VI
|
|
|
+ *
|
|
|
+ * Allocates a virtual interface for the given physical port. If @mac is
|
|
|
+ * not %NULL it contains the MAC address of the VI as assigned by FW.
|
|
|
+ * @mac should be large enough to hold an Ethernet address.
|
|
|
+ * Returns < 0 on error.
|
|
|
+ */
|
|
|
+int t4_init_portinfo(struct port_info *pi, int mbox,
|
|
|
+ int port, int pf, int vf, u8 mac[])
|
|
|
{
|
|
|
- u8 addr[6];
|
|
|
- int ret, i, j = 0;
|
|
|
+ int ret;
|
|
|
struct fw_port_cmd c;
|
|
|
- struct fw_rss_vi_config_cmd rvc;
|
|
|
+ unsigned int rss_size;
|
|
|
|
|
|
memset(&c, 0, sizeof(c));
|
|
|
- memset(&rvc, 0, sizeof(rvc));
|
|
|
+ c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
|
|
|
+ FW_CMD_REQUEST_F | FW_CMD_READ_F |
|
|
|
+ FW_PORT_CMD_PORTID_V(port));
|
|
|
+ c.action_to_len16 = cpu_to_be32(
|
|
|
+ FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
|
|
|
+ FW_LEN16(c));
|
|
|
+ ret = t4_wr_mbox(pi->adapter, mbox, &c, sizeof(c), &c);
|
|
|
+ if (ret)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ret = t4_alloc_vi(pi->adapter, mbox, port, pf, vf, 1, mac, &rss_size);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ pi->viid = ret;
|
|
|
+ pi->tx_chan = port;
|
|
|
+ pi->lport = port;
|
|
|
+ pi->rss_size = rss_size;
|
|
|
+
|
|
|
+ ret = be32_to_cpu(c.u.info.lstatus_to_modtype);
|
|
|
+ pi->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP_F) ?
|
|
|
+ FW_PORT_CMD_MDIOADDR_G(ret) : -1;
|
|
|
+ pi->port_type = FW_PORT_CMD_PTYPE_G(ret);
|
|
|
+ pi->mod_type = FW_PORT_MOD_TYPE_NA;
|
|
|
+
|
|
|
+ init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap));
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
|
|
|
+{
|
|
|
+ u8 addr[6];
|
|
|
+ int ret, i, j = 0;
|
|
|
|
|
|
for_each_port(adap, i) {
|
|
|
- unsigned int rss_size;
|
|
|
- struct port_info *p = adap2pinfo(adap, i);
|
|
|
+ struct port_info *pi = adap2pinfo(adap, i);
|
|
|
|
|
|
while ((adap->params.portvec & (1 << j)) == 0)
|
|
|
j++;
|
|
|
|
|
|
- c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
|
|
|
- FW_CMD_REQUEST_F | FW_CMD_READ_F |
|
|
|
- FW_PORT_CMD_PORTID_V(j));
|
|
|
- c.action_to_len16 = cpu_to_be32(
|
|
|
- FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
|
|
|
- FW_LEN16(c));
|
|
|
- ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
|
|
|
+ ret = t4_init_portinfo(pi, mbox, j, pf, vf, addr);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- ret = t4_alloc_vi(adap, mbox, j, pf, vf, 1, addr, &rss_size);
|
|
|
- if (ret < 0)
|
|
|
- return ret;
|
|
|
-
|
|
|
- p->viid = ret;
|
|
|
- p->tx_chan = j;
|
|
|
- p->lport = j;
|
|
|
- p->rss_size = rss_size;
|
|
|
memcpy(adap->port[i]->dev_addr, addr, ETH_ALEN);
|
|
|
adap->port[i]->dev_port = j;
|
|
|
-
|
|
|
- ret = be32_to_cpu(c.u.info.lstatus_to_modtype);
|
|
|
- p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP_F) ?
|
|
|
- FW_PORT_CMD_MDIOADDR_G(ret) : -1;
|
|
|
- p->port_type = FW_PORT_CMD_PTYPE_G(ret);
|
|
|
- p->mod_type = FW_PORT_MOD_TYPE_NA;
|
|
|
-
|
|
|
- rvc.op_to_viid =
|
|
|
- cpu_to_be32(FW_CMD_OP_V(FW_RSS_VI_CONFIG_CMD) |
|
|
|
- FW_CMD_REQUEST_F | FW_CMD_READ_F |
|
|
|
- FW_RSS_VI_CONFIG_CMD_VIID(p->viid));
|
|
|
- rvc.retval_len16 = cpu_to_be32(FW_LEN16(rvc));
|
|
|
- ret = t4_wr_mbox(adap, mbox, &rvc, sizeof(rvc), &rvc);
|
|
|
- if (ret)
|
|
|
- return ret;
|
|
|
- p->rss_mode = be32_to_cpu(rvc.u.basicvirtual.defaultq_to_udpen);
|
|
|
-
|
|
|
- init_link_config(&p->link_cfg, be16_to_cpu(c.u.info.pcap));
|
|
|
j++;
|
|
|
}
|
|
|
return 0;
|