Skip to content

Commit

Permalink
be2net: Fix driver load failure for different FW configs in Lancer
Browse files Browse the repository at this point in the history
Driver assumes FW resource counts and capabilities while creating queues and
using functionality like RSS. This causes driver load to fail in FW configs
where resources and capabilities are reduced. Fix this by querying FW
configuration during probe and using resources and capabilities accordingly.

Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Padmanabh Ratnakar authored and David S. Miller committed Oct 22, 2012
1 parent 47b70db commit abb9395
Show file tree
Hide file tree
Showing 4 changed files with 349 additions and 54 deletions.
10 changes: 8 additions & 2 deletions drivers/net/ethernet/emulex/benet/be.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,6 @@ struct be_adapter {
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 */
Expand Down Expand Up @@ -434,10 +433,17 @@ 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;
};

#define be_physfn(adapter) (!adapter->virtfn)
Expand Down
150 changes: 147 additions & 3 deletions drivers/net/ethernet/emulex/benet/be_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -1658,9 +1658,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)
Expand Down Expand Up @@ -2792,6 +2792,150 @@ int be_cmd_query_port_name(struct be_adapter *adapter, u8 *port_name)
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->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;
}

int be_roce_mcc_cmd(void *netdev_handle, void *wrb_payload,
int wrb_payload_size, u16 *cmd_status, u16 *ext_status)
{
Expand Down
66 changes: 65 additions & 1 deletion drivers/net/ethernet/emulex/benet/be_cmds.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ 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_HSW_CONFIG 153
#define OPCODE_COMMON_READ_OBJECT 171
#define OPCODE_COMMON_WRITE_OBJECT 172
Expand Down Expand Up @@ -1684,6 +1686,66 @@ 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
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];
};

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,
Expand Down Expand Up @@ -1798,4 +1860,6 @@ 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);
Loading

0 comments on commit abb9395

Please sign in to comment.