Example #1
0
/*
 * XXX: Poll a particular ring. The implementation is incomplete.
 * Once the ring interrupts are disabled, we need to do bge_recyle()
 * for the ring as well and re enable the ring interrupt automatically
 * if the poll doesn't find any packets in the ring. We need to
 * have MSI-X interrupts support for this.
 *
 * The basic poll policy is that rings that are dealing with explicit
 * flows (like TCP or some service) and are marked as such should
 * have their own MSI-X interrupt per ring. bge_intr() should leave
 * that interrupt disabled after an upcall. The ring is in poll mode.
 * When a poll thread comes down and finds nothing, the MSI-X interrupt
 * is automatically enabled. Squeue needs to deal with the race of
 * a new interrupt firing and reaching before poll thread returns.
 */
mblk_t *
bge_poll_ring(void *arg, int bytes_to_pickup)
{
    recv_ring_t *rrp = arg;
    bge_t *bgep = rrp->bgep;
    bge_rbd_t *hw_rbd_p;
    uint64_t slot;
    mblk_t *head;
    mblk_t **tail;
    mblk_t *mp;
    size_t sz = 0;

    mutex_enter(rrp->rx_lock);

    /*
     * Sync (all) the receive ring descriptors
     * before accepting the packets they describe
     */
    DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORKERNEL);
    if (*rrp->prod_index_p >= rrp->desc.nslots) {
        bgep->bge_chip_state = BGE_CHIP_ERROR;
        bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
        mutex_exit(rrp->rx_lock);
        return (NULL);
    }
    if (bge_check_dma_handle(bgep, rrp->desc.dma_hdl) != DDI_FM_OK) {
        rrp->rx_next = *rrp->prod_index_p;
        bge_mbx_put(bgep, rrp->chip_mbx_reg, rrp->rx_next);
        bgep->bge_dma_error = B_TRUE;
        bgep->bge_chip_state = BGE_CHIP_ERROR;
        mutex_exit(rrp->rx_lock);
        return (NULL);
    }

    hw_rbd_p = DMA_VPTR(rrp->desc);
    head = NULL;
    tail = &head;
    slot = rrp->rx_next;

    /* Note: volatile */
    while ((slot != *rrp->prod_index_p) && (sz <= bytes_to_pickup)) {
        if ((mp = bge_receive_packet(bgep, &hw_rbd_p[slot], rrp))
                != NULL) {
            *tail = mp;
            sz += msgdsize(mp);
            tail = &mp->b_next;
        }
        rrp->rx_next = slot = NEXT(slot, rrp->desc.nslots);
    }

    bge_mbx_put(bgep, rrp->chip_mbx_reg, rrp->rx_next);
    if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
        bgep->bge_chip_state = BGE_CHIP_ERROR;
    mutex_exit(rrp->rx_lock);
    return (head);
}
Example #2
0
/*
 * Reset the physical layer
 */
void
bge_phys_reset(bge_t *bgep)
{
	BGE_TRACE(("bge_phys_reset($%p)", (void *)bgep));

	mutex_enter(bgep->genlock);
	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS)
		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_UNAFFECTED);
	mutex_exit(bgep->genlock);
}
Example #3
0
static mblk_t *
bge_receive_ring(bge_t *bgep, recv_ring_t *rrp)
{
    bge_rbd_t *hw_rbd_p;
    uint64_t slot;
    mblk_t *head;
    mblk_t **tail;
    mblk_t *mp;
    int recv_cnt = 0;

    ASSERT(mutex_owned(rrp->rx_lock));

    /*
     * Sync (all) the receive ring descriptors
     * before accepting the packets they describe
     */
    DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORKERNEL);
    if (*rrp->prod_index_p >= rrp->desc.nslots) {
        bgep->bge_chip_state = BGE_CHIP_ERROR;
        bge_fm_ereport(bgep, DDI_FM_DEVICE_INVAL_STATE);
        return (NULL);
    }
    if (bge_check_dma_handle(bgep, rrp->desc.dma_hdl) != DDI_FM_OK) {
        rrp->rx_next = *rrp->prod_index_p;
        bge_mbx_put(bgep, rrp->chip_mbx_reg, rrp->rx_next);
        bgep->bge_dma_error = B_TRUE;
        bgep->bge_chip_state = BGE_CHIP_ERROR;
        return (NULL);
    }

    hw_rbd_p = DMA_VPTR(rrp->desc);
    head = NULL;
    tail = &head;
    slot = rrp->rx_next;

    while ((slot != *rrp->prod_index_p) && /* Note: volatile	*/
            (recv_cnt < BGE_MAXPKT_RCVED)) {
        if ((mp = bge_receive_packet(bgep, &hw_rbd_p[slot], rrp))
                != NULL) {
            *tail = mp;
            tail = &mp->b_next;
            recv_cnt++;
        }
        rrp->rx_next = slot = NEXT(slot, rrp->desc.nslots);
    }

    bge_mbx_put(bgep, rrp->chip_mbx_reg, rrp->rx_next);
    if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK)
        bgep->bge_chip_state = BGE_CHIP_ERROR;
    return (head);
}
Example #4
0
/*
 * Here we have to determine which media we're using (copper or serdes).
 * Once that's done, we can initialise the physical layer appropriately.
 */
int
bge_phys_init(bge_t *bgep)
{
	BGE_TRACE(("bge_phys_init($%p)", (void *)bgep));

	mutex_enter(bgep->genlock);

	/*
	 * Probe for the (internal) PHY.  If it's not there, we'll assume
	 * that this is a 5703/4S, with a SerDes interface rather than
	 * a PHY. BCM5714S/BCM5715S are not supported.It are based on
	 * BCM800x PHY.
	 */
	bgep->phy_mii_addr = 1;
	if (DEVICE_5717_SERIES_CHIPSETS(bgep)) {
		int regval = bge_reg_get32(bgep, CPMU_STATUS_REG);
		if (regval & CPMU_STATUS_FUN_NUM)
			bgep->phy_mii_addr += 1;
		regval = bge_reg_get32(bgep, SGMII_STATUS_REG);
		if (regval & MEDIA_SELECTION_MODE)
			bgep->phy_mii_addr += 7;
	}

	if (bge_phy_probe(bgep)) {
		bgep->chipid.flags &= ~CHIP_FLAG_SERDES;
		bgep->physops = &copper_ops;
	} else {
		bgep->chipid.flags |= CHIP_FLAG_SERDES;
		bgep->physops = &serdes_ops;
	}

	if ((*bgep->physops->phys_restart)(bgep, B_FALSE) != DDI_SUCCESS) {
		mutex_exit(bgep->genlock);
		return (EIO);
	}
	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
		mutex_exit(bgep->genlock);
		return (EIO);
	}
	mutex_exit(bgep->genlock);
	return (0);
}
Example #5
0
int
bge_m_stat(void *arg, uint_t stat, uint64_t *val)
{
	bge_t *bgep = arg;
	bge_statistics_t *bstp;
	bge_statistics_reg_t *pstats;

	if (bgep->bge_chip_state != BGE_CHIP_RUNNING) {
		return (EINVAL);
	}

	if (bgep->chipid.statistic_type == BGE_STAT_BLK)
		bstp = DMA_VPTR(bgep->statistics);
	else {
		pstats = bgep->pstats;
		pstats->ifHCOutOctets +=
		    bge_reg_get32(bgep, STAT_IFHCOUT_OCTETS_REG);
		pstats->etherStatsCollisions +=
		    bge_reg_get32(bgep, STAT_ETHER_COLLIS_REG);
		pstats->outXonSent +=
		    bge_reg_get32(bgep, STAT_OUTXON_SENT_REG);
		pstats->outXoffSent +=
		    bge_reg_get32(bgep, STAT_OUTXOFF_SENT_REG);
		pstats->dot3StatsInternalMacTransmitErrors +=
		    bge_reg_get32(bgep, STAT_DOT3_INTMACTX_ERR_REG);
		pstats->dot3StatsSingleCollisionFrames +=
		    bge_reg_get32(bgep, STAT_DOT3_SCOLLI_FRAME_REG);
		pstats->dot3StatsMultipleCollisionFrames +=
		    bge_reg_get32(bgep, STAT_DOT3_MCOLLI_FRAME_REG);
		pstats->dot3StatsDeferredTransmissions +=
		    bge_reg_get32(bgep, STAT_DOT3_DEFERED_TX_REG);
		pstats->dot3StatsExcessiveCollisions +=
		    bge_reg_get32(bgep, STAT_DOT3_EXCE_COLLI_REG);
		pstats->dot3StatsLateCollisions +=
		    bge_reg_get32(bgep, STAT_DOT3_LATE_COLLI_REG);
		pstats->ifHCOutUcastPkts +=
		    bge_reg_get32(bgep, STAT_IFHCOUT_UPKGS_REG);
		pstats->ifHCOutMulticastPkts +=
		    bge_reg_get32(bgep, STAT_IFHCOUT_MPKGS_REG);
		pstats->ifHCOutBroadcastPkts +=
		    bge_reg_get32(bgep, STAT_IFHCOUT_BPKGS_REG);
		pstats->ifHCInOctets +=
		    bge_reg_get32(bgep, STAT_IFHCIN_OCTETS_REG);
		pstats->etherStatsFragments +=
		    bge_reg_get32(bgep, STAT_ETHER_FRAGMENT_REG);
		pstats->ifHCInUcastPkts +=
		    bge_reg_get32(bgep, STAT_IFHCIN_UPKGS_REG);
		pstats->ifHCInMulticastPkts +=
		    bge_reg_get32(bgep, STAT_IFHCIN_MPKGS_REG);
		pstats->ifHCInBroadcastPkts +=
		    bge_reg_get32(bgep, STAT_IFHCIN_BPKGS_REG);
		pstats->dot3StatsFCSErrors +=
		    bge_reg_get32(bgep, STAT_DOT3_FCS_ERR_REG);
		pstats->dot3StatsAlignmentErrors +=
		    bge_reg_get32(bgep, STAT_DOT3_ALIGN_ERR_REG);
		pstats->xonPauseFramesReceived +=
		    bge_reg_get32(bgep, STAT_XON_PAUSE_RX_REG);
		pstats->xoffPauseFramesReceived +=
		    bge_reg_get32(bgep, STAT_XOFF_PAUSE_RX_REG);
		pstats->macControlFramesReceived +=
		    bge_reg_get32(bgep, STAT_MAC_CTRL_RX_REG);
		pstats->xoffStateEntered +=
		    bge_reg_get32(bgep, STAT_XOFF_STATE_ENTER_REG);
		pstats->dot3StatsFrameTooLongs +=
		    bge_reg_get32(bgep, STAT_DOT3_FRAME_TOOLONG_REG);
		pstats->etherStatsJabbers +=
		    bge_reg_get32(bgep, STAT_ETHER_JABBERS_REG);
		pstats->etherStatsUndersizePkts +=
		    bge_reg_get32(bgep, STAT_ETHER_UNDERSIZE_REG);
		mutex_enter(bgep->genlock);
		if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
			ddi_fm_service_impact(bgep->devinfo,
			    DDI_SERVICE_UNAFFECTED);
		}
		mutex_exit(bgep->genlock);
	}

	switch (stat) {
	case MAC_STAT_IFSPEED:
		*val = (bgep->link_state != LINK_STATE_UNKNOWN) ?
		           (bgep->param_link_speed * 1000000ull) : 0;
		break;

	case MAC_STAT_MULTIRCV:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCInMulticastPkts;
		else
			*val = pstats->ifHCInMulticastPkts;
		break;

	case MAC_STAT_BRDCSTRCV:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCInBroadcastPkts;
		else
			*val = pstats->ifHCInBroadcastPkts;
		break;

	case MAC_STAT_MULTIXMT:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCOutMulticastPkts;
		else
			*val = pstats->ifHCOutMulticastPkts;
		break;

	case MAC_STAT_BRDCSTXMT:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCOutBroadcastPkts;
		else
			*val = pstats->ifHCOutBroadcastPkts;
		break;

	case MAC_STAT_NORCVBUF:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifInDiscards;
		else
			*val = 0;
		break;

	case MAC_STAT_IERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK) {
			*val = bstp->s.dot3StatsFCSErrors +
			    bstp->s.dot3StatsAlignmentErrors +
			    bstp->s.dot3StatsFrameTooLongs +
			    bstp->s.etherStatsUndersizePkts +
			    bstp->s.etherStatsJabbers;
		} else {
			*val = pstats->dot3StatsFCSErrors +
			    pstats->dot3StatsAlignmentErrors +
			    pstats->dot3StatsFrameTooLongs +
			    pstats->etherStatsUndersizePkts +
			    pstats->etherStatsJabbers;
		}
		break;

	case MAC_STAT_NOXMTBUF:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifOutDiscards;
		else
			*val = 0;
		break;

	case MAC_STAT_OERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifOutDiscards;
		else
			*val = 0;
		break;

	case MAC_STAT_COLLISIONS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.etherStatsCollisions;
		else
			*val = pstats->etherStatsCollisions;
		break;

	case MAC_STAT_RBYTES:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCInOctets;
		else
			*val = pstats->ifHCInOctets;
		break;

	case MAC_STAT_IPACKETS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCInUcastPkts +
			    bstp->s.ifHCInMulticastPkts +
			    bstp->s.ifHCInBroadcastPkts;
		else
			*val = pstats->ifHCInUcastPkts +
			    pstats->ifHCInMulticastPkts +
			    pstats->ifHCInBroadcastPkts;
		break;

	case MAC_STAT_OBYTES:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCOutOctets;
		else
			*val = pstats->ifHCOutOctets;
		break;

	case MAC_STAT_OPACKETS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.ifHCOutUcastPkts +
			    bstp->s.ifHCOutMulticastPkts +
			    bstp->s.ifHCOutBroadcastPkts;
		else
			*val = pstats->ifHCOutUcastPkts +
			    pstats->ifHCOutMulticastPkts +
			    pstats->ifHCOutBroadcastPkts;
		break;

	case ETHER_STAT_ALIGN_ERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsAlignmentErrors;
		else
			*val = pstats->dot3StatsAlignmentErrors;
		break;

	case ETHER_STAT_FCS_ERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsFCSErrors;
		else
			*val = pstats->dot3StatsFCSErrors;
		break;

	case ETHER_STAT_FIRST_COLLISIONS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsSingleCollisionFrames;
		else
			*val = pstats->dot3StatsSingleCollisionFrames;
		break;

	case ETHER_STAT_MULTI_COLLISIONS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsMultipleCollisionFrames;
		else
			*val = pstats->dot3StatsMultipleCollisionFrames;
		break;

	case ETHER_STAT_DEFER_XMTS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsDeferredTransmissions;
		else
			*val = pstats->dot3StatsDeferredTransmissions;
		break;

	case ETHER_STAT_TX_LATE_COLLISIONS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsLateCollisions;
		else
			*val = pstats->dot3StatsLateCollisions;
		break;

	case ETHER_STAT_EX_COLLISIONS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsExcessiveCollisions;
		else
			*val = pstats->dot3StatsExcessiveCollisions;
		break;

	case ETHER_STAT_MACXMT_ERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsInternalMacTransmitErrors;
		else
			*val = bgep->pstats->dot3StatsInternalMacTransmitErrors;
		break;

	case ETHER_STAT_CARRIER_ERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsCarrierSenseErrors;
		else
			*val = 0;
		break;

	case ETHER_STAT_TOOLONG_ERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.dot3StatsFrameTooLongs;
		else
			*val = pstats->dot3StatsFrameTooLongs;
		break;

#if (MAC_VERSION > 1)
	case ETHER_STAT_TOOSHORT_ERRORS:
		if (bgep->chipid.statistic_type == BGE_STAT_BLK)
			*val = bstp->s.etherStatsUndersizePkts;
		else
			*val = pstats->etherStatsUndersizePkts;
		break;
#endif

	case ETHER_STAT_XCVR_ADDR:
		*val = bgep->phy_mii_addr;
		break;

	case ETHER_STAT_XCVR_ID:
		mutex_enter(bgep->genlock);
		*val = bge_mii_get16(bgep, MII_PHYIDH);
		*val <<= 16;
		*val |= bge_mii_get16(bgep, MII_PHYIDL);
		if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
			ddi_fm_service_impact(bgep->devinfo,
			    DDI_SERVICE_UNAFFECTED);
		}
		mutex_exit(bgep->genlock);
		break;

	case ETHER_STAT_XCVR_INUSE:
		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
			*val = XCVR_1000X;
		else
			*val = XCVR_1000T;
		break;

	case ETHER_STAT_CAP_1000FDX:
		*val = 1;
		break;

	case ETHER_STAT_CAP_1000HDX:
		*val = 1;
		break;

	case ETHER_STAT_CAP_100FDX:
		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
			*val = 0;
		else
			*val = 1;
		break;

	case ETHER_STAT_CAP_100HDX:
		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
			*val = 0;
		else
			*val = 1;
		break;

	case ETHER_STAT_CAP_10FDX:
		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
			*val = 0;
		else
			*val = 1;
		break;

	case ETHER_STAT_CAP_10HDX:
		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
			*val = 0;
		else
			*val = 1;
		break;

	case ETHER_STAT_CAP_ASMPAUSE:
		*val = 1;
		break;

	case ETHER_STAT_CAP_PAUSE:
		*val = 1;
		break;

	case ETHER_STAT_CAP_AUTONEG:
		*val = 1;
		break;

#if (MAC_VERSION > 1)
	case ETHER_STAT_CAP_REMFAULT:
		*val = 1;
		break;
#endif

	case ETHER_STAT_ADV_CAP_1000FDX:
		*val = bgep->param_adv_1000fdx;
		break;

	case ETHER_STAT_ADV_CAP_1000HDX:
		*val = bgep->param_adv_1000hdx;
		break;

	case ETHER_STAT_ADV_CAP_100FDX:
		*val = bgep->param_adv_100fdx;
		break;

	case ETHER_STAT_ADV_CAP_100HDX:
		*val = bgep->param_adv_100hdx;
		break;

	case ETHER_STAT_ADV_CAP_10FDX:
		*val = bgep->param_adv_10fdx;
		break;

	case ETHER_STAT_ADV_CAP_10HDX:
		*val = bgep->param_adv_10hdx;
		break;

	case ETHER_STAT_ADV_CAP_ASMPAUSE:
		*val = bgep->param_adv_asym_pause;
		break;

	case ETHER_STAT_ADV_CAP_PAUSE:
		*val = bgep->param_adv_pause;
		break;

	case ETHER_STAT_ADV_CAP_AUTONEG:
		*val = bgep->param_adv_autoneg;
		break;

#if (MAC_VERSION > 1)
	case ETHER_STAT_ADV_REMFAULT:
		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
			*val = 0;
		else {
			mutex_enter(bgep->genlock);
			*val = bge_mii_get16(bgep, MII_AN_ADVERT) &
			    MII_AN_ADVERT_REMFAULT ? 1 : 0;
			if (bge_check_acc_handle(bgep, bgep->io_handle) !=
			    DDI_FM_OK) {
				ddi_fm_service_impact(bgep->devinfo,
				    DDI_SERVICE_UNAFFECTED);
			}
			mutex_exit(bgep->genlock);
		}
		break;
#endif

	case ETHER_STAT_LP_CAP_1000FDX:
		*val = bgep->param_lp_1000fdx;
		break;

	case ETHER_STAT_LP_CAP_1000HDX:
		*val = bgep->param_lp_1000hdx;
		break;

	case ETHER_STAT_LP_CAP_100FDX:
		*val = bgep->param_lp_100fdx;
		break;

	case ETHER_STAT_LP_CAP_100HDX:
		*val = bgep->param_lp_100hdx;
		break;

	case ETHER_STAT_LP_CAP_10FDX:
		*val = bgep->param_lp_10fdx;
		break;

	case ETHER_STAT_LP_CAP_10HDX:
		*val = bgep->param_lp_10hdx;
		break;

	case ETHER_STAT_LP_CAP_ASMPAUSE:
		*val = bgep->param_lp_asym_pause;
		break;

	case ETHER_STAT_LP_CAP_PAUSE:
		*val = bgep->param_lp_pause;
		break;

	case ETHER_STAT_LP_CAP_AUTONEG:
		*val = bgep->param_lp_autoneg;
		break;

#if (MAC_VERSION > 1)
	case ETHER_STAT_LP_REMFAULT:
		if (bgep->chipid.flags & CHIP_FLAG_SERDES)
			*val = 0;
		else {
			mutex_enter(bgep->genlock);
			*val = bge_mii_get16(bgep, MII_AN_LPABLE) &
			    MII_AN_ADVERT_REMFAULT ? 1 : 0;
			if (bge_check_acc_handle(bgep, bgep->io_handle) !=
			    DDI_FM_OK) {
				ddi_fm_service_impact(bgep->devinfo,
				    DDI_SERVICE_UNAFFECTED);
			}
			mutex_exit(bgep->genlock);
		}
		break;
#endif

	case ETHER_STAT_LINK_ASMPAUSE:
		*val = bgep->param_adv_asym_pause &&
		    bgep->param_lp_asym_pause &&
		    bgep->param_adv_pause != bgep->param_lp_pause;
		break;

	case ETHER_STAT_LINK_PAUSE:
		*val = bgep->param_link_rx_pause;
		break;

	case ETHER_STAT_LINK_AUTONEG:
		*val = bgep->param_link_autoneg;
		break;

	case ETHER_STAT_LINK_DUPLEX:
		*val = (bgep->link_state != LINK_STATE_UNKNOWN) ?
		           bgep->param_link_duplex : LINK_DUPLEX_UNKNOWN;
		break;

	default:
		return (ENOTSUP);
	}

	return (0);
}
Example #6
0
static int
bge_phydata_update(kstat_t *ksp, int flag)
{
	bge_t *bgep;
	kstat_named_t *knp;
	const bge_ksindex_t *ksip;

	if (flag != KSTAT_READ)
		return (EACCES);

	bgep = ksp->ks_private;
	if (bgep->bge_chip_state == BGE_CHIP_FAULT)
		return (EIO);

	knp = ksp->ks_data;

	/*
	 * Read the PHY registers & update the kstats ...
	 *
	 * We need to hold the mutex while performing MII reads, but
	 * we don't want to hold it across the entire sequence of reads.
	 * So we grab and release it on each iteration, 'cos it doesn't
	 * really matter if the kstats are less than 100% consistent ...
	 */
	for (ksip = bge_phydata; ksip->name != NULL; ++knp, ++ksip) {
		mutex_enter(bgep->genlock);
		switch (ksip->index) {
		case MII_STATUS:
			knp->value.ui64 = bgep->phy_gen_status;
			break;

		case MII_PHYIDH:
			knp->value.ui64 = bge_mii_get16(bgep, MII_PHYIDH);
			knp->value.ui64 <<= 16;
			knp->value.ui64 |= bge_mii_get16(bgep, MII_PHYIDL);
			break;

		case EEE_MODE_REG:
			knp->value.ui64 = 0;
			if (bgep->link_state == LINK_STATE_UP)
			{
				knp->value.ui64 =
				    (bge_reg_get32(bgep, EEE_MODE_REG) & 0x80) ?
				        1 : 0;
			}
			break;

		default:
			knp->value.ui64 = bge_mii_get16(bgep, ksip->index);
			break;
		}
		if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
			ddi_fm_service_impact(bgep->devinfo,
			    DDI_SERVICE_DEGRADED);
			mutex_exit(bgep->genlock);
			return (EIO);
		}
		mutex_exit(bgep->genlock);
	}

	return (0);
}
Example #7
0
static int
bge_driverinfo_update(kstat_t *ksp, int flag)
{
	bge_t *bgep;
	kstat_named_t *knp;
	ddi_acc_handle_t handle;

	if (flag != KSTAT_READ)
		return (EACCES);

	bgep = ksp->ks_private;
	if (bgep->bge_chip_state == BGE_CHIP_FAULT)
		return (EIO);

	knp = ksp->ks_data;

	(knp++)->value.ui64 = bgep->rx_buff[0].cookie.dmac_laddress;
	(knp++)->value.ui64 = bgep->tx_buff[0].cookie.dmac_laddress;
	(knp++)->value.ui64 = bgep->rx_desc[0].cookie.dmac_laddress;
	(knp++)->value.ui64 = bgep->tx_desc.cookie.dmac_laddress;

	(knp++)->value.ui64 = bgep->send[0].tx_free;
	(knp++)->value.ui64 = bgep->send[0].tx_array;
	(knp++)->value.ui64 = bgep->send[0].tc_next;
	(knp++)->value.ui64 = bgep->send[0].tx_next;
	(knp++)->value.ui64 = bgep->send[0].txfill_next;
	(knp++)->value.ui64 = bgep->send[0].txpkt_next;
	(knp++)->value.ui64 = bgep->send[0].txbuf_pop_queue->count +
	    bgep->send[0].txbuf_push_queue->count;
	(knp++)->value.ui64 = bgep->send[0].tx_flow;
	(knp++)->value.ui64 = bgep->tx_resched_needed;
	(knp++)->value.ui64 = bgep->tx_resched;
	(knp++)->value.ui64 = bgep->send[0].tx_nobuf;
	(knp++)->value.ui64 = bgep->send[0].tx_nobd;
	(knp++)->value.ui64 = bgep->send[0].tx_block;
	(knp++)->value.ui64 = bgep->send[0].tx_alloc_fail;

	(knp++)->value.ui64 = bgep->watchdog;
	(knp++)->value.ui64 = bgep->chip_resets;
	(knp++)->value.ui64 = bgep->missed_dmas;
	(knp++)->value.ui64 = bgep->missed_updates;

	/*
	 * Hold the mutex while accessing the chip registers
	 * just in case the factotum is trying to reset it!
	 */
	handle = bgep->cfg_handle;
	mutex_enter(bgep->genlock);
	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_MHCR);
	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_PDRWCR);
	(knp++)->value.ui64 = pci_config_get32(handle, PCI_CONF_BGE_PCISTATE);
	if (bge_check_acc_handle(bgep, bgep->cfg_handle) != DDI_FM_OK) {
		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
		mutex_exit(bgep->genlock);
		return (EIO);
	}

	(knp++)->value.ui64 = bge_reg_get32(bgep, BUFFER_MANAGER_STATUS_REG);
	(knp++)->value.ui64 = bge_reg_get32(bgep, RCV_INITIATOR_STATUS_REG);
	if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
		ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
		mutex_exit(bgep->genlock);
		return (EIO);
	}
	mutex_exit(bgep->genlock);

	return (0);
}