aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/orinoco/main.c')
-rw-r--r--drivers/net/wireless/orinoco/main.c297
1 files changed, 64 insertions, 233 deletions
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index 0727b41a397..dab6649ad0c 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -210,9 +210,10 @@ struct orinoco_rx_data {
210/* Function prototypes */ 210/* Function prototypes */
211/********************************************************************/ 211/********************************************************************/
212 212
213static void __orinoco_set_multicast_list(struct net_device *dev); 213static int __orinoco_set_multicast_list(struct net_device *dev);
214static int __orinoco_up(struct orinoco_private *priv); 214static int __orinoco_up(struct orinoco_private *priv);
215static int __orinoco_down(struct orinoco_private *priv); 215static int __orinoco_down(struct orinoco_private *priv);
216static int __orinoco_commit(struct orinoco_private *priv);
216 217
217/********************************************************************/ 218/********************************************************************/
218/* Internal helper functions */ 219/* Internal helper functions */
@@ -1524,7 +1525,7 @@ static int __orinoco_up(struct orinoco_private *priv)
1524 1525
1525 netif_carrier_off(dev); /* just to make sure */ 1526 netif_carrier_off(dev); /* just to make sure */
1526 1527
1527 err = __orinoco_program_rids(dev); 1528 err = __orinoco_commit(priv);
1528 if (err) { 1529 if (err) {
1529 printk(KERN_ERR "%s: Error %d configuring card\n", 1530 printk(KERN_ERR "%s: Error %d configuring card\n",
1530 dev->name, err); 1531 dev->name, err);
@@ -1593,237 +1594,7 @@ static int orinoco_reinit_firmware(struct orinoco_private *priv)
1593 return err; 1594 return err;
1594} 1595}
1595 1596
1596int __orinoco_program_rids(struct net_device *dev) 1597static int
1597{
1598 struct orinoco_private *priv = ndev_priv(dev);
1599 hermes_t *hw = &priv->hw;
1600 int err;
1601 struct hermes_idstring idbuf;
1602
1603 /* Set the MAC address */
1604 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
1605 HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
1606 if (err) {
1607 printk(KERN_ERR "%s: Error %d setting MAC address\n",
1608 dev->name, err);
1609 return err;
1610 }
1611
1612 /* Set up the link mode */
1613 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
1614 priv->port_type);
1615 if (err) {
1616 printk(KERN_ERR "%s: Error %d setting port type\n",
1617 dev->name, err);
1618 return err;
1619 }
1620 /* Set the channel/frequency */
1621 if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
1622 err = hermes_write_wordrec(hw, USER_BAP,
1623 HERMES_RID_CNFOWNCHANNEL,
1624 priv->channel);
1625 if (err) {
1626 printk(KERN_ERR "%s: Error %d setting channel %d\n",
1627 dev->name, err, priv->channel);
1628 return err;
1629 }
1630 }
1631
1632 if (priv->has_ibss) {
1633 u16 createibss;
1634
1635 if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
1636 printk(KERN_WARNING "%s: This firmware requires an "
1637 "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
1638 /* With wvlan_cs, in this case, we would crash.
1639 * hopefully, this driver will behave better...
1640 * Jean II */
1641 createibss = 0;
1642 } else {
1643 createibss = priv->createibss;
1644 }
1645
1646 err = hermes_write_wordrec(hw, USER_BAP,
1647 HERMES_RID_CNFCREATEIBSS,
1648 createibss);
1649 if (err) {
1650 printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
1651 dev->name, err);
1652 return err;
1653 }
1654 }
1655
1656 /* Set the desired BSSID */
1657 err = __orinoco_hw_set_wap(priv);
1658 if (err) {
1659 printk(KERN_ERR "%s: Error %d setting AP address\n",
1660 dev->name, err);
1661 return err;
1662 }
1663 /* Set the desired ESSID */
1664 idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
1665 memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
1666 /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
1667 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
1668 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
1669 &idbuf);
1670 if (err) {
1671 printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
1672 dev->name, err);
1673 return err;
1674 }
1675 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
1676 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
1677 &idbuf);
1678 if (err) {
1679 printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
1680 dev->name, err);
1681 return err;
1682 }
1683
1684 /* Set the station name */
1685 idbuf.len = cpu_to_le16(strlen(priv->nick));
1686 memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
1687 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
1688 HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
1689 &idbuf);
1690 if (err) {
1691 printk(KERN_ERR "%s: Error %d setting nickname\n",
1692 dev->name, err);
1693 return err;
1694 }
1695
1696 /* Set AP density */
1697 if (priv->has_sensitivity) {
1698 err = hermes_write_wordrec(hw, USER_BAP,
1699 HERMES_RID_CNFSYSTEMSCALE,
1700 priv->ap_density);
1701 if (err) {
1702 printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
1703 "Disabling sensitivity control\n",
1704 dev->name, err);
1705
1706 priv->has_sensitivity = 0;
1707 }
1708 }
1709
1710 /* Set RTS threshold */
1711 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
1712 priv->rts_thresh);
1713 if (err) {
1714 printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
1715 dev->name, err);
1716 return err;
1717 }
1718
1719 /* Set fragmentation threshold or MWO robustness */
1720 if (priv->has_mwo)
1721 err = hermes_write_wordrec(hw, USER_BAP,
1722 HERMES_RID_CNFMWOROBUST_AGERE,
1723 priv->mwo_robust);
1724 else
1725 err = hermes_write_wordrec(hw, USER_BAP,
1726 HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
1727 priv->frag_thresh);
1728 if (err) {
1729 printk(KERN_ERR "%s: Error %d setting fragmentation\n",
1730 dev->name, err);
1731 return err;
1732 }
1733
1734 /* Set bitrate */
1735 err = __orinoco_hw_set_bitrate(priv);
1736 if (err) {
1737 printk(KERN_ERR "%s: Error %d setting bitrate\n",
1738 dev->name, err);
1739 return err;
1740 }
1741
1742 /* Set power management */
1743 if (priv->has_pm) {
1744 err = hermes_write_wordrec(hw, USER_BAP,
1745 HERMES_RID_CNFPMENABLED,
1746 priv->pm_on);
1747 if (err) {
1748 printk(KERN_ERR "%s: Error %d setting up PM\n",
1749 dev->name, err);
1750 return err;
1751 }
1752
1753 err = hermes_write_wordrec(hw, USER_BAP,
1754 HERMES_RID_CNFMULTICASTRECEIVE,
1755 priv->pm_mcast);
1756 if (err) {
1757 printk(KERN_ERR "%s: Error %d setting up PM\n",
1758 dev->name, err);
1759 return err;
1760 }
1761 err = hermes_write_wordrec(hw, USER_BAP,
1762 HERMES_RID_CNFMAXSLEEPDURATION,
1763 priv->pm_period);
1764 if (err) {
1765 printk(KERN_ERR "%s: Error %d setting up PM\n",
1766 dev->name, err);
1767 return err;
1768 }
1769 err = hermes_write_wordrec(hw, USER_BAP,
1770 HERMES_RID_CNFPMHOLDOVERDURATION,
1771 priv->pm_timeout);
1772 if (err) {
1773 printk(KERN_ERR "%s: Error %d setting up PM\n",
1774 dev->name, err);
1775 return err;
1776 }
1777 }
1778
1779 /* Set preamble - only for Symbol so far... */
1780 if (priv->has_preamble) {
1781 err = hermes_write_wordrec(hw, USER_BAP,
1782 HERMES_RID_CNFPREAMBLE_SYMBOL,
1783 priv->preamble);
1784 if (err) {
1785 printk(KERN_ERR "%s: Error %d setting preamble\n",
1786 dev->name, err);
1787 return err;
1788 }
1789 }
1790
1791 /* Set up encryption */
1792 if (priv->has_wep || priv->has_wpa) {
1793 err = __orinoco_hw_setup_enc(priv);
1794 if (err) {
1795 printk(KERN_ERR "%s: Error %d activating encryption\n",
1796 dev->name, err);
1797 return err;
1798 }
1799 }
1800
1801 if (priv->iw_mode == IW_MODE_MONITOR) {
1802 /* Enable monitor mode */
1803 dev->type = ARPHRD_IEEE80211;
1804 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
1805 HERMES_TEST_MONITOR, 0, NULL);
1806 } else {
1807 /* Disable monitor mode */
1808 dev->type = ARPHRD_ETHER;
1809 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
1810 HERMES_TEST_STOP, 0, NULL);
1811 }
1812 if (err)
1813 return err;
1814
1815 /* Set promiscuity / multicast*/
1816 priv->promiscuous = 0;
1817 priv->mc_count = 0;
1818
1819 /* FIXME: what about netif_tx_lock */
1820 __orinoco_set_multicast_list(dev);
1821
1822 return 0;
1823}
1824
1825/* FIXME: return int? */
1826static void
1827__orinoco_set_multicast_list(struct net_device *dev) 1598__orinoco_set_multicast_list(struct net_device *dev)
1828{ 1599{
1829 struct orinoco_private *priv = ndev_priv(dev); 1600 struct orinoco_private *priv = ndev_priv(dev);
@@ -1843,6 +1614,8 @@ __orinoco_set_multicast_list(struct net_device *dev)
1843 1614
1844 err = __orinoco_hw_set_multicast_list(priv, dev->mc_list, mc_count, 1615 err = __orinoco_hw_set_multicast_list(priv, dev->mc_list, mc_count,
1845 promisc); 1616 promisc);
1617
1618 return err;
1846} 1619}
1847 1620
1848/* This must be called from user context, without locks held - use 1621/* This must be called from user context, without locks held - use
@@ -1920,6 +1693,64 @@ void orinoco_reset(struct work_struct *work)
1920 printk(KERN_ERR "%s: Device has been disabled!\n", dev->name); 1693 printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
1921} 1694}
1922 1695
1696static int __orinoco_commit(struct orinoco_private *priv)
1697{
1698 struct net_device *dev = priv->ndev;
1699 int err = 0;
1700
1701 err = orinoco_hw_program_rids(priv);
1702
1703 /* FIXME: what about netif_tx_lock */
1704 (void) __orinoco_set_multicast_list(dev);
1705
1706 return err;
1707}
1708
1709/* Ensures configuration changes are applied. May result in a reset.
1710 * The caller should hold priv->lock
1711 */
1712int orinoco_commit(struct orinoco_private *priv)
1713{
1714 struct net_device *dev = priv->ndev;
1715 hermes_t *hw = &priv->hw;
1716 int err;
1717
1718 if (priv->broken_disableport) {
1719 schedule_work(&priv->reset_work);
1720 return 0;
1721 }
1722
1723 err = hermes_disable_port(hw, 0);
1724 if (err) {
1725 printk(KERN_WARNING "%s: Unable to disable port "
1726 "while reconfiguring card\n", dev->name);
1727 priv->broken_disableport = 1;
1728 goto out;
1729 }
1730
1731 err = __orinoco_commit(priv);
1732 if (err) {
1733 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
1734 dev->name);
1735 goto out;
1736 }
1737
1738 err = hermes_enable_port(hw, 0);
1739 if (err) {
1740 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
1741 dev->name);
1742 goto out;
1743 }
1744
1745 out:
1746 if (err) {
1747 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
1748 schedule_work(&priv->reset_work);
1749 err = 0;
1750 }
1751 return err;
1752}
1753
1923/********************************************************************/ 1754/********************************************************************/
1924/* Interrupt handler */ 1755/* Interrupt handler */
1925/********************************************************************/ 1756/********************************************************************/