hxge_pfc.c revision fe930412c257f961ae67039de3b164b83717976a
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <hxge_impl.h>
#include <hxge_classify.h>
#include <hxge_pfc.h>
#include <hpi_pfc.h>
#include <sys/ethernet.h>
/*
* Ethernet broadcast address definition.
*/
static ether_addr_st etherbroadcastaddr = {\
0xff, 0xff, 0xff, 0xff, 0xff, 0xff \
};
struct ether_addr *);
{
return (status);
(void) hxge_classify_exit_sw(hxgep);
return (status);
}
return (HXGE_OK);
}
{
return (hxge_classify_exit_sw(hxgep));
}
static hxge_status_t
{
/* Retrieve the saved entry */
(void *)&tcam_rdptr, sizeof (hxge_tcam_entry_t));
/* Compare the entry */
if (status == HPI_FAILURE) {
" hxge_tcam_dump_entry: tcam read failed at location %d ",
location));
return (HXGE_ERROR);
}
" key: %llx %llx\n mask: %llx %llx\n ASC RAM %llx \n", location,
return (HXGE_OK);
}
void
{
int location;
int start_location = 0;
"hxge_tcam_dump: Invalid location %d \n", location));
return;
}
if (location == -1) {
start_location = 0;
} else {
}
}
/*ARGSUSED*/
static hxge_status_t
{
return (HXGE_OK);
}
void
{
"hxge_put_tcam addr fs $%p type %x offset %x",
}
static uint32_t
{
}
static hxge_status_t
{
" hxge_tcam_default_add_entry: common hardware not set"));
return (HXGE_ERROR);
}
/*
* The class id and blade id are common for all classes
* Only use the blade id for matching and the rest are wild cards.
* This will allow one TCAM entry to match all traffic in order
* to spread the traffic using source hash.
*/
if (rs & HPI_PFC_ERROR) {
" hxge_tcam_default_add_entry tcam entry write"
" failed for location %d", location));
return (HXGE_ERROR);
}
/* Add the associative portion */
/* Use source hash to spread traffic */
if (rs & HPI_PFC_ERROR) {
" hxge_tcam_default_add_entry tcam entry write"
" failed for ASC RAM location %d", location));
return (HXGE_ERROR);
}
sizeof (hxge_tcam_entry_t));
return (HXGE_OK);
}
/*
* Configure one TCAM entry for each class and make it match
* everything within the class in order to spread the traffic
* among the DMA channels based on the source hash.
*
* This is the default for now. This may change when Crossbow is
* available for configuring TCAM.
*/
static hxge_status_t
{
/*
* Add TCAM and its associative ram entries
* A wild card will be used for the class code in order to match
* any classes.
*/
class = 0;
"hxge_tcam_default_config "
"hxge_tcam_default_add_entry failed class %d ",
class));
return (HXGE_ERROR);
}
/* Enable the classes */
for (class = TCAM_CLASS_TCP_IPV4;
/*
* By default, it is set to HXGE_CLASS_TCAM_LOOKUP in
* hxge_ndd.c. It may be overwritten in hxge.conf.
*/
if (status & HPI_PFC_ERROR) {
"hxge_tcam_default_config "
"hxge_pfc_ip_class_config failed "
return (HXGE_ERROR);
}
}
return (status);
}
{
/*
* Set new interface local address and re-init device.
* This is destructive to any other streams attached
* to this device.
*/
return (status);
}
{
/*
* Exit if the address is same as ouraddr or multicast or broadcast
*/
goto hxge_set_mac_addr_exit;
}
/*
* Set new interface local address and re-init device.
* This is destructive to any other streams attached
* to this device.
*/
goto hxge_set_mac_addr_end;
return (status);
fail:
"Unable to set mac address"));
return (status);
}
/*
* Add a multicast address entry into the HW hash table
*/
{
uint_t j;
"Allocating hash filter storage."));
KM_SLEEP);
}
/*
* Note that mchash is an 8 bit value and thus 0 <= mchash <= 255.
* Consequently, 0 <= j <= 15 and 0 <= mchash % HASH_REG_WIDTH <= 15.
*/
j = mchash / HASH_REG_WIDTH;
}
if (rx_init) {
(void) hxge_pfc_load_hash_table(hxgep);
}
return (HXGE_OK);
fail:
"Unable to add multicast address"));
return (status);
}
/*
* Remove a multicast address entry from the HW hash table
*/
{
uint_t j;
"Hash filter already de_allocated."));
return (HXGE_OK);
}
j = mchash / HASH_REG_WIDTH;
}
if (hash_filter->hash_ref_cnt == 0) {
"De-allocating hash filter storage."));
}
if (rx_init) {
(void) hxge_pfc_load_hash_table(hxgep);
/* Enable hash only if there are any hash entries */
B_TRUE);
}
return (HXGE_OK);
fail:
"Unable to remove multicast address"));
return (status);
}
static hxge_status_t
struct ether_addr *addrp)
{
int i;
" hxge_pfc_set_mac_address: common hardware not set"));
return (HXGE_ERROR);
}
/*
* Convert a byte array to a 48 bit value.
* Need to check endianess if in doubt
*/
addr = 0;
for (i = 0; i < ETHERADDRL; i++) {
addr <<= 8;
}
if (hpi_status != HPI_SUCCESS) {
" hxge_pfc_set_mac_address: failed to set address"));
return (HXGE_ERROR);
}
return (HXGE_OK);
}
/*ARGSUSED*/
{
return (HXGE_OK);
}
{
if (rs & HPI_PFC_ERROR) {
" hxge_pfc_set_hash %x failed ", seed));
return (HXGE_ERROR | rs);
}
return (HXGE_OK);
}
{
" hxge_pfc_config_tcam_enable: common hardware not set"));
return (HXGE_ERROR);
}
if (hpi_status != HPI_SUCCESS) {
" hpi_pfc_set_tcam_enable: enable tcam failed"));
return (HXGE_ERROR);
}
return (HXGE_OK);
}
{
" hxge_pfc_config_tcam_disable: common hardware not set"));
return (HXGE_ERROR);
}
if (hpi_status != HPI_SUCCESS) {
" hpi_pfc_set_tcam_enable: disable tcam failed"));
return (HXGE_ERROR);
}
return (HXGE_OK);
}
static hxge_status_t
{
if (rs & HPI_PFC_ERROR) {
" hxge_cfg_tcam_ip_class opt %x for class %d failed ",
class_config, class));
return (HXGE_ERROR | rs);
}
if (cfg.lookup_enable)
*class_config = ccfg;
ccfg));
return (HXGE_OK);
}
{
t_class_config = 0;
if (t_status & HPI_PFC_ERROR) {
" hxge_pfc_ip_class_config_get for class %d tcam failed",
class));
return (t_status);
}
*config = t_class_config;
return (HXGE_OK);
}
static hxge_status_t
{
" hxge_pfc_config_init: common hardware not set"));
return (HXGE_ERROR);
}
/* Reset PFC block from PEU to clear any previous state */
HXGE_DELAY(1000);
(void) hpi_pfc_set_default_dma(handle, 0);
(void) hpi_pfc_mac_addr_enable(handle, 0);
/* Set the drop log mask to ignore the logs */
/* Clear the interrupt masks to receive interrupts */
(void) hpi_pfc_set_interrupt_mask(handle, 0, 0, 0);
/* Clear the interrupt status */
(void) hpi_pfc_clear_interrupt_status(handle);
return (HXGE_OK);
}
static hxge_status_t
{
"==> hxge_pfc_tcam_invalidate_all"));
" hxge_pfc_tcam_invalidate_all: common hardware not set"));
return (HXGE_ERROR);
}
if (rs != HPI_SUCCESS)
return (HXGE_ERROR);
return (HXGE_OK);
}
static hxge_status_t
{
" hxge_pfc_tcam_init: common hardware not set"));
return (HXGE_ERROR);
}
/*
* Disable the TCAM.
*/
if (rs != HPI_SUCCESS) {
return (HXGE_ERROR | rs);
}
/*
* Invalidate all the TCAM entries for this blade.
*/
if (rs != HPI_SUCCESS) {
return (HXGE_ERROR | rs);
}
return (HXGE_OK);
}
static hxge_status_t
{
" hxge_pfc_vlan_tbl_clear_all: common hardware not set"));
return (HXGE_ERROR);
}
if (rs != HPI_SUCCESS) {
"failed vlan table clear\n"));
return (HXGE_ERROR | rs);
}
return (HXGE_OK);
}
{
if (class_config != config) {
}
} else {
if (class_config & HXGE_CLASS_DISCARD)
else
else
cfg.lookup_enable = 0;
}
if (rs & HPI_PFC_ERROR) {
" hxge_pfc_ip_class_config %x for class %d tcam failed",
return (HXGE_ERROR);
}
return (HXGE_OK);
}
{
if (cl == TCAM_CLASS_RESERVED_4 ||
cl == TCAM_CLASS_RESERVED_5 ||
cl == TCAM_CLASS_RESERVED_6 ||
continue;
if (status & HPI_PFC_ERROR) {
"hxge_pfc_ip_class_config failed "
}
}
return (HXGE_OK);
}
static hxge_status_t
{
int i;
boolean_t implicit_valid = 0;
return (HXGE_ERROR);
}
/* configure vlan tables */
#if defined(__i386)
#else
#endif
for (i = 0; i < cfgd_vlans; i++) {
if (status != HPI_SUCCESS) {
"hpi_pfc_cfg_vlan_table_entry_set Failed"));
return (HXGE_ERROR);
}
}
}
/* Configure the vlan_ctrl register */
/* Let hw generate the parity bits in pfc_vlan_table */
parity = 0;
/*
* Enable it only if there is a valid implicity vlan id either in
* NDD table or the .conf file.
*/
implicit_valid = 1;
if (status != HPI_SUCCESS) {
"hxge_pfc_update_hw: hpi_pfc_cfg_vlan_control_set failed"));
return (HXGE_ERROR);
}
/* config MAC addresses */
/* Need to think about this */
/* Configure hash value and classes */
"hxge_pfc_ip_class_config_all Failed"));
return (HXGE_ERROR);
}
return (HXGE_OK);
}
{
"failed PFC config init."));
return (status);
}
return (status);
}
/*
* invalidate VLAN RDC tables
*/
"failed VLAN Table Invalidate. "));
return (status);
}
return (HXGE_OK);
}
{
"hxge_classify_init_hw already init"));
return (HXGE_OK);
}
/* Now do a real configuration */
"hxge_pfc_update_hw failed"));
return (HXGE_ERROR);
}
"hxge_tcam_default_config failed"));
return (status);
}
return (HXGE_OK);
}
{
int alloc_size;
"hxge_classify_init_sw already init"));
return (HXGE_OK);
}
/* Init SW structures */
/* Start from the beginning of TCAM */
return (HXGE_OK);
}
{
int alloc_size;
int fsize;
fsize = sizeof (tcam_flow_spec_t);
if (classify_ptr->tcam_entries) {
}
return (HXGE_OK);
}
/*ARGSUSED*/
{
return (HXGE_OK);
}
{
return (DDI_INTR_UNCLAIMED);
}
}
/*
* need to read the pfc interrupt status register to figure out
* what is happenning
*/
/* Collect each individual drops */
/* Collect the total drops for all kinds */
}
INT_CTL, " TCAM parity error addr: 0x%x",
}
" vlan table parity error addr: 0x%x",
}
(void) hpi_pfc_clear_interrupt_status(handle);
return (DDI_INTR_CLAIMED);
}
static void
{
int i, j;
}
}
{
if (hpi_status != HPI_SUCCESS) {
"hxge_pfc_mac_addr_get: pfc_mac_addr_get_i failed"));
goto exit;
}
exit:
"status [0x%x]", status));
return (status);
}
/*
* Calculate the bit in the multicast address filter
* that selects the given * address.
* Note: For Hydra, the last 8-bits are used.
*/
static uint32_t
{
uint32_t c;
int byte;
int bit;
/* Hydra calculates the hash backwardly */
else
c >>= 1;
}
}
}
static hxge_status_t
{
uint32_t i;
/*
* Load the multicast hash filter bits.
*/
for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) {
if (hash_filter != NULL) {
} else {
hashtab_e = 0;
}
hashtab_e) != HPI_SUCCESS)
return (HXGE_ERROR);
}
return (HXGE_OK);
}