diff options
Diffstat (limited to 'kernel/drivers/net/ethernet/emulex')
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/Kconfig | 4 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/Kconfig | 9 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be.h | 64 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be_cmds.c | 156 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be_cmds.h | 76 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be_ethtool.c | 50 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be_hw.h | 14 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be_main.c | 804 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be_roce.c | 38 | ||||
-rw-r--r-- | kernel/drivers/net/ethernet/emulex/benet/be_roce.h | 6 |
10 files changed, 861 insertions, 360 deletions
diff --git a/kernel/drivers/net/ethernet/emulex/Kconfig b/kernel/drivers/net/ethernet/emulex/Kconfig index 1b8d638c6..fdbb27ceb 100644 --- a/kernel/drivers/net/ethernet/emulex/Kconfig +++ b/kernel/drivers/net/ethernet/emulex/Kconfig @@ -7,9 +7,7 @@ config NET_VENDOR_EMULEX default y depends on PCI ---help--- - If you have a network (Ethernet) card belonging to this class, say Y - and read the Ethernet-HOWTO, available from - <http://www.tldp.org/docs.html#howto>. + If you have a network (Ethernet) card belonging to this class, say Y. Note that the answer to this question doesn't directly affect the kernel: saying N will just cause the configurator to skip all diff --git a/kernel/drivers/net/ethernet/emulex/benet/Kconfig b/kernel/drivers/net/ethernet/emulex/benet/Kconfig index ea94a8eb6..710856326 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/Kconfig +++ b/kernel/drivers/net/ethernet/emulex/benet/Kconfig @@ -5,6 +5,15 @@ config BE2NET This driver implements the NIC functionality for ServerEngines' 10Gbps network adapter - BladeEngine. +config BE2NET_HWMON + bool "HWMON support for be2net driver" + depends on BE2NET && HWMON + depends on !(BE2NET=y && HWMON=m) + default y + ---help--- + Say Y here if you want to expose thermal sensor data on + be2net network adapter. + config BE2NET_VXLAN bool "VXLAN offload support on be2net driver" default y diff --git a/kernel/drivers/net/ethernet/emulex/benet/be.h b/kernel/drivers/net/ethernet/emulex/benet/be.h index 1bf1cdce7..6ee78c203 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be.h +++ b/kernel/drivers/net/ethernet/emulex/benet/be.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -31,11 +31,13 @@ #include <linux/slab.h> #include <linux/u64_stats_sync.h> #include <linux/cpumask.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> #include "be_hw.h" #include "be_roce.h" -#define DRV_VER "10.6.0.1" +#define DRV_VER "10.6.0.3" #define DRV_NAME "be2net" #define BE_NAME "Emulex BladeEngine2" #define BE3_NAME "Emulex BladeEngine3" @@ -103,6 +105,8 @@ #define MAX_VFS 30 /* Max VFs supported by BE3 FW */ #define FW_VER_LEN 32 +#define CNTL_SERIAL_NUM_WORDS 8 /* Controller serial number words */ +#define CNTL_SERIAL_NUM_WORD_SZ (sizeof(u16)) /* Byte-sz of serial num word */ #define RSS_INDIR_TABLE_LEN 128 #define RSS_HASH_KEY_LEN 40 @@ -226,6 +230,7 @@ struct be_mcc_obj { struct be_tx_stats { u64 tx_bytes; u64 tx_pkts; + u64 tx_vxlan_offload_pkts; u64 tx_reqs; u64 tx_compl; ulong tx_jiffies; @@ -273,6 +278,7 @@ struct be_rx_page_info { struct be_rx_stats { u64 rx_bytes; u64 rx_pkts; + u64 rx_vxlan_offload_pkts; u32 rx_drops_no_skbs; /* skb allocation errors */ u32 rx_drops_no_frags; /* HW has no fetched frags */ u32 rx_post_fail; /* page post alloc failures */ @@ -314,7 +320,6 @@ struct be_rx_obj { } ____cacheline_aligned_in_smp; struct be_drv_stats { - u32 be_on_die_temperature; u32 eth_red_drops; u32 dma_map_errors; u32 rx_drops_no_pbuf; @@ -366,6 +371,7 @@ struct be_vf_cfg { u32 tx_rate; u32 plink_tracking; u32 privileges; + bool spoofchk; }; enum vf_state { @@ -382,6 +388,7 @@ enum vf_state { #define BE_FLAGS_SETUP_DONE BIT(9) #define BE_FLAGS_EVT_INCOMPATIBLE_SFP BIT(10) #define BE_FLAGS_ERR_DETECTION_SCHEDULED BIT(11) +#define BE_FLAGS_OS2BMC BIT(12) #define BE_UC_PMAC_COUNT 30 #define BE_VF_UC_PMAC_COUNT 2 @@ -426,6 +433,8 @@ struct be_resources { u32 vf_if_cap_flags; /* VF if capability flags */ }; +#define be_is_os2bmc_enabled(adapter) (adapter->flags & BE_FLAGS_OS2BMC) + struct rss_info { u64 rss_flags; u8 rsstable[RSS_INDIR_TABLE_LEN]; @@ -433,6 +442,12 @@ struct rss_info { u8 rss_hkey[RSS_HASH_KEY_LEN]; }; +#define BE_INVALID_DIE_TEMP 0xFF +struct be_hwmon { + struct device *hwmon_dev; + u8 be_on_die_temp; /* Unit: millidegree Celsius */ +}; + /* Macros to read/write the 'features' word of be_wrb_params structure. */ #define BE_WRB_F_BIT(name) BE_WRB_F_##name##_BIT @@ -453,7 +468,8 @@ enum { BE_WRB_F_LSO_BIT, /* LSO */ BE_WRB_F_LSO6_BIT, /* LSO6 */ BE_WRB_F_VLAN_BIT, /* VLAN */ - BE_WRB_F_VLAN_SKIP_HW_BIT /* Skip VLAN tag (workaround) */ + BE_WRB_F_VLAN_SKIP_HW_BIT, /* Skip VLAN tag (workaround) */ + BE_WRB_F_OS2BMC_BIT /* Send packet to the management ring */ }; /* The structure below provides a HW-agnostic abstraction of WRB params @@ -514,6 +530,7 @@ struct be_adapter { u16 work_counter; struct delayed_work be_err_detection_work; + u8 err_flags; u32 flags; u32 cmd_privileges; /* Ethtool knobs and info */ @@ -565,6 +582,7 @@ struct be_adapter { u16 pvid; __be16 vxlan_port; int vxlan_port_count; + int vxlan_port_aliases; struct phy_info phy; u8 wol_cap; bool wol_en; @@ -572,8 +590,13 @@ struct be_adapter { u16 qnq_vid; u32 msg_enable; int be_get_temp_freq; + struct be_hwmon hwmon_info; u8 pf_number; + u8 pci_func_num; struct rss_info rss_info; + /* Filters for packets that need to be sent to BMC */ + u32 bmc_filt_mask; + u16 serial_num[CNTL_SERIAL_NUM_WORDS]; }; #define be_physfn(adapter) (!adapter->virtfn) @@ -772,26 +795,36 @@ static inline bool is_ipv4_pkt(struct sk_buff *skb) return skb->protocol == htons(ETH_P_IP) && ip_hdr(skb)->version == 4; } -static inline bool be_multi_rxq(const struct be_adapter *adapter) +#define BE_ERROR_EEH 1 +#define BE_ERROR_UE BIT(1) +#define BE_ERROR_FW BIT(2) +#define BE_ERROR_HW (BE_ERROR_EEH | BE_ERROR_UE) +#define BE_ERROR_ANY (BE_ERROR_EEH | BE_ERROR_UE | BE_ERROR_FW) +#define BE_CLEAR_ALL 0xFF + +static inline u8 be_check_error(struct be_adapter *adapter, u32 err_type) { - return adapter->num_rx_qs > 1; + return (adapter->err_flags & err_type); } -static inline bool be_error(struct be_adapter *adapter) +static inline void be_set_error(struct be_adapter *adapter, int err_type) { - return adapter->eeh_error || adapter->hw_error || adapter->fw_timeout; + struct net_device *netdev = adapter->netdev; + + adapter->err_flags |= err_type; + netif_carrier_off(netdev); + + dev_info(&adapter->pdev->dev, "%s: Link down\n", netdev->name); } -static inline bool be_hw_error(struct be_adapter *adapter) +static inline void be_clear_error(struct be_adapter *adapter, int err_type) { - return adapter->eeh_error || adapter->hw_error; + adapter->err_flags &= ~err_type; } -static inline void be_clear_all_error(struct be_adapter *adapter) +static inline bool be_multi_rxq(const struct be_adapter *adapter) { - adapter->eeh_error = false; - adapter->hw_error = false; - adapter->fw_timeout = false; + return adapter->num_rx_qs > 1; } void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, @@ -804,6 +837,7 @@ bool be_pause_supported(struct be_adapter *adapter); u32 be_get_fw_log_level(struct be_adapter *adapter); int be_update_queues(struct be_adapter *adapter); int be_poll(struct napi_struct *napi, int budget); +void be_eqd_update(struct be_adapter *adapter, bool force_update); /* * internal function to initialize-cleanup roce device. @@ -814,8 +848,6 @@ void be_roce_dev_remove(struct be_adapter *); /* * internal function to open-close roce device during ifup-ifdown. */ -void be_roce_dev_open(struct be_adapter *); -void be_roce_dev_close(struct be_adapter *); void be_roce_dev_shutdown(struct be_adapter *); #endif /* BE_H */ diff --git a/kernel/drivers/net/ethernet/emulex/benet/be_cmds.c b/kernel/drivers/net/ethernet/emulex/benet/be_cmds.c index c5e1d0ac7..1795c935f 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/kernel/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -88,19 +88,21 @@ static inline void *embedded_payload(struct be_mcc_wrb *wrb) return wrb->payload.embedded_payload; } -static void be_mcc_notify(struct be_adapter *adapter) +static int be_mcc_notify(struct be_adapter *adapter) { struct be_queue_info *mccq = &adapter->mcc_obj.q; u32 val = 0; - if (be_error(adapter)) - return; + if (be_check_error(adapter, BE_ERROR_ANY)) + return -EIO; val |= mccq->id & DB_MCCQ_RING_ID_MASK; val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; wmb(); iowrite32(val, adapter->db + DB_MCCQ_OFFSET); + + return 0; } /* To check if valid bit is set, check the entire word as we don't know @@ -140,6 +142,7 @@ static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status) if (base_status == MCC_STATUS_NOT_SUPPORTED || base_status == MCC_STATUS_ILLEGAL_REQUEST || addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES || + addl_status == MCC_ADDL_STATUS_INSUFFICIENT_VLANS || (opcode == OPCODE_COMMON_WRITE_FLASHROM && (base_status == MCC_STATUS_ILLEGAL_FIELD || addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH))) @@ -169,6 +172,12 @@ static void be_async_cmd_process(struct be_adapter *adapter, return; } + if (opcode == OPCODE_LOWLEVEL_SET_LOOPBACK_MODE && + subsystem == CMD_SUBSYSTEM_LOWLEVEL) { + complete(&adapter->et_cmd_compl); + return; + } + if ((opcode == OPCODE_COMMON_WRITE_FLASHROM || opcode == OPCODE_COMMON_WRITE_OBJECT) && subsystem == CMD_SUBSYSTEM_COMMON) { @@ -191,10 +200,12 @@ static void be_async_cmd_process(struct be_adapter *adapter, if (base_status == MCC_STATUS_SUCCESS) { struct be_cmd_resp_get_cntl_addnl_attribs *resp = (void *)resp_hdr; - adapter->drv_stats.be_on_die_temperature = + adapter->hwmon_info.be_on_die_temp = resp->on_die_temperature; } else { adapter->be_get_temp_freq = 0; + adapter->hwmon_info.be_on_die_temp = + BE_INVALID_DIE_TEMP; } return; } @@ -330,6 +341,21 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, } } +#define MGMT_ENABLE_MASK 0x4 +static void be_async_grp5_fw_control_process(struct be_adapter *adapter, + struct be_mcc_compl *compl) +{ + struct be_async_fw_control *evt = (struct be_async_fw_control *)compl; + u32 evt_dw1 = le32_to_cpu(evt->event_data_word1); + + if (evt_dw1 & MGMT_ENABLE_MASK) { + adapter->flags |= BE_FLAGS_OS2BMC; + adapter->bmc_filt_mask = le32_to_cpu(evt->event_data_word2); + } else { + adapter->flags &= ~BE_FLAGS_OS2BMC; + } +} + static void be_async_grp5_evt_process(struct be_adapter *adapter, struct be_mcc_compl *compl) { @@ -346,6 +372,10 @@ static void be_async_grp5_evt_process(struct be_adapter *adapter, case ASYNC_EVENT_PVID_STATE: be_async_grp5_pvid_state_process(adapter, compl); break; + /* Async event to disable/enable os2bmc and/or mac-learning */ + case ASYNC_EVENT_FW_CONTROL: + be_async_grp5_fw_control_process(adapter, compl); + break; default: break; } @@ -486,7 +516,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; for (i = 0; i < mcc_timeout; i++) { - if (be_error(adapter)) + if (be_check_error(adapter, BE_ERROR_ANY)) return -EIO; local_bh_disable(); @@ -499,7 +529,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) } if (i == mcc_timeout) { dev_err(&adapter->pdev->dev, "FW not responding\n"); - adapter->fw_timeout = true; + be_set_error(adapter, BE_ERROR_FW); return -EIO; } return status; @@ -519,7 +549,9 @@ static int be_mcc_notify_wait(struct be_adapter *adapter) resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1); - be_mcc_notify(adapter); + status = be_mcc_notify(adapter); + if (status) + goto out; status = be_mcc_wait_compl(adapter); if (status == -EIO) @@ -538,7 +570,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) u32 ready; do { - if (be_error(adapter)) + if (be_check_error(adapter, BE_ERROR_ANY)) return -EIO; ready = ioread32(db); @@ -551,7 +583,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) if (msecs > 4000) { dev_err(&adapter->pdev->dev, "FW not responding\n"); - adapter->fw_timeout = true; + be_set_error(adapter, BE_ERROR_FW); be_detect_error(adapter); return -1; } @@ -819,8 +851,10 @@ static int be_cmd_notify_wait(struct be_adapter *adapter, return status; dest_wrb = be_cmd_copy(adapter, wrb); - if (!dest_wrb) - return -EBUSY; + if (!dest_wrb) { + status = -EBUSY; + goto unlock; + } if (use_mcc(adapter)) status = be_mcc_notify_wait(adapter); @@ -830,6 +864,7 @@ static int be_cmd_notify_wait(struct be_adapter *adapter, if (!status) memcpy(wrb, dest_wrb, sizeof(*wrb)); +unlock: be_cmd_unlock(adapter); return status; } @@ -1457,7 +1492,7 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags, *if_handle = le32_to_cpu(resp->interface_id); /* Hack to retrieve VF's pmac-id on BE3 */ - if (BE3_chip(adapter) && !be_physfn(adapter)) + if (BE3_chip(adapter) && be_virtfn(adapter)) adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id); } return status; @@ -1525,7 +1560,10 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) else hdr->version = 2; - be_mcc_notify(adapter); + status = be_mcc_notify(adapter); + if (status) + goto err; + adapter->stats_cmd_sent = true; err: @@ -1561,7 +1599,10 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, req->cmd_params.params.pport_num = cpu_to_le16(adapter->hba_port_num); req->cmd_params.params.reset_stats = 0; - be_mcc_notify(adapter); + status = be_mcc_notify(adapter); + if (status) + goto err; + adapter->stats_cmd_sent = true; err: @@ -1665,8 +1706,7 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter) OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req), wrb, NULL); - be_mcc_notify(adapter); - + status = be_mcc_notify(adapter); err: spin_unlock_bh(&adapter->mcc_lock); return status; @@ -1838,7 +1878,7 @@ static int __be_cmd_modify_eqd(struct be_adapter *adapter, cpu_to_le32(set_eqd[i].delay_multiplier); } - be_mcc_notify(adapter); + status = be_mcc_notify(adapter); err: spin_unlock_bh(&adapter->mcc_lock); return status; @@ -1947,6 +1987,8 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) be_if_cap_flags(adapter)); } flags &= be_if_cap_flags(adapter); + if (!flags) + return -ENOTSUPP; return __be_cmd_rx_filter(adapter, flags, value); } @@ -2298,7 +2340,10 @@ int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + sizeof(struct lancer_cmd_req_write_object))); - be_mcc_notify(adapter); + status = be_mcc_notify(adapter); + if (status) + goto err_unlock; + spin_unlock_bh(&adapter->mcc_lock); if (!wait_for_completion_timeout(&adapter->et_cmd_compl, @@ -2469,7 +2514,10 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, req->params.op_code = cpu_to_le32(flash_opcode); req->params.data_buf_size = cpu_to_le32(buf_size); - be_mcc_notify(adapter); + status = be_mcc_notify(adapter); + if (status) + goto err_unlock; + spin_unlock_bh(&adapter->mcc_lock); if (!wait_for_completion_timeout(&adapter->et_cmd_compl, @@ -2563,7 +2611,7 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, wrb = wrb_from_mccq(adapter); if (!wrb) { status = -EBUSY; - goto err; + goto err_unlock; } req = embedded_payload(wrb); @@ -2577,8 +2625,19 @@ int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num, req->loopback_type = loopback_type; req->loopback_state = enable; - status = be_mcc_notify_wait(adapter); -err: + status = be_mcc_notify(adapter); + if (status) + goto err_unlock; + + spin_unlock_bh(&adapter->mcc_lock); + + if (!wait_for_completion_timeout(&adapter->et_cmd_compl, + msecs_to_jiffies(SET_LB_MODE_TIMEOUT))) + status = -ETIMEDOUT; + + return status; + +err_unlock: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -2614,7 +2673,9 @@ int be_cmd_loopback_test(struct be_adapter *adapter, u32 port_num, req->num_pkts = cpu_to_le32(num_pkts); req->loopback_type = cpu_to_le32(loopback_type); - be_mcc_notify(adapter); + status = be_mcc_notify(adapter); + if (status) + goto err; spin_unlock_bh(&adapter->mcc_lock); @@ -2796,10 +2857,11 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter) struct be_mcc_wrb *wrb; struct be_cmd_req_cntl_attribs *req; struct be_cmd_resp_cntl_attribs *resp; - int status; + int status, i; int payload_len = max(sizeof(*req), sizeof(*resp)); struct mgmt_controller_attrib *attribs; struct be_dma_mem attribs_cmd; + u32 *serial_num; if (mutex_lock_interruptible(&adapter->mbox_lock)) return -1; @@ -2830,6 +2892,11 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter) if (!status) { attribs = attribs_cmd.va + sizeof(struct be_cmd_resp_hdr); adapter->hba_port_num = attribs->hba_attribs.phy_port; + adapter->pci_func_num = attribs->pci_func_num; + serial_num = attribs->hba_attribs.controller_serial_number; + for (i = 0; i < CNTL_SERIAL_NUM_WORDS; i++) + adapter->serial_num[i] = le32_to_cpu(serial_num[i]) & + (BIT_MASK(16) - 1); } err: @@ -3156,7 +3223,7 @@ int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom) } int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, - u32 domain, u16 intf_id, u16 hsw_mode) + u32 domain, u16 intf_id, u16 hsw_mode, u8 spoofchk) { struct be_mcc_wrb *wrb; struct be_cmd_req_set_hsw_config *req; @@ -3192,6 +3259,14 @@ int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, ctxt, hsw_mode); } + /* Enable/disable both mac and vlan spoof checking */ + if (!BEx_chip(adapter) && spoofchk) { + AMAP_SET_BITS(struct amap_set_hsw_context, mac_spoofchk, + ctxt, spoofchk); + AMAP_SET_BITS(struct amap_set_hsw_context, vlan_spoofchk, + ctxt, spoofchk); + } + be_dws_cpu_to_le(req->context, sizeof(req->context)); status = be_mcc_notify_wait(adapter); @@ -3202,7 +3277,7 @@ err: /* Get Hyper switch config */ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, - u32 domain, u16 intf_id, u8 *mode) + u32 domain, u16 intf_id, u8 *mode, bool *spoofchk) { struct be_mcc_wrb *wrb; struct be_cmd_req_get_hsw_config *req; @@ -3250,6 +3325,10 @@ int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, if (mode) *mode = AMAP_GET_BITS(struct amap_get_hsw_resp_context, port_fwd_type, &resp->context); + if (spoofchk) + *spoofchk = + AMAP_GET_BITS(struct amap_get_hsw_resp_context, + spoofchk, &resp->context); } err: @@ -3261,7 +3340,7 @@ static bool be_is_wol_excluded(struct be_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; - if (!be_physfn(adapter)) + if (be_virtfn(adapter)) return true; switch (pdev->subsystem_device) { @@ -3636,7 +3715,6 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res) status = -EINVAL; goto err; } - adapter->pf_number = desc->pf_num; be_copy_nic_desc(res, desc); } @@ -3648,7 +3726,10 @@ err: return status; } -/* Will use MBOX only if MCCQ has not been created */ +/* Will use MBOX only if MCCQ has not been created + * non-zero domain => a PF is querying this on behalf of a VF + * zero domain => a PF or a VF is querying this for itself + */ int be_cmd_get_profile_config(struct be_adapter *adapter, struct be_resources *res, u8 query, u8 domain) { @@ -3675,10 +3756,15 @@ int be_cmd_get_profile_config(struct be_adapter *adapter, OPCODE_COMMON_GET_PROFILE_CONFIG, cmd.size, &wrb, &cmd); - req->hdr.domain = domain; if (!lancer_chip(adapter)) req->hdr.version = 1; req->type = ACTIVE_PROFILE_TYPE; + /* When a function is querying profile information relating to + * itself hdr.pf_number must be set to it's pci_func_num + 1 + */ + req->hdr.domain = domain; + if (domain == 0) + req->hdr.pf_num = adapter->pci_func_num + 1; /* When QUERY_MODIFIABLE_FIELDS_TYPE bit is set, cmd returns the * descriptors with all bits set to "1" for the fields which can be @@ -3848,12 +3934,16 @@ static void be_fill_vf_res_template(struct be_adapter *adapter, vf_if_cap_flags &= ~(BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS); } - - nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); } else { num_vf_qs = 1; } + if (res_mod.vf_if_cap_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) { + nic_vft->flags |= BIT(IF_CAPS_FLAGS_VALID_SHIFT); + vf_if_cap_flags &= ~BE_IF_FLAGS_VLAN_PROMISCUOUS; + } + + nic_vft->cap_flags = cpu_to_le32(vf_if_cap_flags); nic_vft->rq_count = cpu_to_le16(num_vf_qs); nic_vft->txq_count = cpu_to_le16(num_vf_qs); nic_vft->rssq_count = cpu_to_le16(num_vf_qs); diff --git a/kernel/drivers/net/ethernet/emulex/benet/be_cmds.h b/kernel/drivers/net/ethernet/emulex/benet/be_cmds.h index 1ec22300e..91155ea74 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/kernel/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -65,7 +65,8 @@ enum mcc_base_status { enum mcc_addl_status { MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES = 0x16, MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH = 0x4d, - MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a + MCC_ADDL_STATUS_TOO_MANY_INTERFACES = 0x4a, + MCC_ADDL_STATUS_INSUFFICIENT_VLANS = 0xab }; #define CQE_BASE_STATUS_MASK 0xFFFF @@ -104,6 +105,7 @@ struct be_mcc_compl { #define ASYNC_DEBUG_EVENT_TYPE_QNQ 1 #define ASYNC_EVENT_CODE_SLIPORT 0x11 #define ASYNC_EVENT_PORT_MISCONFIG 0x9 +#define ASYNC_EVENT_FW_CONTROL 0x5 enum { LINK_DOWN = 0x0, @@ -180,6 +182,22 @@ struct be_async_event_misconfig_port { u32 flags; } __packed; +#define BMC_FILT_BROADCAST_ARP BIT(0) +#define BMC_FILT_BROADCAST_DHCP_CLIENT BIT(1) +#define BMC_FILT_BROADCAST_DHCP_SERVER BIT(2) +#define BMC_FILT_BROADCAST_NET_BIOS BIT(3) +#define BMC_FILT_BROADCAST BIT(7) +#define BMC_FILT_MULTICAST_IPV6_NEIGH_ADVER BIT(8) +#define BMC_FILT_MULTICAST_IPV6_RA BIT(9) +#define BMC_FILT_MULTICAST_IPV6_RAS BIT(10) +#define BMC_FILT_MULTICAST BIT(15) +struct be_async_fw_control { + u32 event_data_word1; + u32 event_data_word2; + u32 evt_tag; + u32 event_data_word4; +} __packed; + struct be_mcc_mailbox { struct be_mcc_wrb wrb; struct be_mcc_compl compl; @@ -271,7 +289,9 @@ struct be_cmd_req_hdr { u32 timeout; /* dword 1 */ u32 request_length; /* dword 2 */ u8 version; /* dword 3 */ - u8 rsvd[3]; /* dword 3 */ + u8 rsvd1; /* dword 3 */ + u8 pf_num; /* dword 3 */ + u8 rsvd2; /* dword 3 */ }; #define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ @@ -602,6 +622,11 @@ enum be_if_flags { BE_IF_FLAGS_VLAN_PROMISCUOUS |\ BE_IF_FLAGS_MCAST_PROMISCUOUS) +#define BE_IF_EN_FLAGS (BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |\ + BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_UNTAGGED) + +#define BE_IF_ALL_FILT_FLAGS (BE_IF_EN_FLAGS | BE_IF_FLAGS_ALL_PROMISCUOUS) + /* An RX interface is an object with one or more MAC addresses and * filtering capabilities. */ struct be_cmd_req_if_create { @@ -1109,10 +1134,6 @@ struct be_cmd_req_query_fw_cfg { u32 rsvd[31]; }; -/* ASIC revisions */ -#define ASIC_REV_B0 0x10 -#define ASIC_REV_P2 0x11 - struct be_cmd_resp_query_fw_cfg { struct be_cmd_resp_hdr hdr; u32 be_config_number; @@ -1481,6 +1502,8 @@ struct be_cmd_resp_acpi_wol_magic_config_v1 { #define BE_PME_D3COLD_CAP 0x80 /********************** LoopBack test *********************/ +#define SET_LB_MODE_TIMEOUT 12000 + struct be_cmd_req_loopback_test { struct be_cmd_req_hdr hdr; u32 loopback_type; @@ -1621,15 +1644,21 @@ struct be_cmd_req_set_qos { struct mgmt_hba_attribs { u32 rsvd0[24]; u8 controller_model_number[32]; - u32 rsvd1[79]; - u8 rsvd2[3]; + u32 rsvd1[16]; + u32 controller_serial_number[8]; + u32 rsvd2[55]; + u8 rsvd3[3]; u8 phy_port; - u32 rsvd3[13]; + u32 rsvd4[13]; } __packed; struct mgmt_controller_attrib { struct mgmt_hba_attribs hba_attribs; - u32 rsvd0[10]; + u32 rsvd0[2]; + u16 rsvd1; + u8 pci_func_num; + u8 rsvd2; + u32 rsvd3[7]; } __packed; struct be_cmd_req_cntl_attribs { @@ -1744,19 +1773,26 @@ struct be_cmd_req_set_mac_list { /*********************** HSW Config ***********************/ #define PORT_FWD_TYPE_VEPA 0x3 #define PORT_FWD_TYPE_VEB 0x2 +#define PORT_FWD_TYPE_PASSTHRU 0x1 + +#define ENABLE_MAC_SPOOFCHK 0x2 +#define DISABLE_MAC_SPOOFCHK 0x3 struct amap_set_hsw_context { u8 interface_id[16]; - u8 rsvd0[14]; + u8 rsvd0[8]; + u8 mac_spoofchk[2]; + u8 rsvd1[4]; u8 pvid_valid; u8 pport; - u8 rsvd1[6]; + u8 rsvd2[6]; u8 port_fwd_type[3]; - u8 rsvd2[7]; + u8 rsvd3[5]; + u8 vlan_spoofchk[2]; u8 pvid[16]; - u8 rsvd3[32]; u8 rsvd4[32]; u8 rsvd5[32]; + u8 rsvd6[32]; } __packed; struct be_cmd_req_set_hsw_config { @@ -1774,11 +1810,13 @@ struct amap_get_hsw_req_context { struct amap_get_hsw_resp_context { u8 rsvd0[6]; u8 port_fwd_type[3]; - u8 rsvd1[7]; + u8 rsvd1[5]; + u8 spoofchk; + u8 rsvd2; u8 pvid[16]; - u8 rsvd2[32]; u8 rsvd3[32]; u8 rsvd4[32]; + u8 rsvd5[32]; } __packed; struct be_cmd_req_get_hsw_config { @@ -2334,9 +2372,9 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array, u8 mac_count, u32 domain); int be_cmd_set_mac(struct be_adapter *adapter, u8 *mac, int if_id, u32 dom); int be_cmd_set_hsw_config(struct be_adapter *adapter, u16 pvid, u32 domain, - u16 intf_id, u16 hsw_mode); + u16 intf_id, u16 hsw_mode, u8 spoofchk); int be_cmd_get_hsw_config(struct be_adapter *adapter, u16 *pvid, u32 domain, - u16 intf_id, u8 *mode); + u16 intf_id, u8 *mode, bool *spoofchk); int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter); int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level); int be_cmd_get_fw_log_level(struct be_adapter *adapter); diff --git a/kernel/drivers/net/ethernet/emulex/benet/be_ethtool.c b/kernel/drivers/net/ethernet/emulex/benet/be_ethtool.c index 2835dee5d..734f655c9 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/kernel/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -123,7 +123,6 @@ static const struct be_ethtool_stat et_stats[] = { {DRVSTAT_INFO(dma_map_errors)}, /* Number of packets dropped due to random early drop function */ {DRVSTAT_INFO(eth_red_drops)}, - {DRVSTAT_INFO(be_on_die_temperature)}, {DRVSTAT_INFO(rx_roce_bytes_lsd)}, {DRVSTAT_INFO(rx_roce_bytes_msd)}, {DRVSTAT_INFO(rx_roce_frames)}, @@ -139,6 +138,7 @@ static const struct be_ethtool_stat et_stats[] = { static const struct be_ethtool_stat et_rx_stats[] = { {DRVSTAT_RX_INFO(rx_bytes)},/* If moving this member see above note */ {DRVSTAT_RX_INFO(rx_pkts)}, /* If moving this member see above note */ + {DRVSTAT_RX_INFO(rx_vxlan_offload_pkts)}, {DRVSTAT_RX_INFO(rx_compl)}, {DRVSTAT_RX_INFO(rx_compl_err)}, {DRVSTAT_RX_INFO(rx_mcast_pkts)}, @@ -191,6 +191,7 @@ static const struct be_ethtool_stat et_tx_stats[] = { {DRVSTAT_TX_INFO(tx_internal_parity_err)}, {DRVSTAT_TX_INFO(tx_bytes)}, {DRVSTAT_TX_INFO(tx_pkts)}, + {DRVSTAT_TX_INFO(tx_vxlan_offload_pkts)}, /* Number of skbs queued for trasmission by the driver */ {DRVSTAT_TX_INFO(tx_reqs)}, /* Number of times the TX queue was stopped due to lack @@ -233,9 +234,6 @@ static void be_get_drvinfo(struct net_device *netdev, strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), sizeof(drvinfo->bus_info)); - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; } static u32 lancer_cmd_get_file_len(struct be_adapter *adapter, u8 *file_name) @@ -368,6 +366,14 @@ static int be_set_coalesce(struct net_device *netdev, aic++; } + /* For Skyhawk, the EQD setting happens via EQ_DB when AIC is enabled. + * When AIC is disabled, persistently force set EQD value via the + * FW cmd, so that we don't have to calculate the delay multiplier + * encode value each time EQ_DB is rung + */ + if (!et->use_adaptive_rx_coalesce && skyhawk_chip(adapter)) + be_eqd_update(adapter, true); + return 0; } @@ -840,10 +846,21 @@ err: static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type, u64 *status) { - be_cmd_set_loopback(adapter, adapter->hba_port_num, loopback_type, 1); + int ret; + + ret = be_cmd_set_loopback(adapter, adapter->hba_port_num, + loopback_type, 1); + if (ret) + return ret; + *status = be_cmd_loopback_test(adapter, adapter->hba_port_num, loopback_type, 1500, 2, 0xabc); - be_cmd_set_loopback(adapter, adapter->hba_port_num, BE_NO_LOOPBACK, 1); + + ret = be_cmd_set_loopback(adapter, adapter->hba_port_num, + BE_NO_LOOPBACK, 1); + if (ret) + return ret; + return *status; } @@ -1045,9 +1062,7 @@ static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, static int be_set_rss_hash_opts(struct be_adapter *adapter, struct ethtool_rxnfc *cmd) { - struct be_rx_obj *rxo; - int status = 0, i, j; - u8 rsstable[128]; + int status; u32 rss_flags = adapter->rss_info.rss_flags; if (cmd->data != L3_RSS_FLAGS && @@ -1096,20 +1111,11 @@ static int be_set_rss_hash_opts(struct be_adapter *adapter, } if (rss_flags == adapter->rss_info.rss_flags) - return status; - - if (be_multi_rxq(adapter)) { - for (j = 0; j < 128; j += adapter->num_rss_qs) { - for_all_rss_queues(adapter, rxo, i) { - if ((j + i) >= 128) - break; - rsstable[j + i] = rxo->rss_id; - } - } - } + return 0; status = be_cmd_rss_config(adapter, adapter->rss_info.rsstable, - rss_flags, 128, adapter->rss_info.rss_hkey); + rss_flags, RSS_INDIR_TABLE_LEN, + adapter->rss_info.rss_hkey); if (!status) adapter->rss_info.rss_flags = rss_flags; diff --git a/kernel/drivers/net/ethernet/emulex/benet/be_hw.h b/kernel/drivers/net/ethernet/emulex/benet/be_hw.h index 48840889d..c684bb32b 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/kernel/drivers/net/ethernet/emulex/benet/be_hw.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -132,6 +132,18 @@ #define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ /* Rearm bit */ #define DB_EQ_REARM_SHIFT (29) /* bit 29 */ +/* Rearm to interrupt delay encoding */ +#define DB_EQ_R2I_DLY_SHIFT (30) /* bits 30 - 31 */ + +/* Rearm to interrupt (R2I) delay multiplier encoding represents 3 different + * values configured in CEV_REARM2IRPT_DLY_MULT_CSR register. This value is + * programmed by host driver while ringing an EQ doorbell(EQ_DB) if a delay + * between rearming the EQ and next interrupt on this EQ is desired. + */ +#define R2I_DLY_ENC_0 0 /* No delay */ +#define R2I_DLY_ENC_1 1 /* maps to 160us EQ delay */ +#define R2I_DLY_ENC_2 2 /* maps to 96us EQ delay */ +#define R2I_DLY_ENC_3 3 /* maps to 48us EQ delay */ /********* Compl Q door bell *************/ #define DB_CQ_OFFSET 0x120 diff --git a/kernel/drivers/net/ethernet/emulex/benet/be_main.c b/kernel/drivers/net/ethernet/emulex/benet/be_main.c index e43cc8a73..8a1d9fffd 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be_main.c +++ b/kernel/drivers/net/ethernet/emulex/benet/be_main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -179,7 +179,7 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) if (lancer_chip(adapter)) return; - if (adapter->eeh_error) + if (be_check_error(adapter, BE_ERROR_EEH)) return; status = be_cmd_intr_set(adapter, enable); @@ -191,6 +191,9 @@ static void be_rxq_notify(struct be_adapter *adapter, u16 qid, u16 posted) { u32 val = 0; + if (be_check_error(adapter, BE_ERROR_HW)) + return; + val |= qid & DB_RQ_RING_ID_MASK; val |= posted << DB_RQ_NUM_POSTED_SHIFT; @@ -203,6 +206,9 @@ static void be_txq_notify(struct be_adapter *adapter, struct be_tx_obj *txo, { u32 val = 0; + if (be_check_error(adapter, BE_ERROR_HW)) + return; + val |= txo->q.id & DB_TXULP_RING_ID_MASK; val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT; @@ -211,14 +217,15 @@ static void be_txq_notify(struct be_adapter *adapter, struct be_tx_obj *txo, } static void be_eq_notify(struct be_adapter *adapter, u16 qid, - bool arm, bool clear_int, u16 num_popped) + bool arm, bool clear_int, u16 num_popped, + u32 eq_delay_mult_enc) { u32 val = 0; val |= qid & DB_EQ_RING_ID_MASK; val |= ((qid & DB_EQ_RING_ID_EXT_MASK) << DB_EQ_RING_ID_EXT_MASK_SHIFT); - if (adapter->eeh_error) + if (be_check_error(adapter, BE_ERROR_HW)) return; if (arm) @@ -227,6 +234,7 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, val |= 1 << DB_EQ_CLR_SHIFT; val |= 1 << DB_EQ_EVNT_SHIFT; val |= num_popped << DB_EQ_NUM_POPPED_SHIFT; + val |= eq_delay_mult_enc << DB_EQ_R2I_DLY_SHIFT; iowrite32(val, adapter->db + DB_EQ_OFFSET); } @@ -238,7 +246,7 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) val |= ((qid & DB_CQ_RING_ID_EXT_MASK) << DB_CQ_RING_ID_EXT_MASK_SHIFT); - if (adapter->eeh_error) + if (be_check_error(adapter, BE_ERROR_HW)) return; if (arm) @@ -265,6 +273,10 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) if (ether_addr_equal(addr->sa_data, netdev->dev_addr)) return 0; + /* if device is not running, copy MAC to netdev->dev_addr */ + if (!netif_running(netdev)) + goto done; + /* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT * privilege or if PF did not provision the new MAC address. * On BE3, this cmd will always fail if the VF doesn't have the @@ -299,9 +311,9 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) status = -EPERM; goto err; } - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - dev_info(dev, "MAC address changed to %pM\n", mac); +done: + ether_addr_copy(netdev->dev_addr, addr->sa_data); + dev_info(dev, "MAC address changed to %pM\n", addr->sa_data); return 0; err: dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data); @@ -662,16 +674,21 @@ void be_link_status_update(struct be_adapter *adapter, u8 link_status) netif_carrier_on(netdev); else netif_carrier_off(netdev); + + netdev_info(netdev, "Link is %s\n", link_status ? "Up" : "Down"); } static void be_tx_stats_update(struct be_tx_obj *txo, struct sk_buff *skb) { struct be_tx_stats *stats = tx_stats(txo); + u64 tx_pkts = skb_shinfo(skb)->gso_segs ? : 1; u64_stats_update_begin(&stats->sync); stats->tx_reqs++; stats->tx_bytes += skb->len; - stats->tx_pkts += (skb_shinfo(skb)->gso_segs ? : 1); + stats->tx_pkts += tx_pkts; + if (skb->encapsulation && skb->ip_summed == CHECKSUM_PARTIAL) + stats->tx_vxlan_offload_pkts += tx_pkts; u64_stats_update_end(&stats->sync); } @@ -810,6 +827,8 @@ static void wrb_fill_hdr(struct be_adapter *adapter, SET_TX_WRB_HDR_BITS(num_wrb, hdr, skb_wrb_cnt(skb)); SET_TX_WRB_HDR_BITS(len, hdr, skb->len); + SET_TX_WRB_HDR_BITS(mgmt, hdr, + BE_WRB_F_GET(wrb_params->features, OS2BMC)); } static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb, @@ -1104,11 +1123,12 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, struct sk_buff *skb, struct be_wrb_params *wrb_params) { - /* Lancer, SH-R ASICs have a bug wherein Packets that are 32 bytes or - * less may cause a transmit stall on that port. So the work-around is - * to pad short packets (<= 32 bytes) to a 36-byte length. + /* Lancer, SH and BE3 in SRIOV mode have a bug wherein + * packets that are 32b or less may cause a transmit stall + * on that port. The workaround is to pad such packets + * (len <= 32 bytes) to a minimum length of 36b. */ - if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) { + if (skb->len <= 32) { if (skb_put_padto(skb, 36)) return NULL; } @@ -1146,6 +1166,130 @@ static void be_xmit_flush(struct be_adapter *adapter, struct be_tx_obj *txo) txo->pend_wrb_cnt = 0; } +/* OS2BMC related */ + +#define DHCP_CLIENT_PORT 68 +#define DHCP_SERVER_PORT 67 +#define NET_BIOS_PORT1 137 +#define NET_BIOS_PORT2 138 +#define DHCPV6_RAS_PORT 547 + +#define is_mc_allowed_on_bmc(adapter, eh) \ + (!is_multicast_filt_enabled(adapter) && \ + is_multicast_ether_addr(eh->h_dest) && \ + !is_broadcast_ether_addr(eh->h_dest)) + +#define is_bc_allowed_on_bmc(adapter, eh) \ + (!is_broadcast_filt_enabled(adapter) && \ + is_broadcast_ether_addr(eh->h_dest)) + +#define is_arp_allowed_on_bmc(adapter, skb) \ + (is_arp(skb) && is_arp_filt_enabled(adapter)) + +#define is_broadcast_packet(eh, adapter) \ + (is_multicast_ether_addr(eh->h_dest) && \ + !compare_ether_addr(eh->h_dest, adapter->netdev->broadcast)) + +#define is_arp(skb) (skb->protocol == htons(ETH_P_ARP)) + +#define is_arp_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & (BMC_FILT_BROADCAST_ARP)) + +#define is_dhcp_client_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & BMC_FILT_BROADCAST_DHCP_CLIENT) + +#define is_dhcp_srvr_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & BMC_FILT_BROADCAST_DHCP_SERVER) + +#define is_nbios_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & BMC_FILT_BROADCAST_NET_BIOS) + +#define is_ipv6_na_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & \ + BMC_FILT_MULTICAST_IPV6_NEIGH_ADVER) + +#define is_ipv6_ra_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & BMC_FILT_MULTICAST_IPV6_RA) + +#define is_ipv6_ras_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & BMC_FILT_MULTICAST_IPV6_RAS) + +#define is_broadcast_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & BMC_FILT_BROADCAST) + +#define is_multicast_filt_enabled(adapter) \ + (adapter->bmc_filt_mask & BMC_FILT_MULTICAST) + +static bool be_send_pkt_to_bmc(struct be_adapter *adapter, + struct sk_buff **skb) +{ + struct ethhdr *eh = (struct ethhdr *)(*skb)->data; + bool os2bmc = false; + + if (!be_is_os2bmc_enabled(adapter)) + goto done; + + if (!is_multicast_ether_addr(eh->h_dest)) + goto done; + + if (is_mc_allowed_on_bmc(adapter, eh) || + is_bc_allowed_on_bmc(adapter, eh) || + is_arp_allowed_on_bmc(adapter, (*skb))) { + os2bmc = true; + goto done; + } + + if ((*skb)->protocol == htons(ETH_P_IPV6)) { + struct ipv6hdr *hdr = ipv6_hdr((*skb)); + u8 nexthdr = hdr->nexthdr; + + if (nexthdr == IPPROTO_ICMPV6) { + struct icmp6hdr *icmp6 = icmp6_hdr((*skb)); + + switch (icmp6->icmp6_type) { + case NDISC_ROUTER_ADVERTISEMENT: + os2bmc = is_ipv6_ra_filt_enabled(adapter); + goto done; + case NDISC_NEIGHBOUR_ADVERTISEMENT: + os2bmc = is_ipv6_na_filt_enabled(adapter); + goto done; + default: + break; + } + } + } + + if (is_udp_pkt((*skb))) { + struct udphdr *udp = udp_hdr((*skb)); + + switch (ntohs(udp->dest)) { + case DHCP_CLIENT_PORT: + os2bmc = is_dhcp_client_filt_enabled(adapter); + goto done; + case DHCP_SERVER_PORT: + os2bmc = is_dhcp_srvr_filt_enabled(adapter); + goto done; + case NET_BIOS_PORT1: + case NET_BIOS_PORT2: + os2bmc = is_nbios_filt_enabled(adapter); + goto done; + case DHCPV6_RAS_PORT: + os2bmc = is_ipv6_ras_filt_enabled(adapter); + goto done; + default: + break; + } + } +done: + /* For packets over a vlan, which are destined + * to BMC, asic expects the vlan to be inline in the packet. + */ + if (os2bmc) + *skb = be_insert_vlan_in_pkt(adapter, *skb, NULL); + + return os2bmc; +} + static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -1167,6 +1311,18 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) goto drop; } + /* if os2bmc is enabled and if the pkt is destined to bmc, + * enqueue the pkt a 2nd time with mgmt bit set. + */ + if (be_send_pkt_to_bmc(adapter, &skb)) { + BE_WRB_F_SET(wrb_params.features, OS2BMC, 1); + wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params); + if (unlikely(!wrb_cnt)) + goto drop; + else + skb_get(skb); + } + if (be_is_txq_full(txo)) { netif_stop_subqueue(netdev, q_idx); tx_stats(txo)->tx_stops++; @@ -1265,7 +1421,8 @@ static int be_vid_config(struct be_adapter *adapter) if (status) { dev_err(dev, "Setting HW VLAN filtering failed\n"); /* Set to VLAN promisc mode as setting VLAN filter failed */ - if (addl_status(status) == + if (addl_status(status) == MCC_ADDL_STATUS_INSUFFICIENT_VLANS || + addl_status(status) == MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES) return be_set_vlan_promisc(adapter); } else if (adapter->if_flags & BE_IF_FLAGS_VLAN_PROMISCUOUS) { @@ -1466,6 +1623,7 @@ static int be_get_vf_config(struct net_device *netdev, int vf, vi->qos = vf_cfg->vlan_tag >> VLAN_PRIO_SHIFT; memcpy(&vi->mac, vf_cfg->mac_addr, ETH_ALEN); vi->linkstate = adapter->vf_cfg[vf].plink_tracking; + vi->spoofchk = adapter->vf_cfg[vf].spoofchk; return 0; } @@ -1478,7 +1636,7 @@ static int be_set_vf_tvt(struct be_adapter *adapter, int vf, u16 vlan) int status; /* Enable Transparent VLAN Tagging */ - status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0); + status = be_cmd_set_hsw_config(adapter, vlan, vf + 1, vf_if_id, 0, 0); if (status) return status; @@ -1507,7 +1665,7 @@ static int be_clear_vf_tvt(struct be_adapter *adapter, int vf) /* Reset Transparent VLAN Tagging. */ status = be_cmd_set_hsw_config(adapter, BE_RESET_VLAN_TAG_ID, vf + 1, - vf_cfg->if_handle, 0); + vf_cfg->if_handle, 0, 0); if (status) return status; @@ -1642,6 +1800,39 @@ static int be_set_vf_link_state(struct net_device *netdev, int vf, return 0; } +static int be_set_vf_spoofchk(struct net_device *netdev, int vf, bool enable) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; + u8 spoofchk; + int status; + + if (!sriov_enabled(adapter)) + return -EPERM; + + if (vf >= adapter->num_vfs) + return -EINVAL; + + if (BEx_chip(adapter)) + return -EOPNOTSUPP; + + if (enable == vf_cfg->spoofchk) + return 0; + + spoofchk = enable ? ENABLE_MAC_SPOOFCHK : DISABLE_MAC_SPOOFCHK; + + status = be_cmd_set_hsw_config(adapter, 0, vf + 1, vf_cfg->if_handle, + 0, spoofchk); + if (status) { + dev_err(&adapter->pdev->dev, + "Spoofchk change on VF %d failed: %#x\n", vf, status); + return be_cmd_status(status); + } + + vf_cfg->spoofchk = enable; + return 0; +} + static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts, ulong now) { @@ -1650,61 +1841,110 @@ static void be_aic_update(struct be_aic_obj *aic, u64 rx_pkts, u64 tx_pkts, aic->jiffies = now; } -static void be_eqd_update(struct be_adapter *adapter) +static int be_get_new_eqd(struct be_eq_obj *eqo) { - struct be_set_eqd set_eqd[MAX_EVT_QS]; - int eqd, i, num = 0, start; + struct be_adapter *adapter = eqo->adapter; + int eqd, start; struct be_aic_obj *aic; - struct be_eq_obj *eqo; struct be_rx_obj *rxo; struct be_tx_obj *txo; - u64 rx_pkts, tx_pkts; + u64 rx_pkts = 0, tx_pkts = 0; ulong now; u32 pps, delta; + int i; - for_all_evt_queues(adapter, eqo, i) { - aic = &adapter->aic_obj[eqo->idx]; - if (!aic->enable) { - if (aic->jiffies) - aic->jiffies = 0; - eqd = aic->et_eqd; - goto modify_eqd; - } + aic = &adapter->aic_obj[eqo->idx]; + if (!aic->enable) { + if (aic->jiffies) + aic->jiffies = 0; + eqd = aic->et_eqd; + return eqd; + } - rxo = &adapter->rx_obj[eqo->idx]; + for_all_rx_queues_on_eq(adapter, eqo, rxo, i) { do { start = u64_stats_fetch_begin_irq(&rxo->stats.sync); - rx_pkts = rxo->stats.rx_pkts; + rx_pkts += rxo->stats.rx_pkts; } while (u64_stats_fetch_retry_irq(&rxo->stats.sync, start)); + } - txo = &adapter->tx_obj[eqo->idx]; + for_all_tx_queues_on_eq(adapter, eqo, txo, i) { do { start = u64_stats_fetch_begin_irq(&txo->stats.sync); - tx_pkts = txo->stats.tx_reqs; + tx_pkts += txo->stats.tx_reqs; } while (u64_stats_fetch_retry_irq(&txo->stats.sync, start)); + } - /* Skip, if wrapped around or first calculation */ - now = jiffies; - if (!aic->jiffies || time_before(now, aic->jiffies) || - rx_pkts < aic->rx_pkts_prev || - tx_pkts < aic->tx_reqs_prev) { - be_aic_update(aic, rx_pkts, tx_pkts, now); - continue; - } + /* Skip, if wrapped around or first calculation */ + now = jiffies; + if (!aic->jiffies || time_before(now, aic->jiffies) || + rx_pkts < aic->rx_pkts_prev || + tx_pkts < aic->tx_reqs_prev) { + be_aic_update(aic, rx_pkts, tx_pkts, now); + return aic->prev_eqd; + } - delta = jiffies_to_msecs(now - aic->jiffies); - pps = (((u32)(rx_pkts - aic->rx_pkts_prev) * 1000) / delta) + - (((u32)(tx_pkts - aic->tx_reqs_prev) * 1000) / delta); - eqd = (pps / 15000) << 2; + delta = jiffies_to_msecs(now - aic->jiffies); + if (delta == 0) + return aic->prev_eqd; - if (eqd < 8) - eqd = 0; - eqd = min_t(u32, eqd, aic->max_eqd); - eqd = max_t(u32, eqd, aic->min_eqd); + pps = (((u32)(rx_pkts - aic->rx_pkts_prev) * 1000) / delta) + + (((u32)(tx_pkts - aic->tx_reqs_prev) * 1000) / delta); + eqd = (pps / 15000) << 2; - be_aic_update(aic, rx_pkts, tx_pkts, now); -modify_eqd: - if (eqd != aic->prev_eqd) { + if (eqd < 8) + eqd = 0; + eqd = min_t(u32, eqd, aic->max_eqd); + eqd = max_t(u32, eqd, aic->min_eqd); + + be_aic_update(aic, rx_pkts, tx_pkts, now); + + return eqd; +} + +/* For Skyhawk-R only */ +static u32 be_get_eq_delay_mult_enc(struct be_eq_obj *eqo) +{ + struct be_adapter *adapter = eqo->adapter; + struct be_aic_obj *aic = &adapter->aic_obj[eqo->idx]; + ulong now = jiffies; + int eqd; + u32 mult_enc; + + if (!aic->enable) + return 0; + + if (time_before_eq(now, aic->jiffies) || + jiffies_to_msecs(now - aic->jiffies) < 1) + eqd = aic->prev_eqd; + else + eqd = be_get_new_eqd(eqo); + + if (eqd > 100) + mult_enc = R2I_DLY_ENC_1; + else if (eqd > 60) + mult_enc = R2I_DLY_ENC_2; + else if (eqd > 20) + mult_enc = R2I_DLY_ENC_3; + else + mult_enc = R2I_DLY_ENC_0; + + aic->prev_eqd = eqd; + + return mult_enc; +} + +void be_eqd_update(struct be_adapter *adapter, bool force_update) +{ + struct be_set_eqd set_eqd[MAX_EVT_QS]; + struct be_aic_obj *aic; + struct be_eq_obj *eqo; + int i, num = 0, eqd; + + for_all_evt_queues(adapter, eqo, i) { + aic = &adapter->aic_obj[eqo->idx]; + eqd = be_get_new_eqd(eqo); + if (force_update || eqd != aic->prev_eqd) { set_eqd[num].delay_multiplier = (eqd * 65)/100; set_eqd[num].eq_id = eqo->q.id; aic->prev_eqd = eqd; @@ -1725,6 +1965,8 @@ static void be_rx_stats_update(struct be_rx_obj *rxo, stats->rx_compl++; stats->rx_bytes += rxcp->pkt_size; stats->rx_pkts++; + if (rxcp->tunneled) + stats->rx_vxlan_offload_pkts++; if (rxcp->pkt_type == BE_MULTICAST_PACKET) stats->rx_mcast_pkts++; if (rxcp->err) @@ -2212,13 +2454,27 @@ static void be_eq_clean(struct be_eq_obj *eqo) { int num = events_get(eqo); - be_eq_notify(eqo->adapter, eqo->q.id, false, true, num); + be_eq_notify(eqo->adapter, eqo->q.id, false, true, num, 0); } -static void be_rx_cq_clean(struct be_rx_obj *rxo) +/* Free posted rx buffers that were not used */ +static void be_rxq_clean(struct be_rx_obj *rxo) { - struct be_rx_page_info *page_info; struct be_queue_info *rxq = &rxo->q; + struct be_rx_page_info *page_info; + + while (atomic_read(&rxq->used) > 0) { + page_info = get_rx_page_info(rxo); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + } + BUG_ON(atomic_read(&rxq->used)); + rxq->tail = 0; + rxq->head = 0; +} + +static void be_rx_cq_clean(struct be_rx_obj *rxo) +{ struct be_queue_info *rx_cq = &rxo->cq; struct be_rx_compl_info *rxcp; struct be_adapter *adapter = rxo->adapter; @@ -2236,7 +2492,9 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) if (lancer_chip(adapter)) break; - if (flush_wait++ > 10 || be_hw_error(adapter)) { + if (flush_wait++ > 50 || + be_check_error(adapter, + BE_ERROR_HW)) { dev_warn(&adapter->pdev->dev, "did not receive flush compl\n"); break; @@ -2253,16 +2511,6 @@ static void be_rx_cq_clean(struct be_rx_obj *rxo) /* After cleanup, leave the CQ in unarmed state */ be_cq_notify(adapter, rx_cq->id, false, 0); - - /* Then free posted rx buffers that were not used */ - while (atomic_read(&rxq->used) > 0) { - page_info = get_rx_page_info(rxo); - put_page(page_info->page); - memset(page_info, 0, sizeof(*page_info)); - } - BUG_ON(atomic_read(&rxq->used)); - rxq->tail = 0; - rxq->head = 0; } static void be_tx_compl_clean(struct be_adapter *adapter) @@ -2297,7 +2545,8 @@ static void be_tx_compl_clean(struct be_adapter *adapter) pending_txqs--; } - if (pending_txqs == 0 || ++timeo > 10 || be_hw_error(adapter)) + if (pending_txqs == 0 || ++timeo > 10 || + be_check_error(adapter, BE_ERROR_HW)) break; mdelay(1); @@ -2341,8 +2590,8 @@ static void be_evt_queues_destroy(struct be_adapter *adapter) be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ); napi_hash_del(&eqo->napi); netif_napi_del(&eqo->napi); + free_cpumask_var(eqo->affinity_mask); } - free_cpumask_var(eqo->affinity_mask); be_queue_free(adapter, &eqo->q); } } @@ -2359,13 +2608,7 @@ static int be_evt_queues_create(struct be_adapter *adapter) for_all_evt_queues(adapter, eqo, i) { int numa_node = dev_to_node(&adapter->pdev->dev); - if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL)) - return -ENOMEM; - cpumask_set_cpu(cpumask_local_spread(i, numa_node), - eqo->affinity_mask); - netif_napi_add(adapter->netdev, &eqo->napi, be_poll, - BE_NAPI_WEIGHT); - napi_hash_add(&eqo->napi); + aic = &adapter->aic_obj[i]; eqo->adapter = adapter; eqo->idx = i; @@ -2381,6 +2624,14 @@ static int be_evt_queues_create(struct be_adapter *adapter) rc = be_cmd_eq_create(adapter, eqo); if (rc) return rc; + + if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL)) + return -ENOMEM; + cpumask_set_cpu(cpumask_local_spread(i, numa_node), + eqo->affinity_mask); + netif_napi_add(adapter->netdev, &eqo->napi, be_poll, + BE_NAPI_WEIGHT); + napi_hash_add(&eqo->napi); } return 0; } @@ -2573,7 +2824,7 @@ static irqreturn_t be_intx(int irq, void *dev) if (num_evts) eqo->spurious_intr = 0; } - be_eq_notify(adapter, eqo->q.id, false, true, num_evts); + be_eq_notify(adapter, eqo->q.id, false, true, num_evts, 0); /* Return IRQ_HANDLED only for the the first spurious intr * after a valid intr to stop the kernel from branding @@ -2589,7 +2840,7 @@ static irqreturn_t be_msix(int irq, void *dev) { struct be_eq_obj *eqo = dev; - be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); + be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0, 0); napi_schedule(&eqo->napi); return IRQ_HANDLED; } @@ -2838,6 +3089,7 @@ int be_poll(struct napi_struct *napi, int budget) int max_work = 0, work, i, num_evts; struct be_rx_obj *rxo; struct be_tx_obj *txo; + u32 mult_enc = 0; num_evts = events_get(eqo); @@ -2863,10 +3115,18 @@ int be_poll(struct napi_struct *napi, int budget) if (max_work < budget) { napi_complete(napi); - be_eq_notify(adapter, eqo->q.id, true, false, num_evts); + + /* Skyhawk EQ_DB has a provision to set the rearm to interrupt + * delay via a delay multiplier encoding value + */ + if (skyhawk_chip(adapter)) + mult_enc = be_get_eq_delay_mult_enc(eqo); + + be_eq_notify(adapter, eqo->q.id, true, false, num_evts, + mult_enc); } else { /* As we'll continue in polling mode, count and clear events */ - be_eq_notify(adapter, eqo->q.id, false, false, num_evts); + be_eq_notify(adapter, eqo->q.id, false, false, num_evts, 0); } return max_work; } @@ -2898,22 +3158,19 @@ void be_detect_error(struct be_adapter *adapter) u32 ue_lo = 0, ue_hi = 0, ue_lo_mask = 0, ue_hi_mask = 0; u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; u32 i; - bool error_detected = false; struct device *dev = &adapter->pdev->dev; - struct net_device *netdev = adapter->netdev; - if (be_hw_error(adapter)) + if (be_check_error(adapter, BE_ERROR_HW)) return; if (lancer_chip(adapter)) { sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); if (sliport_status & SLIPORT_STATUS_ERR_MASK) { + be_set_error(adapter, BE_ERROR_UE); sliport_err1 = ioread32(adapter->db + SLIPORT_ERROR1_OFFSET); sliport_err2 = ioread32(adapter->db + SLIPORT_ERROR2_OFFSET); - adapter->hw_error = true; - error_detected = true; /* Do not log error messages if its a FW reset */ if (sliport_err1 == SLIPORT_ERROR_FW_RESET1 && sliport_err2 == SLIPORT_ERROR_FW_RESET2) { @@ -2945,12 +3202,12 @@ void be_detect_error(struct be_adapter *adapter) */ if (ue_lo || ue_hi) { - error_detected = true; dev_err(dev, "Unrecoverable Error detected in the adapter"); dev_err(dev, "Please reboot server to recover"); if (skyhawk_chip(adapter)) - adapter->hw_error = true; + be_set_error(adapter, BE_ERROR_UE); + for (i = 0; ue_lo; ue_lo >>= 1, i++) { if (ue_lo & 1) dev_err(dev, "UE: %s bit set\n", @@ -2963,8 +3220,6 @@ void be_detect_error(struct be_adapter *adapter) } } } - if (error_detected) - netif_carrier_off(netdev); } static void be_msix_disable(struct be_adapter *adapter) @@ -3015,7 +3270,7 @@ fail: dev_warn(dev, "MSIx enable failed\n"); /* INTx is not supported in VFs, so fail probe if enable_msix fails */ - if (!be_physfn(adapter)) + if (be_virtfn(adapter)) return num_vec; return 0; } @@ -3044,8 +3299,10 @@ static int be_msix_register(struct be_adapter *adapter) return 0; err_msix: - for (i--, eqo = &adapter->eq_obj[i]; i >= 0; i--, eqo--) + for (i--; i >= 0; i--) { + eqo = &adapter->eq_obj[i]; free_irq(be_msix_vec_get(adapter, eqo), eqo); + } dev_warn(&adapter->pdev->dev, "MSIX Request IRQ failed - err %d\n", status); be_msix_disable(adapter); @@ -3062,7 +3319,7 @@ static int be_irq_register(struct be_adapter *adapter) if (status == 0) goto done; /* INTx is not supported for VF */ - if (!be_physfn(adapter)) + if (be_virtfn(adapter)) return status; } @@ -3115,13 +3372,54 @@ static void be_rx_qs_destroy(struct be_adapter *adapter) for_all_rx_queues(adapter, rxo, i) { q = &rxo->q; if (q->created) { + /* If RXQs are destroyed while in an "out of buffer" + * state, there is a possibility of an HW stall on + * Lancer. So, post 64 buffers to each queue to relieve + * the "out of buffer" condition. + * Make sure there's space in the RXQ before posting. + */ + if (lancer_chip(adapter)) { + be_rx_cq_clean(rxo); + if (atomic_read(&q->used) == 0) + be_post_rx_frags(rxo, GFP_KERNEL, + MAX_RX_POST); + } + be_cmd_rxq_destroy(adapter, q); be_rx_cq_clean(rxo); + be_rxq_clean(rxo); } be_queue_free(adapter, q); } } +static void be_disable_if_filters(struct be_adapter *adapter) +{ + be_cmd_pmac_del(adapter, adapter->if_handle, + adapter->pmac_id[0], 0); + + be_clear_uc_list(adapter); + + /* The IFACE flags are enabled in the open path and cleared + * in the close path. When a VF gets detached from the host and + * assigned to a VM the following happens: + * - VF's IFACE flags get cleared in the detach path + * - IFACE create is issued by the VF in the attach path + * Due to a bug in the BE3/Skyhawk-R FW + * (Lancer FW doesn't have the bug), the IFACE capability flags + * specified along with the IFACE create cmd issued by a VF are not + * honoured by FW. As a consequence, if a *new* driver + * (that enables/disables IFACE flags in open/close) + * is loaded in the host and an *old* driver is * used by a VM/VF, + * the IFACE gets created *without* the needed flags. + * To avoid this, disable RX-filter flags only for Lancer. + */ + if (lancer_chip(adapter)) { + be_cmd_rx_filter(adapter, BE_IF_ALL_FILT_FLAGS, OFF); + adapter->if_flags &= ~BE_IF_ALL_FILT_FLAGS; + } +} + static int be_close(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -3134,7 +3432,7 @@ static int be_close(struct net_device *netdev) if (!(adapter->flags & BE_FLAGS_SETUP_DONE)) return 0; - be_roce_dev_close(adapter); + be_disable_if_filters(adapter); if (adapter->flags & BE_FLAGS_NAPI_ENABLED) { for_all_evt_queues(adapter, eqo, i) { @@ -3153,7 +3451,6 @@ static int be_close(struct net_device *netdev) be_tx_compl_clean(adapter); be_rx_qs_destroy(adapter); - be_clear_uc_list(adapter); for_all_evt_queues(adapter, eqo, i) { if (msix_enabled(adapter)) @@ -3221,7 +3518,7 @@ static int be_rx_qs_create(struct be_adapter *adapter) netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, - 128, rss_key); + RSS_INDIR_TABLE_LEN, rss_key); if (rc) { rss->rss_flags = RSS_ENABLE_NONE; return rc; @@ -3229,9 +3526,37 @@ static int be_rx_qs_create(struct be_adapter *adapter) memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); - /* First time posting */ + /* Post 1 less than RXQ-len to avoid head being equal to tail, + * which is a queue empty condition + */ for_all_rx_queues(adapter, rxo, i) - be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST); + be_post_rx_frags(rxo, GFP_KERNEL, RX_Q_LEN - 1); + + return 0; +} + +static int be_enable_if_filters(struct be_adapter *adapter) +{ + int status; + + status = be_cmd_rx_filter(adapter, BE_IF_EN_FLAGS, ON); + if (status) + return status; + + /* For BE3 VFs, the PF programs the initial MAC address */ + if (!(BEx_chip(adapter) && be_virtfn(adapter))) { + status = be_cmd_pmac_add(adapter, adapter->netdev->dev_addr, + adapter->if_handle, + &adapter->pmac_id[0], 0); + if (status) + return status; + } + + if (adapter->vlans_added) + be_vid_config(adapter); + + be_set_rx_mode(adapter->netdev); + return 0; } @@ -3248,6 +3573,10 @@ static int be_open(struct net_device *netdev) if (status) goto err; + status = be_enable_if_filters(adapter); + if (status) + goto err; + status = be_irq_register(adapter); if (status) goto err; @@ -3263,7 +3592,7 @@ static int be_open(struct net_device *netdev) for_all_evt_queues(adapter, eqo, i) { napi_enable(&eqo->napi); be_enable_busy_poll(eqo); - be_eq_notify(adapter, eqo->q.id, true, true, 0); + be_eq_notify(adapter, eqo->q.id, true, true, 0, 0); } adapter->flags |= BE_FLAGS_NAPI_ENABLED; @@ -3272,8 +3601,6 @@ static int be_open(struct net_device *netdev) be_link_status_update(adapter, link_status); netif_tx_start_all_queues(netdev); - be_roce_dev_open(adapter); - #ifdef CONFIG_BE2NET_VXLAN if (skyhawk_chip(adapter)) vxlan_get_rx_port(netdev); @@ -3287,15 +3614,15 @@ err: static int be_setup_wol(struct be_adapter *adapter, bool enable) { + struct device *dev = &adapter->pdev->dev; struct be_dma_mem cmd; - int status = 0; u8 mac[ETH_ALEN]; + int status; eth_zero_addr(mac); cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config); - cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma, - GFP_KERNEL); + cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL); if (!cmd.va) return -ENOMEM; @@ -3304,24 +3631,18 @@ static int be_setup_wol(struct be_adapter *adapter, bool enable) PCICFG_PM_CONTROL_OFFSET, PCICFG_PM_CONTROL_MASK); if (status) { - dev_err(&adapter->pdev->dev, - "Could not enable Wake-on-lan\n"); - dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, - cmd.dma); - return status; + dev_err(dev, "Could not enable Wake-on-lan\n"); + goto err; } - status = be_cmd_enable_magic_wol(adapter, - adapter->netdev->dev_addr, - &cmd); - pci_enable_wake(adapter->pdev, PCI_D3hot, 1); - pci_enable_wake(adapter->pdev, PCI_D3cold, 1); } else { - status = be_cmd_enable_magic_wol(adapter, mac, &cmd); - pci_enable_wake(adapter->pdev, PCI_D3hot, 0); - pci_enable_wake(adapter->pdev, PCI_D3cold, 0); + ether_addr_copy(mac, adapter->netdev->dev_addr); } - dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma); + status = be_cmd_enable_magic_wol(adapter, mac, &cmd); + pci_enable_wake(adapter->pdev, PCI_D3hot, enable); + pci_enable_wake(adapter->pdev, PCI_D3cold, enable); +err: + dma_free_coherent(dev, cmd.size, cmd.va, cmd.dma); return status; } @@ -3444,16 +3765,6 @@ static void be_cancel_err_detection(struct be_adapter *adapter) } } -static void be_mac_clear(struct be_adapter *adapter) -{ - if (adapter->pmac_id) { - be_cmd_pmac_del(adapter, adapter->if_handle, - adapter->pmac_id[0], 0); - kfree(adapter->pmac_id); - adapter->pmac_id = NULL; - } -} - #ifdef CONFIG_BE2NET_VXLAN static void be_disable_vxlan_offloads(struct be_adapter *adapter) { @@ -3528,8 +3839,8 @@ static int be_clear(struct be_adapter *adapter) #ifdef CONFIG_BE2NET_VXLAN be_disable_vxlan_offloads(adapter); #endif - /* delete the primary mac along with the uc-mac list */ - be_mac_clear(adapter); + kfree(adapter->pmac_id); + adapter->pmac_id = NULL; be_cmd_if_destroy(adapter, adapter->if_handle, 0); @@ -3540,30 +3851,16 @@ static int be_clear(struct be_adapter *adapter) return 0; } -static int be_if_create(struct be_adapter *adapter, u32 *if_handle, - u32 cap_flags, u32 vf) -{ - u32 en_flags; - - en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS | - BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS; - - en_flags &= cap_flags; - - return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf); -} - static int be_vfs_if_create(struct be_adapter *adapter) { struct be_resources res = {0}; + u32 cap_flags, en_flags, vf; struct be_vf_cfg *vf_cfg; - u32 cap_flags, vf; int status; /* If a FW profile exists, then cap_flags are updated */ cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST; + BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS; for_all_vfs(adapter, vf_cfg, vf) { if (!BE3_chip(adapter)) { @@ -3579,8 +3876,12 @@ static int be_vfs_if_create(struct be_adapter *adapter) } } - status = be_if_create(adapter, &vf_cfg->if_handle, - cap_flags, vf + 1); + en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST | + BE_IF_FLAGS_PASS_L3L4_ERRORS); + status = be_cmd_if_create(adapter, cap_flags, en_flags, + &vf_cfg->if_handle, vf + 1); if (status) return status; } @@ -3610,6 +3911,7 @@ static int be_vf_setup(struct be_adapter *adapter) struct device *dev = &adapter->pdev->dev; struct be_vf_cfg *vf_cfg; int status, old_vfs, vf; + bool spoofchk; old_vfs = pci_num_vf(adapter->pdev); @@ -3657,6 +3959,12 @@ static int be_vf_setup(struct be_adapter *adapter) if (!old_vfs) be_cmd_config_qos(adapter, 0, 0, vf + 1); + status = be_cmd_get_hsw_config(adapter, NULL, vf + 1, + vf_cfg->if_handle, NULL, + &spoofchk); + if (!status) + vf_cfg->spoofchk = spoofchk; + if (!old_vfs) { be_cmd_enable_vf(adapter, vf + 1); be_cmd_set_logical_link_config(adapter, @@ -3733,8 +4041,9 @@ static void BEx_get_resources(struct be_adapter *adapter, * *only* if it is RSS-capable. */ if (BE2_chip(adapter) || use_sriov || (adapter->port_num > 1) || - !be_physfn(adapter) || (be_is_mc(adapter) && - !(adapter->function_caps & BE_FUNCTION_CAPS_RSS))) { + be_virtfn(adapter) || + (be_is_mc(adapter) && + !(adapter->function_caps & BE_FUNCTION_CAPS_RSS))) { res->max_tx_qs = 1; } else if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) { struct be_resources super_nic_res = {0}; @@ -3895,10 +4204,6 @@ static int be_get_config(struct be_adapter *adapter) int status, level; u16 profile_id; - status = be_cmd_get_cntl_attributes(adapter); - if (status) - return status; - status = be_cmd_query_fw_cfg(adapter); if (status) return status; @@ -3944,15 +4249,8 @@ static int be_mac_setup(struct be_adapter *adapter) memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN); - } else { - /* Maybe the HW was reset; dev_addr must be re-programmed */ - memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN); } - /* For BE3-R VFs, the PF programs the initial MAC address */ - if (!(BEx_chip(adapter) && be_virtfn(adapter))) - be_cmd_pmac_add(adapter, mac, adapter->if_handle, - &adapter->pmac_id[0], 0); return 0; } @@ -4075,7 +4373,7 @@ static int be_func_init(struct be_adapter *adapter) msleep(100); /* We can clear all errors when function reset succeeds */ - be_clear_all_error(adapter); + be_clear_error(adapter, BE_CLEAR_ALL); } /* Tell FW we're ready to fire cmds */ @@ -4092,6 +4390,7 @@ static int be_func_init(struct be_adapter *adapter) static int be_setup(struct be_adapter *adapter) { struct device *dev = &adapter->pdev->dev; + u32 en_flags; int status; status = be_func_init(adapter); @@ -4103,6 +4402,11 @@ static int be_setup(struct be_adapter *adapter) if (!lancer_chip(adapter)) be_cmd_req_native_mode(adapter); + /* Need to invoke this cmd first to get the PCI Function Number */ + status = be_cmd_get_cntl_attributes(adapter); + if (status) + return status; + if (!BE2_chip(adapter) && be_physfn(adapter)) be_alloc_sriov_res(adapter); @@ -4114,8 +4418,11 @@ static int be_setup(struct be_adapter *adapter) if (status) goto err; - status = be_if_create(adapter, &adapter->if_handle, - be_if_cap_flags(adapter), 0); + /* will enable all the needed filter flags in be_open() */ + en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS; + en_flags = en_flags & be_if_cap_flags(adapter); + status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags, + &adapter->if_handle, 0); if (status) goto err; @@ -4141,11 +4448,6 @@ static int be_setup(struct be_adapter *adapter) dev_err(dev, "Please upgrade firmware to version >= 4.0\n"); } - if (adapter->vlans_added) - be_vid_config(adapter); - - be_set_rx_mode(adapter->netdev); - status = be_cmd_set_flow_control(adapter, adapter->tx_fc, adapter->rx_fc); if (status) @@ -4182,7 +4484,7 @@ static void be_netpoll(struct net_device *netdev) int i; for_all_evt_queues(adapter, eqo, i) { - be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); + be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0, 0); napi_schedule(&eqo->napi); } } @@ -4666,18 +4968,15 @@ static int lancer_fw_download(struct be_adapter *adapter, return 0; } -#define BE2_UFI 2 -#define BE3_UFI 3 -#define BE3R_UFI 10 -#define SH_UFI 4 -#define SH_P2_UFI 11 - -static int be_get_ufi_type(struct be_adapter *adapter, - struct flash_file_hdr_g3 *fhdr) +/* Check if the flash image file is compatible with the adapter that + * is being flashed. + */ +static bool be_check_ufi_compatibility(struct be_adapter *adapter, + struct flash_file_hdr_g3 *fhdr) { if (!fhdr) { dev_err(&adapter->pdev->dev, "Invalid FW UFI file"); - return -1; + return false; } /* First letter of the build version is used to identify @@ -4685,43 +4984,30 @@ static int be_get_ufi_type(struct be_adapter *adapter, */ switch (fhdr->build[0]) { case BLD_STR_UFI_TYPE_SH: - return (fhdr->asic_type_rev == ASIC_REV_P2) ? SH_P2_UFI : - SH_UFI; + if (!skyhawk_chip(adapter)) + return false; + break; case BLD_STR_UFI_TYPE_BE3: - return (fhdr->asic_type_rev == ASIC_REV_B0) ? BE3R_UFI : - BE3_UFI; + if (!BE3_chip(adapter)) + return false; + break; case BLD_STR_UFI_TYPE_BE2: - return BE2_UFI; - default: - return -1; - } -} - -/* Check if the flash image file is compatible with the adapter that - * is being flashed. - * BE3 chips with asic-rev B0 must be flashed only with BE3R_UFI type. - * Skyhawk chips with asic-rev P2 must be flashed only with SH_P2_UFI type. - */ -static bool be_check_ufi_compatibility(struct be_adapter *adapter, - struct flash_file_hdr_g3 *fhdr) -{ - int ufi_type = be_get_ufi_type(adapter, fhdr); - - switch (ufi_type) { - case SH_P2_UFI: - return skyhawk_chip(adapter); - case SH_UFI: - return (skyhawk_chip(adapter) && - adapter->asic_rev < ASIC_REV_P2); - case BE3R_UFI: - return BE3_chip(adapter); - case BE3_UFI: - return (BE3_chip(adapter) && adapter->asic_rev < ASIC_REV_B0); - case BE2_UFI: - return BE2_chip(adapter); + if (!BE2_chip(adapter)) + return false; + break; default: return false; } + + /* In BE3 FW images the "asic_type_rev" field doesn't track the + * asic_rev of the chips it is compatible with. + * When asic_type_rev is 0 the image is compatible only with + * pre-BE3-R chips (asic_rev < 0x10) + */ + if (BEx_chip(adapter) && fhdr->asic_type_rev == 0) + return adapter->asic_rev < 0x10; + else + return (fhdr->asic_type_rev >= adapter->asic_rev); } static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) @@ -4829,7 +5115,7 @@ static int be_ndo_bridge_setlink(struct net_device *dev, struct nlmsghdr *nlh, adapter->if_handle, mode == BRIDGE_MODE_VEPA ? PORT_FWD_TYPE_VEPA : - PORT_FWD_TYPE_VEB); + PORT_FWD_TYPE_VEB, 0); if (status) goto err; @@ -4853,23 +5139,24 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, int status = 0; u8 hsw_mode; - if (!sriov_enabled(adapter)) - return 0; - /* BE and Lancer chips support VEB mode only */ if (BEx_chip(adapter) || lancer_chip(adapter)) { hsw_mode = PORT_FWD_TYPE_VEB; } else { status = be_cmd_get_hsw_config(adapter, NULL, 0, - adapter->if_handle, &hsw_mode); + adapter->if_handle, &hsw_mode, + NULL); if (status) return 0; + + if (hsw_mode == PORT_FWD_TYPE_PASSTHRU) + return 0; } return ndo_dflt_bridge_getlink(skb, pid, seq, dev, hsw_mode == PORT_FWD_TYPE_VEPA ? BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB, - 0, 0, nlflags); + 0, 0, nlflags, filter_mask, NULL); } #ifdef CONFIG_BE2NET_VXLAN @@ -4894,9 +5181,14 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family, struct device *dev = &adapter->pdev->dev; int status; - if (lancer_chip(adapter) || BEx_chip(adapter)) + if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter)) return; + if (adapter->vxlan_port == port && adapter->vxlan_port_count) { + adapter->vxlan_port_aliases++; + return; + } + if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) { dev_info(dev, "Only one UDP port supported for VxLAN offloads\n"); @@ -4941,12 +5233,17 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family, { struct be_adapter *adapter = netdev_priv(netdev); - if (lancer_chip(adapter) || BEx_chip(adapter)) + if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter)) return; if (adapter->vxlan_port != port) goto done; + if (adapter->vxlan_port_aliases) { + adapter->vxlan_port_aliases--; + return; + } + be_disable_vxlan_offloads(adapter); dev_info(&adapter->pdev->dev, @@ -4998,6 +5295,27 @@ static netdev_features_t be_features_check(struct sk_buff *skb, } #endif +static int be_get_phys_port_id(struct net_device *dev, + struct netdev_phys_item_id *ppid) +{ + int i, id_len = CNTL_SERIAL_NUM_WORDS * CNTL_SERIAL_NUM_WORD_SZ + 1; + struct be_adapter *adapter = netdev_priv(dev); + u8 *id; + + if (MAX_PHYS_ITEM_ID_LEN < id_len) + return -ENOSPC; + + ppid->id[0] = adapter->hba_port_num + 1; + id = &ppid->id[1]; + for (i = CNTL_SERIAL_NUM_WORDS - 1; i >= 0; + i--, id += CNTL_SERIAL_NUM_WORD_SZ) + memcpy(id, &adapter->serial_num[i], CNTL_SERIAL_NUM_WORD_SZ); + + ppid->id_len = id_len; + + return 0; +} + static const struct net_device_ops be_netdev_ops = { .ndo_open = be_open, .ndo_stop = be_close, @@ -5014,6 +5332,7 @@ static const struct net_device_ops be_netdev_ops = { .ndo_set_vf_rate = be_set_vf_tx_rate, .ndo_get_vf_config = be_get_vf_config, .ndo_set_vf_link_state = be_set_vf_link_state, + .ndo_set_vf_spoofchk = be_set_vf_spoofchk, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = be_netpoll, #endif @@ -5027,6 +5346,7 @@ static const struct net_device_ops be_netdev_ops = { .ndo_del_vxlan_port = be_del_vxlan_port, .ndo_features_check = be_features_check, #endif + .ndo_get_phys_port_id = be_get_phys_port_id, }; static void be_netdev_init(struct net_device *netdev) @@ -5118,7 +5438,7 @@ static void be_err_detection_task(struct work_struct *work) be_detect_error(adapter); - if (adapter->hw_error) { + if (be_check_error(adapter, BE_ERROR_HW)) { be_cleanup(adapter); /* As of now error recovery support is in Lancer only */ @@ -5182,7 +5502,9 @@ static void be_worker(struct work_struct *work) be_post_rx_frags(rxo, GFP_KERNEL, MAX_RX_POST); } - be_eqd_update(adapter); + /* EQ-delay update for Skyhawk is done while notifying EQ */ + if (!skyhawk_chip(adapter)) + be_eqd_update(adapter, false); if (adapter->flags & BE_FLAGS_EVT_INCOMPATIBLE_SFP) be_log_sfp_info(adapter); @@ -5202,7 +5524,7 @@ static void be_unmap_pci_bars(struct be_adapter *adapter) static int db_bar(struct be_adapter *adapter) { - if (lancer_chip(adapter) || !be_physfn(adapter)) + if (lancer_chip(adapter) || be_virtfn(adapter)) return 0; else return 4; @@ -5381,6 +5703,30 @@ static void be_remove(struct pci_dev *pdev) free_netdev(adapter->netdev); } +static ssize_t be_hwmon_show_temp(struct device *dev, + struct device_attribute *dev_attr, + char *buf) +{ + struct be_adapter *adapter = dev_get_drvdata(dev); + + /* Unit: millidegree Celsius */ + if (adapter->hwmon_info.be_on_die_temp == BE_INVALID_DIE_TEMP) + return -EIO; + else + return sprintf(buf, "%u\n", + adapter->hwmon_info.be_on_die_temp * 1000); +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, + be_hwmon_show_temp, NULL, 1); + +static struct attribute *be_hwmon_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + NULL +}; + +ATTRIBUTE_GROUPS(be_hwmon); + static char *mc_name(struct be_adapter *adapter) { char *str = ""; /* default */ @@ -5500,6 +5846,16 @@ static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) be_schedule_err_detection(adapter); + /* On Die temperature not supported for VF. */ + if (be_physfn(adapter) && IS_ENABLED(CONFIG_BE2NET_HWMON)) { + adapter->hwmon_info.hwmon_dev = + devm_hwmon_device_register_with_groups(&pdev->dev, + DRV_NAME, + adapter, + be_hwmon_groups); + adapter->hwmon_info.be_on_die_temp = BE_INVALID_DIE_TEMP; + } + dev_info(&pdev->dev, "%s: %s %s port %c\n", nic_name(pdev), func_name(adapter), mc_name(adapter), adapter->port_name); @@ -5549,7 +5905,6 @@ static int be_pci_resume(struct pci_dev *pdev) if (status) return status; - pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); status = be_resume(adapter); @@ -5592,8 +5947,8 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, dev_err(&adapter->pdev->dev, "EEH error detected\n"); - if (!adapter->eeh_error) { - adapter->eeh_error = true; + if (!be_check_error(adapter, BE_ERROR_EEH)) { + be_set_error(adapter, BE_ERROR_EEH); be_cancel_err_detection(adapter); @@ -5629,7 +5984,6 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; pci_set_master(pdev); - pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); /* Check if card is ok and fw is ready */ @@ -5640,7 +5994,7 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) return PCI_ERS_RESULT_DISCONNECT; pci_cleanup_aer_uncorrect_error_status(pdev); - be_clear_all_error(adapter); + be_clear_error(adapter, BE_CLEAR_ALL); return PCI_ERS_RESULT_RECOVERED; } diff --git a/kernel/drivers/net/ethernet/emulex/benet/be_roce.c b/kernel/drivers/net/ethernet/emulex/benet/be_roce.c index 132866433..4089156a7 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be_roce.c +++ b/kernel/drivers/net/ethernet/emulex/benet/be_roce.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -116,40 +116,6 @@ void be_roce_dev_remove(struct be_adapter *adapter) } } -static void _be_roce_dev_open(struct be_adapter *adapter) -{ - if (ocrdma_drv && adapter->ocrdma_dev && - ocrdma_drv->state_change_handler) - ocrdma_drv->state_change_handler(adapter->ocrdma_dev, - BE_DEV_UP); -} - -void be_roce_dev_open(struct be_adapter *adapter) -{ - if (be_roce_supported(adapter)) { - mutex_lock(&be_adapter_list_lock); - _be_roce_dev_open(adapter); - mutex_unlock(&be_adapter_list_lock); - } -} - -static void _be_roce_dev_close(struct be_adapter *adapter) -{ - if (ocrdma_drv && adapter->ocrdma_dev && - ocrdma_drv->state_change_handler) - ocrdma_drv->state_change_handler(adapter->ocrdma_dev, - BE_DEV_DOWN); -} - -void be_roce_dev_close(struct be_adapter *adapter) -{ - if (be_roce_supported(adapter)) { - mutex_lock(&be_adapter_list_lock); - _be_roce_dev_close(adapter); - mutex_unlock(&be_adapter_list_lock); - } -} - void be_roce_dev_shutdown(struct be_adapter *adapter) { if (be_roce_supported(adapter)) { @@ -177,8 +143,6 @@ int be_roce_register_driver(struct ocrdma_driver *drv) _be_roce_dev_add(dev); netdev = dev->netdev; - if (netif_running(netdev) && netif_oper_up(netdev)) - _be_roce_dev_open(dev); } mutex_unlock(&be_adapter_list_lock); return 0; diff --git a/kernel/drivers/net/ethernet/emulex/benet/be_roce.h b/kernel/drivers/net/ethernet/emulex/benet/be_roce.h index e6f7eb1a7..fde609789 100644 --- a/kernel/drivers/net/ethernet/emulex/benet/be_roce.h +++ b/kernel/drivers/net/ethernet/emulex/benet/be_roce.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 - 2014 Emulex + * Copyright (C) 2005 - 2015 Emulex * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -60,9 +60,7 @@ struct ocrdma_driver { void (*state_change_handler) (struct ocrdma_dev *, u32 new_state); }; -enum { - BE_DEV_UP = 0, - BE_DEV_DOWN = 1, +enum be_roce_event { BE_DEV_SHUTDOWN = 2 }; |