int cw1200_core_probe(const struct sbus_ops *sbus_ops,
		      struct sbus_priv *sbus,
		      struct device *pdev,
		      struct cw1200_common **pself)
{
	int err = -EINVAL;
	struct ieee80211_hw *dev;
	struct cw1200_common *priv;

	dev = cw1200_init_common(sizeof(struct cw1200_common));
	if (!dev)
		goto err;

	priv = dev->priv;
	priv->sbus_ops = sbus_ops;
	priv->sbus_priv = sbus;
	priv->pdev = pdev;

	SET_IEEE80211_DEV(priv->hw, pdev);

	err = cw1200_register_common(dev);
	if (err) {
		cw1200_free_common(dev);
		goto err;
	}

	*pself = dev->priv;

	/* Realtime workqueue */
	priv->bh_workqueue = alloc_workqueue("cw1200_bh",
				WQ_MEM_RECLAIM | WQ_HIGHPRI
				| WQ_CPU_INTENSIVE, 1);

	if(!priv->bh_workqueue) {
		cw1200_unregister_common(dev);
		cw1200_free_common(dev);
		err = -ENOMEM;
		goto err;
	}

	INIT_WORK(&priv->bh_work, cw1200_bh_work);

err:
	return err;
}
int cw1200_core_probe(const struct sbus_ops *sbus_ops,
		      struct sbus_priv *sbus,
		      struct device *pdev,
		      struct cw1200_common **pself,
		      u8 *mac_addr)
{
	int err = -ENOMEM;
	u16 ctrl_reg;
	struct ieee80211_hw *dev;
	struct cw1200_common *priv;
	struct wsm_operational_mode mode = {
		.power_mode = wsm_power_mode_quiescent,
		.disableMoreFlagUsage = true,
	};

	dev = cw1200_init_common(sizeof(struct cw1200_common), mac_addr);
	if (!dev)
		goto err;

	priv = dev->priv;

	priv->sbus_ops = sbus_ops;
	priv->sbus_priv = sbus;
	priv->pdev = pdev;
	SET_IEEE80211_DEV(priv->hw, pdev);

	/* WSM callbacks. */
	priv->wsm_cbc.scan_complete = cw1200_scan_complete_cb;
	priv->wsm_cbc.tx_confirm = cw1200_tx_confirm_cb;
	priv->wsm_cbc.rx = cw1200_rx_cb;
	priv->wsm_cbc.suspend_resume = cw1200_suspend_resume;
	/* priv->wsm_cbc.set_pm_complete = cw1200_set_pm_complete_cb; */
	priv->wsm_cbc.channel_switch = cw1200_channel_switch_cb;

	err = cw1200_register_bh(priv);
	if (err)
		goto err1;

	err = cw1200_load_firmware(priv);
	if (err)
		goto err2;
	priv->sbus_ops->lock(priv->sbus_priv);
	WARN_ON(priv->sbus_ops->set_block_size(priv->sbus_priv,
			SDIO_BLOCK_SIZE));
	priv->sbus_ops->unlock(priv->sbus_priv);

	if (wait_event_interruptible_timeout(priv->wsm_startup_done,
				priv->wsm_caps.firmwareReady, 3*HZ) <= 0) {
		/* TODO: Needs to find how to reset device */
		/*       in QUEUE mode properly.           */
		goto err3;
	}

	WARN_ON(cw1200_reg_write_16(priv, ST90TDS_CONTROL_REG_ID,
					ST90TDS_CONT_WUP_BIT));

	if (cw1200_reg_read_16(priv,ST90TDS_CONTROL_REG_ID, &ctrl_reg))
		WARN_ON(cw1200_reg_read_16(priv,ST90TDS_CONTROL_REG_ID,
						&ctrl_reg));


	WARN_ON(!(ctrl_reg & ST90TDS_CONT_RDY_BIT));

	/* Set low-power mode. */
	WARN_ON(wsm_set_operational_mode(priv, &mode));

	/* Enable multi-TX confirmation */
	WARN_ON(wsm_use_multi_tx_conf(priv, true));

	err = cw1200_register_common(dev);
	if (err) {
		priv->sbus_ops->irq_unsubscribe(priv->sbus_priv);
		goto err3;
	}

	*pself = dev->priv;
	return err;

err3:
	sbus_ops->reset(sbus);
err2:
	cw1200_unregister_bh(priv);
err1:
	cw1200_free_common(dev);
err:
	return err;
}
EXPORT_SYMBOL_GPL(cw1200_core_probe);

void cw1200_core_release(struct cw1200_common *self)
{
	cw1200_unregister_common(self->hw);
	cw1200_free_common(self->hw);
	return;
}
Exemple #3
0
int cw1200_core_probe(const struct hwbus_ops *hwbus_ops,
		      struct hwbus_priv *hwbus,
		      struct device *pdev,
		      struct cw1200_common **core,
		      int ref_clk, const u8 *macaddr,
		      const char *sdd_path, bool have_5ghz)
{
	int err = -EINVAL;
	struct ieee80211_hw *dev;
	struct cw1200_common *priv;
	struct wsm_operational_mode mode = {
		.power_mode = cw1200_power_mode,
		.disable_more_flag_usage = true,
	};

	dev = cw1200_init_common(macaddr, have_5ghz);
	if (!dev)
		goto err;

	priv = dev->priv;
	priv->hw_refclk = ref_clk;
	if (cw1200_refclk)
		priv->hw_refclk = cw1200_refclk;

	priv->sdd_path = (char *)sdd_path;
	if (cw1200_sdd_path)
		priv->sdd_path = cw1200_sdd_path;

	priv->hwbus_ops = hwbus_ops;
	priv->hwbus_priv = hwbus;
	priv->pdev = pdev;
	SET_IEEE80211_DEV(priv->hw, pdev);

	/* Pass struct cw1200_common back up */
	*core = priv;

	err = cw1200_register_bh(priv);
	if (err)
		goto err1;

	err = cw1200_load_firmware(priv);
	if (err)
		goto err2;

	if (wait_event_interruptible_timeout(priv->wsm_startup_done,
					     priv->firmware_ready,
					     3*HZ) <= 0) {
		/* TODO: Need to find how to reset device
		   in QUEUE mode properly.
		*/
		pr_err("Timeout waiting on device startup\n");
		err = -ETIMEDOUT;
		goto err2;
	}

	/* Set low-power mode. */
	wsm_set_operational_mode(priv, &mode);

	/* Enable multi-TX confirmation */
	wsm_use_multi_tx_conf(priv, true);

	err = cw1200_register_common(dev);
	if (err)
		goto err2;

	return err;

err2:
	cw1200_unregister_bh(priv);
err1:
	cw1200_free_common(dev);
err:
	*core = NULL;
	return err;
}
EXPORT_SYMBOL_GPL(cw1200_core_probe);

void cw1200_core_release(struct cw1200_common *self)
{
	/* Disable device interrupts */
	self->hwbus_ops->lock(self->hwbus_priv);
	__cw1200_irq_enable(self, 0);
	self->hwbus_ops->unlock(self->hwbus_priv);

	/* And then clean up */
	cw1200_unregister_common(self->hw);
	cw1200_free_common(self->hw);
	return;
}