diff options
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r-- | drivers/net/wireless/b43/main.c | 229 |
1 files changed, 123 insertions, 106 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 0d9824c7e28f..2e563662c9a2 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -1557,16 +1557,19 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) | |||
1557 | return ret; | 1557 | return ret; |
1558 | } | 1558 | } |
1559 | 1559 | ||
1560 | static void do_release_fw(struct b43_firmware_file *fw) | ||
1561 | { | ||
1562 | release_firmware(fw->data); | ||
1563 | fw->data = NULL; | ||
1564 | fw->filename = NULL; | ||
1565 | } | ||
1566 | |||
1560 | static void b43_release_firmware(struct b43_wldev *dev) | 1567 | static void b43_release_firmware(struct b43_wldev *dev) |
1561 | { | 1568 | { |
1562 | release_firmware(dev->fw.ucode); | 1569 | do_release_fw(&dev->fw.ucode); |
1563 | dev->fw.ucode = NULL; | 1570 | do_release_fw(&dev->fw.pcm); |
1564 | release_firmware(dev->fw.pcm); | 1571 | do_release_fw(&dev->fw.initvals); |
1565 | dev->fw.pcm = NULL; | 1572 | do_release_fw(&dev->fw.initvals_band); |
1566 | release_firmware(dev->fw.initvals); | ||
1567 | dev->fw.initvals = NULL; | ||
1568 | release_firmware(dev->fw.initvals_band); | ||
1569 | dev->fw.initvals_band = NULL; | ||
1570 | } | 1573 | } |
1571 | 1574 | ||
1572 | static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | 1575 | static void b43_print_fw_helptext(struct b43_wl *wl, bool error) |
@@ -1584,33 +1587,43 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | |||
1584 | 1587 | ||
1585 | static int do_request_fw(struct b43_wldev *dev, | 1588 | static int do_request_fw(struct b43_wldev *dev, |
1586 | const char *name, | 1589 | const char *name, |
1587 | const struct firmware **fw) | 1590 | struct b43_firmware_file *fw) |
1588 | { | 1591 | { |
1589 | char path[sizeof(modparam_fwpostfix) + 32]; | 1592 | char path[sizeof(modparam_fwpostfix) + 32]; |
1593 | const struct firmware *blob; | ||
1590 | struct b43_fw_header *hdr; | 1594 | struct b43_fw_header *hdr; |
1591 | u32 size; | 1595 | u32 size; |
1592 | int err; | 1596 | int err; |
1593 | 1597 | ||
1594 | if (!name) | 1598 | if (!name) { |
1599 | /* Don't fetch anything. Free possibly cached firmware. */ | ||
1600 | do_release_fw(fw); | ||
1595 | return 0; | 1601 | return 0; |
1602 | } | ||
1603 | if (fw->filename) { | ||
1604 | if (strcmp(fw->filename, name) == 0) | ||
1605 | return 0; /* Already have this fw. */ | ||
1606 | /* Free the cached firmware first. */ | ||
1607 | do_release_fw(fw); | ||
1608 | } | ||
1596 | 1609 | ||
1597 | snprintf(path, ARRAY_SIZE(path), | 1610 | snprintf(path, ARRAY_SIZE(path), |
1598 | "b43%s/%s.fw", | 1611 | "b43%s/%s.fw", |
1599 | modparam_fwpostfix, name); | 1612 | modparam_fwpostfix, name); |
1600 | err = request_firmware(fw, path, dev->dev->dev); | 1613 | err = request_firmware(&blob, path, dev->dev->dev); |
1601 | if (err) { | 1614 | if (err) { |
1602 | b43err(dev->wl, "Firmware file \"%s\" not found " | 1615 | b43err(dev->wl, "Firmware file \"%s\" not found " |
1603 | "or load failed.\n", path); | 1616 | "or load failed.\n", path); |
1604 | return err; | 1617 | return err; |
1605 | } | 1618 | } |
1606 | if ((*fw)->size < sizeof(struct b43_fw_header)) | 1619 | if (blob->size < sizeof(struct b43_fw_header)) |
1607 | goto err_format; | 1620 | goto err_format; |
1608 | hdr = (struct b43_fw_header *)((*fw)->data); | 1621 | hdr = (struct b43_fw_header *)(blob->data); |
1609 | switch (hdr->type) { | 1622 | switch (hdr->type) { |
1610 | case B43_FW_TYPE_UCODE: | 1623 | case B43_FW_TYPE_UCODE: |
1611 | case B43_FW_TYPE_PCM: | 1624 | case B43_FW_TYPE_PCM: |
1612 | size = be32_to_cpu(hdr->size); | 1625 | size = be32_to_cpu(hdr->size); |
1613 | if (size != (*fw)->size - sizeof(struct b43_fw_header)) | 1626 | if (size != blob->size - sizeof(struct b43_fw_header)) |
1614 | goto err_format; | 1627 | goto err_format; |
1615 | /* fallthrough */ | 1628 | /* fallthrough */ |
1616 | case B43_FW_TYPE_IV: | 1629 | case B43_FW_TYPE_IV: |
@@ -1621,10 +1634,15 @@ static int do_request_fw(struct b43_wldev *dev, | |||
1621 | goto err_format; | 1634 | goto err_format; |
1622 | } | 1635 | } |
1623 | 1636 | ||
1624 | return err; | 1637 | fw->data = blob; |
1638 | fw->filename = name; | ||
1639 | |||
1640 | return 0; | ||
1625 | 1641 | ||
1626 | err_format: | 1642 | err_format: |
1627 | b43err(dev->wl, "Firmware file \"%s\" format error.\n", path); | 1643 | b43err(dev->wl, "Firmware file \"%s\" format error.\n", path); |
1644 | release_firmware(blob); | ||
1645 | |||
1628 | return -EPROTO; | 1646 | return -EPROTO; |
1629 | } | 1647 | } |
1630 | 1648 | ||
@@ -1636,97 +1654,96 @@ static int b43_request_firmware(struct b43_wldev *dev) | |||
1636 | u32 tmshigh; | 1654 | u32 tmshigh; |
1637 | int err; | 1655 | int err; |
1638 | 1656 | ||
1657 | /* Get microcode */ | ||
1639 | tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); | 1658 | tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); |
1640 | if (!fw->ucode) { | 1659 | if ((rev >= 5) && (rev <= 10)) |
1660 | filename = "ucode5"; | ||
1661 | else if ((rev >= 11) && (rev <= 12)) | ||
1662 | filename = "ucode11"; | ||
1663 | else if (rev >= 13) | ||
1664 | filename = "ucode13"; | ||
1665 | else | ||
1666 | goto err_no_ucode; | ||
1667 | err = do_request_fw(dev, filename, &fw->ucode); | ||
1668 | if (err) | ||
1669 | goto err_load; | ||
1670 | |||
1671 | /* Get PCM code */ | ||
1672 | if ((rev >= 5) && (rev <= 10)) | ||
1673 | filename = "pcm5"; | ||
1674 | else if (rev >= 11) | ||
1675 | filename = NULL; | ||
1676 | else | ||
1677 | goto err_no_pcm; | ||
1678 | err = do_request_fw(dev, filename, &fw->pcm); | ||
1679 | if (err) | ||
1680 | goto err_load; | ||
1681 | |||
1682 | /* Get initvals */ | ||
1683 | switch (dev->phy.type) { | ||
1684 | case B43_PHYTYPE_A: | ||
1685 | if ((rev >= 5) && (rev <= 10)) { | ||
1686 | if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) | ||
1687 | filename = "a0g1initvals5"; | ||
1688 | else | ||
1689 | filename = "a0g0initvals5"; | ||
1690 | } else | ||
1691 | goto err_no_initvals; | ||
1692 | break; | ||
1693 | case B43_PHYTYPE_G: | ||
1641 | if ((rev >= 5) && (rev <= 10)) | 1694 | if ((rev >= 5) && (rev <= 10)) |
1642 | filename = "ucode5"; | 1695 | filename = "b0g0initvals5"; |
1643 | else if ((rev >= 11) && (rev <= 12)) | ||
1644 | filename = "ucode11"; | ||
1645 | else if (rev >= 13) | 1696 | else if (rev >= 13) |
1646 | filename = "ucode13"; | 1697 | filename = "lp0initvals13"; |
1647 | else | 1698 | else |
1648 | goto err_no_ucode; | 1699 | goto err_no_initvals; |
1649 | err = do_request_fw(dev, filename, &fw->ucode); | 1700 | break; |
1650 | if (err) | 1701 | case B43_PHYTYPE_N: |
1651 | goto err_load; | 1702 | if ((rev >= 11) && (rev <= 12)) |
1703 | filename = "n0initvals11"; | ||
1704 | else | ||
1705 | goto err_no_initvals; | ||
1706 | break; | ||
1707 | default: | ||
1708 | goto err_no_initvals; | ||
1652 | } | 1709 | } |
1653 | if (!fw->pcm) { | 1710 | err = do_request_fw(dev, filename, &fw->initvals); |
1711 | if (err) | ||
1712 | goto err_load; | ||
1713 | |||
1714 | /* Get bandswitch initvals */ | ||
1715 | switch (dev->phy.type) { | ||
1716 | case B43_PHYTYPE_A: | ||
1717 | if ((rev >= 5) && (rev <= 10)) { | ||
1718 | if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) | ||
1719 | filename = "a0g1bsinitvals5"; | ||
1720 | else | ||
1721 | filename = "a0g0bsinitvals5"; | ||
1722 | } else if (rev >= 11) | ||
1723 | filename = NULL; | ||
1724 | else | ||
1725 | goto err_no_initvals; | ||
1726 | break; | ||
1727 | case B43_PHYTYPE_G: | ||
1654 | if ((rev >= 5) && (rev <= 10)) | 1728 | if ((rev >= 5) && (rev <= 10)) |
1655 | filename = "pcm5"; | 1729 | filename = "b0g0bsinitvals5"; |
1656 | else if (rev >= 11) | 1730 | else if (rev >= 11) |
1657 | filename = NULL; | 1731 | filename = NULL; |
1658 | else | 1732 | else |
1659 | goto err_no_pcm; | ||
1660 | err = do_request_fw(dev, filename, &fw->pcm); | ||
1661 | if (err) | ||
1662 | goto err_load; | ||
1663 | } | ||
1664 | if (!fw->initvals) { | ||
1665 | switch (dev->phy.type) { | ||
1666 | case B43_PHYTYPE_A: | ||
1667 | if ((rev >= 5) && (rev <= 10)) { | ||
1668 | if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) | ||
1669 | filename = "a0g1initvals5"; | ||
1670 | else | ||
1671 | filename = "a0g0initvals5"; | ||
1672 | } else | ||
1673 | goto err_no_initvals; | ||
1674 | break; | ||
1675 | case B43_PHYTYPE_G: | ||
1676 | if ((rev >= 5) && (rev <= 10)) | ||
1677 | filename = "b0g0initvals5"; | ||
1678 | else if (rev >= 13) | ||
1679 | filename = "lp0initvals13"; | ||
1680 | else | ||
1681 | goto err_no_initvals; | ||
1682 | break; | ||
1683 | case B43_PHYTYPE_N: | ||
1684 | if ((rev >= 11) && (rev <= 12)) | ||
1685 | filename = "n0initvals11"; | ||
1686 | else | ||
1687 | goto err_no_initvals; | ||
1688 | break; | ||
1689 | default: | ||
1690 | goto err_no_initvals; | 1733 | goto err_no_initvals; |
1691 | } | 1734 | break; |
1692 | err = do_request_fw(dev, filename, &fw->initvals); | 1735 | case B43_PHYTYPE_N: |
1693 | if (err) | 1736 | if ((rev >= 11) && (rev <= 12)) |
1694 | goto err_load; | 1737 | filename = "n0bsinitvals11"; |
1695 | } | 1738 | else |
1696 | if (!fw->initvals_band) { | ||
1697 | switch (dev->phy.type) { | ||
1698 | case B43_PHYTYPE_A: | ||
1699 | if ((rev >= 5) && (rev <= 10)) { | ||
1700 | if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) | ||
1701 | filename = "a0g1bsinitvals5"; | ||
1702 | else | ||
1703 | filename = "a0g0bsinitvals5"; | ||
1704 | } else if (rev >= 11) | ||
1705 | filename = NULL; | ||
1706 | else | ||
1707 | goto err_no_initvals; | ||
1708 | break; | ||
1709 | case B43_PHYTYPE_G: | ||
1710 | if ((rev >= 5) && (rev <= 10)) | ||
1711 | filename = "b0g0bsinitvals5"; | ||
1712 | else if (rev >= 11) | ||
1713 | filename = NULL; | ||
1714 | else | ||
1715 | goto err_no_initvals; | ||
1716 | break; | ||
1717 | case B43_PHYTYPE_N: | ||
1718 | if ((rev >= 11) && (rev <= 12)) | ||
1719 | filename = "n0bsinitvals11"; | ||
1720 | else | ||
1721 | goto err_no_initvals; | ||
1722 | break; | ||
1723 | default: | ||
1724 | goto err_no_initvals; | 1739 | goto err_no_initvals; |
1725 | } | 1740 | break; |
1726 | err = do_request_fw(dev, filename, &fw->initvals_band); | 1741 | default: |
1727 | if (err) | 1742 | goto err_no_initvals; |
1728 | goto err_load; | ||
1729 | } | 1743 | } |
1744 | err = do_request_fw(dev, filename, &fw->initvals_band); | ||
1745 | if (err) | ||
1746 | goto err_load; | ||
1730 | 1747 | ||
1731 | return 0; | 1748 | return 0; |
1732 | 1749 | ||
@@ -1765,18 +1782,18 @@ static int b43_upload_microcode(struct b43_wldev *dev) | |||
1765 | int err = 0; | 1782 | int err = 0; |
1766 | 1783 | ||
1767 | /* Upload Microcode. */ | 1784 | /* Upload Microcode. */ |
1768 | data = (__be32 *) (dev->fw.ucode->data + hdr_len); | 1785 | data = (__be32 *) (dev->fw.ucode.data->data + hdr_len); |
1769 | len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32); | 1786 | len = (dev->fw.ucode.data->size - hdr_len) / sizeof(__be32); |
1770 | b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000); | 1787 | b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000); |
1771 | for (i = 0; i < len; i++) { | 1788 | for (i = 0; i < len; i++) { |
1772 | b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i])); | 1789 | b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i])); |
1773 | udelay(10); | 1790 | udelay(10); |
1774 | } | 1791 | } |
1775 | 1792 | ||
1776 | if (dev->fw.pcm) { | 1793 | if (dev->fw.pcm.data) { |
1777 | /* Upload PCM data. */ | 1794 | /* Upload PCM data. */ |
1778 | data = (__be32 *) (dev->fw.pcm->data + hdr_len); | 1795 | data = (__be32 *) (dev->fw.pcm.data->data + hdr_len); |
1779 | len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32); | 1796 | len = (dev->fw.pcm.data->size - hdr_len) / sizeof(__be32); |
1780 | b43_shm_control_word(dev, B43_SHM_HW, 0x01EA); | 1797 | b43_shm_control_word(dev, B43_SHM_HW, 0x01EA); |
1781 | b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000); | 1798 | b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000); |
1782 | /* No need for autoinc bit in SHM_HW */ | 1799 | /* No need for autoinc bit in SHM_HW */ |
@@ -1913,19 +1930,19 @@ static int b43_upload_initvals(struct b43_wldev *dev) | |||
1913 | size_t count; | 1930 | size_t count; |
1914 | int err; | 1931 | int err; |
1915 | 1932 | ||
1916 | hdr = (const struct b43_fw_header *)(fw->initvals->data); | 1933 | hdr = (const struct b43_fw_header *)(fw->initvals.data->data); |
1917 | ivals = (const struct b43_iv *)(fw->initvals->data + hdr_len); | 1934 | ivals = (const struct b43_iv *)(fw->initvals.data->data + hdr_len); |
1918 | count = be32_to_cpu(hdr->size); | 1935 | count = be32_to_cpu(hdr->size); |
1919 | err = b43_write_initvals(dev, ivals, count, | 1936 | err = b43_write_initvals(dev, ivals, count, |
1920 | fw->initvals->size - hdr_len); | 1937 | fw->initvals.data->size - hdr_len); |
1921 | if (err) | 1938 | if (err) |
1922 | goto out; | 1939 | goto out; |
1923 | if (fw->initvals_band) { | 1940 | if (fw->initvals_band.data) { |
1924 | hdr = (const struct b43_fw_header *)(fw->initvals_band->data); | 1941 | hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data); |
1925 | ivals = (const struct b43_iv *)(fw->initvals_band->data + hdr_len); | 1942 | ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len); |
1926 | count = be32_to_cpu(hdr->size); | 1943 | count = be32_to_cpu(hdr->size); |
1927 | err = b43_write_initvals(dev, ivals, count, | 1944 | err = b43_write_initvals(dev, ivals, count, |
1928 | fw->initvals_band->size - hdr_len); | 1945 | fw->initvals_band.data->size - hdr_len); |
1929 | if (err) | 1946 | if (err) |
1930 | goto out; | 1947 | goto out; |
1931 | } | 1948 | } |