예제 #1
0
int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
{
	void *addr;
	int err = 0;
	int ring;
	struct netxen_recv_context *recv_ctx;
	struct nx_host_rds_ring *rds_ring;
	struct nx_host_sds_ring *sds_ring;
	struct nx_host_tx_ring *tx_ring;

	struct pci_dev *pdev = adapter->pdev;
	struct net_device *netdev = adapter->netdev;
	int port = adapter->portnum;

	recv_ctx = &adapter->recv_ctx;
	tx_ring = adapter->tx_ring;

	addr = pci_alloc_consistent(pdev,
			sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
			&recv_ctx->phys_addr);
	if (addr == NULL) {
		dev_err(&pdev->dev, "failed to allocate hw context\n");
		return -ENOMEM;
	}

	memset(addr, 0, sizeof(struct netxen_ring_ctx));
	recv_ctx->hwctx = (struct netxen_ring_ctx *)addr;
	recv_ctx->hwctx->ctx_id = cpu_to_le32(port);
	recv_ctx->hwctx->cmd_consumer_offset =
		cpu_to_le64(recv_ctx->phys_addr +
			sizeof(struct netxen_ring_ctx));
	tx_ring->hw_consumer =
		(__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));

	/* cmd desc ring */
	addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring),
			&tx_ring->phys_addr);

	if (addr == NULL) {
		dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n",
				netdev->name);
		err = -ENOMEM;
		goto err_out_free;
	}

	tx_ring->desc_head = (struct cmd_desc_type0 *)addr;

	for (ring = 0; ring < adapter->max_rds_rings; ring++) {
		rds_ring = &recv_ctx->rds_rings[ring];
		addr = pci_alloc_consistent(adapter->pdev,
				RCV_DESC_RINGSIZE(rds_ring),
				&rds_ring->phys_addr);
		if (addr == NULL) {
			dev_err(&pdev->dev,
				"%s: failed to allocate rds ring [%d]\n",
				netdev->name, ring);
			err = -ENOMEM;
			goto err_out_free;
		}
		rds_ring->desc_head = (struct rcv_desc *)addr;

		if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
			rds_ring->crb_rcv_producer =
				netxen_get_ioaddr(adapter,
			recv_crb_registers[port].crb_rcv_producer[ring]);
	}

	for (ring = 0; ring < adapter->max_sds_rings; ring++) {
		sds_ring = &recv_ctx->sds_rings[ring];

		addr = pci_alloc_consistent(adapter->pdev,
				STATUS_DESC_RINGSIZE(sds_ring),
				&sds_ring->phys_addr);
		if (addr == NULL) {
			dev_err(&pdev->dev,
				"%s: failed to allocate sds ring [%d]\n",
				netdev->name, ring);
			err = -ENOMEM;
			goto err_out_free;
		}
		sds_ring->desc_head = (struct status_desc *)addr;

		if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
			sds_ring->crb_sts_consumer =
				netxen_get_ioaddr(adapter,
				recv_crb_registers[port].crb_sts_consumer[ring]);

			sds_ring->crb_intr_mask =
				netxen_get_ioaddr(adapter,
				recv_crb_registers[port].sw_int_mask[ring]);
		}
	}


	if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) {
		if (test_and_set_bit(__NX_FW_ATTACHED, &adapter->state))
			goto done;
		if (reset_devices)
			nx_fw_cmd_reset_ctx(adapter);
		err = nx_fw_cmd_create_rx_ctx(adapter);
		if (err)
			goto err_out_free;
		err = nx_fw_cmd_create_tx_ctx(adapter);
		if (err)
			goto err_out_free;
	} else {
		err = netxen_init_old_ctx(adapter);
		if (err)
			goto err_out_free;
	}

done:
	return 0;

err_out_free:
	netxen_free_hw_resources(adapter);
	return err;
}
int netxen_alloc_hw_resources(struct netxen_adapter *adapter)
{
	struct netxen_hardware_context *hw = &adapter->ahw;
	u32 state = 0;
	void *addr;
	int err = 0;
	int ctx, ring;
	struct netxen_recv_context *recv_ctx;
	struct nx_host_rds_ring *rds_ring;

	err = netxen_receive_peg_ready(adapter);
	if (err) {
		printk(KERN_ERR "Rcv Peg initialization not complete:%x.\n",
				state);
		return err;
	}

	addr = pci_alloc_consistent(adapter->pdev,
			sizeof(struct netxen_ring_ctx) + sizeof(uint32_t),
			&adapter->ctx_desc_phys_addr);

	if (addr == NULL) {
		DPRINTK(ERR, "failed to allocate hw context\n");
		return -ENOMEM;
	}
	memset(addr, 0, sizeof(struct netxen_ring_ctx));
	adapter->ctx_desc = (struct netxen_ring_ctx *)addr;
	adapter->ctx_desc->ctx_id = cpu_to_le32(adapter->portnum);
	adapter->ctx_desc->cmd_consumer_offset =
		cpu_to_le64(adapter->ctx_desc_phys_addr +
			sizeof(struct netxen_ring_ctx));
	adapter->cmd_consumer =
		(__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx));

	/* cmd desc ring */
	addr = pci_alloc_consistent(adapter->pdev,
			sizeof(struct cmd_desc_type0) *
			adapter->max_tx_desc_count,
			&hw->cmd_desc_phys_addr);

	if (addr == NULL) {
		printk(KERN_ERR "%s failed to allocate tx desc ring\n",
				netxen_nic_driver_name);
		return -ENOMEM;
	}

	hw->cmd_desc_head = (struct cmd_desc_type0 *)addr;

	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
		recv_ctx = &adapter->recv_ctx[ctx];

		for (ring = 0; ring < adapter->max_rds_rings; ring++) {
			/* rx desc ring */
			rds_ring = &recv_ctx->rds_rings[ring];
			addr = pci_alloc_consistent(adapter->pdev,
					RCV_DESC_RINGSIZE,
					&rds_ring->phys_addr);
			if (addr == NULL) {
				printk(KERN_ERR "%s failed to allocate rx "
					"desc ring[%d]\n",
					netxen_nic_driver_name, ring);
				err = -ENOMEM;
				goto err_out_free;
			}
			rds_ring->desc_head = (struct rcv_desc *)addr;

			if (adapter->fw_major < 4)
				rds_ring->crb_rcv_producer =
					recv_crb_registers[adapter->portnum].
					crb_rcv_producer[ring];
		}

		/* status desc ring */
		addr = pci_alloc_consistent(adapter->pdev,
				STATUS_DESC_RINGSIZE,
				&recv_ctx->rcv_status_desc_phys_addr);
		if (addr == NULL) {
			printk(KERN_ERR "%s failed to allocate sts desc ring\n",
					netxen_nic_driver_name);
			err = -ENOMEM;
			goto err_out_free;
		}
		recv_ctx->rcv_status_desc_head = (struct status_desc *)addr;

		if (adapter->fw_major < 4)
			recv_ctx->crb_sts_consumer =
				recv_crb_registers[adapter->portnum].
				crb_sts_consumer;
	}

	if (adapter->fw_major >= 4) {
		adapter->intr_scheme = INTR_SCHEME_PERPORT;
		adapter->msi_mode = MSI_MODE_MULTIFUNC;

		err = nx_fw_cmd_create_rx_ctx(adapter);
		if (err)
			goto err_out_free;
		err = nx_fw_cmd_create_tx_ctx(adapter);
		if (err)
			goto err_out_free;
	} else {

		adapter->intr_scheme = adapter->pci_read_normalize(adapter,
				CRB_NIC_CAPABILITIES_FW);
		adapter->msi_mode = adapter->pci_read_normalize(adapter,
				CRB_NIC_MSI_MODE_FW);
		adapter->crb_intr_mask = sw_int_mask[adapter->portnum];

		err = netxen_init_old_ctx(adapter);
		if (err) {
			netxen_free_hw_resources(adapter);
			return err;
		}

	}

	return 0;

err_out_free:
	netxen_free_hw_resources(adapter);
	return err;
}