diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 18:07:07 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 18:07:07 -0800 |
commit | 6be35c700f742e911ecedd07fcc43d4439922334 (patch) | |
tree | ca9f37214d204465fcc2d79c82efd291e357c53c /drivers/net/ethernet/emulex | |
parent | e37aa63e87bd581f9be5555ed0ba83f5295c92fc (diff) | |
parent | 520dfe3a3645257bf83660f672c47f8558f3d4c4 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller:
1) Allow to dump, monitor, and change the bridge multicast database
using netlink. From Cong Wang.
2) RFC 5961 TCP blind data injection attack mitigation, from Eric
Dumazet.
3) Networking user namespace support from Eric W. Biederman.
4) tuntap/virtio-net multiqueue support by Jason Wang.
5) Support for checksum offload of encapsulated packets (basically,
tunneled traffic can still be checksummed by HW). From Joseph
Gasparakis.
6) Allow BPF filter access to VLAN tags, from Eric Dumazet and
Daniel Borkmann.
7) Bridge port parameters over netlink and BPDU blocking support
from Stephen Hemminger.
8) Improve data access patterns during inet socket demux by rearranging
socket layout, from Eric Dumazet.
9) TIPC protocol updates and cleanups from Ying Xue, Paul Gortmaker, and
Jon Maloy.
10) Update TCP socket hash sizing to be more in line with current day
realities. The existing heurstics were choosen a decade ago.
From Eric Dumazet.
11) Fix races, queue bloat, and excessive wakeups in ATM and
associated drivers, from Krzysztof Mazur and David Woodhouse.
12) Support DOVE (Distributed Overlay Virtual Ethernet) extensions
in VXLAN driver, from David Stevens.
13) Add "oops_only" mode to netconsole, from Amerigo Wang.
14) Support set and query of VEB/VEPA bridge mode via PF_BRIDGE, also
allow DCB netlink to work on namespaces other than the initial
namespace. From John Fastabend.
15) Support PTP in the Tigon3 driver, from Matt Carlson.
16) tun/vhost zero copy fixes and improvements, plus turn it on
by default, from Michael S. Tsirkin.
17) Support per-association statistics in SCTP, from Michele
Baldessari.
And many, many, driver updates, cleanups, and improvements. Too
numerous to mention individually.
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1722 commits)
net/mlx4_en: Add support for destination MAC in steering rules
net/mlx4_en: Use generic etherdevice.h functions.
net: ethtool: Add destination MAC address to flow steering API
bridge: add support of adding and deleting mdb entries
bridge: notify mdb changes via netlink
ndisc: Unexport ndisc_{build,send}_skb().
uapi: add missing netconf.h to export list
pkt_sched: avoid requeues if possible
solos-pci: fix double-free of TX skb in DMA mode
bnx2: Fix accidental reversions.
bna: Driver Version Updated to 3.1.2.1
bna: Firmware update
bna: Add RX State
bna: Rx Page Based Allocation
bna: TX Intr Coalescing Fix
bna: Tx and Rx Optimizations
bna: Code Cleanup and Enhancements
ath9k: check pdata variable before dereferencing it
ath5k: RX timestamp is reported at end of frame
ath9k_htc: RX timestamp is reported at end of frame
...
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 51 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.c | 409 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_cmds.h | 177 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 80 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_hw.h | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 849 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_roce.c | 5 |
9 files changed, 1136 insertions, 459 deletions
diff --git a/drivers/net/ethernet/emulex/Kconfig b/drivers/net/ethernet/emulex/Kconfig index 7a28a6433944..1b8d638c6cb1 100644 --- a/drivers/net/ethernet/emulex/Kconfig +++ b/drivers/net/ethernet/emulex/Kconfig @@ -5,7 +5,7 @@ config NET_VENDOR_EMULEX bool "Emulex devices" default y - depends on PCI && INET + depends on PCI ---help--- If you have a network (Ethernet) card belonging to this class, say Y and read the Ethernet-HOWTO, available from diff --git a/drivers/net/ethernet/emulex/benet/Kconfig b/drivers/net/ethernet/emulex/benet/Kconfig index 804db04a2bd0..231129dd1764 100644 --- a/drivers/net/ethernet/emulex/benet/Kconfig +++ b/drivers/net/ethernet/emulex/benet/Kconfig @@ -1,6 +1,6 @@ config BE2NET tristate "ServerEngines' 10Gbps NIC - BladeEngine" - depends on PCI && INET + depends on PCI ---help--- This driver implements the NIC functionality for ServerEngines' 10Gbps network adapter - BladeEngine. diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index cf4c05bdf5fe..abf26c7c1d19 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -34,7 +34,7 @@ #include "be_hw.h" #include "be_roce.h" -#define DRV_VER "4.4.31.0u" +#define DRV_VER "4.4.161.0u" #define DRV_NAME "be2net" #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" @@ -53,6 +53,7 @@ #define OC_DEVICE_ID3 0xe220 /* Device id for Lancer cards */ #define OC_DEVICE_ID4 0xe228 /* Device id for VF in Lancer */ #define OC_DEVICE_ID5 0x720 /* Device Id for Skyhawk cards */ +#define OC_DEVICE_ID6 0x728 /* Device id for VF in SkyHawk */ #define OC_SUBSYS_DEVICE_ID1 0xE602 #define OC_SUBSYS_DEVICE_ID2 0xE642 #define OC_SUBSYS_DEVICE_ID3 0xE612 @@ -71,6 +72,7 @@ static inline char *nic_name(struct pci_dev *pdev) case BE_DEVICE_ID2: return BE3_NAME; case OC_DEVICE_ID5: + case OC_DEVICE_ID6: return OC_NAME_SH; default: return BE_NAME; @@ -346,7 +348,6 @@ struct be_adapter { struct pci_dev *pdev; struct net_device *netdev; - u8 __iomem *csr; u8 __iomem *db; /* Door Bell */ struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ @@ -374,11 +375,8 @@ struct be_adapter { struct be_rx_obj rx_obj[MAX_RX_QS]; u32 big_page_size; /* Compounded page size shared by rx wrbs */ - u8 eq_next_idx; struct be_drv_stats drv_stats; - u16 vlans_added; - u16 max_vlans; /* Number of vlans supported */ u8 vlan_tag[VLAN_N_VID]; u8 vlan_prio_bmap; /* Available Priority BitMap */ u16 recommended_prio; /* Recommended Priority */ @@ -391,6 +389,7 @@ struct be_adapter { struct delayed_work func_recovery_work; u32 flags; + u32 cmd_privileges; /* Ethtool knobs and info */ char fw_ver[FW_VER_LEN]; int if_handle; /* Used to configure filtering */ @@ -408,10 +407,8 @@ struct be_adapter { u32 rx_fc; /* Rx flow control */ u32 tx_fc; /* Tx flow control */ bool stats_cmd_sent; - u8 generation; /* BladeEngine ASIC generation */ u32 if_type; struct { - u8 __iomem *base; /* Door Bell */ u32 size; u32 total_size; u64 io_addr; @@ -434,10 +431,18 @@ struct be_adapter { struct phy_info phy; u8 wol_cap; bool wol; - u32 max_pmac_cnt; /* Max secondary UC MACs programmable */ u32 uc_macs; /* Count of secondary UC MAC programmed */ u32 msg_enable; int be_get_temp_freq; + u16 max_mcast_mac; + u16 max_tx_queues; + u16 max_rss_queues; + u16 max_rx_queues; + u16 max_pmac_cnt; + u16 max_vlans; + u16 max_event_queues; + u32 if_cap_flags; + u8 pf_number; }; #define be_physfn(adapter) (!adapter->virtfn) @@ -448,21 +453,25 @@ struct be_adapter { for (i = 0, vf_cfg = &adapter->vf_cfg[i]; i < adapter->num_vfs; \ i++, vf_cfg++) -/* BladeEngine Generation numbers */ -#define BE_GEN2 2 -#define BE_GEN3 3 - #define ON 1 #define OFF 0 -#define lancer_chip(adapter) ((adapter->pdev->device == OC_DEVICE_ID3) || \ - (adapter->pdev->device == OC_DEVICE_ID4)) -#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5) +#define lancer_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID3 || \ + adapter->pdev->device == OC_DEVICE_ID4) + +#define skyhawk_chip(adapter) (adapter->pdev->device == OC_DEVICE_ID5 || \ + adapter->pdev->device == OC_DEVICE_ID6) + +#define BE3_chip(adapter) (adapter->pdev->device == BE_DEVICE_ID2 || \ + adapter->pdev->device == OC_DEVICE_ID2) +#define BE2_chip(adapter) (adapter->pdev->device == BE_DEVICE_ID1 || \ + adapter->pdev->device == OC_DEVICE_ID1) -#define be_roce_supported(adapter) ((adapter->if_type == SLI_INTF_TYPE_3 || \ - adapter->sli_family == SKYHAWK_SLI_FAMILY) && \ - (adapter->function_mode & RDMA_ENABLED)) +#define BEx_chip(adapter) (BE3_chip(adapter) || BE2_chip(adapter)) + +#define be_roce_supported(adapter) (skyhawk_chip(adapter) && \ + (adapter->function_mode & RDMA_ENABLED)) extern const struct ethtool_ops be_ethtool_ops; @@ -637,12 +646,6 @@ static inline bool be_is_wol_excluded(struct be_adapter *adapter) } } -static inline bool be_type_2_3(struct be_adapter *adapter) -{ - return (adapter->if_type == SLI_INTF_TYPE_2 || - adapter->if_type == SLI_INTF_TYPE_3) ? true : false; -} - extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped); extern void be_link_status_update(struct be_adapter *adapter, u8 link_status); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index af60bb26e330..f2875aa47661 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -19,6 +19,55 @@ #include "be.h" #include "be_cmds.h" +static struct be_cmd_priv_map cmd_priv_map[] = { + { + OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, + CMD_SUBSYSTEM_ETH, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_COMMON_GET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON, + BE_PRIV_LNKQUERY | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_COMMON_SET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_ETH_GET_PPORT_STATS, + CMD_SUBSYSTEM_ETH, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + }, + { + OPCODE_COMMON_GET_PHY_DETAILS, + CMD_SUBSYSTEM_COMMON, + BE_PRIV_LNKMGMT | BE_PRIV_VHADM | + BE_PRIV_DEVCFG | BE_PRIV_DEVSEC + } +}; + +static bool be_cmd_allowed(struct be_adapter *adapter, u8 opcode, + u8 subsystem) +{ + int i; + int num_entries = sizeof(cmd_priv_map)/sizeof(struct be_cmd_priv_map); + u32 cmd_privileges = adapter->cmd_privileges; + + for (i = 0; i < num_entries; i++) + if (opcode == cmd_priv_map[i].opcode && + subsystem == cmd_priv_map[i].subsystem) + if (!(cmd_privileges & cmd_priv_map[i].priv_mask)) + return false; + + return true; +} + static inline void *embedded_payload(struct be_mcc_wrb *wrb) { return wrb->payload.embedded_payload; @@ -419,14 +468,13 @@ static int be_mbox_notify_wait(struct be_adapter *adapter) static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) { u32 sem; + u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH : + SLIPORT_SEMAPHORE_OFFSET_BE; - if (lancer_chip(adapter)) - sem = ioread32(adapter->db + MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET); - else - sem = ioread32(adapter->csr + MPU_EP_SEMAPHORE_OFFSET); + pci_read_config_dword(adapter->pdev, reg, &sem); + *stage = sem & POST_STAGE_MASK; - *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK; - if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK) + if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK) return -1; else return 0; @@ -452,10 +500,33 @@ int lancer_wait_ready(struct be_adapter *adapter) return status; } +static bool lancer_provisioning_error(struct be_adapter *adapter) +{ + u32 sliport_status = 0, sliport_err1 = 0, sliport_err2 = 0; + sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); + if (sliport_status & SLIPORT_STATUS_ERR_MASK) { + sliport_err1 = ioread32(adapter->db + + SLIPORT_ERROR1_OFFSET); + sliport_err2 = ioread32(adapter->db + + SLIPORT_ERROR2_OFFSET); + + if (sliport_err1 == SLIPORT_ERROR_NO_RESOURCE1 && + sliport_err2 == SLIPORT_ERROR_NO_RESOURCE2) + return true; + } + return false; +} + int lancer_test_and_set_rdy_state(struct be_adapter *adapter) { int status; u32 sliport_status, err, reset_needed; + bool resource_error; + + resource_error = lancer_provisioning_error(adapter); + if (resource_error) + return -1; + status = lancer_wait_ready(adapter); if (!status) { sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET); @@ -477,6 +548,14 @@ int lancer_test_and_set_rdy_state(struct be_adapter *adapter) status = -1; } } + /* Stop error recovery if error is not recoverable. + * No resource error is temporary errors and will go away + * when PF provisions resources. + */ + resource_error = lancer_provisioning_error(adapter); + if (status == -1 && !resource_error) + adapter->eeh_error = true; + return status; } @@ -601,6 +680,9 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) struct be_queue_info *mccq = &adapter->mcc_obj.q; struct be_mcc_wrb *wrb; + if (!mccq->created) + return NULL; + if (atomic_read(&mccq->used) >= mccq->len) { dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n"); return NULL; @@ -1155,8 +1237,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, req->id = cpu_to_le16(q->id); status = be_mbox_notify_wait(adapter); - if (!status) - q->created = false; + q->created = false; mutex_unlock(&adapter->mbox_lock); return status; @@ -1183,8 +1264,7 @@ int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) req->id = cpu_to_le16(q->id); status = be_mcc_notify_wait(adapter); - if (!status) - q->created = false; + q->created = false; err: spin_unlock_bh(&adapter->mcc_lock); @@ -1281,7 +1361,8 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) be_wrb_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size, wrb, nonemb_cmd); - if (adapter->generation == BE_GEN3) + /* version 1 of the cmd is not supported only by BE2 */ + if (!BE2_chip(adapter)) hdr->version = 1; be_mcc_notify(adapter); @@ -1301,6 +1382,10 @@ int lancer_cmd_get_pport_stats(struct be_adapter *adapter, struct lancer_cmd_req_pport_stats *req; int status = 0; + if (!be_cmd_allowed(adapter, OPCODE_ETH_GET_PPORT_STATS, + CMD_SUBSYSTEM_ETH)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -1367,7 +1452,8 @@ int be_cmd_link_status_query(struct be_adapter *adapter, u16 *link_speed, 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)) + /* version 1 of the cmd is not supported only by BE2 */ + if (!BE2_chip(adapter)) req->hdr.version = 1; req->hdr.domain = dom; @@ -1658,9 +1744,9 @@ int be_cmd_rx_filter(struct be_adapter *adapter, u32 flags, u32 value) /* Reset mcast promisc mode if already set by setting mask * and not setting flags field */ - if (!lancer_chip(adapter) || be_physfn(adapter)) - req->if_flags_mask |= - cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS); + req->if_flags_mask |= + cpu_to_le32(BE_IF_FLAGS_MCAST_PROMISCUOUS & + adapter->if_cap_flags); req->mcast_num = cpu_to_le32(netdev_mc_count(adapter->netdev)); netdev_for_each_mc_addr(ha, adapter->netdev) @@ -1680,6 +1766,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) struct be_cmd_req_set_flow_control *req; int status; + if (!be_cmd_allowed(adapter, OPCODE_COMMON_SET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -1709,6 +1799,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) struct be_cmd_req_get_flow_control *req; int status; + if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_FLOW_CONTROL, + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -2067,7 +2161,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, int offset) { struct be_mcc_wrb *wrb; - struct be_cmd_write_flashrom *req; + struct be_cmd_read_flash_crc *req; int status; spin_lock_bh(&adapter->mcc_lock); @@ -2080,7 +2174,8 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, req = embedded_payload(wrb); be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, - OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4, wrb, NULL); + OPCODE_COMMON_READ_FLASHROM, sizeof(*req), + wrb, NULL); req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT); req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); @@ -2089,7 +2184,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, status = be_mcc_notify_wait(adapter); if (!status) - memcpy(flashed_crc, req->params.data_buf, 4); + memcpy(flashed_crc, req->crc, 4); err: spin_unlock_bh(&adapter->mcc_lock); @@ -2275,6 +2370,10 @@ int be_cmd_get_phy_info(struct be_adapter *adapter) struct be_dma_mem cmd; int status; + if (!be_cmd_allowed(adapter, OPCODE_COMMON_GET_PHY_DETAILS, + CMD_SUBSYSTEM_COMMON)) + return -EPERM; + spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); @@ -2434,6 +2533,42 @@ err: return status; } +/* Get privilege(s) for a function */ +int be_cmd_get_fn_privileges(struct be_adapter *adapter, u32 *privilege, + u32 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_fn_privileges *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FN_PRIVILEGES, sizeof(*req), + wrb, NULL); + + req->hdr.domain = domain; + + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_fn_privileges *resp = + embedded_payload(wrb); + *privilege = le32_to_cpu(resp->privilege_mask); + } + +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + /* Uses synchronous MCCQ */ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, bool *pmac_id_active, u32 *pmac_id, u8 domain) @@ -2651,6 +2786,10 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter) int payload_len = sizeof(*req); struct be_dma_mem cmd; + if (!be_cmd_allowed(adapter, OPCODE_ETH_ACPI_WOL_MAGIC_CONFIG, + CMD_SUBSYSTEM_ETH)) + return -EPERM; + memset(&cmd, 0, sizeof(struct be_dma_mem)); cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1); cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, @@ -2792,6 +2931,240 @@ err: return status; } +static struct be_nic_resource_desc *be_get_nic_desc(u8 *buf, u32 desc_count, + u32 max_buf_size) +{ + struct be_nic_resource_desc *desc = (struct be_nic_resource_desc *)buf; + int i; + + for (i = 0; i < desc_count; i++) { + desc->desc_len = RESOURCE_DESC_SIZE; + if (((void *)desc + desc->desc_len) > + (void *)(buf + max_buf_size)) { + desc = NULL; + break; + } + + if (desc->desc_type == NIC_RESOURCE_DESC_TYPE_ID) + break; + + desc = (void *)desc + desc->desc_len; + } + + if (!desc || i == MAX_RESOURCE_DESC) + return NULL; + + return desc; +} + +/* Uses Mbox */ +int be_cmd_get_func_config(struct be_adapter *adapter) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_func_config *req; + int status; + struct be_dma_mem cmd; + + memset(&cmd, 0, sizeof(struct be_dma_mem)); + cmd.size = sizeof(struct be_cmd_resp_get_func_config); + cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, + &cmd.dma); + if (!cmd.va) { + dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); + return -ENOMEM; + } + if (mutex_lock_interruptible(&adapter->mbox_lock)) + return -1; + + wrb = wrb_from_mbox(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = cmd.va; + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FUNC_CONFIG, + cmd.size, wrb, &cmd); + + status = be_mbox_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_func_config *resp = cmd.va; + u32 desc_count = le32_to_cpu(resp->desc_count); + struct be_nic_resource_desc *desc; + + desc = be_get_nic_desc(resp->func_param, desc_count, + sizeof(resp->func_param)); + if (!desc) { + status = -EINVAL; + goto err; + } + + adapter->pf_number = desc->pf_num; + adapter->max_pmac_cnt = le16_to_cpu(desc->unicast_mac_count); + adapter->max_vlans = le16_to_cpu(desc->vlan_count); + adapter->max_mcast_mac = le16_to_cpu(desc->mcast_mac_count); + adapter->max_tx_queues = le16_to_cpu(desc->txq_count); + adapter->max_rss_queues = le16_to_cpu(desc->rssq_count); + adapter->max_rx_queues = le16_to_cpu(desc->rq_count); + + adapter->max_event_queues = le16_to_cpu(desc->eq_count); + adapter->if_cap_flags = le32_to_cpu(desc->cap_flags); + } +err: + mutex_unlock(&adapter->mbox_lock); + pci_free_consistent(adapter->pdev, cmd.size, + cmd.va, cmd.dma); + return status; +} + + /* Uses sync mcc */ +int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, + u8 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_get_profile_config *req; + int status; + struct be_dma_mem cmd; + + memset(&cmd, 0, sizeof(struct be_dma_mem)); + cmd.size = sizeof(struct be_cmd_resp_get_profile_config); + cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, + &cmd.dma); + if (!cmd.va) { + dev_err(&adapter->pdev->dev, "Memory alloc failure\n"); + return -ENOMEM; + } + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = cmd.va; + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_PROFILE_CONFIG, + cmd.size, wrb, &cmd); + + req->type = ACTIVE_PROFILE_TYPE; + req->hdr.domain = domain; + + status = be_mcc_notify_wait(adapter); + if (!status) { + struct be_cmd_resp_get_profile_config *resp = cmd.va; + u32 desc_count = le32_to_cpu(resp->desc_count); + struct be_nic_resource_desc *desc; + + desc = be_get_nic_desc(resp->func_param, desc_count, + sizeof(resp->func_param)); + + if (!desc) { + status = -EINVAL; + goto err; + } + *cap_flags = le32_to_cpu(desc->cap_flags); + } +err: + spin_unlock_bh(&adapter->mcc_lock); + pci_free_consistent(adapter->pdev, cmd.size, + cmd.va, cmd.dma); + return status; +} + +/* Uses sync mcc */ +int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, + u8 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_set_profile_config *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_PROFILE_CONFIG, sizeof(*req), + wrb, NULL); + + req->hdr.domain = domain; + req->desc_count = cpu_to_le32(1); + + req->nic_desc.desc_type = NIC_RESOURCE_DESC_TYPE_ID; + req->nic_desc.desc_len = RESOURCE_DESC_SIZE; + req->nic_desc.flags = (1 << QUN) | (1 << IMM) | (1 << NOSV); + req->nic_desc.pf_num = adapter->pf_number; + req->nic_desc.vf_num = domain; + + /* Mark fields invalid */ + req->nic_desc.unicast_mac_count = 0xFFFF; + req->nic_desc.mcc_count = 0xFFFF; + req->nic_desc.vlan_count = 0xFFFF; + req->nic_desc.mcast_mac_count = 0xFFFF; + req->nic_desc.txq_count = 0xFFFF; + req->nic_desc.rq_count = 0xFFFF; + req->nic_desc.rssq_count = 0xFFFF; + req->nic_desc.lro_count = 0xFFFF; + req->nic_desc.cq_count = 0xFFFF; + req->nic_desc.toe_conn_count = 0xFFFF; + req->nic_desc.eq_count = 0xFFFF; + req->nic_desc.link_param = 0xFF; + req->nic_desc.bw_min = 0xFFFFFFFF; + req->nic_desc.acpi_params = 0xFF; + req->nic_desc.wol_param = 0x0F; + + /* Change BW */ + req->nic_desc.bw_min = cpu_to_le32(bps); + req->nic_desc.bw_max = cpu_to_le32(bps); + status = be_mcc_notify_wait(adapter); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + +/* Uses sync mcc */ +int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_enable_disable_vf *req; + int status; + + if (!lancer_chip(adapter)) + return 0; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + + req = embedded_payload(wrb); + + be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_ENABLE_DISABLE_VF, sizeof(*req), + wrb, NULL); + + req->hdr.domain = domain; + req->enable = 1; + status = be_mcc_notify_wait(adapter); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload, int wrb_payload_size, u16 *cmd_status, u16 *ext_status) { diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h index 0936e21e3cff..d6552e19ffee 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.h +++ b/drivers/net/ethernet/emulex/benet/be_cmds.h @@ -196,9 +196,14 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_GET_MAC_LIST 147 #define OPCODE_COMMON_SET_MAC_LIST 148 #define OPCODE_COMMON_GET_HSW_CONFIG 152 +#define OPCODE_COMMON_GET_FUNC_CONFIG 160 +#define OPCODE_COMMON_GET_PROFILE_CONFIG 164 +#define OPCODE_COMMON_SET_PROFILE_CONFIG 165 #define OPCODE_COMMON_SET_HSW_CONFIG 153 +#define OPCODE_COMMON_GET_FN_PRIVILEGES 170 #define OPCODE_COMMON_READ_OBJECT 171 #define OPCODE_COMMON_WRITE_OBJECT 172 +#define OPCODE_COMMON_ENABLE_DISABLE_VF 196 #define OPCODE_ETH_RSS_CONFIG 1 #define OPCODE_ETH_ACPI_CONFIG 2 @@ -1151,14 +1156,22 @@ struct flashrom_params { u32 op_type; u32 data_buf_size; u32 offset; - u8 data_buf[4]; }; struct be_cmd_write_flashrom { struct be_cmd_req_hdr hdr; struct flashrom_params params; -}; + u8 data_buf[32768]; + u8 rsvd[4]; +} __packed; +/* cmd to read flash crc */ +struct be_cmd_read_flash_crc { + struct be_cmd_req_hdr hdr; + struct flashrom_params params; + u8 crc[4]; + u8 rsvd[4]; +}; /**************** Lancer Firmware Flash ************/ struct amap_lancer_write_obj_context { u8 write_length[24]; @@ -1429,6 +1442,41 @@ struct be_cmd_resp_set_func_cap { u8 rsvd[212]; }; +/*********************** Function Privileges ***********************/ +enum { + BE_PRIV_DEFAULT = 0x1, + BE_PRIV_LNKQUERY = 0x2, + BE_PRIV_LNKSTATS = 0x4, + BE_PRIV_LNKMGMT = 0x8, + BE_PRIV_LNKDIAG = 0x10, + BE_PRIV_UTILQUERY = 0x20, + BE_PRIV_FILTMGMT = 0x40, + BE_PRIV_IFACEMGMT = 0x80, + BE_PRIV_VHADM = 0x100, + BE_PRIV_DEVCFG = 0x200, + BE_PRIV_DEVSEC = 0x400 +}; +#define MAX_PRIVILEGES (BE_PRIV_VHADM | BE_PRIV_DEVCFG | \ + BE_PRIV_DEVSEC) +#define MIN_PRIVILEGES BE_PRIV_DEFAULT + +struct be_cmd_priv_map { + u8 opcode; + u8 subsystem; + u32 priv_mask; +}; + +struct be_cmd_req_get_fn_privileges { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_cmd_resp_get_fn_privileges { + struct be_cmd_resp_hdr hdr; + u32 privilege_mask; +}; + + /******************** GET/SET_MACLIST **************************/ #define BE_MAX_MAC 64 struct be_cmd_req_get_mac_list { @@ -1608,33 +1656,6 @@ struct be_cmd_resp_get_stats_v1 { struct be_hw_stats_v1 hw_stats; }; -static inline void *hw_stats_from_cmd(struct be_adapter *adapter) -{ - if (adapter->generation == BE_GEN3) { - struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va; - - return &cmd->hw_stats; - } else { - struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va; - - return &cmd->hw_stats; - } -} - -static inline void *be_erx_stats_from_cmd(struct be_adapter *adapter) -{ - if (adapter->generation == BE_GEN3) { - struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); - - return &hw_stats->erx; - } else { - struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); - - return &hw_stats->erx; - } -} - - /************** get fat capabilites *******************/ #define MAX_MODULES 27 #define MAX_MODES 4 @@ -1684,6 +1705,96 @@ struct be_cmd_req_set_ext_fat_caps { struct be_fat_conf_params set_params; }; +#define RESOURCE_DESC_SIZE 72 +#define NIC_RESOURCE_DESC_TYPE_ID 0x41 +#define MAX_RESOURCE_DESC 4 + +/* QOS unit number */ +#define QUN 4 +/* Immediate */ +#define IMM 6 +/* No save */ +#define NOSV 7 + +struct be_nic_resource_desc { + u8 desc_type; + u8 desc_len; + u8 rsvd1; + u8 flags; + u8 vf_num; + u8 rsvd2; + u8 pf_num; + u8 rsvd3; + u16 unicast_mac_count; + u8 rsvd4[6]; + u16 mcc_count; + u16 vlan_count; + u16 mcast_mac_count; + u16 txq_count; + u16 rq_count; + u16 rssq_count; + u16 lro_count; + u16 cq_count; + u16 toe_conn_count; + u16 eq_count; + u32 rsvd5; + u32 cap_flags; + u8 link_param; + u8 rsvd6[3]; + u32 bw_min; + u32 bw_max; + u8 acpi_params; + u8 wol_param; + u16 rsvd7; + u32 rsvd8[3]; +}; + +struct be_cmd_req_get_func_config { + struct be_cmd_req_hdr hdr; +}; + +struct be_cmd_resp_get_func_config { + struct be_cmd_req_hdr hdr; + u32 desc_count; + u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE]; +}; + +#define ACTIVE_PROFILE_TYPE 0x2 +struct be_cmd_req_get_profile_config { + struct be_cmd_req_hdr hdr; + u8 rsvd; + u8 type; + u16 rsvd1; +}; + +struct be_cmd_resp_get_profile_config { + struct be_cmd_req_hdr hdr; + u32 desc_count; + u8 func_param[MAX_RESOURCE_DESC * RESOURCE_DESC_SIZE]; +}; + +struct be_cmd_req_set_profile_config { + struct be_cmd_req_hdr hdr; + u32 rsvd; + u32 desc_count; + struct be_nic_resource_desc nic_desc; +}; + +struct be_cmd_resp_set_profile_config { + struct be_cmd_req_hdr hdr; +}; + +struct be_cmd_enable_disable_vf { + struct be_cmd_req_hdr hdr; + u8 enable; + u8 rsvd[3]; +}; + +static inline bool check_privilege(struct be_adapter *adapter, u32 flags) +{ + return flags & adapter->cmd_privileges ? true : false; +} + extern int be_pci_fnum_get(struct be_adapter *adapter); extern int be_fw_wait_ready(struct be_adapter *adapter); extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr, @@ -1780,6 +1891,8 @@ extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter); 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_fn_privileges(struct be_adapter *adapter, + u32 *privilege, u32 domain); extern int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac, bool *pmac_id_active, u32 *pmac_id, u8 domain); @@ -1798,4 +1911,10 @@ extern int be_cmd_set_ext_fat_capabilites(struct be_adapter *adapter, extern int lancer_wait_ready(struct be_adapter *adapter); extern int lancer_test_and_set_rdy_state(struct be_adapter *adapter); extern int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name); +extern int be_cmd_get_func_config(struct be_adapter *adapter); +extern int be_cmd_get_profile_config(struct be_adapter *adapter, u32 *cap_flags, + u8 domain); +extern int be_cmd_set_profile_config(struct be_adapter *adapter, u32 bps, + u8 domain); +extern int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain); diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 8e6fb0ba6aa9..00454a10f88d 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -261,6 +261,9 @@ be_get_reg_len(struct net_device *netdev) struct be_adapter *adapter = netdev_priv(netdev); u32 log_size = 0; + if (!check_privilege(adapter, MAX_PRIVILEGES)) + return 0; + if (be_physfn(adapter)) { if (lancer_chip(adapter)) log_size = lancer_cmd_get_file_len(adapter, @@ -525,6 +528,10 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) u8 link_status; u16 link_speed = 0; int status; + u32 auto_speeds; + u32 fixed_speeds; + u32 dac_cable_len; + u16 interface_type; if (adapter->phy.link_speed < 0) { status = be_cmd_link_status_query(adapter, &link_speed, @@ -534,39 +541,46 @@ static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) ethtool_cmd_speed_set(ecmd, link_speed); status = be_cmd_get_phy_info(adapter); - if (status) - return status; - - ecmd->supported = - convert_to_et_setting(adapter->phy.interface_type, - adapter->phy.auto_speeds_supported | - adapter->phy.fixed_speeds_supported); - ecmd->advertising = - convert_to_et_setting(adapter->phy.interface_type, - adapter->phy.auto_speeds_supported); - - ecmd->port = be_get_port_type(adapter->phy.interface_type, - adapter->phy.dac_cable_len); - - if (adapter->phy.auto_speeds_supported) { - ecmd->supported |= SUPPORTED_Autoneg; - ecmd->autoneg = AUTONEG_ENABLE; - ecmd->advertising |= ADVERTISED_Autoneg; - } + if (!status) { + interface_type = adapter->phy.interface_type; + auto_speeds = adapter->phy.auto_speeds_supported; + fixed_speeds = adapter->phy.fixed_speeds_supported; + dac_cable_len = adapter->phy.dac_cable_len; + + ecmd->supported = + convert_to_et_setting(interface_type, + auto_speeds | + fixed_speeds); + ecmd->advertising = + convert_to_et_setting(interface_type, + auto_speeds); + + ecmd->port = be_get_port_type(interface_type, + dac_cable_len); + + if (adapter->phy.auto_speeds_supported) { + ecmd->supported |= SUPPORTED_Autoneg; + ecmd->autoneg = AUTONEG_ENABLE; + ecmd->advertising |= ADVERTISED_Autoneg; + } - if (be_pause_supported(adapter)) { ecmd->supported |= SUPPORTED_Pause; - ecmd->advertising |= ADVERTISED_Pause; - } - - switch (adapter->phy.interface_type) { - case PHY_TYPE_KR_10GB: - case PHY_TYPE_KX4_10GB: - ecmd->transceiver = XCVR_INTERNAL; - break; - default: - ecmd->transceiver = XCVR_EXTERNAL; - break; + if (be_pause_supported(adapter)) + ecmd->advertising |= ADVERTISED_Pause; + + switch (adapter->phy.interface_type) { + case PHY_TYPE_KR_10GB: + case PHY_TYPE_KX4_10GB: + ecmd->transceiver = XCVR_INTERNAL; + break; + default: + ecmd->transceiver = XCVR_EXTERNAL; + break; + } + } else { + ecmd->port = PORT_OTHER; + ecmd->autoneg = AUTONEG_DISABLE; + ecmd->transceiver = XCVR_DUMMY1; } /* Save for future use */ @@ -787,6 +801,10 @@ static int be_get_eeprom_len(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); + + if (!check_privilege(adapter, MAX_PRIVILEGES)) + return 0; + if (lancer_chip(adapter)) { if (be_physfn(adapter)) return lancer_cmd_get_file_len(adapter, diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index b755f7061dce..541d4530d5bf 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h @@ -31,12 +31,12 @@ #define MPU_EP_CONTROL 0 -/********** MPU semphore ******************/ -#define MPU_EP_SEMAPHORE_OFFSET 0xac -#define MPU_EP_SEMAPHORE_IF_TYPE2_OFFSET 0x400 -#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF -#define EP_SEMAPHORE_POST_ERR_MASK 0x1 -#define EP_SEMAPHORE_POST_ERR_SHIFT 31 +/********** MPU semphore: used for SH & BE *************/ +#define SLIPORT_SEMAPHORE_OFFSET_BE 0x7c +#define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 +#define POST_STAGE_MASK 0x0000FFFF +#define POST_ERR_MASK 0x1 +#define POST_ERR_SHIFT 31 /* MPU semphore POST stage values */ #define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */ @@ -59,6 +59,9 @@ #define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002 #define PHYSDEV_CONTROL_INP_MASK 0x40000000 +#define SLIPORT_ERROR_NO_RESOURCE1 0x2 +#define SLIPORT_ERROR_NO_RESOURCE2 0x9 + /********* Memory BAR register ************/ #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt @@ -102,11 +105,6 @@ #define SLI_INTF_TYPE_2 2 #define SLI_INTF_TYPE_3 3 -/* SLI family */ -#define BE_SLI_FAMILY 0x0 -#define LANCER_A0_SLI_FAMILY 0xA -#define SKYHAWK_SLI_FAMILY 0x2 - /********* ISR0 Register offset **********/ #define CEV_ISR0_OFFSET 0xC18 #define CEV_ISR_SIZE 4 diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index d1b6cc587639..f95612b907ae 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -44,6 +44,7 @@ static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID3)}, { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID4)}, { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID5)}, + { PCI_DEVICE(EMULEX_VENDOR_ID, OC_DEVICE_ID6)}, { 0 } }; MODULE_DEVICE_TABLE(pci, be_dev_ids); @@ -237,23 +238,46 @@ static int be_mac_addr_set(struct net_device *netdev, void *p) int status = 0; u8 current_mac[ETH_ALEN]; u32 pmac_id = adapter->pmac_id[0]; + bool active_mac = true; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - status = be_cmd_mac_addr_query(adapter, current_mac, false, - adapter->if_handle, 0); + /* For BE VF, MAC address is already activated by PF. + * Hence only operation left is updating netdev->devaddr. + * Update it if user is passing the same MAC which was used + * during configuring VF MAC from PF(Hypervisor). + */ + if (!lancer_chip(adapter) && !be_physfn(adapter)) { + status = be_cmd_mac_addr_query(adapter, current_mac, + false, adapter->if_handle, 0); + if (!status && !memcmp(current_mac, addr->sa_data, ETH_ALEN)) + goto done; + else + goto err; + } + + if (!memcmp(addr->sa_data, netdev->dev_addr, ETH_ALEN)) + goto done; + + /* For Lancer check if any MAC is active. + * If active, get its mac id. + */ + if (lancer_chip(adapter) && !be_physfn(adapter)) + be_cmd_get_mac_from_list(adapter, current_mac, &active_mac, + &pmac_id, 0); + + status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, + adapter->if_handle, + &adapter->pmac_id[0], 0); + if (status) goto err; - if (memcmp(addr->sa_data, current_mac, ETH_ALEN)) { - status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data, - adapter->if_handle, &adapter->pmac_id[0], 0); - if (status) - goto err; - - be_cmd_pmac_del(adapter, adapter->if_handle, pmac_id, 0); - } + if (active_mac) + be_cmd_pmac_del(adapter, adapter->if_handle, + pmac_id, 0); +done: memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); return 0; err: @@ -261,7 +285,35 @@ err: return status; } -static void populate_be2_stats(struct be_adapter *adapter) +/* BE2 supports only v0 cmd */ +static void *hw_stats_from_cmd(struct be_adapter *adapter) +{ + if (BE2_chip(adapter)) { + struct be_cmd_resp_get_stats_v0 *cmd = adapter->stats_cmd.va; + + return &cmd->hw_stats; + } else { + struct be_cmd_resp_get_stats_v1 *cmd = adapter->stats_cmd.va; + + return &cmd->hw_stats; + } +} + +/* BE2 supports only v0 cmd */ +static void *be_erx_stats_from_cmd(struct be_adapter *adapter) +{ + if (BE2_chip(adapter)) { + struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->erx; + } else { + struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); + + return &hw_stats->erx; + } +} + +static void populate_be_v0_stats(struct be_adapter *adapter) { struct be_hw_stats_v0 *hw_stats = hw_stats_from_cmd(adapter); struct be_pmem_stats *pmem_sts = &hw_stats->pmem; @@ -310,7 +362,7 @@ static void populate_be2_stats(struct be_adapter *adapter) adapter->drv_stats.eth_red_drops = pmem_sts->eth_red_drops; } -static void populate_be3_stats(struct be_adapter *adapter) +static void populate_be_v1_stats(struct be_adapter *adapter) { struct be_hw_stats_v1 *hw_stats = hw_stats_from_cmd(adapter); struct be_pmem_stats *pmem_sts = &hw_stats->pmem; @@ -412,28 +464,25 @@ void be_parse_stats(struct be_adapter *adapter) struct be_rx_obj *rxo; int i; - if (adapter->generation == BE_GEN3) { - if (lancer_chip(adapter)) - populate_lancer_stats(adapter); - else - populate_be3_stats(adapter); + if (lancer_chip(adapter)) { + populate_lancer_stats(adapter); } else { - populate_be2_stats(adapter); - } - - if (lancer_chip(adapter)) - goto done; + if (BE2_chip(adapter)) + populate_be_v0_stats(adapter); + else + /* for BE3 and Skyhawk */ + populate_be_v1_stats(adapter); - /* as erx_v1 is longer than v0, ok to use v1 defn for v0 access */ - for_all_rx_queues(adapter, rxo, i) { - /* below erx HW counter can actually wrap around after - * 65535. Driver accumulates a 32-bit value - */ - accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags, - (u16)erx->rx_drops_no_fragments[rxo->q.id]); + /* as erx_v1 is longer than v0, ok to use v1 for v0 access */ + for_all_rx_queues(adapter, rxo, i) { + /* below erx HW counter can actually wrap around after + * 65535. Driver accumulates a 32-bit value + */ + accumulate_16bit_val(&rx_stats(rxo)->rx_drops_no_frags, + (u16)erx->rx_drops_no_fragments \ + [rxo->q.id]); + } } -done: - return; } static struct rtnl_link_stats64 *be_get_stats64(struct net_device *netdev, @@ -597,16 +646,6 @@ static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, hdr, skb_shinfo(skb)->gso_size); if (skb_is_gso_v6(skb) && !lancer_chip(adapter)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso6, hdr, 1); - if (lancer_chip(adapter) && adapter->sli_family == - LANCER_A0_SLI_FAMILY) { - AMAP_SET_BITS(struct amap_eth_hdr_wrb, ipcs, hdr, 1); - if (is_tcp_pkt(skb)) - AMAP_SET_BITS(struct amap_eth_hdr_wrb, - tcpcs, hdr, 1); - else if (is_udp_pkt(skb)) - AMAP_SET_BITS(struct amap_eth_hdr_wrb, - udpcs, hdr, 1); - } } else if (skb->ip_summed == CHECKSUM_PARTIAL) { if (is_tcp_pkt(skb)) AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); @@ -856,11 +895,15 @@ static int be_vlan_add_vid(struct net_device *netdev, u16 vid) struct be_adapter *adapter = netdev_priv(netdev); int status = 0; - if (!be_physfn(adapter)) { + if (!lancer_chip(adapter) && !be_physfn(adapter)) { status = -EINVAL; goto ret; } + /* Packets with VID 0 are always received by Lancer by default */ + if (lancer_chip(adapter) && vid == 0) + goto ret; + adapter->vlan_tag[vid] = 1; if (adapter->vlans_added <= (adapter->max_vlans + 1)) status = be_vid_config(adapter); @@ -878,11 +921,15 @@ static int be_vlan_rem_vid(struct net_device *netdev, u16 vid) struct be_adapter *adapter = netdev_priv(netdev); int status = 0; - if (!be_physfn(adapter)) { + if (!lancer_chip(adapter) && !be_physfn(adapter)) { status = -EINVAL; goto ret; } + /* Packets with VID 0 are always received by Lancer by default */ + if (lancer_chip(adapter) && vid == 0) + goto ret; + adapter->vlan_tag[vid] = 0; if (adapter->vlans_added <= adapter->max_vlans) status = be_vid_config(adapter); @@ -917,7 +964,7 @@ static void be_set_rx_mode(struct net_device *netdev) /* Enable multicast promisc if num configured exceeds what we support */ if (netdev->flags & IFF_ALLMULTI || - netdev_mc_count(netdev) > BE_MAX_MC) { + netdev_mc_count(netdev) > adapter->max_mcast_mac) { be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); goto done; } @@ -962,6 +1009,9 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) struct be_adapter *adapter = netdev_priv(netdev); struct be_vf_cfg *vf_cfg = &adapter->vf_cfg[vf]; int status; + bool active_mac = false; + u32 pmac_id; + u8 old_mac[ETH_ALEN]; if (!sriov_enabled(adapter)) return -EPERM; @@ -970,6 +1020,12 @@ static int be_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) return -EINVAL; if (lancer_chip(adapter)) { + status = be_cmd_get_mac_from_list(adapter, old_mac, &active_mac, + &pmac_id, vf + 1); + if (!status && active_mac) + be_cmd_pmac_del(adapter, vf_cfg->if_handle, + pmac_id, vf + 1); + status = be_cmd_set_mac_list(adapter, mac, 1, vf + 1); } else { status = be_cmd_pmac_del(adapter, vf_cfg->if_handle, @@ -1062,7 +1118,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev, return -EINVAL; } - status = be_cmd_set_qos(adapter, rate / 10, vf + 1); + if (lancer_chip(adapter)) + status = be_cmd_set_profile_config(adapter, rate / 10, vf + 1); + else + status = be_cmd_set_qos(adapter, rate / 10, vf + 1); if (status) dev_err(&adapter->pdev->dev, @@ -1616,24 +1675,6 @@ static inline int events_get(struct be_eq_obj *eqo) return num; } -static int event_handle(struct be_eq_obj *eqo) -{ - bool rearm = false; - int num = events_get(eqo); - - /* Deal with any spurious interrupts that come without events */ - if (!num) - rearm = true; - - if (num || msix_enabled(eqo->adapter)) - be_eq_notify(eqo->adapter, eqo->q.id, rearm, true, num); - - if (num) - napi_schedule(&eqo->napi); - - return num; -} - /* Leaves the EQ is disarmed state */ static void be_eq_clean(struct be_eq_obj *eqo) { @@ -1837,12 +1878,13 @@ static void be_tx_queues_destroy(struct be_adapter *adapter) static int be_num_txqs_want(struct be_adapter *adapter) { - if (sriov_want(adapter) || be_is_mc(adapter) || - lancer_chip(adapter) || !be_physfn(adapter) || - adapter->generation == BE_GEN2) + if ((!lancer_chip(adapter) && sriov_want(adapter)) || + be_is_mc(adapter) || + (!lancer_chip(adapter) && !be_physfn(adapter)) || + BE2_chip(adapter)) return 1; else - return MAX_TX_QS; + return adapter->max_tx_queues; } static int be_tx_cqs_create(struct be_adapter *adapter) @@ -1954,22 +1996,31 @@ static int be_rx_cqs_create(struct be_adapter *adapter) static irqreturn_t be_intx(int irq, void *dev) { - struct be_adapter *adapter = dev; - int num_evts; + struct be_eq_obj *eqo = dev; + struct be_adapter *adapter = eqo->adapter; + int num_evts = 0; - /* With INTx only one EQ is used */ - num_evts = event_handle(&adapter->eq_obj[0]); - if (num_evts) - return IRQ_HANDLED; - else - return IRQ_NONE; + /* On Lancer, clear-intr bit of the EQ DB does not work. + * INTx is de-asserted only on notifying num evts. + */ + if (lancer_chip(adapter)) + num_evts = events_get(eqo); + + /* The EQ-notify may not de-assert INTx rightaway, causing + * the ISR to be invoked again. So, return HANDLED even when + * num_evts is zero. + */ + be_eq_notify(adapter, eqo->q.id, false, true, num_evts); + napi_schedule(&eqo->napi); + return IRQ_HANDLED; } static irqreturn_t be_msix(int irq, void *dev) { struct be_eq_obj *eqo = dev; - event_handle(eqo); + be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); + napi_schedule(&eqo->napi); return IRQ_HANDLED; } @@ -2065,9 +2116,11 @@ int be_poll(struct napi_struct *napi, int budget) { struct be_eq_obj *eqo = container_of(napi, struct be_eq_obj, napi); struct be_adapter *adapter = eqo->adapter; - int max_work = 0, work, i; + int max_work = 0, work, i, num_evts; bool tx_done; + num_evts = events_get(eqo); + /* Process all TXQs serviced by this EQ */ for (i = eqo->idx; i < adapter->num_tx_qs; i += adapter->num_evt_qs) { tx_done = be_process_tx(adapter, &adapter->tx_obj[i], @@ -2090,10 +2143,10 @@ 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, 0); + be_eq_notify(adapter, eqo->q.id, true, false, num_evts); } else { /* As we'll continue in polling mode, count and clear events */ - be_eq_notify(adapter, eqo->q.id, false, false, events_get(eqo)); + be_eq_notify(adapter, eqo->q.id, false, false, num_evts); } return max_work; } @@ -2177,9 +2230,11 @@ static void be_msix_disable(struct be_adapter *adapter) static uint be_num_rss_want(struct be_adapter *adapter) { u32 num = 0; + if ((adapter->function_caps & BE_FUNCTION_CAPS_RSS) && - !sriov_want(adapter) && be_physfn(adapter)) { - num = (adapter->be3_native) ? BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; + (lancer_chip(adapter) || + (!sriov_want(adapter) && be_physfn(adapter)))) { + num = adapter->max_rss_queues; num = min_t(u32, num, (u32)netif_get_num_default_rss_queues()); } return num; @@ -2277,10 +2332,10 @@ static int be_irq_register(struct be_adapter *adapter) return status; } - /* INTx */ + /* INTx: only the first EQ is used */ netdev->irq = adapter->pdev->irq; status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name, - adapter); + &adapter->eq_obj[0]); if (status) { dev_err(&adapter->pdev->dev, "INTx request IRQ failed - err %d\n", status); @@ -2302,7 +2357,7 @@ static void be_irq_unregister(struct be_adapter *adapter) /* INTx */ if (!msix_enabled(adapter)) { - free_irq(netdev->irq, adapter); + free_irq(netdev->irq, &adapter->eq_obj[0]); goto done; } @@ -2579,10 +2634,30 @@ static int be_clear(struct be_adapter *adapter) be_tx_queues_destroy(adapter); be_evt_queues_destroy(adapter); + kfree(adapter->pmac_id); + adapter->pmac_id = NULL; + be_msix_disable(adapter); return 0; } +static void be_get_vf_if_cap_flags(struct be_adapter *adapter, + u32 *cap_flags, u8 domain) +{ + bool profile_present = false; + int status; + + if (lancer_chip(adapter)) { + status = be_cmd_get_profile_config(adapter, cap_flags, domain); + if (!status) + profile_present = true; + } + + if (!profile_present) + *cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST; +} + static int be_vf_setup_init(struct be_adapter *adapter) { struct be_vf_cfg *vf_cfg; @@ -2634,9 +2709,13 @@ static int be_vf_setup(struct be_adapter *adapter) if (status) goto err; - cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST; for_all_vfs(adapter, vf_cfg, vf) { + be_get_vf_if_cap_flags(adapter, &cap_flags, vf + 1); + + en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST); + status = be_cmd_if_create(adapter, cap_flags, en_flags, &vf_cfg->if_handle, vf + 1); if (status) @@ -2661,6 +2740,8 @@ static int be_vf_setup(struct be_adapter *adapter) if (status) goto err; vf_cfg->def_vid = def_vlan; + + be_cmd_enable_vf(adapter, vf + 1); } return 0; err: @@ -2674,7 +2755,10 @@ static void be_setup_init(struct be_adapter *adapter) adapter->if_handle = -1; adapter->be3_native = false; adapter->promiscuous = false; - adapter->eq_next_idx = 0; + if (be_physfn(adapter)) + adapter->cmd_privileges = MAX_PRIVILEGES; + else + adapter->cmd_privileges = MIN_PRIVILEGES; } static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle, @@ -2712,12 +2796,93 @@ static int be_get_mac_addr(struct be_adapter *adapter, u8 *mac, u32 if_handle, return status; } +static void be_get_resources(struct be_adapter *adapter) +{ + int status; + bool profile_present = false; + + if (lancer_chip(adapter)) { + status = be_cmd_get_func_config(adapter); + + if (!status) + profile_present = true; + } + + if (profile_present) { + /* Sanity fixes for Lancer */ + adapter->max_pmac_cnt = min_t(u16, adapter->max_pmac_cnt, + BE_UC_PMAC_COUNT); + adapter->max_vlans = min_t(u16, adapter->max_vlans, + BE_NUM_VLANS_SUPPORTED); + adapter->max_mcast_mac = min_t(u16, adapter->max_mcast_mac, + BE_MAX_MC); + adapter->max_tx_queues = min_t(u16, adapter->max_tx_queues, + MAX_TX_QS); + adapter->max_rss_queues = min_t(u16, adapter->max_rss_queues, + BE3_MAX_RSS_QS); + adapter->max_event_queues = min_t(u16, + adapter->max_event_queues, + BE3_MAX_RSS_QS); + + if (adapter->max_rss_queues && + adapter->max_rss_queues == adapter->max_rx_queues) + adapter->max_rss_queues -= 1; + + if (adapter->max_event_queues < adapter->max_rss_queues) + adapter->max_rss_queues = adapter->max_event_queues; + + } else { + if (be_physfn(adapter)) + adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; + else + adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; + + if (adapter->function_mode & FLEX10_MODE) + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; + else + adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; + + adapter->max_mcast_mac = BE_MAX_MC; + adapter->max_tx_queues = MAX_TX_QS; + adapter->max_rss_queues = (adapter->be3_native) ? + BE3_MAX_RSS_QS : BE2_MAX_RSS_QS; + adapter->max_event_queues = BE3_MAX_RSS_QS; + + adapter->if_cap_flags = BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_BROADCAST | + BE_IF_FLAGS_MULTICAST | + BE_IF_FLAGS_PASS_L3L4_ERRORS | + BE_IF_FLAGS_MCAST_PROMISCUOUS | + BE_IF_FLAGS_VLAN_PROMISCUOUS | + BE_IF_FLAGS_PROMISCUOUS; + + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) + adapter->if_cap_flags |= BE_IF_FLAGS_RSS; + } +} + /* Routine to query per function resource limits */ static int be_get_config(struct be_adapter *adapter) { - int pos; + int pos, status; u16 dev_num_vfs; + status = be_cmd_query_fw_cfg(adapter, &adapter->port_num, + &adapter->function_mode, + &adapter->function_caps); + if (status) + goto err; + + be_get_resources(adapter); + + /* primary mac needs 1 pmac entry */ + adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, + sizeof(u32), GFP_KERNEL); + if (!adapter->pmac_id) { + status = -ENOMEM; + goto err; + } + pos = pci_find_ext_capability(adapter->pdev, PCI_EXT_CAP_ID_SRIOV); if (pos) { pci_read_config_word(adapter->pdev, pos + PCI_SRIOV_TOTAL_VF, @@ -2726,13 +2891,14 @@ static int be_get_config(struct be_adapter *adapter) dev_num_vfs = min_t(u16, dev_num_vfs, MAX_VFS); adapter->dev_num_vfs = dev_num_vfs; } - return 0; +err: + return status; } static int be_setup(struct be_adapter *adapter) { struct device *dev = &adapter->pdev->dev; - u32 cap_flags, en_flags; + u32 en_flags; u32 tx_fc, rx_fc; int status; u8 mac[ETH_ALEN]; @@ -2740,9 +2906,12 @@ static int be_setup(struct be_adapter *adapter) be_setup_init(adapter); - be_get_config(adapter); + if (!lancer_chip(adapter)) + be_cmd_req_native_mode(adapter); - be_cmd_req_native_mode(adapter); + status = be_get_config(adapter); + if (status) + goto err; be_msix_enable(adapter); @@ -2762,24 +2931,22 @@ static int be_setup(struct be_adapter *adapter) if (status) goto err; + be_cmd_get_fn_privileges(adapter, &adapter->cmd_privileges, 0); + /* In UMC mode FW does not return right privileges. + * Override with correct privilege equivalent to PF. + */ + if (be_is_mc(adapter)) + adapter->cmd_privileges = MAX_PRIVILEGES; + en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS; - cap_flags = en_flags | BE_IF_FLAGS_MCAST_PROMISCUOUS | - BE_IF_FLAGS_VLAN_PROMISCUOUS | BE_IF_FLAGS_PROMISCUOUS; - if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) { - cap_flags |= BE_IF_FLAGS_RSS; + if (adapter->function_caps & BE_FUNCTION_CAPS_RSS) en_flags |= BE_IF_FLAGS_RSS; - } - if (lancer_chip(adapter) && !be_physfn(adapter)) { - en_flags = BE_IF_FLAGS_UNTAGGED | - BE_IF_FLAGS_BROADCAST | - BE_IF_FLAGS_MULTICAST; - cap_flags = en_flags; - } + en_flags = en_flags & adapter->if_cap_flags; - status = be_cmd_if_create(adapter, cap_flags, en_flags, + status = be_cmd_if_create(adapter, adapter->if_cap_flags, en_flags, &adapter->if_handle, 0); if (status != 0) goto err; @@ -2827,8 +2994,8 @@ static int be_setup(struct be_adapter *adapter) dev_warn(dev, "device doesn't support SRIOV\n"); } - be_cmd_get_phy_info(adapter); - if (be_pause_supported(adapter)) + status = be_cmd_get_phy_info(adapter); + if (!status && be_pause_supported(adapter)) adapter->phy.fc_autoneg = 1; schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); @@ -2846,8 +3013,10 @@ static void be_netpoll(struct net_device *netdev) struct be_eq_obj *eqo; int i; - for_all_evt_queues(adapter, eqo, i) - event_handle(eqo); + for_all_evt_queues(adapter, eqo, i) { + be_eq_notify(eqo->adapter, eqo->q.id, false, true, 0); + napi_schedule(&eqo->napi); + } return; } @@ -2895,7 +3064,7 @@ static bool is_comp_in_ufi(struct be_adapter *adapter, int i = 0, img_type = 0; struct flash_section_info_g2 *fsec_g2 = NULL; - if (adapter->generation != BE_GEN3) + if (BE2_chip(adapter)) fsec_g2 = (struct flash_section_info_g2 *)fsec; for (i = 0; i < MAX_FLASH_COMP; i++) { @@ -2928,7 +3097,49 @@ struct flash_section_info *get_fsec_info(struct be_adapter *adapter, return NULL; } -static int be_flash_data(struct be_adapter *adapter, +static int be_flash(struct be_adapter *adapter, const u8 *img, + struct be_dma_mem *flash_cmd, int optype, int img_size) +{ + u32 total_bytes = 0, flash_op, num_bytes = 0; + int status = 0; + struct be_cmd_write_flashrom *req = flash_cmd->va; + + total_bytes = img_size; + while (total_bytes) { + num_bytes = min_t(u32, 32*1024, total_bytes); + + total_bytes -= num_bytes; + + if (!total_bytes) { + if (optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_FLASH; + else + flash_op = FLASHROM_OPER_FLASH; + } else { + if (optype == OPTYPE_PHY_FW) + flash_op = FLASHROM_OPER_PHY_SAVE; + else + flash_op = FLASHROM_OPER_SAVE; + } + + memcpy(req->data_buf, img, num_bytes); + img += num_bytes; + status = be_cmd_write_flashrom(adapter, flash_cmd, optype, + flash_op, num_bytes); + if (status) { + if (status == ILLEGAL_IOCTL_REQ && + optype == OPTYPE_PHY_FW) + break; + dev_err(&adapter->pdev->dev, + "cmd to write to flash rom failed.\n"); + return status; + } + } + return 0; +} + +/* For BE2 and BE3 */ +static int be_flash_BEx(struct be_adapter *adapter, const struct firmware *fw, struct be_dma_mem *flash_cmd, int num_of_images) @@ -2936,12 +3147,9 @@ static int be_flash_data(struct be_adapter *adapter, { int status = 0, i, filehdr_size = 0; int img_hdrs_size = (num_of_images * sizeof(struct image_hdr)); - u32 total_bytes = 0, flash_op; - int num_bytes; const u8 *p = fw->data; - struct be_cmd_write_flashrom *req = flash_cmd->va; const struct flash_comp *pflashcomp; - int num_comp, hdr_size; + int num_comp, redboot; struct flash_section_info *fsec = NULL; struct flash_comp gen3_flash_types[] = { @@ -2986,7 +3194,7 @@ static int be_flash_data(struct be_adapter *adapter, FLASH_IMAGE_MAX_SIZE_g2, IMAGE_FIRMWARE_BACKUP_FCoE} }; - if (adapter->generation == BE_GEN3) { + if (BE3_chip(adapter)) { pflashcomp = gen3_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g3); num_comp = ARRAY_SIZE(gen3_flash_types); @@ -2995,6 +3203,7 @@ static int be_flash_data(struct be_adapter *adapter, filehdr_size = sizeof(struct flash_file_hdr_g2); num_comp = ARRAY_SIZE(gen2_flash_types); } + /* Get flash section info*/ fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); if (!fsec) { @@ -3010,70 +3219,105 @@ static int be_flash_data(struct be_adapter *adapter, memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) continue; - if (pflashcomp[i].optype == OPTYPE_PHY_FW) { - if (!phy_flashing_required(adapter)) + if (pflashcomp[i].optype == OPTYPE_PHY_FW && + !phy_flashing_required(adapter)) continue; - } - - hdr_size = filehdr_size + - (num_of_images * sizeof(struct image_hdr)); - if ((pflashcomp[i].optype == OPTYPE_REDBOOT) && - (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, - pflashcomp[i].size, hdr_size))) - continue; + if (pflashcomp[i].optype == OPTYPE_REDBOOT) { + redboot = be_flash_redboot(adapter, fw->data, + pflashcomp[i].offset, pflashcomp[i].size, + filehdr_size + img_hdrs_size); + if (!redboot) + continue; + } - /* Flash the component */ p = fw->data; p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; if (p + pflashcomp[i].size > fw->data + fw->size) return -1; - total_bytes = pflashcomp[i].size; - while (total_bytes) { - if (total_bytes > 32*1024) - num_bytes = 32*1024; - else - num_bytes = total_bytes; - total_bytes -= num_bytes; - if (!total_bytes) { - if (pflashcomp[i].optype == OPTYPE_PHY_FW) - flash_op = FLASHROM_OPER_PHY_FLASH; - else - flash_op = FLASHROM_OPER_FLASH; - } else { - if (pflashcomp[i].optype == OPTYPE_PHY_FW) - flash_op = FLASHROM_OPER_PHY_SAVE; - else - flash_op = FLASHROM_OPER_SAVE; - } - memcpy(req->params.data_buf, p, num_bytes); - p += num_bytes; - status = be_cmd_write_flashrom(adapter, flash_cmd, - pflashcomp[i].optype, flash_op, num_bytes); - if (status) { - if ((status == ILLEGAL_IOCTL_REQ) && - (pflashcomp[i].optype == - OPTYPE_PHY_FW)) - break; - dev_err(&adapter->pdev->dev, - "cmd to write to flash rom failed.\n"); - return -1; - } + + status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, + pflashcomp[i].size); + if (status) { + dev_err(&adapter->pdev->dev, + "Flashing section type %d failed.\n", + pflashcomp[i].img_type); + return status; } } return 0; } -static int get_ufigen_type(struct flash_file_hdr_g2 *fhdr) +static int be_flash_skyhawk(struct be_adapter *adapter, + const struct firmware *fw, + struct be_dma_mem *flash_cmd, int num_of_images) { - if (fhdr == NULL) - return 0; - if (fhdr->build[0] == '3') - return BE_GEN3; - else if (fhdr->build[0] == '2') - return BE_GEN2; - else - return 0; + int status = 0, i, filehdr_size = 0; + int img_offset, img_size, img_optype, redboot; + int img_hdrs_size = num_of_images * sizeof(struct image_hdr); + const u8 *p = fw->data; + struct flash_section_info *fsec = NULL; + + filehdr_size = sizeof(struct flash_file_hdr_g3); + fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); + if (!fsec) { + dev_err(&adapter->pdev->dev, + "Invalid Cookie. UFI corrupted ?\n"); + return -1; + } + + for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { + img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); + img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); + + switch (le32_to_cpu(fsec->fsec_entry[i].type)) { + case IMAGE_FIRMWARE_iSCSI: + img_optype = OPTYPE_ISCSI_ACTIVE; + break; + case IMAGE_BOOT_CODE: + img_optype = OPTYPE_REDBOOT; + break; + case IMAGE_OPTION_ROM_ISCSI: + img_optype = OPTYPE_BIOS; + break; + case IMAGE_OPTION_ROM_PXE: + img_optype = OPTYPE_PXE_BIOS; + break; + case IMAGE_OPTION_ROM_FCoE: + img_optype = OPTYPE_FCOE_BIOS; + break; + case IMAGE_FIRMWARE_BACKUP_iSCSI: + img_optype = OPTYPE_ISCSI_BACKUP; + break; + case IMAGE_NCSI: + img_optype = OPTYPE_NCSI_FW; + break; + default: + continue; + } + + if (img_optype == OPTYPE_REDBOOT) { + redboot = be_flash_redboot(adapter, fw->data, + img_offset, img_size, + filehdr_size + img_hdrs_size); + if (!redboot) + continue; + } + + p = fw->data; + p += filehdr_size + img_offset + img_hdrs_size; + if (p + img_size > fw->data + fw->size) + return -1; + + status = be_flash(adapter, p, flash_cmd, img_optype, img_size); + if (status) { + dev_err(&adapter->pdev->dev, + "Flashing section type %d failed.\n", + fsec->fsec_entry[i].type); + return status; + } + } + return 0; } static int lancer_wait_idle(struct be_adapter *adapter) @@ -3207,6 +3451,28 @@ lancer_fw_exit: return status; } +#define UFI_TYPE2 2 +#define UFI_TYPE3 3 +#define UFI_TYPE4 4 +static int be_get_ufi_type(struct be_adapter *adapter, + struct flash_file_hdr_g2 *fhdr) +{ + if (fhdr == NULL) + goto be_get_ufi_exit; + + if (skyhawk_chip(adapter) && fhdr->build[0] == '4') + return UFI_TYPE4; + else if (BE3_chip(adapter) && fhdr->build[0] == '3') + return UFI_TYPE3; + else if (BE2_chip(adapter) && fhdr->build[0] == '2') + return UFI_TYPE2; + +be_get_ufi_exit: + dev_err(&adapter->pdev->dev, + "UFI and Interface are not compatible for flashing\n"); + return -1; +} + static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) { struct flash_file_hdr_g2 *fhdr; @@ -3214,12 +3480,9 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) struct image_hdr *img_hdr_ptr = NULL; struct be_dma_mem flash_cmd; const u8 *p; - int status = 0, i = 0, num_imgs = 0; - - p = fw->data; - fhdr = (struct flash_file_hdr_g2 *) p; + int status = 0, i = 0, num_imgs = 0, ufi_type = 0; - flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024; + flash_cmd.size = sizeof(struct be_cmd_write_flashrom); flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size, &flash_cmd.dma, GFP_KERNEL); if (!flash_cmd.va) { @@ -3229,27 +3492,32 @@ static int be_fw_download(struct be_adapter *adapter, const struct firmware* fw) goto be_fw_exit; } - if ((adapter->generation == BE_GEN3) && - (get_ufigen_type(fhdr) == BE_GEN3)) { - fhdr3 = (struct flash_file_hdr_g3 *) fw->data; - num_imgs = le32_to_cpu(fhdr3->num_imgs); - for (i = 0; i < num_imgs; i++) { - img_hdr_ptr = (struct image_hdr *) (fw->data + - (sizeof(struct flash_file_hdr_g3) + - i * sizeof(struct image_hdr))); - if (le32_to_cpu(img_hdr_ptr->imageid) == 1) - status = be_flash_data(adapter, fw, &flash_cmd, - num_imgs); + p = fw->data; + fhdr = (struct flash_file_hdr_g2 *)p; + + ufi_type = be_get_ufi_type(adapter, fhdr); + + fhdr3 = (struct flash_file_hdr_g3 *)fw->data; + num_imgs = le32_to_cpu(fhdr3->num_imgs); + for (i = 0; i < num_imgs; i++) { + img_hdr_ptr = (struct image_hdr *)(fw->data + + (sizeof(struct flash_file_hdr_g3) + + i * sizeof(struct image_hdr))); + if (le32_to_cpu(img_hdr_ptr->imageid) == 1) { + if (ufi_type == UFI_TYPE4) + status = be_flash_skyhawk(adapter, fw, + &flash_cmd, num_imgs); + else if (ufi_type == UFI_TYPE3) + status = be_flash_BEx(adapter, fw, &flash_cmd, + num_imgs); } - } else if ((adapter->generation == BE_GEN2) && - (get_ufigen_type(fhdr) == BE_GEN2)) { - status = be_flash_data(adapter, fw, &flash_cmd, 0); - } else { - dev_err(&adapter->pdev->dev, - "UFI and Interface are not compatible for flashing\n"); - status = -1; } + if (ufi_type == UFI_TYPE2) + status = be_flash_BEx(adapter, fw, &flash_cmd, 0); + else if (ufi_type == -1) + status = -1; + dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va, flash_cmd.dma); if (status) { @@ -3344,80 +3612,47 @@ static void be_netdev_init(struct net_device *netdev) static void be_unmap_pci_bars(struct be_adapter *adapter) { - if (adapter->csr) - iounmap(adapter->csr); if (adapter->db) - iounmap(adapter->db); - if (adapter->roce_db.base) - pci_iounmap(adapter->pdev, adapter->roce_db.base); + pci_iounmap(adapter->pdev, adapter->db); } -static int lancer_roce_map_pci_bars(struct be_adapter *adapter) +static int db_bar(struct be_adapter *adapter) { - struct pci_dev *pdev = adapter->pdev; - u8 __iomem *addr; - - addr = pci_iomap(pdev, 2, 0); - if (addr == NULL) - return -ENOMEM; + if (lancer_chip(adapter) || !be_physfn(adapter)) + return 0; + else + return 4; +} - adapter->roce_db.base = addr; - adapter->roce_db.io_addr = pci_resource_start(pdev, 2); - adapter->roce_db.size = 8192; - adapter->roce_db.total_size = pci_resource_len(pdev, 2); +static int be_roce_map_pci_bars(struct be_adapter *adapter) +{ + if (skyhawk_chip(adapter)) { + adapter->roce_db.size = 4096; + adapter->roce_db.io_addr = pci_resource_start(adapter->pdev, + db_bar(adapter)); + adapter->roce_db.total_size = pci_resource_len(adapter->pdev, + db_bar(adapter)); + } return 0; } static int be_map_pci_bars(struct be_adapter *adapter) { u8 __iomem *addr; - int db_reg; + u32 sli_intf; - if (lancer_chip(adapter)) { - if (be_type_2_3(adapter)) { - addr = ioremap_nocache( - pci_resource_start(adapter->pdev, 0), - pci_resource_len(adapter->pdev, 0)); - if (addr == NULL) - return -ENOMEM; - adapter->db = addr; - } - if (adapter->if_type == SLI_INTF_TYPE_3) { - if (lancer_roce_map_pci_bars(adapter)) - goto pci_map_err; - } - return 0; - } - - if (be_physfn(adapter)) { - addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), - pci_resource_len(adapter->pdev, 2)); - if (addr == NULL) - return -ENOMEM; - adapter->csr = addr; - } + pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); + adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> + SLI_INTF_IF_TYPE_SHIFT; - if (adapter->generation == BE_GEN2) { - db_reg = 4; - } else { - if (be_physfn(adapter)) - db_reg = 4; - else - db_reg = 0; - } - addr = ioremap_nocache(pci_resource_start(adapter->pdev, db_reg), - pci_resource_len(adapter->pdev, db_reg)); + addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); if (addr == NULL) goto pci_map_err; adapter->db = addr; - if (adapter->sli_family == SKYHAWK_SLI_FAMILY) { - adapter->roce_db.size = 4096; - adapter->roce_db.io_addr = - pci_resource_start(adapter->pdev, db_reg); - adapter->roce_db.total_size = - pci_resource_len(adapter->pdev, db_reg); - } + + be_roce_map_pci_bars(adapter); return 0; + pci_map_err: be_unmap_pci_bars(adapter); return -ENOMEM; @@ -3437,7 +3672,6 @@ static void be_ctrl_cleanup(struct be_adapter *adapter) if (mem->va) dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va, mem->dma); - kfree(adapter->pmac_id); } static int be_ctrl_init(struct be_adapter *adapter) @@ -3445,8 +3679,14 @@ static int be_ctrl_init(struct be_adapter *adapter) struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced; struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem; struct be_dma_mem *rx_filter = &adapter->rx_filter; + u32 sli_intf; int status; + pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); + adapter->sli_family = (sli_intf & SLI_INTF_FAMILY_MASK) >> + SLI_INTF_FAMILY_SHIFT; + adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; + status = be_map_pci_bars(adapter); if (status) goto done; @@ -3473,13 +3713,6 @@ static int be_ctrl_init(struct be_adapter *adapter) goto free_mbox; } memset(rx_filter->va, 0, rx_filter->size); - - /* primary mac needs 1 pmac entry */ - adapter->pmac_id = kcalloc(adapter->max_pmac_cnt + 1, - sizeof(*adapter->pmac_id), GFP_KERNEL); - if (!adapter->pmac_id) - return -ENOMEM; - mutex_init(&adapter->mbox_lock); spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_cq_lock); @@ -3512,14 +3745,14 @@ static int be_stats_init(struct be_adapter *adapter) { struct be_dma_mem *cmd = &adapter->stats_cmd; - if (adapter->generation == BE_GEN2) { + if (lancer_chip(adapter)) + cmd->size = sizeof(struct lancer_cmd_req_pport_stats); + else if (BE2_chip(adapter)) cmd->size = sizeof(struct be_cmd_req_get_stats_v0); - } else { - if (lancer_chip(adapter)) - cmd->size = sizeof(struct lancer_cmd_req_pport_stats); - else - cmd->size = sizeof(struct be_cmd_req_get_stats_v1); - } + else + /* BE3 and Skyhawk */ + cmd->size = sizeof(struct be_cmd_req_get_stats_v1); + cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma, GFP_KERNEL); if (cmd->va == NULL) @@ -3528,7 +3761,7 @@ static int be_stats_init(struct be_adapter *adapter) return 0; } -static void __devexit be_remove(struct pci_dev *pdev) +static void be_remove(struct pci_dev *pdev) { struct be_adapter *adapter = pci_get_drvdata(pdev); @@ -3573,6 +3806,9 @@ u32 be_get_fw_log_level(struct be_adapter *adapter) u32 level = 0; int j; + if (lancer_chip(adapter)) + return 0; + memset(&extfat_cmd, 0, sizeof(struct be_dma_mem)); extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps); extfat_cmd.va = pci_alloc_consistent(adapter->pdev, extfat_cmd.size, @@ -3598,26 +3834,12 @@ u32 be_get_fw_log_level(struct be_adapter *adapter) err: return level; } + static int be_get_initial_config(struct be_adapter *adapter) { int status; u32 level; - status = be_cmd_query_fw_cfg(adapter, &adapter->port_num, - &adapter->function_mode, &adapter->function_caps); - if (status) - return status; - - if (adapter->function_mode & FLEX10_MODE) - adapter->max_vlans = BE_NUM_VLANS_SUPPORTED/8; - else - adapter->max_vlans = BE_NUM_VLANS_SUPPORTED; - - if (be_physfn(adapter)) - adapter->max_pmac_cnt = BE_UC_PMAC_COUNT; - else - adapter->max_pmac_cnt = BE_VF_UC_PMAC_COUNT; - status = be_cmd_get_cntl_attributes(adapter); if (status) return status; @@ -3642,55 +3864,6 @@ static int be_get_initial_config(struct be_adapter *adapter) return 0; } -static int be_dev_type_check(struct be_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - u32 sli_intf = 0, if_type; - - switch (pdev->device) { - case BE_DEVICE_ID1: - case OC_DEVICE_ID1: - adapter->generation = BE_GEN2; - break; - case BE_DEVICE_ID2: - case OC_DEVICE_ID2: - adapter->generation = BE_GEN3; - break; - case OC_DEVICE_ID3: - case OC_DEVICE_ID4: - pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); - adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> - SLI_INTF_IF_TYPE_SHIFT; - if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> - SLI_INTF_IF_TYPE_SHIFT; - if (((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) || - !be_type_2_3(adapter)) { - dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); - return -EINVAL; - } - adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >> - SLI_INTF_FAMILY_SHIFT); - adapter->generation = BE_GEN3; - break; - case OC_DEVICE_ID5: - pci_read_config_dword(pdev, SLI_INTF_REG_OFFSET, &sli_intf); - if ((sli_intf & SLI_INTF_VALID_MASK) != SLI_INTF_VALID) { - dev_err(&pdev->dev, "SLI_INTF reg val is not valid\n"); - return -EINVAL; - } - adapter->sli_family = ((sli_intf & SLI_INTF_FAMILY_MASK) >> - SLI_INTF_FAMILY_SHIFT); - adapter->generation = BE_GEN3; - break; - default: - adapter->generation = 0; - } - - pci_read_config_dword(adapter->pdev, SLI_INTF_REG_OFFSET, &sli_intf); - adapter->virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; - return 0; -} - static int lancer_recover_func(struct be_adapter *adapter) { int status; @@ -3721,8 +3894,9 @@ static int lancer_recover_func(struct be_adapter *adapter) "Adapter SLIPORT recovery succeeded\n"); return 0; err: - dev_err(&adapter->pdev->dev, - "Adapter SLIPORT recovery failed\n"); + if (adapter->eeh_error) + dev_err(&adapter->pdev->dev, + "Adapter SLIPORT recovery failed\n"); return status; } @@ -3820,8 +3994,7 @@ static inline char *func_name(struct be_adapter *adapter) return be_physfn(adapter) ? "PF" : "VF"; } -static int __devinit be_probe(struct pci_dev *pdev, - const struct pci_device_id *pdev_id) +static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) { int status = 0; struct be_adapter *adapter; @@ -3845,11 +4018,6 @@ static int __devinit be_probe(struct pci_dev *pdev, adapter = netdev_priv(netdev); adapter->pdev = pdev; pci_set_drvdata(pdev, adapter); - - status = be_dev_type_check(adapter); - if (status) - goto free_netdev; - adapter->netdev = netdev; SET_NETDEV_DEV(netdev, &pdev->dev); @@ -4023,9 +4191,6 @@ static void be_shutdown(struct pci_dev *pdev) netif_device_detach(adapter->netdev); - if (adapter->wol) - be_setup_wol(adapter, true); - be_cmd_reset_function(adapter); pci_disable_device(pdev); @@ -4061,9 +4226,13 @@ static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, /* The error could cause the FW to trigger a flash debug dump. * Resetting the card while flash dump is in progress - * can cause it not to recover; wait for it to finish + * can cause it not to recover; wait for it to finish. + * Wait only for first function as it is needed only once per + * adapter. */ - ssleep(30); + if (pdev->devfn == 0) + ssleep(30); + return PCI_ERS_RESULT_NEED_RESET; } diff --git a/drivers/net/ethernet/emulex/benet/be_roce.c b/drivers/net/ethernet/emulex/benet/be_roce.c index deecc44b3617..55d32aa0a093 100644 --- a/drivers/net/ethernet/emulex/benet/be_roce.c +++ b/drivers/net/ethernet/emulex/benet/be_roce.c @@ -47,10 +47,7 @@ static void _be_roce_dev_add(struct be_adapter *adapter) dev_info.dpp_unmapped_len = 0; } dev_info.pdev = adapter->pdev; - if (adapter->sli_family == SKYHAWK_SLI_FAMILY) - dev_info.db = adapter->db; - else - dev_info.db = adapter->roce_db.base; + dev_info.db = adapter->db; dev_info.unmapped_db = adapter->roce_db.io_addr; dev_info.db_page_size = adapter->roce_db.size; dev_info.db_total_size = adapter->roce_db.total_size; |