Home | History | Annotate | Download | only in hxge
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include <hxge_impl.h>
     28 #include <hxge_vmac.h>
     29 
     30 hxge_status_t hxge_vmac_init(p_hxge_t hxgep);
     31 hxge_status_t hxge_tx_vmac_init(p_hxge_t hxgep);
     32 hxge_status_t hxge_rx_vmac_init(p_hxge_t hxgep);
     33 hxge_status_t hxge_tx_vmac_enable(p_hxge_t hxgep);
     34 hxge_status_t hxge_tx_vmac_disable(p_hxge_t hxgep);
     35 hxge_status_t hxge_rx_vmac_enable(p_hxge_t hxgep);
     36 hxge_status_t hxge_rx_vmac_disable(p_hxge_t hxgep);
     37 hxge_status_t hxge_tx_vmac_reset(p_hxge_t hxgep);
     38 hxge_status_t hxge_rx_vmac_reset(p_hxge_t hxgep);
     39 uint_t hxge_vmac_intr(caddr_t arg1, caddr_t arg2);
     40 hxge_status_t hxge_set_promisc(p_hxge_t hxgep, boolean_t on);
     41 
     42 hxge_status_t
     43 hxge_link_init(p_hxge_t hxgep)
     44 {
     45 	p_hxge_stats_t		statsp;
     46 
     47 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_link_init>"));
     48 
     49 	statsp = hxgep->statsp;
     50 
     51 	statsp->mac_stats.cap_10gfdx = 1;
     52 	statsp->mac_stats.lp_cap_10gfdx = 1;
     53 
     54 	/*
     55 	 * The driver doesn't control the link.
     56 	 * It is always 10Gb full duplex.
     57 	 */
     58 	statsp->mac_stats.link_duplex = 2;
     59 	statsp->mac_stats.link_speed = 10000;
     60 
     61 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_link_init"));
     62 	return (HXGE_OK);
     63 }
     64 
     65 hxge_status_t
     66 hxge_vmac_init(p_hxge_t hxgep)
     67 {
     68 	hxge_status_t status = HXGE_OK;
     69 
     70 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_vmac_init:"));
     71 
     72 	if ((status = hxge_tx_vmac_reset(hxgep)) != HXGE_OK)
     73 		goto fail;
     74 
     75 	if ((status = hxge_rx_vmac_reset(hxgep)) != HXGE_OK)
     76 		goto fail;
     77 
     78 	if ((status = hxge_tx_vmac_enable(hxgep)) != HXGE_OK)
     79 		goto fail;
     80 
     81 	if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK)
     82 		goto fail;
     83 
     84 	/* Clear the interrupt status registers */
     85 	(void) hpi_vmac_clear_rx_int_stat(hxgep->hpi_handle);
     86 	(void) hpi_vmac_clear_tx_int_stat(hxgep->hpi_handle);
     87 
     88 	/*
     89 	 * Take the masks off the overflow counters. Interrupt the system when
     90 	 * any counts overflow. Don't interrupt the system for each frame.
     91 	 * The current counts are retrieved when the "kstat" command is used.
     92 	 */
     93 	(void) hpi_pfc_set_rx_int_stat_mask(hxgep->hpi_handle, 0, 1);
     94 	(void) hpi_pfc_set_tx_int_stat_mask(hxgep->hpi_handle, 0, 1);
     95 
     96 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_vmac_init:"));
     97 
     98 	return (HXGE_OK);
     99 fail:
    100 	HXGE_DEBUG_MSG((hxgep, MAC_CTL,
    101 	    "hxge_vmac_init: failed to initialize VMAC>"));
    102 
    103 	return (status);
    104 }
    105 
    106 
    107 /* Initialize the TxVMAC sub-block */
    108 
    109 hxge_status_t
    110 hxge_tx_vmac_init(p_hxge_t hxgep)
    111 {
    112 	uint64_t	config;
    113 	hpi_handle_t	handle = hxgep->hpi_handle;
    114 
    115 	/* CFG_VMAC_TX_EN is done separately */
    116 	config = CFG_VMAC_TX_CRC_INSERT | CFG_VMAC_TX_PAD;
    117 
    118 	if (hpi_vmac_tx_config(handle, INIT, config,
    119 	    hxgep->vmac.maxframesize) != HPI_SUCCESS)
    120 		return (HXGE_ERROR);
    121 
    122 	hxgep->vmac.tx_config = config;
    123 
    124 	return (HXGE_OK);
    125 }
    126 
    127 /* Initialize the RxVMAC sub-block */
    128 
    129 hxge_status_t
    130 hxge_rx_vmac_init(p_hxge_t hxgep)
    131 {
    132 	uint64_t	xconfig;
    133 	hpi_handle_t	handle = hxgep->hpi_handle;
    134 	uint16_t	max_frame_length = hxgep->vmac.maxframesize;
    135 
    136 	/*
    137 	 * NOTE: CFG_VMAC_RX_ENABLE is done separately. Do not enable
    138 	 * strip CRC.  Bug ID 11451 -- enable strip CRC will cause
    139 	 * rejection on minimum sized packets.
    140 	 */
    141 	xconfig = CFG_VMAC_RX_PASS_FLOW_CTRL_FR;
    142 
    143 	if (hxgep->filter.all_phys_cnt != 0)
    144 		xconfig |= CFG_VMAC_RX_PROMISCUOUS_MODE;
    145 
    146 	if (hxgep->filter.all_multicast_cnt != 0)
    147 		xconfig |= CFG_VMAC_RX_PROMIXCUOUS_GROUP;
    148 
    149 	if (hxgep->statsp->port_stats.lb_mode != hxge_lb_normal)
    150 		xconfig |= CFG_VMAC_RX_LOOP_BACK;
    151 
    152 	if (hpi_vmac_rx_config(handle, INIT, xconfig,
    153 	    max_frame_length) != HPI_SUCCESS)
    154 		return (HXGE_ERROR);
    155 
    156 	hxgep->vmac.rx_config = xconfig;
    157 
    158 	return (HXGE_OK);
    159 }
    160 
    161 /* Enable TxVMAC */
    162 
    163 hxge_status_t
    164 hxge_tx_vmac_enable(p_hxge_t hxgep)
    165 {
    166 	hpi_status_t	rv;
    167 	hxge_status_t	status = HXGE_OK;
    168 	hpi_handle_t	handle = hxgep->hpi_handle;
    169 
    170 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_enable"));
    171 
    172 	rv = hxge_tx_vmac_init(hxgep);
    173 	if (rv != HXGE_OK)
    174 		return (rv);
    175 
    176 	/* Based on speed */
    177 	hxgep->msg_min = ETHERMIN;
    178 
    179 	rv = hpi_vmac_tx_config(handle, ENABLE, CFG_VMAC_TX_EN, 0);
    180 
    181 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
    182 
    183 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_enable"));
    184 
    185 	return (status);
    186 }
    187 
    188 /* Disable TxVMAC */
    189 
    190 hxge_status_t
    191 hxge_tx_vmac_disable(p_hxge_t hxgep)
    192 {
    193 	hpi_status_t	rv;
    194 	hxge_status_t	status = HXGE_OK;
    195 	hpi_handle_t	handle = hxgep->hpi_handle;
    196 
    197 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_disable"));
    198 
    199 	rv = hpi_vmac_tx_config(handle, DISABLE, CFG_VMAC_TX_EN, 0);
    200 
    201 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
    202 
    203 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_disable"));
    204 
    205 	return (status);
    206 }
    207 
    208 /* Enable RxVMAC */
    209 
    210 hxge_status_t
    211 hxge_rx_vmac_enable(p_hxge_t hxgep)
    212 {
    213 	hpi_status_t	rv;
    214 	hxge_status_t	status = HXGE_OK;
    215 	hpi_handle_t	handle = hxgep->hpi_handle;
    216 
    217 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_enable"));
    218 
    219 	/*
    220 	 * Because of hardware bug document with CR6770577, need
    221 	 * reprogram max framesize when enabling/disabling RX
    222 	 * vmac.  Max framesize is programed here in
    223 	 * hxge_rx_vmac_init().
    224 	 */
    225 	rv = hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep),
    226 	    (uint16_t)hxgep->vmac.maxframesize);
    227 	if (rv != HPI_SUCCESS) {
    228 		HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable"));
    229 		return (HXGE_ERROR);
    230 	}
    231 
    232 	/*
    233 	 * Wait for a period of time.
    234 	 */
    235 	HXGE_DELAY(10);
    236 
    237 	/*
    238 	 * Enable the vmac.
    239 	 */
    240 	rv = hpi_vmac_rx_config(handle, ENABLE, CFG_VMAC_RX_EN, 0);
    241 
    242 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
    243 
    244 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable"));
    245 	return (status);
    246 }
    247 
    248 /* Disable RxVMAC */
    249 
    250 hxge_status_t
    251 hxge_rx_vmac_disable(p_hxge_t hxgep)
    252 {
    253 	hpi_status_t	rv;
    254 	hxge_status_t	status = HXGE_OK;
    255 	hpi_handle_t	handle = hxgep->hpi_handle;
    256 
    257 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_disable"));
    258 
    259 	/*
    260 	 * Because of hardware bug document with CR6770577, need
    261 	 * reprogram max framesize when enabling/disabling RX
    262 	 * vmac.  Max framesize is programed here in
    263 	 * hxge_rx_vmac_init().
    264 	 */
    265 	(void) hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep),
    266 	    (uint16_t)0);
    267 
    268 	/*
    269 	 * Wait for 10us before doing disable.
    270 	 */
    271 	HXGE_DELAY(10);
    272 
    273 	rv = hpi_vmac_rx_config(handle, DISABLE, CFG_VMAC_RX_EN, 0);
    274 
    275 	status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR;
    276 
    277 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_disable"));
    278 	return (status);
    279 }
    280 
    281 /* Reset TxVMAC */
    282 
    283 hxge_status_t
    284 hxge_tx_vmac_reset(p_hxge_t hxgep)
    285 {
    286 	hpi_handle_t	handle = hxgep->hpi_handle;
    287 
    288 	(void) hpi_tx_vmac_reset(handle);
    289 
    290 	return (HXGE_OK);
    291 }
    292 
    293 /* Reset RxVMAC */
    294 
    295 hxge_status_t
    296 hxge_rx_vmac_reset(p_hxge_t hxgep)
    297 {
    298 	hpi_handle_t	handle = hxgep->hpi_handle;
    299 
    300 	(void) hpi_vmac_rx_set_framesize(HXGE_DEV_HPI_HANDLE(hxgep),
    301 	    (uint16_t)0);
    302 
    303 	/*
    304 	 * Wait for 10us  before doing reset.
    305 	 */
    306 	HXGE_DELAY(10);
    307 
    308 	(void) hpi_rx_vmac_reset(handle);
    309 
    310 	return (HXGE_OK);
    311 }
    312 
    313 /*ARGSUSED*/
    314 uint_t
    315 hxge_vmac_intr(caddr_t arg1, caddr_t arg2)
    316 {
    317 	p_hxge_t	hxgep = (p_hxge_t)arg2;
    318 	hpi_handle_t	handle;
    319 
    320 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_vmac_intr"));
    321 
    322 	handle = HXGE_DEV_HPI_HANDLE(hxgep);
    323 
    324 	hxge_save_cntrs(hxgep);
    325 
    326 	/* Clear the interrupt status registers */
    327 	(void) hpi_vmac_clear_rx_int_stat(handle);
    328 	(void) hpi_vmac_clear_tx_int_stat(handle);
    329 
    330 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_vmac_intr"));
    331 	return (DDI_INTR_CLAIMED);
    332 }
    333 
    334 /*
    335  * Set promiscous mode
    336  */
    337 hxge_status_t
    338 hxge_set_promisc(p_hxge_t hxgep, boolean_t on)
    339 {
    340 	hxge_status_t status = HXGE_OK;
    341 
    342 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_set_promisc: on %d", on));
    343 
    344 	hxgep->filter.all_phys_cnt = ((on) ? 1 : 0);
    345 
    346 	RW_ENTER_WRITER(&hxgep->filter_lock);
    347 	if ((status = hxge_rx_vmac_disable(hxgep)) != HXGE_OK)
    348 		goto fail;
    349 	if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK)
    350 		goto fail;
    351 	RW_EXIT(&hxgep->filter_lock);
    352 
    353 	if (on)
    354 		hxgep->statsp->mac_stats.promisc = B_TRUE;
    355 	else
    356 		hxgep->statsp->mac_stats.promisc = B_FALSE;
    357 
    358 	HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_set_promisc"));
    359 	return (HXGE_OK);
    360 
    361 fail:
    362 	RW_EXIT(&hxgep->filter_lock);
    363 
    364 	HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_promisc: "
    365 	    "Unable to set promisc (%d)", on));
    366 	return (status);
    367 }
    368 
    369 void
    370 hxge_save_cntrs(p_hxge_t hxgep)
    371 {
    372 	p_hxge_stats_t	statsp;
    373 	hpi_handle_t	handle;
    374 
    375 	vmac_tx_frame_cnt_t tx_frame_cnt;
    376 	vmac_tx_byte_cnt_t tx_byte_cnt;
    377 	vmac_rx_frame_cnt_t rx_frame_cnt;
    378 	vmac_rx_byte_cnt_t rx_byte_cnt;
    379 	vmac_rx_drop_fr_cnt_t rx_drop_fr_cnt;
    380 	vmac_rx_drop_byte_cnt_t rx_drop_byte_cnt;
    381 	vmac_rx_crc_cnt_t rx_crc_cnt;
    382 	vmac_rx_pause_cnt_t rx_pause_cnt;
    383 	vmac_rx_bcast_fr_cnt_t rx_bcast_fr_cnt;
    384 	vmac_rx_mcast_fr_cnt_t rx_mcast_fr_cnt;
    385 
    386 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_save_cntrs"));
    387 
    388 	statsp = (p_hxge_stats_t)hxgep->statsp;
    389 	handle = hxgep->hpi_handle;
    390 
    391 	HXGE_REG_RD64(handle, VMAC_TX_FRAME_CNT, &tx_frame_cnt.value);
    392 	HXGE_REG_RD64(handle, VMAC_TX_BYTE_CNT, &tx_byte_cnt.value);
    393 	HXGE_REG_RD64(handle, VMAC_RX_FRAME_CNT, &rx_frame_cnt.value);
    394 	HXGE_REG_RD64(handle, VMAC_RX_BYTE_CNT, &rx_byte_cnt.value);
    395 	HXGE_REG_RD64(handle, VMAC_RX_DROP_FR_CNT, &rx_drop_fr_cnt.value);
    396 	HXGE_REG_RD64(handle, VMAC_RX_DROP_BYTE_CNT, &rx_drop_byte_cnt.value);
    397 	HXGE_REG_RD64(handle, VMAC_RX_CRC_CNT, &rx_crc_cnt.value);
    398 	HXGE_REG_RD64(handle, VMAC_RX_PAUSE_CNT, &rx_pause_cnt.value);
    399 	HXGE_REG_RD64(handle, VMAC_RX_BCAST_FR_CNT, &rx_bcast_fr_cnt.value);
    400 	HXGE_REG_RD64(handle, VMAC_RX_MCAST_FR_CNT, &rx_mcast_fr_cnt.value);
    401 
    402 	statsp->vmac_stats.tx_frame_cnt += tx_frame_cnt.bits.tx_frame_cnt;
    403 	statsp->vmac_stats.tx_byte_cnt += tx_byte_cnt.bits.tx_byte_cnt;
    404 	statsp->vmac_stats.rx_frame_cnt += rx_frame_cnt.bits.rx_frame_cnt;
    405 	statsp->vmac_stats.rx_byte_cnt += rx_byte_cnt.bits.rx_byte_cnt;
    406 	statsp->vmac_stats.rx_drop_frame_cnt +=
    407 	    rx_drop_fr_cnt.bits.rx_drop_frame_cnt;
    408 	statsp->vmac_stats.rx_drop_byte_cnt +=
    409 	    rx_drop_byte_cnt.bits.rx_drop_byte_cnt;
    410 	statsp->vmac_stats.rx_crc_cnt += rx_crc_cnt.bits.rx_crc_cnt;
    411 	statsp->vmac_stats.rx_pause_cnt += rx_pause_cnt.bits.rx_pause_cnt;
    412 	statsp->vmac_stats.rx_bcast_fr_cnt +=
    413 	    rx_bcast_fr_cnt.bits.rx_bcast_fr_cnt;
    414 	statsp->vmac_stats.rx_mcast_fr_cnt +=
    415 	    rx_mcast_fr_cnt.bits.rx_mcast_fr_cnt;
    416 
    417 hxge_save_cntrs_exit:
    418 	HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_save_cntrs"));
    419 }
    420 
    421 int
    422 hxge_vmac_set_framesize(p_hxge_t hxgep)
    423 {
    424 	int	status = 0;
    425 
    426 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_vmac_set_framesize"));
    427 
    428 	RW_ENTER_WRITER(&hxgep->filter_lock);
    429 	(void) hxge_rx_vmac_disable(hxgep);
    430 	(void) hxge_tx_vmac_disable(hxgep);
    431 
    432 	/*
    433 	 * Apply the new jumbo parameter here which is contained in hxgep
    434 	 * data structure (hxgep->vmac.maxframesize);
    435 	 * The order of the following two calls is important.
    436 	 */
    437 	(void) hxge_tx_vmac_enable(hxgep);
    438 	(void) hxge_rx_vmac_enable(hxgep);
    439 	RW_EXIT(&hxgep->filter_lock);
    440 
    441 	HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_vmac_set_framesize"));
    442 	return (status);
    443 }
    444