/*************************************************************************
* myri10ge.c: Myricom Myri-10G Ethernet driver.
*
- * Copyright (C) 2005 - 2007 Myricom, Inc.
+ * Copyright (C) 2005 - 2009 Myricom, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.4.3-1.378"
+#define MYRI10GE_VERSION_STR "1.4.4-1.401"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
ss->dca_tag = NULL;
}
}
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_MYRI10GE_DCA */
/* reset mcp/driver shared state back to 0 */
myri10ge_teardown_dca(mgp);
return 0;
}
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_MYRI10GE_DCA */
static inline void
myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
__be32 low;
low = src->addr_low;
- src->addr_low = htonl(DMA_32BIT_MASK);
+ src->addr_low = htonl(DMA_BIT_MASK(32));
myri10ge_pio_copy(dst, src, 4 * sizeof(*src));
mb();
myri10ge_pio_copy(dst + 4, src + 4, 4 * sizeof(*src));
skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
if (unlikely(skb == NULL)) {
- mgp->stats.rx_dropped++;
+ ss->stats.rx_dropped++;
do {
i--;
put_page(rx_frags[i].page);
skb_shinfo(skb)->nr_frags = 0;
}
skb->protocol = eth_type_trans(skb, dev);
+ skb_record_rx_queue(skb, ss - &mgp->ss[0]);
if (mgp->csum_flag) {
if ((skb->protocol == htons(ETH_P_IP)) ||
{
struct myri10ge_slice_state *ss =
container_of(napi, struct myri10ge_slice_state, napi);
- struct net_device *netdev = ss->mgp->dev;
int work_done;
#ifdef CONFIG_MYRI10GE_DCA
work_done = myri10ge_clean_rx_done(ss, budget);
if (work_done < budget) {
- netif_rx_complete(netdev, napi);
+ napi_complete(napi);
put_be32(htonl(3), ss->irq_claim);
}
return work_done;
/* an interrupt on a non-zero receive-only slice is implicitly
* valid since MSI-X irqs are not shared */
if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {
- netif_rx_schedule(ss->dev, &ss->napi);
+ napi_schedule(&ss->napi);
return (IRQ_HANDLED);
}
/* low bit indicates receives are present, so schedule
* napi poll handler */
if (stats->valid & 1)
- netif_rx_schedule(ss->dev, &ss->napi);
+ napi_schedule(&ss->napi);
if (!mgp->msi_enabled && !mgp->msix_enabled) {
put_be32(0, mgp->irq_deassert);
*ip_hdr = iph;
if (iph->protocol != IPPROTO_TCP)
return -1;
+ if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+ return -1;
*hdr_flags |= LRO_TCP;
*tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
lro_mgr->lro_arr = ss->rx_done.lro_desc;
lro_mgr->get_frag_header = myri10ge_get_frag_header;
lro_mgr->max_aggr = myri10ge_lro_max_pkts;
+ lro_mgr->frag_align_pad = 2;
if (lro_mgr->max_aggr > MAX_SKB_FRAGS)
lro_mgr->max_aggr = MAX_SKB_FRAGS;
{
struct sk_buff *segs, *curr;
struct myri10ge_priv *mgp = netdev_priv(dev);
+ struct myri10ge_slice_state *ss;
int status;
segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
return 0;
drop:
+ ss = &mgp->ss[skb_get_queue_mapping(skb)];
dev_kfree_skb_any(skb);
- mgp->stats.tx_dropped += 1;
+ ss->stats.tx_dropped += 1;
return 0;
}
myri10ge_load_firmware(mgp, 0);
}
+static const struct net_device_ops myri10ge_netdev_ops = {
+ .ndo_open = myri10ge_open,
+ .ndo_stop = myri10ge_close,
+ .ndo_start_xmit = myri10ge_xmit,
+ .ndo_get_stats = myri10ge_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = myri10ge_change_mtu,
+ .ndo_set_multicast_list = myri10ge_set_multicast_list,
+ .ndo_set_mac_address = myri10ge_set_mac_address,
+};
+
static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
int i;
int status = -ENXIO;
int dac_enabled;
+ unsigned hdr_offset, ss_offset;
netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
if (netdev == NULL) {
if (status != 0) {
dev_err(&pdev->dev, "Error %d writing PCI_EXP_DEVCTL\n",
status);
- goto abort_with_netdev;
+ goto abort_with_enabled;
}
pci_set_master(pdev);
dac_enabled = 1;
- status = pci_set_dma_mask(pdev, DMA_64BIT_MASK);
+ status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
if (status != 0) {
dac_enabled = 0;
dev_err(&pdev->dev,
"64-bit pci address mask was refused, "
"trying 32-bit\n");
- status = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ status = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
}
if (status != 0) {
dev_err(&pdev->dev, "Error %d setting DMA mask\n", status);
- goto abort_with_netdev;
+ goto abort_with_enabled;
}
- (void)pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
+ (void)pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
mgp->cmd = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->cmd),
&mgp->cmd_bus, GFP_KERNEL);
if (mgp->cmd == NULL)
- goto abort_with_netdev;
+ goto abort_with_enabled;
mgp->board_span = pci_resource_len(pdev, 0);
mgp->iomem_base = pci_resource_start(pdev, 0);
if (mgp->mtrr >= 0)
mgp->wc_enabled = 1;
#endif
- /* Hack. need to get rid of these magic numbers */
- mgp->sram_size =
- 2 * 1024 * 1024 - (2 * (48 * 1024) + (32 * 1024)) - 0x100;
- if (mgp->sram_size > mgp->board_span) {
- dev_err(&pdev->dev, "board span %ld bytes too small\n",
- mgp->board_span);
- goto abort_with_mtrr;
- }
mgp->sram = ioremap_wc(mgp->iomem_base, mgp->board_span);
if (mgp->sram == NULL) {
dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
status = -ENXIO;
goto abort_with_mtrr;
}
+ hdr_offset =
+ ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc;
+ ss_offset = hdr_offset + offsetof(struct mcp_gen_header, string_specs);
+ mgp->sram_size = ntohl(__raw_readl(mgp->sram + ss_offset));
+ if (mgp->sram_size > mgp->board_span ||
+ mgp->sram_size <= MYRI10GE_FW_OFFSET) {
+ dev_err(&pdev->dev,
+ "invalid sram_size %dB or board span %ldB\n",
+ mgp->sram_size, mgp->board_span);
+ goto abort_with_ioremap;
+ }
memcpy_fromio(mgp->eeprom_strings,
- mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
- MYRI10GE_EEPROM_STRINGS_SIZE);
+ mgp->sram + mgp->sram_size, MYRI10GE_EEPROM_STRINGS_SIZE);
memset(mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2);
status = myri10ge_read_mac_addr(mgp);
if (status)
myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
if ((myri10ge_initial_mtu + ETH_HLEN) < 68)
myri10ge_initial_mtu = 68;
+
+ netdev->netdev_ops = &myri10ge_netdev_ops;
netdev->mtu = myri10ge_initial_mtu;
- netdev->open = myri10ge_open;
- netdev->stop = myri10ge_close;
- netdev->hard_start_xmit = myri10ge_xmit;
- netdev->get_stats = myri10ge_get_stats;
netdev->base_addr = mgp->iomem_base;
- netdev->change_mtu = myri10ge_change_mtu;
- netdev->set_multicast_list = myri10ge_set_multicast_list;
- netdev->set_mac_address = myri10ge_set_mac_address;
netdev->features = mgp->features;
if (dac_enabled)
myri10ge_dummy_rdma(mgp, 0);
abort_with_ioremap:
+ if (mgp->mac_addr_string != NULL)
+ dev_err(&pdev->dev,
+ "myri10ge_probe() failed: MAC=%s, SN=%ld\n",
+ mgp->mac_addr_string, mgp->serial_number);
iounmap(mgp->sram);
abort_with_mtrr:
dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd),
mgp->cmd, mgp->cmd_bus);
-abort_with_netdev:
+abort_with_enabled:
+ pci_disable_device(pdev);
+abort_with_netdev:
free_netdev(netdev);
return status;
}
mgp->cmd, mgp->cmd_bus);
free_netdev(netdev);
+ pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
}
.next = NULL,
.priority = 0,
};
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_MYRI10GE_DCA */
static __init int myri10ge_init_module(void)
{