Skip to content
Snippets Groups Projects
sge.c 58.3 KiB
Newer Older

		if (t1_espi_get_mon_t204(adapter, &(seop[0]), 0) < 0)
		for (i = 0; i < nports; i++) {
			struct sk_buff *skb = sge->espibug_skb[i];

			if (!netif_running(adapter->port[i].dev) ||
			    netif_queue_stopped(adapter->port[i].dev) ||
			    !seop[i] || ((seop[i] & 0xfff) != 0) || !skb)
				continue;

			if (!skb->cb[0]) {
				u8 ch_mac_addr[ETH_ALEN] = {
					0x0, 0x7, 0x43, 0x0, 0x0, 0x0
				};

				skb_copy_to_linear_data_offset(skb,
						    sizeof(struct cpl_tx_pkt),
							       ch_mac_addr,
							       ETH_ALEN);
				skb_copy_to_linear_data_offset(skb,
							       skb->len - 10,
							       ch_mac_addr,
							       ETH_ALEN);
				skb->cb[0] = 0xff;

			/* bump the reference count to avoid freeing of
			 * the skb once the DMA has completed.
			 */
			skb = skb_get(skb);
			t1_sge_tx(skb, adapter, 0, adapter->port[i].dev);
		}
	}
	mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
static void espibug_workaround(unsigned long data)
{
	struct adapter *adapter = (struct adapter *)data;
	struct sge *sge = adapter->sge;

	if (netif_running(adapter->port[0].dev)) {
	        struct sk_buff *skb = sge->espibug_skb[0];
	        u32 seop = t1_espi_get_mon(adapter, 0x930, 0);

	        if ((seop & 0xfff0fff) == 0xfff && skb) {
	                if (!skb->cb[0]) {
	                        u8 ch_mac_addr[ETH_ALEN] =
	                            {0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
	                        skb_copy_to_linear_data_offset(skb,
						     sizeof(struct cpl_tx_pkt),
							       ch_mac_addr,
							       ETH_ALEN);
	                        skb_copy_to_linear_data_offset(skb,
							       skb->len - 10,
							       ch_mac_addr,
							       ETH_ALEN);
	                        skb->cb[0] = 0xff;
	                }

	                /* bump the reference count to avoid freeing of the
	                 * skb once the DMA has completed.
	                 */
	                skb = skb_get(skb);
	                t1_sge_tx(skb, adapter, 0, adapter->port[0].dev);
	        }
	}
	mod_timer(&sge->espibug_timer, jiffies + sge->espibug_timeout);
}

/*
 * Creates a t1_sge structure and returns suggested resource parameters.
 */
struct sge * __devinit t1_sge_create(struct adapter *adapter,
				     struct sge_params *p)
{
	struct sge *sge = kzalloc(sizeof(*sge), GFP_KERNEL);

	if (!sge)
		return NULL;

	sge->adapter = adapter;
	sge->netdev = adapter->port[0].dev;
	sge->rx_pkt_pad = t1_is_T1B(adapter) ? 0 : 2;
	sge->jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;

	for_each_port(adapter, i) {
		sge->port_stats[i] = alloc_percpu(struct sge_port_stats);
		if (!sge->port_stats[i])
			goto nomem_port;
	}

	init_timer(&sge->tx_reclaim_timer);
	sge->tx_reclaim_timer.data = (unsigned long)sge;
	sge->tx_reclaim_timer.function = sge_tx_reclaim_cb;

	if (is_T2(sge->adapter)) {
		init_timer(&sge->espibug_timer);

		if (adapter->params.nports > 1) {
			tx_sched_init(sge);
			sge->espibug_timer.function = espibug_workaround_t204;
			sge->espibug_timer.function = espibug_workaround;
		sge->espibug_timer.data = (unsigned long)sge->adapter;
		sge->espibug_timeout = 1;
		/* for T204, every 10ms */
		if (adapter->params.nports > 1)
			sge->espibug_timeout = HZ/100;

	p->cmdQ_size[0] = SGE_CMDQ0_E_N;
	p->cmdQ_size[1] = SGE_CMDQ1_E_N;
	p->freelQ_size[!sge->jumbo_fl] = SGE_FREEL_SIZE;
	p->freelQ_size[sge->jumbo_fl] = SGE_JUMBO_FREEL_SIZE;
	if (sge->tx_sched) {
		if (board_info(sge->adapter)->board == CHBT_BOARD_CHT204)
			p->rx_coalesce_usecs = 15;
		else
			p->rx_coalesce_usecs = 50;
	} else
		p->rx_coalesce_usecs = 50;

	p->coalesce_enable = 0;
	p->sample_interval_usecs = 0;

	return sge;
nomem_port:
	while (i >= 0) {
		free_percpu(sge->port_stats[i]);
		--i;
	}
	kfree(sge);
	return NULL;