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_CRC_CHECK_DISABLE | 141 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, max_frame_length) 153 != 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 rv = hxge_rx_vmac_init(hxgep); 220 if (rv != HXGE_OK) 221 return (rv); 222 223 rv = hpi_vmac_rx_config(handle, ENABLE, CFG_VMAC_RX_EN, 0); 224 225 status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; 226 227 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_enable")); 228 229 return (status); 230 } 231 232 /* Disable RxVMAC */ 233 234 hxge_status_t 235 hxge_rx_vmac_disable(p_hxge_t hxgep) 236 { 237 hpi_status_t rv; 238 hxge_status_t status = HXGE_OK; 239 hpi_handle_t handle = hxgep->hpi_handle; 240 241 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_rx_vmac_disable")); 242 243 rv = hpi_vmac_rx_config(handle, DISABLE, CFG_VMAC_RX_EN, 0); 244 245 status = (rv == HPI_SUCCESS) ? HXGE_OK : HXGE_ERROR; 246 247 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_rx_vmac_disable")); 248 249 return (status); 250 } 251 252 /* Reset TxVMAC */ 253 254 hxge_status_t 255 hxge_tx_vmac_reset(p_hxge_t hxgep) 256 { 257 hpi_handle_t handle = hxgep->hpi_handle; 258 259 (void) hpi_tx_vmac_reset(handle); 260 261 return (HXGE_OK); 262 } 263 264 /* Reset RxVMAC */ 265 266 hxge_status_t 267 hxge_rx_vmac_reset(p_hxge_t hxgep) 268 { 269 hpi_handle_t handle = hxgep->hpi_handle; 270 271 (void) hpi_rx_vmac_reset(handle); 272 273 return (HXGE_OK); 274 } 275 276 /*ARGSUSED*/ 277 uint_t 278 hxge_vmac_intr(caddr_t arg1, caddr_t arg2) 279 { 280 p_hxge_t hxgep = (p_hxge_t)arg2; 281 hpi_handle_t handle; 282 283 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_vmac_intr")); 284 285 handle = HXGE_DEV_HPI_HANDLE(hxgep); 286 287 hxge_save_cntrs(hxgep); 288 289 /* Clear the interrupt status registers */ 290 (void) hpi_vmac_clear_rx_int_stat(handle); 291 (void) hpi_vmac_clear_tx_int_stat(handle); 292 293 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_vmac_intr")); 294 return (DDI_INTR_CLAIMED); 295 } 296 297 /* 298 * Set promiscous mode 299 */ 300 hxge_status_t 301 hxge_set_promisc(p_hxge_t hxgep, boolean_t on) 302 { 303 hxge_status_t status = HXGE_OK; 304 305 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_set_promisc: on %d", on)); 306 307 hxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 308 309 RW_ENTER_WRITER(&hxgep->filter_lock); 310 if ((status = hxge_rx_vmac_disable(hxgep)) != HXGE_OK) 311 goto fail; 312 if ((status = hxge_rx_vmac_enable(hxgep)) != HXGE_OK) 313 goto fail; 314 RW_EXIT(&hxgep->filter_lock); 315 316 if (on) 317 hxgep->statsp->mac_stats.promisc = B_TRUE; 318 else 319 hxgep->statsp->mac_stats.promisc = B_FALSE; 320 321 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_set_promisc")); 322 return (HXGE_OK); 323 324 fail: 325 RW_EXIT(&hxgep->filter_lock); 326 327 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_set_promisc: " 328 "Unable to set promisc (%d)", on)); 329 return (status); 330 } 331 332 void 333 hxge_save_cntrs(p_hxge_t hxgep) 334 { 335 p_hxge_stats_t statsp; 336 hpi_handle_t handle; 337 338 vmac_tx_frame_cnt_t tx_frame_cnt; 339 vmac_tx_byte_cnt_t tx_byte_cnt; 340 vmac_rx_frame_cnt_t rx_frame_cnt; 341 vmac_rx_byte_cnt_t rx_byte_cnt; 342 vmac_rx_drop_fr_cnt_t rx_drop_fr_cnt; 343 vmac_rx_drop_byte_cnt_t rx_drop_byte_cnt; 344 vmac_rx_crc_cnt_t rx_crc_cnt; 345 vmac_rx_pause_cnt_t rx_pause_cnt; 346 vmac_rx_bcast_fr_cnt_t rx_bcast_fr_cnt; 347 vmac_rx_mcast_fr_cnt_t rx_mcast_fr_cnt; 348 349 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_save_cntrs")); 350 351 statsp = (p_hxge_stats_t)hxgep->statsp; 352 handle = hxgep->hpi_handle; 353 354 HXGE_REG_RD64(handle, VMAC_TX_FRAME_CNT, &tx_frame_cnt.value); 355 HXGE_REG_RD64(handle, VMAC_TX_BYTE_CNT, &tx_byte_cnt.value); 356 HXGE_REG_RD64(handle, VMAC_RX_FRAME_CNT, &rx_frame_cnt.value); 357 HXGE_REG_RD64(handle, VMAC_RX_BYTE_CNT, &rx_byte_cnt.value); 358 HXGE_REG_RD64(handle, VMAC_RX_DROP_FR_CNT, &rx_drop_fr_cnt.value); 359 HXGE_REG_RD64(handle, VMAC_RX_DROP_BYTE_CNT, &rx_drop_byte_cnt.value); 360 HXGE_REG_RD64(handle, VMAC_RX_CRC_CNT, &rx_crc_cnt.value); 361 HXGE_REG_RD64(handle, VMAC_RX_PAUSE_CNT, &rx_pause_cnt.value); 362 HXGE_REG_RD64(handle, VMAC_RX_BCAST_FR_CNT, &rx_bcast_fr_cnt.value); 363 HXGE_REG_RD64(handle, VMAC_RX_MCAST_FR_CNT, &rx_mcast_fr_cnt.value); 364 365 statsp->vmac_stats.tx_frame_cnt += tx_frame_cnt.bits.tx_frame_cnt; 366 statsp->vmac_stats.tx_byte_cnt += tx_byte_cnt.bits.tx_byte_cnt; 367 statsp->vmac_stats.rx_frame_cnt += rx_frame_cnt.bits.rx_frame_cnt; 368 statsp->vmac_stats.rx_byte_cnt += rx_byte_cnt.bits.rx_byte_cnt; 369 statsp->vmac_stats.rx_drop_frame_cnt += 370 rx_drop_fr_cnt.bits.rx_drop_frame_cnt; 371 statsp->vmac_stats.rx_drop_byte_cnt += 372 rx_drop_byte_cnt.bits.rx_drop_byte_cnt; 373 statsp->vmac_stats.rx_crc_cnt += rx_crc_cnt.bits.rx_crc_cnt; 374 statsp->vmac_stats.rx_pause_cnt += rx_pause_cnt.bits.rx_pause_cnt; 375 statsp->vmac_stats.rx_bcast_fr_cnt += 376 rx_bcast_fr_cnt.bits.rx_bcast_fr_cnt; 377 statsp->vmac_stats.rx_mcast_fr_cnt += 378 rx_mcast_fr_cnt.bits.rx_mcast_fr_cnt; 379 380 hxge_save_cntrs_exit: 381 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_save_cntrs")); 382 } 383 384 int 385 hxge_vmac_set_framesize(p_hxge_t hxgep) 386 { 387 int status = 0; 388 389 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "==> hxge_vmac_set_framesize")); 390 391 RW_ENTER_WRITER(&hxgep->filter_lock); 392 (void) hxge_rx_vmac_disable(hxgep); 393 (void) hxge_tx_vmac_disable(hxgep); 394 395 /* 396 * Apply the new jumbo parameter here which is contained in hxgep 397 * data structure (hxgep->vmac.maxframesize); 398 * The order of the following two calls is important. 399 */ 400 (void) hxge_tx_vmac_enable(hxgep); 401 (void) hxge_rx_vmac_enable(hxgep); 402 RW_EXIT(&hxgep->filter_lock); 403 404 HXGE_DEBUG_MSG((hxgep, NDD_CTL, "<== hxge_vmac_set_framesize")); 405 return (status); 406 } 407