diff options
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 73 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 46 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 64 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 46 |
5 files changed, 174 insertions, 61 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index cbdec2536da6..74aa14811977 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -74,6 +74,9 @@ static inline char *nic_name(struct pci_dev *pdev) /* Number of bytes of an RX frame that are copied to skb->data */ #define BE_HDR_LEN ((u16) 64) +/* allocate extra space to allow tunneling decapsulation without head reallocation */ +#define BE_RX_SKB_ALLOC_SIZE (BE_HDR_LEN + 64) + #define BE_MAX_JUMBO_FRAME_SIZE 9018 #define BE_MIN_MTU 256 @@ -262,7 +265,6 @@ struct be_drv_stats { u32 rx_drops_no_erx_descr; u32 rx_drops_no_tpre_descr; u32 rx_drops_too_many_frags; - u32 rx_drops_invalid_ring; u32 forwarded_packets; u32 rx_drops_mtu; u32 rx_crc_errors; @@ -273,7 +275,7 @@ struct be_drv_stats { u32 rx_in_range_errors; u32 rx_out_range_errors; u32 rx_frame_too_long; - u32 rx_address_match_errors; + u32 rx_address_mismatch_drops; u32 rx_dropped_too_small; u32 rx_dropped_too_short; u32 rx_dropped_header_too_small; diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 0fcb45624796..29dff7de66b6 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1257,11 +1257,13 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u8 *mac_speed, } req = embedded_payload(wrb); + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); + if (adapter->generation == BE_GEN3 || lancer_chip(adapter)) req->hdr.version = 1; - be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req), wrb, NULL); + req->hdr.domain = dom; status = be_mcc_notify_wait(adapter); if (!status) { @@ -2298,52 +2300,81 @@ err: /* Uses synchronous MCCQ */ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, - u32 *pmac_id) + bool *pmac_id_active, u32 *pmac_id, u8 *mac) { struct be_mcc_wrb *wrb; struct be_cmd_req_get_mac_list *req; int status; int mac_count; + struct be_dma_mem get_mac_list_cmd; + int i; + + memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem)); + get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list); + get_mac_list_cmd.va = pci_alloc_consistent(adapter->pdev, + get_mac_list_cmd.size, + &get_mac_list_cmd.dma); + + if (!get_mac_list_cmd.va) { + dev_err(&adapter->pdev->dev, + "Memory allocation failure during GET_MAC_LIST\n"); + return -ENOMEM; + } spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); if (!wrb) { status = -EBUSY; - goto err; + goto out; } - req = embedded_payload(wrb); + + req = get_mac_list_cmd.va; be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_GET_MAC_LIST, sizeof(*req), - wrb, NULL); + wrb, &get_mac_list_cmd); req->hdr.domain = domain; + req->mac_type = MAC_ADDRESS_TYPE_NETWORK; + req->perm_override = 1; status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_get_mac_list *resp = - embedded_payload(wrb); - int i; - u8 *ctxt = &resp->context[0][0]; - status = -EIO; - mac_count = resp->mac_count; - be_dws_le_to_cpu(&resp->context, sizeof(resp->context)); + get_mac_list_cmd.va; + mac_count = resp->true_mac_count + resp->pseudo_mac_count; + /* Mac list returned could contain one or more active mac_ids + * or one or more pseudo permanant mac addresses. If an active + * mac_id is present, return first active mac_id found + */ for (i = 0; i < mac_count; i++) { - if (!AMAP_GET_BITS(struct amap_get_mac_list_context, - act, ctxt)) { - *pmac_id = AMAP_GET_BITS - (struct amap_get_mac_list_context, - macid, ctxt); - status = 0; - break; + struct get_list_macaddr *mac_entry; + u16 mac_addr_size; + u32 mac_id; + + mac_entry = &resp->macaddr_list[i]; + mac_addr_size = le16_to_cpu(mac_entry->mac_addr_size); + /* mac_id is a 32 bit value and mac_addr size + * is 6 bytes + */ + if (mac_addr_size == sizeof(u32)) { + *pmac_id_active = true; + mac_id = mac_entry->mac_addr_id.s_mac_id.mac_id; + *pmac_id = le32_to_cpu(mac_id); + goto out; } - ctxt += sizeof(struct amap_get_mac_list_context) / 8; } + /* If no active mac_id found, return first pseudo mac addr */ + *pmac_id_active = false; + memcpy(mac, resp->macaddr_list[0].mac_addr_id.macaddr, + ETH_ALEN); } -err: +out: spin_unlock_bh(&adapter->mcc_lock); + pci_free_consistent(adapter->pdev, get_mac_list_cmd.size, + get_mac_list_cmd.va, get_mac_list_cmd.dma); return status; } diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index dca89249088f..5bb66c80f05e 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -592,8 +592,8 @@ struct be_port_rxf_stats_v0 { u32 rx_in_range_errors; /* dword 10*/ u32 rx_out_range_errors; /* dword 11*/ u32 rx_frame_too_long; /* dword 12*/ - u32 rx_address_match_errors; /* dword 13*/ - u32 rx_vlan_mismatch; /* dword 14*/ + u32 rx_address_mismatch_drops; /* dword 13*/ + u32 rx_vlan_mismatch_drops; /* dword 14*/ u32 rx_dropped_too_small; /* dword 15*/ u32 rx_dropped_too_short; /* dword 16*/ u32 rx_dropped_header_too_small; /* dword 17*/ @@ -799,8 +799,8 @@ struct lancer_pport_stats { u32 rx_control_frames_unknown_opcode_hi; u32 rx_in_range_errors; u32 rx_out_of_range_errors; - u32 rx_address_match_errors; - u32 rx_vlan_mismatch_errors; + u32 rx_address_mismatch_drops; + u32 rx_vlan_mismatch_drops; u32 rx_dropped_too_small; u32 rx_dropped_too_short; u32 rx_dropped_header_too_small; @@ -1346,22 +1346,36 @@ struct be_cmd_resp_set_func_cap { /******************** GET/SET_MACLIST **************************/ #define BE_MAX_MAC 64 -struct amap_get_mac_list_context { - u8 macid[31]; - u8 act; -} __packed; - struct be_cmd_req_get_mac_list { struct be_cmd_req_hdr hdr; - u32 rsvd; + u8 mac_type; + u8 perm_override; + u16 iface_id; + u32 mac_id; + u32 rsvd[3]; +} __packed; + +struct get_list_macaddr { + u16 mac_addr_size; + union { + u8 macaddr[6]; + struct { + u8 rsvd[2]; + u32 mac_id; + } __packed s_mac_id; + } __packed mac_addr_id; } __packed; struct be_cmd_resp_get_mac_list { struct be_cmd_resp_hdr hdr; - u8 mac_count; - u8 rsvd1; - u16 rsvd2; - u8 context[sizeof(struct amap_get_mac_list_context) / 8][BE_MAX_MAC]; + struct get_list_macaddr fd_macaddr; /* Factory default mac */ + struct get_list_macaddr macid_macaddr; /* soft mac */ + u8 true_mac_count; + u8 pseudo_mac_count; + u8 mac_list_size; + u8 rsvd; + /* perm override mac */ + struct get_list_macaddr macaddr_list[BE_MAX_MAC]; } __packed; struct be_cmd_req_set_mac_list { @@ -1384,7 +1398,7 @@ struct be_port_rxf_stats_v1 { u32 rx_in_range_errors; u32 rx_out_range_errors; u32 rx_frame_too_long; - u32 rx_address_match_errors; + u32 rx_address_mismatch_drops; u32 rx_dropped_too_small; u32 rx_dropped_too_short; u32 rx_dropped_header_too_small; @@ -1575,7 +1589,7 @@ extern int be_cmd_req_native_mode(struct be_adapter *adapter); extern int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size); extern void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf); extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u32 domain, - u32 *pmac_id); + bool *pmac_id_active, u32 *pmac_id, u8 *mac); extern int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count, u32 domain); diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 802e5ddef8a8..dc1383c396c0 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -42,15 +42,42 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(rx_alignment_symbol_errors)}, {DRVSTAT_INFO(rx_pause_frames)}, {DRVSTAT_INFO(rx_control_frames)}, + /* Received packets dropped when the Ethernet length field + * is not equal to the actual Ethernet data length. + */ {DRVSTAT_INFO(rx_in_range_errors)}, + /* Received packets dropped when their length field is >= 1501 bytes + * and <= 1535 bytes. + */ {DRVSTAT_INFO(rx_out_range_errors)}, + /* Received packets dropped when they are longer than 9216 bytes */ {DRVSTAT_INFO(rx_frame_too_long)}, - {DRVSTAT_INFO(rx_address_match_errors)}, + /* Received packets dropped when they don't pass the unicast or + * multicast address filtering. + */ + {DRVSTAT_INFO(rx_address_mismatch_drops)}, + /* Received packets dropped when IP packet length field is less than + * the IP header length field. + */ {DRVSTAT_INFO(rx_dropped_too_small)}, + /* Received packets dropped when IP length field is greater than + * the actual packet length. + */ {DRVSTAT_INFO(rx_dropped_too_short)}, + /* Received packets dropped when the IP header length field is less + * than 5. + */ {DRVSTAT_INFO(rx_dropped_header_too_small)}, + /* Received packets dropped when the TCP header length field is less + * than 5 or the TCP header length + IP header length is more + * than IP packet length. + */ {DRVSTAT_INFO(rx_dropped_tcp_length)}, {DRVSTAT_INFO(rx_dropped_runt)}, + /* Number of received packets dropped when a fifo for descriptors going + * into the packet demux block overflows. In normal operation, this + * fifo must never overflow. + */ {DRVSTAT_INFO(rxpp_fifo_overflow_drop)}, {DRVSTAT_INFO(rx_input_fifo_overflow_drop)}, {DRVSTAT_INFO(rx_ip_checksum_errs)}, @@ -59,16 +86,35 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(tx_pauseframes)}, {DRVSTAT_INFO(tx_controlframes)}, {DRVSTAT_INFO(rx_priority_pause_frames)}, + /* Received packets dropped when an internal fifo going into + * main packet buffer tank (PMEM) overflows. + */ {DRVSTAT_INFO(pmem_fifo_overflow_drop)}, {DRVSTAT_INFO(jabber_events)}, + /* Received packets dropped due to lack of available HW packet buffers + * used to temporarily hold the received packets. + */ {DRVSTAT_INFO(rx_drops_no_pbuf)}, - {DRVSTAT_INFO(rx_drops_no_txpb)}, + /* Received packets dropped due to input receive buffer + * descriptor fifo overflowing. + */ {DRVSTAT_INFO(rx_drops_no_erx_descr)}, + /* Packets dropped because the internal FIFO to the offloaded TCP + * receive processing block is full. This could happen only for + * offloaded iSCSI or FCoE trarffic. + */ {DRVSTAT_INFO(rx_drops_no_tpre_descr)}, + /* Received packets dropped when they need more than 8 + * receive buffers. This cannot happen as the driver configures + * 2048 byte receive buffers. + */ {DRVSTAT_INFO(rx_drops_too_many_frags)}, - {DRVSTAT_INFO(rx_drops_invalid_ring)}, {DRVSTAT_INFO(forwarded_packets)}, + /* Received packets dropped when the frame length + * is more than 9018 bytes + */ {DRVSTAT_INFO(rx_drops_mtu)}, + /* Number of packets dropped due to random early drop function */ {DRVSTAT_INFO(eth_red_drops)}, {DRVSTAT_INFO(be_on_die_temperature)} }; @@ -84,8 +130,15 @@ static const struct be_ethtool_stat et_rx_stats[] = { {DRVSTAT_RX_INFO(rx_events)}, {DRVSTAT_RX_INFO(rx_compl)}, {DRVSTAT_RX_INFO(rx_mcast_pkts)}, + /* Number of page allocation failures while posting receive buffers + * to HW. + */ {DRVSTAT_RX_INFO(rx_post_fail)}, + /* Recevied packets dropped due to skb allocation failure */ {DRVSTAT_RX_INFO(rx_drops_no_skbs)}, + /* Received packets dropped due to lack of available fetched buffers + * posted by the driver. + */ {DRVSTAT_RX_INFO(rx_drops_no_frags)} }; #define ETHTOOL_RXSTATS_NUM (ARRAY_SIZE(et_rx_stats)) @@ -97,9 +150,14 @@ static const struct be_ethtool_stat et_tx_stats[] = { {DRVSTAT_TX_INFO(tx_compl)}, /* If moving this member see above note */ {DRVSTAT_TX_INFO(tx_bytes)}, {DRVSTAT_TX_INFO(tx_pkts)}, + /* Number of skbs queued for trasmission by the driver */ {DRVSTAT_TX_INFO(tx_reqs)}, + /* Number of TX work request blocks DMAed to HW */ {DRVSTAT_TX_INFO(tx_wrbs)}, {DRVSTAT_TX_INFO(tx_compl)}, + /* Number of times the TX queue was stopped due to lack + * of spaces in the TXQ. + */ {DRVSTAT_TX_INFO(tx_stops)} }; #define ETHTOOL_TXSTATS_NUM (ARRAY_SIZE(et_tx_stats)) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index e703d64434f8..780498784d8e 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -286,7 +286,9 @@ static void populate_be2_stats(struct be_adapter *adapter) drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow; drvs->rx_dropped_header_too_small = port_stats->rx_dropped_header_too_small; - drvs->rx_address_match_errors = port_stats->rx_address_match_errors; + drvs->rx_address_mismatch_drops = + port_stats->rx_address_mismatch_drops + + port_stats->rx_vlan_mismatch_drops; drvs->rx_alignment_symbol_errors = port_stats->rx_alignment_symbol_errors; @@ -298,9 +300,7 @@ static void populate_be2_stats(struct be_adapter *adapter) else drvs->jabber_events = rxf_stats->port0_jabber_events; drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; - drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; - drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; drvs->forwarded_packets = rxf_stats->forwarded_packets; drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; @@ -337,7 +337,7 @@ static void populate_be3_stats(struct be_adapter *adapter) port_stats->rx_dropped_header_too_small; drvs->rx_input_fifo_overflow_drop = port_stats->rx_input_fifo_overflow_drop; - drvs->rx_address_match_errors = port_stats->rx_address_match_errors; + drvs->rx_address_mismatch_drops = port_stats->rx_address_mismatch_drops; drvs->rx_alignment_symbol_errors = port_stats->rx_alignment_symbol_errors; drvs->rxpp_fifo_overflow_drop = port_stats->rxpp_fifo_overflow_drop; @@ -345,9 +345,7 @@ static void populate_be3_stats(struct be_adapter *adapter) drvs->tx_controlframes = port_stats->tx_controlframes; drvs->jabber_events = port_stats->jabber_events; drvs->rx_drops_no_pbuf = rxf_stats->rx_drops_no_pbuf; - drvs->rx_drops_no_txpb = rxf_stats->rx_drops_no_txpb; drvs->rx_drops_no_erx_descr = rxf_stats->rx_drops_no_erx_descr; - drvs->rx_drops_invalid_ring = rxf_stats->rx_drops_invalid_ring; drvs->forwarded_packets = rxf_stats->forwarded_packets; drvs->rx_drops_mtu = rxf_stats->rx_drops_mtu; drvs->rx_drops_no_tpre_descr = rxf_stats->rx_drops_no_tpre_descr; @@ -380,13 +378,14 @@ static void populate_lancer_stats(struct be_adapter *adapter) drvs->rx_dropped_header_too_small = pport_stats->rx_dropped_header_too_small; drvs->rx_input_fifo_overflow_drop = pport_stats->rx_fifo_overflow; - drvs->rx_address_match_errors = pport_stats->rx_address_match_errors; + drvs->rx_address_mismatch_drops = + pport_stats->rx_address_mismatch_drops + + pport_stats->rx_vlan_mismatch_drops; drvs->rx_alignment_symbol_errors = pport_stats->rx_symbol_errors_lo; drvs->rxpp_fifo_overflow_drop = pport_stats->rx_fifo_overflow; drvs->tx_pauseframes = pport_stats->tx_pause_frames_lo; drvs->tx_controlframes = pport_stats->tx_control_frames_lo; drvs->jabber_events = pport_stats->rx_jabbers; - drvs->rx_drops_invalid_ring = pport_stats->rx_drops_invalid_queue; drvs->forwarded_packets = pport_stats->num_forwards_lo; drvs->rx_drops_mtu = pport_stats->rx_drops_mtu_lo; drvs->rx_drops_too_many_frags = @@ -1189,7 +1188,7 @@ static void be_rx_compl_process(struct be_adapter *adapter, struct net_device *netdev = adapter->netdev; struct sk_buff *skb; - skb = netdev_alloc_skb_ip_align(netdev, BE_HDR_LEN); + skb = netdev_alloc_skb_ip_align(netdev, BE_RX_SKB_ALLOC_SIZE); if (unlikely(!skb)) { rx_stats(rxo)->rx_drops_no_skbs++; be_rx_compl_discard(adapter, rxo, rxcp); @@ -2609,19 +2608,28 @@ static void be_setup_init(struct be_adapter *adapter) adapter->eq_next_idx = 0; } -static int be_configure_mac_from_list(struct be_adapter *adapter, u8 *mac) +static int be_add_mac_from_list(struct be_adapter *adapter, u8 *mac) { u32 pmac_id; - int status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id); - if (status != 0) - goto do_none; - status = be_cmd_mac_addr_query(adapter, mac, - MAC_ADDRESS_TYPE_NETWORK, - false, adapter->if_handle, pmac_id); + int status; + bool pmac_id_active; + + status = be_cmd_get_mac_from_list(adapter, 0, &pmac_id_active, + &pmac_id, mac); if (status != 0) goto do_none; - status = be_cmd_pmac_add(adapter, mac, adapter->if_handle, - &adapter->pmac_id, 0); + + if (pmac_id_active) { + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, + false, adapter->if_handle, pmac_id); + + if (!status) + adapter->pmac_id = pmac_id; + } else { + status = be_cmd_pmac_add(adapter, mac, + adapter->if_handle, &adapter->pmac_id, 0); + } do_none: return status; } @@ -2686,7 +2694,7 @@ static int be_setup(struct be_adapter *adapter) */ if (!be_physfn(adapter)) { if (lancer_chip(adapter)) - status = be_configure_mac_from_list(adapter, mac); + status = be_add_mac_from_list(adapter, mac); else status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, false, |