MFC 206662: Cleanup if_media handling in mxge(4)

This commit is contained in:
Andrew Gallatin 2010-04-27 15:38:58 +00:00
parent 3db0099738
commit 953a22892c
2 changed files with 79 additions and 44 deletions

View File

@ -883,6 +883,9 @@ mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data)
case MXGEFW_CMD_ERROR_BUSY:
err = EBUSY;
break;
case MXGEFW_CMD_ERROR_I2C_ABSENT:
err = ENXIO;
break;
default:
device_printf(sc->dev,
"mxge: command %d "
@ -2782,37 +2785,25 @@ static struct mxge_media_type mxge_sfp_media_types[] =
};
static void
mxge_set_media(mxge_softc_t *sc, int type)
mxge_media_set(mxge_softc_t *sc, int media_type)
{
sc->media_flags |= type;
ifmedia_add(&sc->media, sc->media_flags, 0, NULL);
ifmedia_set(&sc->media, sc->media_flags);
ifmedia_add(&sc->media, IFM_ETHER | IFM_FDX | media_type,
0, NULL);
ifmedia_set(&sc->media, IFM_ETHER | IFM_FDX | media_type);
sc->current_media = media_type;
sc->media.ifm_media = sc->media.ifm_cur->ifm_media;
}
/*
* Determine the media type for a NIC. Some XFPs will identify
* themselves only when their link is up, so this is initiated via a
* link up interrupt. However, this can potentially take up to
* several milliseconds, so it is run via the watchdog routine, rather
* than in the interrupt handler itself. This need only be done
* once, not each time the link is up.
*/
static void
mxge_media_probe(mxge_softc_t *sc)
mxge_media_init(mxge_softc_t *sc)
{
mxge_cmd_t cmd;
char *cage_type;
char *ptr;
struct mxge_media_type *mxge_media_types = NULL;
int i, err, ms, mxge_media_type_entries;
uint32_t byte;
int i;
sc->need_media_probe = 0;
/* if we've already set a media type, we're done */
if (sc->media_flags != (IFM_ETHER | IFM_AUTO))
return;
ifmedia_removeall(&sc->media);
mxge_media_set(sc, IFM_AUTO);
/*
* parse the product code to deterimine the interface type
@ -2823,6 +2814,7 @@ mxge_media_probe(mxge_softc_t *sc)
ptr = sc->product_code_string;
if (ptr == NULL) {
device_printf(sc->dev, "Missing product code\n");
return;
}
for (i = 0; i < 3; i++, ptr++) {
@ -2835,17 +2827,44 @@ mxge_media_probe(mxge_softc_t *sc)
}
if (*ptr == 'C') {
/* -C is CX4 */
mxge_set_media(sc, IFM_10G_CX4);
return;
}
else if (*ptr == 'Q') {
sc->connector = MXGE_CX4;
mxge_media_set(sc, IFM_10G_CX4);
} else if (*ptr == 'Q') {
/* -Q is Quad Ribbon Fiber */
sc->connector = MXGE_QRF;
device_printf(sc->dev, "Quad Ribbon Fiber Media\n");
/* FreeBSD has no media type for Quad ribbon fiber */
return;
} else if (*ptr == 'R') {
/* -R is XFP */
sc->connector = MXGE_XFP;
} else if (*ptr == 'S' || *(ptr +1) == 'S') {
/* -S or -2S is SFP+ */
sc->connector = MXGE_SFP;
} else {
device_printf(sc->dev, "Unknown media type: %c\n", *ptr);
}
}
if (*ptr == 'R') {
/*
* Determine the media type for a NIC. Some XFPs will identify
* themselves only when their link is up, so this is initiated via a
* link up interrupt. However, this can potentially take up to
* several milliseconds, so it is run via the watchdog routine, rather
* than in the interrupt handler itself.
*/
static void
mxge_media_probe(mxge_softc_t *sc)
{
mxge_cmd_t cmd;
char *cage_type;
struct mxge_media_type *mxge_media_types = NULL;
int i, err, ms, mxge_media_type_entries;
uint32_t byte;
sc->need_media_probe = 0;
if (sc->connector == MXGE_XFP) {
/* -R is XFP */
mxge_media_types = mxge_xfp_media_types;
mxge_media_type_entries =
@ -2853,9 +2872,7 @@ mxge_media_probe(mxge_softc_t *sc)
sizeof (mxge_xfp_media_types[0]);
byte = MXGE_XFP_COMPLIANCE_BYTE;
cage_type = "XFP";
}
if (*ptr == 'S' || *(ptr +1) == 'S') {
} else if (sc->connector == MXGE_SFP) {
/* -S or -2S is SFP+ */
mxge_media_types = mxge_sfp_media_types;
mxge_media_type_entries =
@ -2863,10 +2880,8 @@ mxge_media_probe(mxge_softc_t *sc)
sizeof (mxge_sfp_media_types[0]);
cage_type = "SFP+";
byte = 3;
}
if (mxge_media_types == NULL) {
device_printf(sc->dev, "Unknown media type: %c\n", *ptr);
} else {
/* nothing to do; media type cannot change */
return;
}
@ -2909,7 +2924,10 @@ mxge_media_probe(mxge_softc_t *sc)
if (mxge_verbose)
device_printf(sc->dev, "%s:%s\n", cage_type,
mxge_media_types[0].name);
mxge_set_media(sc, mxge_media_types[0].flag);
if (sc->current_media != mxge_media_types[0].flag) {
mxge_media_init(sc);
mxge_media_set(sc, mxge_media_types[0].flag);
}
return;
}
for (i = 1; i < mxge_media_type_entries; i++) {
@ -2919,12 +2937,16 @@ mxge_media_probe(mxge_softc_t *sc)
cage_type,
mxge_media_types[i].name);
mxge_set_media(sc, mxge_media_types[i].flag);
if (sc->current_media != mxge_media_types[i].flag) {
mxge_media_init(sc);
mxge_media_set(sc, mxge_media_types[i].flag);
}
return;
}
}
device_printf(sc->dev, "%s media 0x%x unknown\n", cage_type,
cmd.data0);
if (mxge_verbose)
device_printf(sc->dev, "%s media 0x%x unknown\n",
cage_type, cmd.data0);
return;
}
@ -2988,10 +3010,12 @@ mxge_intr(void *arg)
sc->link_state = stats->link_up;
if (sc->link_state) {
if_link_state_change(sc->ifp, LINK_STATE_UP);
sc->ifp->if_baudrate = IF_Gbps(10UL);
if (mxge_verbose)
device_printf(sc->dev, "link up\n");
} else {
if_link_state_change(sc->ifp, LINK_STATE_DOWN);
sc->ifp->if_baudrate = 0;
if (mxge_verbose)
device_printf(sc->dev, "link down\n");
}
@ -4026,9 +4050,9 @@ mxge_media_status(struct ifnet *ifp, struct ifmediareq *ifmr)
if (sc == NULL)
return;
ifmr->ifm_status = IFM_AVALID;
ifmr->ifm_active = IFM_ETHER | IFM_FDX;
ifmr->ifm_status |= sc->link_state ? IFM_ACTIVE : 0;
ifmr->ifm_active = IFM_AUTO | IFM_ETHER;
ifmr->ifm_active |= sc->link_state ? IFM_FDX : 0;
ifmr->ifm_active |= sc->current_media;
}
static int
@ -4135,6 +4159,9 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
break;
case SIOCGIFMEDIA:
mtx_lock(&sc->driver_mtx);
mxge_media_probe(sc);
mtx_unlock(&sc->driver_mtx);
err = ifmedia_ioctl(ifp, (struct ifreq *)data,
&sc->media, command);
break;
@ -4767,7 +4794,7 @@ mxge_attach(device_t dev)
/* Initialise the ifmedia structure */
ifmedia_init(&sc->media, 0, mxge_media_change,
mxge_media_status);
mxge_set_media(sc, IFM_ETHER | IFM_AUTO);
mxge_media_init(sc);
mxge_media_probe(sc);
sc->dying = 0;
ether_ifattach(ifp, sc->mac_addr);

View File

@ -268,6 +268,8 @@ struct mxge_softc {
int num_slices;
int rx_ring_size;
int dying;
int connector;
int current_media;
mxge_dma_t dmabench_dma;
struct callout co_hdl;
struct taskqueue *tq;
@ -293,6 +295,12 @@ struct mxge_softc {
#define MXGE_MIN_THROTTLE 416
#define MXGE_MAX_THROTTLE 4096
/* Types of connectors on NICs supported by this driver */
#define MXGE_CX4 0
#define MXGE_XFP 1
#define MXGE_SFP 2
#define MXGE_QRF 3
#define MXGE_HIGHPART_TO_U32(X) \
(sizeof (X) == 8) ? ((uint32_t)((uint64_t)(X) >> 32)) : (0)
#define MXGE_LOWPART_TO_U32(X) ((uint32_t)(X))