⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spider_net.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	return 0;}/** * spider_net_init_firmware - reads in firmware parts * @card: card structure * * Returns 0 on success, <0 on failure * * spider_net_init_firmware opens the sequencer firmware and does some basic * checks. This function opens and releases the firmware structure. A call * to download the firmware is performed before the release. * * Firmware format * =============== * spider_fw.bin is expected to be a file containing 6*1024*4 bytes, 4k being * the program for each sequencer. Use the command *    tail -q -n +2 Seq_code1_0x088.txt Seq_code2_0x090.txt              \ *         Seq_code3_0x098.txt Seq_code4_0x0A0.txt Seq_code5_0x0A8.txt   \ *         Seq_code6_0x0B0.txt | xxd -r -p -c4 > spider_fw.bin * * to generate spider_fw.bin, if you have sequencer programs with something * like the following contents for each sequencer: *    <ONE LINE COMMENT> *    <FIRST 4-BYTES-WORD FOR SEQUENCER> *    <SECOND 4-BYTES-WORD FOR SEQUENCER> *     ... *    <1024th 4-BYTES-WORD FOR SEQUENCER> */static intspider_net_init_firmware(struct spider_net_card *card){	struct firmware *firmware = NULL;	struct device_node *dn;	const u8 *fw_prop = NULL;	int err = -ENOENT;	int fw_size;	if (request_firmware((const struct firmware **)&firmware,			     SPIDER_NET_FIRMWARE_NAME, &card->pdev->dev) == 0) {		if ( (firmware->size != SPIDER_NET_FIRMWARE_LEN) &&		     netif_msg_probe(card) ) {			dev_err(&card->netdev->dev,			       "Incorrect size of spidernet firmware in " \			       "filesystem. Looking in host firmware...\n");			goto try_host_fw;		}		err = spider_net_download_firmware(card, firmware->data);		release_firmware(firmware);		if (err)			goto try_host_fw;		goto done;	}try_host_fw:	dn = pci_device_to_OF_node(card->pdev);	if (!dn)		goto out_err;	fw_prop = of_get_property(dn, "firmware", &fw_size);	if (!fw_prop)		goto out_err;	if ( (fw_size != SPIDER_NET_FIRMWARE_LEN) &&	     netif_msg_probe(card) ) {		dev_err(&card->netdev->dev,		       "Incorrect size of spidernet firmware in host firmware\n");		goto done;	}	err = spider_net_download_firmware(card, fw_prop);done:	return err;out_err:	if (netif_msg_probe(card))		dev_err(&card->netdev->dev,		       "Couldn't find spidernet firmware in filesystem " \		       "or host firmware\n");	return err;}/** * spider_net_open - called upon ifonfig up * @netdev: interface device structure * * returns 0 on success, <0 on failure * * spider_net_open allocates all the descriptors and memory needed for * operation, sets up multicast list and enables interrupts */intspider_net_open(struct net_device *netdev){	struct spider_net_card *card = netdev_priv(netdev);	int result;	result = spider_net_init_firmware(card);	if (result)		goto init_firmware_failed;	/* start probing with copper */	spider_net_setup_aneg(card);	if (card->phy.def->phy_id)		mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);	result = spider_net_init_chain(card, &card->tx_chain);	if (result)		goto alloc_tx_failed;	card->low_watermark = NULL;	result = spider_net_init_chain(card, &card->rx_chain);	if (result)		goto alloc_rx_failed;	/* Allocate rx skbs */	if (spider_net_alloc_rx_skbs(card))		goto alloc_skbs_failed;	spider_net_set_multi(netdev);	/* further enhancement: setup hw vlan, if needed */	result = -EBUSY;	if (request_irq(netdev->irq, spider_net_interrupt,			     IRQF_SHARED, netdev->name, netdev))		goto register_int_failed;	spider_net_enable_card(card);	netif_start_queue(netdev);	netif_carrier_on(netdev);	napi_enable(&card->napi);	spider_net_enable_interrupts(card);	return 0;register_int_failed:	spider_net_free_rx_chain_contents(card);alloc_skbs_failed:	spider_net_free_chain(card, &card->rx_chain);alloc_rx_failed:	spider_net_free_chain(card, &card->tx_chain);alloc_tx_failed:	del_timer_sync(&card->aneg_timer);init_firmware_failed:	return result;}/** * spider_net_link_phy * @data: used for pointer to card structure * */static void spider_net_link_phy(unsigned long data){	struct spider_net_card *card = (struct spider_net_card *)data;	struct mii_phy *phy = &card->phy;	/* if link didn't come up after SPIDER_NET_ANEG_TIMEOUT tries, setup phy again */	if (card->aneg_count > SPIDER_NET_ANEG_TIMEOUT) {		pr_info("%s: link is down trying to bring it up\n", card->netdev->name);		switch (card->medium) {		case BCM54XX_COPPER:			/* enable fiber with autonegotiation first */			if (phy->def->ops->enable_fiber)				phy->def->ops->enable_fiber(phy, 1);			card->medium = BCM54XX_FIBER;			break;		case BCM54XX_FIBER:			/* fiber didn't come up, try to disable fiber autoneg */			if (phy->def->ops->enable_fiber)				phy->def->ops->enable_fiber(phy, 0);			card->medium = BCM54XX_UNKNOWN;			break;		case BCM54XX_UNKNOWN:			/* copper, fiber with and without failed,			 * retry from beginning */			spider_net_setup_aneg(card);			card->medium = BCM54XX_COPPER;			break;		}		card->aneg_count = 0;		mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);		return;	}	/* link still not up, try again later */	if (!(phy->def->ops->poll_link(phy))) {		card->aneg_count++;		mod_timer(&card->aneg_timer, jiffies + SPIDER_NET_ANEG_TIMER);		return;	}	/* link came up, get abilities */	phy->def->ops->read_link(phy);	spider_net_write_reg(card, SPIDER_NET_GMACST,			     spider_net_read_reg(card, SPIDER_NET_GMACST));	spider_net_write_reg(card, SPIDER_NET_GMACINTEN, 0x4);	if (phy->speed == 1000)		spider_net_write_reg(card, SPIDER_NET_GMACMODE, 0x00000001);	else		spider_net_write_reg(card, SPIDER_NET_GMACMODE, 0);	card->aneg_count = 0;	pr_debug("Found %s with %i Mbps, %s-duplex %sautoneg.\n",		phy->def->name, phy->speed, phy->duplex==1 ? "Full" : "Half",		phy->autoneg==1 ? "" : "no ");	return;}/** * spider_net_setup_phy - setup PHY * @card: card structure * * returns 0 on success, <0 on failure * * spider_net_setup_phy is used as part of spider_net_probe. **/static intspider_net_setup_phy(struct spider_net_card *card){	struct mii_phy *phy = &card->phy;	spider_net_write_reg(card, SPIDER_NET_GDTDMASEL,			     SPIDER_NET_DMASEL_VALUE);	spider_net_write_reg(card, SPIDER_NET_GPCCTRL,			     SPIDER_NET_PHY_CTRL_VALUE);	phy->dev = card->netdev;	phy->mdio_read = spider_net_read_phy;	phy->mdio_write = spider_net_write_phy;	for (phy->mii_id = 1; phy->mii_id <= 31; phy->mii_id++) {		unsigned short id;		id = spider_net_read_phy(card->netdev, phy->mii_id, MII_BMSR);		if (id != 0x0000 && id != 0xffff) {			if (!mii_phy_probe(phy, phy->mii_id)) {				pr_info("Found %s.\n", phy->def->name);				break;			}		}	}	return 0;}/** * spider_net_workaround_rxramfull - work around firmware bug * @card: card structure * * no return value **/static voidspider_net_workaround_rxramfull(struct spider_net_card *card){	int i, sequencer = 0;	/* cancel reset */	spider_net_write_reg(card, SPIDER_NET_CKRCTRL,			     SPIDER_NET_CKRCTRL_RUN_VALUE);	/* empty sequencer data */	for (sequencer = 0; sequencer < SPIDER_NET_FIRMWARE_SEQS;	     sequencer++) {		spider_net_write_reg(card, SPIDER_NET_GSnPRGADR +				     sequencer * 8, 0x0);		for (i = 0; i < SPIDER_NET_FIRMWARE_SEQWORDS; i++) {			spider_net_write_reg(card, SPIDER_NET_GSnPRGDAT +					     sequencer * 8, 0x0);		}	}	/* set sequencer operation */	spider_net_write_reg(card, SPIDER_NET_GSINIT, 0x000000fe);	/* reset */	spider_net_write_reg(card, SPIDER_NET_CKRCTRL,			     SPIDER_NET_CKRCTRL_STOP_VALUE);}/** * spider_net_stop - called upon ifconfig down * @netdev: interface device structure * * always returns 0 */intspider_net_stop(struct net_device *netdev){	struct spider_net_card *card = netdev_priv(netdev);	napi_disable(&card->napi);	netif_carrier_off(netdev);	netif_stop_queue(netdev);	del_timer_sync(&card->tx_timer);	del_timer_sync(&card->aneg_timer);	spider_net_disable_interrupts(card);	free_irq(netdev->irq, netdev);	spider_net_write_reg(card, SPIDER_NET_GDTDMACCNTR,			     SPIDER_NET_DMA_TX_FEND_VALUE);	/* turn off DMA, force end */	spider_net_disable_rxdmac(card);	/* release chains */	spider_net_release_tx_chain(card, 1);	spider_net_free_rx_chain_contents(card);	spider_net_free_chain(card, &card->tx_chain);	spider_net_free_chain(card, &card->rx_chain);	return 0;}/** * spider_net_tx_timeout_task - task scheduled by the watchdog timeout * function (to be called not under interrupt status) * @data: data, is interface device structure * * called as task when tx hangs, resets interface (if interface is up) */static voidspider_net_tx_timeout_task(struct work_struct *work){	struct spider_net_card *card =		container_of(work, struct spider_net_card, tx_timeout_task);	struct net_device *netdev = card->netdev;	if (!(netdev->flags & IFF_UP))		goto out;	netif_device_detach(netdev);	spider_net_stop(netdev);	spider_net_workaround_rxramfull(card);	spider_net_init_card(card);	if (spider_net_setup_phy(card))		goto out;	spider_net_open(netdev);	spider_net_kick_tx_dma(card);	netif_device_attach(netdev);out:	atomic_dec(&card->tx_timeout_task_counter);}/** * spider_net_tx_timeout - called when the tx timeout watchdog kicks in. * @netdev: interface device structure * * called, if tx hangs. Schedules a task that resets the interface */static voidspider_net_tx_timeout(struct net_device *netdev){	struct spider_net_card *card;	card = netdev_priv(netdev);	atomic_inc(&card->tx_timeout_task_counter);	if (netdev->flags & IFF_UP)		schedule_work(&card->tx_timeout_task);	else		atomic_dec(&card->tx_timeout_task_counter);	card->spider_stats.tx_timeouts++;}/** * spider_net_setup_netdev_ops - initialization of net_device operations * @netdev: net_device structure * * fills out function pointers in the net_device structure */static voidspider_net_setup_netdev_ops(struct net_device *netdev){	netdev->open = &spider_net_open;	netdev->stop = &spider_net_stop;	netdev->hard_start_xmit = &spider_net_xmit;	netdev->set_multicast_list = &spider_net_set_multi;	netdev->set_mac_address = &spider_net_set_mac;	netdev->change_mtu = &spider_net_change_mtu;	netdev->do_ioctl = &spider_net_do_ioctl;	/* tx watchdog */	netdev->tx_timeout = &spider_net_tx_timeout;	netdev->watchdog_timeo = SPIDER_NET_WATCHDOG_TIMEOUT;	/* HW VLAN */#ifdef CONFIG_NET_POLL_CONTROLLER	/* poll controller */	netdev->poll_controller = &spider_net_poll_controller;#endif /* CONFIG_NET_POLL_CONTROLLER */	/* ethtool ops */	netdev->ethtool_ops = &spider_net_ethtool_ops;}/** * spider_net_setup_netdev - initialization of net_device * @card: card structure * * Returns 0 on success or <0 on failure * * spider_net_setup_netdev initializes the net_device structure **/static intspider_net_setup_netdev(struct spider_net_card *card){	int result;	struct net_device *netdev = card->netdev;	struct device_node *dn;	struct sockaddr addr;	const u8 *mac;	SET_NETDEV_DEV(netdev, &card->pdev->dev);	pci_set_drvdata(card->pdev, netdev);	init_timer(&card->tx_timer);	card->tx_timer.function =		(void (*)(unsigned long)) spider_net_cleanup_tx_ring;	card->tx_timer.data = (unsigned long) card;	netdev->irq = card->pdev->irq;	card->aneg_count = 0;	init_timer(&card->aneg_timer);	card->aneg_timer.function = spider_net_link_phy;	card->aneg_timer.data = (unsigned long) card;	card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;	netif_napi_add(netdev, &card->napi,		       spider_net_poll, SPIDER_NET_NAPI_WEIGHT);	spider_net_setup_netdev_ops(netdev);	netdev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX;	/* some time: NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX |	 *		NETIF_F_HW_VLAN_FILTER */	netdev->irq = card->pdev->irq;	card->num_rx_ints = 0;	card->ignore_rx_ramfull = 0;	dn = pci_device_to_OF_node(card->pdev);	if (!dn)		return -EIO;	mac = of_get_property(dn, "local-mac-address", NULL);	if (!mac)		return -EIO;	memcpy(addr.sa_data, mac, ETH_ALEN);	result =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -