Exemplo n.º 1
0
/**
 * gelic_net_set_multi - sets multicast addresses and promisc flags
 * @netdev: interface device structure
 *
 * gelic_net_set_multi configures multicast addresses as needed for the
 * netdev interface. It also sets up multicast, allmulti and promisc
 * flags appropriately
 */
void gelic_net_set_multi(struct net_device *netdev)
{
	struct gelic_card *card = netdev_card(netdev);
	struct dev_mc_list *mc;
	unsigned int i;
	uint8_t *p;
	u64 addr;
	int status;

	/* clear all multicast address */
	status = lv1_net_remove_multicast_address(bus_id(card), dev_id(card),
						  0, 1);
	if (status)
		dev_err(ctodev(card),
			"lv1_net_remove_multicast_address failed %d\n",
			status);
	/* set broadcast address */
	status = lv1_net_add_multicast_address(bus_id(card), dev_id(card),
					       GELIC_NET_BROADCAST_ADDR, 0);
	if (status)
		dev_err(ctodev(card),
			"lv1_net_add_multicast_address failed, %d\n",
			status);

	if ((netdev->flags & IFF_ALLMULTI) ||
	    (netdev->mc_count > GELIC_NET_MC_COUNT_MAX)) {
		status = lv1_net_add_multicast_address(bus_id(card),
						       dev_id(card),
						       0, 1);
		if (status)
			dev_err(ctodev(card),
				"lv1_net_add_multicast_address failed, %d\n",
				status);
		return;
	}

	/* set multicast addresses */
	for (mc = netdev->mc_list; mc; mc = mc->next) {
		addr = 0;
		p = mc->dmi_addr;
		for (i = 0; i < ETH_ALEN; i++) {
			addr <<= 8;
			addr |= *p++;
		}
		status = lv1_net_add_multicast_address(bus_id(card),
						       dev_id(card),
						       addr, 0);
		if (status)
			dev_err(ctodev(card),
				"lv1_net_add_multicast_address failed, %d\n",
				status);
	}
}
Exemplo n.º 2
0
/**
 * gelic_net_kick_txdma - enables TX DMA processing
 * @card: card structure
 * @descr: descriptor address to enable TX processing at
 *
 */
static int gelic_net_kick_txdma(struct gelic_net_card *card,
				struct gelic_net_descr *descr)
{
	int status = 0;
	int count = 10;

	if (card->tx_dma_progress)
		return 0;

	if (gelic_net_get_descr_status(descr) == GELIC_NET_DESCR_CARDOWNED) {
		card->tx_dma_progress = 1;
		/* sometimes we need retry here */
		while (count--) {
			status = lv1_net_start_tx_dma(bus_id(card),
						      dev_id(card),
						      descr->bus_addr, 0);
			if (!status)
				break;
		}
		if (!count)
			dev_info(ctodev(card), "lv1_net_start_txdma failed," \
				"status=%d %#lx\n",
				 status, card->irq_status);
	}
	return status;
}
Exemplo n.º 3
0
/**
 * gelic_net_disable_txdmac - disables the transmit DMA controller
 * @card: card structure
 *
 * gelic_net_disable_txdmac terminates processing on the DMA controller by
 * turing off DMA and issueing a force end
 */
static inline void gelic_net_disable_txdmac(struct gelic_net_card *card)
{
	int status;

	/* this hvc blocks until the DMA in progress really stopped */
	status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0);
	if (status)
		dev_err(ctodev(card),
			"lv1_net_stop_tx_dma faild, status=%d\n", status);
}
Exemplo n.º 4
0
/**
 * gelic_net_enable_rxdmac - enables the receive DMA controller
 * @card: card structure
 *
 * gelic_net_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
 * in the GDADMACCNTR register
 */
static inline void gelic_net_enable_rxdmac(struct gelic_net_card *card)
{
	int status;

	status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
				card->rx_chain.tail->bus_addr, 0);
	if (status)
		dev_info(ctodev(card),
			 "lv1_net_start_rx_dma failed, status=%d\n", status);
}
/**
 * gelic_card_disable_rxdmac - disables the receive DMA controller
 * @card: card structure
 *
 * gelic_card_disable_rxdmac terminates processing on the DMA controller by
 * turing off DMA and issuing a force end
 */
static void gelic_card_disable_rxdmac(struct gelic_card *card)
{
	int status;

	/* this hvc blocks until the DMA in progress really stopped */
	status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card));
	if (status)
		dev_err(ctodev(card),
			"lv1_net_stop_rx_dma failed, %d\n", status);
}
/* set irq_mask */
int gelic_card_set_irq_mask(struct gelic_card *card, u64 mask)
{
	int status;

	status = lv1_net_set_interrupt_mask(bus_id(card), dev_id(card),
					    mask, 0);
	if (status)
		dev_info(ctodev(card),
			 "%s failed %d\n", __func__, status);
	return status;
}
static int gelic_card_set_link_mode(struct gelic_card *card, int mode)
{
	int status;
	u64 v1, v2;

	status = lv1_net_control(bus_id(card), dev_id(card),
				 GELIC_LV1_SET_NEGOTIATION_MODE,
				 GELIC_LV1_PHY_ETHERNET_0, mode, 0, &v1, &v2);
	if (status) {
		pr_info("%s: failed setting negotiation mode %d\n", __func__,
			status);
		return -EBUSY;
	}

	card->link_mode = mode;
	return 0;
}
Exemplo n.º 8
0
/**
 * gelic_card_kick_txdma - enables TX DMA processing
 * @card: card structure
 * @descr: descriptor address to enable TX processing at
 *
 */
static int gelic_card_kick_txdma(struct gelic_card *card,
				 struct gelic_descr *descr)
{
	int status = 0;

	if (card->tx_dma_progress)
		return 0;

	if (gelic_descr_get_status(descr) == GELIC_DESCR_DMA_CARDOWNED) {
		card->tx_dma_progress = 1;
		status = lv1_net_start_tx_dma(bus_id(card), dev_id(card),
					      descr->bus_addr, 0);
		if (status)
			dev_info(ctodev(card), "lv1_net_start_txdma failed," \
				 "status=%d\n", status);
	}
	return status;
}
static void gelic_card_get_ether_port_status(struct gelic_card *card,
					     int inform)
{
	u64 v2;
	struct net_device *ether_netdev;

	lv1_net_control(bus_id(card), dev_id(card),
			GELIC_LV1_GET_ETH_PORT_STATUS,
			GELIC_LV1_VLAN_TX_ETHERNET_0, 0, 0,
			&card->ether_port_status, &v2);

	if (inform) {
		ether_netdev = card->netdev[GELIC_PORT_ETHERNET_0];
		if (card->ether_port_status & GELIC_LV1_ETHER_LINK_UP)
			netif_carrier_on(ether_netdev);
		else
			netif_carrier_off(ether_netdev);
	}
}
Exemplo n.º 10
0
static u32 gelic_net_get_link(struct net_device *netdev)
{
	struct gelic_net_card *card = netdev_priv(netdev);
	int status;
	u64 v1, v2;
	int link;

	status = lv1_net_control(bus_id(card), dev_id(card),
			GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
			&v1, &v2);
	if (status)
		return 0; /* link down */

	if (v1 & GELIC_NET_LINK_UP)
		link = 1;
	else
		link = 0;

	return link;
}
Exemplo n.º 11
0
static int gelic_net_get_settings(struct net_device *netdev,
				  struct ethtool_cmd *cmd)
{
	struct gelic_net_card *card = netdev_priv(netdev);
	int status;
	u64 v1, v2;
	int speed, duplex;

	speed = duplex = -1;
	status = lv1_net_control(bus_id(card), dev_id(card),
			GELIC_NET_GET_ETH_PORT_STATUS, GELIC_NET_PORT, 0, 0,
			&v1, &v2);
	if (status) {
		/* link down */
	} else {
		if (v1 & GELIC_NET_FULL_DUPLEX) {
			duplex = DUPLEX_FULL;
		} else {
			duplex = DUPLEX_HALF;
		}

		if (v1 & GELIC_NET_SPEED_10 ) {
			speed = SPEED_10;
		} else if (v1 & GELIC_NET_SPEED_100) {
			speed = SPEED_100;
		} else if (v1 & GELIC_NET_SPEED_1000) {
			speed = SPEED_1000;
		}
	}
	cmd->supported = SUPPORTED_TP | SUPPORTED_Autoneg |
			SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
			SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
			SUPPORTED_1000baseT_Half | SUPPORTED_1000baseT_Full;
	cmd->advertising = cmd->supported;
	cmd->speed = speed;
	cmd->duplex = duplex;
	cmd->autoneg = AUTONEG_ENABLE; /* always enabled */
	cmd->port = PORT_TP;

	return 0;
}
/**
 * gelic_card_enable_rxdmac - enables the receive DMA controller
 * @card: card structure
 *
 * gelic_card_enable_rxdmac enables the DMA controller by setting RX_DMA_EN
 * in the GDADMACCNTR register
 */
static void gelic_card_enable_rxdmac(struct gelic_card *card)
{
	int status;

#ifdef DEBUG
	if (gelic_descr_get_status(card->rx_chain.head) !=
	    GELIC_DESCR_DMA_CARDOWNED) {
		printk(KERN_ERR "%s: status=%x\n", __func__,
		       be32_to_cpu(card->rx_chain.head->dmac_cmd_status));
		printk(KERN_ERR "%s: nextphy=%x\n", __func__,
		       be32_to_cpu(card->rx_chain.head->next_descr_addr));
		printk(KERN_ERR "%s: head=%p\n", __func__,
		       card->rx_chain.head);
	}
#endif
	status = lv1_net_start_rx_dma(bus_id(card), dev_id(card),
				card->rx_chain.head->bus_addr, 0);
	if (status)
		dev_info(ctodev(card),
			 "lv1_net_start_rx_dma failed, status=%d\n", status);
}
Exemplo n.º 13
0
static int ps3_gelic_driver_remove (struct ps3_system_bus_device *dev)
{
	struct gelic_net_card *card = ps3_system_bus_get_driver_data(dev);

	wait_event(card->waitq,
		   atomic_read(&card->tx_timeout_task_counter) == 0);

	lv1_net_set_interrupt_status_indicator(bus_id(card), dev_id(card),
					       0 , 0);

	unregister_netdev(card->netdev);
	free_netdev(card->netdev);

	ps3_system_bus_set_driver_data(dev, NULL);

	ps3_dma_region_free(dev->d_region);

	ps3_close_hv_device(dev);

	return 0;
}
Exemplo n.º 14
0
/**
 * gelic_ether_setup_netdev - initialization of net_device
 * @netdev: net_device structure
 * @card: card structure
 *
 * Returns 0 on success or <0 on failure
 *
 * gelic_ether_setup_netdev initializes the net_device structure
 * and register it.
 **/
int __devinit gelic_net_setup_netdev(struct net_device *netdev,
				     struct gelic_card *card)
{
	int status;
	u64 v1, v2;

	netdev->features = NETIF_F_IP_CSUM;

	status = lv1_net_control(bus_id(card), dev_id(card),
				 GELIC_LV1_GET_MAC_ADDRESS,
				 0, 0, 0, &v1, &v2);
	v1 <<= 16;
	if (status || !is_valid_ether_addr((u8 *)&v1)) {
		dev_info(ctodev(card),
			 "%s:lv1_net_control GET_MAC_ADDR failed %d\n",
			 __func__, status);
		return -EINVAL;
	}
	memcpy(netdev->dev_addr, &v1, ETH_ALEN);

	if (card->vlan_required) {
		netdev->hard_header_len += VLAN_HLEN;
		/*
		 * As vlan is internally used,
		 * we can not receive vlan packets
		 */
		netdev->features |= NETIF_F_VLAN_CHALLENGED;
	}

	status = register_netdev(netdev);
	if (status) {
		dev_err(ctodev(card), "%s:Couldn't register %s %d\n",
			__func__, netdev->name, status);
		return status;
	}
	dev_info(ctodev(card), "%s: MAC addr %pM\n",
		 netdev->name, netdev->dev_addr);

	return 0;
}
Exemplo n.º 15
0
static int gelic_net_set_wol(struct net_device *netdev,
			     struct ethtool_wolinfo *wol)
{
	int status;
	struct gelic_card *card;
	u64 v1, v2;

	if (ps3_compare_firmware_version(2, 2, 0) < 0 ||
	    !capable(CAP_NET_ADMIN))
		return -EPERM;

	if (wol->wolopts & ~WAKE_MAGIC)
		return -EINVAL;

	card = netdev_card(netdev);
	if (wol->wolopts & WAKE_MAGIC) {
		status = lv1_net_control(bus_id(card), dev_id(card),
					 GELIC_LV1_SET_WOL,
					 GELIC_LV1_WOL_MAGIC_PACKET,
					 0, GELIC_LV1_WOL_MP_ENABLE,
					 &v1, &v2);
		if (status) {
			pr_info("%s: enabling WOL failed %d\n", __func__,
				status);
			status = -EIO;
			goto done;
		}
		status = lv1_net_control(bus_id(card), dev_id(card),
					 GELIC_LV1_SET_WOL,
					 GELIC_LV1_WOL_ADD_MATCH_ADDR,
					 0, GELIC_LV1_WOL_MATCH_ALL,
					 &v1, &v2);
		if (!status)
			ps3_sys_manager_set_wol(1);
		else {
			pr_info("%s: enabling WOL filter failed %d\n",
				__func__, status);
			status = -EIO;
		}
	} else {
		status = lv1_net_control(bus_id(card), dev_id(card),
					 GELIC_LV1_SET_WOL,
					 GELIC_LV1_WOL_MAGIC_PACKET,
					 0, GELIC_LV1_WOL_MP_DISABLE,
					 &v1, &v2);
		if (status) {
			pr_info("%s: disabling WOL failed %d\n", __func__,
				status);
			status = -EIO;
			goto done;
		}
		status = lv1_net_control(bus_id(card), dev_id(card),
					 GELIC_LV1_SET_WOL,
					 GELIC_LV1_WOL_DELETE_MATCH_ADDR,
					 0, GELIC_LV1_WOL_MATCH_ALL,
					 &v1, &v2);
		if (!status)
			ps3_sys_manager_set_wol(0);
		else {
			pr_info("%s: removing WOL filter failed %d\n",
				__func__, status);
			status = -EIO;
		}
	}
done:
	return status;
}
Exemplo n.º 16
0
/**
 * gelic_net_setup_netdev - initialization of net_device
 * @card: card structure
 *
 * Returns 0 on success or <0 on failure
 *
 * gelic_net_setup_netdev initializes the net_device structure
 **/
static int gelic_net_setup_netdev(struct gelic_net_card *card)
{
	struct net_device *netdev = card->netdev;
	struct sockaddr addr;
	unsigned int i;
	int status;
	u64 v1, v2;

	SET_MODULE_OWNER(netdev);
	SET_NETDEV_DEV(netdev, &card->dev->core);
	spin_lock_init(&card->tx_dma_lock);

	card->rx_csum = GELIC_NET_RX_CSUM_DEFAULT;

	gelic_net_setup_netdev_ops(netdev);

	netdev->features = NETIF_F_IP_CSUM;

	status = lv1_net_control(bus_id(card), dev_id(card),
				 GELIC_NET_GET_MAC_ADDRESS,
				 0, 0, 0, &v1, &v2);
	if (status || !is_valid_ether_addr((u8 *)&v1)) {
		dev_info(ctodev(card),
			 "%s:lv1_net_control GET_MAC_ADDR failed %d\n",
			 __func__, status);
		return -EINVAL;
	}
	v1 <<= 16;
	memcpy(addr.sa_data, &v1, ETH_ALEN);
	memcpy(netdev->dev_addr, addr.sa_data, ETH_ALEN);
	dev_info(ctodev(card), "MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n",
		 netdev->dev_addr[0], netdev->dev_addr[1],
		 netdev->dev_addr[2], netdev->dev_addr[3],
		 netdev->dev_addr[4], netdev->dev_addr[5]);

	card->vlan_index = -1;	/* no vlan */
	for (i = 0; i < GELIC_NET_VLAN_MAX; i++) {
		status = lv1_net_control(bus_id(card), dev_id(card),
					GELIC_NET_GET_VLAN_ID,
					i + 1, /* index; one based */
					0, 0, &v1, &v2);
		if (status == GELIC_NET_VLAN_NO_ENTRY) {
			dev_dbg(ctodev(card),
				"GELIC_VLAN_ID no entry:%d, VLAN disabled\n",
				status);
			card->vlan_id[i] = 0;
		} else if (status) {
			dev_dbg(ctodev(card),
				"%s:GELIC_NET_VLAN_ID faild, status=%d\n",
				__func__, status);
			card->vlan_id[i] = 0;
		} else {
			card->vlan_id[i] = (u32)v1;
			dev_dbg(ctodev(card), "vlan_id:%d, %lx\n", i, v1);
		}
	}
	if (card->vlan_id[GELIC_NET_VLAN_WIRED - 1])
		card->vlan_index = GELIC_NET_VLAN_WIRED - 1;

	status = register_netdev(netdev);
	if (status) {
		dev_err(ctodev(card), "%s:Couldn't register net_device: %d\n",
			__func__, status);
		return status;
	}

	return 0;
}
Exemplo n.º 17
0
/**
 * ps3_gelic_driver_probe - add a device to the control of this driver
 */
static int ps3_gelic_driver_probe (struct ps3_system_bus_device *dev)
{
	struct gelic_net_card *card = gelic_net_alloc_card();
	int result;

	if (!card) {
		dev_info(&dev->core, "gelic_net_alloc_card failed\n");
		result = -ENOMEM;
		goto fail_alloc_card;
	}

	ps3_system_bus_set_driver_data(dev, card);
	card->dev = dev;

	result = ps3_open_hv_device(dev);

	if (result) {
		dev_dbg(&dev->core, "ps3_open_hv_device failed\n");
		goto fail_open;
	}

	result = ps3_dma_region_create(dev->d_region);

	if (result) {
		dev_dbg(&dev->core, "ps3_dma_region_create failed(%d)\n",
			result);
		BUG_ON("check region type");
		goto fail_dma_region;
	}

	result = lv1_net_set_interrupt_status_indicator(bus_id(card),
							dev_id(card),
		ps3_mm_phys_to_lpar(__pa(&card->irq_status)),
		0);

	if (result) {
		dev_dbg(&dev->core,
			"lv1_net_set_interrupt_status_indicator failed: %s\n",
			ps3_result(result));
		result = -EIO;
		goto fail_status_indicator;
	}

	result = gelic_net_setup_netdev(card);

	if (result) {
		dev_dbg(&dev->core, "%s:%d: ps3_dma_region_create failed: "
			"(%d)\n", __func__, __LINE__, result);
		goto fail_setup_netdev;
	}

	return 0;

fail_setup_netdev:
	lv1_net_set_interrupt_status_indicator(bus_id(card),
					       bus_id(card),
					       0 , 0);
fail_status_indicator:
	ps3_dma_region_free(dev->d_region);
fail_dma_region:
	ps3_close_hv_device(dev);
fail_open:
	ps3_system_bus_set_driver_data(dev, NULL);
	free_netdev(card->netdev);
fail_alloc_card:
	return result;
}