|
@@ -7103,52 +7103,88 @@ 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.
|
|
|
+ */
|
|
|
+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 */
|
|
|
+ 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;
|
|
|
}
|