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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <hxge_impl.h> 29 #include <hxge_vmac.h> 30 31 hxge_status_t hxge_vmac_init(p_hxge_t hxgep); 32 hxge_status_t hxge_tx_vmac_init(p_hxge_t hxgep); 33 hxge_status_t hxge_rx_vmac_init(p_hxge_t hxgep); 34 hxge_status_t hxge_tx_vmac_enable(p_hxge_t hxgep); 35 hxge_status_t hxge_tx_vmac_disable(p_hxge_t hxgep); 36 hxge_status_t hxge_rx_vmac_enable(p_hxge_t hxgep); 37 hxge_status_t hxge_rx_vmac_disable(p_hxge_t hxgep); 38 hxge_status_t hxge_tx_vmac_reset(p_hxge_t hxgep); 39 hxge_status_t hxge_rx_vmac_reset(p_hxge_t hxgep); 40 uint_t hxge_vmac_intr(caddr_t arg1, caddr_t arg2); 41 hxge_status_t hxge_set_promisc(p_hxge_t hxgep, boolean_t on); 42 43 extern boolean_t hxge_jumbo_enable; 44 45 hxge_status_t 46 hxge_link_init(p_hxge_t hxgep) 47 { 48 p_hxge_stats_t statsp; 49 50 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_link_init>")); 51 52 statsp = hxgep->statsp; 53 54 statsp->mac_stats.cap_10gfdx = 1; 55 statsp->mac_stats.lp_cap_10gfdx = 1; 56 57 /* 58 * The driver doesn't control the link. 59 * It is always 10Gb full duplex. 60 */ 61 statsp->mac_stats.link_duplex = 2; 62 statsp->mac_stats.link_speed = 10000; 63 64 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_link_init")); 65 return (HXGE_OK); 66 } 67 68 hxge_status_t 69 hxge_vmac_init(p_hxge_t hxgep) 70 { 71 hxge_status_t status = HXGE_OK; 72 73 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_vmac_init:")); 74 75 if ((status = hxge_tx_vmac_reset(hxgep)) != HXGE_OK) 76 goto fail; 77 78 if ((status = hxge_rx_vmac_reset(hxgep)) != HXGE_OK) 79 goto fail; 80 81 if ((status = hxge_tx_vmac_enable(hxgep)) != HXGE_OK) 82 goto fail; 83 84 if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK) 85 goto fail; 86 87 /* Clear the interrupt status registers */ 88 (void) hpi_vmac_clear_rx_int_stat(hxgep->hpi_handle); 89 (void) hpi_vmac_clear_tx_int_stat(hxgep->hpi_handle); 90 91 /* 92 * Take the masks off the overflow counters. Interrupt the system when 93 * any counts overflow. Don't interrupt the system for each frame. 94 * The current counts are retrieved when the "kstat" command is used. 95 */ 96 (void) hpi_pfc_set_rx_int_stat_mask(hxgep->hpi_handle, 0, 1); 97 (void) hpi_pfc_set_tx_int_stat_mask(hxgep->hpi_handle, 0, 1); 98 99 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_vmac_init:")); 100 101 return (HXGE_OK); 102 fail: 103 HXGE_DEBUG_MSG((hxgep, MAC_CTL, 104 "hxge_vmac_init: failed to initialize VMAC>")); 105 106 return (status); 107 } 108 109 110 /* Initialize the TxVMAC sub-block */ 111 112 hxge_status_t 113 hxge_tx_vmac_init(p_hxge_t hxgep) 114 { 115 uint64_t config; 116 hpi_handle_t handle = hxgep->hpi_handle; 117 118 /* Set Max and Min Frame Size */ 119 120 hxgep->vmac.is_jumbo = B_FALSE; 121 if (hxge_jumbo_enable) 122 hxgep->vmac.is_jumbo = B_TRUE; 123 124 if (hxgep->param_arr[param_accept_jumbo].value || 125 hxgep->vmac.is_jumbo == B_TRUE) 126 hxgep->vmac.maxframesize = TX_JUMBO_MTU; 127 else 128 hxgep->vmac.maxframesize = STD_FRAME_SIZE + TX_PKT_HEADER_SIZE; 129 hxgep->vmac.minframesize = 64; 130 131 /* CFG_VMAC_TX_EN is done separately */ 132 config = CFG_VMAC_TX_CRC_INSERT | CFG_VMAC_TX_PAD; 133 134 if (hpi_vmac_tx_config(handle, INIT, config, 135 hxgep->vmac.maxframesize) != HPI_SUCCESS) 136 return (HXGE_ERROR); 137 138 hxgep->vmac.tx_config = config; 139 140 return (HXGE_OK); 141 } 142 143 /* Initialize the RxVMAC sub-block */ 144 145 hxge_status_t 146 hxge_rx_vmac_init(p_hxge_t hxgep) 147 { 148 uint64_t xconfig; 149 hpi_handle_t handle = hxgep->hpi_handle; 150 uint16_t max_frame_length = hxgep->vmac.maxframesize; 151 152 /* 153 * NOTE: CFG_VMAC_RX_ENABLE is done separately. Do not enable 154 * strip CRC. Bug ID 11451 -- enable strip CRC will cause 155 * rejection on minimum sized packets. 156 */ 157 xconfig = CFG_VMAC_RX_CRC_CHECK_DISABLE | 158 CFG_VMAC_RX_PASS_FLOW_CTRL_FR; 159 160 if (hxgep->filter.all_phys_cnt != 0) 161 xconfig |= CFG_VMAC_RX_PROMISCUOUS_MODE; 162 163 if (hxgep->filter.all_multicast_cnt != 0) 164 xconfig |= CFG_VMAC_RX_PROMIXCUOUS_GROUP; 165 166 if (hxgep->statsp->port_stats.lb_mode != hxge_lb_normal) 167 xconfig |= CFG_VMAC_RX_LOOP_BACK; 168 169 if (hpi_vmac_rx_config(handle, INIT, xconfig, max_frame_length) 170 != HPI_SUCCESS) 171 return (HXGE_ERROR); 172 173 hxgep->vmac.rx_config = xconfig; 174 175 return (HXGE_OK); 176 } 177 178 /* Enable TxVMAC */ 179 180 hxge_status_t 181 hxge_tx_vmac_enable(p_hxge_t hxgep) 182 { 183 hpi_status_t rv; 184 hxge_status_t status = HXGE_OK; 185 hpi_handle_t handle = hxgep->hpi_handle; 186 187 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_enable")); 188 189 rv = hxge_tx_vmac_init(hxgep); 190 if (rv != HXGE_OK) 191 return (rv); 192 193 /* Based on speed */ 194 hxgep->msg_min = ETHERMIN; 195 196 rv = hpi_vmac_tx_config(handle, ENABLE, CFG_VMAC_TX_EN, 0); 197 198 status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; 199 200 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_enable")); 201 202 return (status); 203 } 204 205 /* Disable TxVMAC */ 206 207 hxge_status_t 208 hxge_tx_vmac_disable(p_hxge_t hxgep) 209 { 210 hpi_status_t rv; 211 hxge_status_t status = HXGE_OK; 212 hpi_handle_t handle = hxgep->hpi_handle; 213 214 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_tx_vmac_disable")); 215 216 rv = hpi_vmac_tx_config(handle, DISABLE, CFG_VMAC_TX_EN, 0); 217 218 status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; 219 220 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_tx_vmac_disable")); 221 222 return (status); 223 } 224 225 /* Enable RxVMAC */ 226 227 hxge_status_t 228 hxge_rx_vmac_enable(p_hxge_t hxgep) 229 { 230 hpi_status_t rv; 231 hxge_status_t status = HXGE_OK; 232 hpi_handle_t handle = hxgep->hpi_handle; 233 234 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_enable")); 235 236 rv = hxge_rx_vmac_init(hxgep); 237 if (rv != HXGE_OK) 238 return (rv); 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 246 return (status); 247 } 248 249 /* Disable RxVMAC */ 250 251 hxge_status_t 252 hxge_rx_vmac_disable(p_hxge_t hxgep) 253 { 254 hpi_status_t rv; 255 hxge_status_t status = HXGE_OK; 256 hpi_handle_t handle = hxgep->hpi_handle; 257 258 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_disable")); 259 260 rv = hpi_vmac_rx_config(handle, DISABLE, CFG_VMAC_RX_EN, 0); 261 262 status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; 263 264 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_disable")); 265 266 return (status); 267 } 268 269 /* Reset TxVMAC */ 270 271 hxge_status_t 272 hxge_tx_vmac_reset(p_hxge_t hxgep) 273 { 274 hpi_handle_t handle = hxgep->hpi_handle; 275 276 (void) hpi_tx_vmac_reset(handle); 277 278 return (HXGE_OK); 279 } 280 281 /* Reset RxVMAC */ 282 283 hxge_status_t 284 hxge_rx_vmac_reset(p_hxge_t hxgep) 285 { 286 hpi_handle_t handle = hxgep->hpi_handle; 287 288 (void) hpi_rx_vmac_reset(handle); 289 290 return (HXGE_OK); 291 } 292 293 /*ARGSUSED*/ 294 uint_t 295 hxge_vmac_intr(caddr_t arg1, caddr_t arg2) 296 { 297 p_hxge_t hxgep = (p_hxge_t)arg2; 298 hpi_handle_t handle; 299 300 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_vmac_intr")); 301 302 handle = HXGE_DEV_HPI_HANDLE(hxgep); 303 304 hxge_save_cntrs(hxgep); 305 306 /* Clear the interrupt status registers */ 307 (void) hpi_vmac_clear_rx_int_stat(handle); 308 (void) hpi_vmac_clear_tx_int_stat(handle); 309 310 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_vmac_intr")); 311 return (DDI_INTR_CLAIMED); 312 } 313 314 /* 315 * Set promiscous mode 316 */ 317 hxge_status_t 318 hxge_set_promisc(p_hxge_t hxgep, boolean_t on) 319 { 320 hxge_status_t status = HXGE_OK; 321 322 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_set_promisc: on %d", on)); 323 324 hxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 325 326 RW_ENTER_WRITER(&hxgep->filter_lock); 327 if ((status = hxge_rx_vmac_disable(hxgep)) != HXGE_OK) 328 goto fail; 329 if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK) 330 goto fail; 331 RW_EXIT(&hxgep->filter_lock); 332 333 if (on) 334 hxgep->statsp->mac_stats.promisc = B_TRUE; 335 else 336 hxgep->statsp->mac_stats.promisc = B_FALSE; 337 338 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_set_promisc")); 339 return (HXGE_OK); 340 341 fail: 342 RW_EXIT(&hxgep->filter_lock); 343 344 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_promisc: " 345 "Unable to set promisc (%d)", on)); 346 return (status); 347 } 348 349 void 350 hxge_save_cntrs(p_hxge_t hxgep) 351 { 352 p_hxge_stats_t statsp; 353 hpi_handle_t handle; 354 355 vmac_tx_frame_cnt_t tx_frame_cnt; 356 vmac_tx_byte_cnt_t tx_byte_cnt; 357 vmac_rx_frame_cnt_t rx_frame_cnt; 358 vmac_rx_byte_cnt_t rx_byte_cnt; 359 vmac_rx_drop_fr_cnt_t rx_drop_fr_cnt; 360 vmac_rx_drop_byte_cnt_t rx_drop_byte_cnt; 361 vmac_rx_crc_cnt_t rx_crc_cnt; 362 vmac_rx_pause_cnt_t rx_pause_cnt; 363 vmac_rx_bcast_fr_cnt_t rx_bcast_fr_cnt; 364 vmac_rx_mcast_fr_cnt_t rx_mcast_fr_cnt; 365 366 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_save_cntrs")); 367 368 statsp = (p_hxge_stats_t)hxgep->statsp; 369 handle = hxgep->hpi_handle; 370 371 HXGE_REG_RD64(handle, VMAC_TX_FRAME_CNT, &tx_frame_cnt.value); 372 HXGE_REG_RD64(handle, VMAC_TX_BYTE_CNT, &tx_byte_cnt.value); 373 HXGE_REG_RD64(handle, VMAC_RX_FRAME_CNT, &rx_frame_cnt.value); 374 HXGE_REG_RD64(handle, VMAC_RX_BYTE_CNT, &rx_byte_cnt.value); 375 HXGE_REG_RD64(handle, VMAC_RX_DROP_FR_CNT, &rx_drop_fr_cnt.value); 376 HXGE_REG_RD64(handle, VMAC_RX_DROP_BYTE_CNT, &rx_drop_byte_cnt.value); 377 HXGE_REG_RD64(handle, VMAC_RX_CRC_CNT, &rx_crc_cnt.value); 378 HXGE_REG_RD64(handle, VMAC_RX_PAUSE_CNT, &rx_pause_cnt.value); 379 HXGE_REG_RD64(handle, VMAC_RX_BCAST_FR_CNT, &rx_bcast_fr_cnt.value); 380 HXGE_REG_RD64(handle, VMAC_RX_MCAST_FR_CNT, &rx_mcast_fr_cnt.value); 381 382 statsp->vmac_stats.tx_frame_cnt += tx_frame_cnt.bits.tx_frame_cnt; 383 statsp->vmac_stats.tx_byte_cnt += tx_byte_cnt.bits.tx_byte_cnt; 384 statsp->vmac_stats.rx_frame_cnt += rx_frame_cnt.bits.rx_frame_cnt; 385 statsp->vmac_stats.rx_byte_cnt += rx_byte_cnt.bits.rx_byte_cnt; 386 statsp->vmac_stats.rx_drop_frame_cnt += 387 rx_drop_fr_cnt.bits.rx_drop_frame_cnt; 388 statsp->vmac_stats.rx_drop_byte_cnt += 389 rx_drop_byte_cnt.bits.rx_drop_byte_cnt; 390 statsp->vmac_stats.rx_crc_cnt += rx_crc_cnt.bits.rx_crc_cnt; 391 statsp->vmac_stats.rx_pause_cnt += rx_pause_cnt.bits.rx_pause_cnt; 392 statsp->vmac_stats.rx_bcast_fr_cnt += 393 rx_bcast_fr_cnt.bits.rx_bcast_fr_cnt; 394 statsp->vmac_stats.rx_mcast_fr_cnt += 395 rx_mcast_fr_cnt.bits.rx_mcast_fr_cnt; 396 397 hxge_save_cntrs_exit: 398 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_save_cntrs")); 399 } 400