Lines Matching refs:wdev

156 bool wfx_api_older_than(struct wfx_dev *wdev, int major, int minor)  in wfx_api_older_than()  argument
158 if (wdev->hw_caps.api_version_major < major) in wfx_api_older_than()
160 if (wdev->hw_caps.api_version_major > major) in wfx_api_older_than()
162 if (wdev->hw_caps.api_version_minor < minor) in wfx_api_older_than()
174 int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len) in wfx_send_pds() argument
179 dev_err(wdev->dev, "PDS: malformed file (legacy format?)\n"); in wfx_send_pds()
186 dev_err(wdev->dev, "PDS:%d: corrupted file\n", chunk_num); in wfx_send_pds()
190 dev_info(wdev->dev, "PDS:%d: skip unknown data\n", chunk_num); in wfx_send_pds()
194 dev_warn(wdev->dev, "PDS:%d: unexpectedly large chunk\n", chunk_num); in wfx_send_pds()
196 dev_warn(wdev->dev, "PDS:%d: unexpected content\n", chunk_num); in wfx_send_pds()
198 ret = wfx_hif_configuration(wdev, buf + 4, chunk_len - 4); in wfx_send_pds()
200 dev_err(wdev->dev, "PDS:%d: invalid data (unsupported options?)\n", chunk_num); in wfx_send_pds()
204 dev_err(wdev->dev, "PDS:%d: chip didn't reply (corrupted file?)\n", chunk_num); in wfx_send_pds()
208 dev_err(wdev->dev, "PDS:%d: chip returned an unknown error\n", chunk_num); in wfx_send_pds()
219 static int wfx_send_pdata_pds(struct wfx_dev *wdev) in wfx_send_pdata_pds() argument
225 ret = request_firmware(&pds, wdev->pdata.file_pds, wdev->dev); in wfx_send_pdata_pds()
227 dev_err(wdev->dev, "can't load antenna parameters (PDS file %s). The device may be unstable.\n", in wfx_send_pdata_pds()
228 wdev->pdata.file_pds); in wfx_send_pdata_pds()
236 ret = wfx_send_pds(wdev, tmp_buf, pds->size); in wfx_send_pdata_pds()
245 struct wfx_dev *wdev = data; in wfx_free_common() local
247 mutex_destroy(&wdev->tx_power_loop_info_lock); in wfx_free_common()
248 mutex_destroy(&wdev->rx_stats_lock); in wfx_free_common()
249 mutex_destroy(&wdev->conf_mutex); in wfx_free_common()
250 ieee80211_free_hw(wdev->hw); in wfx_free_common()
257 struct wfx_dev *wdev; in wfx_init_common() local
302 wdev = hw->priv; in wfx_init_common()
303 wdev->hw = hw; in wfx_init_common()
304 wdev->dev = dev; in wfx_init_common()
305 wdev->hwbus_ops = hwbus_ops; in wfx_init_common()
306 wdev->hwbus_priv = hwbus_priv; in wfx_init_common()
307 memcpy(&wdev->pdata, pdata, sizeof(*pdata)); in wfx_init_common()
308 of_property_read_string(dev->of_node, "silabs,antenna-config-file", &wdev->pdata.file_pds); in wfx_init_common()
309 wdev->pdata.gpio_wakeup = devm_gpiod_get_optional(dev, "wakeup", GPIOD_OUT_LOW); in wfx_init_common()
310 if (IS_ERR(wdev->pdata.gpio_wakeup)) in wfx_init_common()
313 if (wdev->pdata.gpio_wakeup) in wfx_init_common()
314 gpiod_set_consumer_name(wdev->pdata.gpio_wakeup, "wfx wakeup"); in wfx_init_common()
316 mutex_init(&wdev->conf_mutex); in wfx_init_common()
317 mutex_init(&wdev->rx_stats_lock); in wfx_init_common()
318 mutex_init(&wdev->tx_power_loop_info_lock); in wfx_init_common()
319 init_completion(&wdev->firmware_ready); in wfx_init_common()
320 INIT_DELAYED_WORK(&wdev->cooling_timeout_work, wfx_cooling_timeout_work); in wfx_init_common()
321 skb_queue_head_init(&wdev->tx_pending); in wfx_init_common()
322 init_waitqueue_head(&wdev->tx_dequeue); in wfx_init_common()
323 wfx_init_hif_cmd(&wdev->hif_cmd); in wfx_init_common()
325 if (devm_add_action_or_reset(dev, wfx_free_common, wdev)) in wfx_init_common()
328 return wdev; in wfx_init_common()
335 int wfx_probe(struct wfx_dev *wdev) in wfx_probe() argument
344 gpio_saved = wdev->pdata.gpio_wakeup; in wfx_probe()
345 wdev->pdata.gpio_wakeup = NULL; in wfx_probe()
346 wdev->poll_irq = true; in wfx_probe()
348 wdev->bh_wq = alloc_workqueue("wfx_bh_wq", WQ_HIGHPRI, 0); in wfx_probe()
349 if (!wdev->bh_wq) in wfx_probe()
352 wfx_bh_register(wdev); in wfx_probe()
354 err = wfx_init_device(wdev); in wfx_probe()
358 wfx_bh_poll_irq(wdev); in wfx_probe()
359 err = wait_for_completion_timeout(&wdev->firmware_ready, 1 * HZ); in wfx_probe()
361 dev_err(wdev->dev, "timeout while waiting for startup indication\n"); in wfx_probe()
367 dev_info(wdev->dev, "started firmware %d.%d.%d \"%s\" (API: %d.%d, keyset: %02X, caps: 0x%.8X)\n", in wfx_probe()
368 wdev->hw_caps.firmware_major, wdev->hw_caps.firmware_minor, in wfx_probe()
369 wdev->hw_caps.firmware_build, wdev->hw_caps.firmware_label, in wfx_probe()
370 wdev->hw_caps.api_version_major, wdev->hw_caps.api_version_minor, in wfx_probe()
371 wdev->keyset, wdev->hw_caps.link_mode); in wfx_probe()
372 snprintf(wdev->hw->wiphy->fw_version, in wfx_probe()
373 sizeof(wdev->hw->wiphy->fw_version), in wfx_probe()
375 wdev->hw_caps.firmware_major, in wfx_probe()
376 wdev->hw_caps.firmware_minor, in wfx_probe()
377 wdev->hw_caps.firmware_build); in wfx_probe()
379 if (wfx_api_older_than(wdev, 1, 0)) { in wfx_probe()
380 dev_err(wdev->dev, "unsupported firmware API version (expect 1 while firmware returns %d)\n", in wfx_probe()
381 wdev->hw_caps.api_version_major); in wfx_probe()
386 if (wdev->hw_caps.link_mode == SEC_LINK_ENFORCED) { in wfx_probe()
387 dev_err(wdev->dev, "chip require secure_link, but can't negotiate it\n"); in wfx_probe()
391 if (wdev->hw_caps.region_sel_mode) { in wfx_probe()
392 wdev->hw->wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS; in wfx_probe()
393 wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[11].flags |= in wfx_probe()
395 wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[12].flags |= in wfx_probe()
397 wdev->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[13].flags |= in wfx_probe()
401 dev_dbg(wdev->dev, "sending configuration file %s\n", wdev->pdata.file_pds); in wfx_probe()
402 err = wfx_send_pdata_pds(wdev); in wfx_probe()
406 wdev->poll_irq = false; in wfx_probe()
407 err = wdev->hwbus_ops->irq_subscribe(wdev->hwbus_priv); in wfx_probe()
411 err = wfx_hif_use_multi_tx_conf(wdev, true); in wfx_probe()
413 dev_err(wdev->dev, "misconfigured IRQ?\n"); in wfx_probe()
415 wdev->pdata.gpio_wakeup = gpio_saved; in wfx_probe()
416 if (wdev->pdata.gpio_wakeup) { in wfx_probe()
417 dev_dbg(wdev->dev, "enable 'quiescent' power mode with wakeup GPIO and PDS file %s\n", in wfx_probe()
418 wdev->pdata.file_pds); in wfx_probe()
419 gpiod_set_value_cansleep(wdev->pdata.gpio_wakeup, 1); in wfx_probe()
420 wfx_control_reg_write(wdev, 0); in wfx_probe()
421 wfx_hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_QUIESCENT); in wfx_probe()
423 wfx_hif_set_operational_mode(wdev, HIF_OP_POWER_MODE_DOZE); in wfx_probe()
426 for (i = 0; i < ARRAY_SIZE(wdev->addresses); i++) { in wfx_probe()
427 eth_zero_addr(wdev->addresses[i].addr); in wfx_probe()
428 err = of_get_mac_address(wdev->dev->of_node, wdev->addresses[i].addr); in wfx_probe()
430 wdev->addresses[i].addr[ETH_ALEN - 1] += i; in wfx_probe()
432 ether_addr_copy(wdev->addresses[i].addr, wdev->hw_caps.mac_addr[i]); in wfx_probe()
433 if (!is_valid_ether_addr(wdev->addresses[i].addr)) { in wfx_probe()
434 dev_warn(wdev->dev, "using random MAC address\n"); in wfx_probe()
435 eth_random_addr(wdev->addresses[i].addr); in wfx_probe()
437 dev_info(wdev->dev, "MAC address %d: %pM\n", i, wdev->addresses[i].addr); in wfx_probe()
439 wdev->hw->wiphy->n_addresses = ARRAY_SIZE(wdev->addresses); in wfx_probe()
440 wdev->hw->wiphy->addresses = wdev->addresses; in wfx_probe()
442 if (!wfx_api_older_than(wdev, 3, 8)) in wfx_probe()
443 wdev->hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; in wfx_probe()
445 err = ieee80211_register_hw(wdev->hw); in wfx_probe()
449 err = wfx_debug_init(wdev); in wfx_probe()
456 ieee80211_unregister_hw(wdev->hw); in wfx_probe()
458 wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); in wfx_probe()
460 wfx_bh_unregister(wdev); in wfx_probe()
461 destroy_workqueue(wdev->bh_wq); in wfx_probe()
465 void wfx_release(struct wfx_dev *wdev) in wfx_release() argument
467 ieee80211_unregister_hw(wdev->hw); in wfx_release()
468 wfx_hif_shutdown(wdev); in wfx_release()
469 wdev->hwbus_ops->irq_unsubscribe(wdev->hwbus_priv); in wfx_release()
470 wfx_bh_unregister(wdev); in wfx_release()
471 destroy_workqueue(wdev->bh_wq); in wfx_release()