1 /****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2009-2010 Solarflare Communications Inc.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published
7 * by the Free Software Foundation, incorporated herein by reference.
10 #include "net_driver.h"
13 #include "mcdi_pcol.h"
15 int efx_mcdi_set_mac(struct efx_nic
*efx
)
18 u8 cmdbytes
[MC_CMD_SET_MAC_IN_LEN
];
20 memcpy(cmdbytes
+ MC_CMD_SET_MAC_IN_ADDR_OFST
,
21 efx
->net_dev
->dev_addr
, ETH_ALEN
);
23 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_MTU
,
24 EFX_MAX_FRAME_LEN(efx
->net_dev
->mtu
));
25 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_DRAIN
, 0);
27 /* The MCDI command provides for controlling accept/reject
28 * of broadcast packets too, but the driver doesn't currently
30 reject
= (efx
->promiscuous
) ? 0 :
31 (1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN
);
32 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_REJECT
, reject
);
34 switch (efx
->wanted_fc
) {
35 case EFX_FC_RX
| EFX_FC_TX
:
36 fcntl
= MC_CMD_FCNTL_BIDIR
;
39 fcntl
= MC_CMD_FCNTL_RESPOND
;
42 fcntl
= MC_CMD_FCNTL_OFF
;
45 if (efx
->wanted_fc
& EFX_FC_AUTO
)
46 fcntl
= MC_CMD_FCNTL_AUTO
;
48 fcntl
= MC_CMD_FCNTL_OFF
;
50 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_FCNTL
, fcntl
);
52 return efx_mcdi_rpc(efx
, MC_CMD_SET_MAC
, cmdbytes
, sizeof(cmdbytes
),
56 bool efx_mcdi_mac_check_fault(struct efx_nic
*efx
)
58 u8 outbuf
[MC_CMD_GET_LINK_OUT_LEN
];
62 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
64 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
65 outbuf
, sizeof(outbuf
), &outlength
);
67 netif_err(efx
, hw
, efx
->net_dev
, "%s: failed rc=%d\n",
72 return MCDI_DWORD(outbuf
, GET_LINK_OUT_MAC_FAULT
) != 0;
75 int efx_mcdi_mac_stats(struct efx_nic
*efx
, dma_addr_t dma_addr
,
76 u32 dma_len
, int enable
, int clear
)
78 u8 inbuf
[MC_CMD_MAC_STATS_IN_LEN
];
81 int period
= enable
? 1000 : 0;
85 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN
!= 0);
87 addr_lo
= ((u64
)dma_addr
) >> 0;
88 addr_hi
= ((u64
)dma_addr
) >> 32;
90 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_DMA_ADDR_LO
, addr_lo
);
91 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_DMA_ADDR_HI
, addr_hi
);
92 cmd_ptr
= (efx_dword_t
*)MCDI_PTR(inbuf
, MAC_STATS_IN_CMD
);
93 EFX_POPULATE_DWORD_7(*cmd_ptr
,
94 MC_CMD_MAC_STATS_IN_DMA
, !!enable
,
95 MC_CMD_MAC_STATS_IN_CLEAR
, clear
,
96 MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE
, 1,
97 MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE
, !!enable
,
98 MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR
, 0,
99 MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT
, 1,
100 MC_CMD_MAC_STATS_IN_PERIOD_MS
, period
);
101 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_DMA_LEN
, dma_len
);
103 rc
= efx_mcdi_rpc(efx
, MC_CMD_MAC_STATS
, inbuf
, sizeof(inbuf
),
111 netif_err(efx
, hw
, efx
->net_dev
, "%s: %s failed rc=%d\n",
112 __func__
, enable
? "enable" : "disable", rc
);
116 int efx_mcdi_mac_reconfigure(struct efx_nic
*efx
)
120 WARN_ON(!mutex_is_locked(&efx
->mac_lock
));
122 rc
= efx_mcdi_set_mac(efx
);
126 return efx_mcdi_rpc(efx
, MC_CMD_SET_MCAST_HASH
,
127 efx
->multicast_hash
.byte
,
128 sizeof(efx
->multicast_hash
),