aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mwl8k.c107
1 files changed, 39 insertions, 68 deletions
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index a40434b5572b..a961b698c691 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -1613,38 +1613,39 @@ struct mwl8k_cmd_mac_multicast_adr {
1613 1613
1614#define MWL8K_ENABLE_RX_MULTICAST 0x000F 1614#define MWL8K_ENABLE_RX_MULTICAST 0x000F
1615 1615
1616static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, 1616static struct mwl8k_cmd_pkt *
1617 int mc_count, 1617__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
1618 struct dev_addr_list *mclist) 1618 int mc_count, struct dev_addr_list *mclist)
1619{ 1619{
1620 struct mwl8k_priv *priv = hw->priv;
1620 struct mwl8k_cmd_mac_multicast_adr *cmd; 1621 struct mwl8k_cmd_mac_multicast_adr *cmd;
1621 int index = 0; 1622 int size;
1622 int rc; 1623 int i;
1623 int size = sizeof(*cmd) + mc_count * ETH_ALEN; 1624
1625 if (mc_count > priv->num_mcaddrs)
1626 mc_count = priv->num_mcaddrs;
1627
1628 size = sizeof(*cmd) + mc_count * ETH_ALEN;
1624 1629
1625 cmd = kzalloc(size, GFP_KERNEL); 1630 cmd = kzalloc(size, GFP_ATOMIC);
1626 if (cmd == NULL) 1631 if (cmd == NULL)
1627 return -ENOMEM; 1632 return NULL;
1628 1633
1629 cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); 1634 cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
1630 cmd->header.length = cpu_to_le16(size); 1635 cmd->header.length = cpu_to_le16(size);
1631 cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); 1636 cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
1632 cmd->numaddr = cpu_to_le16(mc_count); 1637 cmd->numaddr = cpu_to_le16(mc_count);
1633 1638
1634 while (index < mc_count && mclist) { 1639 for (i = 0; i < mc_count && mclist; i++) {
1635 if (mclist->da_addrlen != ETH_ALEN) { 1640 if (mclist->da_addrlen != ETH_ALEN) {
1636 rc = -EINVAL; 1641 kfree(cmd);
1637 goto mwl8k_cmd_mac_multicast_adr_exit; 1642 return NULL;
1638 } 1643 }
1639 memcpy(cmd->addr[index++], mclist->da_addr, ETH_ALEN); 1644 memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN);
1640 mclist = mclist->next; 1645 mclist = mclist->next;
1641 } 1646 }
1642 1647
1643 rc = mwl8k_post_cmd(hw, &cmd->header); 1648 return &cmd->header;
1644
1645mwl8k_cmd_mac_multicast_adr_exit:
1646 kfree(cmd);
1647 return rc;
1648} 1649}
1649 1650
1650/* 1651/*
@@ -3091,12 +3092,21 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw,
3091 printk(KERN_ERR "%s() timed out\n", __func__); 3092 printk(KERN_ERR "%s() timed out\n", __func__);
3092} 3093}
3093 3094
3095static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw,
3096 int mc_count, struct dev_addr_list *mclist)
3097{
3098 struct mwl8k_cmd_pkt *cmd;
3099
3100 cmd = __mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
3101
3102 return (unsigned long)cmd;
3103}
3104
3094struct mwl8k_configure_filter_worker { 3105struct mwl8k_configure_filter_worker {
3095 struct mwl8k_work_struct header; 3106 struct mwl8k_work_struct header;
3096 unsigned int changed_flags; 3107 unsigned int changed_flags;
3097 unsigned int *total_flags; 3108 unsigned int total_flags;
3098 int mc_count; 3109 struct mwl8k_cmd_pkt *multicast_adr_cmd;
3099 struct dev_addr_list *mclist;
3100}; 3110};
3101 3111
3102#define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC 3112#define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC
@@ -3105,18 +3115,12 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
3105{ 3115{
3106 struct mwl8k_configure_filter_worker *worker = 3116 struct mwl8k_configure_filter_worker *worker =
3107 (struct mwl8k_configure_filter_worker *)wt; 3117 (struct mwl8k_configure_filter_worker *)wt;
3108
3109 struct ieee80211_hw *hw = worker->header.hw; 3118 struct ieee80211_hw *hw = worker->header.hw;
3110 unsigned int changed_flags = worker->changed_flags;
3111 unsigned int *total_flags = worker->total_flags;
3112 int mc_count = worker->mc_count;
3113 struct dev_addr_list *mclist = worker->mclist;
3114
3115 struct mwl8k_priv *priv = hw->priv; 3119 struct mwl8k_priv *priv = hw->priv;
3116 int rc = 0; 3120 int rc = 0;
3117 3121
3118 if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { 3122 if (worker->changed_flags & FIF_BCN_PRBRESP_PROMISC) {
3119 if (*total_flags & FIF_BCN_PRBRESP_PROMISC) 3123 if (worker->total_flags & FIF_BCN_PRBRESP_PROMISC)
3120 rc = mwl8k_cmd_set_pre_scan(hw); 3124 rc = mwl8k_cmd_set_pre_scan(hw);
3121 else { 3125 else {
3122 u8 *bssid; 3126 u8 *bssid;
@@ -3129,54 +3133,20 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt)
3129 } 3133 }
3130 } 3134 }
3131 3135
3132 if (rc) 3136 if (!rc && worker->multicast_adr_cmd != NULL)
3133 goto mwl8k_configure_filter_exit; 3137 rc = mwl8k_post_cmd(hw, worker->multicast_adr_cmd);
3134 if (mc_count) { 3138 kfree(worker->multicast_adr_cmd);
3135 if (mc_count > priv->num_mcaddrs)
3136 mc_count = priv->num_mcaddrs;
3137
3138 rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
3139 if (rc)
3140 printk(KERN_ERR
3141 "%s()Error setting multicast addresses\n",
3142 __func__);
3143 }
3144 3139
3145mwl8k_configure_filter_exit:
3146 return rc; 3140 return rc;
3147} 3141}
3148 3142
3149static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw,
3150 int mc_count, struct dev_addr_list *mclist)
3151{
3152 struct mwl8k_configure_filter_worker *worker;
3153
3154 worker = kzalloc(sizeof(*worker), GFP_ATOMIC);
3155
3156 if (!worker)
3157 return 0;
3158
3159 /*
3160 * XXX: This is _HORRIBLY_ broken!!
3161 *
3162 * No locking, the mclist pointer might be invalid as soon as this
3163 * function returns, something in the list might be invalidated
3164 * once we get to the worker, etc...
3165 */
3166 worker->mc_count = mc_count;
3167 worker->mclist = mclist;
3168
3169 return (u64)worker;
3170}
3171
3172static void mwl8k_configure_filter(struct ieee80211_hw *hw, 3143static void mwl8k_configure_filter(struct ieee80211_hw *hw,
3173 unsigned int changed_flags, 3144 unsigned int changed_flags,
3174 unsigned int *total_flags, 3145 unsigned int *total_flags,
3175 u64 multicast) 3146 u64 multicast)
3176{ 3147{
3177
3178 struct mwl8k_configure_filter_worker *worker = (void *)multicast;
3179 struct mwl8k_priv *priv = hw->priv; 3148 struct mwl8k_priv *priv = hw->priv;
3149 struct mwl8k_configure_filter_worker *worker;
3180 3150
3181 /* Clear unsupported feature flags */ 3151 /* Clear unsupported feature flags */
3182 *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; 3152 *total_flags &= MWL8K_SUPPORTED_IF_FLAGS;
@@ -3184,12 +3154,13 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
3184 if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS)) 3154 if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS))
3185 return; 3155 return;
3186 3156
3157 worker = kzalloc(sizeof(*worker), GFP_ATOMIC);
3187 if (worker == NULL) 3158 if (worker == NULL)
3188 return; 3159 return;
3189 3160
3190 worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY;
3191 worker->changed_flags = changed_flags; 3161 worker->changed_flags = changed_flags;
3192 worker->total_flags = total_flags; 3162 worker->total_flags = *total_flags;
3163 worker->multicast_adr_cmd = (void *)(unsigned long)multicast;
3193 3164
3194 mwl8k_queue_work(hw, &worker->header, priv->config_wq, 3165 mwl8k_queue_work(hw, &worker->header, priv->config_wq,
3195 mwl8k_configure_filter_wt); 3166 mwl8k_configure_filter_wt);