Merge branch 'be2net-next'

Sathya Perla says:

====================
be2net: patch set

Patch 1 is a minor optimization for issuing multicast promisc FW cmd
only when the interface is not already in that mode.

Patch 2 provides support for VF TX-rate setting on Skyhawk-R.

Patch 3 provides support for flashing new FW flash regions.

Patches 4, 5, 6 cleanup the MCC processing (for FW cmds) code in be_cmds.c.
The MCC error reporting and event handling code are areas that needed
cleanup.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-05-30 17:27:39 -07:00
commit 078252e0e8
5 changed files with 438 additions and 277 deletions

View File

@ -374,6 +374,7 @@ enum vf_state {
#define BE_FLAGS_LINK_STATUS_INIT 1
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
#define BE_FLAGS_VLAN_PROMISC (1 << 4)
#define BE_FLAGS_MCAST_PROMISC (1 << 5)
#define BE_FLAGS_NAPI_ENABLED (1 << 9)
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11)
#define BE_FLAGS_VXLAN_OFFLOADS (1 << 12)

View File

@ -119,22 +119,29 @@ static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
return (void *)addr;
}
static int be_mcc_compl_process(struct be_adapter *adapter,
struct be_mcc_compl *compl)
static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
{
u16 compl_status, extd_status;
struct be_cmd_resp_hdr *resp_hdr;
if (base_status == MCC_STATUS_NOT_SUPPORTED ||
base_status == MCC_STATUS_ILLEGAL_REQUEST ||
addl_status == MCC_ADDL_STATUS_TOO_MANY_INTERFACES ||
(opcode == OPCODE_COMMON_WRITE_FLASHROM &&
(base_status == MCC_STATUS_ILLEGAL_FIELD ||
addl_status == MCC_ADDL_STATUS_FLASH_IMAGE_CRC_MISMATCH)))
return true;
else
return false;
}
/* Place holder for all the async MCC cmds wherein the caller is not in a busy
* loop (has not issued be_mcc_notify_wait())
*/
static void be_async_cmd_process(struct be_adapter *adapter,
struct be_mcc_compl *compl,
struct be_cmd_resp_hdr *resp_hdr)
{
enum mcc_base_status base_status = base_status(compl->status);
u8 opcode = 0, subsystem = 0;
/* Just swap the status to host endian; mcc tag is opaquely copied
* from mcc_wrb */
be_dws_le_to_cpu(compl, 4);
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
CQE_STATUS_COMPL_MASK;
resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
if (resp_hdr) {
opcode = resp_hdr->opcode;
subsystem = resp_hdr->subsystem;
@ -143,61 +150,86 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
complete(&adapter->et_cmd_compl);
return 0;
return;
}
if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
(opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
(subsystem == CMD_SUBSYSTEM_COMMON)) {
adapter->flash_status = compl_status;
if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
opcode == OPCODE_COMMON_WRITE_OBJECT) &&
subsystem == CMD_SUBSYSTEM_COMMON) {
adapter->flash_status = compl->status;
complete(&adapter->et_cmd_compl);
return;
}
if (compl_status == MCC_STATUS_SUCCESS) {
if (((opcode == OPCODE_ETH_GET_STATISTICS) ||
(opcode == OPCODE_ETH_GET_PPORT_STATS)) &&
(subsystem == CMD_SUBSYSTEM_ETH)) {
be_parse_stats(adapter);
adapter->stats_cmd_sent = false;
}
if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
subsystem == CMD_SUBSYSTEM_COMMON) {
if ((opcode == OPCODE_ETH_GET_STATISTICS ||
opcode == OPCODE_ETH_GET_PPORT_STATS) &&
subsystem == CMD_SUBSYSTEM_ETH &&
base_status == MCC_STATUS_SUCCESS) {
be_parse_stats(adapter);
adapter->stats_cmd_sent = false;
return;
}
if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
subsystem == CMD_SUBSYSTEM_COMMON) {
if (base_status == MCC_STATUS_SUCCESS) {
struct be_cmd_resp_get_cntl_addnl_attribs *resp =
(void *)resp_hdr;
(void *)resp_hdr;
adapter->drv_stats.be_on_die_temperature =
resp->on_die_temperature;
}
} else {
if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
resp->on_die_temperature;
} else {
adapter->be_get_temp_freq = 0;
}
return;
}
}
if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
compl_status == MCC_STATUS_ILLEGAL_REQUEST)
goto done;
static int be_mcc_compl_process(struct be_adapter *adapter,
struct be_mcc_compl *compl)
{
enum mcc_base_status base_status;
enum mcc_addl_status addl_status;
struct be_cmd_resp_hdr *resp_hdr;
u8 opcode = 0, subsystem = 0;
if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
/* Just swap the status to host endian; mcc tag is opaquely copied
* from mcc_wrb */
be_dws_le_to_cpu(compl, 4);
base_status = base_status(compl->status);
addl_status = addl_status(compl->status);
resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
if (resp_hdr) {
opcode = resp_hdr->opcode;
subsystem = resp_hdr->subsystem;
}
be_async_cmd_process(adapter, compl, resp_hdr);
if (base_status != MCC_STATUS_SUCCESS &&
!be_skip_err_log(opcode, base_status, addl_status)) {
if (base_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
dev_warn(&adapter->pdev->dev,
"VF is not privileged to issue opcode %d-%d\n",
opcode, subsystem);
} else {
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
CQE_STATUS_EXTD_MASK;
dev_err(&adapter->pdev->dev,
"opcode %d-%d failed:status %d-%d\n",
opcode, subsystem, compl_status, extd_status);
if (extd_status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES)
return extd_status;
opcode, subsystem, base_status, addl_status);
}
}
done:
return compl_status;
return compl->status;
}
/* Link state evt is a string of bytes; no need for endian swapping */
static void be_async_link_state_process(struct be_adapter *adapter,
struct be_async_event_link_state *evt)
struct be_mcc_compl *compl)
{
struct be_async_event_link_state *evt =
(struct be_async_event_link_state *)compl;
/* When link status changes, link speed must be re-queried from FW */
adapter->phy.link_speed = -1;
@ -220,10 +252,11 @@ static void be_async_link_state_process(struct be_adapter *adapter,
/* Grp5 CoS Priority evt */
static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
struct
be_async_event_grp5_cos_priority
*evt)
struct be_mcc_compl *compl)
{
struct be_async_event_grp5_cos_priority *evt =
(struct be_async_event_grp5_cos_priority *)compl;
if (evt->valid) {
adapter->vlan_prio_bmap = evt->available_priority_bmap;
adapter->recommended_prio &= ~VLAN_PRIO_MASK;
@ -234,10 +267,11 @@ static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
/* Grp5 QOS Speed evt: qos_link_speed is in units of 10 Mbps */
static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
struct
be_async_event_grp5_qos_link_speed
*evt)
struct be_mcc_compl *compl)
{
struct be_async_event_grp5_qos_link_speed *evt =
(struct be_async_event_grp5_qos_link_speed *)compl;
if (adapter->phy.link_speed >= 0 &&
evt->physical_port == adapter->port_num)
adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10;
@ -245,10 +279,11 @@ static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
/*Grp5 PVID evt*/
static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
struct
be_async_event_grp5_pvid_state
*evt)
struct be_mcc_compl *compl)
{
struct be_async_event_grp5_pvid_state *evt =
(struct be_async_event_grp5_pvid_state *)compl;
if (evt->enabled) {
adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid);
@ -258,26 +293,21 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
}
static void be_async_grp5_evt_process(struct be_adapter *adapter,
u32 trailer, struct be_mcc_compl *evt)
struct be_mcc_compl *compl)
{
u8 event_type = 0;
event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
ASYNC_TRAILER_EVENT_TYPE_MASK;
u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
ASYNC_EVENT_TYPE_MASK;
switch (event_type) {
case ASYNC_EVENT_COS_PRIORITY:
be_async_grp5_cos_priority_process(adapter,
(struct be_async_event_grp5_cos_priority *)evt);
break;
be_async_grp5_cos_priority_process(adapter, compl);
break;
case ASYNC_EVENT_QOS_SPEED:
be_async_grp5_qos_speed_process(adapter,
(struct be_async_event_grp5_qos_link_speed *)evt);
break;
be_async_grp5_qos_speed_process(adapter, compl);
break;
case ASYNC_EVENT_PVID_STATE:
be_async_grp5_pvid_state_process(adapter,
(struct be_async_event_grp5_pvid_state *)evt);
break;
be_async_grp5_pvid_state_process(adapter, compl);
break;
default:
dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n",
event_type);
@ -286,13 +316,13 @@ static void be_async_grp5_evt_process(struct be_adapter *adapter,
}
static void be_async_dbg_evt_process(struct be_adapter *adapter,
u32 trailer, struct be_mcc_compl *cmp)
struct be_mcc_compl *cmp)
{
u8 event_type = 0;
struct be_async_event_qnq *evt = (struct be_async_event_qnq *) cmp;
event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
ASYNC_TRAILER_EVENT_TYPE_MASK;
event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
ASYNC_EVENT_TYPE_MASK;
switch (event_type) {
case ASYNC_DEBUG_EVENT_TYPE_QNQ:
@ -307,25 +337,33 @@ static void be_async_dbg_evt_process(struct be_adapter *adapter,
}
}
static inline bool is_link_state_evt(u32 trailer)
static inline bool is_link_state_evt(u32 flags)
{
return ((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
ASYNC_TRAILER_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_LINK_STATE;
return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_LINK_STATE;
}
static inline bool is_grp5_evt(u32 trailer)
static inline bool is_grp5_evt(u32 flags)
{
return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
ASYNC_TRAILER_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_GRP_5);
return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_GRP_5;
}
static inline bool is_dbg_evt(u32 trailer)
static inline bool is_dbg_evt(u32 flags)
{
return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) &
ASYNC_TRAILER_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_QNQ);
return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
ASYNC_EVENT_CODE_QNQ;
}
static void be_mcc_event_process(struct be_adapter *adapter,
struct be_mcc_compl *compl)
{
if (is_link_state_evt(compl->flags))
be_async_link_state_process(adapter, compl);
else if (is_grp5_evt(compl->flags))
be_async_grp5_evt_process(adapter, compl);
else if (is_dbg_evt(compl->flags))
be_async_dbg_evt_process(adapter, compl);
}
static struct be_mcc_compl *be_mcc_compl_get(struct be_adapter *adapter)
@ -367,21 +405,13 @@ int be_process_mcc(struct be_adapter *adapter)
struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
spin_lock(&adapter->mcc_cq_lock);
while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
/* Interpret flags as an async trailer */
if (is_link_state_evt(compl->flags))
be_async_link_state_process(adapter,
(struct be_async_event_link_state *) compl);
else if (is_grp5_evt(compl->flags))
be_async_grp5_evt_process(adapter,
compl->flags, compl);
else if (is_dbg_evt(compl->flags))
be_async_dbg_evt_process(adapter,
compl->flags, compl);
be_mcc_event_process(adapter, compl);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used);
status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used);
}
be_mcc_compl_use(compl);
num++;
@ -441,7 +471,9 @@ static int be_mcc_notify_wait(struct be_adapter *adapter)
if (status == -EIO)
goto out;
status = resp->status;
status = (resp->base_status |
((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
CQE_ADDL_STATUS_SHIFT));
out:
return status;
}
@ -2300,7 +2332,7 @@ err_unlock:
}
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
int offset)
u16 optype, int offset)
{
struct be_mcc_wrb *wrb;
struct be_cmd_read_flash_crc *req;
@ -2319,7 +2351,7 @@ int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
wrb, NULL);
req->params.op_type = cpu_to_le32(OPTYPE_REDBOOT);
req->params.op_type = cpu_to_le32(optype);
req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
req->params.offset = cpu_to_le32(offset);
req->params.data_buf_size = cpu_to_le32(0x4);
@ -3562,33 +3594,47 @@ void be_reset_nic_desc(struct be_nic_res_desc *nic)
nic->cq_count = 0xFFFF;
nic->toe_conn_count = 0xFFFF;
nic->eq_count = 0xFFFF;
nic->iface_count = 0xFFFF;
nic->link_param = 0xFF;
nic->channel_id_param = cpu_to_le16(0xF000);
nic->acpi_params = 0xFF;
nic->wol_param = 0x0F;
nic->bw_min = 0xFFFFFFFF;
nic->tunnel_iface_count = 0xFFFF;
nic->direct_tenant_iface_count = 0xFFFF;
nic->bw_max = 0xFFFFFFFF;
}
int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain)
int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate, u16 link_speed,
u8 domain)
{
if (lancer_chip(adapter)) {
struct be_nic_res_desc nic_desc;
struct be_nic_res_desc nic_desc;
u32 bw_percent;
u16 version = 0;
be_reset_nic_desc(&nic_desc);
if (BE3_chip(adapter))
return be_cmd_set_qos(adapter, max_rate / 10, domain);
be_reset_nic_desc(&nic_desc);
nic_desc.pf_num = adapter->pf_number;
nic_desc.vf_num = domain;
if (lancer_chip(adapter)) {
nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V0;
nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
(1 << NOSV_SHIFT);
nic_desc.pf_num = adapter->pf_number;
nic_desc.vf_num = domain;
nic_desc.bw_max = cpu_to_le32(bps);
return be_cmd_set_profile_config(adapter, &nic_desc,
RESOURCE_DESC_SIZE_V0,
0, domain);
nic_desc.bw_max = cpu_to_le32(max_rate / 10);
} else {
return be_cmd_set_qos(adapter, bps, domain);
version = 1;
nic_desc.hdr.desc_type = NIC_RESOURCE_DESC_TYPE_V1;
nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V1;
nic_desc.flags = (1 << IMM_SHIFT) | (1 << NOSV_SHIFT);
bw_percent = max_rate ? (max_rate * 100) / link_speed : 100;
nic_desc.bw_max = cpu_to_le32(bw_percent);
}
return be_cmd_set_profile_config(adapter, &nic_desc,
nic_desc.hdr.desc_len,
version, domain);
}
int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)

View File

@ -50,7 +50,7 @@ struct be_mcc_wrb {
#define CQE_FLAGS_CONSUMED_MASK (1 << 27)
/* Completion Status */
enum {
enum mcc_base_status {
MCC_STATUS_SUCCESS = 0,
MCC_STATUS_FAILED = 1,
MCC_STATUS_ILLEGAL_REQUEST = 2,
@ -60,12 +60,25 @@ enum {
MCC_STATUS_NOT_SUPPORTED = 66
};
#define MCC_ADDL_STS_INSUFFICIENT_RESOURCES 0x16
/* Additional 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
};
#define CQE_STATUS_COMPL_MASK 0xFFFF
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */
#define CQE_STATUS_EXTD_MASK 0xFFFF
#define CQE_STATUS_EXTD_SHIFT 16 /* bits 16 - 31 */
#define CQE_BASE_STATUS_MASK 0xFFFF
#define CQE_BASE_STATUS_SHIFT 0 /* bits 0 - 15 */
#define CQE_ADDL_STATUS_MASK 0xFF
#define CQE_ADDL_STATUS_SHIFT 16 /* bits 16 - 31 */
#define base_status(status) \
((enum mcc_base_status) \
(status > 0 ? (status & CQE_BASE_STATUS_MASK) : 0))
#define addl_status(status) \
((enum mcc_addl_status) \
(status > 0 ? (status >> CQE_ADDL_STATUS_SHIFT) & \
CQE_ADDL_STATUS_MASK : 0))
struct be_mcc_compl {
u32 status; /* dword 0 */
@ -74,13 +87,13 @@ struct be_mcc_compl {
u32 flags; /* dword 3 */
};
/* When the async bit of mcc_compl is set, the last 4 bytes of
* mcc_compl is interpreted as follows:
/* When the async bit of mcc_compl flags is set, flags
* is interpreted as follows:
*/
#define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */
#define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF
#define ASYNC_TRAILER_EVENT_TYPE_SHIFT 16
#define ASYNC_TRAILER_EVENT_TYPE_MASK 0xFF
#define ASYNC_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */
#define ASYNC_EVENT_CODE_MASK 0xFF
#define ASYNC_EVENT_TYPE_SHIFT 16
#define ASYNC_EVENT_TYPE_MASK 0xFF
#define ASYNC_EVENT_CODE_LINK_STATE 0x1
#define ASYNC_EVENT_CODE_GRP_5 0x5
#define ASYNC_EVENT_QOS_SPEED 0x1
@ -89,10 +102,6 @@ struct be_mcc_compl {
#define ASYNC_EVENT_CODE_QNQ 0x6
#define ASYNC_DEBUG_EVENT_TYPE_QNQ 1
struct be_async_event_trailer {
u32 code;
};
enum {
LINK_DOWN = 0x0,
LINK_UP = 0x1
@ -100,7 +109,7 @@ enum {
#define LINK_STATUS_MASK 0x1
#define LOGICAL_LINK_STATUS_MASK 0x2
/* When the event code of an async trailer is link-state, the mcc_compl
/* When the event code of compl->flags is link-state, the mcc_compl
* must be interpreted as follows
*/
struct be_async_event_link_state {
@ -110,10 +119,10 @@ struct be_async_event_link_state {
u8 port_speed;
u8 port_fault;
u8 rsvd0[7];
struct be_async_event_trailer trailer;
u32 flags;
} __packed;
/* When the event code of an async trailer is GRP-5 and event_type is QOS_SPEED
/* When the event code of compl->flags is GRP-5 and event_type is QOS_SPEED
* the mcc_compl must be interpreted as follows
*/
struct be_async_event_grp5_qos_link_speed {
@ -121,10 +130,10 @@ struct be_async_event_grp5_qos_link_speed {
u8 rsvd[5];
u16 qos_link_speed;
u32 event_tag;
struct be_async_event_trailer trailer;
u32 flags;
} __packed;
/* When the event code of an async trailer is GRP5 and event type is
/* When the event code of compl->flags is GRP5 and event type is
* CoS-Priority, the mcc_compl must be interpreted as follows
*/
struct be_async_event_grp5_cos_priority {
@ -134,10 +143,10 @@ struct be_async_event_grp5_cos_priority {
u8 valid;
u8 rsvd0;
u8 event_tag;
struct be_async_event_trailer trailer;
u32 flags;
} __packed;
/* When the event code of an async trailer is GRP5 and event type is
/* When the event code of compl->flags is GRP5 and event type is
* PVID state, the mcc_compl must be interpreted as follows
*/
struct be_async_event_grp5_pvid_state {
@ -146,7 +155,7 @@ struct be_async_event_grp5_pvid_state {
u16 tag;
u32 event_tag;
u32 rsvd1;
struct be_async_event_trailer trailer;
u32 flags;
} __packed;
/* async event indicating outer VLAN tag in QnQ */
@ -156,7 +165,7 @@ struct be_async_event_qnq {
u16 vlan_tag;
u32 event_tag;
u8 rsvd1[4];
struct be_async_event_trailer trailer;
u32 flags;
} __packed;
struct be_mcc_mailbox {
@ -258,8 +267,8 @@ struct be_cmd_resp_hdr {
u8 opcode; /* dword 0 */
u8 subsystem; /* dword 0 */
u8 rsvd[2]; /* dword 0 */
u8 status; /* dword 1 */
u8 add_status; /* dword 1 */
u8 base_status; /* dword 1 */
u8 addl_status; /* dword 1 */
u8 rsvd1[2]; /* dword 1 */
u32 response_length; /* dword 2 */
u32 actual_resp_len; /* dword 3 */
@ -1186,7 +1195,8 @@ struct be_cmd_read_flash_crc {
struct flashrom_params params;
u8 crc[4];
u8 rsvd[4];
};
} __packed;
/**************** Lancer Firmware Flash ************/
struct amap_lancer_write_obj_context {
u8 write_length[24];
@ -1891,16 +1901,20 @@ struct be_nic_res_desc {
u16 cq_count;
u16 toe_conn_count;
u16 eq_count;
u32 rsvd5;
u16 vlan_id;
u16 iface_count;
u32 cap_flags;
u8 link_param;
u8 rsvd6[3];
u8 rsvd6;
u16 channel_id_param;
u32 bw_min;
u32 bw_max;
u8 acpi_params;
u8 wol_param;
u16 rsvd7;
u32 rsvd8[7];
u16 tunnel_iface_count;
u16 direct_tenant_iface_count;
u32 rsvd8[6];
} __packed;
/************ Multi-Channel type ***********/
@ -2084,7 +2098,7 @@ int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,
u32 data_size, u32 data_offset, const char *obj_name,
u32 *data_read, u32 *eof, u8 *addn_status);
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc,
int offset);
u16 optype, int offset);
int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
struct be_dma_mem *nonemb_cmd);
int be_cmd_fw_init(struct be_adapter *adapter);
@ -2101,7 +2115,8 @@ int be_cmd_get_seeprom_data(struct be_adapter *adapter,
int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
u8 loopback_type, u8 enable);
int be_cmd_get_phy_info(struct be_adapter *adapter);
int be_cmd_config_qos(struct be_adapter *adapter, u32 bps, u8 domain);
int be_cmd_config_qos(struct be_adapter *adapter, u32 max_rate,
u16 link_speed, u8 domain);
void be_detect_error(struct be_adapter *adapter);
int be_cmd_get_die_temperature(struct be_adapter *adapter);
int be_cmd_get_cntl_attributes(struct be_adapter *adapter);

View File

@ -188,10 +188,14 @@
#define OPTYPE_FCOE_FW_ACTIVE 10
#define OPTYPE_FCOE_FW_BACKUP 11
#define OPTYPE_NCSI_FW 13
#define OPTYPE_REDBOOT_DIR 18
#define OPTYPE_REDBOOT_CONFIG 19
#define OPTYPE_SH_PHY_FW 21
#define OPTYPE_FLASHISM_JUMPVECTOR 22
#define OPTYPE_UFI_DIR 23
#define OPTYPE_PHY_FW 99
#define TN_8022 13
#define ILLEGAL_IOCTL_REQ 2
#define FLASHROM_OPER_PHY_FLASH 9
#define FLASHROM_OPER_PHY_SAVE 10
#define FLASHROM_OPER_FLASH 1
@ -250,6 +254,9 @@
#define IMAGE_FIRMWARE_BACKUP_FCoE 178
#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179
#define IMAGE_FIRMWARE_PHY 192
#define IMAGE_REDBOOT_DIR 208
#define IMAGE_REDBOOT_CONFIG 209
#define IMAGE_UFI_DIR 210
#define IMAGE_BOOT_CODE 224
/************* Rx Packet Type Encoding **************/
@ -534,7 +541,8 @@ struct flash_section_entry {
u32 image_size;
u32 cksum;
u32 entry_point;
u32 rsvd0;
u16 optype;
u16 rsvd0;
u32 rsvd1;
u8 ver_data[32];
} __packed;

View File

@ -1111,7 +1111,8 @@ static int be_vid_config(struct be_adapter *adapter)
status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num);
if (status) {
/* Set to VLAN promisc mode as setting VLAN filter failed */
if (status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES)
if (addl_status(status) ==
MCC_ADDL_STATUS_INSUFFICIENT_RESOURCES)
goto set_vlan_promisc;
dev_err(&adapter->pdev->dev,
"Setting HW VLAN filtering failed.\n");
@ -1190,7 +1191,7 @@ ret:
static void be_clear_promisc(struct be_adapter *adapter)
{
adapter->promiscuous = false;
adapter->flags &= ~BE_FLAGS_VLAN_PROMISC;
adapter->flags &= ~(BE_FLAGS_VLAN_PROMISC | BE_FLAGS_MCAST_PROMISC);
be_cmd_rx_filter(adapter, IFF_PROMISC, OFF);
}
@ -1215,10 +1216,8 @@ 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(adapter)) {
be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
goto done;
}
netdev_mc_count(netdev) > be_max_mc(adapter))
goto set_mcast_promisc;
if (netdev_uc_count(netdev) != adapter->uc_macs) {
struct netdev_hw_addr *ha;
@ -1244,15 +1243,22 @@ static void be_set_rx_mode(struct net_device *netdev)
}
status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
/* Set to MCAST promisc mode if setting MULTICAST address fails */
if (status) {
dev_info(&adapter->pdev->dev,
"Exhausted multicast HW filters.\n");
dev_info(&adapter->pdev->dev,
"Disabling HW multicast filtering.\n");
be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
if (!status) {
if (adapter->flags & BE_FLAGS_MCAST_PROMISC)
adapter->flags &= ~BE_FLAGS_MCAST_PROMISC;
goto done;
}
set_mcast_promisc:
if (adapter->flags & BE_FLAGS_MCAST_PROMISC)
return;
/* Set to MCAST promisc mode if setting MULTICAST address fails
* or if num configured exceeds what we support
*/
status = be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
if (!status)
adapter->flags |= BE_FLAGS_MCAST_PROMISC;
done:
return;
}
@ -1347,7 +1353,10 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
int min_tx_rate, int max_tx_rate)
{
struct be_adapter *adapter = netdev_priv(netdev);
int status = 0;
struct device *dev = &adapter->pdev->dev;
int percent_rate, status = 0;
u16 link_speed = 0;
u8 link_status;
if (!sriov_enabled(adapter))
return -EPERM;
@ -1358,18 +1367,47 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
if (min_tx_rate)
return -EINVAL;
if (max_tx_rate < 100 || max_tx_rate > 10000) {
dev_err(&adapter->pdev->dev,
"max tx rate must be between 100 and 10000 Mbps\n");
return -EINVAL;
if (!max_tx_rate)
goto config_qos;
status = be_cmd_link_status_query(adapter, &link_speed,
&link_status, 0);
if (status)
goto err;
if (!link_status) {
dev_err(dev, "TX-rate setting not allowed when link is down\n");
status = -EPERM;
goto err;
}
status = be_cmd_config_qos(adapter, max_tx_rate / 10, vf + 1);
if (max_tx_rate < 100 || max_tx_rate > link_speed) {
dev_err(dev, "TX-rate must be between 100 and %d Mbps\n",
link_speed);
status = -EINVAL;
goto err;
}
/* On Skyhawk the QOS setting must be done only as a % value */
percent_rate = link_speed / 100;
if (skyhawk_chip(adapter) && (max_tx_rate % percent_rate)) {
dev_err(dev, "TX-rate must be a multiple of %d Mbps\n",
percent_rate);
status = -EINVAL;
goto err;
}
config_qos:
status = be_cmd_config_qos(adapter, max_tx_rate, link_speed, vf + 1);
if (status)
dev_err(&adapter->pdev->dev,
"max tx rate %d on VF %d failed\n", max_tx_rate, vf);
else
adapter->vf_cfg[vf].tx_rate = max_tx_rate;
goto err;
adapter->vf_cfg[vf].tx_rate = max_tx_rate;
return 0;
err:
dev_err(dev, "TX-rate setting of %dMbps on VF%d failed\n",
max_tx_rate, vf);
return status;
}
static int be_set_vf_link_state(struct net_device *netdev, int vf,
@ -3130,7 +3168,6 @@ static int be_vf_setup(struct be_adapter *adapter)
struct be_vf_cfg *vf_cfg;
int status, old_vfs, vf;
u32 privileges;
u16 lnk_speed;
old_vfs = pci_num_vf(adapter->pdev);
if (old_vfs) {
@ -3186,16 +3223,9 @@ static int be_vf_setup(struct be_adapter *adapter)
vf);
}
/* BE3 FW, by default, caps VF TX-rate to 100mbps.
* Allow full available bandwidth
*/
if (BE3_chip(adapter) && !old_vfs)
be_cmd_config_qos(adapter, 1000, vf + 1);
status = be_cmd_link_status_query(adapter, &lnk_speed,
NULL, vf + 1);
if (!status)
vf_cfg->tx_rate = lnk_speed;
/* Allow full available bandwidth */
if (!old_vfs)
be_cmd_config_qos(adapter, 0, 0, vf + 1);
if (!old_vfs) {
be_cmd_enable_vf(adapter, vf + 1);
@ -3601,34 +3631,7 @@ static void be_netpoll(struct net_device *netdev)
}
#endif
#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
static bool be_flash_redboot(struct be_adapter *adapter,
const u8 *p, u32 img_start, int image_size,
int hdr_size)
{
u32 crc_offset;
u8 flashed_crc[4];
int status;
crc_offset = hdr_size + img_start + image_size - 4;
p += crc_offset;
status = be_cmd_get_flash_crc(adapter, flashed_crc, (image_size - 4));
if (status) {
dev_err(&adapter->pdev->dev,
"could not get crc from flash, not flashing redboot\n");
return false;
}
/*update redboot only if crc does not match*/
if (!memcmp(flashed_crc, p, 4))
return false;
else
return true;
}
static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
static bool phy_flashing_required(struct be_adapter *adapter)
{
@ -3675,12 +3678,35 @@ static struct flash_section_info *get_fsec_info(struct be_adapter *adapter,
return NULL;
}
static int be_check_flash_crc(struct be_adapter *adapter, const u8 *p,
u32 img_offset, u32 img_size, int hdr_size,
u16 img_optype, bool *crc_match)
{
u32 crc_offset;
int status;
u8 crc[4];
status = be_cmd_get_flash_crc(adapter, crc, img_optype, img_size - 4);
if (status)
return status;
crc_offset = hdr_size + img_offset + img_size - 4;
/* Skip flashing, if crc of flashed region matches */
if (!memcmp(crc, p + crc_offset, 4))
*crc_match = true;
else
*crc_match = false;
return status;
}
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;
u32 total_bytes, flash_op, num_bytes;
int status;
total_bytes = img_size;
while (total_bytes) {
@ -3704,14 +3730,11 @@ static int be_flash(struct be_adapter *adapter, const u8 *img,
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");
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
optype == OPTYPE_PHY_FW)
break;
else if (status)
return status;
}
}
return 0;
}
@ -3721,12 +3744,13 @@ static int be_flash_BEx(struct be_adapter *adapter,
const struct firmware *fw,
struct be_dma_mem *flash_cmd, int num_of_images)
{
int status = 0, i, filehdr_size = 0;
int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
const u8 *p = fw->data;
const struct flash_comp *pflashcomp;
int num_comp, redboot;
struct device *dev = &adapter->pdev->dev;
struct flash_section_info *fsec = NULL;
int status, i, filehdr_size, num_comp;
const struct flash_comp *pflashcomp;
bool crc_match;
const u8 *p;
struct flash_comp gen3_flash_types[] = {
{ FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE,
@ -3783,8 +3807,7 @@ static int be_flash_BEx(struct be_adapter *adapter,
/* Get flash section info*/
fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
if (!fsec) {
dev_err(&adapter->pdev->dev,
"Invalid Cookie. UFI corrupted ?\n");
dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
return -1;
}
for (i = 0; i < num_comp; i++) {
@ -3800,25 +3823,32 @@ static int be_flash_BEx(struct be_adapter *adapter,
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)
status = be_check_flash_crc(adapter, fw->data,
pflashcomp[i].offset,
pflashcomp[i].size,
filehdr_size +
img_hdrs_size,
OPTYPE_REDBOOT, &crc_match);
if (status) {
dev_err(dev,
"Could not get CRC for 0x%x region\n",
pflashcomp[i].optype);
continue;
}
if (crc_match)
continue;
}
p = fw->data;
p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
p = fw->data + filehdr_size + pflashcomp[i].offset +
img_hdrs_size;
if (p + pflashcomp[i].size > fw->data + fw->size)
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",
dev_err(dev, "Flashing section type 0x%x failed\n",
pflashcomp[i].img_type);
return status;
}
@ -3826,74 +3856,135 @@ static int be_flash_BEx(struct be_adapter *adapter,
return 0;
}
static u16 be_get_img_optype(struct flash_section_entry fsec_entry)
{
u32 img_type = le32_to_cpu(fsec_entry.type);
u16 img_optype = le16_to_cpu(fsec_entry.optype);
if (img_optype != 0xFFFF)
return img_optype;
switch (img_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;
case IMAGE_FLASHISM_JUMPVECTOR:
img_optype = OPTYPE_FLASHISM_JUMPVECTOR;
break;
case IMAGE_FIRMWARE_PHY:
img_optype = OPTYPE_SH_PHY_FW;
break;
case IMAGE_REDBOOT_DIR:
img_optype = OPTYPE_REDBOOT_DIR;
break;
case IMAGE_REDBOOT_CONFIG:
img_optype = OPTYPE_REDBOOT_CONFIG;
break;
case IMAGE_UFI_DIR:
img_optype = OPTYPE_UFI_DIR;
break;
default:
break;
}
return img_optype;
}
static int be_flash_skyhawk(struct be_adapter *adapter,
const struct firmware *fw,
struct be_dma_mem *flash_cmd, int num_of_images)
{
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 device *dev = &adapter->pdev->dev;
struct flash_section_info *fsec = NULL;
u32 img_offset, img_size, img_type;
int status, i, filehdr_size;
bool crc_match, old_fw_img;
u16 img_optype;
const u8 *p;
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");
dev_err(dev, "Invalid Cookie. FW image may be 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);
img_type = le32_to_cpu(fsec->fsec_entry[i].type);
img_optype = be_get_img_optype(fsec->fsec_entry[i]);
old_fw_img = fsec->fsec_entry[i].optype == 0xFFFF;
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:
if (img_optype == 0xFFFF)
continue;
/* Don't bother verifying CRC if an old FW image is being
* flashed
*/
if (old_fw_img)
goto flash;
status = be_check_flash_crc(adapter, fw->data, img_offset,
img_size, filehdr_size +
img_hdrs_size, img_optype,
&crc_match);
/* The current FW image on the card does not recognize the new
* FLASH op_type. The FW download is partially complete.
* Reboot the server now to enable FW image to recognize the
* new FLASH op_type. To complete the remaining process,
* download the same FW again after the reboot.
*/
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST ||
base_status(status) == MCC_STATUS_ILLEGAL_FIELD) {
dev_err(dev, "Flash incomplete. Reset the server\n");
dev_err(dev, "Download FW image again after reset\n");
return -EAGAIN;
} else if (status) {
dev_err(dev, "Could not get CRC for 0x%x region\n",
img_optype);
return -EFAULT;
}
if (img_optype == OPTYPE_REDBOOT) {
redboot = be_flash_redboot(adapter, fw->data,
img_offset, img_size,
filehdr_size +
img_hdrs_size);
if (!redboot)
continue;
}
if (crc_match)
continue;
p = fw->data;
p += filehdr_size + img_offset + img_hdrs_size;
flash:
p = fw->data + 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;
/* For old FW images ignore ILLEGAL_FIELD error or errors on
* UFI_DIR region
*/
if (old_fw_img &&
(base_status(status) == MCC_STATUS_ILLEGAL_FIELD ||
(img_optype == OPTYPE_UFI_DIR &&
base_status(status) == MCC_STATUS_FAILED))) {
continue;
} else if (status) {
dev_err(dev, "Flashing section type 0x%x failed\n",
img_type);
return -EFAULT;
}
}
return 0;