- Updated to the latest myri10ge firmware
- Added support for multicast filtering, now that the firmware supports it. Note that this is not yet tested, as multicast seems to panic -current (even w/o mxge loaded) - Added workaround to cope with different irq data struct size on pre-multicast firmware which can found running on nics. - Added Intel E5000 PCIe chipsets to list providing aligned completions. - Replaced various magic constants with #defines, now that they are defined in the firmware headers.
This commit is contained in:
parent
eb65c05e44
commit
0fa7f68197
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -426,8 +426,10 @@ mxge_select_firmware(mxge_softc_t *sc)
|
||||
}
|
||||
/* see if the upstream bridge is known to
|
||||
provided aligned completions */
|
||||
if (/* HT2000 */ (pvend == 0x1166 && pdid == 0x0132) ||
|
||||
/* Ontario */ (pvend == 0x10b5 && pdid == 0x8532)) {
|
||||
if (/* HT2000 */ (pvend == 0x1166 && pdid == 0x0132) ||
|
||||
/* PLX */ (pvend == 0x10b5 && pdid == 0x8532) ||
|
||||
/* Intel */ (pvend == 0x8086 &&
|
||||
/* E5000 */(pdid >= 0x25f7 && pdid <= 0x25fa))) {
|
||||
if (mxge_verbose)
|
||||
device_printf(sc->dev,
|
||||
"Assuming aligned completions "
|
||||
@ -579,7 +581,7 @@ mxge_dummy_rdma(mxge_softc_t *sc, int enable)
|
||||
buf[5] = htobe32(enable); /* enable? */
|
||||
|
||||
|
||||
submit = (volatile char *)(sc->sram + 0xfc01c0);
|
||||
submit = (volatile char *)(sc->sram + MXGEFW_BOOT_DUMMY_RDMA);
|
||||
|
||||
mxge_pio_copy(submit, buf, 64);
|
||||
mb();
|
||||
@ -604,7 +606,7 @@ mxge_send_cmd(mxge_softc_t *sc, uint32_t cmd, mxge_cmd_t *data)
|
||||
mcp_cmd_t *buf;
|
||||
char buf_bytes[sizeof(*buf) + 8];
|
||||
volatile mcp_cmd_response_t *response = sc->cmd;
|
||||
volatile char *cmd_addr = sc->sram + MXGEFW_CMD_OFFSET;
|
||||
volatile char *cmd_addr = sc->sram + MXGEFW_ETH_CMD;
|
||||
uint32_t dma_low, dma_high;
|
||||
int sleep_total = 0;
|
||||
|
||||
@ -748,7 +750,7 @@ mxge_load_firmware(mxge_softc_t *sc)
|
||||
buf[5] = htobe32(8); /* where to copy to */
|
||||
buf[6] = htobe32(0); /* where to jump to */
|
||||
|
||||
submit = (volatile char *)(sc->sram + 0xfc0000);
|
||||
submit = (volatile char *)(sc->sram + MXGEFW_BOOT_HANDOFF);
|
||||
mxge_pio_copy(submit, buf, 64);
|
||||
mb();
|
||||
DELAY(1000);
|
||||
@ -825,6 +827,73 @@ mxge_change_promisc(mxge_softc_t *sc, int promisc)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
mxge_set_multicast_list(mxge_softc_t *sc)
|
||||
{
|
||||
mxge_cmd_t cmd;
|
||||
struct ifmultiaddr *ifma;
|
||||
struct ifnet *ifp = sc->ifp;
|
||||
int err;
|
||||
|
||||
/* This firmware is known to not support multicast */
|
||||
if (!sc->fw_multicast_support)
|
||||
return;
|
||||
|
||||
/* Disable multicast filtering while we play with the lists*/
|
||||
err = mxge_send_cmd(sc, MXGEFW_ENABLE_ALLMULTI, &cmd);
|
||||
if (err != 0) {
|
||||
device_printf(sc->dev, "Failed MXGEFW_ENABLE_ALLMULTI,"
|
||||
" error status: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (ifp->if_flags & IFF_ALLMULTI)
|
||||
/* request to disable multicast filtering, so quit here */
|
||||
return;
|
||||
|
||||
/* Flush all the filters */
|
||||
|
||||
err = mxge_send_cmd(sc, MXGEFW_LEAVE_ALL_MULTICAST_GROUPS, &cmd);
|
||||
if (err != 0) {
|
||||
device_printf(sc->dev,
|
||||
"Failed MXGEFW_LEAVE_ALL_MULTICAST_GROUPS"
|
||||
", error status: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Walk the multicast list, and add each address */
|
||||
|
||||
IF_ADDR_LOCK(ifp);
|
||||
TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
|
||||
if (ifma->ifma_addr->sa_family != AF_LINK)
|
||||
continue;
|
||||
bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
|
||||
&cmd.data0, 4);
|
||||
bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr) + 4,
|
||||
&cmd.data1, 2);
|
||||
cmd.data0 = htonl(cmd.data0);
|
||||
cmd.data1 = htonl(cmd.data1);
|
||||
err = mxge_send_cmd(sc, MXGEFW_JOIN_MULTICAST_GROUP, &cmd);
|
||||
if (err != 0) {
|
||||
device_printf(sc->dev, "Failed "
|
||||
"MXGEFW_JOIN_MULTICAST_GROUP, error status:"
|
||||
"%d\t", err);
|
||||
/* abort, leaving multicast filtering off */
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
IF_ADDR_UNLOCK(ifp);
|
||||
/* Enable multicast filtering */
|
||||
err = mxge_send_cmd(sc, MXGEFW_DISABLE_ALLMULTI, &cmd);
|
||||
if (err != 0) {
|
||||
device_printf(sc->dev, "Failed MXGEFW_DISABLE_ALLMULTI"
|
||||
", error status: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
mxge_reset(mxge_softc_t *sc)
|
||||
{
|
||||
@ -932,6 +1001,7 @@ mxge_reset(mxge_softc_t *sc)
|
||||
status = mxge_update_mac_address(sc);
|
||||
mxge_change_promisc(sc, 0);
|
||||
mxge_change_pause(sc, sc->pause);
|
||||
mxge_set_multicast_list(sc);
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1085,6 +1155,12 @@ mxge_add_sysctls(mxge_softc_t *sc)
|
||||
&fw->dropped_link_error_or_filtered,
|
||||
0, mxge_handle_be32,
|
||||
"I", "dropped_link_error_or_filtered");
|
||||
SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
|
||||
"dropped_multicast_filtered",
|
||||
CTLTYPE_INT|CTLFLAG_RD,
|
||||
&fw->dropped_multicast_filtered,
|
||||
0, mxge_handle_be32,
|
||||
"I", "dropped_multicast_filtered");
|
||||
SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
|
||||
"dropped_runt",
|
||||
CTLTYPE_INT|CTLFLAG_RD, &fw->dropped_runt,
|
||||
@ -1225,7 +1301,7 @@ mxge_submit_req_wc(mxge_tx_buf_t *tx, mcp_kreq_ether_send_t *src, int cnt)
|
||||
if (cnt > 0) {
|
||||
/* pad it to 64 bytes. The src is 64 bytes bigger than it
|
||||
needs to be so that we don't overrun it */
|
||||
mxge_pio_copy(tx->wc_fifo + (cnt<<18), src, 64);
|
||||
mxge_pio_copy(tx->wc_fifo + MXGEFW_ETH_SEND_OFFSET(cnt), src, 64);
|
||||
mb();
|
||||
}
|
||||
}
|
||||
@ -2266,6 +2342,7 @@ mxge_open(mxge_softc_t *sc)
|
||||
mxge_cmd_t cmd;
|
||||
int i, err;
|
||||
bus_dmamap_t map;
|
||||
bus_addr_t bus;
|
||||
|
||||
|
||||
/* Copy the MAC address in case it was overridden */
|
||||
@ -2317,9 +2394,9 @@ mxge_open(mxge_softc_t *sc)
|
||||
}
|
||||
|
||||
if (sc->wc) {
|
||||
sc->tx.wc_fifo = sc->sram + 0x200000;
|
||||
sc->rx_small.wc_fifo = sc->sram + 0x300000;
|
||||
sc->rx_big.wc_fifo = sc->sram + 0x340000;
|
||||
sc->tx.wc_fifo = sc->sram + MXGEFW_ETH_SEND_4;
|
||||
sc->rx_small.wc_fifo = sc->sram + MXGEFW_ETH_RECV_SMALL;
|
||||
sc->rx_big.wc_fifo = sc->sram + MXGEFW_ETH_RECV_BIG;
|
||||
} else {
|
||||
sc->tx.wc_fifo = 0;
|
||||
sc->rx_small.wc_fifo = 0;
|
||||
@ -2357,10 +2434,31 @@ mxge_open(mxge_softc_t *sc)
|
||||
&cmd);
|
||||
cmd.data0 = sc->big_bytes;
|
||||
err |= mxge_send_cmd(sc, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd);
|
||||
|
||||
if (err != 0) {
|
||||
device_printf(sc->dev, "failed to setup params\n");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
/* Now give him the pointer to the stats block */
|
||||
cmd.data0 = MXGE_LOWPART_TO_U32(sc->fw_stats_dma.bus_addr);
|
||||
cmd.data1 = MXGE_HIGHPART_TO_U32(sc->fw_stats_dma.bus_addr);
|
||||
err = mxge_send_cmd(sc, MXGEFW_CMD_SET_STATS_DMA, &cmd);
|
||||
cmd.data2 = sizeof(struct mcp_irq_data);
|
||||
err = mxge_send_cmd(sc, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd);
|
||||
|
||||
if (err != 0) {
|
||||
bus = sc->fw_stats_dma.bus_addr;
|
||||
bus += offsetof(struct mcp_irq_data, send_done_count);
|
||||
cmd.data0 = MXGE_LOWPART_TO_U32(bus);
|
||||
cmd.data1 = MXGE_HIGHPART_TO_U32(bus);
|
||||
err = mxge_send_cmd(sc,
|
||||
MXGEFW_CMD_SET_STATS_DMA_OBSOLETE,
|
||||
&cmd);
|
||||
/* Firmware cannot support multicast without STATS_DMA_V2 */
|
||||
sc->fw_multicast_support = 0;
|
||||
} else {
|
||||
sc->fw_multicast_support = 1;
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
device_printf(sc->dev, "failed to setup params\n");
|
||||
@ -2487,6 +2585,13 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
|
||||
err = mxge_open(sc);
|
||||
else {
|
||||
/* take care of promis can allmulti
|
||||
flag chages */
|
||||
mxge_change_promisc(sc,
|
||||
ifp->if_flags & IFF_PROMISC);
|
||||
mxge_set_multicast_list(sc);
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
|
||||
mxge_close(sc);
|
||||
@ -2496,7 +2601,9 @@ mxge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
|
||||
|
||||
case SIOCADDMULTI:
|
||||
case SIOCDELMULTI:
|
||||
err = 0;
|
||||
sx_xlock(&sc->driver_lock);
|
||||
mxge_set_multicast_list(sc);
|
||||
sx_xunlock(&sc->driver_lock);
|
||||
break;
|
||||
|
||||
case SIOCSIFCAP:
|
||||
|
@ -155,6 +155,7 @@ typedef struct {
|
||||
int read_dma;
|
||||
int write_dma;
|
||||
int read_write_dma;
|
||||
int fw_multicast_support;
|
||||
char *mac_addr_string;
|
||||
char product_code_string[64];
|
||||
char serial_number_string[64];
|
||||
|
@ -147,7 +147,19 @@ typedef struct mcp_kreq_ether_recv mcp_kreq_ether_recv_t;
|
||||
|
||||
/* Commands */
|
||||
|
||||
#define MXGEFW_CMD_OFFSET 0xf80000
|
||||
#define MXGEFW_BOOT_HANDOFF 0xfc0000
|
||||
#define MXGEFW_BOOT_DUMMY_RDMA 0xfc01c0
|
||||
|
||||
#define MXGEFW_ETH_CMD 0xf80000
|
||||
#define MXGEFW_ETH_SEND_4 0x200000
|
||||
#define MXGEFW_ETH_SEND_1 0x240000
|
||||
#define MXGEFW_ETH_SEND_2 0x280000
|
||||
#define MXGEFW_ETH_SEND_3 0x2c0000
|
||||
#define MXGEFW_ETH_RECV_SMALL 0x300000
|
||||
#define MXGEFW_ETH_RECV_BIG 0x340000
|
||||
|
||||
#define MXGEFW_ETH_SEND(n) (0x200000 + (((n) & 0x03) * 0x40000))
|
||||
#define MXGEFW_ETH_SEND_OFFSET(n) (MXGEFW_ETH_SEND(n) - MXGEFW_ETH_SEND_4)
|
||||
|
||||
enum myri10ge_mcp_cmd_type {
|
||||
MXGEFW_CMD_NONE = 0,
|
||||
@ -212,7 +224,7 @@ enum myri10ge_mcp_cmd_type {
|
||||
MXGEFW_CMD_SET_MTU,
|
||||
MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, /* in microseconds */
|
||||
MXGEFW_CMD_SET_STATS_INTERVAL, /* in microseconds */
|
||||
MXGEFW_CMD_SET_STATS_DMA,
|
||||
MXGEFW_CMD_SET_STATS_DMA_OBSOLETE, /* replaced by SET_STATS_DMA_V2 */
|
||||
|
||||
MXGEFW_ENABLE_PROMISC,
|
||||
MXGEFW_DISABLE_PROMISC,
|
||||
@ -226,7 +238,26 @@ enum myri10ge_mcp_cmd_type {
|
||||
data2 = RDMA length (MSH), WDMA length (LSH)
|
||||
command return data = repetitions (MSH), 0.5-ms ticks (LSH)
|
||||
*/
|
||||
MXGEFW_DMA_TEST
|
||||
MXGEFW_DMA_TEST,
|
||||
|
||||
MXGEFW_ENABLE_ALLMULTI,
|
||||
MXGEFW_DISABLE_ALLMULTI,
|
||||
|
||||
/* returns MXGEFW_CMD_ERROR_MULTICAST
|
||||
if there is no room in the cache
|
||||
data0,MSH(data1) = multicast group address */
|
||||
MXGEFW_JOIN_MULTICAST_GROUP,
|
||||
/* returns MXGEFW_CMD_ERROR_MULTICAST
|
||||
if the address is not in the cache,
|
||||
or is equal to FF-FF-FF-FF-FF-FF
|
||||
data0,MSH(data1) = multicast group address */
|
||||
MXGEFW_LEAVE_MULTICAST_GROUP,
|
||||
MXGEFW_LEAVE_ALL_MULTICAST_GROUPS,
|
||||
|
||||
MXGEFW_CMD_SET_STATS_DMA_V2,
|
||||
/* data0, data1 = bus addr,
|
||||
data2 = sizeof(struct mcp_irq_data) from driver point of view, allows
|
||||
adding new stuff to mcp_irq_data without changing the ABI */
|
||||
};
|
||||
typedef enum myri10ge_mcp_cmd_type myri10ge_mcp_cmd_type_t;
|
||||
|
||||
@ -240,13 +271,19 @@ enum myri10ge_mcp_cmd_status {
|
||||
MXGEFW_CMD_ERROR_CLOSED,
|
||||
MXGEFW_CMD_ERROR_HASH_ERROR,
|
||||
MXGEFW_CMD_ERROR_BAD_PORT,
|
||||
MXGEFW_CMD_ERROR_RESOURCES
|
||||
MXGEFW_CMD_ERROR_RESOURCES,
|
||||
MXGEFW_CMD_ERROR_MULTICAST
|
||||
};
|
||||
typedef enum myri10ge_mcp_cmd_status myri10ge_mcp_cmd_status_t;
|
||||
|
||||
|
||||
/* 40 Bytes */
|
||||
#define MXGEFW_OLD_IRQ_DATA_LEN 40
|
||||
|
||||
struct mcp_irq_data {
|
||||
/* add new counters at the beginning */
|
||||
uint32_t future_use[5];
|
||||
uint32_t dropped_multicast_filtered;
|
||||
/* 40 Bytes */
|
||||
uint32_t send_done_count;
|
||||
|
||||
uint32_t link_up;
|
||||
|
Loading…
Reference in New Issue
Block a user