Exemplo n.º 1
0
static int p54p_open(struct ieee80211_hw *dev)
{
	struct p54p_priv *priv = dev->priv;
	int err;

	init_completion(&priv->boot_comp);
	err = request_irq(priv->pdev->irq, p54p_interrupt,
			  IRQF_SHARED, "p54pci", dev);
	if (err) {
		dev_err(&priv->pdev->dev, "failed to register IRQ handler\n");
		return err;
	}

	memset(priv->ring_control, 0, sizeof(*priv->ring_control));
	err = p54p_upload_firmware(dev);
	if (err) {
		free_irq(priv->pdev->irq, dev);
		return err;
	}
	priv->rx_idx_data = priv->tx_idx_data = 0;
	priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0;

	p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data,
		ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data);

	p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt,
		ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt);

	P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
	P54P_READ(ring_control_base);
	wmb();
	udelay(10);

	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT));
	P54P_READ(int_enable);
	wmb();
	udelay(10);

	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
	P54P_READ(dev_int);

	if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
		printk(KERN_ERR "%s: Cannot boot firmware!\n",
		       wiphy_name(dev->wiphy));
		p54p_stop(dev);
		return -ETIMEDOUT;
	}

	P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE));
	P54P_READ(int_enable);
	wmb();
	udelay(10);

	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
	P54P_READ(dev_int);
	wmb();
	udelay(10);

	return 0;
}
Exemplo n.º 2
0
static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
	int ring_index, struct p54p_desc *ring, u32 ring_limit,
	struct sk_buff **rx_buf)
{
	struct p54p_priv *priv = dev->priv;
	struct p54p_ring_control *ring_control = priv->ring_control;
	struct p54p_desc *desc;
	u32 idx, i;

	i = (*index) % ring_limit;
	(*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
	idx %= ring_limit;
	while (i != idx) {
		u16 len;
		struct sk_buff *skb;
		dma_addr_t dma_addr;
		desc = &ring[i];
		len = le16_to_cpu(desc->len);
		skb = rx_buf[i];

		if (!skb) {
			i++;
			i %= ring_limit;
			continue;
		}

		if (unlikely(len > priv->common.rx_mtu)) {
			if (net_ratelimit())
				dev_err(&priv->pdev->dev, "rx'd frame size "
					"exceeds length threshold.\n");

			len = priv->common.rx_mtu;
		}
		dma_addr = le32_to_cpu(desc->host_addr);
		pci_dma_sync_single_for_cpu(priv->pdev, dma_addr,
			priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
		skb_put(skb, len);

		if (p54_rx(dev, skb)) {
			pci_unmap_single(priv->pdev, dma_addr,
				priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
			rx_buf[i] = NULL;
			desc->host_addr = cpu_to_le32(0);
		} else {
			skb_trim(skb, 0);
			pci_dma_sync_single_for_device(priv->pdev, dma_addr,
				priv->common.rx_mtu + 32, PCI_DMA_FROMDEVICE);
			desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
		}

		i++;
		i %= ring_limit;
	}

	p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf, *index);
}
Exemplo n.º 3
0
static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index,
	int ring_index, struct p54p_desc *ring, u32 ring_limit,
	struct sk_buff **rx_buf)
{
	struct p54p_priv *priv = dev->priv;
	struct p54p_ring_control *ring_control = priv->ring_control;
	struct p54p_desc *desc;
	u32 idx, i;

	i = (*index) % ring_limit;
	(*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]);
	idx %= ring_limit;
	while (i != idx) {
		u16 len;
		struct sk_buff *skb;
		desc = &ring[i];
		len = le16_to_cpu(desc->len);
		skb = rx_buf[i];

		if (!skb) {
			i++;
			i %= ring_limit;
			continue;
		}
		skb_put(skb, len);

		if (p54_rx(dev, skb)) {
			pci_unmap_single(priv->pdev,
					 le32_to_cpu(desc->host_addr),
					 priv->common.rx_mtu + 32,
					 PCI_DMA_FROMDEVICE);
			rx_buf[i] = NULL;
			desc->host_addr = 0;
		} else {
			skb_trim(skb, 0);
			desc->len = cpu_to_le16(priv->common.rx_mtu + 32);
		}

		i++;
		i %= ring_limit;
	}

	p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf);
}
Exemplo n.º 4
0
Arquivo: p54pci.c Projeto: 274914765/C
static irqreturn_t p54p_interrupt(int irq, void *dev_id)
{
    struct ieee80211_hw *dev = dev_id;
    struct p54p_priv *priv = dev->priv;
    struct p54p_ring_control *ring_control = priv->ring_control;
    __le32 reg;

    spin_lock(&priv->lock);
    reg = P54P_READ(int_ident);
    if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
        spin_unlock(&priv->lock);
        return IRQ_HANDLED;
    }

    P54P_WRITE(int_ack, reg);

    reg &= P54P_READ(int_enable);

    if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) {
        struct p54p_desc *desc;
        u32 idx, i;
        i = priv->tx_idx;
        i %= ARRAY_SIZE(ring_control->tx_data);
        priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
        idx %= ARRAY_SIZE(ring_control->tx_data);

        while (i != idx) {
            desc = &ring_control->tx_data[i];
            if (priv->tx_buf[i]) {
                kfree(priv->tx_buf[i]);
                priv->tx_buf[i] = NULL;
            }

            pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
                     le16_to_cpu(desc->len), PCI_DMA_TODEVICE);

            desc->host_addr = 0;
            desc->device_addr = 0;
            desc->len = 0;
            desc->flags = 0;

            i++;
            i %= ARRAY_SIZE(ring_control->tx_data);
        }

        i = priv->rx_idx;
        i %= ARRAY_SIZE(ring_control->rx_data);
        priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
        idx %= ARRAY_SIZE(ring_control->rx_data);
        while (i != idx) {
            u16 len;
            struct sk_buff *skb;
            desc = &ring_control->rx_data[i];
            len = le16_to_cpu(desc->len);
            skb = priv->rx_buf[i];

            skb_put(skb, len);

            if (p54_rx(dev, skb)) {
                pci_unmap_single(priv->pdev,
                         le32_to_cpu(desc->host_addr),
                         MAX_RX_SIZE, PCI_DMA_FROMDEVICE);

                priv->rx_buf[i] = NULL;
                desc->host_addr = 0;
            } else {
                skb_trim(skb, 0);
                desc->len = cpu_to_le16(MAX_RX_SIZE);
            }

            i++;
            i %= ARRAY_SIZE(ring_control->rx_data);
        }

        p54p_refill_rx_ring(dev);

        wmb();
        P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
    } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))
        complete(&priv->boot_comp);

    spin_unlock(&priv->lock);

    return reg ? IRQ_HANDLED : IRQ_NONE;
}