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