#include <sys/cmn_err.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include "qede.h"
typedef struct {
uint32_t qsm_type;
uint32_t qsm_speed;
mac_ether_media_t qsm_media;
} qede_sfp_map_t;
typedef enum {
QS_1G = 1000,
QS_10G = 10000,
QS_25G = 25000,
QS_40G = 40000,
QS_100G = 100000
} qede_speed_t;
static const qede_sfp_map_t qede_sfp_map[] = {
{ ETH_TRANSCEIVER_TYPE_1G_LX, QS_1G, ETHER_MEDIA_1000BASE_LX },
{ ETH_TRANSCEIVER_TYPE_1G_SX, QS_1G, ETHER_MEDIA_1000BASE_SX },
{ ETH_TRANSCEIVER_TYPE_10G_SR, QS_10G, ETHER_MEDIA_10GBASE_SR },
{ ETH_TRANSCEIVER_TYPE_10G_SR, QS_1G, ETHER_MEDIA_1000BASE_SX },
{ ETH_TRANSCEIVER_TYPE_10G_LR, QS_10G, ETHER_MEDIA_10GBASE_LR },
{ ETH_TRANSCEIVER_TYPE_10G_LR, QS_1G, ETHER_MEDIA_1000BASE_LX },
{ ETH_TRANSCEIVER_TYPE_10G_LRM, QS_10G, ETHER_MEDIA_10GBASE_LRM },
{ ETH_TRANSCEIVER_TYPE_10G_ER, QS_10G, ETHER_MEDIA_10GBASE_ER },
{ ETH_TRANSCEIVER_TYPE_10G_PCC, QS_10G, ETHER_MEDIA_10GBASE_CR },
{ ETH_TRANSCEIVER_TYPE_10G_ACC, QS_10G, ETHER_MEDIA_10GBASE_ACC },
{ ETH_TRANSCEIVER_TYPE_XLPPI, QS_40G, ETHER_MEDIA_40G_XLPPI },
{ ETH_TRANSCEIVER_TYPE_40G_LR4, QS_40G, ETHER_MEDIA_40GBASE_LR4 },
{ ETH_TRANSCEIVER_TYPE_40G_SR4, QS_40G, ETHER_MEDIA_40GBASE_SR4 },
{ ETH_TRANSCEIVER_TYPE_40G_CR4, QS_40G, ETHER_MEDIA_40GBASE_CR4 },
{ ETH_TRANSCEIVER_TYPE_100G_AOC, QS_100G, ETHER_MEDIA_100GBASE_AOC4 },
{ ETH_TRANSCEIVER_TYPE_100G_SR4, QS_100G, ETHER_MEDIA_100GBASE_SR4 },
{ ETH_TRANSCEIVER_TYPE_100G_LR4, QS_100G, ETHER_MEDIA_100GBASE_LR4 },
{ ETH_TRANSCEIVER_TYPE_100G_ER4, QS_100G, ETHER_MEDIA_100GBASE_ER4 },
{ ETH_TRANSCEIVER_TYPE_100G_ACC, QS_100G, ETHER_MEDIA_100GBASE_ACC4 },
{ ETH_TRANSCEIVER_TYPE_100G_CR4, QS_100G, ETHER_MEDIA_100GBASE_CR4 },
{ ETH_TRANSCEIVER_TYPE_4x10G_SR, QS_40G, ETHER_MEDIA_40GBASE_SR4 },
{ ETH_TRANSCEIVER_TYPE_25G_CA_N, QS_25G, ETHER_MEDIA_25GBASE_CR },
{ ETH_TRANSCEIVER_TYPE_25G_CA_L, QS_25G, ETHER_MEDIA_25GBASE_CR },
{ ETH_TRANSCEIVER_TYPE_25G_CA_S, QS_25G, ETHER_MEDIA_25GBASE_CR },
{ ETH_TRANSCEIVER_TYPE_25G_ACC_S, QS_25G, ETHER_MEDIA_25GBASE_ACC },
{ ETH_TRANSCEIVER_TYPE_25G_ACC_M, QS_25G, ETHER_MEDIA_25GBASE_ACC },
{ ETH_TRANSCEIVER_TYPE_25G_ACC_L, QS_25G, ETHER_MEDIA_25GBASE_ACC },
{ ETH_TRANSCEIVER_TYPE_25G_SR, QS_25G, ETHER_MEDIA_25GBASE_SR },
{ ETH_TRANSCEIVER_TYPE_25G_LR, QS_25G, ETHER_MEDIA_25GBASE_LR },
{ ETH_TRANSCEIVER_TYPE_25G_AOC, QS_25G, ETHER_MEDIA_25GBASE_AOC },
{ ETH_TRANSCEIVER_TYPE_4x10G, QS_40G, ETHER_MEDIA_40GBASE_CR4 },
{ ETH_TRANSCEIVER_TYPE_4x25G_CR, QS_100G, ETHER_MEDIA_100GBASE_CR4 },
{ ETH_TRANSCEIVER_TYPE_1000BASET, QS_1G, ETHER_MEDIA_1000BASE_T },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR, QS_40G,
ETHER_MEDIA_40GBASE_SR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_SR, QS_10G,
ETHER_MEDIA_10GBASE_SR },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR, QS_40G,
ETHER_MEDIA_40GBASE_CR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_CR, QS_10G,
ETHER_MEDIA_10GBASE_CR },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR, QS_40G,
ETHER_MEDIA_40GBASE_LR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_10G_40G_LR, QS_10G,
ETHER_MEDIA_10GBASE_LR },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR, QS_100G,
ETHER_MEDIA_100GBASE_SR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_SR, QS_40G,
ETHER_MEDIA_40GBASE_SR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR, QS_100G,
ETHER_MEDIA_100GBASE_CR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_CR, QS_40G,
ETHER_MEDIA_40GBASE_CR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR, QS_100G,
ETHER_MEDIA_100GBASE_LR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_LR, QS_40G,
ETHER_MEDIA_40GBASE_LR4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC, QS_100G,
ETHER_MEDIA_100GBASE_AOC4 },
{ ETH_TRANSCEIVER_TYPE_MULTI_RATE_40G_100G_AOC, QS_40G,
ETHER_MEDIA_40GBASE_AOC4 },
};
mac_ether_media_t
qede_link_to_media(qede_link_cfg_t *cfg, uint32_t speed)
{
uint32_t type = (cfg->txr_data & ETH_TRANSCEIVER_TYPE_MASK) >>
ETH_TRANSCEIVER_TYPE_SHIFT;
switch (cfg->media) {
case MEDIA_SFPP_10G_FIBER:
case MEDIA_XFP_FIBER:
case MEDIA_DA_TWINAX:
case MEDIA_SFP_1G_FIBER:
case MEDIA_MODULE_FIBER:
for (size_t i = 0; i < ARRAY_SIZE(qede_sfp_map); i++) {
if (qede_sfp_map[i].qsm_type == type &&
qede_sfp_map[i].qsm_speed == speed) {
return (qede_sfp_map[i].qsm_media);
}
}
return (ETHER_MEDIA_UNKNOWN);
case MEDIA_BASE_T:
switch (speed) {
case QS_1G:
return (ETHER_MEDIA_1000BASE_T);
case QS_10G:
return (ETHER_MEDIA_10GBASE_T);
default:
return (ETHER_MEDIA_UNKNOWN);
}
case MEDIA_KR:
switch (speed) {
case QS_1G:
return (ETHER_MEDIA_1000BASE_KX);
case QS_10G:
return (ETHER_MEDIA_10GBASE_KR);
case QS_25G:
return (ETHER_MEDIA_25GBASE_KR);
case QS_40G:
return (ETHER_MEDIA_40GBASE_KR4);
case QS_100G:
return (ETHER_MEDIA_100GBASE_KR4);
default:
return (ETHER_MEDIA_UNKNOWN);
}
case MEDIA_NOT_PRESENT:
return (ETHER_MEDIA_NONE);
case MEDIA_UNSPECIFIED:
default:
return (ETHER_MEDIA_UNKNOWN);
}
}
void
qede_update_media_info(struct ecore_dev *edev, qede_link_cfg_t *link)
{
struct ecore_hwfn *hwfn = &edev->hwfns[0];
struct ecore_ptt *ptt;
link->media = MEDIA_UNSPECIFIED;
link->txr_data = ETH_TRANSCEIVER_STATE_UPDATING;
if (IS_VF(edev) || !ecore_mcp_is_init(hwfn))
return;
ptt = ecore_ptt_acquire(hwfn);
if (ptt == NULL)
return;
link->media = ecore_rd(hwfn, ptt, hwfn->mcp_info->port_addr +
offsetof(struct public_port, media_type));
link->txr_data = ecore_rd(hwfn, ptt, hwfn->mcp_info->port_addr +
offsetof(struct public_port, transceiver_data));
ecore_ptt_release(hwfn, ptt);
}
size_t
qede_sprintf(char *s, const char *fmt, ...)
{
size_t r;
va_list args;
va_start(args, fmt);
r = vsnprintf(s, SIZE_MAX, fmt, args);
va_end(args);
return (r);
}