diff options
| author | Kou Ishizaki <kou.ishizaki@toshiba.co.jp> | 2007-02-20 17:34:50 -0500 |
|---|---|---|
| committer | Jeff Garzik <jeff@garzik.org> | 2007-02-27 04:16:03 -0500 |
| commit | 3cf761ddccb9332218973e17f9b987bb5cae7b69 (patch) | |
| tree | cde24a6922ef6988d301dff011782bb83cc2dd50 /drivers/net/spider_net.c | |
| parent | abdb66b566fce5641c90100e0a113a94bab43fda (diff) | |
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: Kou Ishizaki <kou.ishizaki@toshiba.co.jp>
Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/spider_net.c')
| -rw-r--r-- | drivers/net/spider_net.c | 247 |
1 files changed, 123 insertions, 124 deletions
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c index 8aa3ebe2a0e..fef455694d7 100644 --- a/drivers/net/spider_net.c +++ b/drivers/net/spider_net.c | |||
| @@ -1705,6 +1705,124 @@ spider_net_enable_card(struct spider_net_card *card) | |||
| 1705 | } | 1705 | } |
| 1706 | 1706 | ||
| 1707 | /** | 1707 | /** |
| 1708 | * spider_net_download_firmware - loads firmware into the adapter | ||
| 1709 | * @card: card structure | ||
| 1710 | * @firmware_ptr: pointer to firmware data | ||
| 1711 | * | ||
| 1712 | * spider_net_download_firmware loads the firmware data into the | ||
| 1713 | * adapter. It assumes the length etc. to be allright. | ||
| 1714 | */ | ||
| 1715 | static int | ||
| 1716 | spider_net_download_firmware(struct spider_net_card *card, | ||
| 1717 | const void *firmware_ptr) | ||
| 1718 | { | ||
| 1719 | int sequencer, i; | ||
| 1720 | const u32 *fw_ptr = firmware_ptr; | ||
| 1721 | |||
| 1722 | /* stop sequencers */ | ||
| 1723 | spider_net_write_reg(card, SPIDER_NET_GSINIT, | ||
| 1724 | SPIDER_NET_STOP_SEQ_VALUE); | ||
| 1725 | |||
| 1726 | for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS; | ||
| 1727 | sequencer++) { | ||
| 1728 | spider_net_write_reg(card, | ||
| 1729 | SPIDER_NET_GSnPRGADR + sequencer * 8, 0); | ||
| 1730 | for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) { | ||
| 1731 | spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT + | ||
| 1732 | sequencer * 8, *fw_ptr); | ||
| 1733 | fw_ptr++; | ||
| 1734 | } | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | if (spider_net_read_reg(card, SPIDER_NET_GSINIT)) | ||
| 1738 | return -EIO; | ||
| 1739 | |||
| 1740 | spider_net_write_reg(card, SPIDER_NET_GSINIT, | ||
| 1741 | SPIDER_NET_RUN_SEQ_VALUE); | ||
| 1742 | |||
| 1743 | return 0; | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | /** | ||
| 1747 | * spider_net_init_firmware - reads in firmware parts | ||
| 1748 | * @card: card structure | ||
| 1749 | * | ||
| 1750 | * Returns 0 on success, <0 on failure | ||
| 1751 | * | ||
| 1752 | * spider_net_init_firmware opens the sequencer firmware and does some basic | ||
| 1753 | * checks. This function opens and releases the firmware structure. A call | ||
| 1754 | * to download the firmware is performed before the release. | ||
| 1755 | * | ||
| 1756 | * Firmware format | ||
| 1757 | * =============== | ||
| 1758 | * spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being | ||
| 1759 | * the program for each sequencer. Use the command | ||
| 1760 | * tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \ | ||
| 1761 | * Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \ | ||
| 1762 | * Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin | ||
| 1763 | * | ||
| 1764 | * to generate spider_fw.bin, if you have sequencer programs with something | ||
| 1765 | * like the following contents for each sequencer: | ||
| 1766 | * <ONE LINE COMMENT> | ||
| 1767 | * <FIRST 4-BYTES-WORD FOR SEQUENCER> | ||
| 1768 | * <SECOND 4-BYTES-WORD FOR SEQUENCER> | ||
| 1769 | * ... | ||
| 1770 | * <1024th 4-BYTES-WORD FOR SEQUENCER> | ||
| 1771 | */ | ||
| 1772 | static int | ||
| 1773 | spider_net_init_firmware(struct spider_net_card *card) | ||
| 1774 | { | ||
| 1775 | struct firmware *firmware = NULL; | ||
| 1776 | struct device_node *dn; | ||
| 1777 | const u8 *fw_prop = NULL; | ||
| 1778 | int err = -ENOENT; | ||
| 1779 | int fw_size; | ||
| 1780 | |||
| 1781 | if (request_firmware((const struct firmware **)&firmware, | ||
| 1782 | SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) { | ||
| 1783 | if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) && | ||
| 1784 | netif_msg_probe(card) ) { | ||
| 1785 | pr_err("Incorrect size of spidernet firmware in " \ | ||
| 1786 | "filesystem. Looking in host firmware...\n"); | ||
| 1787 | goto try_host_fw; | ||
| 1788 | } | ||
| 1789 | err = spider_net_download_firmware(card, firmware->data); | ||
| 1790 | |||
| 1791 | release_firmware(firmware); | ||
| 1792 | if (err) | ||
| 1793 | goto try_host_fw; | ||
| 1794 | |||
| 1795 | goto done; | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | try_host_fw: | ||
| 1799 | dn = pci_device_to_OF_node(card->pdev); | ||
| 1800 | if (!dn) | ||
| 1801 | goto out_err; | ||
| 1802 | |||
| 1803 | fw_prop = get_property(dn, "firmware", &fw_size); | ||
| 1804 | if (!fw_prop) | ||
| 1805 | goto out_err; | ||
| 1806 | |||
| 1807 | if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) && | ||
| 1808 | netif_msg_probe(card) ) { | ||
| 1809 | pr_err("Incorrect size of spidernet firmware in " \ | ||
| 1810 | "host firmware\n"); | ||
| 1811 | goto done; | ||
| 1812 | } | ||
| 1813 | |||
| 1814 | err = spider_net_download_firmware(card, fw_prop); | ||
| 1815 | |||
| 1816 | done: | ||
| 1817 | return err; | ||
| 1818 | out_err: | ||
| 1819 | if (netif_msg_probe(card)) | ||
| 1820 | pr_err("Couldn't find spidernet firmware in filesystem " \ | ||
| 1821 | "or host firmware\n"); | ||
| 1822 | return err; | ||
| 1823 | } | ||
| 1824 | |||
| 1825 | /** | ||
| 1708 | * spider_net_open - called upon ifonfig up | 1826 | * spider_net_open - called upon ifonfig up |
| 1709 | * @netdev: interface device structure | 1827 | * @netdev: interface device structure |
| 1710 | * | 1828 | * |
| @@ -1719,6 +1837,10 @@ spider_net_open(struct net_device *netdev) | |||
| 1719 | struct spider_net_card *card = netdev_priv(netdev); | 1837 | struct spider_net_card *card = netdev_priv(netdev); |
| 1720 | int result; | 1838 | int result; |
| 1721 | 1839 | ||
| 1840 | result = spider_net_init_firmware(card); | ||
| 1841 | if (result) | ||
| 1842 | goto init_firmware_failed; | ||
| 1843 | |||
| 1722 | /* start probing with copper */ | 1844 | /* start probing with copper */ |
| 1723 | spider_net_setup_aneg(card); | 1845 | spider_net_setup_aneg(card); |
| 1724 | if (card->phy.def->phy_id) | 1846 | if (card->phy.def->phy_id) |
| @@ -1762,6 +1884,7 @@ alloc_rx_failed: | |||
| 1762 | spider_net_free_chain(card, &card->tx_chain); | 1884 | spider_net_free_chain(card, &card->tx_chain); |
| 1763 | alloc_tx_failed: | 1885 | alloc_tx_failed: |
| 1764 | del_timer_sync(&card->aneg_timer); | 1886 | del_timer_sync(&card->aneg_timer); |
| 1887 | init_firmware_failed: | ||
| 1765 | return result; | 1888 | return result; |
| 1766 | } | 1889 | } |
| 1767 | 1890 | ||
| @@ -1873,124 +1996,6 @@ spider_net_setup_phy(struct spider_net_card *card) | |||
| 1873 | } | 1996 | } |
| 1874 | 1997 | ||
| 1875 | /** | 1998 | /** |
| 1876 | * spider_net_download_firmware - loads firmware into the adapter | ||
| 1877 | * @card: card structure | ||
| 1878 | * @firmware_ptr: pointer to firmware data | ||
| 1879 | * | ||
| 1880 | * spider_net_download_firmware loads the firmware data into the | ||
| 1881 | * adapter. It assumes the length etc. to be allright. | ||
| 1882 | */ | ||
| 1883 | static int | ||
| 1884 | spider_net_download_firmware(struct spider_net_card *card, | ||
| 1885 | const void *firmware_ptr) | ||
| 1886 | { | ||
| 1887 | int sequencer, i; | ||
| 1888 | const u32 *fw_ptr = firmware_ptr; | ||
| 1889 | |||
| 1890 | /* stop sequencers */ | ||
| 1891 | spider_net_write_reg(card, SPIDER_NET_GSINIT, | ||
| 1892 | SPIDER_NET_STOP_SEQ_VALUE); | ||
| 1893 | |||
| 1894 | for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS; | ||
| 1895 | sequencer++) { | ||
| 1896 | spider_net_write_reg(card, | ||
| 1897 | SPIDER_NET_GSnPRGADR + sequencer * 8, 0); | ||
| 1898 | for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) { | ||
| 1899 | spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT + | ||
| 1900 | sequencer * 8, *fw_ptr); | ||
| 1901 | fw_ptr++; | ||
| 1902 | } | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | if (spider_net_read_reg(card, SPIDER_NET_GSINIT)) | ||
| 1906 | return -EIO; | ||
| 1907 | |||
| 1908 | spider_net_write_reg(card, SPIDER_NET_GSINIT, | ||
| 1909 | SPIDER_NET_RUN_SEQ_VALUE); | ||
| 1910 | |||
| 1911 | return 0; | ||
| 1912 | } | ||
| 1913 | |||
| 1914 | /** | ||
| 1915 | * spider_net_init_firmware - reads in firmware parts | ||
| 1916 | * @card: card structure | ||
| 1917 | * | ||
| 1918 | * Returns 0 on success, <0 on failure | ||
| 1919 | * | ||
| 1920 | * spider_net_init_firmware opens the sequencer firmware and does some basic | ||
| 1921 | * checks. This function opens and releases the firmware structure. A call | ||
| 1922 | * to download the firmware is performed before the release. | ||
| 1923 | * | ||
| 1924 | * Firmware format | ||
| 1925 | * =============== | ||
| 1926 | * spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being | ||
| 1927 | * the program for each sequencer. Use the command | ||
| 1928 | * tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt \ | ||
| 1929 | * Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt \ | ||
| 1930 | * Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin | ||
| 1931 | * | ||
| 1932 | * to generate spider_fw.bin, if you have sequencer programs with something | ||
| 1933 | * like the following contents for each sequencer: | ||
| 1934 | * <ONE LINE COMMENT> | ||
| 1935 | * <FIRST 4-BYTES-WORD FOR SEQUENCER> | ||
| 1936 | * <SECOND 4-BYTES-WORD FOR SEQUENCER> | ||
| 1937 | * ... | ||
| 1938 | * <1024th 4-BYTES-WORD FOR SEQUENCER> | ||
| 1939 | */ | ||
| 1940 | static int | ||
| 1941 | spider_net_init_firmware(struct spider_net_card *card) | ||
| 1942 | { | ||
| 1943 | struct firmware *firmware = NULL; | ||
| 1944 | struct device_node *dn; | ||
| 1945 | const u8 *fw_prop = NULL; | ||
| 1946 | int err = -ENOENT; | ||
| 1947 | int fw_size; | ||
| 1948 | |||
| 1949 | if (request_firmware((const struct firmware **)&firmware, | ||
| 1950 | SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) { | ||
| 1951 | if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) && | ||
| 1952 | netif_msg_probe(card) ) { | ||
| 1953 | pr_err("Incorrect size of spidernet firmware in " \ | ||
| 1954 | "filesystem. Looking in host firmware...\n"); | ||
| 1955 | goto try_host_fw; | ||
| 1956 | } | ||
| 1957 | err = spider_net_download_firmware(card, firmware->data); | ||
| 1958 | |||
| 1959 | release_firmware(firmware); | ||
| 1960 | if (err) | ||
| 1961 | goto try_host_fw; | ||
| 1962 | |||
| 1963 | goto done; | ||
| 1964 | } | ||
| 1965 | |||
| 1966 | try_host_fw: | ||
| 1967 | dn = pci_device_to_OF_node(card->pdev); | ||
| 1968 | if (!dn) | ||
| 1969 | goto out_err; | ||
| 1970 | |||
| 1971 | fw_prop = get_property(dn, "firmware", &fw_size); | ||
| 1972 | if (!fw_prop) | ||
| 1973 | goto out_err; | ||
| 1974 | |||
| 1975 | if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) && | ||
| 1976 | netif_msg_probe(card) ) { | ||
| 1977 | pr_err("Incorrect size of spidernet firmware in " \ | ||
| 1978 | "host firmware\n"); | ||
| 1979 | goto done; | ||
| 1980 | } | ||
| 1981 | |||
| 1982 | err = spider_net_download_firmware(card, fw_prop); | ||
| 1983 | |||
| 1984 | done: | ||
| 1985 | return err; | ||
| 1986 | out_err: | ||
| 1987 | if (netif_msg_probe(card)) | ||
| 1988 | pr_err("Couldn't find spidernet firmware in filesystem " \ | ||
| 1989 | "or host firmware\n"); | ||
| 1990 | return err; | ||
| 1991 | } | ||
| 1992 | |||
| 1993 | /** | ||
| 1994 | * spider_net_workaround_rxramfull - work around firmware bug | 1999 | * spider_net_workaround_rxramfull - work around firmware bug |
| 1995 | * @card: card structure | 2000 | * @card: card structure |
| 1996 | * | 2001 | * |
| @@ -2090,8 +2095,6 @@ spider_net_tx_timeout_task(struct work_struct *work) | |||
| 2090 | 2095 | ||
| 2091 | if (spider_net_setup_phy(card)) | 2096 | if (spider_net_setup_phy(card)) |
| 2092 | goto out; | 2097 | goto out; |
| 2093 | if (spider_net_init_firmware(card)) | ||
| 2094 | goto out; | ||
| 2095 | 2098 | ||
| 2096 | spider_net_open(netdev); | 2099 | spider_net_open(netdev); |
| 2097 | spider_net_kick_tx_dma(card); | 2100 | spider_net_kick_tx_dma(card); |
| @@ -2363,10 +2366,6 @@ spider_net_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2363 | if (err) | 2366 | if (err) |
| 2364 | goto out_undo_pci; | 2367 | goto out_undo_pci; |
| 2365 | 2368 | ||
| 2366 | err = spider_net_init_firmware(card); | ||
| 2367 | if (err) | ||
| 2368 | goto out_undo_pci; | ||
| 2369 | |||
| 2370 | err = spider_net_setup_netdev(card); | 2369 | err = spider_net_setup_netdev(card); |
| 2371 | if (err) | 2370 | if (err) |
| 2372 | goto out_undo_pci; | 2371 | goto out_undo_pci; |
