1 /***********************license start*************** 2 * Author: Cavium Networks 3 * 4 * Contact: support@caviumnetworks.com 5 * This file is part of the OCTEON SDK 6 * 7 * Copyright (c) 2003-2008 Cavium Networks 8 * 9 * This file is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License, Version 2, as 11 * published by the Free Software Foundation. 12 * 13 * This file is distributed in the hope that it will be useful, but 14 * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16 * NONINFRINGEMENT. See the GNU General Public License for more 17 * details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this file; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 22 * or visit http://www.gnu.org/licenses/. 23 * 24 * This file may also be available under a different license from Cavium. 25 * Contact Cavium Networks for more information 26 ***********************license end**************************************/ 27 28 /* 29 * Interface to the hardware Packet Input Processing unit. 30 * 31 */ 32 33 #ifndef __CVMX_PIP_H__ 34 #define __CVMX_PIP_H__ 35 36 #include <asm/octeon/cvmx-wqe.h> 37 #include <asm/octeon/cvmx-fpa.h> 38 #include <asm/octeon/cvmx-pip-defs.h> 39 40 #define CVMX_PIP_NUM_INPUT_PORTS 48 41 #define CVMX_PIP_NUM_WATCHERS 4 42 43 /* 44 * Encodes the different error and exception codes 45 */ 46 typedef enum { 47 CVMX_PIP_L4_NO_ERR = 0ull, 48 /* 49 * 1 = TCP (UDP) packet not long enough to cover TCP (UDP) 50 * header 51 */ 52 CVMX_PIP_L4_MAL_ERR = 1ull, 53 /* 2 = TCP/UDP checksum failure */ 54 CVMX_PIP_CHK_ERR = 2ull, 55 /* 56 * 3 = TCP/UDP length check (TCP/UDP length does not match IP 57 * length). 58 */ 59 CVMX_PIP_L4_LENGTH_ERR = 3ull, 60 /* 4 = illegal TCP/UDP port (either source or dest port is zero) */ 61 CVMX_PIP_BAD_PRT_ERR = 4ull, 62 /* 8 = TCP flags = FIN only */ 63 CVMX_PIP_TCP_FLG8_ERR = 8ull, 64 /* 9 = TCP flags = 0 */ 65 CVMX_PIP_TCP_FLG9_ERR = 9ull, 66 /* 10 = TCP flags = FIN+RST+* */ 67 CVMX_PIP_TCP_FLG10_ERR = 10ull, 68 /* 11 = TCP flags = SYN+URG+* */ 69 CVMX_PIP_TCP_FLG11_ERR = 11ull, 70 /* 12 = TCP flags = SYN+RST+* */ 71 CVMX_PIP_TCP_FLG12_ERR = 12ull, 72 /* 13 = TCP flags = SYN+FIN+* */ 73 CVMX_PIP_TCP_FLG13_ERR = 13ull 74 } cvmx_pip_l4_err_t; 75 76 typedef enum { 77 78 CVMX_PIP_IP_NO_ERR = 0ull, 79 /* 1 = not IPv4 or IPv6 */ 80 CVMX_PIP_NOT_IP = 1ull, 81 /* 2 = IPv4 header checksum violation */ 82 CVMX_PIP_IPV4_HDR_CHK = 2ull, 83 /* 3 = malformed (packet not long enough to cover IP hdr) */ 84 CVMX_PIP_IP_MAL_HDR = 3ull, 85 /* 4 = malformed (packet not long enough to cover len in IP hdr) */ 86 CVMX_PIP_IP_MAL_PKT = 4ull, 87 /* 5 = TTL / hop count equal zero */ 88 CVMX_PIP_TTL_HOP = 5ull, 89 /* 6 = IPv4 options / IPv6 early extension headers */ 90 CVMX_PIP_OPTS = 6ull 91 } cvmx_pip_ip_exc_t; 92 93 /** 94 * NOTES 95 * late collision (data received before collision) 96 * late collisions cannot be detected by the receiver 97 * they would appear as JAM bits which would appear as bad FCS 98 * or carrier extend error which is CVMX_PIP_EXTEND_ERR 99 */ 100 typedef enum { 101 /* No error */ 102 CVMX_PIP_RX_NO_ERR = 0ull, 103 /* RGM+SPI 1 = partially received packet (buffering/bandwidth 104 * not adequate) */ 105 CVMX_PIP_PARTIAL_ERR = 1ull, 106 /* RGM+SPI 2 = receive packet too large and truncated */ 107 CVMX_PIP_JABBER_ERR = 2ull, 108 /* 109 * RGM 3 = max frame error (pkt len > max frame len) (with FCS 110 * error) 111 */ 112 CVMX_PIP_OVER_FCS_ERR = 3ull, 113 /* RGM+SPI 4 = max frame error (pkt len > max frame len) */ 114 CVMX_PIP_OVER_ERR = 4ull, 115 /* 116 * RGM 5 = nibble error (data not byte multiple - 100M and 10M 117 * only) 118 */ 119 CVMX_PIP_ALIGN_ERR = 5ull, 120 /* 121 * RGM 6 = min frame error (pkt len < min frame len) (with FCS 122 * error) 123 */ 124 CVMX_PIP_UNDER_FCS_ERR = 6ull, 125 /* RGM 7 = FCS error */ 126 CVMX_PIP_GMX_FCS_ERR = 7ull, 127 /* RGM+SPI 8 = min frame error (pkt len < min frame len) */ 128 CVMX_PIP_UNDER_ERR = 8ull, 129 /* RGM 9 = Frame carrier extend error */ 130 CVMX_PIP_EXTEND_ERR = 9ull, 131 /* 132 * RGM 10 = length mismatch (len did not match len in L2 133 * length/type) 134 */ 135 CVMX_PIP_LENGTH_ERR = 10ull, 136 /* RGM 11 = Frame error (some or all data bits marked err) */ 137 CVMX_PIP_DAT_ERR = 11ull, 138 /* SPI 11 = DIP4 error */ 139 CVMX_PIP_DIP_ERR = 11ull, 140 /* 141 * RGM 12 = packet was not large enough to pass the skipper - 142 * no inspection could occur. 143 */ 144 CVMX_PIP_SKIP_ERR = 12ull, 145 /* 146 * RGM 13 = studder error (data not repeated - 100M and 10M 147 * only) 148 */ 149 CVMX_PIP_NIBBLE_ERR = 13ull, 150 /* RGM+SPI 16 = FCS error */ 151 CVMX_PIP_PIP_FCS = 16L, 152 /* 153 * RGM+SPI+PCI 17 = packet was not large enough to pass the 154 * skipper - no inspection could occur. 155 */ 156 CVMX_PIP_PIP_SKIP_ERR = 17L, 157 /* 158 * RGM+SPI+PCI 18 = malformed l2 (packet not long enough to 159 * cover L2 hdr). 160 */ 161 CVMX_PIP_PIP_L2_MAL_HDR = 18L 162 /* 163 * NOTES: xx = late collision (data received before collision) 164 * late collisions cannot be detected by the receiver 165 * they would appear as JAM bits which would appear as 166 * bad FCS or carrier extend error which is 167 * CVMX_PIP_EXTEND_ERR 168 */ 169 } cvmx_pip_rcv_err_t; 170 171 /** 172 * This defines the err_code field errors in the work Q entry 173 */ 174 typedef union { 175 cvmx_pip_l4_err_t l4_err; 176 cvmx_pip_ip_exc_t ip_exc; 177 cvmx_pip_rcv_err_t rcv_err; 178 } cvmx_pip_err_t; 179 180 /** 181 * Status statistics for a port 182 */ 183 typedef struct { 184 /* Inbound octets marked to be dropped by the IPD */ 185 uint32_t dropped_octets; 186 /* Inbound packets marked to be dropped by the IPD */ 187 uint32_t dropped_packets; 188 /* RAW PCI Packets received by PIP per port */ 189 uint32_t pci_raw_packets; 190 /* Number of octets processed by PIP */ 191 uint32_t octets; 192 /* Number of packets processed by PIP */ 193 uint32_t packets; 194 /* 195 * Number of identified L2 multicast packets. Does not 196 * include broadcast packets. Only includes packets whose 197 * parse mode is SKIP_TO_L2 198 */ 199 uint32_t multicast_packets; 200 /* 201 * Number of identified L2 broadcast packets. Does not 202 * include multicast packets. Only includes packets whose 203 * parse mode is SKIP_TO_L2 204 */ 205 uint32_t broadcast_packets; 206 /* Number of 64B packets */ 207 uint32_t len_64_packets; 208 /* Number of 65-127B packets */ 209 uint32_t len_65_127_packets; 210 /* Number of 128-255B packets */ 211 uint32_t len_128_255_packets; 212 /* Number of 256-511B packets */ 213 uint32_t len_256_511_packets; 214 /* Number of 512-1023B packets */ 215 uint32_t len_512_1023_packets; 216 /* Number of 1024-1518B packets */ 217 uint32_t len_1024_1518_packets; 218 /* Number of 1519-max packets */ 219 uint32_t len_1519_max_packets; 220 /* Number of packets with FCS or Align opcode errors */ 221 uint32_t fcs_align_err_packets; 222 /* Number of packets with length < min */ 223 uint32_t runt_packets; 224 /* Number of packets with length < min and FCS error */ 225 uint32_t runt_crc_packets; 226 /* Number of packets with length > max */ 227 uint32_t oversize_packets; 228 /* Number of packets with length > max and FCS error */ 229 uint32_t oversize_crc_packets; 230 /* Number of packets without GMX/SPX/PCI errors received by PIP */ 231 uint32_t inb_packets; 232 /* 233 * Total number of octets from all packets received by PIP, 234 * including CRC 235 */ 236 uint64_t inb_octets; 237 /* Number of packets with GMX/SPX/PCI errors received by PIP */ 238 uint16_t inb_errors; 239 } cvmx_pip_port_status_t; 240 241 /** 242 * Definition of the PIP custom header that can be prepended 243 * to a packet by external hardware. 244 */ 245 typedef union { 246 uint64_t u64; 247 struct { 248 /* 249 * Documented as R - Set if the Packet is RAWFULL. If 250 * set, this header must be the full 8 bytes. 251 */ 252 uint64_t rawfull:1; 253 /* Must be zero */ 254 uint64_t reserved0:5; 255 /* PIP parse mode for this packet */ 256 uint64_t parse_mode:2; 257 /* Must be zero */ 258 uint64_t reserved1:1; 259 /* 260 * Skip amount, including this header, to the 261 * beginning of the packet 262 */ 263 uint64_t skip_len:7; 264 /* Must be zero */ 265 uint64_t reserved2:6; 266 /* POW input queue for this packet */ 267 uint64_t qos:3; 268 /* POW input group for this packet */ 269 uint64_t grp:4; 270 /* 271 * Flag to store this packet in the work queue entry, 272 * if possible 273 */ 274 uint64_t rs:1; 275 /* POW input tag type */ 276 uint64_t tag_type:2; 277 /* POW input tag */ 278 uint64_t tag:32; 279 } s; 280 } cvmx_pip_pkt_inst_hdr_t; 281 282 /* CSR typedefs have been moved to cvmx-csr-*.h */ 283 284 /** 285 * Configure an ethernet input port 286 * 287 * @port_num: Port number to configure 288 * @port_cfg: Port hardware configuration 289 * @port_tag_cfg: 290 * Port POW tagging configuration 291 */ 292 static inline void cvmx_pip_config_port(uint64_t port_num, 293 union cvmx_pip_prt_cfgx port_cfg, 294 union cvmx_pip_prt_tagx port_tag_cfg) 295 { 296 cvmx_write_csr(CVMX_PIP_PRT_CFGX(port_num), port_cfg.u64); 297 cvmx_write_csr(CVMX_PIP_PRT_TAGX(port_num), port_tag_cfg.u64); 298 } 299 #if 0 300 /** 301 * @deprecated This function is a thin wrapper around the Pass1 version 302 * of the CVMX_PIP_QOS_WATCHX CSR; Pass2 has added a field for 303 * setting the group that is incompatible with this function, 304 * the preferred upgrade path is to use the CSR directly. 305 * 306 * Configure the global QoS packet watchers. Each watcher is 307 * capable of matching a field in a packet to determine the 308 * QoS queue for scheduling. 309 * 310 * @watcher: Watcher number to configure (0 - 3). 311 * @match_type: Watcher match type 312 * @match_value: 313 * Value the watcher will match against 314 * @qos: QoS queue for packets matching this watcher 315 */ 316 static inline void cvmx_pip_config_watcher(uint64_t watcher, 317 cvmx_pip_qos_watch_types match_type, 318 uint64_t match_value, uint64_t qos) 319 { 320 cvmx_pip_port_watcher_cfg_t watcher_config; 321 322 watcher_config.u64 = 0; 323 watcher_config.s.match_type = match_type; 324 watcher_config.s.match_value = match_value; 325 watcher_config.s.qos = qos; 326 327 cvmx_write_csr(CVMX_PIP_QOS_WATCHX(watcher), watcher_config.u64); 328 } 329 #endif 330 /** 331 * Configure the VLAN priority to QoS queue mapping. 332 * 333 * @vlan_priority: 334 * VLAN priority (0-7) 335 * @qos: QoS queue for packets matching this watcher 336 */ 337 static inline void cvmx_pip_config_vlan_qos(uint64_t vlan_priority, 338 uint64_t qos) 339 { 340 union cvmx_pip_qos_vlanx pip_qos_vlanx; 341 pip_qos_vlanx.u64 = 0; 342 pip_qos_vlanx.s.qos = qos; 343 cvmx_write_csr(CVMX_PIP_QOS_VLANX(vlan_priority), pip_qos_vlanx.u64); 344 } 345 346 /** 347 * Configure the Diffserv to QoS queue mapping. 348 * 349 * @diffserv: Diffserv field value (0-63) 350 * @qos: QoS queue for packets matching this watcher 351 */ 352 static inline void cvmx_pip_config_diffserv_qos(uint64_t diffserv, uint64_t qos) 353 { 354 union cvmx_pip_qos_diffx pip_qos_diffx; 355 pip_qos_diffx.u64 = 0; 356 pip_qos_diffx.s.qos = qos; 357 cvmx_write_csr(CVMX_PIP_QOS_DIFFX(diffserv), pip_qos_diffx.u64); 358 } 359 360 /** 361 * Get the status counters for a port. 362 * 363 * @port_num: Port number to get statistics for. 364 * @clear: Set to 1 to clear the counters after they are read 365 * @status: Where to put the results. 366 */ 367 static inline void cvmx_pip_get_port_status(uint64_t port_num, uint64_t clear, 368 cvmx_pip_port_status_t *status) 369 { 370 union cvmx_pip_stat_ctl pip_stat_ctl; 371 union cvmx_pip_stat0_prtx stat0; 372 union cvmx_pip_stat1_prtx stat1; 373 union cvmx_pip_stat2_prtx stat2; 374 union cvmx_pip_stat3_prtx stat3; 375 union cvmx_pip_stat4_prtx stat4; 376 union cvmx_pip_stat5_prtx stat5; 377 union cvmx_pip_stat6_prtx stat6; 378 union cvmx_pip_stat7_prtx stat7; 379 union cvmx_pip_stat8_prtx stat8; 380 union cvmx_pip_stat9_prtx stat9; 381 union cvmx_pip_stat_inb_pktsx pip_stat_inb_pktsx; 382 union cvmx_pip_stat_inb_octsx pip_stat_inb_octsx; 383 union cvmx_pip_stat_inb_errsx pip_stat_inb_errsx; 384 385 pip_stat_ctl.u64 = 0; 386 pip_stat_ctl.s.rdclr = clear; 387 cvmx_write_csr(CVMX_PIP_STAT_CTL, pip_stat_ctl.u64); 388 389 stat0.u64 = cvmx_read_csr(CVMX_PIP_STAT0_PRTX(port_num)); 390 stat1.u64 = cvmx_read_csr(CVMX_PIP_STAT1_PRTX(port_num)); 391 stat2.u64 = cvmx_read_csr(CVMX_PIP_STAT2_PRTX(port_num)); 392 stat3.u64 = cvmx_read_csr(CVMX_PIP_STAT3_PRTX(port_num)); 393 stat4.u64 = cvmx_read_csr(CVMX_PIP_STAT4_PRTX(port_num)); 394 stat5.u64 = cvmx_read_csr(CVMX_PIP_STAT5_PRTX(port_num)); 395 stat6.u64 = cvmx_read_csr(CVMX_PIP_STAT6_PRTX(port_num)); 396 stat7.u64 = cvmx_read_csr(CVMX_PIP_STAT7_PRTX(port_num)); 397 stat8.u64 = cvmx_read_csr(CVMX_PIP_STAT8_PRTX(port_num)); 398 stat9.u64 = cvmx_read_csr(CVMX_PIP_STAT9_PRTX(port_num)); 399 pip_stat_inb_pktsx.u64 = 400 cvmx_read_csr(CVMX_PIP_STAT_INB_PKTSX(port_num)); 401 pip_stat_inb_octsx.u64 = 402 cvmx_read_csr(CVMX_PIP_STAT_INB_OCTSX(port_num)); 403 pip_stat_inb_errsx.u64 = 404 cvmx_read_csr(CVMX_PIP_STAT_INB_ERRSX(port_num)); 405 406 status->dropped_octets = stat0.s.drp_octs; 407 status->dropped_packets = stat0.s.drp_pkts; 408 status->octets = stat1.s.octs; 409 status->pci_raw_packets = stat2.s.raw; 410 status->packets = stat2.s.pkts; 411 status->multicast_packets = stat3.s.mcst; 412 status->broadcast_packets = stat3.s.bcst; 413 status->len_64_packets = stat4.s.h64; 414 status->len_65_127_packets = stat4.s.h65to127; 415 status->len_128_255_packets = stat5.s.h128to255; 416 status->len_256_511_packets = stat5.s.h256to511; 417 status->len_512_1023_packets = stat6.s.h512to1023; 418 status->len_1024_1518_packets = stat6.s.h1024to1518; 419 status->len_1519_max_packets = stat7.s.h1519; 420 status->fcs_align_err_packets = stat7.s.fcs; 421 status->runt_packets = stat8.s.undersz; 422 status->runt_crc_packets = stat8.s.frag; 423 status->oversize_packets = stat9.s.oversz; 424 status->oversize_crc_packets = stat9.s.jabber; 425 status->inb_packets = pip_stat_inb_pktsx.s.pkts; 426 status->inb_octets = pip_stat_inb_octsx.s.octs; 427 status->inb_errors = pip_stat_inb_errsx.s.errs; 428 429 if (cvmx_octeon_is_pass1()) { 430 /* 431 * Kludge to fix Octeon Pass 1 errata - Drop counts 432 * don't work. 433 */ 434 if (status->inb_packets > status->packets) 435 status->dropped_packets = 436 status->inb_packets - status->packets; 437 else 438 status->dropped_packets = 0; 439 if (status->inb_octets - status->inb_packets * 4 > 440 status->octets) 441 status->dropped_octets = 442 status->inb_octets - status->inb_packets * 4 - 443 status->octets; 444 else 445 status->dropped_octets = 0; 446 } 447 } 448 449 /** 450 * Configure the hardware CRC engine 451 * 452 * @interface: Interface to configure (0 or 1) 453 * @invert_result: 454 * Invert the result of the CRC 455 * @reflect: Reflect 456 * @initialization_vector: 457 * CRC initialization vector 458 */ 459 static inline void cvmx_pip_config_crc(uint64_t interface, 460 uint64_t invert_result, uint64_t reflect, 461 uint32_t initialization_vector) 462 { 463 if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN58XX)) { 464 union cvmx_pip_crc_ctlx config; 465 union cvmx_pip_crc_ivx pip_crc_ivx; 466 467 config.u64 = 0; 468 config.s.invres = invert_result; 469 config.s.reflect = reflect; 470 cvmx_write_csr(CVMX_PIP_CRC_CTLX(interface), config.u64); 471 472 pip_crc_ivx.u64 = 0; 473 pip_crc_ivx.s.iv = initialization_vector; 474 cvmx_write_csr(CVMX_PIP_CRC_IVX(interface), pip_crc_ivx.u64); 475 } 476 } 477 478 /** 479 * Clear all bits in a tag mask. This should be called on 480 * startup before any calls to cvmx_pip_tag_mask_set. Each bit 481 * set in the final mask represent a byte used in the packet for 482 * tag generation. 483 * 484 * @mask_index: Which tag mask to clear (0..3) 485 */ 486 static inline void cvmx_pip_tag_mask_clear(uint64_t mask_index) 487 { 488 uint64_t index; 489 union cvmx_pip_tag_incx pip_tag_incx; 490 pip_tag_incx.u64 = 0; 491 pip_tag_incx.s.en = 0; 492 for (index = mask_index * 16; index < (mask_index + 1) * 16; index++) 493 cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64); 494 } 495 496 /** 497 * Sets a range of bits in the tag mask. The tag mask is used 498 * when the cvmx_pip_port_tag_cfg_t tag_mode is non zero. 499 * There are four separate masks that can be configured. 500 * 501 * @mask_index: Which tag mask to modify (0..3) 502 * @offset: Offset into the bitmask to set bits at. Use the GCC macro 503 * offsetof() to determine the offsets into packet headers. 504 * For example, offsetof(ethhdr, protocol) returns the offset 505 * of the ethernet protocol field. The bitmask selects which 506 * bytes to include the the tag, with bit offset X selecting 507 * byte at offset X from the beginning of the packet data. 508 * @len: Number of bytes to include. Usually this is the sizeof() 509 * the field. 510 */ 511 static inline void cvmx_pip_tag_mask_set(uint64_t mask_index, uint64_t offset, 512 uint64_t len) 513 { 514 while (len--) { 515 union cvmx_pip_tag_incx pip_tag_incx; 516 uint64_t index = mask_index * 16 + offset / 8; 517 pip_tag_incx.u64 = cvmx_read_csr(CVMX_PIP_TAG_INCX(index)); 518 pip_tag_incx.s.en |= 0x80 >> (offset & 0x7); 519 cvmx_write_csr(CVMX_PIP_TAG_INCX(index), pip_tag_incx.u64); 520 offset++; 521 } 522 } 523 524 #endif /* __CVMX_PIP_H__ */ 525