aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2012-09-17 21:33:54 -0400
committerBen Hutchings <bhutchings@solarflare.com>2013-08-21 14:43:03 -0400
commit43f775b2fa759a9c126a911f999f35aeb0fbbb84 (patch)
tree619d7933f388e396ab51415fcfb35eefcae2c0b2 /drivers/net/ethernet/sfc
parent319ec6444d723f9f01b96728c163d7eaf75e24d7 (diff)
sfc: Collect all MCDI port functions into mcdi_port.c
Collect together MCDI port functions from mcdi.c, mcdi_mac.c, mcdi_phy.c and siena.c. Rename the 'siena' functions accordingly. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r--drivers/net/ethernet/sfc/Makefile3
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c30
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h9
-rw-r--r--drivers/net/ethernet/sfc/mcdi_mac.c114
-rw-r--r--drivers/net/ethernet/sfc/mcdi_port.c (renamed from drivers/net/ethernet/sfc/mcdi_phy.c)271
-rw-r--r--drivers/net/ethernet/sfc/phy.h17
-rw-r--r--drivers/net/ethernet/sfc/siena.c104
7 files changed, 242 insertions, 306 deletions
diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile
index 84f9c9642b7a..5b31d8a4ae5e 100644
--- a/drivers/net/ethernet/sfc/Makefile
+++ b/drivers/net/ethernet/sfc/Makefile
@@ -1,8 +1,7 @@
1sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \ 1sfc-y += efx.o nic.o falcon.o siena.o tx.o rx.o filter.o \
2 mcdi_mac.o \
3 selftest.o ethtool.o qt202x_phy.o mdio_10g.o \ 2 selftest.o ethtool.o qt202x_phy.o mdio_10g.o \
4 tenxpress.o txc43128_phy.o falcon_boards.o \ 3 tenxpress.o txc43128_phy.o falcon_boards.o \
5 mcdi.o mcdi_phy.o mcdi_mon.o ptp.o 4 mcdi.o mcdi_port.o mcdi_mon.o ptp.o
6sfc-$(CONFIG_SFC_MTD) += mtd.o 5sfc-$(CONFIG_SFC_MTD) += mtd.o
7sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o 6sfc-$(CONFIG_SFC_SRIOV) += siena_sriov.o
8 7
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 4781e02c4f05..5132abaad649 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -514,36 +514,6 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
514 spin_unlock(&mcdi->iface_lock); 514 spin_unlock(&mcdi->iface_lock);
515} 515}
516 516
517static unsigned int efx_mcdi_event_link_speed[] = {
518 [MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
519 [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
520 [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
521};
522
523
524static void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
525{
526 u32 flags, fcntl, speed, lpa;
527
528 speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
529 EFX_BUG_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
530 speed = efx_mcdi_event_link_speed[speed];
531
532 flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
533 fcntl = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_FCNTL);
534 lpa = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LP_CAP);
535
536 /* efx->link_state is only modified by efx_mcdi_phy_get_link(),
537 * which is only run after flushing the event queues. Therefore, it
538 * is safe to modify the link state outside of the mac_lock here.
539 */
540 efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
541
542 efx_mcdi_phy_check_fcntl(efx, lpa);
543
544 efx_link_status_changed(efx);
545}
546
547/* Called from falcon_process_eventq for MCDI events */ 517/* Called from falcon_process_eventq for MCDI events */
548void efx_mcdi_process_event(struct efx_channel *channel, 518void efx_mcdi_process_event(struct efx_channel *channel,
549 efx_qword_t *event) 519 efx_qword_t *event)
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 73bc76eabb83..c8f2cd57041c 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -196,9 +196,14 @@ extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
196extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id); 196extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
197extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx); 197extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
198extern int efx_mcdi_flush_rxqs(struct efx_nic *efx); 198extern int efx_mcdi_flush_rxqs(struct efx_nic *efx);
199extern int efx_mcdi_port_probe(struct efx_nic *efx);
200extern void efx_mcdi_port_remove(struct efx_nic *efx);
201extern int efx_mcdi_port_reconfigure(struct efx_nic *efx);
202extern void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev);
199extern int efx_mcdi_set_mac(struct efx_nic *efx); 203extern int efx_mcdi_set_mac(struct efx_nic *efx);
200extern int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, 204#define EFX_MC_STATS_GENERATION_INVALID ((__force __le64)(-1))
201 u32 dma_len, int enable, int clear); 205extern void efx_mcdi_mac_start_stats(struct efx_nic *efx);
206extern void efx_mcdi_mac_stop_stats(struct efx_nic *efx);
202extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx); 207extern bool efx_mcdi_mac_check_fault(struct efx_nic *efx);
203extern enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason); 208extern enum reset_type efx_mcdi_map_reset_reason(enum reset_type reason);
204extern int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method); 209extern int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method);
diff --git a/drivers/net/ethernet/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c
deleted file mode 100644
index 1b84b90fbef6..000000000000
--- a/drivers/net/ethernet/sfc/mcdi_mac.c
+++ /dev/null
@@ -1,114 +0,0 @@
1/****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2009-2010 Solarflare Communications Inc.
4 *
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.
8 */
9
10#include "net_driver.h"
11#include "efx.h"
12#include "mcdi.h"
13#include "mcdi_pcol.h"
14
15int efx_mcdi_set_mac(struct efx_nic *efx)
16{
17 u32 reject, fcntl;
18 MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN);
19
20 memcpy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
21 efx->net_dev->dev_addr, ETH_ALEN);
22
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);
26
27 /* The MCDI command provides for controlling accept/reject
28 * of broadcast packets too, but the driver doesn't currently
29 * expose this. */
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);
33
34 switch (efx->wanted_fc) {
35 case EFX_FC_RX | EFX_FC_TX:
36 fcntl = MC_CMD_FCNTL_BIDIR;
37 break;
38 case EFX_FC_RX:
39 fcntl = MC_CMD_FCNTL_RESPOND;
40 break;
41 default:
42 fcntl = MC_CMD_FCNTL_OFF;
43 break;
44 }
45 if (efx->wanted_fc & EFX_FC_AUTO)
46 fcntl = MC_CMD_FCNTL_AUTO;
47 if (efx->fc_disable)
48 fcntl = MC_CMD_FCNTL_OFF;
49
50 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
51
52 return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
53 NULL, 0, NULL);
54}
55
56bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
57{
58 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
59 size_t outlength;
60 int rc;
61
62 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
63
64 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
65 outbuf, sizeof(outbuf), &outlength);
66 if (rc) {
67 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
68 __func__, rc);
69 return true;
70 }
71
72 return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
73}
74
75int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
76 u32 dma_len, int enable, int clear)
77{
78 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
79 int rc;
80 efx_dword_t *cmd_ptr;
81 int period = enable ? 1000 : 0;
82 u32 addr_hi;
83 u32 addr_lo;
84
85 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
86
87 addr_lo = ((u64)dma_addr) >> 0;
88 addr_hi = ((u64)dma_addr) >> 32;
89
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);
102
103 rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
104 NULL, 0, NULL);
105 if (rc)
106 goto fail;
107
108 return 0;
109
110fail:
111 netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n",
112 __func__, enable ? "enable" : "disable", rc);
113 return rc;
114}
diff --git a/drivers/net/ethernet/sfc/mcdi_phy.c b/drivers/net/ethernet/sfc/mcdi_port.c
index 86c0d21b84bc..8f31e3d3f304 100644
--- a/drivers/net/ethernet/sfc/mcdi_phy.c
+++ b/drivers/net/ethernet/sfc/mcdi_port.c
@@ -125,16 +125,16 @@ fail:
125 return rc; 125 return rc;
126} 126}
127 127
128int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus, 128static int efx_mcdi_mdio_read(struct net_device *net_dev,
129 unsigned int prtad, unsigned int devad, u16 addr, 129 int prtad, int devad, u16 addr)
130 u16 *value_out, u32 *status_out)
131{ 130{
131 struct efx_nic *efx = netdev_priv(net_dev);
132 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN); 132 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_READ_IN_LEN);
133 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN); 133 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_READ_OUT_LEN);
134 size_t outlen; 134 size_t outlen;
135 int rc; 135 int rc;
136 136
137 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, bus); 137 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_BUS, efx->mdio_bus);
138 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad); 138 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_PRTAD, prtad);
139 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad); 139 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_DEVAD, devad);
140 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr); 140 MCDI_SET_DWORD(inbuf, MDIO_READ_IN_ADDR, addr);
@@ -144,25 +144,27 @@ int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus,
144 if (rc) 144 if (rc)
145 goto fail; 145 goto fail;
146 146
147 *value_out = (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE); 147 if (MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS) !=
148 *status_out = MCDI_DWORD(outbuf, MDIO_READ_OUT_STATUS); 148 MC_CMD_MDIO_STATUS_GOOD)
149 return 0; 149 return -EIO;
150
151 return (u16)MCDI_DWORD(outbuf, MDIO_READ_OUT_VALUE);
150 152
151fail: 153fail:
152 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); 154 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
153 return rc; 155 return rc;
154} 156}
155 157
156int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus, 158static int efx_mcdi_mdio_write(struct net_device *net_dev,
157 unsigned int prtad, unsigned int devad, u16 addr, 159 int prtad, int devad, u16 addr, u16 value)
158 u16 value, u32 *status_out)
159{ 160{
161 struct efx_nic *efx = netdev_priv(net_dev);
160 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN); 162 MCDI_DECLARE_BUF(inbuf, MC_CMD_MDIO_WRITE_IN_LEN);
161 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN); 163 MCDI_DECLARE_BUF(outbuf, MC_CMD_MDIO_WRITE_OUT_LEN);
162 size_t outlen; 164 size_t outlen;
163 int rc; 165 int rc;
164 166
165 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, bus); 167 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_BUS, efx->mdio_bus);
166 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad); 168 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_PRTAD, prtad);
167 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad); 169 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_DEVAD, devad);
168 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr); 170 MCDI_SET_DWORD(inbuf, MDIO_WRITE_IN_ADDR, addr);
@@ -173,7 +175,10 @@ int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus,
173 if (rc) 175 if (rc)
174 goto fail; 176 goto fail;
175 177
176 *status_out = MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS); 178 if (MCDI_DWORD(outbuf, MDIO_WRITE_OUT_STATUS) !=
179 MC_CMD_MDIO_STATUS_GOOD)
180 return -EIO;
181
177 return 0; 182 return 0;
178 183
179fail: 184fail:
@@ -304,6 +309,33 @@ static u32 mcdi_to_ethtool_media(u32 media)
304 } 309 }
305} 310}
306 311
312static void efx_mcdi_phy_decode_link(struct efx_nic *efx,
313 struct efx_link_state *link_state,
314 u32 speed, u32 flags, u32 fcntl)
315{
316 switch (fcntl) {
317 case MC_CMD_FCNTL_AUTO:
318 WARN_ON(1); /* This is not a link mode */
319 link_state->fc = EFX_FC_AUTO | EFX_FC_TX | EFX_FC_RX;
320 break;
321 case MC_CMD_FCNTL_BIDIR:
322 link_state->fc = EFX_FC_TX | EFX_FC_RX;
323 break;
324 case MC_CMD_FCNTL_RESPOND:
325 link_state->fc = EFX_FC_RX;
326 break;
327 default:
328 WARN_ON(1);
329 case MC_CMD_FCNTL_OFF:
330 link_state->fc = 0;
331 break;
332 }
333
334 link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
335 link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
336 link_state->speed = speed;
337}
338
307static int efx_mcdi_phy_probe(struct efx_nic *efx) 339static int efx_mcdi_phy_probe(struct efx_nic *efx)
308{ 340{
309 struct efx_mcdi_phy_data *phy_data; 341 struct efx_mcdi_phy_data *phy_data;
@@ -403,7 +435,7 @@ fail:
403 return rc; 435 return rc;
404} 436}
405 437
406int efx_mcdi_phy_reconfigure(struct efx_nic *efx) 438int efx_mcdi_port_reconfigure(struct efx_nic *efx)
407{ 439{
408 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; 440 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
409 u32 caps = (efx->link_advertising ? 441 u32 caps = (efx->link_advertising ?
@@ -414,37 +446,10 @@ int efx_mcdi_phy_reconfigure(struct efx_nic *efx)
414 efx->loopback_mode, 0); 446 efx->loopback_mode, 0);
415} 447}
416 448
417void efx_mcdi_phy_decode_link(struct efx_nic *efx,
418 struct efx_link_state *link_state,
419 u32 speed, u32 flags, u32 fcntl)
420{
421 switch (fcntl) {
422 case MC_CMD_FCNTL_AUTO:
423 WARN_ON(1); /* This is not a link mode */
424 link_state->fc = EFX_FC_AUTO | EFX_FC_TX | EFX_FC_RX;
425 break;
426 case MC_CMD_FCNTL_BIDIR:
427 link_state->fc = EFX_FC_TX | EFX_FC_RX;
428 break;
429 case MC_CMD_FCNTL_RESPOND:
430 link_state->fc = EFX_FC_RX;
431 break;
432 default:
433 WARN_ON(1);
434 case MC_CMD_FCNTL_OFF:
435 link_state->fc = 0;
436 break;
437 }
438
439 link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN));
440 link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN));
441 link_state->speed = speed;
442}
443
444/* Verify that the forced flow control settings (!EFX_FC_AUTO) are 449/* Verify that the forced flow control settings (!EFX_FC_AUTO) are
445 * supported by the link partner. Warn the user if this isn't the case 450 * supported by the link partner. Warn the user if this isn't the case
446 */ 451 */
447void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa) 452static void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa)
448{ 453{
449 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; 454 struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
450 u32 rmtadv; 455 u32 rmtadv;
@@ -808,10 +813,10 @@ static int efx_mcdi_phy_get_module_info(struct efx_nic *efx,
808 } 813 }
809} 814}
810 815
811const struct efx_phy_operations efx_mcdi_phy_ops = { 816static const struct efx_phy_operations efx_mcdi_phy_ops = {
812 .probe = efx_mcdi_phy_probe, 817 .probe = efx_mcdi_phy_probe,
813 .init = efx_port_dummy_op_int, 818 .init = efx_port_dummy_op_int,
814 .reconfigure = efx_mcdi_phy_reconfigure, 819 .reconfigure = efx_mcdi_port_reconfigure,
815 .poll = efx_mcdi_phy_poll, 820 .poll = efx_mcdi_phy_poll,
816 .fini = efx_port_dummy_op_void, 821 .fini = efx_port_dummy_op_void,
817 .remove = efx_mcdi_phy_remove, 822 .remove = efx_mcdi_phy_remove,
@@ -823,3 +828,183 @@ const struct efx_phy_operations efx_mcdi_phy_ops = {
823 .get_module_eeprom = efx_mcdi_phy_get_module_eeprom, 828 .get_module_eeprom = efx_mcdi_phy_get_module_eeprom,
824 .get_module_info = efx_mcdi_phy_get_module_info, 829 .get_module_info = efx_mcdi_phy_get_module_info,
825}; 830};
831
832static unsigned int efx_mcdi_event_link_speed[] = {
833 [MCDI_EVENT_LINKCHANGE_SPEED_100M] = 100,
834 [MCDI_EVENT_LINKCHANGE_SPEED_1G] = 1000,
835 [MCDI_EVENT_LINKCHANGE_SPEED_10G] = 10000,
836};
837
838void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev)
839{
840 u32 flags, fcntl, speed, lpa;
841
842 speed = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_SPEED);
843 EFX_BUG_ON_PARANOID(speed >= ARRAY_SIZE(efx_mcdi_event_link_speed));
844 speed = efx_mcdi_event_link_speed[speed];
845
846 flags = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LINK_FLAGS);
847 fcntl = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_FCNTL);
848 lpa = EFX_QWORD_FIELD(*ev, MCDI_EVENT_LINKCHANGE_LP_CAP);
849
850 /* efx->link_state is only modified by efx_mcdi_phy_get_link(),
851 * which is only run after flushing the event queues. Therefore, it
852 * is safe to modify the link state outside of the mac_lock here.
853 */
854 efx_mcdi_phy_decode_link(efx, &efx->link_state, speed, flags, fcntl);
855
856 efx_mcdi_phy_check_fcntl(efx, lpa);
857
858 efx_link_status_changed(efx);
859}
860
861int efx_mcdi_set_mac(struct efx_nic *efx)
862{
863 u32 reject, fcntl;
864 MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN);
865
866 BUILD_BUG_ON(MC_CMD_SET_MAC_OUT_LEN != 0);
867
868 memcpy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
869 efx->net_dev->dev_addr, ETH_ALEN);
870
871 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
872 EFX_MAX_FRAME_LEN(efx->net_dev->mtu));
873 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_DRAIN, 0);
874
875 /* The MCDI command provides for controlling accept/reject
876 * of broadcast packets too, but the driver doesn't currently
877 * expose this. */
878 reject = (efx->promiscuous) ? 0 :
879 (1 << MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN);
880 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_REJECT, reject);
881
882 switch (efx->wanted_fc) {
883 case EFX_FC_RX | EFX_FC_TX:
884 fcntl = MC_CMD_FCNTL_BIDIR;
885 break;
886 case EFX_FC_RX:
887 fcntl = MC_CMD_FCNTL_RESPOND;
888 break;
889 default:
890 fcntl = MC_CMD_FCNTL_OFF;
891 break;
892 }
893 if (efx->wanted_fc & EFX_FC_AUTO)
894 fcntl = MC_CMD_FCNTL_AUTO;
895 if (efx->fc_disable)
896 fcntl = MC_CMD_FCNTL_OFF;
897
898 MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
899
900 return efx_mcdi_rpc(efx, MC_CMD_SET_MAC, cmdbytes, sizeof(cmdbytes),
901 NULL, 0, NULL);
902}
903
904bool efx_mcdi_mac_check_fault(struct efx_nic *efx)
905{
906 MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_LINK_OUT_LEN);
907 size_t outlength;
908 int rc;
909
910 BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0);
911
912 rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0,
913 outbuf, sizeof(outbuf), &outlength);
914 if (rc) {
915 netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n",
916 __func__, rc);
917 return true;
918 }
919
920 return MCDI_DWORD(outbuf, GET_LINK_OUT_MAC_FAULT) != 0;
921}
922
923static int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr,
924 u32 dma_len, int enable, int clear)
925{
926 MCDI_DECLARE_BUF(inbuf, MC_CMD_MAC_STATS_IN_LEN);
927 int rc;
928 efx_dword_t *cmd_ptr;
929 int period = enable ? 1000 : 0;
930
931 BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0);
932
933 MCDI_SET_QWORD(inbuf, MAC_STATS_IN_DMA_ADDR, dma_addr);
934 cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD);
935 EFX_POPULATE_DWORD_7(*cmd_ptr,
936 MC_CMD_MAC_STATS_IN_DMA, !!enable,
937 MC_CMD_MAC_STATS_IN_CLEAR, clear,
938 MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE, 1,
939 MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE, !!enable,
940 MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR, 0,
941 MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT, 1,
942 MC_CMD_MAC_STATS_IN_PERIOD_MS, period);
943 MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len);
944
945 rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf),
946 NULL, 0, NULL);
947 if (rc)
948 goto fail;
949
950 return 0;
951
952fail:
953 netif_err(efx, hw, efx->net_dev, "%s: %s failed rc=%d\n",
954 __func__, enable ? "enable" : "disable", rc);
955 return rc;
956}
957
958void efx_mcdi_mac_start_stats(struct efx_nic *efx)
959{
960 __le64 *dma_stats = efx->stats_buffer.addr;
961
962 dma_stats[MC_CMD_MAC_GENERATION_END] = EFX_MC_STATS_GENERATION_INVALID;
963
964 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr,
965 MC_CMD_MAC_NSTATS * sizeof(u64), 1, 0);
966}
967
968void efx_mcdi_mac_stop_stats(struct efx_nic *efx)
969{
970 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0);
971}
972
973int efx_mcdi_port_probe(struct efx_nic *efx)
974{
975 int rc;
976
977 /* Hook in PHY operations table */
978 efx->phy_op = &efx_mcdi_phy_ops;
979
980 /* Set up MDIO structure for PHY */
981 efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
982 efx->mdio.mdio_read = efx_mcdi_mdio_read;
983 efx->mdio.mdio_write = efx_mcdi_mdio_write;
984
985 /* Fill out MDIO structure, loopback modes, and initial link state */
986 rc = efx->phy_op->probe(efx);
987 if (rc != 0)
988 return rc;
989
990 /* Allocate buffer for stats */
991 rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
992 MC_CMD_MAC_NSTATS * sizeof(u64));
993 if (rc)
994 return rc;
995 netif_dbg(efx, probe, efx->net_dev,
996 "stats buffer at %llx (virt %p phys %llx)\n",
997 (u64)efx->stats_buffer.dma_addr,
998 efx->stats_buffer.addr,
999 (u64)virt_to_phys(efx->stats_buffer.addr));
1000
1001 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 1);
1002
1003 return 0;
1004}
1005
1006void efx_mcdi_port_remove(struct efx_nic *efx)
1007{
1008 efx->phy_op->remove(efx);
1009 efx_nic_free_buffer(efx, &efx->stats_buffer);
1010}
diff --git a/drivers/net/ethernet/sfc/phy.h b/drivers/net/ethernet/sfc/phy.h
index 11d148cd8441..4f6eb8177a6d 100644
--- a/drivers/net/ethernet/sfc/phy.h
+++ b/drivers/net/ethernet/sfc/phy.h
@@ -47,21 +47,4 @@ extern const struct efx_phy_operations falcon_txc_phy_ops;
47extern void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir); 47extern void falcon_txc_set_gpio_dir(struct efx_nic *efx, int pin, int dir);
48extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val); 48extern void falcon_txc_set_gpio_val(struct efx_nic *efx, int pin, int val);
49 49
50/****************************************************************************
51 * Siena managed PHYs
52 */
53extern const struct efx_phy_operations efx_mcdi_phy_ops;
54
55extern int efx_mcdi_mdio_read(struct efx_nic *efx, unsigned int bus,
56 unsigned int prtad, unsigned int devad,
57 u16 addr, u16 *value_out, u32 *status_out);
58extern int efx_mcdi_mdio_write(struct efx_nic *efx, unsigned int bus,
59 unsigned int prtad, unsigned int devad,
60 u16 addr, u16 value, u32 *status_out);
61extern void efx_mcdi_phy_decode_link(struct efx_nic *efx,
62 struct efx_link_state *link_state,
63 u32 speed, u32 flags, u32 fcntl);
64extern int efx_mcdi_phy_reconfigure(struct efx_nic *efx);
65extern void efx_mcdi_phy_check_fcntl(struct efx_nic *efx, u32 lpa);
66
67#endif 50#endif
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 1febedb4987c..b5d5568485d0 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -51,81 +51,6 @@ static void siena_push_irq_moderation(struct efx_channel *channel)
51 channel->channel); 51 channel->channel);
52} 52}
53 53
54static int siena_mdio_write(struct net_device *net_dev,
55 int prtad, int devad, u16 addr, u16 value)
56{
57 struct efx_nic *efx = netdev_priv(net_dev);
58 uint32_t status;
59 int rc;
60
61 rc = efx_mcdi_mdio_write(efx, efx->mdio_bus, prtad, devad,
62 addr, value, &status);
63 if (rc)
64 return rc;
65 if (status != MC_CMD_MDIO_STATUS_GOOD)
66 return -EIO;
67
68 return 0;
69}
70
71static int siena_mdio_read(struct net_device *net_dev,
72 int prtad, int devad, u16 addr)
73{
74 struct efx_nic *efx = netdev_priv(net_dev);
75 uint16_t value;
76 uint32_t status;
77 int rc;
78
79 rc = efx_mcdi_mdio_read(efx, efx->mdio_bus, prtad, devad,
80 addr, &value, &status);
81 if (rc)
82 return rc;
83 if (status != MC_CMD_MDIO_STATUS_GOOD)
84 return -EIO;
85
86 return (int)value;
87}
88
89/* This call is responsible for hooking in the MAC and PHY operations */
90static int siena_probe_port(struct efx_nic *efx)
91{
92 int rc;
93
94 /* Hook in PHY operations table */
95 efx->phy_op = &efx_mcdi_phy_ops;
96
97 /* Set up MDIO structure for PHY */
98 efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22;
99 efx->mdio.mdio_read = siena_mdio_read;
100 efx->mdio.mdio_write = siena_mdio_write;
101
102 /* Fill out MDIO structure, loopback modes, and initial link state */
103 rc = efx->phy_op->probe(efx);
104 if (rc != 0)
105 return rc;
106
107 /* Allocate buffer for stats */
108 rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
109 MC_CMD_MAC_NSTATS * sizeof(u64));
110 if (rc)
111 return rc;
112 netif_dbg(efx, probe, efx->net_dev,
113 "stats buffer at %llx (virt %p phys %llx)\n",
114 (u64)efx->stats_buffer.dma_addr,
115 efx->stats_buffer.addr,
116 (u64)virt_to_phys(efx->stats_buffer.addr));
117
118 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 1);
119
120 return 0;
121}
122
123static void siena_remove_port(struct efx_nic *efx)
124{
125 efx->phy_op->remove(efx);
126 efx_nic_free_buffer(efx, &efx->stats_buffer);
127}
128
129void siena_prepare_flush(struct efx_nic *efx) 54void siena_prepare_flush(struct efx_nic *efx)
130{ 55{
131 if (efx->fc_disable++ == 0) 56 if (efx->fc_disable++ == 0)
@@ -447,8 +372,6 @@ static void siena_remove_nic(struct efx_nic *efx)
447 efx->nic_data = NULL; 372 efx->nic_data = NULL;
448} 373}
449 374
450#define STATS_GENERATION_INVALID ((__force __le64)(-1))
451
452static int siena_try_update_nic_stats(struct efx_nic *efx) 375static int siena_try_update_nic_stats(struct efx_nic *efx)
453{ 376{
454 __le64 *dma_stats; 377 __le64 *dma_stats;
@@ -459,7 +382,7 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
459 dma_stats = efx->stats_buffer.addr; 382 dma_stats = efx->stats_buffer.addr;
460 383
461 generation_end = dma_stats[MC_CMD_MAC_GENERATION_END]; 384 generation_end = dma_stats[MC_CMD_MAC_GENERATION_END];
462 if (generation_end == STATS_GENERATION_INVALID) 385 if (generation_end == EFX_MC_STATS_GENERATION_INVALID)
463 return 0; 386 return 0;
464 rmb(); 387 rmb();
465 388
@@ -562,21 +485,6 @@ static void siena_update_nic_stats(struct efx_nic *efx)
562 /* Use the old values instead */ 485 /* Use the old values instead */
563} 486}
564 487
565static void siena_start_nic_stats(struct efx_nic *efx)
566{
567 __le64 *dma_stats = efx->stats_buffer.addr;
568
569 dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID;
570
571 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr,
572 MC_CMD_MAC_NSTATS * sizeof(u64), 1, 0);
573}
574
575static void siena_stop_nic_stats(struct efx_nic *efx)
576{
577 efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0);
578}
579
580static int siena_mac_reconfigure(struct efx_nic *efx) 488static int siena_mac_reconfigure(struct efx_nic *efx)
581{ 489{
582 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_MCAST_HASH_IN_LEN); 490 MCDI_DECLARE_BUF(inbuf, MC_CMD_SET_MCAST_HASH_IN_LEN);
@@ -691,18 +599,18 @@ const struct efx_nic_type siena_a0_nic_type = {
691 .map_reset_reason = efx_mcdi_map_reset_reason, 599 .map_reset_reason = efx_mcdi_map_reset_reason,
692 .map_reset_flags = siena_map_reset_flags, 600 .map_reset_flags = siena_map_reset_flags,
693 .reset = efx_mcdi_reset, 601 .reset = efx_mcdi_reset,
694 .probe_port = siena_probe_port, 602 .probe_port = efx_mcdi_port_probe,
695 .remove_port = siena_remove_port, 603 .remove_port = efx_mcdi_port_remove,
696 .prepare_flush = siena_prepare_flush, 604 .prepare_flush = siena_prepare_flush,
697 .finish_flush = siena_finish_flush, 605 .finish_flush = siena_finish_flush,
698 .update_stats = siena_update_nic_stats, 606 .update_stats = siena_update_nic_stats,
699 .start_stats = siena_start_nic_stats, 607 .start_stats = efx_mcdi_mac_start_stats,
700 .stop_stats = siena_stop_nic_stats, 608 .stop_stats = efx_mcdi_mac_stop_stats,
701 .set_id_led = efx_mcdi_set_id_led, 609 .set_id_led = efx_mcdi_set_id_led,
702 .push_irq_moderation = siena_push_irq_moderation, 610 .push_irq_moderation = siena_push_irq_moderation,
703 .reconfigure_mac = siena_mac_reconfigure, 611 .reconfigure_mac = siena_mac_reconfigure,
704 .check_mac_fault = efx_mcdi_mac_check_fault, 612 .check_mac_fault = efx_mcdi_mac_check_fault,
705 .reconfigure_port = efx_mcdi_phy_reconfigure, 613 .reconfigure_port = efx_mcdi_port_reconfigure,
706 .get_wol = siena_get_wol, 614 .get_wol = siena_get_wol,
707 .set_wol = siena_set_wol, 615 .set_wol = siena_set_wol,
708 .resume_wol = siena_init_wol, 616 .resume_wol = siena_init_wol,