示例#1
0
/* Internally resume the rings on group basis (Eg IRM) */
int
oce_resume_group_rings(oce_group_t *grp)
{
	struct oce_dev *dev = grp->parent;
	int qidx, pmac_idx, ret = DDI_SUCCESS;

	if (grp->state & GROUP_MAC_STARTED) {

		if (grp->grp_num == 0) {
			if (dev->num_mca > OCE_MAX_MCA) {
				ret = oce_set_multicast_table(dev, dev->if_id,
				    &dev->multi_cast[0], OCE_MAX_MCA, B_TRUE,
				    MBX_BOOTSTRAP);
			} else {
				ret = oce_set_multicast_table(dev, dev->if_id,
				    &dev->multi_cast[0], dev->num_mca, B_FALSE,
				    MBX_BOOTSTRAP);
			}
			if (ret != 0) {
				oce_log(dev, CE_WARN, MOD_CONFIG,
				    "set mcast failed 0x%x", ret);
				return (ret);
			}
		}

		/* Add the group based MACs */
		for (pmac_idx = 0; pmac_idx < grp->num_pmac; pmac_idx++) {
			if (grp->pmac_ids[pmac_idx] != INVALID_PMAC_ID) {
				ret = oce_add_mac(dev, grp->if_id,
				    (uint8_t *)&grp->mac_addr[pmac_idx],
				    &grp->pmac_ids[pmac_idx], MBX_BOOTSTRAP);
				if (ret != DDI_SUCCESS) {
					oce_log(dev, CE_WARN, MOD_CONFIG,
					    "MAC addition failed grp = %p, "
					    "idx = %d, ret = %x",
					    (void *)grp, pmac_idx, ret);
					return (ret);
				}
			}
		}

		for (qidx = 0; qidx < grp->num_rings; qidx++) {
			mac_ring_intr_set(grp->ring[qidx].rx->handle,
			    dev->htable[grp->ring[qidx].rx->cq->eq->idx]);
			(void) oce_start_rq(grp->ring[qidx].rx);
		}
		grp->state &= ~GROUP_SUSPEND;
	}
	return (ret);
}
示例#2
0
int
oce_m_multicast(void *arg, boolean_t add, const uint8_t *mca)
{
	struct oce_dev *dev = (struct oce_dev *)arg;
	struct ether_addr  *mca_drv_list;
	struct ether_addr  mca_hw_list[OCE_MAX_MCA];
	uint16_t new_mcnt = dev->num_mca;
	int ret;
	int i;

	/* check the address */
	if ((mca[0] & 0x1) == 0) {
		return (EINVAL);
	}
	/* Allocate the local array for holding the addresses temporarily */
	bzero(&mca_hw_list, sizeof (&mca_hw_list));
	mca_drv_list = &dev->multi_cast[0];

	DEV_LOCK(dev);
	if (add) {
		/* check if we exceeded hw max  supported */
		if (new_mcnt < OCE_MAX_MCA) {
			/* copy entire dev mca to the mbx */
			bcopy((void*)mca_drv_list,
			    (void*)mca_hw_list,
			    (dev->num_mca * sizeof (struct ether_addr)));
			/* Append the new one to local list */
			bcopy(mca, &mca_hw_list[dev->num_mca],
			    sizeof (struct ether_addr));
		}
		new_mcnt++;
	} else {
		struct ether_addr *hwlistp = &mca_hw_list[0];
		for (i = 0; i < dev->num_mca; i++) {
			/* copy only if it does not match */
			if (bcmp((mca_drv_list + i), mca, ETHERADDRL)) {
				bcopy(mca_drv_list + i, hwlistp,
				    ETHERADDRL);
				hwlistp++;
			} else {
				new_mcnt--;
			}
		}
	}

	if (dev->suspended) {
		goto finish;
	}
	if (new_mcnt > OCE_MAX_MCA) {
		ret = oce_set_multicast_table(dev, dev->if_id, &mca_hw_list[0],
		    OCE_MAX_MCA, B_TRUE);
	} else {
		ret = oce_set_multicast_table(dev, dev->if_id,
		    &mca_hw_list[0], new_mcnt, B_FALSE);
	}
		if (ret != 0) {
		oce_log(dev, CE_WARN, MOD_CONFIG,
		    "mcast %s fails", add ? "ADD" : "DEL");
		DEV_UNLOCK(dev);
		return (EIO);
	}
	/*
	 *  Copy the local structure to dev structure
	 */
finish:
	if (new_mcnt && new_mcnt <= OCE_MAX_MCA) {
		bcopy(mca_hw_list, mca_drv_list,
		    new_mcnt * sizeof (struct ether_addr));

		dev->num_mca = (uint16_t)new_mcnt;
	}
	DEV_UNLOCK(dev);
	oce_log(dev, CE_NOTE, MOD_CONFIG,
	    "mcast %s, addr=%02x:%02x:%02x:%02x:%02x:%02x, num_mca=%d",
	    add ? "ADD" : "DEL",
	    mca[0], mca[1], mca[2], mca[3], mca[4], mca[5],
	    dev->num_mca);
	return (0);
} /* oce_m_multicast */