Lines Matching +full:firmware +full:- +full:initialized

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries.
9 #include <linux/firmware.h>
22 #define WILC1000_FW_PREFIX "atmel/wilc1000_wifi_firmware-"
28 #define WILC3000_FW_PREFIX "atmel/wilc3000_wifi_firmware-"
36 if (wilc->close) { in isr_uh_routine()
47 if (wilc->close) { in isr_bh_routine()
60 struct wilc *wl = vif->wilc; in init_irq()
63 ret = request_threaded_irq(wl->dev_irq_num, isr_uh_routine, in init_irq()
66 dev->name, wl); in init_irq()
71 netdev_dbg(dev, "IRQ request succeeded IRQ-NUM= %d\n", wl->dev_irq_num); in init_irq()
79 struct wilc *wilc = vif->wilc; in deinit_irq()
82 if (wilc->dev_irq_num) in deinit_irq()
83 free_irq(wilc->dev_irq_num, wilc); in deinit_irq()
91 if (wilc->mac_status == WILC_MAC_STATUS_INIT) { in wilc_mac_indicate()
92 wilc->mac_status = status; in wilc_mac_indicate()
93 complete(&wilc->sync_event); in wilc_mac_indicate()
95 wilc->mac_status = status; in wilc_mac_indicate()
106 if (vif->iftype == WILC_STATION_MODE) in get_if_handler()
107 if (ether_addr_equal_unaligned(h->addr2, vif->bssid)) { in get_if_handler()
108 ndev = vif->ndev; in get_if_handler()
111 if (vif->iftype == WILC_AP_MODE) in get_if_handler()
112 if (ether_addr_equal_unaligned(h->addr1, vif->bssid)) { in get_if_handler()
113 ndev = vif->ndev; in get_if_handler()
127 ether_addr_copy(vif->bssid, bssid); in wilc_wlan_set_bssid()
129 eth_zero_addr(vif->bssid); in wilc_wlan_set_bssid()
131 vif->iftype = mode; in wilc_wlan_set_bssid()
140 srcu_idx = srcu_read_lock(&wilc->srcu); in wilc_wlan_get_num_conn_ifcs()
142 if (!is_zero_ether_addr(vif->bssid)) in wilc_wlan_get_num_conn_ifcs()
145 srcu_read_unlock(&wilc->srcu, srcu_idx); in wilc_wlan_get_num_conn_ifcs()
154 srcu_idx = srcu_read_lock(&wl->srcu); in wilc_wake_tx_queues()
156 if (ifc->mac_opened && netif_queue_stopped(ifc->ndev)) in wilc_wake_tx_queues()
157 netif_wake_queue(ifc->ndev); in wilc_wake_tx_queues()
159 srcu_read_unlock(&wl->srcu, srcu_idx); in wilc_wake_tx_queues()
168 complete(&wl->txq_thread_started); in wilc_txq_task()
170 if (wait_for_completion_interruptible(&wl->txq_event)) in wilc_txq_task()
172 if (wl->close) { in wilc_txq_task()
173 complete(&wl->txq_thread_started); in wilc_txq_task()
195 } while (!wl->close); in wilc_txq_task()
203 struct wilc *wilc = vif->wilc; in wilc_wlan_get_firmware()
204 const struct firmware *wilc_fw; in wilc_wlan_get_firmware()
205 char *firmware; in wilc_wlan_get_firmware() local
208 if (is_wilc1000(wilc->chipid)) in wilc_wlan_get_firmware()
209 firmware = WILC1000_FW(WILC1000_API_VER); in wilc_wlan_get_firmware()
210 else if (is_wilc3000(wilc->chipid)) in wilc_wlan_get_firmware()
211 firmware = WILC3000_FW(WILC3000_API_VER); in wilc_wlan_get_firmware()
213 return -EINVAL; in wilc_wlan_get_firmware()
215 netdev_info(dev, "WILC%d loading firmware [%s]\n", in wilc_wlan_get_firmware()
216 is_wilc1000(wilc->chipid) ? 1000 : 3000, in wilc_wlan_get_firmware()
217 firmware); in wilc_wlan_get_firmware()
219 ret = request_firmware(&wilc_fw, firmware, wilc->dev); in wilc_wlan_get_firmware()
221 netdev_err(dev, "%s - firmware not available\n", firmware); in wilc_wlan_get_firmware()
222 return -EINVAL; in wilc_wlan_get_firmware()
224 wilc->firmware = wilc_fw; in wilc_wlan_get_firmware()
232 struct wilc *wilc = vif->wilc; in wilc_start_firmware()
239 if (!wait_for_completion_timeout(&wilc->sync_event, in wilc_start_firmware()
241 return -ETIME; in wilc_start_firmware()
249 struct wilc *wilc = vif->wilc; in wilc_firmware_download()
252 if (!wilc->firmware) { in wilc_firmware_download()
253 netdev_err(dev, "Firmware buffer is NULL\n"); in wilc_firmware_download()
254 return -ENOBUFS; in wilc_firmware_download()
257 ret = wilc_wlan_firmware_download(wilc, wilc->firmware->data, in wilc_firmware_download()
258 wilc->firmware->size); in wilc_firmware_download()
262 release_firmware(wilc->firmware); in wilc_firmware_download()
263 wilc->firmware = NULL; in wilc_firmware_download()
272 struct wilc_priv *priv = &vif->priv; in wilc_init_fw_config()
278 netdev_dbg(dev, "Start configuring Firmware\n"); in wilc_init_fw_config()
279 hif_drv = (struct host_if_drv *)priv->hif_drv; in wilc_init_fw_config()
282 w = vif->iftype; in wilc_init_fw_config()
438 return -EINVAL; in wilc_init_fw_config()
444 struct wilc *wl = vif->wilc; in wlan_deinitialize_threads()
446 wl->close = 1; in wlan_deinitialize_threads()
448 complete(&wl->txq_event); in wlan_deinitialize_threads()
450 if (wl->txq_thread) { in wlan_deinitialize_threads()
451 kthread_stop(wl->txq_thread); in wlan_deinitialize_threads()
452 wl->txq_thread = NULL; in wlan_deinitialize_threads()
459 struct wilc *wl = vif->wilc; in wilc_wlan_deinitialize()
466 if (wl->initialized) { in wilc_wlan_deinitialize()
469 if (!wl->dev_irq_num && in wilc_wlan_deinitialize()
470 wl->hif_func->disable_interrupt) { in wilc_wlan_deinitialize()
471 mutex_lock(&wl->hif_cs); in wilc_wlan_deinitialize()
472 wl->hif_func->disable_interrupt(wl); in wilc_wlan_deinitialize()
473 mutex_unlock(&wl->hif_cs); in wilc_wlan_deinitialize()
475 complete(&wl->txq_event); in wilc_wlan_deinitialize()
483 wl->initialized = false; in wilc_wlan_deinitialize()
487 netdev_dbg(dev, "wilc1000 is not initialized\n"); in wilc_wlan_deinitialize()
494 struct wilc *wilc = vif->wilc; in wlan_initialize_threads()
496 wilc->txq_thread = kthread_run(wilc_txq_task, (void *)wilc, in wlan_initialize_threads()
497 "%s-tx", dev->name); in wlan_initialize_threads()
498 if (IS_ERR(wilc->txq_thread)) { in wlan_initialize_threads()
500 wilc->close = 1; in wlan_initialize_threads()
501 return PTR_ERR(wilc->txq_thread); in wlan_initialize_threads()
503 wait_for_completion(&wilc->txq_thread_started); in wlan_initialize_threads()
511 struct wilc *wl = vif->wilc; in wilc_wlan_initialize()
513 if (!wl->initialized) { in wilc_wlan_initialize()
514 wl->mac_status = WILC_MAC_STATUS_INIT; in wilc_wlan_initialize()
515 wl->close = 0; in wilc_wlan_initialize()
525 if (wl->dev_irq_num && init_irq(dev)) { in wilc_wlan_initialize()
526 ret = -EIO; in wilc_wlan_initialize()
530 if (!wl->dev_irq_num && in wilc_wlan_initialize()
531 wl->hif_func->enable_interrupt && in wilc_wlan_initialize()
532 wl->hif_func->enable_interrupt(wl)) { in wilc_wlan_initialize()
533 ret = -EIO; in wilc_wlan_initialize()
557 netdev_dbg(dev, "Firmware Ver = %s\n", firmware_ver); in wilc_wlan_initialize()
562 netdev_err(dev, "Failed to configure firmware\n"); in wilc_wlan_initialize()
565 wl->initialized = true; in wilc_wlan_initialize()
572 if (!wl->dev_irq_num && in wilc_wlan_initialize()
573 wl->hif_func->disable_interrupt) in wilc_wlan_initialize()
574 wl->hif_func->disable_interrupt(wl); in wilc_wlan_initialize()
576 if (wl->dev_irq_num) in wilc_wlan_initialize()
584 netdev_dbg(dev, "wilc1000 already initialized\n"); in wilc_wlan_initialize()
600 struct wilc *wl = vif->wilc; in wilc_mac_open()
604 if (!wl || !wl->dev) { in wilc_mac_open()
606 return -ENODEV; in wilc_mac_open()
621 wilc_set_operation_mode(vif, wilc_get_vif_idx(vif), vif->iftype, in wilc_mac_open()
622 vif->idx); in wilc_mac_open()
624 netdev_dbg(ndev, "Mac address: %pM\n", ndev->dev_addr); in wilc_mac_open()
625 ret = wilc_set_mac_address(vif, ndev->dev_addr); in wilc_mac_open()
629 if (!wl->open_ifcs) in wilc_mac_open()
634 mgmt_regs.interface_stypes = vif->mgmt_reg_stypes; in wilc_mac_open()
636 vif->mgmt_reg_stypes = 0; in wilc_mac_open()
637 wilc_update_mgmt_frame_registrations(vif->ndev->ieee80211_ptr->wiphy, in wilc_mac_open()
638 vif->ndev->ieee80211_ptr, in wilc_mac_open()
641 wl->open_ifcs++; in wilc_mac_open()
642 vif->mac_opened = 1; in wilc_mac_open()
650 return &vif->netstats; in mac_stats()
657 struct wilc *wilc = vif->wilc; in wilc_set_mac_addr()
663 if (!is_valid_ether_addr(addr->sa_data)) in wilc_set_mac_addr()
664 return -EADDRNOTAVAIL; in wilc_set_mac_addr()
666 if (!vif->mac_opened) { in wilc_set_mac_addr()
673 srcu_idx = srcu_read_lock(&wilc->srcu); in wilc_set_mac_addr()
676 if (ether_addr_equal(addr->sa_data, mac_addr)) { in wilc_set_mac_addr()
678 srcu_read_unlock(&wilc->srcu, srcu_idx); in wilc_set_mac_addr()
679 return -EADDRNOTAVAIL; in wilc_set_mac_addr()
681 srcu_read_unlock(&wilc->srcu, srcu_idx); in wilc_set_mac_addr()
685 srcu_read_unlock(&wilc->srcu, srcu_idx); in wilc_set_mac_addr()
687 result = wilc_set_mac_address(vif, addr->sa_data); in wilc_set_mac_addr()
703 if (dev->flags & IFF_PROMISC) in wilc_set_multicast_list()
706 if (dev->flags & IFF_ALLMULTI || in wilc_set_multicast_list()
707 dev->mc.count > WILC_MULTICAST_TABLE_SIZE) { in wilc_set_multicast_list()
712 if (dev->mc.count == 0) { in wilc_set_multicast_list()
717 mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_ATOMIC); in wilc_set_multicast_list()
724 memcpy(cur_mc, ha->addr, ETH_ALEN); in wilc_set_multicast_list()
730 if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list)) in wilc_set_multicast_list()
738 dev_kfree_skb(pv_data->skb); in wilc_tx_complete()
745 struct wilc *wilc = vif->wilc; in wilc_mac_xmit()
749 if (skb->dev != ndev) { in wilc_mac_xmit()
762 tx_data->buff = skb->data; in wilc_mac_xmit()
763 tx_data->size = skb->len; in wilc_mac_xmit()
764 tx_data->skb = skb; in wilc_mac_xmit()
766 vif->netstats.tx_packets++; in wilc_mac_xmit()
767 vif->netstats.tx_bytes += tx_data->size; in wilc_mac_xmit()
769 tx_data->buff, tx_data->size, in wilc_mac_xmit()
776 srcu_idx = srcu_read_lock(&wilc->srcu); in wilc_mac_xmit()
778 if (vif->mac_opened) in wilc_mac_xmit()
779 netif_stop_queue(vif->ndev); in wilc_mac_xmit()
781 srcu_read_unlock(&wilc->srcu, srcu_idx); in wilc_mac_xmit()
790 struct wilc *wl = vif->wilc; in wilc_mac_close()
794 if (wl->open_ifcs > 0) in wilc_mac_close()
795 wl->open_ifcs--; in wilc_mac_close()
799 if (vif->ndev) { in wilc_mac_close()
800 netif_stop_queue(vif->ndev); in wilc_mac_close()
803 wilc_deinit_host_int(vif->ndev); in wilc_mac_close()
806 if (wl->open_ifcs == 0) { in wilc_mac_close()
808 wl->close = 1; in wilc_mac_close()
812 vif->mac_opened = 0; in wilc_mac_close()
831 srcu_idx = srcu_read_lock(&wilc->srcu); in wilc_frmw_to_host()
847 skb->dev = wilc_netdev; in wilc_frmw_to_host()
851 skb->protocol = eth_type_trans(skb, wilc_netdev); in wilc_frmw_to_host()
852 vif->netstats.rx_packets++; in wilc_frmw_to_host()
853 vif->netstats.rx_bytes += frame_len; in wilc_frmw_to_host()
854 skb->ip_summed = CHECKSUM_UNNECESSARY; in wilc_frmw_to_host()
859 srcu_read_unlock(&wilc->srcu, srcu_idx); in wilc_frmw_to_host()
867 srcu_idx = srcu_read_lock(&wilc->srcu); in wilc_wfi_mgmt_rx()
874 if ((vif->mgmt_reg_stypes & auth_bit && in wilc_wfi_mgmt_rx()
875 ieee80211_is_auth(mgmt->frame_control)) && in wilc_wfi_mgmt_rx()
876 vif->iftype == WILC_STATION_MODE && is_auth) { in wilc_wfi_mgmt_rx()
881 if (vif->priv.p2p_listen_state && in wilc_wfi_mgmt_rx()
882 vif->mgmt_reg_stypes & type_bit) in wilc_wfi_mgmt_rx()
885 if (vif->monitor_flag) in wilc_wfi_mgmt_rx()
886 wilc_wfi_monitor_rx(wilc->monitor_dev, buff, size); in wilc_wfi_mgmt_rx()
888 srcu_read_unlock(&wilc->srcu, srcu_idx); in wilc_wfi_mgmt_rx()
908 if (wilc->firmware) { in wilc_netdev_cleanup()
909 release_firmware(wilc->firmware); in wilc_netdev_cleanup()
910 wilc->firmware = NULL; in wilc_netdev_cleanup()
913 list_for_each_entry_safe(vif, vif_tmp, &wilc->vif_list, list) { in wilc_netdev_cleanup()
914 mutex_lock(&wilc->vif_mutex); in wilc_netdev_cleanup()
915 list_del_rcu(&vif->list); in wilc_netdev_cleanup()
916 wilc->vif_num--; in wilc_netdev_cleanup()
917 mutex_unlock(&wilc->vif_mutex); in wilc_netdev_cleanup()
918 synchronize_srcu(&wilc->srcu); in wilc_netdev_cleanup()
919 if (vif->ndev) in wilc_netdev_cleanup()
920 unregister_netdev(vif->ndev); in wilc_netdev_cleanup()
924 destroy_workqueue(wilc->hif_workqueue); in wilc_netdev_cleanup()
937 srcu_idx = srcu_read_lock(&wl->srcu); in wilc_get_available_idx()
939 if (vif->idx == 0) in wilc_get_available_idx()
944 srcu_read_unlock(&wl->srcu, srcu_idx); in wilc_get_available_idx()
959 return ERR_PTR(-ENOMEM); in wilc_netdev_ifc_init()
962 ndev->ieee80211_ptr = &vif->priv.wdev; in wilc_netdev_ifc_init()
963 strcpy(ndev->name, name); in wilc_netdev_ifc_init()
964 vif->wilc = wl; in wilc_netdev_ifc_init()
965 vif->ndev = ndev; in wilc_netdev_ifc_init()
966 ndev->ml_priv = vif; in wilc_netdev_ifc_init()
968 ndev->netdev_ops = &wilc_netdev_ops; in wilc_netdev_ifc_init()
970 SET_NETDEV_DEV(ndev, wiphy_dev(wl->wiphy)); in wilc_netdev_ifc_init()
972 vif->priv.wdev.wiphy = wl->wiphy; in wilc_netdev_ifc_init()
973 vif->priv.wdev.netdev = ndev; in wilc_netdev_ifc_init()
974 vif->priv.wdev.iftype = type; in wilc_netdev_ifc_init()
975 vif->priv.dev = ndev; in wilc_netdev_ifc_init()
977 ndev->needs_free_netdev = true; in wilc_netdev_ifc_init()
978 vif->iftype = vif_type; in wilc_netdev_ifc_init()
979 vif->idx = wilc_get_available_idx(wl); in wilc_netdev_ifc_init()
980 vif->mac_opened = 0; in wilc_netdev_ifc_init()
982 memcpy(mac_address, wl->nv_mac_address, ETH_ALEN); in wilc_netdev_ifc_init()
983 /* WILC firmware uses locally administered MAC address for the in wilc_netdev_ifc_init()
988 if (vif->idx) in wilc_netdev_ifc_init()
991 eth_hw_addr_set(vif->ndev, mac_address); in wilc_netdev_ifc_init()
993 mutex_lock(&wl->vif_mutex); in wilc_netdev_ifc_init()
994 list_add_tail_rcu(&vif->list, &wl->vif_list); in wilc_netdev_ifc_init()
995 wl->vif_num += 1; in wilc_netdev_ifc_init()
996 mutex_unlock(&wl->vif_mutex); in wilc_netdev_ifc_init()
997 synchronize_srcu(&wl->srcu); in wilc_netdev_ifc_init()
1005 ret = -EFAULT; in wilc_netdev_ifc_init()
1012 mutex_lock(&wl->vif_mutex); in wilc_netdev_ifc_init()
1013 list_del_rcu(&vif->list); in wilc_netdev_ifc_init()
1014 wl->vif_num -= 1; in wilc_netdev_ifc_init()
1015 mutex_unlock(&wl->vif_mutex); in wilc_netdev_ifc_init()
1016 synchronize_srcu(&wl->srcu); in wilc_netdev_ifc_init()