diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-09-12 11:14:33 -0400 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-09-12 11:14:33 -0400 |
commit | 25a765b7f05cb8460fa01b54568894b20e184862 (patch) | |
tree | 0b56db57b4d9f912393ab303c269e0fe6cdf8635 /drivers/staging/csr/inet.c | |
parent | 9d2be9287107695708e6aae5105a8a518a6cb4d0 (diff) | |
parent | 64282278989d5b0398dcb3ba7904cb00c621dc35 (diff) |
Merge branch 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip into stable/for-linus-3.7
* 'x86/platform' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (9690 commits)
x86: Document x86_init.paging.pagetable_init()
x86: xen: Cleanup and remove x86_init.paging.pagetable_setup_done()
x86: Move paging_init() call to x86_init.paging.pagetable_init()
x86: Rename pagetable_setup_start() to pagetable_init()
x86: Remove base argument from x86_init.paging.pagetable_setup_start
Linux 3.6-rc5
HID: tpkbd: work even if the new Lenovo Keyboard driver is not configured
Remove user-triggerable BUG from mpol_to_str
xen/pciback: Fix proper FLR steps.
uml: fix compile error in deliver_alarm()
dj: memory scribble in logi_dj
Fix order of arguments to compat_put_time[spec|val]
xen: Use correct masking in xen_swiotlb_alloc_coherent.
xen: fix logical error in tlb flushing
xen/p2m: Fix one-off error in checking the P2M tree directory.
powerpc: Don't use __put_user() in patch_instruction
powerpc: Make sure IPI handlers see data written by IPI senders
powerpc: Restore correct DSCR in context switch
powerpc: Fix DSCR inheritance in copy_thread()
powerpc: Keep thread.dscr and thread.dscr_inherit in sync
...
Diffstat (limited to 'drivers/staging/csr/inet.c')
-rw-r--r-- | drivers/staging/csr/inet.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/drivers/staging/csr/inet.c b/drivers/staging/csr/inet.c new file mode 100644 index 000000000000..b4acb54ecc62 --- /dev/null +++ b/drivers/staging/csr/inet.c @@ -0,0 +1,106 @@ +/* + * --------------------------------------------------------------------------- + * FILE: inet.c + * + * PURPOSE: + * Routines related to IP address changes. + * Optional part of the porting exercise. It uses system network + * handlers to obtain the UniFi IP address and pass it to the SME + * using the unifi_sys_ip_configured_ind(). + * + * Copyright (C) 2008-2009 Cambridge Silicon Radio Ltd. + * + * Refer to LICENSE.txt included with this source code for details on + * the license terms. + * + * --------------------------------------------------------------------------- + */ +#include <linux/inetdevice.h> +#include <linux/notifier.h> + +#include "unifi_priv.h" +#include "csr_wifi_hip_conversions.h" + +/* + * The inet notifier is global and not per-netdev. To avoid having a + * notifier registered when there are no unifi devices present, it's + * registered after the first unifi network device is registered, and + * unregistered when the last unifi network device is unregistered. + */ + +static atomic_t inet_notif_refs = ATOMIC_INIT(0); + +static int uf_inetaddr_event(struct notifier_block *notif, unsigned long event, void *ifa) +{ + struct net_device *ndev; + unifi_priv_t *priv; + struct in_ifaddr *if_addr; + netInterface_priv_t *InterfacePriv = (netInterface_priv_t *)NULL; + + if (!ifa || !((struct in_ifaddr *)ifa)->ifa_dev) { + unifi_trace(NULL, UDBG1, "uf_inetaddr_event (%lu) ifa=%p\n", event, ifa); + return NOTIFY_DONE; + } + + ndev = ((struct in_ifaddr *)ifa)->ifa_dev->dev; + InterfacePriv = (netInterface_priv_t*) netdev_priv(ndev); + + /* As the notifier is global, the call may be for a non-UniFi netdev. + * Therefore check the netdev_priv to make sure it's a known UniFi one. + */ + if (uf_find_netdev_priv(InterfacePriv) == -1) { + unifi_trace(NULL, UDBG1, "uf_inetaddr_event (%lu) ndev=%p, other netdev_priv=%p\n", + event, ndev, InterfacePriv); + return NOTIFY_DONE; + } + + if (!InterfacePriv->privPtr) { + unifi_error(NULL, "uf_inetaddr_event null priv (%lu) ndev=%p, InterfacePriv=%p\n", + event, ndev, InterfacePriv); + return NOTIFY_DONE; + } + + priv = InterfacePriv->privPtr; + if_addr = (struct in_ifaddr *)ifa; + + /* If this event is for a UniFi device, notify the SME that an IP + * address has been added or removed. */ + if (uf_find_priv(priv) != -1) { + switch (event) { + case NETDEV_UP: + unifi_info(priv, "IP address assigned for %s\n", priv->netdev[InterfacePriv->InterfaceTag]->name); + priv->sta_ip_address = if_addr->ifa_address; +#ifdef CSR_SUPPORT_WEXT + sme_mgt_packet_filter_set(priv); +#endif + break; + case NETDEV_DOWN: + unifi_info(priv, "IP address removed for %s\n", priv->netdev[InterfacePriv->InterfaceTag]->name); + priv->sta_ip_address = 0xFFFFFFFF; +#ifdef CSR_SUPPORT_WEXT + sme_mgt_packet_filter_set(priv); +#endif + break; + } + } + + return NOTIFY_DONE; +} + +static struct notifier_block uf_inetaddr_notifier = { + .notifier_call = uf_inetaddr_event, +}; + +void uf_register_inet_notifier(void) +{ + if (atomic_inc_return(&inet_notif_refs) == 1) { + register_inetaddr_notifier(&uf_inetaddr_notifier); + } +} + +void uf_unregister_inet_notifier(void) +{ + if (atomic_dec_return(&inet_notif_refs) == 0) { + unregister_inetaddr_notifier(&uf_inetaddr_notifier); + } +} |