diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic')
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c | 21 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 15 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | 37 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge.h | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c | 315 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlge/qlge_main.c | 101 |
12 files changed, 327 insertions, 205 deletions
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index 37ccbe54e62d..eb3dfdbb642b 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -53,8 +53,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 79 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.79" +#define _NETXEN_NIC_LINUX_SUBVERSION 80 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.80" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 24) + ((b) << 16) + (c)) #define _major(v) (((v) >> 24) & 0xff) diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 39730403782f..10468e7932dd 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c @@ -489,7 +489,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, int port = adapter->physical_port; if (adapter->ahw.port_type == NETXEN_NIC_GBE) { - if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS)) return; /* get flow control settings */ val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port)); @@ -511,7 +511,7 @@ netxen_nic_get_pauseparam(struct net_device *dev, break; } } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { - if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) + if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS)) return; pause->rx_pause = 1; val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL); @@ -534,7 +534,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, int port = adapter->physical_port; /* read mode */ if (adapter->ahw.port_type == NETXEN_NIC_GBE) { - if ((port < 0) || (port > NETXEN_NIU_MAX_GBE_PORTS)) + if ((port < 0) || (port >= NETXEN_NIU_MAX_GBE_PORTS)) return -EIO; /* set flow control */ val = NXRD32(adapter, NETXEN_NIU_GB_MAC_CONFIG_0(port)); @@ -577,7 +577,7 @@ netxen_nic_set_pauseparam(struct net_device *dev, } NXWR32(adapter, NETXEN_NIU_GB_PAUSE_CTL, val); } else if (adapter->ahw.port_type == NETXEN_NIC_XGBE) { - if ((port < 0) || (port > NETXEN_NIU_MAX_XG_PORTS)) + if ((port < 0) || (port >= NETXEN_NIU_MAX_XG_PORTS)) return -EIO; val = NXRD32(adapter, NETXEN_NIU_XG_PAUSE_CTL); if (port == 0) { @@ -826,7 +826,12 @@ netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) dump->len = mdump->md_dump_size; else dump->len = 0; - dump->flag = mdump->md_capture_mask; + + if (!mdump->md_enabled) + dump->flag = ETH_FW_DUMP_DISABLE; + else + dump->flag = mdump->md_capture_mask; + dump->version = adapter->fw_version; return 0; } @@ -840,8 +845,10 @@ netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val) switch (val->flag) { case NX_FORCE_FW_DUMP_KEY: - if (!mdump->md_enabled) - mdump->md_enabled = 1; + if (!mdump->md_enabled) { + netdev_info(netdev, "FW dump not enabled\n"); + return 0; + } if (adapter->fw_mdump_rdy) { netdev_info(netdev, "Previous dump not cleared, not forcing dump\n"); return 0; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index de96a948bb7f..946160fa5843 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c @@ -365,7 +365,7 @@ static int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) return 0; - if (port > NETXEN_NIU_MAX_XG_PORTS) + if (port >= NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; mac_cfg = 0; @@ -392,7 +392,7 @@ static int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) u32 port = adapter->physical_port; u16 board_type = adapter->ahw.board_type; - if (port > NETXEN_NIU_MAX_XG_PORTS) + if (port >= NETXEN_NIU_MAX_XG_PORTS) return -EINVAL; mac_cfg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port)); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 8694124ef77d..bc165f4d0f65 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -1437,8 +1437,6 @@ netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) netdev->name, cable_len); } - netxen_advert_link_change(adapter, link_status); - /* update link parameters */ if (duplex == LINKEVENT_FULL_DUPLEX) adapter->link_duplex = DUPLEX_FULL; @@ -1447,6 +1445,8 @@ netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) adapter->module_type = module; adapter->link_autoneg = autoneg; adapter->link_speed = link_speed; + + netxen_advert_link_change(adapter, link_status); } static void @@ -1532,8 +1532,6 @@ static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, } else skb->ip_summed = CHECKSUM_NONE; - skb->dev = adapter->netdev; - buffer->skb = NULL; no_skb: buffer->state = NETXEN_BUFFER_FREE; diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 8680a5dae4a2..eaa1db9fec32 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h @@ -36,8 +36,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 28 -#define QLCNIC_LINUX_VERSIONID "5.0.28" +#define _QLCNIC_LINUX_SUBVERSION 29 +#define QLCNIC_LINUX_VERSIONID "5.0.29" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) @@ -258,6 +258,8 @@ struct rcv_desc { (((sts_data) >> 52) & 0x1) #define qlcnic_get_lro_sts_seq_number(sts_data) \ ((sts_data) & 0x0FFFFFFFF) +#define qlcnic_get_lro_sts_mss(sts_data1) \ + ((sts_data1 >> 32) & 0x0FFFF) struct status_desc { @@ -610,7 +612,11 @@ struct qlcnic_recv_context { #define QLCNIC_CDRP_CMD_GET_MAC_STATS 0x00000037 #define QLCNIC_RCODE_SUCCESS 0 +#define QLCNIC_RCODE_INVALID_ARGS 6 #define QLCNIC_RCODE_NOT_SUPPORTED 9 +#define QLCNIC_RCODE_NOT_PERMITTED 10 +#define QLCNIC_RCODE_NOT_IMPL 15 +#define QLCNIC_RCODE_INVALID 16 #define QLCNIC_RCODE_TIMEOUT 17 #define QLCNIC_DESTROY_CTX_RESET 0 @@ -623,6 +629,7 @@ struct qlcnic_recv_context { #define QLCNIC_CAP0_JUMBO_CONTIGUOUS (1 << 7) #define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8) #define QLCNIC_CAP0_VALIDOFF (1 << 11) +#define QLCNIC_CAP0_LRO_MSS (1 << 21) /* * Context state @@ -829,6 +836,9 @@ struct qlcnic_mac_list_s { #define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9 #define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10 #define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27 +#define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31 + +#define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 /* module types */ #define LINKEVENT_MODULE_NOT_PRESENT 1 @@ -918,6 +928,7 @@ struct qlcnic_ipaddr { #define QLCNIC_NEED_FLR 0x1000 #define QLCNIC_FW_RESET_OWNER 0x2000 #define QLCNIC_FW_HANG 0x4000 +#define QLCNIC_FW_LRO_MSS_CAP 0x8000 #define QLCNIC_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index 8db85244e8ad..b8ead696141e 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -53,12 +53,39 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) rsp = qlcnic_poll_rsp(adapter); if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) { - dev_err(&pdev->dev, "card response timeout.\n"); + dev_err(&pdev->dev, "CDRP response timeout.\n"); cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT; } else if (rsp == QLCNIC_CDRP_RSP_FAIL) { cmd->rsp.cmd = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); - dev_err(&pdev->dev, "failed card response code:0x%x\n", + switch (cmd->rsp.cmd) { + case QLCNIC_RCODE_INVALID_ARGS: + dev_err(&pdev->dev, "CDRP invalid args: 0x%x.\n", cmd->rsp.cmd); + break; + case QLCNIC_RCODE_NOT_SUPPORTED: + case QLCNIC_RCODE_NOT_IMPL: + dev_err(&pdev->dev, + "CDRP command not supported: 0x%x.\n", + cmd->rsp.cmd); + break; + case QLCNIC_RCODE_NOT_PERMITTED: + dev_err(&pdev->dev, + "CDRP requested action not permitted: 0x%x.\n", + cmd->rsp.cmd); + break; + case QLCNIC_RCODE_INVALID: + dev_err(&pdev->dev, + "CDRP invalid or unknown cmd received: 0x%x.\n", + cmd->rsp.cmd); + break; + case QLCNIC_RCODE_TIMEOUT: + dev_err(&pdev->dev, "CDRP command timeout: 0x%x.\n", + cmd->rsp.cmd); + break; + default: + dev_err(&pdev->dev, "CDRP command failed: 0x%x.\n", + cmd->rsp.cmd); + } } else if (rsp == QLCNIC_CDRP_RSP_OK) { cmd->rsp.cmd = QLCNIC_RCODE_SUCCESS; if (cmd->rsp.arg2) @@ -237,6 +264,9 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | QLCNIC_CAP0_VALIDOFF); cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); + if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) + cap |= QLCNIC_CAP0_LRO_MSS; + prq->valid_field_offset = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler); prq->txrx_sds_binding = nsds_rings - 1; @@ -954,9 +984,6 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber); mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped); mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error); - } else { - dev_info(&adapter->pdev->dev, - "%s: Get mac stats failed =%d.\n", __func__, err); } dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h index 6ced3195aad3..28a6b28192e3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h @@ -588,6 +588,7 @@ enum { #define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0)) #define CRB_FW_CAPABILITIES_1 (QLCNIC_CAM_RAM(0x128)) +#define CRB_FW_CAPABILITIES_2 (QLCNIC_CAM_RAM(0x12c)) #define CRB_MAC_BLOCK_START (QLCNIC_CAM_RAM(0x1c0)) /* diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index 799fd40ed03a..0bcda9c51e9b 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c @@ -1488,8 +1488,6 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, skb_checksum_none_assert(skb); } - skb->dev = adapter->netdev; - buffer->skb = NULL; return skb; @@ -1653,6 +1651,9 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, length = skb->len; + if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) + skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); + if (vid != 0xffff) __vlan_hwaccel_put_tag(skb, vid); netif_receive_skb(skb); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index ad98f4d7919d..212c12193275 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1136,6 +1136,8 @@ static int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) { int ring; + u32 capab2; + struct qlcnic_host_rds_ring *rds_ring; if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) @@ -1146,6 +1148,12 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) if (qlcnic_set_eswitch_port_config(adapter)) return -EIO; + if (adapter->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { + capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2); + if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG) + adapter->flags |= QLCNIC_FW_LRO_MSS_CAP; + } + if (qlcnic_fw_create_ctx(adapter)) return -EIO; @@ -1215,6 +1223,7 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) qlcnic_napi_disable(adapter); qlcnic_fw_destroy_ctx(adapter); + adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP; qlcnic_reset_rx_buffers_list(adapter); qlcnic_release_tx_buffers(adapter); @@ -2024,6 +2033,7 @@ qlcnic_tx_pkt(struct qlcnic_adapter *adapter, vh = (struct vlan_ethhdr *)skb->data; flags = FLAGS_VLAN_TAGGED; vlan_tci = vh->h_vlan_TCI; + protocol = ntohs(vh->h_vlan_encapsulated_proto); } else if (vlan_tx_tag_present(skb)) { flags = FLAGS_VLAN_OOB; vlan_tci = vlan_tx_tag_get(skb); diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index 5a639df33f18..a131d7b5d2fe 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -18,13 +18,15 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "v1.00.00.30.00.00-01" +#define DRV_VERSION "v1.00.00.31" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ #define QLGE_VENDOR_ID 0x1077 #define QLGE_DEVICE_ID_8012 0x8012 #define QLGE_DEVICE_ID_8000 0x8000 +#define QLGE_MEZZ_SSYS_ID_068 0x0068 +#define QLGE_MEZZ_SSYS_ID_180 0x0180 #define MAX_CPUS 8 #define MAX_TX_RINGS MAX_CPUS #define MAX_RX_RINGS ((MAX_CPUS * 2) + 1) @@ -1397,7 +1399,6 @@ struct tx_ring { struct tx_ring_desc *q; /* descriptor list for the queue */ spinlock_t lock; atomic_t tx_count; /* counts down for every outstanding IO */ - atomic_t queue_stopped; /* Turns queue off when full. */ struct delayed_work tx_work; struct ql_adapter *qdev; u64 tx_packets; @@ -1535,6 +1536,14 @@ struct nic_stats { u64 rx_1024_to_1518_pkts; u64 rx_1519_to_max_pkts; u64 rx_len_err_pkts; + /* Receive Mac Err stats */ + u64 rx_code_err; + u64 rx_oversize_err; + u64 rx_undersize_err; + u64 rx_preamble_err; + u64 rx_frame_len_err; + u64 rx_crc_err; + u64 rx_err_count; /* * These stats come from offset 500h to 5C8h * in the XGMAC register. diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c index 8e2c2a74f3a5..6f316ab23257 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_ethtool.c @@ -35,10 +35,152 @@ #include "qlge.h" +struct ql_stats { + char stat_string[ETH_GSTRING_LEN]; + int sizeof_stat; + int stat_offset; +}; + +#define QL_SIZEOF(m) FIELD_SIZEOF(struct ql_adapter, m) +#define QL_OFF(m) offsetof(struct ql_adapter, m) + +static const struct ql_stats ql_gstrings_stats[] = { + {"tx_pkts", QL_SIZEOF(nic_stats.tx_pkts), QL_OFF(nic_stats.tx_pkts)}, + {"tx_bytes", QL_SIZEOF(nic_stats.tx_bytes), QL_OFF(nic_stats.tx_bytes)}, + {"tx_mcast_pkts", QL_SIZEOF(nic_stats.tx_mcast_pkts), + QL_OFF(nic_stats.tx_mcast_pkts)}, + {"tx_bcast_pkts", QL_SIZEOF(nic_stats.tx_bcast_pkts), + QL_OFF(nic_stats.tx_bcast_pkts)}, + {"tx_ucast_pkts", QL_SIZEOF(nic_stats.tx_ucast_pkts), + QL_OFF(nic_stats.tx_ucast_pkts)}, + {"tx_ctl_pkts", QL_SIZEOF(nic_stats.tx_ctl_pkts), + QL_OFF(nic_stats.tx_ctl_pkts)}, + {"tx_pause_pkts", QL_SIZEOF(nic_stats.tx_pause_pkts), + QL_OFF(nic_stats.tx_pause_pkts)}, + {"tx_64_pkts", QL_SIZEOF(nic_stats.tx_64_pkt), + QL_OFF(nic_stats.tx_64_pkt)}, + {"tx_65_to_127_pkts", QL_SIZEOF(nic_stats.tx_65_to_127_pkt), + QL_OFF(nic_stats.tx_65_to_127_pkt)}, + {"tx_128_to_255_pkts", QL_SIZEOF(nic_stats.tx_128_to_255_pkt), + QL_OFF(nic_stats.tx_128_to_255_pkt)}, + {"tx_256_511_pkts", QL_SIZEOF(nic_stats.tx_256_511_pkt), + QL_OFF(nic_stats.tx_256_511_pkt)}, + {"tx_512_to_1023_pkts", QL_SIZEOF(nic_stats.tx_512_to_1023_pkt), + QL_OFF(nic_stats.tx_512_to_1023_pkt)}, + {"tx_1024_to_1518_pkts", QL_SIZEOF(nic_stats.tx_1024_to_1518_pkt), + QL_OFF(nic_stats.tx_1024_to_1518_pkt)}, + {"tx_1519_to_max_pkts", QL_SIZEOF(nic_stats.tx_1519_to_max_pkt), + QL_OFF(nic_stats.tx_1519_to_max_pkt)}, + {"tx_undersize_pkts", QL_SIZEOF(nic_stats.tx_undersize_pkt), + QL_OFF(nic_stats.tx_undersize_pkt)}, + {"tx_oversize_pkts", QL_SIZEOF(nic_stats.tx_oversize_pkt), + QL_OFF(nic_stats.tx_oversize_pkt)}, + {"rx_bytes", QL_SIZEOF(nic_stats.rx_bytes), QL_OFF(nic_stats.rx_bytes)}, + {"rx_bytes_ok", QL_SIZEOF(nic_stats.rx_bytes_ok), + QL_OFF(nic_stats.rx_bytes_ok)}, + {"rx_pkts", QL_SIZEOF(nic_stats.rx_pkts), QL_OFF(nic_stats.rx_pkts)}, + {"rx_pkts_ok", QL_SIZEOF(nic_stats.rx_pkts_ok), + QL_OFF(nic_stats.rx_pkts_ok)}, + {"rx_bcast_pkts", QL_SIZEOF(nic_stats.rx_bcast_pkts), + QL_OFF(nic_stats.rx_bcast_pkts)}, + {"rx_mcast_pkts", QL_SIZEOF(nic_stats.rx_mcast_pkts), + QL_OFF(nic_stats.rx_mcast_pkts)}, + {"rx_ucast_pkts", QL_SIZEOF(nic_stats.rx_ucast_pkts), + QL_OFF(nic_stats.rx_ucast_pkts)}, + {"rx_undersize_pkts", QL_SIZEOF(nic_stats.rx_undersize_pkts), + QL_OFF(nic_stats.rx_undersize_pkts)}, + {"rx_oversize_pkts", QL_SIZEOF(nic_stats.rx_oversize_pkts), + QL_OFF(nic_stats.rx_oversize_pkts)}, + {"rx_jabber_pkts", QL_SIZEOF(nic_stats.rx_jabber_pkts), + QL_OFF(nic_stats.rx_jabber_pkts)}, + {"rx_undersize_fcerr_pkts", + QL_SIZEOF(nic_stats.rx_undersize_fcerr_pkts), + QL_OFF(nic_stats.rx_undersize_fcerr_pkts)}, + {"rx_drop_events", QL_SIZEOF(nic_stats.rx_drop_events), + QL_OFF(nic_stats.rx_drop_events)}, + {"rx_fcerr_pkts", QL_SIZEOF(nic_stats.rx_fcerr_pkts), + QL_OFF(nic_stats.rx_fcerr_pkts)}, + {"rx_align_err", QL_SIZEOF(nic_stats.rx_align_err), + QL_OFF(nic_stats.rx_align_err)}, + {"rx_symbol_err", QL_SIZEOF(nic_stats.rx_symbol_err), + QL_OFF(nic_stats.rx_symbol_err)}, + {"rx_mac_err", QL_SIZEOF(nic_stats.rx_mac_err), + QL_OFF(nic_stats.rx_mac_err)}, + {"rx_ctl_pkts", QL_SIZEOF(nic_stats.rx_ctl_pkts), + QL_OFF(nic_stats.rx_ctl_pkts)}, + {"rx_pause_pkts", QL_SIZEOF(nic_stats.rx_pause_pkts), + QL_OFF(nic_stats.rx_pause_pkts)}, + {"rx_64_pkts", QL_SIZEOF(nic_stats.rx_64_pkts), + QL_OFF(nic_stats.rx_64_pkts)}, + {"rx_65_to_127_pkts", QL_SIZEOF(nic_stats.rx_65_to_127_pkts), + QL_OFF(nic_stats.rx_65_to_127_pkts)}, + {"rx_128_255_pkts", QL_SIZEOF(nic_stats.rx_128_255_pkts), + QL_OFF(nic_stats.rx_128_255_pkts)}, + {"rx_256_511_pkts", QL_SIZEOF(nic_stats.rx_256_511_pkts), + QL_OFF(nic_stats.rx_256_511_pkts)}, + {"rx_512_to_1023_pkts", QL_SIZEOF(nic_stats.rx_512_to_1023_pkts), + QL_OFF(nic_stats.rx_512_to_1023_pkts)}, + {"rx_1024_to_1518_pkts", QL_SIZEOF(nic_stats.rx_1024_to_1518_pkts), + QL_OFF(nic_stats.rx_1024_to_1518_pkts)}, + {"rx_1519_to_max_pkts", QL_SIZEOF(nic_stats.rx_1519_to_max_pkts), + QL_OFF(nic_stats.rx_1519_to_max_pkts)}, + {"rx_len_err_pkts", QL_SIZEOF(nic_stats.rx_len_err_pkts), + QL_OFF(nic_stats.rx_len_err_pkts)}, + {"rx_code_err", QL_SIZEOF(nic_stats.rx_code_err), + QL_OFF(nic_stats.rx_code_err)}, + {"rx_oversize_err", QL_SIZEOF(nic_stats.rx_oversize_err), + QL_OFF(nic_stats.rx_oversize_err)}, + {"rx_undersize_err", QL_SIZEOF(nic_stats.rx_undersize_err), + QL_OFF(nic_stats.rx_undersize_err)}, + {"rx_preamble_err", QL_SIZEOF(nic_stats.rx_preamble_err), + QL_OFF(nic_stats.rx_preamble_err)}, + {"rx_frame_len_err", QL_SIZEOF(nic_stats.rx_frame_len_err), + QL_OFF(nic_stats.rx_frame_len_err)}, + {"rx_crc_err", QL_SIZEOF(nic_stats.rx_crc_err), + QL_OFF(nic_stats.rx_crc_err)}, + {"rx_err_count", QL_SIZEOF(nic_stats.rx_err_count), + QL_OFF(nic_stats.rx_err_count)}, + {"tx_cbfc_pause_frames0", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames0), + QL_OFF(nic_stats.tx_cbfc_pause_frames0)}, + {"tx_cbfc_pause_frames1", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames1), + QL_OFF(nic_stats.tx_cbfc_pause_frames1)}, + {"tx_cbfc_pause_frames2", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames2), + QL_OFF(nic_stats.tx_cbfc_pause_frames2)}, + {"tx_cbfc_pause_frames3", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames3), + QL_OFF(nic_stats.tx_cbfc_pause_frames3)}, + {"tx_cbfc_pause_frames4", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames4), + QL_OFF(nic_stats.tx_cbfc_pause_frames4)}, + {"tx_cbfc_pause_frames5", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames5), + QL_OFF(nic_stats.tx_cbfc_pause_frames5)}, + {"tx_cbfc_pause_frames6", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames6), + QL_OFF(nic_stats.tx_cbfc_pause_frames6)}, + {"tx_cbfc_pause_frames7", QL_SIZEOF(nic_stats.tx_cbfc_pause_frames7), + QL_OFF(nic_stats.tx_cbfc_pause_frames7)}, + {"rx_cbfc_pause_frames0", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames0), + QL_OFF(nic_stats.rx_cbfc_pause_frames0)}, + {"rx_cbfc_pause_frames1", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames1), + QL_OFF(nic_stats.rx_cbfc_pause_frames1)}, + {"rx_cbfc_pause_frames2", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames2), + QL_OFF(nic_stats.rx_cbfc_pause_frames2)}, + {"rx_cbfc_pause_frames3", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames3), + QL_OFF(nic_stats.rx_cbfc_pause_frames3)}, + {"rx_cbfc_pause_frames4", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames4), + QL_OFF(nic_stats.rx_cbfc_pause_frames4)}, + {"rx_cbfc_pause_frames5", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames5), + QL_OFF(nic_stats.rx_cbfc_pause_frames5)}, + {"rx_cbfc_pause_frames6", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames6), + QL_OFF(nic_stats.rx_cbfc_pause_frames6)}, + {"rx_cbfc_pause_frames7", QL_SIZEOF(nic_stats.rx_cbfc_pause_frames7), + QL_OFF(nic_stats.rx_cbfc_pause_frames7)}, + {"rx_nic_fifo_drop", QL_SIZEOF(nic_stats.rx_nic_fifo_drop), + QL_OFF(nic_stats.rx_nic_fifo_drop)}, +}; + static const char ql_gstrings_test[][ETH_GSTRING_LEN] = { "Loopback test (offline)" }; #define QLGE_TEST_LEN (sizeof(ql_gstrings_test) / ETH_GSTRING_LEN) +#define QLGE_STATS_LEN ARRAY_SIZE(ql_gstrings_stats) static int ql_update_ring_coalescing(struct ql_adapter *qdev) { @@ -183,73 +325,19 @@ quit: QL_DUMP_STAT(qdev); } -static char ql_stats_str_arr[][ETH_GSTRING_LEN] = { - {"tx_pkts"}, - {"tx_bytes"}, - {"tx_mcast_pkts"}, - {"tx_bcast_pkts"}, - {"tx_ucast_pkts"}, - {"tx_ctl_pkts"}, - {"tx_pause_pkts"}, - {"tx_64_pkts"}, - {"tx_65_to_127_pkts"}, - {"tx_128_to_255_pkts"}, - {"tx_256_511_pkts"}, - {"tx_512_to_1023_pkts"}, - {"tx_1024_to_1518_pkts"}, - {"tx_1519_to_max_pkts"}, - {"tx_undersize_pkts"}, - {"tx_oversize_pkts"}, - {"rx_bytes"}, - {"rx_bytes_ok"}, - {"rx_pkts"}, - {"rx_pkts_ok"}, - {"rx_bcast_pkts"}, - {"rx_mcast_pkts"}, - {"rx_ucast_pkts"}, - {"rx_undersize_pkts"}, - {"rx_oversize_pkts"}, - {"rx_jabber_pkts"}, - {"rx_undersize_fcerr_pkts"}, - {"rx_drop_events"}, - {"rx_fcerr_pkts"}, - {"rx_align_err"}, - {"rx_symbol_err"}, - {"rx_mac_err"}, - {"rx_ctl_pkts"}, - {"rx_pause_pkts"}, - {"rx_64_pkts"}, - {"rx_65_to_127_pkts"}, - {"rx_128_255_pkts"}, - {"rx_256_511_pkts"}, - {"rx_512_to_1023_pkts"}, - {"rx_1024_to_1518_pkts"}, - {"rx_1519_to_max_pkts"}, - {"rx_len_err_pkts"}, - {"tx_cbfc_pause_frames0"}, - {"tx_cbfc_pause_frames1"}, - {"tx_cbfc_pause_frames2"}, - {"tx_cbfc_pause_frames3"}, - {"tx_cbfc_pause_frames4"}, - {"tx_cbfc_pause_frames5"}, - {"tx_cbfc_pause_frames6"}, - {"tx_cbfc_pause_frames7"}, - {"rx_cbfc_pause_frames0"}, - {"rx_cbfc_pause_frames1"}, - {"rx_cbfc_pause_frames2"}, - {"rx_cbfc_pause_frames3"}, - {"rx_cbfc_pause_frames4"}, - {"rx_cbfc_pause_frames5"}, - {"rx_cbfc_pause_frames6"}, - {"rx_cbfc_pause_frames7"}, - {"rx_nic_fifo_drop"}, -}; - static void ql_get_strings(struct net_device *dev, u32 stringset, u8 *buf) { + int index; switch (stringset) { + case ETH_SS_TEST: + memcpy(buf, *ql_gstrings_test, QLGE_TEST_LEN * ETH_GSTRING_LEN); + break; case ETH_SS_STATS: - memcpy(buf, ql_stats_str_arr, sizeof(ql_stats_str_arr)); + for (index = 0; index < QLGE_STATS_LEN; index++) { + memcpy(buf + index * ETH_GSTRING_LEN, + ql_gstrings_stats[index].stat_string, + ETH_GSTRING_LEN); + } break; } } @@ -260,7 +348,7 @@ static int ql_get_sset_count(struct net_device *dev, int sset) case ETH_SS_TEST: return QLGE_TEST_LEN; case ETH_SS_STATS: - return ARRAY_SIZE(ql_stats_str_arr); + return QLGE_STATS_LEN; default: return -EOPNOTSUPP; } @@ -271,69 +359,17 @@ ql_get_ethtool_stats(struct net_device *ndev, struct ethtool_stats *stats, u64 *data) { struct ql_adapter *qdev = netdev_priv(ndev); - struct nic_stats *s = &qdev->nic_stats; + int index, length; + length = QLGE_STATS_LEN; ql_update_stats(qdev); - *data++ = s->tx_pkts; - *data++ = s->tx_bytes; - *data++ = s->tx_mcast_pkts; - *data++ = s->tx_bcast_pkts; - *data++ = s->tx_ucast_pkts; - *data++ = s->tx_ctl_pkts; - *data++ = s->tx_pause_pkts; - *data++ = s->tx_64_pkt; - *data++ = s->tx_65_to_127_pkt; - *data++ = s->tx_128_to_255_pkt; - *data++ = s->tx_256_511_pkt; - *data++ = s->tx_512_to_1023_pkt; - *data++ = s->tx_1024_to_1518_pkt; - *data++ = s->tx_1519_to_max_pkt; - *data++ = s->tx_undersize_pkt; - *data++ = s->tx_oversize_pkt; - *data++ = s->rx_bytes; - *data++ = s->rx_bytes_ok; - *data++ = s->rx_pkts; - *data++ = s->rx_pkts_ok; - *data++ = s->rx_bcast_pkts; - *data++ = s->rx_mcast_pkts; - *data++ = s->rx_ucast_pkts; - *data++ = s->rx_undersize_pkts; - *data++ = s->rx_oversize_pkts; - *data++ = s->rx_jabber_pkts; - *data++ = s->rx_undersize_fcerr_pkts; - *data++ = s->rx_drop_events; - *data++ = s->rx_fcerr_pkts; - *data++ = s->rx_align_err; - *data++ = s->rx_symbol_err; - *data++ = s->rx_mac_err; - *data++ = s->rx_ctl_pkts; - *data++ = s->rx_pause_pkts; - *data++ = s->rx_64_pkts; - *data++ = s->rx_65_to_127_pkts; - *data++ = s->rx_128_255_pkts; - *data++ = s->rx_256_511_pkts; - *data++ = s->rx_512_to_1023_pkts; - *data++ = s->rx_1024_to_1518_pkts; - *data++ = s->rx_1519_to_max_pkts; - *data++ = s->rx_len_err_pkts; - *data++ = s->tx_cbfc_pause_frames0; - *data++ = s->tx_cbfc_pause_frames1; - *data++ = s->tx_cbfc_pause_frames2; - *data++ = s->tx_cbfc_pause_frames3; - *data++ = s->tx_cbfc_pause_frames4; - *data++ = s->tx_cbfc_pause_frames5; - *data++ = s->tx_cbfc_pause_frames6; - *data++ = s->tx_cbfc_pause_frames7; - *data++ = s->rx_cbfc_pause_frames0; - *data++ = s->rx_cbfc_pause_frames1; - *data++ = s->rx_cbfc_pause_frames2; - *data++ = s->rx_cbfc_pause_frames3; - *data++ = s->rx_cbfc_pause_frames4; - *data++ = s->rx_cbfc_pause_frames5; - *data++ = s->rx_cbfc_pause_frames6; - *data++ = s->rx_cbfc_pause_frames7; - *data++ = s->rx_nic_fifo_drop; + for (index = 0; index < length; index++) { + char *p = (char *)qdev + + ql_gstrings_stats[index].stat_offset; + *data++ = (ql_gstrings_stats[index].sizeof_stat == + sizeof(u64)) ? *(u64 *)p : (*(u32 *)p); + } } static int ql_get_settings(struct net_device *ndev, @@ -388,30 +424,33 @@ static void ql_get_drvinfo(struct net_device *ndev, static void ql_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) { struct ql_adapter *qdev = netdev_priv(ndev); - /* What we support. */ - wol->supported = WAKE_MAGIC; - /* What we've currently got set. */ - wol->wolopts = qdev->wol; + unsigned short ssys_dev = qdev->pdev->subsystem_device; + + /* WOL is only supported for mezz card. */ + if (ssys_dev == QLGE_MEZZ_SSYS_ID_068 || + ssys_dev == QLGE_MEZZ_SSYS_ID_180) { + wol->supported = WAKE_MAGIC; + wol->wolopts = qdev->wol; + } } static int ql_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol) { struct ql_adapter *qdev = netdev_priv(ndev); - int status; + unsigned short ssys_dev = qdev->pdev->subsystem_device; + /* WOL is only supported for mezz card. */ + if (ssys_dev != QLGE_MEZZ_SSYS_ID_068 && + ssys_dev != QLGE_MEZZ_SSYS_ID_180) { + netif_info(qdev, drv, qdev->ndev, + "WOL is only supported for mezz card\n"); + return -EOPNOTSUPP; + } if (wol->wolopts & ~WAKE_MAGIC) return -EINVAL; qdev->wol = wol->wolopts; netif_info(qdev, drv, qdev->ndev, "Set wol option 0x%x\n", qdev->wol); - if (!qdev->wol) { - u32 wol = 0; - status = ql_mb_wol_mode(qdev, wol); - netif_err(qdev, drv, qdev->ndev, "WOL %s (wol code 0x%x)\n", - status == 0 ? "cleared successfully" : "clear failed", - wol); - } - return 0; } @@ -528,6 +567,8 @@ static void ql_self_test(struct net_device *ndev, { struct ql_adapter *qdev = netdev_priv(ndev); + memset(data, 0, sizeof(u64) * QLGE_TEST_LEN); + if (netif_running(ndev)) { set_bit(QL_SELFTEST, &qdev->flags); if (eth_test->flags == ETH_TEST_FL_OFFLINE) { diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 09d8d33171df..b53a3b60b648 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c @@ -1433,6 +1433,36 @@ map_error: return NETDEV_TX_BUSY; } +/* Categorizing receive firmware frame errors */ +static void ql_categorize_rx_err(struct ql_adapter *qdev, u8 rx_err) +{ + struct nic_stats *stats = &qdev->nic_stats; + + stats->rx_err_count++; + + switch (rx_err & IB_MAC_IOCB_RSP_ERR_MASK) { + case IB_MAC_IOCB_RSP_ERR_CODE_ERR: + stats->rx_code_err++; + break; + case IB_MAC_IOCB_RSP_ERR_OVERSIZE: + stats->rx_oversize_err++; + break; + case IB_MAC_IOCB_RSP_ERR_UNDERSIZE: + stats->rx_undersize_err++; + break; + case IB_MAC_IOCB_RSP_ERR_PREAMBLE: + stats->rx_preamble_err++; + break; + case IB_MAC_IOCB_RSP_ERR_FRAME_LEN: + stats->rx_frame_len_err++; + break; + case IB_MAC_IOCB_RSP_ERR_CRC: + stats->rx_crc_err++; + default: + break; + } +} + /* Process an inbound completion from an rx ring. */ static void ql_process_mac_rx_gro_page(struct ql_adapter *qdev, struct rx_ring *rx_ring, @@ -1499,15 +1529,6 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, addr = lbq_desc->p.pg_chunk.va; prefetch(addr); - - /* Frame error, so drop the packet. */ - if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - netif_info(qdev, drv, qdev->ndev, - "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); - rx_ring->rx_errors++; - goto err_out; - } - /* The max framesize filter on this chip is set higher than * MTU since FCoE uses 2k frames. */ @@ -1546,7 +1567,7 @@ static void ql_process_mac_rx_page(struct ql_adapter *qdev, struct iphdr *iph = (struct iphdr *) ((u8 *)addr + ETH_HLEN); if (!(iph->frag_off & - cpu_to_be16(IP_MF|IP_OFFSET))) { + htons(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1593,15 +1614,6 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, memcpy(skb_put(new_skb, length), skb->data, length); skb = new_skb; - /* Frame error, so drop the packet. */ - if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - netif_info(qdev, drv, qdev->ndev, - "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); - dev_kfree_skb_any(skb); - rx_ring->rx_errors++; - return; - } - /* loopback self test for ethtool */ if (test_bit(QL_SELFTEST, &qdev->flags)) { ql_check_lb_frame(qdev, skb); @@ -1619,7 +1631,6 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, } prefetch(skb->data); - skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "%s Multicast.\n", @@ -1654,7 +1665,7 @@ static void ql_process_mac_rx_skb(struct ql_adapter *qdev, /* Unfragmented ipv4 UDP frame. */ struct iphdr *iph = (struct iphdr *) skb->data; if (!(iph->frag_off & - ntohs(IP_MF|IP_OFFSET))) { + htons(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, @@ -1908,15 +1919,6 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, return; } - /* Frame error, so drop the packet. */ - if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { - netif_info(qdev, drv, qdev->ndev, - "Receive error, flags2 = 0x%x\n", ib_mac_rsp->flags2); - dev_kfree_skb_any(skb); - rx_ring->rx_errors++; - return; - } - /* The max framesize filter on this chip is set higher than * MTU since FCoE uses 2k frames. */ @@ -1934,7 +1936,6 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, } prefetch(skb->data); - skb->dev = ndev; if (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) { netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "%s Multicast.\n", (ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_M_MASK) == @@ -1968,7 +1969,7 @@ static void ql_process_mac_split_rx_intr(struct ql_adapter *qdev, /* Unfragmented ipv4 UDP frame. */ struct iphdr *iph = (struct iphdr *) skb->data; if (!(iph->frag_off & - ntohs(IP_MF|IP_OFFSET))) { + htons(IP_MF|IP_OFFSET))) { skb->ip_summed = CHECKSUM_UNNECESSARY; netif_printk(qdev, rx_status, KERN_DEBUG, qdev->ndev, "TCP checksum done!\n"); @@ -1999,6 +2000,12 @@ static unsigned long ql_process_mac_rx_intr(struct ql_adapter *qdev, QL_DUMP_IB_MAC_RSP(ib_mac_rsp); + /* Frame error, so drop the packet. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) { + ql_categorize_rx_err(qdev, ib_mac_rsp->flags2); + return (unsigned long)length; + } + if (ib_mac_rsp->flags4 & IB_MAC_IOCB_RSP_HV) { /* The data and headers are split into * separate buffers. @@ -2173,8 +2180,7 @@ static int ql_clean_outbound_rx_ring(struct rx_ring *rx_ring) ql_write_cq_idx(rx_ring); tx_ring = &qdev->tx_ring[net_rsp->txq_idx]; if (__netif_subqueue_stopped(qdev->ndev, tx_ring->wq_id)) { - if (atomic_read(&tx_ring->queue_stopped) && - (atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) + if ((atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) /* * The queue got stopped because the tx_ring was full. * Wake it up, because it's now at least 25% empty. @@ -2558,10 +2564,9 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { netif_info(qdev, tx_queued, qdev->ndev, - "%s: shutting down tx queue %d du to lack of resources.\n", + "%s: BUG! shutting down tx queue %d due to lack of resources.\n", __func__, tx_ring_idx); netif_stop_subqueue(ndev, tx_ring->wq_id); - atomic_inc(&tx_ring->queue_stopped); tx_ring->tx_errors++; return NETDEV_TX_BUSY; } @@ -2612,6 +2617,16 @@ static netdev_tx_t qlge_send(struct sk_buff *skb, struct net_device *ndev) tx_ring->prod_idx, skb->len); atomic_dec(&tx_ring->tx_count); + + if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { + netif_stop_subqueue(ndev, tx_ring->wq_id); + if ((atomic_read(&tx_ring->tx_count) > (tx_ring->wq_len / 4))) + /* + * The queue got stopped because the tx_ring was full. + * Wake it up, because it's now at least 25% empty. + */ + netif_wake_subqueue(qdev->ndev, tx_ring->wq_id); + } return NETDEV_TX_OK; } @@ -2680,7 +2695,6 @@ static void ql_init_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring) tx_ring_desc++; } atomic_set(&tx_ring->tx_count, tx_ring->wq_len); - atomic_set(&tx_ring->queue_stopped, 0); } static void ql_free_tx_resources(struct ql_adapter *qdev, @@ -2703,10 +2717,9 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev, &tx_ring->wq_base_dma); if ((tx_ring->wq_base == NULL) || - tx_ring->wq_base_dma & WQ_ADDR_ALIGN) { - netif_err(qdev, ifup, qdev->ndev, "tx_ring alloc failed.\n"); - return -ENOMEM; - } + tx_ring->wq_base_dma & WQ_ADDR_ALIGN) + goto pci_alloc_err; + tx_ring->q = kmalloc(tx_ring->wq_len * sizeof(struct tx_ring_desc), GFP_KERNEL); if (tx_ring->q == NULL) @@ -2716,6 +2729,9 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev, err: pci_free_consistent(qdev->pdev, tx_ring->wq_size, tx_ring->wq_base, tx_ring->wq_base_dma); + tx_ring->wq_base = NULL; +pci_alloc_err: + netif_err(qdev, ifup, qdev->ndev, "tx_ring alloc failed.\n"); return -ENOMEM; } @@ -4649,7 +4665,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, int err = 0; ndev = alloc_etherdev_mq(sizeof(struct ql_adapter), - min(MAX_CPUS, (int)num_online_cpus())); + min(MAX_CPUS, netif_get_num_default_rss_queues())); if (!ndev) return -ENOMEM; @@ -4666,6 +4682,7 @@ static int __devinit qlge_probe(struct pci_dev *pdev, NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; + ndev->vlan_features = ndev->hw_features; if (test_bit(QL_DMA64, &qdev->flags)) ndev->features |= NETIF_F_HIGHDMA; |