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