Print this page
212 Atheros AR8132 / L1c Gigabit Ethernet Adapter
*** 18,29 ****
--- 18,57 ----
*
* CDDL HEADER END
*/
/*
+ * Copyright (c) 2012 Gary Mills
+ *
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+ /*
+ * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/strsun.h>
#include <sys/stat.h>
*** 51,69 ****
#include <sys/pci.h>
#include <sys/pci_cap.h>
#include "atge.h"
#include "atge_cmn_reg.h"
#include "atge_l1e_reg.h"
#include "atge_l1_reg.h"
/*
! * Atheros/Attansic Ethernet chips are of three types - L1, L2 and L1E.
! * This driver is for L1E/L1 but can be extended to support other chips.
* L1E comes in 1Gigabit and Fast Ethernet flavors. L1 comes in 1Gigabit
! * flavors only.
*
* Atheros/Attansic Ethernet controllers have descriptor based TX and RX
* with an exception of L1E. L1E's RX side is not descriptor based ring.
* The L1E's RX uses pages (not to be confused with MMU pages) for
* receiving pkts. The header has four fields :
--- 79,98 ----
#include <sys/pci.h>
#include <sys/pci_cap.h>
#include "atge.h"
#include "atge_cmn_reg.h"
+ #include "atge_l1c_reg.h"
#include "atge_l1e_reg.h"
#include "atge_l1_reg.h"
/*
! * Atheros/Attansic Ethernet chips are of four types - L1, L2, L1E and L1C.
! * This driver is for L1E/L1/L1C but can be extended to support other chips.
* L1E comes in 1Gigabit and Fast Ethernet flavors. L1 comes in 1Gigabit
! * flavors only. L1C comes in both flavours.
*
* Atheros/Attansic Ethernet controllers have descriptor based TX and RX
* with an exception of L1E. L1E's RX side is not descriptor based ring.
* The L1E's RX uses pages (not to be confused with MMU pages) for
* receiving pkts. The header has four fields :
*** 150,159 ****
--- 179,189 ----
/*
* L1 specific functions.
*/
int atge_l1_alloc_dma(atge_t *);
+ void atge_l1_free_dma(atge_t *);
void atge_l1_init_tx_ring(atge_t *);
void atge_l1_init_rx_ring(atge_t *);
void atge_l1_init_rr_ring(atge_t *);
void atge_l1_init_cmb(atge_t *);
void atge_l1_init_smb(atge_t *);
*** 161,178 ****
--- 191,228 ----
void atge_l1_stop_tx_mac(atge_t *);
void atge_l1_stop_rx_mac(atge_t *);
uint_t atge_l1_interrupt(caddr_t, caddr_t);
void atge_l1_send_packet(atge_ring_t *);
+ /*
+ * L1C specific functions.
+ */
+ int atge_l1c_alloc_dma(atge_t *);
+ void atge_l1c_free_dma(atge_t *);
+ void atge_l1c_init_tx_ring(atge_t *);
+ void atge_l1c_init_rx_ring(atge_t *);
+ void atge_l1c_init_rr_ring(atge_t *);
+ void atge_l1c_init_cmb(atge_t *);
+ void atge_l1c_init_smb(atge_t *);
+ void atge_l1c_program_dma(atge_t *);
+ void atge_l1c_stop_tx_mac(atge_t *);
+ void atge_l1c_stop_rx_mac(atge_t *);
+ uint_t atge_l1c_interrupt(caddr_t, caddr_t);
+ void atge_l1c_send_packet(atge_ring_t *);
+ void atge_l1c_gather_stats(atge_t *);
+ void atge_l1c_clear_stats(atge_t *);
/*
* Function prototyps for MII operations.
*/
uint16_t atge_mii_read(void *, uint8_t, uint8_t);
void atge_mii_write(void *, uint8_t, uint8_t, uint16_t);
+ uint16_t atge_l1c_mii_read(void *, uint8_t, uint8_t);
+ void atge_l1c_mii_write(void *, uint8_t, uint8_t, uint16_t);
void atge_l1e_mii_reset(void *);
void atge_l1_mii_reset(void *);
+ void atge_l1c_mii_reset(void *);
static void atge_mii_notify(void *, link_state_t);
void atge_tx_reclaim(atge_t *atgep, int cons);
/*
* L1E/L2E chip.
*** 195,204 ****
--- 245,265 ----
atge_mii_notify,
atge_l1_mii_reset
};
/*
+ * L1C chip.
+ */
+ static mii_ops_t atge_l1c_mii_ops = {
+ MII_OPS_VERSION,
+ atge_l1c_mii_read,
+ atge_l1c_mii_write,
+ atge_mii_notify,
+ NULL
+ };
+
+ /*
* Function Prototypes for MAC callbacks.
*/
static int atge_m_stat(void *, uint_t, uint64_t *);
static int atge_m_start(void *);
static void atge_m_stop(void *);
*** 270,284 ****
/*
* Table of supported devices.
*/
#define ATGE_VENDOR_ID 0x1969
#define ATGE_L1E_STR "Atheros AR8121/8113/8114"
static atge_cards_t atge_cards[] = {
{ATGE_VENDOR_ID, ATGE_CHIP_L1E_DEV_ID, ATGE_L1E_STR, ATGE_CHIP_L1E},
! {ATGE_VENDOR_ID, ATGE_CHIP_L1_DEV_ID, "Attansic L1", ATGE_CHIP_L1},
};
/*
* Global Debugging flag. Developer level debugging is done only in DEBUG mode.
*/
--- 331,362 ----
/*
* Table of supported devices.
*/
#define ATGE_VENDOR_ID 0x1969
+ #define ATGE_L1_STR "Attansic L1"
+ #define ATGE_L1CG_STR "Atheros AR8131 Gigabit Ethernet"
+ #define ATGE_L1CF_STR "Atheros AR8132 Fast Ethernet"
#define ATGE_L1E_STR "Atheros AR8121/8113/8114"
+ #define ATGE_AR8151V1_STR "Atheros AR8151 v1.0 Gigabit Ethernet"
+ #define ATGE_AR8151V2_STR "Atheros AR8151 v2.0 Gigabit Ethernet"
+ #define ATGE_AR8152V1_STR "Atheros AR8152 v1.1 Fast Ethernet"
+ #define ATGE_AR8152V2_STR "Atheros AR8152 v2.0 Fast Ethernet"
static atge_cards_t atge_cards[] = {
+ {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V2_DEV_ID, ATGE_AR8151V2_STR,
+ ATGE_CHIP_L1C},
+ {ATGE_VENDOR_ID, ATGE_CHIP_AR8151V1_DEV_ID, ATGE_AR8151V1_STR,
+ ATGE_CHIP_L1C},
+ {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V2_DEV_ID, ATGE_AR8152V2_STR,
+ ATGE_CHIP_L1C},
+ {ATGE_VENDOR_ID, ATGE_CHIP_AR8152V1_DEV_ID, ATGE_AR8152V1_STR,
+ ATGE_CHIP_L1C},
+ {ATGE_VENDOR_ID, ATGE_CHIP_L1CG_DEV_ID, ATGE_L1CG_STR, ATGE_CHIP_L1C},
+ {ATGE_VENDOR_ID, ATGE_CHIP_L1CF_DEV_ID, ATGE_L1CF_STR, ATGE_CHIP_L1C},
{ATGE_VENDOR_ID, ATGE_CHIP_L1E_DEV_ID, ATGE_L1E_STR, ATGE_CHIP_L1E},
! {ATGE_VENDOR_ID, ATGE_CHIP_L1_DEV_ID, ATGE_L1_STR, ATGE_CHIP_L1},
};
/*
* Global Debugging flag. Developer level debugging is done only in DEBUG mode.
*/
*** 298,336 ****
va_end(ap);
DTRACE_PROBE1(atge__debug, char *, buf);
}
void
! atge_error(dev_info_t *dip, char *fmt, ...)
{
- va_list ap;
char buf[256];
- va_start(ap, fmt);
(void) vsnprintf(buf, sizeof (buf), fmt, ap);
- va_end(ap);
if (dip) {
! cmn_err(CE_WARN, "%s%d: %s",
ddi_driver_name(dip), ddi_get_instance(dip), buf);
} else {
! cmn_err(CE_WARN, "atge: %s", buf);
}
}
void
atge_mac_config(atge_t *atgep)
{
uint32_t reg;
int speed;
link_duplex_t ld;
reg = INL(atgep, ATGE_MAC_CFG);
reg &= ~(ATGE_CFG_FULL_DUPLEX | ATGE_CFG_TX_FC | ATGE_CFG_RX_FC |
ATGE_CFG_SPEED_MASK);
speed = mii_get_speed(atgep->atge_mii);
switch (speed) {
case 10:
case 100:
reg |= ATGE_CFG_SPEED_10_100;
--- 376,452 ----
va_end(ap);
DTRACE_PROBE1(atge__debug, char *, buf);
}
+ static
void
! atge_message(dev_info_t *dip, int level, char *fmt, va_list ap)
{
char buf[256];
+ char *p = "!%s%d: %s";
+ char *q = "!atge: %s";
(void) vsnprintf(buf, sizeof (buf), fmt, ap);
+ if (level != CE_NOTE) {
+ p++;
+ q++;
+ }
+
if (dip) {
! cmn_err(level, p,
ddi_driver_name(dip), ddi_get_instance(dip), buf);
} else {
! cmn_err(level, q, buf);
}
}
void
+ atge_notice(dev_info_t *dip, char *fmt, ...)
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) atge_message(dip, CE_NOTE, fmt, ap);
+ va_end(ap);
+ }
+
+ void
+ atge_error(dev_info_t *dip, char *fmt, ...)
+ {
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) atge_message(dip, CE_WARN, fmt, ap);
+ va_end(ap);
+ }
+
+ void
atge_mac_config(atge_t *atgep)
{
uint32_t reg;
int speed;
link_duplex_t ld;
+ /* Re-enable TX/RX MACs */
reg = INL(atgep, ATGE_MAC_CFG);
reg &= ~(ATGE_CFG_FULL_DUPLEX | ATGE_CFG_TX_FC | ATGE_CFG_RX_FC |
ATGE_CFG_SPEED_MASK);
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1C:
+ switch (ATGE_DID(atgep)) {
+ case ATGE_CHIP_AR8151V2_DEV_ID:
+ case ATGE_CHIP_AR8151V1_DEV_ID:
+ case ATGE_CHIP_AR8152V2_DEV_ID:
+ reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
+ break;
+ }
+ break;
+ }
+
speed = mii_get_speed(atgep->atge_mii);
switch (speed) {
case 10:
case 100:
reg |= ATGE_CFG_SPEED_10_100;
*** 343,365 ****
ld = mii_get_duplex(atgep->atge_mii);
if (ld == LINK_DUPLEX_FULL)
reg |= ATGE_CFG_FULL_DUPLEX;
/* Re-enable TX/RX MACs */
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB | ATGE_CFG_RX_FC;
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB;
}
OUTL(atgep, ATGE_MAC_CFG, reg);
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) <<
IM_TIMER_TX_SHIFT;
OUTL(atgep, ATGE_IM_TIMER, reg);
}
ATGE_DB(("%s: %s() mac_cfg is : %x",
atgep->atge_name, __func__, INL(atgep, ATGE_MAC_CFG)));
}
--- 459,505 ----
ld = mii_get_duplex(atgep->atge_mii);
if (ld == LINK_DUPLEX_FULL)
reg |= ATGE_CFG_FULL_DUPLEX;
/* Re-enable TX/RX MACs */
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB | ATGE_CFG_RX_FC;
! break;
! case ATGE_CHIP_L1:
! case ATGE_CHIP_L1C:
reg |= ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB;
+ break;
}
OUTL(atgep, ATGE_MAC_CFG, reg);
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) <<
IM_TIMER_TX_SHIFT;
OUTL(atgep, ATGE_IM_TIMER, reg);
+ break;
+ case ATGE_CHIP_L1:
+ break;
+ case ATGE_CHIP_L1C:
+ /* Configure interrupt moderation timer. */
+ reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT;
+ reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT;
+ OUTL(atgep, ATGE_IM_TIMER, reg);
+ /*
+ * We don't want to automatic interrupt clear as task queue
+ * for the interrupt should know interrupt status.
+ */
+ reg = 0;
+ if (ATGE_USECS(atgep->atge_int_rx_mod) != 0)
+ reg |= MASTER_IM_RX_TIMER_ENB;
+ if (ATGE_USECS(atgep->atge_int_tx_mod) != 0)
+ reg |= MASTER_IM_TX_TIMER_ENB;
+ OUTL(atgep, ATGE_MASTER_CFG, reg);
+ break;
}
ATGE_DB(("%s: %s() mac_cfg is : %x",
atgep->atge_name, __func__, INL(atgep, ATGE_MAC_CFG)));
}
*** 521,536 ****
/*
* Add interrupt handler now.
*/
for (i = 0; i < atgep->atge_intr_cnt; i++) {
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
atge_l1e_interrupt, atgep, (caddr_t)(uintptr_t)i);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
atge_l1_interrupt, atgep, (caddr_t)(uintptr_t)i);
}
if (err != DDI_SUCCESS) {
atge_error(atgep->atge_dip,
"ddi_intr_add_handler failed : %d", err);
--- 661,683 ----
/*
* Add interrupt handler now.
*/
for (i = 0; i < atgep->atge_intr_cnt; i++) {
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
atge_l1e_interrupt, atgep, (caddr_t)(uintptr_t)i);
! break;
! case ATGE_CHIP_L1:
err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
atge_l1_interrupt, atgep, (caddr_t)(uintptr_t)i);
+ break;
+ case ATGE_CHIP_L1C:
+ err = ddi_intr_add_handler(atgep->atge_intr_handle[i],
+ atge_l1c_interrupt, atgep, (caddr_t)(uintptr_t)i);
+ break;
}
if (err != DDI_SUCCESS) {
atge_error(atgep->atge_dip,
"ddi_intr_add_handler failed : %d", err);
*** 707,734 ****
atgep->atge_model = 0;
for (i = 0; i < (sizeof (atge_cards) / sizeof (atge_cards_t)); i++) {
if (atge_cards[i].vendor_id == vid &&
atge_cards[i].device_id == did) {
atgep->atge_model = atge_cards[i].model;
atgep->atge_revid =
pci_config_get8(atgep->atge_conf_handle,
PCI_CONF_REVID);
ATGE_DB(("%s: %s : PCI-ID pci%x,%x and model : %d",
atgep->atge_name, __func__, vid, did,
atgep->atge_model));
return (DDI_SUCCESS);
}
}
atge_error(atgep->atge_dip, "atge driver is attaching to unknown"
! " pci%d,%d vendor/device-id card", vid, did);
/*
! * Assume it's L1 chip.
*/
! atgep->atge_model = ATGE_CHIP_L1;
atgep->atge_revid = pci_config_get8(atgep->atge_conf_handle,
PCI_CONF_REVID);
/*
* We will leave the decision to caller.
--- 854,888 ----
atgep->atge_model = 0;
for (i = 0; i < (sizeof (atge_cards) / sizeof (atge_cards_t)); i++) {
if (atge_cards[i].vendor_id == vid &&
atge_cards[i].device_id == did) {
atgep->atge_model = atge_cards[i].model;
+ atgep->atge_vid = vid;
+ atgep->atge_did = did;
atgep->atge_revid =
pci_config_get8(atgep->atge_conf_handle,
PCI_CONF_REVID);
+ atge_notice(atgep->atge_dip, "PCI-ID pci%x,%x,%x: %s",
+ vid, did, atgep->atge_revid,
+ atge_cards[i].cardname);
ATGE_DB(("%s: %s : PCI-ID pci%x,%x and model : %d",
atgep->atge_name, __func__, vid, did,
atgep->atge_model));
return (DDI_SUCCESS);
}
}
atge_error(atgep->atge_dip, "atge driver is attaching to unknown"
! " pci%x,%x vendor/device-id card", vid, did);
/*
! * Assume it's L1C chip.
*/
! atgep->atge_model = ATGE_CHIP_L1C;
! atgep->atge_vid = vid;
! atgep->atge_did = did;
atgep->atge_revid = pci_config_get8(atgep->atge_conf_handle,
PCI_CONF_REVID);
/*
* We will leave the decision to caller.
*** 772,798 ****
return (DDI_SUCCESS);
}
/*
! * Reset functionality for L1 and L1E. It's same.
*/
static void
atge_device_reset(atge_t *atgep)
{
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E ||
! ATGE_MODEL(atgep) == ATGE_CHIP_L1)
atge_device_reset_l1_l1e(atgep);
}
void
atge_device_reset_l1_l1e(atge_t *atgep)
{
uint32_t reg;
int t;
!
OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET);
reg = INL(atgep, ATGE_MASTER_CFG);
for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
drv_usecwait(10);
reg = INL(atgep, ATGE_MASTER_CFG);
if ((reg & MASTER_RESET) == 0)
--- 926,962 ----
return (DDI_SUCCESS);
}
/*
! * Reset functionality for L1, L1E, and L1C. It's same.
*/
static void
atge_device_reset(atge_t *atgep)
{
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
! case ATGE_CHIP_L1:
! case ATGE_CHIP_L1C:
atge_device_reset_l1_l1e(atgep);
+ break;
+ }
}
void
atge_device_reset_l1_l1e(atge_t *atgep)
{
uint32_t reg;
int t;
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1C:
! OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET | 0x40);
! break;
! default:
OUTL(atgep, ATGE_MASTER_CFG, MASTER_RESET);
+ break;
+ }
reg = INL(atgep, ATGE_MASTER_CFG);
for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
drv_usecwait(10);
reg = INL(atgep, ATGE_MASTER_CFG);
if ((reg & MASTER_RESET) == 0)
*** 814,830 ****
if (t == 0) {
atge_error(atgep->atge_dip, "device reset timeout reg : %x",
reg);
}
/*
* Initialize PCIe module. These values came from FreeBSD and
* we don't know the meaning of it.
*/
! OUTL(atgep, 0x12FC, 0x6500);
reg = INL(atgep, 0x1008) | 0x8000;
OUTL(atgep, 0x1008, reg);
/*
* Get chip revision.
*/
atgep->atge_chip_rev = INL(atgep, ATGE_MASTER_CFG) >>
--- 978,1001 ----
if (t == 0) {
atge_error(atgep->atge_dip, "device reset timeout reg : %x",
reg);
}
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1E:
+ case ATGE_CHIP_L1:
/*
* Initialize PCIe module. These values came from FreeBSD and
* we don't know the meaning of it.
*/
! OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500);
reg = INL(atgep, 0x1008) | 0x8000;
OUTL(atgep, 0x1008, reg);
+ break;
+ case ATGE_CHIP_L1C:
+ break;
+ }
/*
* Get chip revision.
*/
atgep->atge_chip_rev = INL(atgep, ATGE_MASTER_CFG) >>
*** 841,864 ****
static int
atge_alloc_dma(atge_t *atgep)
{
int err = DDI_FAILURE;
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
err = atge_l1e_alloc_dma(atgep);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
err = atge_l1_alloc_dma(atgep);
}
return (err);
}
static void
atge_free_dma(atge_t *atgep)
{
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
atge_l1e_free_dma(atgep);
}
}
/*
* Attach entry point in the driver.
--- 1012,1049 ----
static int
atge_alloc_dma(atge_t *atgep)
{
int err = DDI_FAILURE;
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
err = atge_l1e_alloc_dma(atgep);
! break;
! case ATGE_CHIP_L1:
err = atge_l1_alloc_dma(atgep);
+ break;
+ case ATGE_CHIP_L1C:
+ err = atge_l1c_alloc_dma(atgep);
+ break;
}
return (err);
}
static void
atge_free_dma(atge_t *atgep)
{
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
atge_l1e_free_dma(atgep);
+ break;
+ case ATGE_CHIP_L1:
+ atge_l1_free_dma(atgep);
+ break;
+ case ATGE_CHIP_L1C:
+ atge_l1c_free_dma(atgep);
+ break;
}
}
/*
* Attach entry point in the driver.
*** 875,893 ****
mii_ops_t *mii_ops;
instance = ddi_get_instance(devinfo);
switch (cmd) {
- default:
- return (DDI_FAILURE);
-
case DDI_RESUME:
return (atge_resume(devinfo));
case DDI_ATTACH:
ddi_set_driver_private(devinfo, NULL);
break;
}
atgep = kmem_zalloc(sizeof (atge_t), KM_SLEEP);
ddi_set_driver_private(devinfo, atgep);
atgep->atge_dip = devinfo;
--- 1060,1078 ----
mii_ops_t *mii_ops;
instance = ddi_get_instance(devinfo);
switch (cmd) {
case DDI_RESUME:
return (atge_resume(devinfo));
case DDI_ATTACH:
ddi_set_driver_private(devinfo, NULL);
break;
+ default:
+ return (DDI_FAILURE);
+
}
atgep = kmem_zalloc(sizeof (atge_t), KM_SLEEP);
ddi_set_driver_private(devinfo, atgep);
atgep->atge_dip = devinfo;
*** 949,959 ****
DDI_INTR_PRI(atgep->atge_intr_pri));
atgep->atge_link_state = LINK_STATE_DOWN;
atgep->atge_mtu = ETHERMTU;
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
if (atgep->atge_revid > 0xF0) {
/* L2E Rev. B. AR8114 */
atgep->atge_flags |= ATGE_FLAG_FASTETHER;
} else {
if ((INL(atgep, L1E_PHY_STATUS) &
--- 1134,1145 ----
DDI_INTR_PRI(atgep->atge_intr_pri));
atgep->atge_link_state = LINK_STATE_DOWN;
atgep->atge_mtu = ETHERMTU;
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
if (atgep->atge_revid > 0xF0) {
/* L2E Rev. B. AR8114 */
atgep->atge_flags |= ATGE_FLAG_FASTETHER;
} else {
if ((INL(atgep, L1E_PHY_STATUS) &
*** 963,973 ****
--- 1149,1198 ----
} else {
/* L2E Rev. A. AR8113 */
atgep->atge_flags |= ATGE_FLAG_FASTETHER;
}
}
+ break;
+ case ATGE_CHIP_L1:
+ break;
+ case ATGE_CHIP_L1C:
+ /*
+ * One odd thing is AR8132 uses the same PHY hardware(F1
+ * gigabit PHY) of AR8131. So atphy(4) of AR8132 reports
+ * the PHY supports 1000Mbps but that's not true. The PHY
+ * used in AR8132 can't establish gigabit link even if it
+ * shows the same PHY model/revision number of AR8131.
+ *
+ * It seems that AR813x/AR815x has silicon bug for SMB. In
+ * addition, Atheros said that enabling SMB wouldn't improve
+ * performance. However I think it's bad to access lots of
+ * registers to extract MAC statistics.
+ *
+ * Don't use Tx CMB. It is known to have silicon bug.
+ */
+ switch (ATGE_DID(atgep)) {
+ case ATGE_CHIP_AR8152V2_DEV_ID:
+ case ATGE_CHIP_AR8152V1_DEV_ID:
+ atgep->atge_flags |= ATGE_FLAG_APS |
+ ATGE_FLAG_FASTETHER |
+ ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO |
+ ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG;
+ break;
+ case ATGE_CHIP_AR8151V2_DEV_ID:
+ case ATGE_CHIP_AR8151V1_DEV_ID:
+ atgep->atge_flags |= ATGE_FLAG_APS |
+ ATGE_FLAG_ASPM_MON | ATGE_FLAG_JUMBO |
+ ATGE_FLAG_SMB_BUG | ATGE_FLAG_CMB_BUG;
+ break;
+ case ATGE_CHIP_L1CF_DEV_ID:
+ atgep->atge_flags |= ATGE_FLAG_FASTETHER;
+ break;
+ case ATGE_CHIP_L1CG_DEV_ID:
+ break;
}
+ break;
+ }
/*
* Get DMA parameters from PCIe device control register.
*/
err = PCI_CAP_LOCATE(atgep->atge_conf_handle, PCI_CAP_ID_PCI_E,
*** 997,1006 ****
--- 1222,1245 ----
atgep->atge_name, __func__,
(128 << ((burst >> 12) & 0x07)),
(128 << ((burst >> 5) & 0x07))));
}
+ /* Clear data link and flow-control protocol error. */
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1E:
+ break;
+ case ATGE_CHIP_L1:
+ break;
+ case ATGE_CHIP_L1C:
+ OUTL_AND(atgep, ATGE_PEX_UNC_ERR_SEV,
+ ~(PEX_UNC_ERR_SEV_UC | PEX_UNC_ERR_SEV_FCP));
+ OUTL_AND(atgep, ATGE_LTSSM_ID_CFG, ~LTSSM_ID_WRO_ENB);
+ OUTL_OR(atgep, ATGE_PCIE_PHYMISC, PCIE_PHYMISC_FORCE_RCV_DET);
+ break;
+ }
+
/*
* Allocate DMA resources.
*/
err = atge_alloc_dma(atgep);
if (err != DDI_SUCCESS) {
*** 1014,1027 ****
(void) atge_get_macaddr(atgep);
/*
* Setup MII.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
mii_ops = &atge_l1e_mii_ops;
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
mii_ops = &atge_l1_mii_ops;
}
if ((atgep->atge_mii = mii_alloc(atgep, devinfo,
mii_ops)) == NULL) {
atge_error(devinfo, "mii_alloc() failed");
--- 1253,1272 ----
(void) atge_get_macaddr(atgep);
/*
* Setup MII.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
mii_ops = &atge_l1e_mii_ops;
! break;
! case ATGE_CHIP_L1:
mii_ops = &atge_l1_mii_ops;
+ break;
+ case ATGE_CHIP_L1C:
+ mii_ops = &atge_l1c_mii_ops;
+ break;
}
if ((atgep->atge_mii = mii_alloc(atgep, devinfo,
mii_ops)) == NULL) {
atge_error(devinfo, "mii_alloc() failed");
*** 1070,1083 ****
}
/*
* Reset the PHY before starting.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
atge_l1e_mii_reset(atgep);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
atge_l1_mii_reset(atgep);
}
/*
* Let the PHY run.
*/
--- 1315,1334 ----
}
/*
* Reset the PHY before starting.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
atge_l1e_mii_reset(atgep);
! break;
! case ATGE_CHIP_L1:
atge_l1_mii_reset(atgep);
+ break;
+ case ATGE_CHIP_L1C:
+ atge_l1c_mii_reset(atgep);
+ break;
}
/*
* Let the PHY run.
*/
*** 1360,1371 ****
mutex_exit(&atgep->atge_intr_lock);
/*
* Reset the PHY before resuming MII.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
atge_l1e_mii_reset(atgep);
}
mii_resume(atgep->atge_mii);
/* kick-off downstream */
--- 1611,1628 ----
mutex_exit(&atgep->atge_intr_lock);
/*
* Reset the PHY before resuming MII.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
atge_l1e_mii_reset(atgep);
+ break;
+ case ATGE_CHIP_L1:
+ break;
+ case ATGE_CHIP_L1C:
+ break;
}
mii_resume(atgep->atge_mii);
/* kick-off downstream */
*** 1795,1814 ****
/*
* Reprogram the Station address.
*/
atge_program_ether(atgep);
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
atge_l1e_program_dma(atgep);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
atge_l1_program_dma(atgep);
}
ATGE_DB(("%s: %s() dma, counters programmed ", atgep->atge_name,
__func__));
OUTW(atgep, ATGE_INTR_CLR_TIMER, 1*1000/2);
/*
* Set Maximum frame size but don't let MTU be less than ETHER_MTU.
*/
if (atgep->atge_mtu < ETHERMTU)
--- 2052,2100 ----
/*
* Reprogram the Station address.
*/
atge_program_ether(atgep);
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
atge_l1e_program_dma(atgep);
! break;
! case ATGE_CHIP_L1:
atge_l1_program_dma(atgep);
+ break;
+ case ATGE_CHIP_L1C:
+ atge_l1c_program_dma(atgep);
+ break;
}
ATGE_DB(("%s: %s() dma, counters programmed ", atgep->atge_name,
__func__));
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1E:
+ case ATGE_CHIP_L1:
OUTW(atgep, ATGE_INTR_CLR_TIMER, 1*1000/2);
+ break;
+ case ATGE_CHIP_L1C:
+ /*
+ * Disable interrupt re-trigger timer. We don't want automatic
+ * re-triggering of un-ACKed interrupts.
+ */
+ OUTL(atgep, ATGE_INTR_RETRIG_TIMER, ATGE_USECS(0));
+ /* Configure CMB. */
+ OUTL(atgep, ATGE_CMB_TX_TIMER, ATGE_USECS(0));
+ /*
+ * Hardware can be configured to issue SMB interrupt based
+ * on programmed interval. Since there is a callout that is
+ * invoked for every hz in driver we use that instead of
+ * relying on periodic SMB interrupt.
+ */
+ OUTL(atgep, ATGE_SMB_STAT_TIMER, ATGE_USECS(0));
+ /* Clear MAC statistics. */
+ atge_l1c_clear_stats(atgep);
+ break;
+ }
/*
* Set Maximum frame size but don't let MTU be less than ETHER_MTU.
*/
if (atgep->atge_mtu < ETHERMTU)
*** 1818,1827 ****
--- 2104,2123 ----
atgep->atge_max_frame_size += sizeof (struct ether_header) +
VLAN_TAGSZ + ETHERFCSL;
OUTL(atgep, ATGE_FRAME_SIZE, atgep->atge_max_frame_size);
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1E:
+ break;
+ case ATGE_CHIP_L1:
+ break;
+ case ATGE_CHIP_L1C:
+ /* Disable header split(?) */
+ OUTL(atgep, ATGE_HDS_CFG, 0);
+ break;
+ }
/*
* Configure IPG/IFG parameters.
*/
OUTL(atgep, ATGE_IPG_IFG_CFG,
*** 1844,1865 ****
HDPX_CFG_JAMIPG_MASK));
/*
* Configure jumbo frame.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
! fsize = ROUNDUP(atgep->atge_max_frame_size, sizeof (uint64_t));
! OUTL(atgep, ATGE_RXQ_JUMBO_CFG,
! (((fsize / sizeof (uint64_t)) <<
! RXQ_JUMBO_CFG_SZ_THRESH_SHIFT) &
! RXQ_JUMBO_CFG_SZ_THRESH_MASK) |
! ((RXQ_JUMBO_CFG_LKAH_DEFAULT <<
! RXQ_JUMBO_CFG_LKAH_SHIFT) & RXQ_JUMBO_CFG_LKAH_MASK) |
! ((ATGE_USECS(8) << RXQ_JUMBO_CFG_RRD_TIMER_SHIFT) &
! RXQ_JUMBO_CFG_RRD_TIMER_MASK));
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E &&
! atgep->atge_flags & ATGE_FLAG_JUMBO) {
if (atgep->atge_mtu < ETHERMTU)
reg = atgep->atge_max_frame_size;
else if (atgep->atge_mtu < 6 * 1024)
reg = (atgep->atge_max_frame_size * 2) / 3;
--- 2140,2152 ----
HDPX_CFG_JAMIPG_MASK));
/*
* Configure jumbo frame.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
! if (atgep->atge_flags & ATGE_FLAG_JUMBO) {
if (atgep->atge_mtu < ETHERMTU)
reg = atgep->atge_max_frame_size;
else if (atgep->atge_mtu < 6 * 1024)
reg = (atgep->atge_max_frame_size * 2) / 3;
*** 1868,1894 ****
OUTL(atgep, L1E_TX_JUMBO_THRESH,
ROUNDUP(reg, TX_JUMBO_THRESH_UNIT) >>
TX_JUMBO_THRESH_UNIT_SHIFT);
}
/*
* Configure flow-control parameters.
*/
if ((atgep->atge_flags & ATGE_FLAG_PCIE) != 0) {
/*
* Some hardware version require this magic.
*/
! OUTL(atgep, 0x12FC, 0x6500);
reg = INL(atgep, 0x1008);
OUTL(atgep, 0x1008, reg | 0x8000);
}
/*
* These are all magic parameters which came from FreeBSD.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
switch (atgep->atge_chip_rev) {
case 0x8001:
case 0x9001:
case 0x9002:
case 0x9003:
--- 2155,2215 ----
OUTL(atgep, L1E_TX_JUMBO_THRESH,
ROUNDUP(reg, TX_JUMBO_THRESH_UNIT) >>
TX_JUMBO_THRESH_UNIT_SHIFT);
}
+ break;
+ case ATGE_CHIP_L1:
+ fsize = ROUNDUP(atgep->atge_max_frame_size, sizeof (uint64_t));
+ OUTL(atgep, ATGE_RXQ_JUMBO_CFG,
+ (((fsize / sizeof (uint64_t)) <<
+ RXQ_JUMBO_CFG_SZ_THRESH_SHIFT) &
+ RXQ_JUMBO_CFG_SZ_THRESH_MASK) |
+ ((RXQ_JUMBO_CFG_LKAH_DEFAULT <<
+ RXQ_JUMBO_CFG_LKAH_SHIFT) & RXQ_JUMBO_CFG_LKAH_MASK) |
+ ((ATGE_USECS(8) << RXQ_JUMBO_CFG_RRD_TIMER_SHIFT) &
+ RXQ_JUMBO_CFG_RRD_TIMER_MASK));
+ break;
+ case ATGE_CHIP_L1C:
+ break;
+ }
/*
* Configure flow-control parameters.
*/
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1E:
+ case ATGE_CHIP_L1:
if ((atgep->atge_flags & ATGE_FLAG_PCIE) != 0) {
/*
* Some hardware version require this magic.
*/
! OUTL(atgep, ATGE_LTSSM_ID_CFG, 0x6500);
reg = INL(atgep, 0x1008);
OUTL(atgep, 0x1008, reg | 0x8000);
}
+ break;
+ case ATGE_CHIP_L1C:
+ break;
+ }
/*
* These are all magic parameters which came from FreeBSD.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
! reg = INL(atgep, L1E_SRAM_RX_FIFO_LEN);
! rxf_hi = (reg * 4) / 5;
! rxf_lo = reg/ 5;
!
! OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
! ((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
! RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
! ((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
! RXQ_FIFO_PAUSE_THRESH_HI_MASK));
! break;
! case ATGE_CHIP_L1:
switch (atgep->atge_chip_rev) {
case 0x8001:
case 0x9001:
case 0x9002:
case 0x9003:
*** 1924,1948 ****
OUTL(atgep, L1_RXQ_RRD_PAUSE_THRESH,
((rrd_lo << RXQ_RRD_PAUSE_THRESH_LO_SHIFT) &
RXQ_RRD_PAUSE_THRESH_LO_MASK) |
((rrd_hi << RXQ_RRD_PAUSE_THRESH_HI_SHIFT) &
RXQ_RRD_PAUSE_THRESH_HI_MASK));
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
! reg = INL(atgep, L1E_SRAM_RX_FIFO_LEN);
! rxf_hi = (reg * 4) / 5;
! rxf_lo = reg/ 5;
OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
RXQ_FIFO_PAUSE_THRESH_HI_MASK));
}
/* Configure RxQ. */
! reg = 0;
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
reg =
((RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) &
RXQ_CFG_RD_BURST_MASK) |
((RXQ_CFG_RRD_BURST_THRESH_DEFAULT <<
RXQ_CFG_RRD_BURST_THRESH_SHIFT) &
--- 2245,2332 ----
OUTL(atgep, L1_RXQ_RRD_PAUSE_THRESH,
((rrd_lo << RXQ_RRD_PAUSE_THRESH_LO_SHIFT) &
RXQ_RRD_PAUSE_THRESH_LO_MASK) |
((rrd_hi << RXQ_RRD_PAUSE_THRESH_HI_SHIFT) &
RXQ_RRD_PAUSE_THRESH_HI_MASK));
! break;
! case ATGE_CHIP_L1C:
! switch (ATGE_DID(atgep)) {
! case ATGE_CHIP_AR8151V2_DEV_ID:
! case ATGE_CHIP_AR8152V1_DEV_ID:
! OUTL(atgep, ATGE_SERDES_LOCK,
! INL(atgep, ATGE_SERDES_LOCK) |
! SERDES_MAC_CLK_SLOWDOWN |
! SERDES_PHY_CLK_SLOWDOWN);
! break;
! case ATGE_CHIP_L1CG_DEV_ID:
! case ATGE_CHIP_L1CF_DEV_ID:
! /*
! * Configure flow control parameters.
! * XON : 80% of Rx FIFO
! * XOFF : 30% of Rx FIFO
! */
! reg = INL(atgep, L1C_SRAM_RX_FIFO_LEN);
! rxf_hi = (reg * 8) / 10;
! rxf_lo = (reg * 3) / 10;
OUTL(atgep, ATGE_RXQ_FIFO_PAUSE_THRESH,
((rxf_lo << RXQ_FIFO_PAUSE_THRESH_LO_SHIFT) &
RXQ_FIFO_PAUSE_THRESH_LO_MASK) |
((rxf_hi << RXQ_FIFO_PAUSE_THRESH_HI_SHIFT) &
RXQ_FIFO_PAUSE_THRESH_HI_MASK));
+ break;
}
+ break;
+ }
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1E:
/* Configure RxQ. */
! reg = RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB |
! RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB;
! OUTL(atgep, ATGE_RXQ_CFG, reg);
! /*
! * Configure TxQ.
! */
! reg = (128 <<
! (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
! TXQ_CFG_TX_FIFO_BURST_SHIFT;
!
! reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
! TXQ_CFG_TPD_BURST_MASK;
!
! reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB;
!
! OUTL(atgep, ATGE_TXQ_CFG, reg);
! /* Disable RSS. */
! OUTL(atgep, L1E_RSS_IDT_TABLE0, 0);
! OUTL(atgep, L1E_RSS_CPU, 0);
! /*
! * Configure DMA parameters.
! */
! /*
! * Don't use Tx CMB. It is known to cause RRS update failure
! * under certain circumstances. Typical phenomenon of the
! * issue would be unexpected sequence number encountered in
! * Rx handler. Hence we don't set DMA_CFG_TXCMB_ENB.
! */
! OUTL(atgep, ATGE_DMA_CFG,
! DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
! atgep->atge_dma_rd_burst | atgep->atge_dma_wr_burst |
! DMA_CFG_RXCMB_ENB |
! ((DMA_CFG_RD_DELAY_CNT_DEFAULT <<
! DMA_CFG_RD_DELAY_CNT_SHIFT) & DMA_CFG_RD_DELAY_CNT_MASK) |
! ((DMA_CFG_WR_DELAY_CNT_DEFAULT <<
! DMA_CFG_WR_DELAY_CNT_SHIFT) & DMA_CFG_WR_DELAY_CNT_MASK));
! /*
! * Enable CMB/SMB timer.
! */
! OUTL(atgep, L1E_SMB_STAT_TIMER, 100000);
! atge_l1e_clear_stats(atgep);
! break;
! case ATGE_CHIP_L1:
! /* Configure RxQ. */
reg =
((RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) &
RXQ_CFG_RD_BURST_MASK) |
((RXQ_CFG_RRD_BURST_THRESH_DEFAULT <<
RXQ_CFG_RRD_BURST_THRESH_SHIFT) &
*** 1950,1969 ****
((RXQ_CFG_RD_PREF_MIN_IPG_DEFAULT <<
RXQ_CFG_RD_PREF_MIN_IPG_SHIFT) &
RXQ_CFG_RD_PREF_MIN_IPG_MASK) |
RXQ_CFG_CUT_THROUGH_ENB | RXQ_CFG_ENB;
OUTL(atgep, ATGE_RXQ_CFG, reg);
- } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
- reg = RXQ_CFG_ALIGN_32 | RXQ_CFG_CUT_THROUGH_ENB |
- RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB;
- OUTL(atgep, ATGE_RXQ_CFG, reg);
- }
-
/*
* Configure TxQ.
*/
- if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
reg =
(((TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
TXQ_CFG_TPD_BURST_MASK) |
((TXQ_CFG_TX_FIFO_BURST_DEFAULT <<
TXQ_CFG_TX_FIFO_BURST_SHIFT) &
--- 2334,2346 ----
*** 1971,2011 ****
((TXQ_CFG_TPD_FETCH_DEFAULT <<
TXQ_CFG_TPD_FETCH_THRESH_SHIFT) &
TXQ_CFG_TPD_FETCH_THRESH_MASK) |
TXQ_CFG_ENB);
OUTL(atgep, ATGE_TXQ_CFG, reg);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
! reg = (128 <<
! (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
! TXQ_CFG_TX_FIFO_BURST_SHIFT;
!
! reg |= (TXQ_CFG_TPD_BURST_DEFAULT << TXQ_CFG_TPD_BURST_SHIFT) &
! TXQ_CFG_TPD_BURST_MASK;
!
! reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB;
!
! OUTL(atgep, ATGE_TXQ_CFG, reg);
! }
!
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
OUTL(atgep, L1_TX_JUMBO_TPD_TH_IPG,
(((fsize / sizeof (uint64_t) << TX_JUMBO_TPD_TH_SHIFT)) &
TX_JUMBO_TPD_TH_MASK) |
((TX_JUMBO_TPD_IPG_DEFAULT << TX_JUMBO_TPD_IPG_SHIFT) &
TX_JUMBO_TPD_IPG_MASK));
- }
-
- if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
- /* Disable RSS. */
- OUTL(atgep, L1E_RSS_IDT_TABLE0, 0);
- OUTL(atgep, L1E_RSS_CPU, 0);
- }
-
/*
* Configure DMA parameters.
*/
- if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
OUTL(atgep, ATGE_DMA_CFG,
DMA_CFG_ENH_ORDER | DMA_CFG_RCB_64 |
atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB |
atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB);
--- 2348,2366 ----
((TXQ_CFG_TPD_FETCH_DEFAULT <<
TXQ_CFG_TPD_FETCH_THRESH_SHIFT) &
TXQ_CFG_TPD_FETCH_THRESH_MASK) |
TXQ_CFG_ENB);
OUTL(atgep, ATGE_TXQ_CFG, reg);
! /* Jumbo frames */
OUTL(atgep, L1_TX_JUMBO_TPD_TH_IPG,
(((fsize / sizeof (uint64_t) << TX_JUMBO_TPD_TH_SHIFT)) &
TX_JUMBO_TPD_TH_MASK) |
((TX_JUMBO_TPD_IPG_DEFAULT << TX_JUMBO_TPD_IPG_SHIFT) &
TX_JUMBO_TPD_IPG_MASK));
/*
* Configure DMA parameters.
*/
OUTL(atgep, ATGE_DMA_CFG,
DMA_CFG_ENH_ORDER | DMA_CFG_RCB_64 |
atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB |
atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB);
*** 2013,2043 ****
OUTL(atgep, L1_CMB_WR_THRESH,
((CMB_WR_THRESH_RRD_DEFAULT << CMB_WR_THRESH_RRD_SHIFT) &
CMB_WR_THRESH_RRD_MASK) |
((CMB_WR_THRESH_TPD_DEFAULT << CMB_WR_THRESH_TPD_SHIFT) &
CMB_WR_THRESH_TPD_MASK));
- } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
/*
- * Don't use Tx CMB. It is known to cause RRS update failure
- * under certain circumstances. Typical phenomenon of the
- * issue would be unexpected sequence number encountered in
- * Rx handler. Hence we don't set DMA_CFG_TXCMB_ENB.
- */
- OUTL(atgep, ATGE_DMA_CFG,
- DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
- atgep->atge_dma_rd_burst | atgep->atge_dma_wr_burst |
- DMA_CFG_RXCMB_ENB |
- ((DMA_CFG_RD_DELAY_CNT_DEFAULT <<
- DMA_CFG_RD_DELAY_CNT_SHIFT) & DMA_CFG_RD_DELAY_CNT_MASK) |
- ((DMA_CFG_WR_DELAY_CNT_DEFAULT <<
- DMA_CFG_WR_DELAY_CNT_SHIFT) & DMA_CFG_WR_DELAY_CNT_MASK));
- }
-
- /*
* Enable CMB/SMB timer.
*/
- if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
/* Set CMB/SMB timer and enable them. */
OUTL(atgep, L1_CMB_WR_TIMER,
((ATGE_USECS(2) << CMB_WR_TIMER_TX_SHIFT) &
CMB_WR_TIMER_TX_MASK) |
((ATGE_USECS(2) << CMB_WR_TIMER_RX_SHIFT) &
--- 2368,2380 ----
*** 2045,2061 ****
/* Request SMB updates for every seconds. */
OUTL(atgep, L1_SMB_TIMER, ATGE_USECS(1000 * 1000));
OUTL(atgep, L1_CSMB_CTRL,
CSMB_CTRL_SMB_ENB | CSMB_CTRL_CMB_ENB);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
! OUTL(atgep, L1E_SMB_STAT_TIMER, 100000);
! atge_l1e_clear_stats(atgep);
}
/*
* Disable all WOL bits as WOL can interfere normal Rx
* operation.
*/
OUTL(atgep, ATGE_WOL_CFG, 0);
--- 2382,2440 ----
/* Request SMB updates for every seconds. */
OUTL(atgep, L1_SMB_TIMER, ATGE_USECS(1000 * 1000));
OUTL(atgep, L1_CSMB_CTRL,
CSMB_CTRL_SMB_ENB | CSMB_CTRL_CMB_ENB);
! break;
! case ATGE_CHIP_L1C:
! /* Configure RxQ. */
! reg =
! RXQ_CFG_RD_BURST_DEFAULT << L1C_RXQ_CFG_RD_BURST_SHIFT |
! RXQ_CFG_IPV6_CSUM_VERIFY | RXQ_CFG_ENB;
! if ((atgep->atge_flags & ATGE_FLAG_ASPM_MON) != 0)
! reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
! OUTL(atgep, ATGE_RXQ_CFG, reg);
! /*
! * Configure TxQ.
! */
! reg = (128 <<
! (atgep->atge_dma_rd_burst >> DMA_CFG_RD_BURST_SHIFT)) <<
! TXQ_CFG_TX_FIFO_BURST_SHIFT;
!
! switch (ATGE_DID(atgep)) {
! case ATGE_CHIP_AR8152V2_DEV_ID:
! case ATGE_CHIP_AR8152V1_DEV_ID:
! reg >>= 1;
! break;
}
+ reg |= (L1C_TXQ_CFG_TPD_BURST_DEFAULT <<
+ TXQ_CFG_TPD_BURST_SHIFT) & TXQ_CFG_TPD_BURST_MASK;
+ reg |= TXQ_CFG_ENHANCED_MODE | TXQ_CFG_ENB;
+
+ OUTL(atgep, L1C_TXQ_CFG, reg);
+ /* Disable RSS until I understand L1C/L2C's RSS logic. */
+ OUTL(atgep, L1C_RSS_IDT_TABLE0, 0xe4e4e4e4);
+ OUTL(atgep, L1C_RSS_CPU, 0);
/*
+ * Configure DMA parameters.
+ */
+ OUTL(atgep, ATGE_DMA_CFG,
+ DMA_CFG_SMB_DIS |
+ DMA_CFG_OUT_ORDER | DMA_CFG_RD_REQ_PRI | DMA_CFG_RCB_64 |
+ DMA_CFG_RD_DELAY_CNT_DEFAULT << DMA_CFG_RD_DELAY_CNT_SHIFT |
+ DMA_CFG_WR_DELAY_CNT_DEFAULT << DMA_CFG_WR_DELAY_CNT_SHIFT |
+
+ atgep->atge_dma_rd_burst | DMA_CFG_RD_ENB |
+ atgep->atge_dma_wr_burst | DMA_CFG_WR_ENB);
+ /* Configure CMB DMA write threshold not required. */
+ /* Set CMB/SMB timer and enable them not required. */
+ break;
+ }
+
+ /*
* Disable all WOL bits as WOL can interfere normal Rx
* operation.
*/
OUTL(atgep, ATGE_WOL_CFG, 0);
*** 2070,2086 ****
--- 2449,2486 ----
reg = (ATGE_CFG_TX_CRC_ENB | ATGE_CFG_TX_AUTO_PAD |
ATGE_CFG_FULL_DUPLEX |
((ATGE_CFG_PREAMBLE_DEFAULT << ATGE_CFG_PREAMBLE_SHIFT) &
ATGE_CFG_PREAMBLE_MASK));
+ /*
+ * AR813x/AR815x always does checksum computation regardless
+ * of MAC_CFG_RXCSUM_ENB bit. Also the controller is known to
+ * have bug in protocol field in Rx return structure so
+ * these controllers can't handle fragmented frames. Disable
+ * Rx checksum offloading until there is a newer controller
+ * that has sane implementation.
+ */
+ switch (ATGE_DID(atgep)) {
+ case ATGE_CHIP_AR8151V2_DEV_ID:
+ case ATGE_CHIP_AR8151V1_DEV_ID:
+ case ATGE_CHIP_AR8152V2_DEV_ID:
+ reg |= ATGE_CFG_HASH_ALG_CRC32 | ATGE_CFG_SPEED_MODE_SW;
+ break;
+ }
+
if ((atgep->atge_flags & ATGE_FLAG_FASTETHER) != 0) {
reg |= ATGE_CFG_SPEED_10_100;
ATGE_DB(("%s: %s() Fast Ethernet", atgep->atge_name, __func__));
} else {
reg |= ATGE_CFG_SPEED_1000;
ATGE_DB(("%s: %s() 1G speed", atgep->atge_name, __func__));
}
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1C:
+ reg |= L1C_CFG_SINGLE_PAUSE_ENB;
+ break;
+ }
OUTL(atgep, ATGE_MAC_CFG, reg);
atgep->atge_chip_state |= ATGE_CHIP_RUNNING;
*** 2090,2106 ****
atge_rxfilter(atgep);
/*
* Acknowledge all pending interrupts and clear it.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
! OUTL(atgep, ATGE_INTR_STATUS, 0);
! OUTL(atgep, ATGE_INTR_MASK, atgep->atge_intrs);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
OUTL(atgep, ATGE_INTR_MASK, L1E_INTRS);
OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
OUTL(atgep, ATGE_INTR_STATUS, 0);
}
atge_mac_config(atgep);
ATGE_DB(("%s: %s() device started", atgep->atge_name, __func__));
--- 2490,2510 ----
atge_rxfilter(atgep);
/*
* Acknowledge all pending interrupts and clear it.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
OUTL(atgep, ATGE_INTR_MASK, L1E_INTRS);
OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
OUTL(atgep, ATGE_INTR_STATUS, 0);
+ break;
+ case ATGE_CHIP_L1:
+ case ATGE_CHIP_L1C:
+ OUTL(atgep, ATGE_INTR_STATUS, 0);
+ OUTL(atgep, ATGE_INTR_MASK, atgep->atge_intrs);
+ break;
}
atge_mac_config(atgep);
ATGE_DB(("%s: %s() device started", atgep->atge_name, __func__));
*** 2192,2244 ****
}
/*
* Collect stats for L1E. L1 chip's stats are collected by interrupt.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
atge_l1e_gather_stats(atgep);
}
/*
* Disable interrupts.
*/
atge_disable_intrs(atgep);
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1)
OUTL(atgep, L1_CSMB_CTRL, 0);
-
/* Stop DMA Engine */
- if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
atge_l1_stop_tx_mac(atgep);
atge_l1_stop_rx_mac(atgep);
-
reg = INL(atgep, ATGE_DMA_CFG);
reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB);
OUTL(atgep, ATGE_DMA_CFG, reg);
-
- }
-
/*
* Disable queue processing.
*/
/* Stop TxQ */
reg = INL(atgep, ATGE_TXQ_CFG);
reg = reg & ~TXQ_CFG_ENB;
OUTL(atgep, ATGE_TXQ_CFG, reg);
-
/* Stop RxQ */
reg = INL(atgep, ATGE_RXQ_CFG);
reg = reg & ~RXQ_CFG_ENB;
OUTL(atgep, ATGE_RXQ_CFG, reg);
!
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
reg = INL(atgep, ATGE_DMA_CFG);
! reg = reg & ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB);
OUTL(atgep, ATGE_DMA_CFG, reg);
! drv_usecwait(1000);
! atge_l1e_stop_mac(atgep);
! OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
}
for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
break;
--- 2596,2683 ----
}
/*
* Collect stats for L1E. L1 chip's stats are collected by interrupt.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
atge_l1e_gather_stats(atgep);
+ break;
+ case ATGE_CHIP_L1:
+ case ATGE_CHIP_L1C:
+ break;
}
/*
* Disable interrupts.
*/
atge_disable_intrs(atgep);
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
! /* Clear CTRL not required. */
! /* Stop DMA Engine not required. */
! /*
! * Disable queue processing.
! */
! /* Stop TxQ */
! reg = INL(atgep, ATGE_TXQ_CFG);
! reg = reg & ~TXQ_CFG_ENB;
! OUTL(atgep, ATGE_TXQ_CFG, reg);
! /* Stop RxQ */
! reg = INL(atgep, ATGE_RXQ_CFG);
! reg = reg & ~RXQ_CFG_ENB;
! OUTL(atgep, ATGE_RXQ_CFG, reg);
! /* Stop DMA */
! reg = INL(atgep, ATGE_DMA_CFG);
! reg = reg & ~(DMA_CFG_TXCMB_ENB | DMA_CFG_RXCMB_ENB);
! OUTL(atgep, ATGE_DMA_CFG, reg);
! drv_usecwait(1000);
! atge_l1e_stop_mac(atgep);
! OUTL(atgep, ATGE_INTR_STATUS, 0xFFFFFFFF);
! break;
! case ATGE_CHIP_L1:
! /* Clear CTRL. */
OUTL(atgep, L1_CSMB_CTRL, 0);
/* Stop DMA Engine */
atge_l1_stop_tx_mac(atgep);
atge_l1_stop_rx_mac(atgep);
reg = INL(atgep, ATGE_DMA_CFG);
reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB);
OUTL(atgep, ATGE_DMA_CFG, reg);
/*
* Disable queue processing.
*/
/* Stop TxQ */
reg = INL(atgep, ATGE_TXQ_CFG);
reg = reg & ~TXQ_CFG_ENB;
OUTL(atgep, ATGE_TXQ_CFG, reg);
/* Stop RxQ */
reg = INL(atgep, ATGE_RXQ_CFG);
reg = reg & ~RXQ_CFG_ENB;
OUTL(atgep, ATGE_RXQ_CFG, reg);
! break;
! case ATGE_CHIP_L1C:
! /* Clear CTRL not required. */
! /* Stop DMA Engine */
! atge_l1c_stop_tx_mac(atgep);
! atge_l1c_stop_rx_mac(atgep);
reg = INL(atgep, ATGE_DMA_CFG);
! reg &= ~(DMA_CFG_RD_ENB | DMA_CFG_WR_ENB);
OUTL(atgep, ATGE_DMA_CFG, reg);
! /*
! * Disable queue processing.
! */
! /* Stop TxQ */
! reg = INL(atgep, L1C_TXQ_CFG);
! reg = reg & ~TXQ_CFG_ENB;
! OUTL(atgep, L1C_TXQ_CFG, reg);
! /* Stop RxQ */
! reg = INL(atgep, ATGE_RXQ_CFG);
! reg = reg & ~RXQ_CFG_ENB;
! OUTL(atgep, ATGE_RXQ_CFG, reg);
! break;
}
for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
if ((reg = INL(atgep, ATGE_IDLE_STATUS)) == 0)
break;
*** 2259,2284 ****
}
void
atge_device_init(atge_t *atgep)
{
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
atgep->atge_intrs = L1E_INTRS;
atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
atge_l1e_init_tx_ring(atgep);
atge_l1e_init_rx_pages(atgep);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
atgep->atge_intrs = L1_INTRS | INTR_GPHY | INTR_PHY_LINK_DOWN |
INTR_LINK_CHG;
atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
atge_l1_init_tx_ring(atgep);
atge_l1_init_rx_ring(atgep);
atge_l1_init_rr_ring(atgep);
atge_l1_init_cmb(atgep);
atge_l1_init_smb(atgep);
}
}
void
atge_device_restart(atge_t *atgep)
--- 2698,2741 ----
}
void
atge_device_init(atge_t *atgep)
{
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
atgep->atge_intrs = L1E_INTRS;
atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
atge_l1e_init_tx_ring(atgep);
atge_l1e_init_rx_pages(atgep);
! break;
! case ATGE_CHIP_L1:
atgep->atge_intrs = L1_INTRS | INTR_GPHY | INTR_PHY_LINK_DOWN |
INTR_LINK_CHG;
atgep->atge_int_mod = ATGE_IM_TIMER_DEFAULT;
atge_l1_init_tx_ring(atgep);
atge_l1_init_rx_ring(atgep);
atge_l1_init_rr_ring(atgep);
atge_l1_init_cmb(atgep);
atge_l1_init_smb(atgep);
+ break;
+ case ATGE_CHIP_L1C:
+ atgep->atge_intrs = L1C_INTRS | L1C_INTR_GPHY |
+ L1C_INTR_PHY_LINK_DOWN;
+ atgep->atge_int_rx_mod = 400/2;
+ atgep->atge_int_tx_mod = 2000/1;
+
+ atge_l1c_init_tx_ring(atgep);
+ atge_l1c_init_rx_ring(atgep);
+ atge_l1c_init_rr_ring(atgep);
+ atge_l1c_init_cmb(atgep);
+ atge_l1c_init_smb(atgep);
+
+ /* Enable all clocks. */
+ OUTL(atgep, ATGE_CLK_GATING_CFG, 0);
+ break;
}
}
void
atge_device_restart(atge_t *atgep)
*** 2309,2319 ****
}
static int
atge_send_a_packet(atge_t *atgep, mblk_t *mp)
{
- atge_tx_desc_t *txd;
uchar_t *c;
uint32_t cflags = 0;
atge_ring_t *r;
size_t pktlen;
uchar_t *buf;
--- 2766,2775 ----
*** 2359,2368 ****
--- 2815,2845 ----
mcopymsg(mp, buf);
r->r_avail_desc--;
c = (uchar_t *)r->r_desc_ring->addr;
+ switch (ATGE_MODEL(atgep)) {
+ case ATGE_CHIP_L1C:
+ {
+ l1c_tx_desc_t *txd;
+
+ c += (sizeof (l1c_tx_desc_t) * start);
+ txd = (l1c_tx_desc_t *)c;
+
+ ATGE_PUT64(r->r_desc_ring, &txd->addr,
+ r->r_buf_tbl[start]->cookie.dmac_laddress);
+
+ ATGE_PUT32(r->r_desc_ring, &txd->len, L1C_TX_BYTES(pktlen));
+
+ cflags |= L1C_TD_EOP;
+ ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
+ break;
+ }
+ default:
+ {
+ atge_tx_desc_t *txd;
+
c += (sizeof (atge_tx_desc_t) * start);
txd = (atge_tx_desc_t *)c;
ATGE_PUT64(r->r_desc_ring, &txd->addr,
r->r_buf_tbl[start]->cookie.dmac_laddress);
*** 2369,2379 ****
ATGE_PUT32(r->r_desc_ring, &txd->len, ATGE_TX_BYTES(pktlen));
cflags |= ATGE_TD_EOP;
ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
!
/*
* Sync buffer first.
*/
DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV);
--- 2846,2858 ----
ATGE_PUT32(r->r_desc_ring, &txd->len, ATGE_TX_BYTES(pktlen));
cflags |= ATGE_TD_EOP;
ATGE_PUT32(r->r_desc_ring, &txd->flags, cflags);
! break;
! }
! }
/*
* Sync buffer first.
*/
DMA_SYNC(r->r_buf_tbl[start], 0, pktlen, DDI_DMA_SYNC_FORDEV);
*** 2388,2401 ****
DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
/*
* Program TX descriptor to send a packet.
*/
! if (ATGE_MODEL(atgep) == ATGE_CHIP_L1E) {
atge_l1e_send_packet(r);
! } else if (ATGE_MODEL(atgep) == ATGE_CHIP_L1) {
atge_l1_send_packet(r);
}
r->r_atge->atge_opackets++;
r->r_atge->atge_obytes += pktlen;
--- 2867,2886 ----
DMA_SYNC(r->r_desc_ring, 0, ATGE_TX_RING_SZ, DDI_DMA_SYNC_FORDEV);
/*
* Program TX descriptor to send a packet.
*/
! switch (ATGE_MODEL(atgep)) {
! case ATGE_CHIP_L1E:
atge_l1e_send_packet(r);
! break;
! case ATGE_CHIP_L1:
atge_l1_send_packet(r);
+ break;
+ case ATGE_CHIP_L1C:
+ atge_l1c_send_packet(r);
+ break;
}
r->r_atge->atge_opackets++;
r->r_atge->atge_obytes += pktlen;