1 /* 2 * Copyright (c) 2012 Qualcomm Atheros, Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <linux/module.h> 18 #include <linux/netdevice.h> 19 #include <linux/etherdevice.h> 20 #include <linux/slab.h> 21 22 #include "wil6210.h" 23 24 static int wil_open(struct net_device *ndev) 25 { 26 struct wil6210_priv *wil = ndev_to_wil(ndev); 27 28 return wil_up(wil); 29 } 30 31 static int wil_stop(struct net_device *ndev) 32 { 33 struct wil6210_priv *wil = ndev_to_wil(ndev); 34 35 return wil_down(wil); 36 } 37 38 static const struct net_device_ops wil_netdev_ops = { 39 .ndo_open = wil_open, 40 .ndo_stop = wil_stop, 41 .ndo_start_xmit = wil_start_xmit, 42 .ndo_set_mac_address = eth_mac_addr, 43 .ndo_validate_addr = eth_validate_addr, 44 }; 45 46 void *wil_if_alloc(struct device *dev, void __iomem *csr) 47 { 48 struct net_device *ndev; 49 struct wireless_dev *wdev; 50 struct wil6210_priv *wil; 51 struct ieee80211_channel *ch; 52 int rc = 0; 53 54 wdev = wil_cfg80211_init(dev); 55 if (IS_ERR(wdev)) { 56 dev_err(dev, "wil_cfg80211_init failed\n"); 57 return wdev; 58 } 59 60 wil = wdev_to_wil(wdev); 61 wil->csr = csr; 62 wil->wdev = wdev; 63 64 rc = wil_priv_init(wil); 65 if (rc) { 66 dev_err(dev, "wil_priv_init failed\n"); 67 goto out_wdev; 68 } 69 70 wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ 71 /* default monitor channel */ 72 ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; 73 cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); 74 75 ndev = alloc_netdev(0, "wlan%d", ether_setup); 76 if (!ndev) { 77 dev_err(dev, "alloc_netdev_mqs failed\n"); 78 rc = -ENOMEM; 79 goto out_priv; 80 } 81 82 ndev->netdev_ops = &wil_netdev_ops; 83 ndev->ieee80211_ptr = wdev; 84 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); 85 wdev->netdev = ndev; 86 87 wil_link_off(wil); 88 89 return wil; 90 91 out_priv: 92 wil_priv_deinit(wil); 93 94 out_wdev: 95 wil_wdev_free(wil); 96 97 return ERR_PTR(rc); 98 } 99 100 void wil_if_free(struct wil6210_priv *wil) 101 { 102 struct net_device *ndev = wil_to_ndev(wil); 103 if (!ndev) 104 return; 105 106 free_netdev(ndev); 107 wil_priv_deinit(wil); 108 wil_wdev_free(wil); 109 } 110 111 int wil_if_add(struct wil6210_priv *wil) 112 { 113 struct net_device *ndev = wil_to_ndev(wil); 114 int rc; 115 116 rc = register_netdev(ndev); 117 if (rc < 0) { 118 dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); 119 return rc; 120 } 121 122 wil_link_off(wil); 123 124 return 0; 125 } 126 127 void wil_if_remove(struct wil6210_priv *wil) 128 { 129 struct net_device *ndev = wil_to_ndev(wil); 130 131 unregister_netdev(ndev); 132 } 133