Commit 3cf761dd authored by Kou Ishizaki's avatar Kou Ishizaki Committed by Jeff Garzik

spidernet: load firmware when open

This patch moves calling init_firmware() from spider_net_probe() to
spider_net_open() so as to use the driver by built-in.
Signed-off-by: default avatarKou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: default avatarLinas Vepstas <linas@austin.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent abdb66b5
...@@ -1704,6 +1704,124 @@ spider_net_enable_card(struct spider_net_card *card) ...@@ -1704,6 +1704,124 @@ spider_net_enable_card(struct spider_net_card *card)
SPIDER_NET_GDTBSTA); SPIDER_NET_GDTBSTA);
} }
/**
* spider_net_download_firmware - loads firmware into the adapter
* @card: card structure
* @firmware_ptr: pointer to firmware data
*
* spider_net_download_firmware loads the firmware data into the
* adapter. It assumes the length etc. to be allright.
*/
static int
spider_net_download_firmware(struct spider_net_card *card,
const void *firmware_ptr)
{
int sequencer, i;
const u32 *fw_ptr = firmware_ptr;
/* stop sequencers */
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_STOP_SEQ_VALUE);
for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
sequencer++) {
spider_net_write_reg(card,
SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, *fw_ptr);
fw_ptr++;
}
}
if (spider_net_read_reg(card, SPIDER_NET_GSINIT))
return -EIO;
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_RUN_SEQ_VALUE);
return 0;
}
/**
* spider_net_init_firmware - reads in firmware parts
* @card: card structure
*
* Returns 0 on success, <0 on failure
*
* spider_net_init_firmware opens the sequencer firmware and does some basic
* checks. This function opens and releases the firmware structure. A call
* to download the firmware is performed before the release.
*
* Firmware format
* ===============
* spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being
* the program for each sequencer. Use the command
* tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \
* Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \
* Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin
*
* to generate spider_fw.bin, if you have sequencer programs with something
* like the following contents for each sequencer:
* <ONE LINE COMMENT>
* <FIRST 4-BYTES-WORD FOR SEQUENCER>
* <SECOND 4-BYTES-WORD FOR SEQUENCER>
* ...
* <1024th 4-BYTES-WORD FOR SEQUENCER>
*/
static int
spider_net_init_firmware(struct spider_net_card *card)
{
struct firmware *firmware = NULL;
struct device_node *dn;
const u8 *fw_prop = NULL;
int err = -ENOENT;
int fw_size;
if (request_firmware((const struct firmware **)&firmware,
SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
pr_err("Incorrect size of spidernet firmware in " \
"filesystem. Looking in host firmware...\n");
goto try_host_fw;
}
err = spider_net_download_firmware(card, firmware->data);
release_firmware(firmware);
if (err)
goto try_host_fw;
goto done;
}
try_host_fw:
dn = pci_device_to_OF_node(card->pdev);
if (!dn)
goto out_err;
fw_prop = get_property(dn, "firmware", &fw_size);
if (!fw_prop)
goto out_err;
if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
pr_err("Incorrect size of spidernet firmware in " \
"host firmware\n");
goto done;
}
err = spider_net_download_firmware(card, fw_prop);
done:
return err;
out_err:
if (netif_msg_probe(card))
pr_err("Couldn't find spidernet firmware in filesystem " \
"or host firmware\n");
return err;
}
/** /**
* spider_net_open - called upon ifonfig up * spider_net_open - called upon ifonfig up
* @netdev: interface device structure * @netdev: interface device structure
...@@ -1719,6 +1837,10 @@ spider_net_open(struct net_device *netdev) ...@@ -1719,6 +1837,10 @@ spider_net_open(struct net_device *netdev)
struct spider_net_card *card = netdev_priv(netdev); struct spider_net_card *card = netdev_priv(netdev);
int result; int result;
result = spider_net_init_firmware(card);
if (result)
goto init_firmware_failed;
/* start probing with copper */ /* start probing with copper */
spider_net_setup_aneg(card); spider_net_setup_aneg(card);
if (card->phy.def->phy_id) if (card->phy.def->phy_id)
...@@ -1762,6 +1884,7 @@ spider_net_open(struct net_device *netdev) ...@@ -1762,6 +1884,7 @@ spider_net_open(struct net_device *netdev)
spider_net_free_chain(card, &card->tx_chain); spider_net_free_chain(card, &card->tx_chain);
alloc_tx_failed: alloc_tx_failed:
del_timer_sync(&card->aneg_timer); del_timer_sync(&card->aneg_timer);
init_firmware_failed:
return result; return result;
} }
...@@ -1872,124 +1995,6 @@ spider_net_setup_phy(struct spider_net_card *card) ...@@ -1872,124 +1995,6 @@ spider_net_setup_phy(struct spider_net_card *card)
return 0; return 0;
} }
/**
* spider_net_download_firmware - loads firmware into the adapter
* @card: card structure
* @firmware_ptr: pointer to firmware data
*
* spider_net_download_firmware loads the firmware data into the
* adapter. It assumes the length etc. to be allright.
*/
static int
spider_net_download_firmware(struct spider_net_card *card,
const void *firmware_ptr)
{
int sequencer, i;
const u32 *fw_ptr = firmware_ptr;
/* stop sequencers */
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_STOP_SEQ_VALUE);
for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;
sequencer++) {
spider_net_write_reg(card,
SPIDER_NET_GSnPRGADR + sequencer * 8, 0);
for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {
spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +
sequencer * 8, *fw_ptr);
fw_ptr++;
}
}
if (spider_net_read_reg(card, SPIDER_NET_GSINIT))
return -EIO;
spider_net_write_reg(card, SPIDER_NET_GSINIT,
SPIDER_NET_RUN_SEQ_VALUE);
return 0;
}
/**
* spider_net_init_firmware - reads in firmware parts
* @card: card structure
*
* Returns 0 on success, <0 on failure
*
* spider_net_init_firmware opens the sequencer firmware and does some basic
* checks. This function opens and releases the firmware structure. A call
* to download the firmware is performed before the release.
*
* Firmware format
* ===============
* spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being
* the program for each sequencer. Use the command
* tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \
* Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \
* Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin
*
* to generate spider_fw.bin, if you have sequencer programs with something
* like the following contents for each sequencer:
* <ONE LINE COMMENT>
* <FIRST 4-BYTES-WORD FOR SEQUENCER>
* <SECOND 4-BYTES-WORD FOR SEQUENCER>
* ...
* <1024th 4-BYTES-WORD FOR SEQUENCER>
*/
static int
spider_net_init_firmware(struct spider_net_card *card)
{
struct firmware *firmware = NULL;
struct device_node *dn;
const u8 *fw_prop = NULL;
int err = -ENOENT;
int fw_size;
if (request_firmware((const struct firmware **)&firmware,
SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {
if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
pr_err("Incorrect size of spidernet firmware in " \
"filesystem. Looking in host firmware...\n");
goto try_host_fw;
}
err = spider_net_download_firmware(card, firmware->data);
release_firmware(firmware);
if (err)
goto try_host_fw;
goto done;
}
try_host_fw:
dn = pci_device_to_OF_node(card->pdev);
if (!dn)
goto out_err;
fw_prop = get_property(dn, "firmware", &fw_size);
if (!fw_prop)
goto out_err;
if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&
netif_msg_probe(card) ) {
pr_err("Incorrect size of spidernet firmware in " \
"host firmware\n");
goto done;
}
err = spider_net_download_firmware(card, fw_prop);
done:
return err;
out_err:
if (netif_msg_probe(card))
pr_err("Couldn't find spidernet firmware in filesystem " \
"or host firmware\n");
return err;
}
/** /**
* spider_net_workaround_rxramfull - work around firmware bug * spider_net_workaround_rxramfull - work around firmware bug
* @card: card structure * @card: card structure
...@@ -2090,8 +2095,6 @@ spider_net_tx_timeout_task(struct work_struct *work) ...@@ -2090,8 +2095,6 @@ spider_net_tx_timeout_task(struct work_struct *work)
if (spider_net_setup_phy(card)) if (spider_net_setup_phy(card))
goto out; goto out;
if (spider_net_init_firmware(card))
goto out;
spider_net_open(netdev); spider_net_open(netdev);
spider_net_kick_tx_dma(card); spider_net_kick_tx_dma(card);
...@@ -2363,10 +2366,6 @@ spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2363,10 +2366,6 @@ spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err) if (err)
goto out_undo_pci; goto out_undo_pci;
err = spider_net_init_firmware(card);
if (err)
goto out_undo_pci;
err = spider_net_setup_netdev(card); err = spider_net_setup_netdev(card);
if (err) if (err)
goto out_undo_pci; goto out_undo_pci;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment