diff options
author | Lennert Buytenhek <buytenh@wantstofly.org> | 2009-10-22 14:21:30 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-06 16:54:38 -0500 |
commit | 42fba21d56df644887488a29b158cc8916b9ba99 (patch) | |
tree | 2aec3f2ec4b1e96bcfd6079ad0550350bfd321a6 /drivers/net/wireless/mwl8k.c | |
parent | 04b147b19303724aac5ee8e56f113f1935a5c255 (diff) |
mwl8k: add the commands used for AP firmware initialisation
Add the AP version of the GET_HW_SPEC command, as well as the
SET_HW_SPEC command, for initialising AP firmware.
Signed-off-by: Lennert Buytenhek <buytenh@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/mwl8k.c')
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 133 |
1 files changed, 132 insertions, 1 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 90bf19cb6bf4..9b9ce7005da0 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -275,6 +275,7 @@ static const struct ieee80211_rate mwl8k_rates[] = { | |||
275 | /* Firmware command codes */ | 275 | /* Firmware command codes */ |
276 | #define MWL8K_CMD_CODE_DNLD 0x0001 | 276 | #define MWL8K_CMD_CODE_DNLD 0x0001 |
277 | #define MWL8K_CMD_GET_HW_SPEC 0x0003 | 277 | #define MWL8K_CMD_GET_HW_SPEC 0x0003 |
278 | #define MWL8K_CMD_SET_HW_SPEC 0x0004 | ||
278 | #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 | 279 | #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 |
279 | #define MWL8K_CMD_GET_STAT 0x0014 | 280 | #define MWL8K_CMD_GET_STAT 0x0014 |
280 | #define MWL8K_CMD_RADIO_CONTROL 0x001c | 281 | #define MWL8K_CMD_RADIO_CONTROL 0x001c |
@@ -305,6 +306,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | |||
305 | switch (cmd & ~0x8000) { | 306 | switch (cmd & ~0x8000) { |
306 | MWL8K_CMDNAME(CODE_DNLD); | 307 | MWL8K_CMDNAME(CODE_DNLD); |
307 | MWL8K_CMDNAME(GET_HW_SPEC); | 308 | MWL8K_CMDNAME(GET_HW_SPEC); |
309 | MWL8K_CMDNAME(SET_HW_SPEC); | ||
308 | MWL8K_CMDNAME(MAC_MULTICAST_ADR); | 310 | MWL8K_CMDNAME(MAC_MULTICAST_ADR); |
309 | MWL8K_CMDNAME(GET_STAT); | 311 | MWL8K_CMDNAME(GET_STAT); |
310 | MWL8K_CMDNAME(RADIO_CONTROL); | 312 | MWL8K_CMDNAME(RADIO_CONTROL); |
@@ -1596,6 +1598,129 @@ static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw) | |||
1596 | } | 1598 | } |
1597 | 1599 | ||
1598 | /* | 1600 | /* |
1601 | * CMD_GET_HW_SPEC (AP version). | ||
1602 | */ | ||
1603 | struct mwl8k_cmd_get_hw_spec_ap { | ||
1604 | struct mwl8k_cmd_pkt header; | ||
1605 | __u8 hw_rev; | ||
1606 | __u8 host_interface; | ||
1607 | __le16 num_wcb; | ||
1608 | __le16 num_mcaddrs; | ||
1609 | __u8 perm_addr[ETH_ALEN]; | ||
1610 | __le16 region_code; | ||
1611 | __le16 num_antenna; | ||
1612 | __le32 fw_rev; | ||
1613 | __le32 wcbbase0; | ||
1614 | __le32 rxwrptr; | ||
1615 | __le32 rxrdptr; | ||
1616 | __le32 ps_cookie; | ||
1617 | __le32 wcbbase1; | ||
1618 | __le32 wcbbase2; | ||
1619 | __le32 wcbbase3; | ||
1620 | } __attribute__((packed)); | ||
1621 | |||
1622 | static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw) | ||
1623 | { | ||
1624 | struct mwl8k_priv *priv = hw->priv; | ||
1625 | struct mwl8k_cmd_get_hw_spec_ap *cmd; | ||
1626 | int rc; | ||
1627 | |||
1628 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1629 | if (cmd == NULL) | ||
1630 | return -ENOMEM; | ||
1631 | |||
1632 | cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC); | ||
1633 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1634 | |||
1635 | memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); | ||
1636 | cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); | ||
1637 | |||
1638 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1639 | |||
1640 | if (!rc) { | ||
1641 | int off; | ||
1642 | |||
1643 | SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); | ||
1644 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | ||
1645 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | ||
1646 | priv->hw_rev = cmd->hw_rev; | ||
1647 | |||
1648 | off = le32_to_cpu(cmd->wcbbase0) & 0xffff; | ||
1649 | iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off); | ||
1650 | |||
1651 | off = le32_to_cpu(cmd->rxwrptr) & 0xffff; | ||
1652 | iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off); | ||
1653 | |||
1654 | off = le32_to_cpu(cmd->rxrdptr) & 0xffff; | ||
1655 | iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off); | ||
1656 | |||
1657 | off = le32_to_cpu(cmd->wcbbase1) & 0xffff; | ||
1658 | iowrite32(cpu_to_le32(priv->txq[1].txd_dma), priv->sram + off); | ||
1659 | |||
1660 | off = le32_to_cpu(cmd->wcbbase2) & 0xffff; | ||
1661 | iowrite32(cpu_to_le32(priv->txq[2].txd_dma), priv->sram + off); | ||
1662 | |||
1663 | off = le32_to_cpu(cmd->wcbbase3) & 0xffff; | ||
1664 | iowrite32(cpu_to_le32(priv->txq[3].txd_dma), priv->sram + off); | ||
1665 | } | ||
1666 | |||
1667 | kfree(cmd); | ||
1668 | return rc; | ||
1669 | } | ||
1670 | |||
1671 | /* | ||
1672 | * CMD_SET_HW_SPEC. | ||
1673 | */ | ||
1674 | struct mwl8k_cmd_set_hw_spec { | ||
1675 | struct mwl8k_cmd_pkt header; | ||
1676 | __u8 hw_rev; | ||
1677 | __u8 host_interface; | ||
1678 | __le16 num_mcaddrs; | ||
1679 | __u8 perm_addr[ETH_ALEN]; | ||
1680 | __le16 region_code; | ||
1681 | __le32 fw_rev; | ||
1682 | __le32 ps_cookie; | ||
1683 | __le32 caps; | ||
1684 | __le32 rx_queue_ptr; | ||
1685 | __le32 num_tx_queues; | ||
1686 | __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; | ||
1687 | __le32 flags; | ||
1688 | __le32 num_tx_desc_per_queue; | ||
1689 | __le32 total_rxd; | ||
1690 | } __attribute__((packed)); | ||
1691 | |||
1692 | #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080 | ||
1693 | |||
1694 | static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw) | ||
1695 | { | ||
1696 | struct mwl8k_priv *priv = hw->priv; | ||
1697 | struct mwl8k_cmd_set_hw_spec *cmd; | ||
1698 | int rc; | ||
1699 | int i; | ||
1700 | |||
1701 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1702 | if (cmd == NULL) | ||
1703 | return -ENOMEM; | ||
1704 | |||
1705 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_HW_SPEC); | ||
1706 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
1707 | |||
1708 | cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); | ||
1709 | cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma); | ||
1710 | cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); | ||
1711 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | ||
1712 | cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma); | ||
1713 | cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT); | ||
1714 | cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); | ||
1715 | cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS); | ||
1716 | |||
1717 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
1718 | kfree(cmd); | ||
1719 | |||
1720 | return rc; | ||
1721 | } | ||
1722 | |||
1723 | /* | ||
1599 | * CMD_MAC_MULTICAST_ADR. | 1724 | * CMD_MAC_MULTICAST_ADR. |
1600 | */ | 1725 | */ |
1601 | struct mwl8k_cmd_mac_multicast_adr { | 1726 | struct mwl8k_cmd_mac_multicast_adr { |
@@ -3211,7 +3336,13 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3211 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 3336 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3212 | 3337 | ||
3213 | /* Get config data, mac addrs etc */ | 3338 | /* Get config data, mac addrs etc */ |
3214 | rc = mwl8k_cmd_get_hw_spec_sta(hw); | 3339 | if (priv->ap_fw) { |
3340 | rc = mwl8k_cmd_get_hw_spec_ap(hw); | ||
3341 | if (!rc) | ||
3342 | rc = mwl8k_cmd_set_hw_spec(hw); | ||
3343 | } else { | ||
3344 | rc = mwl8k_cmd_get_hw_spec_sta(hw); | ||
3345 | } | ||
3215 | if (rc) { | 3346 | if (rc) { |
3216 | printk(KERN_ERR "%s: Cannot initialise firmware\n", | 3347 | printk(KERN_ERR "%s: Cannot initialise firmware\n", |
3217 | wiphy_name(hw->wiphy)); | 3348 | wiphy_name(hw->wiphy)); |