From: Michal Schmidt <mschmidt@redhat.com> Date: Fri, 3 Sep 2010 16:44:38 -0400 Subject: [net] bnx2x: load firmware in open instead of probe Message-id: <20100903164438.25415.55433.stgit@brian.englab.brq.redhat.com> Patchwork-id: 28115 O-Subject: [RHEL5.6 BZ572012 PATCH 41/46] bnx2x: Load firmware in open() instead of probe() Bugzilla: 572012 RH-Acked-by: David S. Miller <davem@redhat.com> RH-Acked-by: Stanislaw Gruszka <sgruszka@redhat.com> Loading firmware when actually bringing eth device up. This also will allow driver to be insmoded when filesystem with firmware files is not available yet. Suggested by Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net> (cherry picked from commit 6891dd25d3f82e50979b27fde1980aa96320b975) RHEL: we're not loading the firmware from the filesystem. Conflicts: drivers/net/bnx2x/bnx2x_cmn.c drivers/net/bnx2x/bnx2x_main.c diff --git a/drivers/net/bnx2x/bnx2x_cmn.c b/drivers/net/bnx2x/bnx2x_cmn.c index 3679841..ae21df8 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.c +++ b/drivers/net/bnx2x/bnx2x_cmn.c @@ -1232,12 +1232,29 @@ static void bnx2x_alloc_napi(struct bnx2x *bp) } } +static void bnx2x_release_firmware(struct bnx2x *bp) +{ + kfree(bp->init_ops_offsets); + kfree(bp->init_ops); + kfree(bp->init_data); +#if 0 /* firmware is embedded in the RHEL kernel */ + release_firmware(bp->firmware); +#endif +} + /* must be called with rtnl_lock */ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) { u32 load_code; int i, rc; + /* Set init arrays */ + rc = bnx2x_init_firmware(bp); + if (rc) { + BNX2X_ERR("Error loading firmware\n"); + return rc; + } + #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) return -EPERM; @@ -1452,6 +1469,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) #endif bnx2x_inc_load_cnt(bp); + bnx2x_release_firmware(bp); + return 0; #ifdef BCM_CNIC @@ -1477,6 +1496,8 @@ load_error1: bnx2x_napi_disable(bp); bnx2x_free_mem(bp); + bnx2x_release_firmware(bp); + return rc; } diff --git a/drivers/net/bnx2x/bnx2x_cmn.h b/drivers/net/bnx2x/bnx2x_cmn.h index 377db39..2e75df7 100644 --- a/drivers/net/bnx2x/bnx2x_cmn.h +++ b/drivers/net/bnx2x/bnx2x_cmn.h @@ -115,6 +115,15 @@ void bnx2x_int_enable(struct bnx2x *bp); void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw); /** + * Loads device firmware + * + * @param bp + * + * @return int + */ +int bnx2x_init_firmware(struct bnx2x *bp); + +/** * Init HW blocks according to current initialization stage: * COMMON, PORT or FUNCTION. * diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 9b9ea84..9b97f22 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c @@ -7262,9 +7262,7 @@ static int bnx2x_request_firmware(const struct firmware **firmware_p, return 0; } -static inline void bnx2x_release_firmware(const struct firmware *fw) { } - -static int __devinit bnx2x_check_firmware(struct bnx2x *bp) +static int bnx2x_check_firmware(struct bnx2x *bp) { const struct firmware *firmware = bp->firmware; struct bnx2x_fw_file_hdr *fw_hdr; @@ -7375,7 +7373,7 @@ do { \ (u8 *)bp->arr, len); \ } while (0) -static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) +int bnx2x_init_firmware(struct bnx2x *bp) { char fw_file_name[40] = {0}; struct bnx2x_fw_file_hdr *fw_hdr; @@ -7387,7 +7385,7 @@ static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) else if (CHIP_IS_E1H(bp)) offset = sprintf(fw_file_name, FW_FILE_PREFIX_E1H); else { - dev_err(dev, "Unsupported chip revision\n"); + BNX2X_ERR("Unsupported chip revision\n"); return -EINVAL; } @@ -7397,17 +7395,17 @@ static int __devinit bnx2x_init_firmware(struct bnx2x *bp, struct device *dev) BCM_5710_FW_REVISION_VERSION, BCM_5710_FW_ENGINEERING_VERSION); - dev_info(dev, "Loading %s\n", fw_file_name); + BNX2X_DEV_INFO("Loading %s\n", fw_file_name); - rc = bnx2x_request_firmware(&bp->firmware, fw_file_name, dev); + rc = bnx2x_request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev); if (rc) { - dev_err(dev, "Can't load firmware file %s\n", fw_file_name); + BNX2X_ERR("Can't load firmware file %s\n", fw_file_name); goto request_firmware_exit; } rc = bnx2x_check_firmware(bp); if (rc) { - dev_err(dev, "Corrupt firmware file %s\n", fw_file_name); + BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name); goto request_firmware_exit; } @@ -7449,8 +7447,9 @@ init_offsets_alloc_err: init_ops_alloc_err: kfree(bp->init_data); request_firmware_exit: - bnx2x_release_firmware(bp->firmware); - +#if 0 /* not in RHEL */ + release_firmware(bp->firmware); +#endif return rc; } @@ -7502,13 +7501,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, if (rc) goto init_one_exit; - /* Set init arrays */ - rc = bnx2x_init_firmware(bp, &pdev->dev); - if (rc) { - dev_err(&pdev->dev, "Error loading firmware\n"); - goto init_one_exit; - } - rc = register_netdev(dev); if (rc) { dev_err(&pdev->dev, "Cannot register net device\n"); @@ -7566,11 +7558,6 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) /* Make sure RESET task is not scheduled before continuing */ cancel_delayed_work_sync(&bp->reset_task); - kfree(bp->init_ops_offsets); - kfree(bp->init_ops); - kfree(bp->init_data); - bnx2x_release_firmware(bp->firmware); - if (bp->regview) iounmap(bp->regview);