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:
Коммит
078252e0e8
|
@ -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)
|
||||
|
|
|
@ -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)) {
|
||||
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;
|
||||
adapter->drv_stats.be_on_die_temperature =
|
||||
resp->on_die_temperature;
|
||||
}
|
||||
} else {
|
||||
if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
|
||||
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,25 +293,20 @@ 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);
|
||||
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);
|
||||
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);
|
||||
be_async_grp5_pvid_state_process(adapter, compl);
|
||||
break;
|
||||
default:
|
||||
dev_warn(&adapter->pdev->dev, "Unknown grp5 event 0x%x!\n",
|
||||
|
@ -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) ==
|
||||
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,18 +405,10 @@ 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);
|
||||
|
@ -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;
|
||||
u32 bw_percent;
|
||||
u16 version = 0;
|
||||
|
||||
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);
|
||||
nic_desc.bw_max = cpu_to_le32(max_rate / 10);
|
||||
} else {
|
||||
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,
|
||||
RESOURCE_DESC_SIZE_V0,
|
||||
0, domain);
|
||||
} else {
|
||||
return be_cmd_set_qos(adapter, bps, domain);
|
||||
}
|
||||
nic_desc.hdr.desc_len,
|
||||
version, domain);
|
||||
}
|
||||
|
||||
int be_cmd_manage_iface(struct be_adapter *adapter, u32 iface, u8 op)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
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,35 +3631,8 @@ 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 bool phy_flashing_required(struct be_adapter *adapter)
|
||||
{
|
||||
return (adapter->phy.phy_type == TN_8022 &&
|
||||
|
@ -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,15 +3730,12 @@ 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 &&
|
||||
if (base_status(status) == MCC_STATUS_ILLEGAL_REQUEST &&
|
||||
optype == OPTYPE_PHY_FW)
|
||||
break;
|
||||
dev_err(&adapter->pdev->dev,
|
||||
"cmd to write to flash rom failed.\n");
|
||||
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,
|
||||
status = be_check_flash_crc(adapter, fw->data,
|
||||
pflashcomp[i].offset,
|
||||
pflashcomp[i].size,
|
||||
filehdr_size +
|
||||
img_hdrs_size);
|
||||
if (!redboot)
|
||||
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;
|
||||
}
|
||||
|
||||
p = fw->data;
|
||||
p += filehdr_size + pflashcomp[i].offset + img_hdrs_size;
|
||||
if (crc_match)
|
||||
continue;
|
||||
}
|
||||
|
||||
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,29 +3856,15 @@ static int be_flash_BEx(struct be_adapter *adapter,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int be_flash_skyhawk(struct be_adapter *adapter,
|
||||
const struct firmware *fw,
|
||||
struct be_dma_mem *flash_cmd, int num_of_images)
|
||||
static u16 be_get_img_optype(struct flash_section_entry fsec_entry)
|
||||
{
|
||||
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;
|
||||
u32 img_type = le32_to_cpu(fsec_entry.type);
|
||||
u16 img_optype = le16_to_cpu(fsec_entry.optype);
|
||||
|
||||
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;
|
||||
}
|
||||
if (img_optype != 0xFFFF)
|
||||
return img_optype;
|
||||
|
||||
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)) {
|
||||
switch (img_type) {
|
||||
case IMAGE_FIRMWARE_iSCSI:
|
||||
img_optype = OPTYPE_ISCSI_ACTIVE;
|
||||
break;
|
||||
|
@ -3870,30 +3886,105 @@ static int be_flash_skyhawk(struct be_adapter *adapter,
|
|||
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:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (img_optype == OPTYPE_REDBOOT) {
|
||||
redboot = be_flash_redboot(adapter, fw->data,
|
||||
img_offset, img_size,
|
||||
filehdr_size +
|
||||
img_hdrs_size);
|
||||
if (!redboot)
|
||||
continue;
|
||||
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 img_hdrs_size = num_of_images * sizeof(struct image_hdr);
|
||||
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(dev, "Invalid Cookie. FW image may be corrupted\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = fw->data;
|
||||
p += filehdr_size + img_offset + img_hdrs_size;
|
||||
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;
|
||||
|
||||
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 (crc_match)
|
||||
continue;
|
||||
|
||||
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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче