/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include hxge_status_t hxge_vmac_init(p_hxge_t hxgep); hxge_status_t hxge_tx_vmac_init(p_hxge_t hxgep); hxge_status_t hxge_rx_vmac_init(p_hxge_t hxgep); hxge_status_t hxge_tx_vmac_enable(p_hxge_t hxgep); hxge_status_t hxge_tx_vmac_disable(p_hxge_t hxgep); hxge_status_t hxge_rx_vmac_enable(p_hxge_t hxgep); hxge_status_t hxge_rx_vmac_disable(p_hxge_t hxgep); hxge_status_t hxge_tx_vmac_reset(p_hxge_t hxgep); hxge_status_t hxge_rx_vmac_reset(p_hxge_t hxgep); uint_t hxge_vmac_intr(caddr_t arg1, caddr_t arg2); hxge_status_t hxge_set_promisc(p_hxge_t hxgep, boolean_t on); hxge_status_t hxge_link_init(p_hxge_t hxgep) { p_hxge_stats_t statsp; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_link_init>")); statsp = hxgep->statsp; statsp->mac_stats.cap_10gfdx = 1; statsp->mac_stats.lp_cap_10gfdx = 1; /* * The driver doesn't control the link. * It is always 10Gb full duplex. */ statsp->mac_stats.link_duplex = 2; statsp->mac_stats.link_speed = 10000; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_link_init")); return (HXGE_OK); } hxge_status_t hxge_vmac_init(p_hxge_t hxgep) { hxge_status_t status = HXGE_OK; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_vmac_init:")); if ((status = hxge_tx_vmac_reset(hxgep)) != HXGE_OK) goto fail; if ((status = hxge_rx_vmac_reset(hxgep)) != HXGE_OK) goto fail; if ((status = hxge_tx_vmac_enable(hxgep)) != HXGE_OK) goto fail; if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK) goto fail; /* Clear the interrupt status registers */ (void) hpi_vmac_clear_rx_int_stat(hxgep->hpi_handle); (void) hpi_vmac_clear_tx_int_stat(hxgep->hpi_handle); /* * Take the masks off the overflow counters. Interrupt the system when * any counts overflow. Don't interrupt the system for each frame. * The current counts are retrieved when the "kstat" command is used. */ (void) hpi_pfc_set_rx_int_stat_mask(hxgep->hpi_handle, 0, 1); (void) hpi_pfc_set_tx_int_stat_mask(hxgep->hpi_handle, 0, 1); HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_vmac_init:")); return (HXGE_OK); fail: HXGE_DEBUG_MSG((hxgep, MAC_CTL, "hxge_vmac_init: failed to initialize VMAC>")); return (status); } /* Initialize the TxVMAC sub-block */ hxge_status_t hxge_tx_vmac_init(p_hxge_t hxgep) { uint64_t config; hpi_handle_t handle = hxgep->hpi_handle; /* CFG_VMAC_TX_EN is done separately */ config = CFG_VMAC_TX_CRC_INSERT | CFG_VMAC_TX_PAD; if (hpi_vmac_tx_config(handle, INIT, config, hxgep->vmac.maxframesize) != HPI_SUCCESS) return (HXGE_ERROR); hxgep->vmac.tx_config = config; return (HXGE_OK); } /* Initialize the RxVMAC sub-block */ hxge_status_t hxge_rx_vmac_init(p_hxge_t hxgep) { uint64_t xconfig; hpi_handle_t handle = hxgep->hpi_handle; uint16_t max_frame_length = hxgep->vmac.maxframesize; /* * NOTE: CFG_VMAC_RX_ENABLE is done separately. Do not enable * strip CRC. Bug ID 11451 -- enable strip CRC will cause * rejection on minimum sized packets. */ xconfig = CFG_VMAC_RX_PASS_FLOW_CTRL_FR; if (hxgep->filter.all_phys_cnt != 0) xconfig |= CFG_VMAC_RX_PROMISCUOUS_MODE; if (hxgep->filter.all_multicast_cnt != 0) xconfig |= CFG_VMAC_RX_PROMIXCUOUS_GROUP; if (hxgep->statsp->port_stats.lb_mode != hxge_lb_normal) xconfig |= CFG_VMAC_RX_LOOP_BACK; if (hpi_vmac_rx_config(handle, INIT, xconfig, max_frame_length) != HPI_SUCCESS) return (HXGE_ERROR); hxgep->vmac.rx_config = xconfig; return (HXGE_OK); } /* Enable TxVMAC */ hxge_status_t hxge_tx_vmac_enable(p_hxge_t hxgep) { hpi_status_t rv; hxge_status_t status = HXGE_OK; hpi_handle_t handle = hxgep->hpi_handle; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_enable")); rv = hxge_tx_vmac_init(hxgep); if (rv != HXGE_OK) return (rv); /* Based on speed */ hxgep->msg_min = ETHERMIN; rv = hpi_vmac_tx_config(handle, ENABLE, CFG_VMAC_TX_EN, 0); status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_enable")); return (status); } /* Disable TxVMAC */ hxge_status_t hxge_tx_vmac_disable(p_hxge_t hxgep) { hpi_status_t rv; hxge_status_t status = HXGE_OK; hpi_handle_t handle = hxgep->hpi_handle; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_disable")); rv = hpi_vmac_tx_config(handle, DISABLE, CFG_VMAC_TX_EN, 0); status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_disable")); return (status); } /* Enable RxVMAC */ hxge_status_t hxge_rx_vmac_enable(p_hxge_t hxgep) { hpi_status_t rv; hxge_status_t status = HXGE_OK; hpi_handle_t handle = hxgep->hpi_handle; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_enable")); /* * Because of hardware bug document with CR6770577, need * reprogram max framesize when enabling/disabling RX * vmac. Max framesize is programed here in * hxge_rx_vmac_init(). */ rv = hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep), (uint16_t)hxgep->vmac.maxframesize); if (rv != HPI_SUCCESS) { HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable")); return (HXGE_ERROR); } /* * Wait for a period of time. */ HXGE_DELAY(10); /* * Enable the vmac. */ rv = hpi_vmac_rx_config(handle, ENABLE, CFG_VMAC_RX_EN, 0); status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable")); return (status); } /* Disable RxVMAC */ hxge_status_t hxge_rx_vmac_disable(p_hxge_t hxgep) { hpi_status_t rv; hxge_status_t status = HXGE_OK; hpi_handle_t handle = hxgep->hpi_handle; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_disable")); /* * Because of hardware bug document with CR6770577, need * reprogram max framesize when enabling/disabling RX * vmac. Max framesize is programed here in * hxge_rx_vmac_init(). */ (void) hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep), (uint16_t)0); /* * Wait for 10us before doing disable. */ HXGE_DELAY(10); rv = hpi_vmac_rx_config(handle, DISABLE, CFG_VMAC_RX_EN, 0); status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_disable")); return (status); } /* Reset TxVMAC */ hxge_status_t hxge_tx_vmac_reset(p_hxge_t hxgep) { hpi_handle_t handle = hxgep->hpi_handle; (void) hpi_tx_vmac_reset(handle); return (HXGE_OK); } /* Reset RxVMAC */ hxge_status_t hxge_rx_vmac_reset(p_hxge_t hxgep) { hpi_handle_t handle = hxgep->hpi_handle; (void) hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep), (uint16_t)0); /* * Wait for 10us before doing reset. */ HXGE_DELAY(10); (void) hpi_rx_vmac_reset(handle); return (HXGE_OK); } /*ARGSUSED*/ uint_t hxge_vmac_intr(caddr_t arg1, caddr_t arg2) { p_hxge_t hxgep = (p_hxge_t)arg2; hpi_handle_t handle; HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_vmac_intr")); handle = HXGE_DEV_HPI_HANDLE(hxgep); hxge_save_cntrs(hxgep); /* Clear the interrupt status registers */ (void) hpi_vmac_clear_rx_int_stat(handle); (void) hpi_vmac_clear_tx_int_stat(handle); HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_vmac_intr")); return (DDI_INTR_CLAIMED); } /* * Set promiscous mode */ hxge_status_t hxge_set_promisc(p_hxge_t hxgep, boolean_t on) { hxge_status_t status = HXGE_OK; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_set_promisc: on %d", on)); hxgep->filter.all_phys_cnt = ((on) ? 1 : 0); RW_ENTER_WRITER(&hxgep->filter_lock); if ((status = hxge_rx_vmac_disable(hxgep)) != HXGE_OK) goto fail; if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK) goto fail; RW_EXIT(&hxgep->filter_lock); if (on) hxgep->statsp->mac_stats.promisc = B_TRUE; else hxgep->statsp->mac_stats.promisc = B_FALSE; HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_set_promisc")); return (HXGE_OK); fail: RW_EXIT(&hxgep->filter_lock); HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_promisc: " "Unable to set promisc (%d)", on)); return (status); } void hxge_save_cntrs(p_hxge_t hxgep) { p_hxge_stats_t statsp; hpi_handle_t handle; vmac_tx_frame_cnt_t tx_frame_cnt; vmac_tx_byte_cnt_t tx_byte_cnt; vmac_rx_frame_cnt_t rx_frame_cnt; vmac_rx_byte_cnt_t rx_byte_cnt; vmac_rx_drop_fr_cnt_t rx_drop_fr_cnt; vmac_rx_drop_byte_cnt_t rx_drop_byte_cnt; vmac_rx_crc_cnt_t rx_crc_cnt; vmac_rx_pause_cnt_t rx_pause_cnt; vmac_rx_bcast_fr_cnt_t rx_bcast_fr_cnt; vmac_rx_mcast_fr_cnt_t rx_mcast_fr_cnt; HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_save_cntrs")); statsp = (p_hxge_stats_t)hxgep->statsp; handle = hxgep->hpi_handle; HXGE_REG_RD64(handle, VMAC_TX_FRAME_CNT, &tx_frame_cnt.value); HXGE_REG_RD64(handle, VMAC_TX_BYTE_CNT, &tx_byte_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_FRAME_CNT, &rx_frame_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_BYTE_CNT, &rx_byte_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_DROP_FR_CNT, &rx_drop_fr_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_DROP_BYTE_CNT, &rx_drop_byte_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_CRC_CNT, &rx_crc_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_PAUSE_CNT, &rx_pause_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_BCAST_FR_CNT, &rx_bcast_fr_cnt.value); HXGE_REG_RD64(handle, VMAC_RX_MCAST_FR_CNT, &rx_mcast_fr_cnt.value); statsp->vmac_stats.tx_frame_cnt += tx_frame_cnt.bits.tx_frame_cnt; statsp->vmac_stats.tx_byte_cnt += tx_byte_cnt.bits.tx_byte_cnt; statsp->vmac_stats.rx_frame_cnt += rx_frame_cnt.bits.rx_frame_cnt; statsp->vmac_stats.rx_byte_cnt += rx_byte_cnt.bits.rx_byte_cnt; statsp->vmac_stats.rx_drop_frame_cnt += rx_drop_fr_cnt.bits.rx_drop_frame_cnt; statsp->vmac_stats.rx_drop_byte_cnt += rx_drop_byte_cnt.bits.rx_drop_byte_cnt; statsp->vmac_stats.rx_crc_cnt += rx_crc_cnt.bits.rx_crc_cnt; statsp->vmac_stats.rx_pause_cnt += rx_pause_cnt.bits.rx_pause_cnt; statsp->vmac_stats.rx_bcast_fr_cnt += rx_bcast_fr_cnt.bits.rx_bcast_fr_cnt; statsp->vmac_stats.rx_mcast_fr_cnt += rx_mcast_fr_cnt.bits.rx_mcast_fr_cnt; hxge_save_cntrs_exit: HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_save_cntrs")); } int hxge_vmac_set_framesize(p_hxge_t hxgep) { int status = 0; HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_vmac_set_framesize")); RW_ENTER_WRITER(&hxgep->filter_lock); (void) hxge_rx_vmac_disable(hxgep); (void) hxge_tx_vmac_disable(hxgep); /* * Apply the new jumbo parameter here which is contained in hxgep * data structure (hxgep->vmac.maxframesize); * The order of the following two calls is important. */ (void) hxge_tx_vmac_enable(hxgep); (void) hxge_rx_vmac_enable(hxgep); RW_EXIT(&hxgep->filter_lock); HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_vmac_set_framesize")); return (status); }