summaryrefslogtreecommitdiff
path: root/drivers/staging/csr/inet.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-19 23:15:42 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-06-19 23:37:01 (GMT)
commit635d2b00e5070378e7bf812acf47fb135c6ab928 (patch)
tree7048a0a511f3d221aa2dfe40aa3a401991f1b175 /drivers/staging/csr/inet.c
parent15a4bc17b7f4e85cb019e683f14e834078ec2208 (diff)
downloadlinux-fsl-qoriq-635d2b00e5070378e7bf812acf47fb135c6ab928.tar.xz
Staging: add CSR wifi module
This consists of two modules, the driver, and a "helper" module that is just a wrapper around common kernel functions. The wrapper module will be removed soon, but for now it's needed. These files were based on the csr-linux-wifi-5.0.3-oss.tar.gz package provided by CSR and Blue Giga, and is covered under the license specified in the LICENSE.txt file (basically dual BSD and GPLv2). The files were flattened out of the deep directory mess they were originally in, and a few EXPORT_SYMBOL_GPL() were added in order for everything to link properly with the helper module setup. Cc: Mikko Virkkilä <mikko.virkkila@bluegiga.com> Cc: Lauri Hintsala <Lauri.Hintsala@bluegiga.com> Cc: Riku Mettälä <riku.mettala@bluegiga.com> Cc: Veli-Pekka Peltola <veli-pekka.peltola@bluegiga.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/csr/inet.c')
-rw-r--r--drivers/staging/csr/inet.c106
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 0000000..b4acb54
--- /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);
+ }
+}