From e700f9f4a208bf6c5d2b4dd67816555930524476 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Mon, 14 Aug 2006 17:52:54 -0400 Subject: [PATCH] myri10ge: define some previously hardwired firmware constants Define some previously hardwired firmware constants. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 17 ++++++++++------- drivers/net/myri10ge/myri10ge_mcp.h | 14 +++++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) (limited to 'drivers/net/myri10ge') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 9bdd43ab3573..f463a2f2bdde 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -271,7 +271,7 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, struct mcp_cmd *buf; char buf_bytes[sizeof(*buf) + 8]; struct mcp_cmd_response *response = mgp->cmd; - char __iomem *cmd_addr = mgp->sram + MXGEFW_CMD_OFFSET; + char __iomem *cmd_addr = mgp->sram + MXGEFW_ETH_CMD; u32 dma_low, dma_high, result, value; int sleep_total = 0; @@ -404,7 +404,7 @@ static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) buf[4] = htonl(dma_low); /* dummy addr LSW */ buf[5] = htonl(enable); /* enable? */ - submit = mgp->sram + 0xfc01c0; + submit = mgp->sram + MXGEFW_BOOT_DUMMY_RDMA; myri10ge_pio_copy(submit, &buf, sizeof(buf)); for (i = 0; mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20; i++) @@ -600,7 +600,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) buf[5] = htonl(8); /* where to copy to */ buf[6] = htonl(0); /* where to jump to */ - submit = mgp->sram + 0xfc0000; + submit = mgp->sram + MXGEFW_BOOT_HANDOFF; myri10ge_pio_copy(submit, &buf, sizeof(buf)); mb(); @@ -1648,9 +1648,11 @@ static int myri10ge_open(struct net_device *dev) } if (mgp->mtrr >= 0) { - mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + 0x200000; - mgp->rx_small.wc_fifo = (u8 __iomem *) mgp->sram + 0x300000; - mgp->rx_big.wc_fifo = (u8 __iomem *) mgp->sram + 0x340000; + mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4; + mgp->rx_small.wc_fifo = + (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL; + mgp->rx_big.wc_fifo = + (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_BIG; } else { mgp->tx.wc_fifo = NULL; mgp->rx_small.wc_fifo = NULL; @@ -1841,7 +1843,8 @@ myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx, 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 */ - myri10ge_pio_copy(tx->wc_fifo + (cnt << 18), src, 64); + myri10ge_pio_copy(tx->wc_fifo + MXGEFW_ETH_SEND_OFFSET(cnt), + src, 64); mb(); } } diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h index 0a6cae6cb186..d7dfaa5f64a2 100644 --- a/drivers/net/myri10ge/myri10ge_mcp.h +++ b/drivers/net/myri10ge/myri10ge_mcp.h @@ -91,7 +91,19 @@ struct mcp_kreq_ether_recv { /* 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, -- cgit v1.2.3 From fd6746daade513bf7f887625c107878b6aacccfd Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Mon, 14 Aug 2006 17:53:15 -0400 Subject: [PATCH] myri10ge: convert to netdev_alloc_skb Convert the myri10ge driver to use netdev_alloc_skb instead of dev_alloc_skb, which requires to propagate the net_device across several functions. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) (limited to 'drivers/net/myri10ge') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index f463a2f2bdde..c0c41ca688ef 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -798,12 +798,13 @@ myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst, * pages directly and building a fraglist in the near future. */ -static inline struct sk_buff *myri10ge_alloc_big(int bytes) +static inline struct sk_buff *myri10ge_alloc_big(struct net_device *dev, + int bytes) { struct sk_buff *skb; unsigned long data, roundup; - skb = dev_alloc_skb(bytes + 4096 + MXGEFW_PAD); + skb = netdev_alloc_skb(dev, bytes + 4096 + MXGEFW_PAD); if (skb == NULL) return NULL; @@ -821,12 +822,13 @@ static inline struct sk_buff *myri10ge_alloc_big(int bytes) /* Allocate 2x as much space as required and use whichever portion * does not cross a 4KB boundary */ -static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes) +static inline struct sk_buff *myri10ge_alloc_small_safe(struct net_device *dev, + unsigned int bytes) { struct sk_buff *skb; unsigned long data, boundary; - skb = dev_alloc_skb(2 * (bytes + MXGEFW_PAD) - 1); + skb = netdev_alloc_skb(dev, 2 * (bytes + MXGEFW_PAD) - 1); if (unlikely(skb == NULL)) return NULL; @@ -847,12 +849,13 @@ static inline struct sk_buff *myri10ge_alloc_small_safe(unsigned int bytes) /* Allocate just enough space, and verify that the allocated * space does not cross a 4KB boundary */ -static inline struct sk_buff *myri10ge_alloc_small(int bytes) +static inline struct sk_buff *myri10ge_alloc_small(struct net_device *dev, + int bytes) { struct sk_buff *skb; unsigned long roundup, data, end; - skb = dev_alloc_skb(bytes + 16 + MXGEFW_PAD); + skb = netdev_alloc_skb(dev, bytes + 16 + MXGEFW_PAD); if (unlikely(skb == NULL)) return NULL; @@ -868,15 +871,17 @@ static inline struct sk_buff *myri10ge_alloc_small(int bytes) "myri10ge_alloc_small: small skb crossed 4KB boundary\n"); myri10ge_skb_cross_4k = 1; dev_kfree_skb_any(skb); - skb = myri10ge_alloc_small_safe(bytes); + skb = myri10ge_alloc_small_safe(dev, bytes); } return skb; } static inline int -myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes, - int idx) +myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct myri10ge_priv *mgp, + int bytes, int idx) { + struct net_device *dev = mgp->dev; + struct pci_dev *pdev = mgp->pdev; struct sk_buff *skb; dma_addr_t bus; int len, retval = 0; @@ -884,11 +889,11 @@ myri10ge_getbuf(struct myri10ge_rx_buf *rx, struct pci_dev *pdev, int bytes, bytes += VLAN_HLEN; /* account for 802.1q vlan tag */ if ((bytes + MXGEFW_PAD) > (4096 - 16) /* linux overhead */ ) - skb = myri10ge_alloc_big(bytes); + skb = myri10ge_alloc_big(dev, bytes); else if (myri10ge_skb_cross_4k) - skb = myri10ge_alloc_small_safe(bytes); + skb = myri10ge_alloc_small_safe(dev, bytes); else - skb = myri10ge_alloc_small(bytes); + skb = myri10ge_alloc_small(dev, bytes); if (unlikely(skb == NULL)) { rx->alloc_fail++; @@ -951,7 +956,7 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, unmap_len = pci_unmap_len(&rx->info[idx], len); /* try to replace the received skb */ - if (myri10ge_getbuf(rx, mgp->pdev, bytes, idx)) { + if (myri10ge_getbuf(rx, mgp, bytes, idx)) { /* drop the frame -- the old skbuf is re-cycled */ mgp->stats.rx_dropped += 1; return 0; @@ -968,7 +973,6 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, skb_put(skb, len); skb->protocol = eth_type_trans(skb, mgp->dev); - skb->dev = mgp->dev; if (mgp->csum_flag) { if ((skb->protocol == ntohs(ETH_P_IP)) || (skb->protocol == ntohs(ETH_P_IPV6))) { @@ -1439,7 +1443,7 @@ static int myri10ge_allocate_rings(struct net_device *dev) /* Fill the receive rings */ for (i = 0; i <= mgp->rx_small.mask; i++) { - status = myri10ge_getbuf(&mgp->rx_small, mgp->pdev, + status = myri10ge_getbuf(&mgp->rx_small, mgp, mgp->small_bytes, i); if (status) { printk(KERN_ERR @@ -1451,8 +1455,7 @@ static int myri10ge_allocate_rings(struct net_device *dev) for (i = 0; i <= mgp->rx_big.mask; i++) { status = - myri10ge_getbuf(&mgp->rx_big, mgp->pdev, - dev->mtu + ETH_HLEN, i); + myri10ge_getbuf(&mgp->rx_big, mgp, dev->mtu + ETH_HLEN, i); if (status) { printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n", -- cgit v1.2.3 From c58ac5caeb32ef17c2e4fc208f7dc93f6de32b7d Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Mon, 21 Aug 2006 17:36:49 -0400 Subject: [PATCH] myri10ge: use netif_msg_link Add msg_enable and use netif_msg_link to enable/disable reporting of link status changes since some Ethernet switches seem to generate a lot of status changes under some circumstances and some people want to avoid useless flooding in the logs. Also add a counter for link status changes to statistics. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 46 ++++++++++++++++++++++++++++++++++------- 1 file changed, 39 insertions(+), 7 deletions(-) (limited to 'drivers/net/myri10ge') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index c0c41ca688ef..a79afe2134ba 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -192,6 +192,8 @@ struct myri10ge_priv { u32 read_dma; u32 write_dma; u32 read_write_dma; + u32 link_changes; + u32 msg_enable; }; static char *myri10ge_fw_unaligned = "myri10ge_ethp_z8e.dat"; @@ -257,6 +259,12 @@ module_param(myri10ge_max_irq_loops, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_max_irq_loops, "Set stuck legacy IRQ detection threshold\n"); +#define MYRI10GE_MSG_DEFAULT NETIF_MSG_LINK + +static int myri10ge_debug = -1; /* defaults above */ +module_param(myri10ge_debug, int, 0); +MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); + #define MYRI10GE_FW_OFFSET 1024*1024 #define MYRI10GE_HIGHPART_TO_U32(X) \ (sizeof (X) == 8) ? ((u32)((u64)(X) >> 32)) : (0) @@ -764,6 +772,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) mgp->rx_small.cnt = 0; mgp->rx_done.idx = 0; mgp->rx_done.cnt = 0; + mgp->link_changes = 0; status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr); myri10ge_change_promisc(mgp, 0, 0); myri10ge_change_pause(mgp, mgp->pause); @@ -1085,13 +1094,19 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) if (mgp->link_state != stats->link_up) { mgp->link_state = stats->link_up; if (mgp->link_state) { - printk(KERN_INFO "myri10ge: %s: link up\n", - mgp->dev->name); + if (netif_msg_link(mgp)) + printk(KERN_INFO + "myri10ge: %s: link up\n", + mgp->dev->name); netif_carrier_on(mgp->dev); + mgp->link_changes++; } else { - printk(KERN_INFO "myri10ge: %s: link down\n", - mgp->dev->name); + if (netif_msg_link(mgp)) + printk(KERN_INFO + "myri10ge: %s: link down\n", + mgp->dev->name); netif_carrier_off(mgp->dev); + mgp->link_changes++; } } if (mgp->rdma_tags_available != @@ -1293,8 +1308,9 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { "serial_number", "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt", "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized", - "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered", - "dropped_runt", "dropped_overrun", "dropped_no_small_buffer", + "link_changes", "link_up", "dropped_link_overflow", + "dropped_link_error_or_filtered", "dropped_runt", + "dropped_overrun", "dropped_no_small_buffer", "dropped_no_big_buffer" }; @@ -1345,6 +1361,7 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i++] = (unsigned int)mgp->stop_queue; data[i++] = (unsigned int)mgp->watchdog_resets; data[i++] = (unsigned int)mgp->tx_linearized; + data[i++] = (unsigned int)mgp->link_changes; data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up); data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow); data[i++] = @@ -1355,6 +1372,18 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer); } +static void myri10ge_set_msglevel(struct net_device *netdev, u32 value) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + mgp->msg_enable = value; +} + +static u32 myri10ge_get_msglevel(struct net_device *netdev) +{ + struct myri10ge_priv *mgp = netdev_priv(netdev); + return mgp->msg_enable; +} + static struct ethtool_ops myri10ge_ethtool_ops = { .get_settings = myri10ge_get_settings, .get_drvinfo = myri10ge_get_drvinfo, @@ -1375,7 +1404,9 @@ static struct ethtool_ops myri10ge_ethtool_ops = { #endif .get_strings = myri10ge_get_strings, .get_stats_count = myri10ge_get_stats_count, - .get_ethtool_stats = myri10ge_get_ethtool_stats + .get_ethtool_stats = myri10ge_get_ethtool_stats, + .set_msglevel = myri10ge_set_msglevel, + .get_msglevel = myri10ge_get_msglevel }; static int myri10ge_allocate_rings(struct net_device *dev) @@ -2587,6 +2618,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp->csum_flag = MXGEFW_FLAGS_CKSUM; mgp->pause = myri10ge_flow_control; mgp->intr_coal_delay = myri10ge_intr_coal_delay; + mgp->msg_enable = netif_msg_init(myri10ge_debug, MYRI10GE_MSG_DEFAULT); init_waitqueue_head(&mgp->down_wq); if (pci_enable_device(pdev)) { -- cgit v1.2.3 From 85a7ea1b0a3263f3ad423b789a841d03c9acbb65 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Mon, 21 Aug 2006 17:36:56 -0400 Subject: [PATCH] myri10ge: use multicast support in the firmware Some recent myri10ge firmwares support multicast filtering as well as an extended mcp_irq_data structure (64 instead of 40 bytes). The new command MXGEFW_CMD_SET_STATS_DMA_V2 is used to check whether the firmware support those. mgp->fw_multicast_support is defined accordingly. When fw_multicast_support is set, some new multicast filtering commands is passed to the board in myri10ge_set_multicast_list(). Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 99 +++++++++++++++++++++++++++++++++++-- drivers/net/myri10ge/myri10ge_mcp.h | 33 +++++++++++-- 2 files changed, 124 insertions(+), 8 deletions(-) (limited to 'drivers/net/myri10ge') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index a79afe2134ba..e2346e8a4d52 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -187,6 +187,7 @@ struct myri10ge_priv { u8 mac_addr[6]; /* eeprom mac address */ unsigned long serial_number; int vendor_specific_offset; + int fw_multicast_support; u32 devctl; u16 msi_flags; u32 read_dma; @@ -328,6 +329,8 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, if (result == 0) { data->data0 = value; return 0; + } else if (result == MXGEFW_CMD_UNKNOWN) { + return -ENOSYS; } else { dev_err(&mgp->pdev->dev, "command %d failed, result = %d\n", @@ -1309,8 +1312,8 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt", "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized", "link_changes", "link_up", "dropped_link_overflow", - "dropped_link_error_or_filtered", "dropped_runt", - "dropped_overrun", "dropped_no_small_buffer", + "dropped_link_error_or_filtered", "dropped_multicast_filtered", + "dropped_runt", "dropped_overrun", "dropped_no_small_buffer", "dropped_no_big_buffer" }; @@ -1366,6 +1369,8 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow); data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered); + data[i++] = + (unsigned int)ntohl(mgp->fw_stats->dropped_multicast_filtered); data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt); data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun); data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer); @@ -1722,7 +1727,21 @@ static int myri10ge_open(struct net_device *dev) cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus); cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus); - status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA, &cmd, 0); + cmd.data2 = sizeof(struct mcp_irq_data); + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0); + if (status == -ENOSYS) { + dma_addr_t bus = mgp->fw_stats_bus; + bus += offsetof(struct mcp_irq_data, send_done_count); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(bus); + status = myri10ge_send_cmd(mgp, + MXGEFW_CMD_SET_STATS_DMA_OBSOLETE, + &cmd, 0); + /* Firmware cannot support multicast without STATS_DMA_V2 */ + mgp->fw_multicast_support = 0; + } else { + mgp->fw_multicast_support = 1; + } if (status) { printk(KERN_ERR "myri10ge: %s: Couldn't set stats DMA\n", dev->name); @@ -2177,9 +2196,81 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) static void myri10ge_set_multicast_list(struct net_device *dev) { + struct myri10ge_cmd cmd; + struct myri10ge_priv *mgp; + struct dev_mc_list *mc_list; + int err; + + mgp = netdev_priv(dev); /* can be called from atomic contexts, * pass 1 to force atomicity in myri10ge_send_cmd() */ - myri10ge_change_promisc(netdev_priv(dev), dev->flags & IFF_PROMISC, 1); + myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1); + + /* This firmware is known to not support multicast */ + if (!mgp->fw_multicast_support) + return; + + /* Disable multicast filtering */ + + err = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_ALLMULTI, &cmd, 1); + if (err != 0) { + printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_ENABLE_ALLMULTI," + " error status: %d\n", dev->name, err); + goto abort; + } + + if (dev->flags & IFF_ALLMULTI) { + /* request to disable multicast filtering, so quit here */ + return; + } + + /* Flush the filters */ + + err = myri10ge_send_cmd(mgp, MXGEFW_LEAVE_ALL_MULTICAST_GROUPS, + &cmd, 1); + if (err != 0) { + printk(KERN_ERR + "myri10ge: %s: Failed MXGEFW_LEAVE_ALL_MULTICAST_GROUPS" + ", error status: %d\n", dev->name, err); + goto abort; + } + + /* Walk the multicast list, and add each address */ + for (mc_list = dev->mc_list; mc_list != NULL; mc_list = mc_list->next) { + memcpy(&cmd.data0, &mc_list->dmi_addr, 4); + memcpy(&cmd.data1, ((char *)&mc_list->dmi_addr) + 4, 2); + cmd.data0 = htonl(cmd.data0); + cmd.data1 = htonl(cmd.data1); + err = myri10ge_send_cmd(mgp, MXGEFW_JOIN_MULTICAST_GROUP, + &cmd, 1); + + if (err != 0) { + printk(KERN_ERR "myri10ge: %s: Failed " + "MXGEFW_JOIN_MULTICAST_GROUP, error status:" + "%d\t", dev->name, err); + printk(KERN_ERR "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + ((unsigned char *)&mc_list->dmi_addr)[0], + ((unsigned char *)&mc_list->dmi_addr)[1], + ((unsigned char *)&mc_list->dmi_addr)[2], + ((unsigned char *)&mc_list->dmi_addr)[3], + ((unsigned char *)&mc_list->dmi_addr)[4], + ((unsigned char *)&mc_list->dmi_addr)[5] + ); + goto abort; + } + } + /* Enable multicast filtering */ + err = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_ALLMULTI, &cmd, 1); + if (err != 0) { + printk(KERN_ERR "myri10ge: %s: Failed MXGEFW_DISABLE_ALLMULTI," + "error status: %d\n", dev->name, err); + goto abort; + } + + return; + +abort: + return; } static int myri10ge_set_mac_address(struct net_device *dev, void *addr) diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h index d7dfaa5f64a2..9519ae7cd5ec 100644 --- a/drivers/net/myri10ge/myri10ge_mcp.h +++ b/drivers/net/myri10ge/myri10ge_mcp.h @@ -166,7 +166,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, @@ -180,7 +180,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 */ }; enum myri10ge_mcp_cmd_status { @@ -192,11 +211,17 @@ 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 }; -/* 40 Bytes */ +#define MXGEFW_OLD_IRQ_DATA_LEN 40 + struct mcp_irq_data { + /* add new counters at the beginning */ + u32 future_use[5]; + u32 dropped_multicast_filtered; + /* 40 Bytes */ u32 send_done_count; u32 link_up; -- cgit v1.2.3 From ce7f93680aa1d37171c654536ae0ce9745d86a24 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Thu, 31 Aug 2006 01:32:59 -0400 Subject: [PATCH] myri10ge: improve firmware selection Improve the firmware selection by adding 2 cases where we should use the optimized firmware: * when the actual PCIe link width is lower than 8x. * when the board is plugged to one of the new Intel PCIe chipsets that are known to provide aligned PCIe completions. The patch actually raises two concerns: * We might want to add a generic PCI function to get the PCIe link width since some other drivers (at least ipath) do the same. But we probably do not want to add a new function for every PCIe capability. I will probably look at it and discuss it on linux-pci in the future. * As requested during the submission, the PCI ids of chipsets that are known to provided aligned completion are defined in the myri10ge code. If we keep adding new ones, it might become better to move them to pciids.h. But, this sort of quirk to detect these chipsets are very specific to our NIC, I don't think it is worth moving it to the PCI core until somebody else really needs it. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) (limited to 'drivers/net/myri10ge') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index e2346e8a4d52..b19e2034d11f 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2417,6 +2417,8 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) */ #define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE 0x0132 +#define PCI_DEVICE_ID_INTEL_E5000_PCIE23 0x25f7 +#define PCI_DEVICE_ID_INTEL_E5000_PCIE47 0x25fa static void myri10ge_select_firmware(struct myri10ge_priv *mgp) { @@ -2426,15 +2428,34 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) mgp->fw_name = myri10ge_fw_unaligned; if (myri10ge_force_firmware == 0) { + int link_width, exp_cap; + u16 lnk; + + exp_cap = pci_find_capability(mgp->pdev, PCI_CAP_ID_EXP); + pci_read_config_word(mgp->pdev, exp_cap + PCI_EXP_LNKSTA, &lnk); + link_width = (lnk >> 4) & 0x3f; + myri10ge_enable_ecrc(mgp); - /* Check to see if the upstream bridge is known to - * provide aligned completions */ - if (bridge - /* ServerWorks HT2000/HT1000 */ - && bridge->vendor == PCI_VENDOR_ID_SERVERWORKS - && bridge->device == - PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) { + /* Check to see if Link is less than 8 or if the + * upstream bridge is known to provide aligned + * completions */ + if (link_width < 8) { + dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", + link_width); + mgp->tx.boundary = 4096; + mgp->fw_name = myri10ge_fw_aligned; + } else if (bridge && + /* ServerWorks HT2000/HT1000 */ + ((bridge->vendor == PCI_VENDOR_ID_SERVERWORKS + && bridge->device == + PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE) + /* All Intel E5000 PCIE ports */ + || (bridge->vendor == PCI_VENDOR_ID_INTEL + && bridge->device >= + PCI_DEVICE_ID_INTEL_E5000_PCIE23 + && bridge->device <= + PCI_DEVICE_ID_INTEL_E5000_PCIE47))) { dev_info(&mgp->pdev->dev, "Assuming aligned completions (0x%x:0x%x)\n", bridge->vendor, bridge->device); -- cgit v1.2.3 From 7282d491ecaee9883233a0e27283c4c79486279a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 13 Sep 2006 14:30:00 -0400 Subject: drivers/net: const-ify ethtool_ops declarations Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/myri10ge') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index b19e2034d11f..2773440c84be 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1389,7 +1389,7 @@ static u32 myri10ge_get_msglevel(struct net_device *netdev) return mgp->msg_enable; } -static struct ethtool_ops myri10ge_ethtool_ops = { +static const struct ethtool_ops myri10ge_ethtool_ops = { .get_settings = myri10ge_get_settings, .get_drvinfo = myri10ge_get_drvinfo, .get_coalesce = myri10ge_get_coalesce, -- cgit v1.2.3