0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/slab.h>
0012 #include "efx.h"
0013 #include "mcdi_port.h"
0014 #include "mcdi.h"
0015 #include "mcdi_pcol.h"
0016 #include "nic.h"
0017 #include "selftest.h"
0018 #include "mcdi_port_common.h"
0019
0020 static int efx_mcdi_mdio_read(struct net_device *net_dev,
0021 int prtad, int devad, u16 addr)
0022 {
0023 struct efx_nic *efx = efx_netdev_priv(net_dev);
0024 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
0025 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
0026 size_t outlen;
0027 int rc;
0028
0029 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
0030 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
0031 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
0032 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
0033
0034 rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_READ, inbuf, sizeof(inbuf),
0035 outbuf, sizeof(outbuf), &outlen);
0036 if (rc)
0037 return rc;
0038
0039 if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
0040 MC_CMD_MDIO_STATUS_GOOD)
0041 return -EIO;
0042
0043 return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
0044 }
0045
0046 static int efx_mcdi_mdio_write(struct net_device *net_dev,
0047 int prtad, int devad, u16 addr, u16 value)
0048 {
0049 struct efx_nic *efx = efx_netdev_priv(net_dev);
0050 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
0051 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
0052 size_t outlen;
0053 int rc;
0054
0055 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
0056 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
0057 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
0058 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
0059 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_VALUE, value);
0060
0061 rc = efx_mcdi_rpc(efx, MC_CMD_MDIO_WRITE, inbuf, sizeof(inbuf),
0062 outbuf, sizeof(outbuf), &outlen);
0063 if (rc)
0064 return rc;
0065
0066 if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
0067 MC_CMD_MDIO_STATUS_GOOD)
0068 return -EIO;
0069
0070 return 0;
0071 }
0072
0073 u32 efx_mcdi_phy_get_caps(struct efx_nic *efx)
0074 {
0075 struct efx_mcdi_phy_data *phy_data = efx->phy_data;
0076
0077 return phy_data->supported_cap;
0078 }
0079
0080 bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
0081 {
0082 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
0083 size_t outlength;
0084 int rc;
0085
0086 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
0087
0088 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
0089 outbuf, sizeof(outbuf), &outlength);
0090 if (rc)
0091 return true;
0092
0093 return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
0094 }
0095
0096 int efx_mcdi_port_probe(struct efx_nic *efx)
0097 {
0098 int rc;
0099
0100
0101 efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
0102 efx->mdio.mdio_read = efx_mcdi_mdio_read;
0103 efx->mdio.mdio_write = efx_mcdi_mdio_write;
0104
0105
0106 rc = efx_mcdi_phy_probe(efx);
0107 if (rc != 0)
0108 return rc;
0109
0110 return efx_mcdi_mac_init_stats(efx);
0111 }
0112
0113 void efx_mcdi_port_remove(struct efx_nic *efx)
0114 {
0115 efx_mcdi_phy_remove(efx);
0116 efx_mcdi_mac_fini_stats(efx);
0117 }