Skip to content

Commit

Permalink
tg3: Enhance firmware download code to support fragmented firmware
Browse files Browse the repository at this point in the history
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 <benli@broadcom.com>
Signed-off-by: Nithin Nayak Sujir <nsujir@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Nithin Sujir authored and David S. Miller committed Mar 7, 2013
1 parent 77997ea commit 31f11a9
Showing 1 changed file with 42 additions and 6 deletions.
48 changes: 42 additions & 6 deletions drivers/net/ethernet/broadcom/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -3536,14 +3536,41 @@ 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,
const struct tg3_firmware_hdr *fw_hdr)
{
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,
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 31f11a9

Please sign in to comment.