Skip to content

Commit

Permalink
8866 bnxe MAC_CAPAB_TRANSCEIVER support
Browse files Browse the repository at this point in the history
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Approved by: Dan McDonald <danmcd@joyent.com>
  • Loading branch information
rmustacc committed Feb 10, 2018
1 parent 017c366 commit 947eaaf
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 0 deletions.
1 change: 1 addition & 0 deletions usr/src/uts/common/Makefile.files
Expand Up @@ -2219,6 +2219,7 @@ BNXE_OBJS += bnxe_cfg.o \
bnxe_tx.o \
bnxe_workq.o \
bnxe_clc.o \
bnxe_illumos.o \
ecore_sp_verbs.o \
bnxe_context.o \
57710_init_values.o \
Expand Down
3 changes: 3 additions & 0 deletions usr/src/uts/common/io/bnxe/bnxe.h
Expand Up @@ -916,6 +916,9 @@ int BnxeCheckAccHandle(ddi_acc_handle_t handle);
int BnxeCheckDmaHandle(ddi_dma_handle_t handle);
void BnxeFmErrorReport(um_device_t * pUM, char * detail);

/* bnxe_illumos.c */
extern boolean_t bnxe_fill_transceiver(um_device_t *, void *);

extern kmutex_t bnxeLoaderMutex;
extern u32_t bnxeNumPlumbed;

Expand Down
6 changes: 6 additions & 0 deletions usr/src/uts/common/io/bnxe/bnxe_gld.c
Expand Up @@ -34,6 +34,7 @@

/*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2017, Joyent, Inc.
*/

#include "bnxe.h"
Expand Down Expand Up @@ -1859,6 +1860,11 @@ static boolean_t BnxeMacGetCapability(void * pArg,

#endif /* not __S11 or __S12 */

#if defined(ILLUMOS)
case MAC_CAPAB_TRANSCEIVER:
return bnxe_fill_transceiver(pUM, pCapabilityData);
#endif

default:

return B_FALSE;
Expand Down
180 changes: 180 additions & 0 deletions usr/src/uts/common/io/bnxe/bnxe_illumos.c
@@ -0,0 +1,180 @@
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
* http://www.illumos.org/license/CDDL.
*/

/*
* Copyright (c) 2017, Joyent, Inc.
*/

/*
* illumos specific bnxe related functions.
*/

#include "bnxe.h"

/*
* Try to figure out which phy we should be using at this time based on the
* requested transceiver.
*/
static uint_t
bnxe_get_phy_id(um_device_t *um)
{
if (um->lm_dev.params.link.num_phys <= 1)
return (ELINK_INT_PHY);

if (um->lm_dev.vars.link.link_up) {
if ((um->lm_dev.vars.link.link_status &
LINK_STATUS_SERDES_LINK) &&
(um->lm_dev.params.link.phy[ELINK_EXT_PHY2].supported &
ELINK_SUPPORTED_FIBRE))
return (ELINK_EXT_PHY2);
return (ELINK_EXT_PHY1);
} else {
switch (elink_phy_selection(&um->lm_dev.params.link)) {
case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY:
case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
return (ELINK_EXT_PHY1);
case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY:
case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
return (ELINK_EXT_PHY2);
/*
* The above hardware types are the only ones currently defined
* by the specification and common code. If we end up with an
* unknown value, then we default to what the hardware considers
* the default, which is PHY1.
*/
default:
return (ELINK_EXT_PHY1);
}
}
}

static int
bnxe_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
{
uint_t phyid;
um_device_t *um = arg;
struct elink_params *params;
struct elink_phy *phy;
boolean_t present = B_FALSE, usable = B_FALSE;
elink_status_t ret;
uint8_t buf;

if (id != 0 || arg == NULL || infop == NULL)
return (EINVAL);

BNXE_LOCK_ENTER_PHY(um);
phyid = bnxe_get_phy_id(um);
params = &um->lm_dev.params.link;
phy = &params->phy[phyid];
if (phy->media_type == ELINK_ETH_PHY_BASE_T) {
BNXE_LOCK_EXIT_PHY(um);
return (ENOTSUP);
}

/*
* Right now, the core OS-independent code from QLogic doesn't quite
* track whether or not the phy is plugged in, though it easily could.
* As such, the best way to determine whether or not the phy is present
* is to see if we can read the first byte from page 0xa0. We expect to
* get an explicit timeout if the device isn't present. We'll propagate
* EIO on any other error as we're not in a good state to understand
* what happened.
*/
PHY_HW_LOCK(&um->lm_dev);
ret = elink_read_sfp_module_eeprom(phy, params, 0xa0, 0, sizeof (buf),
&buf);
PHY_HW_UNLOCK(&um->lm_dev);
if (ret != ELINK_STATUS_OK && ret != ELINK_STATUS_TIMEOUT) {
BNXE_LOCK_EXIT_PHY(um);
return (EIO);
}
if (ret == ELINK_STATUS_OK) {
present = B_TRUE;
if ((phy->flags & ELINK_FLAGS_SFP_NOT_APPROVED) == 0)
usable = B_TRUE;
}
BNXE_LOCK_EXIT_PHY(um);

mac_transceiver_info_set_present(infop, present);
mac_transceiver_info_set_usable(infop, usable);

return (0);
}

static int
bnxe_transceiver_read(void *arg, uint_t id, uint_t page, void *bp,
size_t nbytes, off_t offset, size_t *nread)
{
uint_t phyid;
um_device_t *um = arg;
struct elink_phy *phy;
struct elink_params *params;
elink_status_t ret;

if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL ||
(page != 0xa0 && page != 0xa2) || offset < 0)
return (EINVAL);

/*
* Sanity check length params.
*/
if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
return (EINVAL);
}

BNXE_LOCK_ENTER_PHY(um);
phyid = bnxe_get_phy_id(um);
params = &um->lm_dev.params.link;
phy = &um->lm_dev.params.link.phy[phyid];

if (phy->media_type == ELINK_ETH_PHY_BASE_T) {
BNXE_LOCK_EXIT_PHY(um);
return (ENOTSUP);
}


PHY_HW_LOCK(&um->lm_dev);
ret = elink_read_sfp_module_eeprom(phy, params, (uint8_t)page,
(uint16_t)offset, (uint16_t)nbytes, bp);
PHY_HW_UNLOCK(&um->lm_dev);

BNXE_LOCK_EXIT_PHY(um);

switch (ret) {
case ELINK_STATUS_OK:
*nread = nbytes;
return (0);
case ELINK_OP_NOT_SUPPORTED:
return (ENOTSUP);
default:
return (EIO);
}
}

boolean_t
bnxe_fill_transceiver(um_device_t *um, void *arg)
{
uint_t ntran = 1;
mac_capab_transceiver_t *mct = arg;

mct->mct_flags = 0;
/*
* While there is nominally a dual-phy version of bnxe out there (see
* ELINK_DUAL_MEDIA and related macros), these haven't been seen in the
* wild. For now, only assume that we have a single phy.
*/
mct->mct_ntransceivers = 1;
mct->mct_info = bnxe_transceiver_info;
mct->mct_read = bnxe_transceiver_read;

return (B_TRUE);
}

0 comments on commit 947eaaf

Please sign in to comment.