static void zd_op_configure_filter(struct ieee80211_hw *hw, unsigned int changed_flags, unsigned int *new_flags, int mc_count, struct dev_mc_list *mclist) { struct zd_mc_hash hash; struct zd_mac *mac = zd_hw_mac(hw); unsigned long flags; int i; /* Only deal with supported flags */ changed_flags &= SUPPORTED_FIF_FLAGS; *new_flags &= SUPPORTED_FIF_FLAGS; /* changed_flags is always populated but this driver * doesn't support all FIF flags so its possible we don't * need to do anything */ if (!changed_flags) return; if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) { zd_mc_add_all(&hash); } else { DECLARE_MAC_BUF(macbuf); zd_mc_clear(&hash); for (i = 0; i < mc_count; i++) { if (!mclist) break; dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n", print_mac(macbuf, mclist->dmi_addr)); zd_mc_add_addr(&hash, mclist->dmi_addr); mclist = mclist->next; } } spin_lock_irqsave(&mac->lock, flags); mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); mac->multicast_hash = hash; spin_unlock_irqrestore(&mac->lock, flags); queue_work(zd_workqueue, &mac->set_multicast_hash_work); if (changed_flags & FIF_CONTROL) queue_work(zd_workqueue, &mac->set_rx_filter_work); /* no handling required for FIF_OTHER_BSS as we don't currently * do BSSID filtering */ /* FIXME: in future it would be nice to enable the probe response * filter (so that the driver doesn't see them) until * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd * have to schedule work to enable prbresp reception, which might * happen too late. For now we'll just listen and forward them all the * time. */ }
void zd_mac_set_multicast_list(struct net_device *dev) { struct zd_mc_hash hash; struct zd_mac *mac = zd_netdev_mac(dev); struct dev_mc_list *mc; unsigned long flags; if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI)) { zd_mc_add_all(&hash); } else { zd_mc_clear(&hash); for (mc = dev->mc_list; mc; mc = mc->next) { dev_dbg_f(zd_mac_dev(mac), "mc addr " MAC_FMT "\n", MAC_ARG(mc->dmi_addr)); zd_mc_add_addr(&hash, mc->dmi_addr); } } spin_lock_irqsave(&mac->lock, flags); mac->multicast_hash = hash; spin_unlock_irqrestore(&mac->lock, flags); queue_work(zd_workqueue, &mac->set_multicast_hash_work); }
static int set_mc_hash(struct zd_mac *mac) { struct zd_mc_hash hash; zd_mc_clear(&hash); return zd_chip_set_multicast_hash(&mac->chip, &hash); }