From patchwork Thu Mar 7 03:02:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nithin Sujir X-Patchwork-Id: 225719 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 8E6F02C0383 for ; Thu, 7 Mar 2013 14:03:44 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756043Ab3CGDD2 (ORCPT ); Wed, 6 Mar 2013 22:03:28 -0500 Received: from mms1.broadcom.com ([216.31.210.17]:4284 "EHLO mms1.broadcom.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753882Ab3CGDDR (ORCPT ); Wed, 6 Mar 2013 22:03:17 -0500 Received: from [10.9.208.57] by mms1.broadcom.com with ESMTP (Broadcom SMTP Relay (Email Firewall v6.5)); Wed, 06 Mar 2013 19:01:01 -0800 X-Server-Uuid: 06151B78-6688-425E-9DE2-57CB27892261 Received: from IRVEXCHSMTP1.corp.ad.broadcom.com (10.9.207.51) by IRVEXCHCAS08.corp.ad.broadcom.com (10.9.208.57) with Microsoft SMTP Server (TLS) id 14.1.438.0; Wed, 6 Mar 2013 19:03:07 -0800 Received: from mail-irva-13.broadcom.com (10.10.10.20) by IRVEXCHSMTP1.corp.ad.broadcom.com (10.9.207.51) with Microsoft SMTP Server id 14.1.438.0; Wed, 6 Mar 2013 19:03:07 -0800 Received: from dl1.broadcom.com (dhcp-10-13-111-115.broadcom.com [10.13.111.115]) by mail-irva-13.broadcom.com (Postfix) with ESMTP id 319D740FE9; Wed, 6 Mar 2013 19:03:07 -0800 (PST) From: "Nithin Nayak Sujir" To: davem@davemloft.net cc: netdev@vger.kernel.org, "Nithin Nayak Sujir" , "Michael Chan" Subject: [PATCH net-next 5/6] tg3: Enhance firmware download code to support fragmented firmware Date: Wed, 6 Mar 2013 19:02:33 -0800 Message-ID: <1362625354-15095-6-git-send-email-nsujir@broadcom.com> X-Mailer: git-send-email 1.8.1.4 In-Reply-To: <1362625354-15095-1-git-send-email-nsujir@broadcom.com> References: <1362625354-15095-1-git-send-email-nsujir@broadcom.com> MIME-Version: 1.0 X-WSS-ID: 7D26DD6723C8188637-01-01 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This lays the ground work to download the 57766 fragmented firmware. We loop until we've written data equal to tp->fw->size minus headers. Reviewed-by: Benjamin Li Signed-off-by: Nithin Nayak Sujir Signed-off-by: Michael Chan --- drivers/net/ethernet/broadcom/tg3.c | 48 ++++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 87bd0e3..54f604b 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -3536,6 +3536,33 @@ static int tg3_halt_cpu(struct tg3 *tp, u32 cpu_base) return 0; } +static int tg3_fw_data_len(struct tg3 *tp, + const struct tg3_firmware_hdr *fw_hdr) +{ + int fw_len; + + /* Non fragmented firmware have one firmware header followed by a + * contiguous chunk of data to be written. The length field in that + * header is not the length of data to be written but the complete + * length of the bss. The data length is determined based on + * tp->fw->size minus headers. + * + * Fragmented firmware have a main header followed by multiple + * fragments. Each fragment is identical to non fragmented firmware + * with a firmware header followed by a contiguous chunk of data. In + * the main header, the length field is unused and set to 0xffffffff. + * In each fragment header the length is the entire size of that + * fragment i.e. fragment data + header length. Data length is + * therefore length field in the header minus TG3_FW_HDR_LEN. + */ + if (tp->fw_len == 0xffffffff) + fw_len = be32_to_cpu(fw_hdr->len); + else + fw_len = tp->fw->size; + + return (fw_len - TG3_FW_HDR_LEN) / sizeof(u32); +} + /* tp->lock is held. */ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, u32 cpu_scratch_base, int cpu_scratch_size, @@ -3543,7 +3570,7 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, { int err, lock_err, i; void (*write_op)(struct tg3 *, u32, u32); - u32 *fw_data = (u32 *)(fw_hdr + 1); + int total_len = tp->fw->size; if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) { netdev_err(tp->dev, @@ -3571,12 +3598,21 @@ static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base, write_op(tp, cpu_scratch_base + i, 0); tw32(cpu_base + CPU_STATE, 0xffffffff); tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT); - for (i = 0; i < (tp->fw->size - TG3_FW_HDR_LEN) / sizeof(u32); i++) - write_op(tp, cpu_scratch_base + - (be32_to_cpu(fw_hdr->base_addr) & 0xffff) + - (i * sizeof(u32)), - be32_to_cpu(fw_data[i])); + do { + u32 *fw_data = (u32 *)(fw_hdr + 1); + for (i = 0; i < tg3_fw_data_len(tp, fw_hdr); i++) + write_op(tp, cpu_scratch_base + + (be32_to_cpu(fw_hdr->base_addr) & 0xffff) + + (i * sizeof(u32)), + be32_to_cpu(fw_data[i])); + + total_len -= be32_to_cpu(fw_hdr->len); + + /* Advance to next fragment */ + fw_hdr = (struct tg3_firmware_hdr *) + ((void *)fw_hdr + be32_to_cpu(fw_hdr->len)); + } while (total_len > 0); err = 0;