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_LINK_STATUS_INIT 1
#define BE_FLAGS_WORKER_SCHEDULED (1 << 3) #define BE_FLAGS_WORKER_SCHEDULED (1 << 3)
#define BE_FLAGS_VLAN_PROMISC (1 << 4) #define BE_FLAGS_VLAN_PROMISC (1 << 4)
#define BE_FLAGS_MCAST_PROMISC (1 << 5)
#define BE_FLAGS_NAPI_ENABLED (1 << 9) #define BE_FLAGS_NAPI_ENABLED (1 << 9)
#define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11) #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD (1 << 11)
#define BE_FLAGS_VXLAN_OFFLOADS (1 << 12) #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; return (void *)addr;
} }
static int be_mcc_compl_process(struct be_adapter *adapter, static bool be_skip_err_log(u8 opcode, u16 base_status, u16 addl_status)
struct be_mcc_compl *compl)
{ {
u16 compl_status, extd_status; if (base_status == MCC_STATUS_NOT_SUPPORTED ||
struct be_cmd_resp_hdr *resp_hdr; 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; 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) { if (resp_hdr) {
opcode = resp_hdr->opcode; opcode = resp_hdr->opcode;
subsystem = resp_hdr->subsystem; subsystem = resp_hdr->subsystem;
@ -143,61 +150,86 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST && if (opcode == OPCODE_LOWLEVEL_LOOPBACK_TEST &&
subsystem == CMD_SUBSYSTEM_LOWLEVEL) { subsystem == CMD_SUBSYSTEM_LOWLEVEL) {
complete(&adapter->et_cmd_compl); complete(&adapter->et_cmd_compl);
return 0; return;
} }
if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) || if ((opcode == OPCODE_COMMON_WRITE_FLASHROM ||
(opcode == OPCODE_COMMON_WRITE_OBJECT)) && opcode == OPCODE_COMMON_WRITE_OBJECT) &&
(subsystem == CMD_SUBSYSTEM_COMMON)) { subsystem == CMD_SUBSYSTEM_COMMON) {
adapter->flash_status = compl_status; adapter->flash_status = compl->status;
complete(&adapter->et_cmd_compl); complete(&adapter->et_cmd_compl);
return;
} }
if (compl_status == MCC_STATUS_SUCCESS) { if ((opcode == OPCODE_ETH_GET_STATISTICS ||
if (((opcode == OPCODE_ETH_GET_STATISTICS) || opcode == OPCODE_ETH_GET_PPORT_STATS) &&
(opcode == OPCODE_ETH_GET_PPORT_STATS)) && subsystem == CMD_SUBSYSTEM_ETH &&
(subsystem == CMD_SUBSYSTEM_ETH)) { base_status == MCC_STATUS_SUCCESS) {
be_parse_stats(adapter); be_parse_stats(adapter);
adapter->stats_cmd_sent = false; adapter->stats_cmd_sent = false;
} return;
if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES && }
subsystem == CMD_SUBSYSTEM_COMMON) {
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 = struct be_cmd_resp_get_cntl_addnl_attribs *resp =
(void *)resp_hdr; (void *)resp_hdr;
adapter->drv_stats.be_on_die_temperature = adapter->drv_stats.be_on_die_temperature =
resp->on_die_temperature; resp->on_die_temperature;
} } else {
} else {
if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
adapter->be_get_temp_freq = 0; adapter->be_get_temp_freq = 0;
}
return;
}
}
if (compl_status == MCC_STATUS_NOT_SUPPORTED || static int be_mcc_compl_process(struct be_adapter *adapter,
compl_status == MCC_STATUS_ILLEGAL_REQUEST) struct be_mcc_compl *compl)
goto done; {
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, dev_warn(&adapter->pdev->dev,
"VF is not privileged to issue opcode %d-%d\n", "VF is not privileged to issue opcode %d-%d\n",
opcode, subsystem); opcode, subsystem);
} else { } else {
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
CQE_STATUS_EXTD_MASK;
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"opcode %d-%d failed:status %d-%d\n", "opcode %d-%d failed:status %d-%d\n",
opcode, subsystem, compl_status, extd_status); opcode, subsystem, base_status, addl_status);
if (extd_status == MCC_ADDL_STS_INSUFFICIENT_RESOURCES)
return extd_status;
} }
} }
done: return compl->status;
return compl_status;
} }
/* Link state evt is a string of bytes; no need for endian swapping */ /* Link state evt is a string of bytes; no need for endian swapping */
static void be_async_link_state_process(struct be_adapter *adapter, 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 */ /* When link status changes, link speed must be re-queried from FW */
adapter->phy.link_speed = -1; adapter->phy.link_speed = -1;
@ -220,10 +252,11 @@ static void be_async_link_state_process(struct be_adapter *adapter,
/* Grp5 CoS Priority evt */ /* Grp5 CoS Priority evt */
static void be_async_grp5_cos_priority_process(struct be_adapter *adapter, static void be_async_grp5_cos_priority_process(struct be_adapter *adapter,
struct struct be_mcc_compl *compl)
be_async_event_grp5_cos_priority
*evt)
{ {
struct be_async_event_grp5_cos_priority *evt =
(struct be_async_event_grp5_cos_priority *)compl;
if (evt->valid) { if (evt->valid) {
adapter->vlan_prio_bmap = evt->available_priority_bmap; adapter->vlan_prio_bmap = evt->available_priority_bmap;
adapter->recommended_prio &= ~VLAN_PRIO_MASK; 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 */ /* 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, static void be_async_grp5_qos_speed_process(struct be_adapter *adapter,
struct struct be_mcc_compl *compl)
be_async_event_grp5_qos_link_speed
*evt)
{ {
struct be_async_event_grp5_qos_link_speed *evt =
(struct be_async_event_grp5_qos_link_speed *)compl;
if (adapter->phy.link_speed >= 0 && if (adapter->phy.link_speed >= 0 &&
evt->physical_port == adapter->port_num) evt->physical_port == adapter->port_num)
adapter->phy.link_speed = le16_to_cpu(evt->qos_link_speed) * 10; 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*/ /*Grp5 PVID evt*/
static void be_async_grp5_pvid_state_process(struct be_adapter *adapter, static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
struct struct be_mcc_compl *compl)
be_async_event_grp5_pvid_state
*evt)
{ {
struct be_async_event_grp5_pvid_state *evt =
(struct be_async_event_grp5_pvid_state *)compl;
if (evt->enabled) { if (evt->enabled) {
adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK; adapter->pvid = le16_to_cpu(evt->tag) & VLAN_VID_MASK;
dev_info(&adapter->pdev->dev, "LPVID: %d\n", adapter->pvid); 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, 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; u8 event_type = (compl->flags >> ASYNC_EVENT_TYPE_SHIFT) &
ASYNC_EVENT_TYPE_MASK;
event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) &
ASYNC_TRAILER_EVENT_TYPE_MASK;
switch (event_type) { switch (event_type) {
case ASYNC_EVENT_COS_PRIORITY: case ASYNC_EVENT_COS_PRIORITY:
be_async_grp5_cos_priority_process(adapter, be_async_grp5_cos_priority_process(adapter, compl);
(struct be_async_event_grp5_cos_priority *)evt); break;
break;
case ASYNC_EVENT_QOS_SPEED: case ASYNC_EVENT_QOS_SPEED:
be_async_grp5_qos_speed_process(adapter, be_async_grp5_qos_speed_process(adapter, compl);
(struct be_async_event_grp5_qos_link_speed *)evt); break;
break;
case ASYNC_EVENT_PVID_STATE: case ASYNC_EVENT_PVID_STATE:
be_async_grp5_pvid_state_process(adapter, be_async_grp5_pvid_state_process(adapter, compl);
(struct be_async_event_grp5_pvid_state *)evt); break;
break;
default: default:
dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n", dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n",
event_type); 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, 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; u8 event_type = 0;
struct be_async_event_qnq *evt = (struct be_async_event_qnq *) cmp; struct be_async_event_qnq *evt = (struct be_async_event_qnq *) cmp;
event_type = (trailer >> ASYNC_TRAILER_EVENT_TYPE_SHIFT) & event_type = (cmp->flags >> ASYNC_EVENT_TYPE_SHIFT) &
ASYNC_TRAILER_EVENT_TYPE_MASK; ASYNC_EVENT_TYPE_MASK;
switch (event_type) { switch (event_type) {
case ASYNC_DEBUG_EVENT_TYPE_QNQ: 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) & return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_LINK_STATE;
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) & return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_GRP_5;
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) & return ((flags >> ASYNC_EVENT_CODE_SHIFT) & ASYNC_EVENT_CODE_MASK) ==
ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_QNQ;
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) 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; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
spin_lock(&adapter->mcc_cq_lock); spin_lock(&adapter->mcc_cq_lock);
while ((compl = be_mcc_compl_get(adapter))) { while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
/* Interpret flags as an async trailer */ be_mcc_event_process(adapter, compl);
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);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { } else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
status = be_mcc_compl_process(adapter, compl); status = be_mcc_compl_process(adapter, compl);
atomic_dec(&mcc_obj->q.used); atomic_dec(&mcc_obj->q.used);
} }
be_mcc_compl_use(compl); be_mcc_compl_use(compl);
num++; num++;
@ -441,7 +471,9 @@ static int be_mcc_notify_wait(struct be_adapter *adapter)
if (status == -EIO) if (status == -EIO)
goto out; goto out;
status = resp->status; status = (resp->base_status |
((resp->addl_status & CQE_ADDL_STATUS_MASK) <<
CQE_ADDL_STATUS_SHIFT));
out: out:
return status; return status;
} }
@ -2300,7 +2332,7 @@ err_unlock:
} }
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, 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_mcc_wrb *wrb;
struct be_cmd_read_flash_crc *req; 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), OPCODE_COMMON_READ_FLASHROM, sizeof(*req),
wrb, NULL); 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.op_code = cpu_to_le32(FLASHROM_OPER_REPORT);
req->params.offset = cpu_to_le32(offset); req->params.offset = cpu_to_le32(offset);
req->params.data_buf_size = cpu_to_le32(0x4); 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->cq_count = 0xFFFF;
nic->toe_conn_count = 0xFFFF; nic->toe_conn_count = 0xFFFF;
nic->eq_count = 0xFFFF; nic->eq_count = 0xFFFF;
nic->iface_count = 0xFFFF;
nic->link_param = 0xFF; nic->link_param = 0xFF;
nic->channel_id_param = cpu_to_le16(0xF000);
nic->acpi_params = 0xFF; nic->acpi_params = 0xFF;
nic->wol_param = 0x0F; nic->wol_param = 0x0F;
nic->bw_min = 0xFFFFFFFF; nic->tunnel_iface_count = 0xFFFF;
nic->direct_tenant_iface_count = 0xFFFF;
nic->bw_max = 0xFFFFFFFF; 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_type = NIC_RESOURCE_DESC_TYPE_V0;
nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0; nic_desc.hdr.desc_len = RESOURCE_DESC_SIZE_V0;
nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) | nic_desc.flags = (1 << QUN_SHIFT) | (1 << IMM_SHIFT) |
(1 << NOSV_SHIFT); (1 << NOSV_SHIFT);
nic_desc.pf_num = adapter->pf_number; nic_desc.bw_max = cpu_to_le32(max_rate / 10);
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);
} else { } 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) 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) #define CQE_FLAGS_CONSUMED_MASK (1 << 27)
/* Completion Status */ /* Completion Status */
enum { enum mcc_base_status {
MCC_STATUS_SUCCESS = 0, MCC_STATUS_SUCCESS = 0,
MCC_STATUS_FAILED = 1, MCC_STATUS_FAILED = 1,
MCC_STATUS_ILLEGAL_REQUEST = 2, MCC_STATUS_ILLEGAL_REQUEST = 2,
@ -60,12 +60,25 @@ enum {
MCC_STATUS_NOT_SUPPORTED = 66 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_BASE_STATUS_MASK 0xFFFF
#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ #define CQE_BASE_STATUS_SHIFT 0 /* bits 0 - 15 */
#define CQE_STATUS_EXTD_MASK 0xFFFF #define CQE_ADDL_STATUS_MASK 0xFF
#define CQE_STATUS_EXTD_SHIFT 16 /* bits 16 - 31 */ #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 { struct be_mcc_compl {
u32 status; /* dword 0 */ u32 status; /* dword 0 */
@ -74,13 +87,13 @@ struct be_mcc_compl {
u32 flags; /* dword 3 */ u32 flags; /* dword 3 */
}; };
/* When the async bit of mcc_compl is set, the last 4 bytes of /* When the async bit of mcc_compl flags is set, flags
* mcc_compl is interpreted as follows: * is interpreted as follows:
*/ */
#define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */ #define ASYNC_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */
#define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF #define ASYNC_EVENT_CODE_MASK 0xFF
#define ASYNC_TRAILER_EVENT_TYPE_SHIFT 16 #define ASYNC_EVENT_TYPE_SHIFT 16
#define ASYNC_TRAILER_EVENT_TYPE_MASK 0xFF #define ASYNC_EVENT_TYPE_MASK 0xFF
#define ASYNC_EVENT_CODE_LINK_STATE 0x1 #define ASYNC_EVENT_CODE_LINK_STATE 0x1
#define ASYNC_EVENT_CODE_GRP_5 0x5 #define ASYNC_EVENT_CODE_GRP_5 0x5
#define ASYNC_EVENT_QOS_SPEED 0x1 #define ASYNC_EVENT_QOS_SPEED 0x1
@ -89,10 +102,6 @@ struct be_mcc_compl {
#define ASYNC_EVENT_CODE_QNQ 0x6 #define ASYNC_EVENT_CODE_QNQ 0x6
#define ASYNC_DEBUG_EVENT_TYPE_QNQ 1 #define ASYNC_DEBUG_EVENT_TYPE_QNQ 1
struct be_async_event_trailer {
u32 code;
};
enum { enum {
LINK_DOWN = 0x0, LINK_DOWN = 0x0,
LINK_UP = 0x1 LINK_UP = 0x1
@ -100,7 +109,7 @@ enum {
#define LINK_STATUS_MASK 0x1 #define LINK_STATUS_MASK 0x1
#define LOGICAL_LINK_STATUS_MASK 0x2 #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 * must be interpreted as follows
*/ */
struct be_async_event_link_state { struct be_async_event_link_state {
@ -110,10 +119,10 @@ struct be_async_event_link_state {
u8 port_speed; u8 port_speed;
u8 port_fault; u8 port_fault;
u8 rsvd0[7]; u8 rsvd0[7];
struct be_async_event_trailer trailer; u32 flags;
} __packed; } __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 * the mcc_compl must be interpreted as follows
*/ */
struct be_async_event_grp5_qos_link_speed { struct be_async_event_grp5_qos_link_speed {
@ -121,10 +130,10 @@ struct be_async_event_grp5_qos_link_speed {
u8 rsvd[5]; u8 rsvd[5];
u16 qos_link_speed; u16 qos_link_speed;
u32 event_tag; u32 event_tag;
struct be_async_event_trailer trailer; u32 flags;
} __packed; } __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 * CoS-Priority, the mcc_compl must be interpreted as follows
*/ */
struct be_async_event_grp5_cos_priority { struct be_async_event_grp5_cos_priority {
@ -134,10 +143,10 @@ struct be_async_event_grp5_cos_priority {
u8 valid; u8 valid;
u8 rsvd0; u8 rsvd0;
u8 event_tag; u8 event_tag;
struct be_async_event_trailer trailer; u32 flags;
} __packed; } __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 * PVID state, the mcc_compl must be interpreted as follows
*/ */
struct be_async_event_grp5_pvid_state { struct be_async_event_grp5_pvid_state {
@ -146,7 +155,7 @@ struct be_async_event_grp5_pvid_state {
u16 tag; u16 tag;
u32 event_tag; u32 event_tag;
u32 rsvd1; u32 rsvd1;
struct be_async_event_trailer trailer; u32 flags;
} __packed; } __packed;
/* async event indicating outer VLAN tag in QnQ */ /* async event indicating outer VLAN tag in QnQ */
@ -156,7 +165,7 @@ struct be_async_event_qnq {
u16 vlan_tag; u16 vlan_tag;
u32 event_tag; u32 event_tag;
u8 rsvd1[4]; u8 rsvd1[4];
struct be_async_event_trailer trailer; u32 flags;
} __packed; } __packed;
struct be_mcc_mailbox { struct be_mcc_mailbox {
@ -258,8 +267,8 @@ struct be_cmd_resp_hdr {
u8 opcode; /* dword 0 */ u8 opcode; /* dword 0 */
u8 subsystem; /* dword 0 */ u8 subsystem; /* dword 0 */
u8 rsvd[2]; /* dword 0 */ u8 rsvd[2]; /* dword 0 */
u8 status; /* dword 1 */ u8 base_status; /* dword 1 */
u8 add_status; /* dword 1 */ u8 addl_status; /* dword 1 */
u8 rsvd1[2]; /* dword 1 */ u8 rsvd1[2]; /* dword 1 */
u32 response_length; /* dword 2 */ u32 response_length; /* dword 2 */
u32 actual_resp_len; /* dword 3 */ u32 actual_resp_len; /* dword 3 */
@ -1186,7 +1195,8 @@ struct be_cmd_read_flash_crc {
struct flashrom_params params; struct flashrom_params params;
u8 crc[4]; u8 crc[4];
u8 rsvd[4]; u8 rsvd[4];
}; } __packed;
/**************** Lancer Firmware Flash ************/ /**************** Lancer Firmware Flash ************/
struct amap_lancer_write_obj_context { struct amap_lancer_write_obj_context {
u8 write_length[24]; u8 write_length[24];
@ -1891,16 +1901,20 @@ struct be_nic_res_desc {
u16 cq_count; u16 cq_count;
u16 toe_conn_count; u16 toe_conn_count;
u16 eq_count; u16 eq_count;
u32 rsvd5; u16 vlan_id;
u16 iface_count;
u32 cap_flags; u32 cap_flags;
u8 link_param; u8 link_param;
u8 rsvd6[3]; u8 rsvd6;
u16 channel_id_param;
u32 bw_min; u32 bw_min;
u32 bw_max; u32 bw_max;
u8 acpi_params; u8 acpi_params;
u8 wol_param; u8 wol_param;
u16 rsvd7; u16 rsvd7;
u32 rsvd8[7]; u16 tunnel_iface_count;
u16 direct_tenant_iface_count;
u32 rsvd8[6];
} __packed; } __packed;
/************ Multi-Channel type ***********/ /************ 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_size, u32 data_offset, const char *obj_name,
u32 *data_read, u32 *eof, u8 *addn_status); u32 *data_read, u32 *eof, u8 *addn_status);
int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc, 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, int be_cmd_enable_magic_wol(struct be_adapter *adapter, u8 *mac,
struct be_dma_mem *nonemb_cmd); struct be_dma_mem *nonemb_cmd);
int be_cmd_fw_init(struct be_adapter *adapter); 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, int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
u8 loopback_type, u8 enable); u8 loopback_type, u8 enable);
int be_cmd_get_phy_info(struct be_adapter *adapter); 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); void be_detect_error(struct be_adapter *adapter);
int be_cmd_get_die_temperature(struct be_adapter *adapter); int be_cmd_get_die_temperature(struct be_adapter *adapter);
int be_cmd_get_cntl_attributes(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_ACTIVE 10
#define OPTYPE_FCOE_FW_BACKUP 11 #define OPTYPE_FCOE_FW_BACKUP 11
#define OPTYPE_NCSI_FW 13 #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 OPTYPE_PHY_FW 99
#define TN_8022 13 #define TN_8022 13
#define ILLEGAL_IOCTL_REQ 2
#define FLASHROM_OPER_PHY_FLASH 9 #define FLASHROM_OPER_PHY_FLASH 9
#define FLASHROM_OPER_PHY_SAVE 10 #define FLASHROM_OPER_PHY_SAVE 10
#define FLASHROM_OPER_FLASH 1 #define FLASHROM_OPER_FLASH 1
@ -250,6 +254,9 @@
#define IMAGE_FIRMWARE_BACKUP_FCoE 178 #define IMAGE_FIRMWARE_BACKUP_FCoE 178
#define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179 #define IMAGE_FIRMWARE_BACKUP_COMP_FCoE 179
#define IMAGE_FIRMWARE_PHY 192 #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 #define IMAGE_BOOT_CODE 224
/************* Rx Packet Type Encoding **************/ /************* Rx Packet Type Encoding **************/
@ -534,7 +541,8 @@ struct flash_section_entry {
u32 image_size; u32 image_size;
u32 cksum; u32 cksum;
u32 entry_point; u32 entry_point;
u32 rsvd0; u16 optype;
u16 rsvd0;
u32 rsvd1; u32 rsvd1;
u8 ver_data[32]; u8 ver_data[32];
} __packed; } __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); status = be_cmd_vlan_config(adapter, adapter->if_handle, vids, num);
if (status) { if (status) {
/* Set to VLAN promisc mode as setting VLAN filter failed */ /* 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; goto set_vlan_promisc;
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Setting HW VLAN filtering failed.\n"); "Setting HW VLAN filtering failed.\n");
@ -1190,7 +1191,7 @@ ret:
static void be_clear_promisc(struct be_adapter *adapter) static void be_clear_promisc(struct be_adapter *adapter)
{ {
adapter->promiscuous = false; 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); 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 */ /* Enable multicast promisc if num configured exceeds what we support */
if (netdev->flags & IFF_ALLMULTI || if (netdev->flags & IFF_ALLMULTI ||
netdev_mc_count(netdev) > be_max_mc(adapter)) { netdev_mc_count(netdev) > be_max_mc(adapter))
be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON); goto set_mcast_promisc;
goto done;
}
if (netdev_uc_count(netdev) != adapter->uc_macs) { if (netdev_uc_count(netdev) != adapter->uc_macs) {
struct netdev_hw_addr *ha; 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); status = be_cmd_rx_filter(adapter, IFF_MULTICAST, ON);
if (!status) {
/* Set to MCAST promisc mode if setting MULTICAST address fails */ if (adapter->flags & BE_FLAGS_MCAST_PROMISC)
if (status) { adapter->flags &= ~BE_FLAGS_MCAST_PROMISC;
dev_info(&adapter->pdev->dev, goto done;
"Exhausted multicast HW filters.\n");
dev_info(&adapter->pdev->dev,
"Disabling HW multicast filtering.\n");
be_cmd_rx_filter(adapter, IFF_ALLMULTI, ON);
} }
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: done:
return; 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) int min_tx_rate, int max_tx_rate)
{ {
struct be_adapter *adapter = netdev_priv(netdev); 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)) if (!sriov_enabled(adapter))
return -EPERM; return -EPERM;
@ -1358,18 +1367,47 @@ static int be_set_vf_tx_rate(struct net_device *netdev, int vf,
if (min_tx_rate) if (min_tx_rate)
return -EINVAL; return -EINVAL;
if (max_tx_rate < 100 || max_tx_rate > 10000) { if (!max_tx_rate)
dev_err(&adapter->pdev->dev, goto config_qos;
"max tx rate must be between 100 and 10000 Mbps\n");
return -EINVAL; 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) if (status)
dev_err(&adapter->pdev->dev, goto err;
"max tx rate %d on VF %d failed\n", max_tx_rate, vf);
else adapter->vf_cfg[vf].tx_rate = max_tx_rate;
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; return status;
} }
static int be_set_vf_link_state(struct net_device *netdev, int vf, 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; struct be_vf_cfg *vf_cfg;
int status, old_vfs, vf; int status, old_vfs, vf;
u32 privileges; u32 privileges;
u16 lnk_speed;
old_vfs = pci_num_vf(adapter->pdev); old_vfs = pci_num_vf(adapter->pdev);
if (old_vfs) { if (old_vfs) {
@ -3186,16 +3223,9 @@ static int be_vf_setup(struct be_adapter *adapter)
vf); vf);
} }
/* BE3 FW, by default, caps VF TX-rate to 100mbps. /* Allow full available bandwidth */
* Allow full available bandwidth if (!old_vfs)
*/ be_cmd_config_qos(adapter, 0, 0, vf + 1);
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;
if (!old_vfs) { if (!old_vfs) {
be_cmd_enable_vf(adapter, vf + 1); be_cmd_enable_vf(adapter, vf + 1);
@ -3601,34 +3631,7 @@ static void be_netpoll(struct net_device *netdev)
} }
#endif #endif
#define FW_FILE_HDR_SIGN "ServerEngines Corp. " static char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "};
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 bool phy_flashing_required(struct be_adapter *adapter) 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; 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, static int be_flash(struct be_adapter *adapter, const u8 *img,
struct be_dma_mem *flash_cmd, int optype, int img_size) 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; struct be_cmd_write_flashrom *req = flash_cmd->va;
u32 total_bytes, flash_op, num_bytes;
int status;
total_bytes = img_size; total_bytes = img_size;
while (total_bytes) { while (total_bytes) {
@ -3704,14 +3730,11 @@ static int be_flash(struct be_adapter *adapter, const u8 *img,
img += num_bytes; img += num_bytes;
status = be_cmd_write_flashrom(adapter, flash_cmd, optype, status = be_cmd_write_flashrom(adapter, flash_cmd, optype,
flash_op, num_bytes); flash_op, num_bytes);
if (status) { if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
if (status == ILLEGAL_IOCTL_REQ && optype == OPTYPE_PHY_FW)
optype == OPTYPE_PHY_FW) break;
break; else if (status)
dev_err(&adapter->pdev->dev,
"cmd to write to flash rom failed.\n");
return status; return status;
}
} }
return 0; return 0;
} }
@ -3721,12 +3744,13 @@ static int be_flash_BEx(struct be_adapter *adapter,
const struct firmware *fw, const struct firmware *fw,
struct be_dma_mem *flash_cmd, int num_of_images) 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)); int img_hdrs_size = (num_of_images * sizeof(struct image_hdr));
const u8 *p = fw->data; struct device *dev = &adapter->pdev->dev;
const struct flash_comp *pflashcomp;
int num_comp, redboot;
struct flash_section_info *fsec = NULL; 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[] = { struct flash_comp gen3_flash_types[] = {
{ FLASH_iSCSI_PRIMARY_IMAGE_START_g3, OPTYPE_ISCSI_ACTIVE, { 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*/ /* Get flash section info*/
fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
if (!fsec) { if (!fsec) {
dev_err(&adapter->pdev->dev, dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
"Invalid Cookie. UFI corrupted ?\n");
return -1; return -1;
} }
for (i = 0; i < num_comp; i++) { for (i = 0; i < num_comp; i++) {
@ -3800,25 +3823,32 @@ static int be_flash_BEx(struct be_adapter *adapter,
continue; continue;
if (pflashcomp[i].optype == OPTYPE_REDBOOT) { if (pflashcomp[i].optype == OPTYPE_REDBOOT) {
redboot = be_flash_redboot(adapter, fw->data, status = be_check_flash_crc(adapter, fw->data,
pflashcomp[i].offset, pflashcomp[i].offset,
pflashcomp[i].size, pflashcomp[i].size,
filehdr_size + filehdr_size +
img_hdrs_size); img_hdrs_size,
if (!redboot) 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; continue;
} }
p = fw->data; p = fw->data + filehdr_size + pflashcomp[i].offset +
p += filehdr_size + pflashcomp[i].offset + img_hdrs_size; img_hdrs_size;
if (p + pflashcomp[i].size > fw->data + fw->size) if (p + pflashcomp[i].size > fw->data + fw->size)
return -1; return -1;
status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype, status = be_flash(adapter, p, flash_cmd, pflashcomp[i].optype,
pflashcomp[i].size); pflashcomp[i].size);
if (status) { if (status) {
dev_err(&adapter->pdev->dev, dev_err(dev, "Flashing section type 0x%x failed\n",
"Flashing section type %d failed.\n",
pflashcomp[i].img_type); pflashcomp[i].img_type);
return status; return status;
} }
@ -3826,74 +3856,135 @@ static int be_flash_BEx(struct be_adapter *adapter,
return 0; 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, static int be_flash_skyhawk(struct be_adapter *adapter,
const struct firmware *fw, const struct firmware *fw,
struct be_dma_mem *flash_cmd, int num_of_images) 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); 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; 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); filehdr_size = sizeof(struct flash_file_hdr_g3);
fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw); fsec = get_fsec_info(adapter, filehdr_size + img_hdrs_size, fw);
if (!fsec) { if (!fsec) {
dev_err(&adapter->pdev->dev, dev_err(dev, "Invalid Cookie. FW image may be corrupted\n");
"Invalid Cookie. UFI corrupted ?\n");
return -1; return -1;
} }
for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) { for (i = 0; i < le32_to_cpu(fsec->fsec_hdr.num_images); i++) {
img_offset = le32_to_cpu(fsec->fsec_entry[i].offset); img_offset = le32_to_cpu(fsec->fsec_entry[i].offset);
img_size = le32_to_cpu(fsec->fsec_entry[i].pad_size); 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)) { if (img_optype == 0xFFFF)
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; 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) { if (crc_match)
redboot = be_flash_redboot(adapter, fw->data, continue;
img_offset, img_size,
filehdr_size +
img_hdrs_size);
if (!redboot)
continue;
}
p = fw->data; flash:
p += filehdr_size + img_offset + img_hdrs_size; p = fw->data + filehdr_size + img_offset + img_hdrs_size;
if (p + img_size > fw->data + fw->size) if (p + img_size > fw->data + fw->size)
return -1; return -1;
status = be_flash(adapter, p, flash_cmd, img_optype, img_size); status = be_flash(adapter, p, flash_cmd, img_optype, img_size);
if (status) { /* For old FW images ignore ILLEGAL_FIELD error or errors on
dev_err(&adapter->pdev->dev, * UFI_DIR region
"Flashing section type %d failed.\n", */
fsec->fsec_entry[i].type); if (old_fw_img &&
return status; (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; return 0;