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"
14 #include "mcdi_pcol.h"
16 static int efx_mcdi_set_mac(struct efx_nic
*efx
)
19 u8 cmdbytes
[MC_CMD_SET_MAC_IN_LEN
];
21 memcpy(cmdbytes
+ MC_CMD_SET_MAC_IN_ADDR_OFST
,
22 efx
->net_dev
->dev_addr
, ETH_ALEN
);
24 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_MTU
,
25 EFX_MAX_FRAME_LEN(efx
->net_dev
->mtu
));
26 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_DRAIN
, 0);
28 /* The MCDI command provides for controlling accept/reject
29 * of broadcast packets too, but the driver doesn't currently
31 reject
= (efx
->promiscuous
) ? 0 :
32 (1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN
);
33 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_REJECT
, reject
);
35 switch (efx
->wanted_fc
) {
36 case EFX_FC_RX
| EFX_FC_TX
:
37 fcntl
= MC_CMD_FCNTL_BIDIR
;
40 fcntl
= MC_CMD_FCNTL_RESPOND
;
43 fcntl
= MC_CMD_FCNTL_OFF
;
46 if (efx
->wanted_fc
& EFX_FC_AUTO
)
47 fcntl
= MC_CMD_FCNTL_AUTO
;
49 MCDI_SET_DWORD(cmdbytes
, SET_MAC_IN_FCNTL
, fcntl
);
51 return efx_mcdi_rpc(efx
, MC_CMD_SET_MAC
, cmdbytes
, sizeof(cmdbytes
),
55 static int efx_mcdi_get_mac_faults(struct efx_nic
*efx
, u32
*faults
)
57 u8 outbuf
[MC_CMD_GET_LINK_OUT_LEN
];
61 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN
!= 0);
63 rc
= efx_mcdi_rpc(efx
, MC_CMD_GET_LINK
, NULL
, 0,
64 outbuf
, sizeof(outbuf
), &outlength
);
68 *faults
= MCDI_DWORD(outbuf
, GET_LINK_OUT_MAC_FAULT
);
72 netif_err(efx
, hw
, efx
->net_dev
, "%s: failed rc=%d\n",
77 int efx_mcdi_mac_stats(struct efx_nic
*efx
, dma_addr_t dma_addr
,
78 u32 dma_len
, int enable
, int clear
)
80 u8 inbuf
[MC_CMD_MAC_STATS_IN_LEN
];
83 int period
= enable
? 1000 : 0;
87 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_LEN
!= 0);
89 addr_lo
= ((u64
)dma_addr
) >> 0;
90 addr_hi
= ((u64
)dma_addr
) >> 32;
92 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_DMA_ADDR_LO
, addr_lo
);
93 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_DMA_ADDR_HI
, addr_hi
);
94 cmd_ptr
= (efx_dword_t
*)MCDI_PTR(inbuf
, MAC_STATS_IN_CMD
);
95 EFX_POPULATE_DWORD_7(*cmd_ptr
,
96 MC_CMD_MAC_STATS_CMD_DMA
, !!enable
,
97 MC_CMD_MAC_STATS_CMD_CLEAR
, clear
,
98 MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE
, 1,
99 MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE
, !!enable
,
100 MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR
, 0,
101 MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT
, 1,
102 MC_CMD_MAC_STATS_CMD_PERIOD_MS
, period
);
103 MCDI_SET_DWORD(inbuf
, MAC_STATS_IN_DMA_LEN
, dma_len
);
105 rc
= efx_mcdi_rpc(efx
, MC_CMD_MAC_STATS
, inbuf
, sizeof(inbuf
),
113 netif_err(efx
, hw
, efx
->net_dev
, "%s: %s failed rc=%d\n",
114 __func__
, enable
? "enable" : "disable", rc
);
118 static int efx_mcdi_mac_reconfigure(struct efx_nic
*efx
)
122 rc
= efx_mcdi_set_mac(efx
);
126 /* Restore the multicast hash registers. */
127 efx
->type
->push_multicast_hash(efx
);
133 static bool efx_mcdi_mac_check_fault(struct efx_nic
*efx
)
136 int rc
= efx_mcdi_get_mac_faults(efx
, &faults
);
137 return (rc
!= 0) || (faults
!= 0);
141 struct efx_mac_operations efx_mcdi_mac_operations
= {
142 .reconfigure
= efx_mcdi_mac_reconfigure
,
143 .update_stats
= efx_port_dummy_op_void
,
144 .check_fault
= efx_mcdi_mac_check_fault
,