aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-06-20 04:16:40 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-20 04:16:40 -0400
commitc3da63f35773b04e885c5659e560d5c521d2682e (patch)
tree5e876e7587f299cadce0b53bfaf912fb28d8283d /net
parent73e42897e8e5619eacb787d2ce69be12f47cfc21 (diff)
parenta97f4424fb4cddecf9b13c9b0e3f79924b624a7f (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/rfkill/core.c56
-rw-r--r--net/wireless/nl80211.c95
2 files changed, 118 insertions, 33 deletions
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 4e68ab439d5d..79693fe2001e 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -56,7 +56,6 @@ struct rfkill {
56 u32 idx; 56 u32 idx;
57 57
58 bool registered; 58 bool registered;
59 bool suspended;
60 bool persistent; 59 bool persistent;
61 60
62 const struct rfkill_ops *ops; 61 const struct rfkill_ops *ops;
@@ -224,7 +223,7 @@ static void rfkill_send_events(struct rfkill *rfkill, enum rfkill_operation op)
224 223
225static void rfkill_event(struct rfkill *rfkill) 224static void rfkill_event(struct rfkill *rfkill)
226{ 225{
227 if (!rfkill->registered || rfkill->suspended) 226 if (!rfkill->registered)
228 return; 227 return;
229 228
230 kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE); 229 kobject_uevent(&rfkill->dev.kobj, KOBJ_CHANGE);
@@ -270,6 +269,9 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
270 unsigned long flags; 269 unsigned long flags;
271 int err; 270 int err;
272 271
272 if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP))
273 return;
274
273 /* 275 /*
274 * Some platforms (...!) generate input events which affect the 276 * Some platforms (...!) generate input events which affect the
275 * _hard_ kill state -- whenever something tries to change the 277 * _hard_ kill state -- whenever something tries to change the
@@ -292,9 +294,6 @@ static void rfkill_set_block(struct rfkill *rfkill, bool blocked)
292 rfkill->state |= RFKILL_BLOCK_SW_SETCALL; 294 rfkill->state |= RFKILL_BLOCK_SW_SETCALL;
293 spin_unlock_irqrestore(&rfkill->lock, flags); 295 spin_unlock_irqrestore(&rfkill->lock, flags);
294 296
295 if (unlikely(rfkill->dev.power.power_state.event & PM_EVENT_SLEEP))
296 return;
297
298 err = rfkill->ops->set_block(rfkill->data, blocked); 297 err = rfkill->ops->set_block(rfkill->data, blocked);
299 298
300 spin_lock_irqsave(&rfkill->lock, flags); 299 spin_lock_irqsave(&rfkill->lock, flags);
@@ -508,19 +507,32 @@ bool rfkill_set_sw_state(struct rfkill *rfkill, bool blocked)
508 blocked = blocked || hwblock; 507 blocked = blocked || hwblock;
509 spin_unlock_irqrestore(&rfkill->lock, flags); 508 spin_unlock_irqrestore(&rfkill->lock, flags);
510 509
511 if (!rfkill->registered) { 510 if (!rfkill->registered)
512 rfkill->persistent = true; 511 return blocked;
513 } else {
514 if (prev != blocked && !hwblock)
515 schedule_work(&rfkill->uevent_work);
516 512
517 rfkill_led_trigger_event(rfkill); 513 if (prev != blocked && !hwblock)
518 } 514 schedule_work(&rfkill->uevent_work);
515
516 rfkill_led_trigger_event(rfkill);
519 517
520 return blocked; 518 return blocked;
521} 519}
522EXPORT_SYMBOL(rfkill_set_sw_state); 520EXPORT_SYMBOL(rfkill_set_sw_state);
523 521
522void rfkill_init_sw_state(struct rfkill *rfkill, bool blocked)
523{
524 unsigned long flags;
525
526 BUG_ON(!rfkill);
527 BUG_ON(rfkill->registered);
528
529 spin_lock_irqsave(&rfkill->lock, flags);
530 __rfkill_set_sw_state(rfkill, blocked);
531 rfkill->persistent = true;
532 spin_unlock_irqrestore(&rfkill->lock, flags);
533}
534EXPORT_SYMBOL(rfkill_init_sw_state);
535
524void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw) 536void rfkill_set_states(struct rfkill *rfkill, bool sw, bool hw)
525{ 537{
526 unsigned long flags; 538 unsigned long flags;
@@ -598,6 +610,15 @@ static ssize_t rfkill_idx_show(struct device *dev,
598 return sprintf(buf, "%d\n", rfkill->idx); 610 return sprintf(buf, "%d\n", rfkill->idx);
599} 611}
600 612
613static ssize_t rfkill_persistent_show(struct device *dev,
614 struct device_attribute *attr,
615 char *buf)
616{
617 struct rfkill *rfkill = to_rfkill(dev);
618
619 return sprintf(buf, "%d\n", rfkill->persistent);
620}
621
601static u8 user_state_from_blocked(unsigned long state) 622static u8 user_state_from_blocked(unsigned long state)
602{ 623{
603 if (state & RFKILL_BLOCK_HW) 624 if (state & RFKILL_BLOCK_HW)
@@ -656,6 +677,7 @@ static struct device_attribute rfkill_dev_attrs[] = {
656 __ATTR(name, S_IRUGO, rfkill_name_show, NULL), 677 __ATTR(name, S_IRUGO, rfkill_name_show, NULL),
657 __ATTR(type, S_IRUGO, rfkill_type_show, NULL), 678 __ATTR(type, S_IRUGO, rfkill_type_show, NULL),
658 __ATTR(index, S_IRUGO, rfkill_idx_show, NULL), 679 __ATTR(index, S_IRUGO, rfkill_idx_show, NULL),
680 __ATTR(persistent, S_IRUGO, rfkill_persistent_show, NULL),
659 __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store), 681 __ATTR(state, S_IRUGO|S_IWUSR, rfkill_state_show, rfkill_state_store),
660 __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store), 682 __ATTR(claim, S_IRUGO|S_IWUSR, rfkill_claim_show, rfkill_claim_store),
661 __ATTR_NULL 683 __ATTR_NULL
@@ -718,8 +740,6 @@ static int rfkill_suspend(struct device *dev, pm_message_t state)
718 740
719 rfkill_pause_polling(rfkill); 741 rfkill_pause_polling(rfkill);
720 742
721 rfkill->suspended = true;
722
723 return 0; 743 return 0;
724} 744}
725 745
@@ -728,10 +748,10 @@ static int rfkill_resume(struct device *dev)
728 struct rfkill *rfkill = to_rfkill(dev); 748 struct rfkill *rfkill = to_rfkill(dev);
729 bool cur; 749 bool cur;
730 750
731 cur = !!(rfkill->state & RFKILL_BLOCK_SW); 751 if (!rfkill->persistent) {
732 rfkill_set_block(rfkill, cur); 752 cur = !!(rfkill->state & RFKILL_BLOCK_SW);
733 753 rfkill_set_block(rfkill, cur);
734 rfkill->suspended = false; 754 }
735 755
736 rfkill_resume_polling(rfkill); 756 rfkill_resume_polling(rfkill);
737 757
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 24168560ebae..241bddd0b4f1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1687,13 +1687,52 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
1687 if (err) 1687 if (err)
1688 goto out_rtnl; 1688 goto out_rtnl;
1689 1689
1690 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 1690 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1691 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { 1691 if (err)
1692 err = -EINVAL;
1693 goto out; 1692 goto out;
1693
1694 /* validate settings */
1695 err = 0;
1696
1697 switch (dev->ieee80211_ptr->iftype) {
1698 case NL80211_IFTYPE_AP:
1699 case NL80211_IFTYPE_AP_VLAN:
1700 /* disallow mesh-specific things */
1701 if (params.plink_action)
1702 err = -EINVAL;
1703 break;
1704 case NL80211_IFTYPE_STATION:
1705 /* disallow everything but AUTHORIZED flag */
1706 if (params.plink_action)
1707 err = -EINVAL;
1708 if (params.vlan)
1709 err = -EINVAL;
1710 if (params.supported_rates)
1711 err = -EINVAL;
1712 if (params.ht_capa)
1713 err = -EINVAL;
1714 if (params.listen_interval >= 0)
1715 err = -EINVAL;
1716 if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
1717 err = -EINVAL;
1718 break;
1719 case NL80211_IFTYPE_MESH_POINT:
1720 /* disallow things mesh doesn't support */
1721 if (params.vlan)
1722 err = -EINVAL;
1723 if (params.ht_capa)
1724 err = -EINVAL;
1725 if (params.listen_interval >= 0)
1726 err = -EINVAL;
1727 if (params.supported_rates)
1728 err = -EINVAL;
1729 if (params.sta_flags_mask)
1730 err = -EINVAL;
1731 break;
1732 default:
1733 err = -EINVAL;
1694 } 1734 }
1695 1735
1696 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1697 if (err) 1736 if (err)
1698 goto out; 1737 goto out;
1699 1738
@@ -1728,9 +1767,6 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1728 if (!info->attrs[NL80211_ATTR_MAC]) 1767 if (!info->attrs[NL80211_ATTR_MAC])
1729 return -EINVAL; 1768 return -EINVAL;
1730 1769
1731 if (!info->attrs[NL80211_ATTR_STA_AID])
1732 return -EINVAL;
1733
1734 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) 1770 if (!info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL])
1735 return -EINVAL; 1771 return -EINVAL;
1736 1772
@@ -1745,9 +1781,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1745 params.listen_interval = 1781 params.listen_interval =
1746 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); 1782 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);
1747 1783
1748 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); 1784 if (info->attrs[NL80211_ATTR_STA_AID]) {
1749 if (!params.aid || params.aid > IEEE80211_MAX_AID) 1785 params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);
1750 return -EINVAL; 1786 if (!params.aid || params.aid > IEEE80211_MAX_AID)
1787 return -EINVAL;
1788 }
1751 1789
1752 if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) 1790 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])
1753 params.ht_capa = 1791 params.ht_capa =
@@ -1762,13 +1800,39 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
1762 if (err) 1800 if (err)
1763 goto out_rtnl; 1801 goto out_rtnl;
1764 1802
1765 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 1803 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1766 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { 1804 if (err)
1767 err = -EINVAL;
1768 goto out; 1805 goto out;
1806
1807 /* validate settings */
1808 err = 0;
1809
1810 switch (dev->ieee80211_ptr->iftype) {
1811 case NL80211_IFTYPE_AP:
1812 case NL80211_IFTYPE_AP_VLAN:
1813 /* all ok but must have AID */
1814 if (!params.aid)
1815 err = -EINVAL;
1816 break;
1817 case NL80211_IFTYPE_MESH_POINT:
1818 /* disallow things mesh doesn't support */
1819 if (params.vlan)
1820 err = -EINVAL;
1821 if (params.aid)
1822 err = -EINVAL;
1823 if (params.ht_capa)
1824 err = -EINVAL;
1825 if (params.listen_interval >= 0)
1826 err = -EINVAL;
1827 if (params.supported_rates)
1828 err = -EINVAL;
1829 if (params.sta_flags_mask)
1830 err = -EINVAL;
1831 break;
1832 default:
1833 err = -EINVAL;
1769 } 1834 }
1770 1835
1771 err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, &params.vlan);
1772 if (err) 1836 if (err)
1773 goto out; 1837 goto out;
1774 1838
@@ -1812,7 +1876,8 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
1812 goto out_rtnl; 1876 goto out_rtnl;
1813 1877
1814 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 1878 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
1815 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN) { 1879 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
1880 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT) {
1816 err = -EINVAL; 1881 err = -EINVAL;
1817 goto out; 1882 goto out;
1818 } 1883 }