[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20090702111820.GA21085@serverengines.com>
Date: Thu, 2 Jul 2009 16:48:40 +0530
From: Sarveshwar Bandi <sarveshwarb@...verengines.com>
To: netdev@...r.kernel.org
Cc: davem@...emloft.net
Subject: [PATCH] be2net: Implementation of request_firmware interface.
Please review and apply patch to net-next tree. Patch implements the
request_firmware interface.
- Sarvesh
Signed-off-by: Sarveshwar Bandi <sarveshwarb@...verengines.com>
---
drivers/net/benet/be.h | 1
drivers/net/benet/be_cmds.c | 28 ++++
drivers/net/benet/be_cmds.h | 18 +++
drivers/net/benet/be_hw.h | 89 ++++++++++++++
drivers/net/benet/be_main.c | 271 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 407 insertions(+), 0 deletions(-)
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index f703758..4f9ae46 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -29,6 +29,7 @@ #include <linux/if_vlan.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>
#include <linux/inet_lro.h>
+#include <linux/firmware.h>
#include "be_hw.h"
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 583517e..acb3115 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -1061,3 +1061,31 @@ int be_cmd_query_fw_cfg(struct be_ctrl_i
spin_unlock(&ctrl->mbox_lock);
return status;
}
+
+int be_cmd_write_flashrom(struct be_ctrl_info *ctrl, struct be_dma_mem *cmd,
+ u32 flash_type, u32 flash_opcode, u32 buf_size)
+{
+ struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem);
+ struct be_cmd_write_flashrom *req = cmd->va;
+ struct be_sge *sge = nonembedded_sgl(wrb);
+ int status;
+
+ spin_lock(&ctrl->mbox_lock);
+ memset(wrb, 0, sizeof(*wrb));
+ be_wrb_hdr_prepare(wrb, cmd->size, false, 1);
+
+ be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+ OPCODE_COMMON_WRITE_FLASHROM, cmd->size);
+ sge->pa_hi = cpu_to_le32(upper_32_bits(cmd->dma));
+ sge->pa_lo = cpu_to_le32(cmd->dma & 0xFFFFFFFF);
+ sge->len = cpu_to_le32(cmd->size);
+
+ req->params.op_type = cpu_to_le32(flash_type);
+ req->params.op_code = cpu_to_le32(flash_opcode);
+ req->params.data_buf_size = cpu_to_le32(buf_size);
+
+ status = be_mbox_db_ring(ctrl);
+
+ spin_unlock(&ctrl->mbox_lock);
+ return status;
+}
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index 747626d..e2b8479 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -117,6 +117,7 @@ #define OPCODE_COMMON_NTWK_MAC_SET 2
#define OPCODE_COMMON_NTWK_MULTICAST_SET 3
#define OPCODE_COMMON_NTWK_VLAN_CONFIG 4
#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5
+#define OPCODE_COMMON_WRITE_FLASHROM 7
#define OPCODE_COMMON_CQ_CREATE 12
#define OPCODE_COMMON_EQ_CREATE 13
#define OPCODE_COMMON_MCC_CREATE 21
@@ -697,6 +698,20 @@ struct be_cmd_resp_query_fw_cfg {
u32 rsvd[26];
};
+/****************** Firmware Flash ******************/
+struct flashrom_params {
+ u32 op_code;
+ u32 op_type;
+ u32 data_buf_size;
+ u32 offset;
+ u8 data_buf[4];
+};
+
+struct be_cmd_write_flashrom {
+ struct be_cmd_req_hdr hdr;
+ struct flashrom_params params;
+};
+
extern int be_pci_fnum_get(struct be_ctrl_info *ctrl);
extern int be_cmd_POST(struct be_ctrl_info *ctrl);
extern int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr,
@@ -745,4 +760,7 @@ extern int be_cmd_set_flow_control(struc
extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl,
u32 *tx_fc, u32 *rx_fc);
extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num);
+extern int be_cmd_write_flashrom(struct be_ctrl_info *ctrl,
+ struct be_dma_mem *cmd, u32 flash_oper,
+ u32 flash_opcode, u32 buf_size);
extern void be_process_mcc(struct be_ctrl_info *ctrl);
diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h
index b02e805..6035f1b 100644
--- a/drivers/net/benet/be_hw.h
+++ b/drivers/net/benet/be_hw.h
@@ -55,6 +55,28 @@ #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MA
#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */
#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26
+/********* Soft Reset registers ***********/
+#define PCICFG_SOFT_RESET_CSR_OFFSET 0x5c
+#define PCICFG_SOFT_RESET_MASK (1 << 7) /* bit 7 */
+
+#define PCICFG_ONLINE0_CSR_OFFSET 0xb0
+#define PCICFG_ONLINE1_CSR_OFFSET 0xb4
+#define PCICFG_MPU_IRAM_ONLINE_MASK (1 << 3) /* bit 3 */
+
+#define PCICFG_UE_STATUS_LOW_MASK_OFFSET 0xa8
+#define PCICFG_UE_STATUS_HIGH_MASK_OFFSET 0xac
+
+#define MPU_EP_CONTROL_CSR_OFFSET 0x0
+#define MPU_EP_CONTROL_CPU_RESET_MASK (1 << 31) /* bit 31 */
+
+/********* POST Descriptors ***************/
+#define MPU_EP_SEMAPHORE_OFFSET 0xac
+#define MPU_POST_ERR_MASK (1 << 31) /* bit 31 */
+#define MPU_POST_STAGE_MASK 0xFFFF /* bits 0 - 15 */
+#define MPU_POST_STAGE_ARMFW_RDY 0xc000
+#define MPU_POST_STAGE_AWAIT_HOST_RDY 0x1
+#define MPU_POST_STAGE_HOST_RDY 0x2
+
/********* Event Q door bell *************/
#define DB_EQ_OFFSET DB_CQ_OFFSET
#define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */
@@ -215,3 +237,70 @@ struct amap_eth_rx_compl {
struct be_eth_rx_compl {
u32 dw[4];
};
+
+/* Flashrom related descriptors */
+#define IMAGE_TYPE_FIRMWARE 160
+#define IMAGE_TYPE_BOOTCODE 224
+#define IMAGE_TYPE_OPTIONROM 32
+
+#define NUM_FLASHDIR_ENTRIES 32
+
+#define FLASHROM_TYPE_FIRMWARE 0
+#define FLASHROM_TYPE_REDBOOT 1
+#define FLASHROM_TYPE_BIOS 2
+
+#define FLASHROM_OPER_FLASH 1
+#define FLASHROM_OPER_SAVE 2
+
+struct controller_id {
+ u32 vendor;
+ u32 device;
+ u32 subvendor;
+ u32 subdevice;
+};
+
+struct flash_file_hdr {
+ u8 sign[32];
+ u32 cksum;
+ u32 antidote;
+ struct controller_id cont_id;
+ u32 file_len;
+ u32 chunk_num;
+ u32 total_chunks;
+ u32 num_imgs;
+ u8 build[24];
+};
+
+struct flash_section_hdr {
+ u32 format_rev;
+ u32 cksum;
+ u32 antidote;
+ u32 build_no;
+ u8 id_string[64];
+ u32 active_entry_mask;
+ u32 valid_entry_mask;
+ u32 org_content_mask;
+ u32 rsvd0;
+ u32 rsvd1;
+ u32 rsvd2;
+ u32 rsvd3;
+ u32 rsvd4;
+};
+
+struct flash_section_entry {
+ u32 type;
+ u32 offset;
+ u32 pad_size;
+ u32 image_size;
+ u32 cksum;
+ u32 entry_point;
+ u32 rsvd0;
+ u32 rsvd1;
+ u8 ver_data[32];
+};
+
+struct flash_section_info {
+ u8 cookie[32];
+ struct flash_section_hdr fsec_hdr;
+ struct flash_section_entry fsec_entry[32];
+};
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 66c10c8..fd9f3b5 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1635,6 +1635,273 @@ static int be_close(struct net_device *n
return 0;
}
+#define FW_FILE_HDR_SIGN "ServerEngines Corp. "
+char flash_cookie[2][16] = {"*** SE FLAS",
+ "H DIRECTORY *** "};
+static int be_flash_image(struct be_adapter *adapter,
+ const struct firmware *fw,
+ struct flash_section_info *fsec,
+ struct be_dma_mem *flash_cmd, u32 flash_type)
+{
+ int status;
+ u32 flash_op, image_type = 0, total_bytes;
+ int num_bytes, i;
+ const u8 *p = fw->data;
+ struct flash_section_entry *fsec_entry = NULL;
+ struct be_cmd_write_flashrom *req = flash_cmd->va;
+
+ switch (flash_type) {
+ case FLASHROM_TYPE_FIRMWARE:
+ image_type = IMAGE_TYPE_FIRMWARE;
+ break;
+ case FLASHROM_TYPE_BIOS:
+ image_type = IMAGE_TYPE_OPTIONROM;
+ break;
+ case FLASHROM_TYPE_REDBOOT:
+ image_type = IMAGE_TYPE_BOOTCODE;
+ break;
+ }
+
+ for (i = 0; i < NUM_FLASHDIR_ENTRIES; i++) {
+ if ((fsec->fsec_entry[i].type == image_type) &&
+ (fsec->fsec_hdr.active_entry_mask & (1<<i)) &&
+ (fsec->fsec_hdr.valid_entry_mask & (1<<i))) {
+ fsec_entry = &fsec->fsec_entry[i];
+ break;
+ }
+ }
+
+ if (!fsec_entry) {
+ dev_err(&adapter->pdev->dev,
+ "Section missing in firmware image\n");
+ return -1;
+ }
+
+ p += sizeof(struct flash_file_hdr) + fsec_entry->offset;
+ if (p + fsec_entry->image_size > fw->data + fw->size)
+ return -1;
+
+ total_bytes = fsec_entry->image_size;
+ if (total_bytes%256)
+ total_bytes = (256 - total_bytes%256) + total_bytes;
+
+ while (total_bytes) {
+ if (total_bytes > 32*1024)
+ num_bytes = 32*1024;
+ else
+ num_bytes = total_bytes;
+ total_bytes -= num_bytes;
+
+ if (!total_bytes)
+ flash_op = FLASHROM_OPER_FLASH;
+ else
+ flash_op = FLASHROM_OPER_SAVE;
+ memcpy(req->params.data_buf, p, num_bytes);
+ p += num_bytes;
+ status = be_cmd_write_flashrom(&adapter->ctrl, flash_cmd,
+ flash_type, flash_op, num_bytes);
+ if (status)
+ return -1;
+ yield();
+ }
+
+ return 0;
+}
+
+static int be_wait_for_post_cmpl(struct be_ctrl_info *ctrl)
+{
+ u32 post_err, post_stage, reg;
+ int status = 0, i = 0;
+
+ do {
+ reg = ioread32(ctrl->csr + MPU_EP_SEMAPHORE_OFFSET);
+ post_err = reg & MPU_POST_ERR_MASK;
+ post_stage = reg & MPU_POST_STAGE_MASK;
+ yield();
+ udelay(1000);
+
+ } while (!post_err &&
+ (post_stage != MPU_POST_STAGE_ARMFW_RDY) &&
+ (i++ < 60000));
+
+ if (post_err || (post_stage != MPU_POST_STAGE_ARMFW_RDY))
+ status = -1;
+
+ return status;
+}
+
+static int be_pci_soft_reset(struct be_ctrl_info *ctrl)
+{
+ u8 __iomem *addr;
+ u32 soft_reset, val;
+ int i = 0;
+
+ addr = ctrl->pcicfg + PCICFG_SOFT_RESET_CSR_OFFSET;
+ val = ioread32(addr);
+ val |= PCICFG_SOFT_RESET_MASK;
+ iowrite32(val, addr);
+
+ /* Wait till soft reset is deasserted */
+ do {
+ udelay(50);
+ val = ioread32(addr);
+ soft_reset = val & PCICFG_SOFT_RESET_MASK;
+ } while (soft_reset && (i++ < 1024));
+
+ if (soft_reset)
+ return -1;
+
+ /* Mask all UEs */
+ val = 0xffffffff;
+ addr = ctrl->pcicfg + PCICFG_UE_STATUS_LOW_MASK_OFFSET;
+ iowrite32(val, addr);
+
+ addr = ctrl->pcicfg + PCICFG_UE_STATUS_HIGH_MASK_OFFSET;
+ iowrite32(val, addr);
+
+ /* Take everyone offline except mpu iram */
+ val = 0;
+ addr = ctrl->pcicfg + PCICFG_ONLINE0_CSR_OFFSET;
+ iowrite32(val, addr);
+
+ val = PCICFG_MPU_IRAM_ONLINE_MASK;
+ addr = ctrl->pcicfg + PCICFG_ONLINE1_CSR_OFFSET;
+ iowrite32(val, addr);
+
+ udelay(20000);
+
+ /* Soft Again*/
+ addr = ctrl->pcicfg + PCICFG_SOFT_RESET_CSR_OFFSET;
+ val = ioread32(addr);
+ val |= PCICFG_SOFT_RESET_MASK;
+
+ iowrite32(val, addr);
+
+ i = 0;
+ do {
+ udelay(50);
+ val = ioread32(addr);
+ soft_reset = val & PCICFG_SOFT_RESET_MASK;
+ } while (soft_reset && (i++ < 1024));
+
+ if (soft_reset)
+ return -1;
+
+ udelay(20000);
+
+ /* Take mpu out of reset*/
+ addr = ctrl->csr + MPU_EP_CONTROL_CSR_OFFSET;
+ val = ioread32(addr);
+ val &= ~MPU_EP_CONTROL_CPU_RESET_MASK;
+
+ iowrite32(val, addr);
+
+ if (be_wait_for_post_cmpl(ctrl))
+ return -1;
+
+ return 0;
+}
+
+int be_load_fw(struct be_adapter *adapter)
+{
+ char fw_file[64];
+ const struct firmware *fw;
+ struct flash_file_hdr *fhdr;
+ struct flash_section_info *fsec = NULL;
+ struct be_dma_mem flash_cmd;
+ int status;
+ const u8 *p;
+ bool entry_found = false;
+ int flash_type;
+ char fw_ver[FW_VER_LEN];
+ char fw_cfg;
+
+ status = be_cmd_get_fw_ver(&adapter->ctrl, fw_ver);
+ if (status)
+ return status;
+
+ fw_cfg = *(fw_ver + 2);
+ if (fw_cfg == '0')
+ fw_cfg = '1';
+ sprintf(fw_file, "be2-cna%c-fw.ufi", fw_cfg);
+
+ if (request_firmware(&fw, fw_file, &adapter->pdev->dev))
+ goto fw_exit;
+
+ p = fw->data;
+ fhdr = (struct flash_file_hdr *) p;
+ if (memcmp(fhdr->sign, FW_FILE_HDR_SIGN, strlen(FW_FILE_HDR_SIGN))) {
+ dev_err(&adapter->pdev->dev,
+ "Firmware(%s) load error (signature did not match)\n",
+ fw_file);
+ status = -1;
+ goto fw_exit;
+ }
+
+ /* fw ver on board matches */
+ if (!strncmp(fhdr->sign + strlen(FW_FILE_HDR_SIGN), fw_ver,
+ FW_VER_LEN))
+ goto fw_exit;
+
+ dev_info(&adapter->pdev->dev,
+ "Flashing firmware file %s\n", fw_file);
+
+ p += sizeof(struct flash_file_hdr);
+ while (p < (fw->data + fw->size)) {
+ fsec = (struct flash_section_info *)p;
+ if (!memcmp(flash_cookie, fsec->cookie, sizeof(flash_cookie))) {
+ entry_found = true;
+ break;
+ }
+ p += 32;
+ }
+
+ if (!entry_found) {
+ status = -1;
+ dev_err(&adapter->pdev->dev,
+ "Flash cookie not found in firmware image\n");
+ goto fw_exit;
+ }
+
+ flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
+ flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size,
+ &flash_cmd.dma);
+ if (!flash_cmd.va) {
+ status = -ENOMEM;
+ dev_err(&adapter->pdev->dev,
+ "Memory allocation failure while flashing\n");
+ goto fw_exit;
+ }
+
+ for (flash_type = FLASHROM_TYPE_FIRMWARE;
+ flash_type <= FLASHROM_TYPE_BIOS; flash_type++) {
+ status = be_flash_image(adapter, fw, fsec, &flash_cmd,
+ flash_type);
+ if (status)
+ break;
+ }
+
+ pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va,
+ flash_cmd.dma);
+ if (status) {
+ dev_err(&adapter->pdev->dev, "Firmware load error\n");
+ goto fw_exit;
+ }
+
+ if (be_pci_soft_reset(&adapter->ctrl)) {
+ dev_err(&adapter->pdev->dev,
+ "Chip reset after load new firmware failed\n");
+ status = -1;
+ }
+
+ if (!status && !be_cmd_get_fw_ver(&adapter->ctrl, fw_ver))
+ dev_info(&adapter->pdev->dev,
+ "Firmware(ver: %s) flashed succesfully\n", fw_ver);
+fw_exit:
+ release_firmware(fw);
+ return status;
+}
+
static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
void **ip_hdr, void **tcpudp_hdr,
u64 *hdr_flags, void *priv)
@@ -1926,6 +2193,10 @@ static int __devinit be_probe(struct pci
if (status)
goto free_netdev;
+ status = be_load_fw(adapter);
+ if (status)
+ goto ctrl_clean;
+
status = be_stats_init(adapter);
if (status)
goto ctrl_clean;
--
1.4.0
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists