struct vlan_group *vlan_grp;
u16 num_vlans;
u8 vlan_tag[VLAN_GROUP_ARRAY_LEN];
+ struct be_dma_mem mc_cmd_mem;
struct be_stats_obj stats;
/* Work queue used to perform periodic tasks like getting statistics */
* (mc == NULL) => multicast promiscous
*/
int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
- struct dev_mc_list *mc_list, u32 mc_count)
+ struct dev_mc_list *mc_list, u32 mc_count,
+ struct be_dma_mem *mem)
{
-#define BE_MAX_MC 32 /* set mcast promisc if > 32 */
struct be_mcc_wrb *wrb;
- struct be_cmd_req_mcast_mac_config *req;
+ struct be_cmd_req_mcast_mac_config *req = mem->va;
+ struct be_sge *sge;
+ int status;
spin_lock_bh(&adapter->mcc_lock);
wrb = wrb_from_mccq(adapter);
- req = embedded_payload(wrb);
+ sge = nonembedded_sgl(wrb);
+ memset(req, 0, sizeof(*req));
- be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
+ be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1);
+ sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma));
+ sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF);
+ sge->len = cpu_to_le32(mem->size);
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req));
req->interface_id = if_id;
- if (mc_list && mc_count <= BE_MAX_MC) {
+ if (mc_list) {
int i;
struct dev_mc_list *mc;
req->promiscuous = 1;
}
- be_mcc_notify_wait(adapter);
+ status = be_mcc_notify_wait(adapter);
spin_unlock_bh(&adapter->mcc_lock);
-
- return 0;
+ return status;
}
/* Uses synchrounous mcc */
u16 rsvd0;
} __packed;
+/******************** Multicast MAC Config *******************/
+#define BE_MAX_MC 64 /* set mcast promisc if > 64 */
struct macaddr {
u8 byte[ETH_ALEN];
};
u16 num_mac;
u8 promiscuous;
u8 interface_id;
- struct macaddr mac[32];
+ struct macaddr mac[BE_MAX_MC];
} __packed;
static inline struct be_hw_stats *
extern int be_cmd_promiscuous_config(struct be_adapter *adapter,
u8 port_num, bool en);
extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
- struct dev_mc_list *mc_list, u32 mc_count);
+ struct dev_mc_list *mc_list, u32 mc_count,
+ struct be_dma_mem *mem);
extern int be_cmd_set_flow_control(struct be_adapter *adapter,
u32 tx_fc, u32 rx_fc);
extern int be_cmd_get_flow_control(struct be_adapter *adapter,
be_cmd_promiscuous_config(adapter, adapter->port_num, 0);
}
- if (netdev->flags & IFF_ALLMULTI) {
- be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0);
+ /* Enable multicast promisc if num configured exceeds what we support */
+ if (netdev->flags & IFF_ALLMULTI || netdev->mc_count > BE_MAX_MC) {
+ be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0,
+ &adapter->mc_cmd_mem);
goto done;
}
be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list,
- netdev->mc_count);
+ netdev->mc_count, &adapter->mc_cmd_mem);
done:
return;
}
if (mem->va)
pci_free_consistent(adapter->pdev, mem->size,
mem->va, mem->dma);
+
+ mem = &adapter->mc_cmd_mem;
+ if (mem->va)
+ pci_free_consistent(adapter->pdev, mem->size,
+ mem->va, mem->dma);
}
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 *mc_cmd_mem = &adapter->mc_cmd_mem;
int status;
status = be_map_pci_bars(adapter);
if (status)
- return status;
+ goto done;
mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev,
mbox_mem_alloc->size, &mbox_mem_alloc->dma);
if (!mbox_mem_alloc->va) {
- be_unmap_pci_bars(adapter);
- return -1;
+ status = -ENOMEM;
+ goto unmap_pci_bars;
}
+
mbox_mem_align->size = sizeof(struct be_mcc_mailbox);
mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16);
mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
+
+ mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config);
+ mc_cmd_mem->va = pci_alloc_consistent(adapter->pdev, mc_cmd_mem->size,
+ &mc_cmd_mem->dma);
+ if (mc_cmd_mem->va == NULL) {
+ status = -ENOMEM;
+ goto free_mbox;
+ }
+ memset(mc_cmd_mem->va, 0, mc_cmd_mem->size);
+
spin_lock_init(&adapter->mbox_lock);
spin_lock_init(&adapter->mcc_lock);
spin_lock_init(&adapter->mcc_cq_lock);
return 0;
+
+free_mbox:
+ pci_free_consistent(adapter->pdev, mbox_mem_alloc->size,
+ mbox_mem_alloc->va, mbox_mem_alloc->dma);
+
+unmap_pci_bars:
+ be_unmap_pci_bars(adapter);
+
+done:
+ return status;
}
static void be_stats_cleanup(struct be_adapter *adapter)