1afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings/****************************************************************************
2afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings * Driver for Solarflare Solarstorm network controllers and boards
30a6f40c66ba388e6349a11bea146955716c4d492Ben Hutchings * Copyright 2009-2010 Solarflare Communications Inc.
4afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings *
5afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings * This program is free software; you can redistribute it and/or modify it
6afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings * under the terms of the GNU General Public License version 2 as published
7afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings * by the Free Software Foundation, incorporated herein by reference.
8afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings */
9afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
10afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings#include "net_driver.h"
11afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings#include "efx.h"
12afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings#include "mcdi.h"
13afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings#include "mcdi_pcol.h"
14afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
15cd2d5b529cdb9bd274f3e4bc68d37d4d63b7f383Ben Hutchingsint efx_mcdi_set_mac(struct efx_nic *efx)
16afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings{
17afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	u32 reject, fcntl;
18afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	u8 cmdbytes[MC_CMD_SET_MAC_IN_LEN];
19afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
20afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	memcpy(cmdbytes + MC_CMD_SET_MAC_IN_ADDR_OFST,
21afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	       efx->net_dev->dev_addr, ETH_ALEN);
22afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
23afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
24afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings			EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
25afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
26afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
27afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	/* The MCDI command provides for controlling accept/reject
28afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	 * of broadcast packets too, but the driver doesn't currently
29afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	 * expose this. */
30afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	reject = (efx->promiscuous) ? 0 :
31afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		(1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN);
32afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_REJECT, reject);
33afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
34afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	switch (efx->wanted_fc) {
35afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	case EFX_FC_RX | EFX_FC_TX:
36afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		fcntl = MC_CMD_FCNTL_BIDIR;
37afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		break;
38afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	case EFX_FC_RX:
39afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		fcntl = MC_CMD_FCNTL_RESPOND;
40afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		break;
41afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	default:
42afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		fcntl = MC_CMD_FCNTL_OFF;
43afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		break;
44afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	}
45afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	if (efx->wanted_fc & EFX_FC_AUTO)
46afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		fcntl = MC_CMD_FCNTL_AUTO;
47a606f4325dca6950996abbae452d33f2af095f39Steve Hodgson	if (efx->fc_disable)
48a606f4325dca6950996abbae452d33f2af095f39Steve Hodgson		fcntl = MC_CMD_FCNTL_OFF;
49afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
50afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
51afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
52afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
53afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings			    NULL, 0, NULL);
54afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings}
55afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
561daf417029ddc10b7854430c1e1118df791d0eafBen Hutchingsbool efx_mcdi_mac_check_fault(struct efx_nic *efx)
57afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings{
58afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	u8 outbuf[MC_CMD_GET_LINK_OUT_LEN];
59afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	size_t outlength;
60afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	int rc;
61afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
62afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
63afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
64afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
65afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings			  outbuf, sizeof(outbuf), &outlength);
661daf417029ddc10b7854430c1e1118df791d0eafBen Hutchings	if (rc) {
671daf417029ddc10b7854430c1e1118df791d0eafBen Hutchings		netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
681daf417029ddc10b7854430c1e1118df791d0eafBen Hutchings			  __func__, rc);
691daf417029ddc10b7854430c1e1118df791d0eafBen Hutchings		return true;
701daf417029ddc10b7854430c1e1118df791d0eafBen Hutchings	}
71afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
721daf417029ddc10b7854430c1e1118df791d0eafBen Hutchings	return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
73afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings}
74afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
75afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchingsint efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
76afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		       u32 dma_len, int enable, int clear)
77afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings{
78afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	u8 inbuf[MC_CMD_MAC_STATS_IN_LEN];
79afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	int rc;
80afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	efx_dword_t *cmd_ptr;
813a595102d4298a357d70aaf1d47ae86d92708ea9Steve Hodgson	int period = enable ? 1000 : 0;
82afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	u32 addr_hi;
83afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	u32 addr_lo;
84afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
8505a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings	BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
86afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
87afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	addr_lo = ((u64)dma_addr) >> 0;
88afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	addr_hi = ((u64)dma_addr) >> 32;
89afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
90afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_LO, addr_lo);
91afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_HI, addr_hi);
92afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD);
933a595102d4298a357d70aaf1d47ae86d92708ea9Steve Hodgson	EFX_POPULATE_DWORD_7(*cmd_ptr,
9405a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings			     MC_CMD_MAC_STATS_IN_DMA, !!enable,
9505a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings			     MC_CMD_MAC_STATS_IN_CLEAR, clear,
9605a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings			     MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE, 1,
9705a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings			     MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE, !!enable,
9805a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings			     MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR, 0,
9905a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings			     MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT, 1,
10005a9320f7e64b69cbf612a69b7358546519ffc30Ben Hutchings			     MC_CMD_MAC_STATS_IN_PERIOD_MS, period);
101afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
102afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
103afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
104afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings			  NULL, 0, NULL);
105afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	if (rc)
106afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		goto fail;
107afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
108afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	return 0;
109afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
110afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchingsfail:
11162776d034cc40c49bafdb3551a6ba35f78e3f08dBen Hutchings	netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n",
11262776d034cc40c49bafdb3551a6ba35f78e3f08dBen Hutchings		  __func__, enable ? "enable" : "disable", rc);
113afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	return rc;
114afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings}
115afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
116710b208dc2687fdb3370110d54a67fb2288835ebBen Hutchingsint efx_mcdi_mac_reconfigure(struct efx_nic *efx)
117afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings{
118afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	int rc;
119afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
12030b81cda9516878906b44fed16aac9df1dbb89c7Ben Hutchings	WARN_ON(!mutex_is_locked(&efx->mac_lock));
12130b81cda9516878906b44fed16aac9df1dbb89c7Ben Hutchings
122afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	rc = efx_mcdi_set_mac(efx);
123afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings	if (rc != 0)
124afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings		return rc;
125afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings
12630b81cda9516878906b44fed16aac9df1dbb89c7Ben Hutchings	return efx_mcdi_rpc(efx, MC_CMD_SET_MCAST_HASH,
12730b81cda9516878906b44fed16aac9df1dbb89c7Ben Hutchings			    efx->multicast_hash.byte,
12830b81cda9516878906b44fed16aac9df1dbb89c7Ben Hutchings			    sizeof(efx->multicast_hash),
12930b81cda9516878906b44fed16aac9df1dbb89c7Ben Hutchings			    NULL, 0, NULL);
130afd4aea03f597f29421dc5767e7d1f754730ec23Ben Hutchings}
131