aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/mcdi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sfc/mcdi.c')
-rw-r--r--drivers/net/sfc/mcdi.c78
1 files changed, 41 insertions, 37 deletions
diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c
index 3912b8fed912..3dd45ed61f0a 100644
--- a/drivers/net/sfc/mcdi.c
+++ b/drivers/net/sfc/mcdi.c
@@ -1,6 +1,6 @@
1/**************************************************************************** 1/****************************************************************************
2 * Driver for Solarflare Solarstorm network controllers and boards 2 * Driver for Solarflare Solarstorm network controllers and boards
3 * Copyright 2008-2009 Solarflare Communications Inc. 3 * Copyright 2008-2011 Solarflare Communications Inc.
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 as published
@@ -50,6 +50,20 @@ static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
50 return &nic_data->mcdi; 50 return &nic_data->mcdi;
51} 51}
52 52
53static inline void
54efx_mcdi_readd(struct efx_nic *efx, efx_dword_t *value, unsigned reg)
55{
56 struct siena_nic_data *nic_data = efx->nic_data;
57 value->u32[0] = (__force __le32)__raw_readl(nic_data->mcdi_smem + reg);
58}
59
60static inline void
61efx_mcdi_writed(struct efx_nic *efx, const efx_dword_t *value, unsigned reg)
62{
63 struct siena_nic_data *nic_data = efx->nic_data;
64 __raw_writel((__force u32)value->u32[0], nic_data->mcdi_smem + reg);
65}
66
53void efx_mcdi_init(struct efx_nic *efx) 67void efx_mcdi_init(struct efx_nic *efx)
54{ 68{
55 struct efx_mcdi_iface *mcdi; 69 struct efx_mcdi_iface *mcdi;
@@ -70,8 +84,8 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
70 const u8 *inbuf, size_t inlen) 84 const u8 *inbuf, size_t inlen)
71{ 85{
72 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 86 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
73 unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); 87 unsigned pdu = MCDI_PDU(efx);
74 unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx); 88 unsigned doorbell = MCDI_DOORBELL(efx);
75 unsigned int i; 89 unsigned int i;
76 efx_dword_t hdr; 90 efx_dword_t hdr;
77 u32 xflags, seqno; 91 u32 xflags, seqno;
@@ -92,29 +106,28 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
92 MCDI_HEADER_SEQ, seqno, 106 MCDI_HEADER_SEQ, seqno,
93 MCDI_HEADER_XFLAGS, xflags); 107 MCDI_HEADER_XFLAGS, xflags);
94 108
95 efx_writed(efx, &hdr, pdu); 109 efx_mcdi_writed(efx, &hdr, pdu);
96 110
97 for (i = 0; i < inlen; i += 4) 111 for (i = 0; i < inlen; i += 4)
98 _efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i); 112 efx_mcdi_writed(efx, (const efx_dword_t *)(inbuf + i),
99 113 pdu + 4 + i);
100 /* Ensure the payload is written out before the header */
101 wmb();
102 114
103 /* ring the doorbell with a distinctive value */ 115 /* ring the doorbell with a distinctive value */
104 _efx_writed(efx, (__force __le32) 0x45789abc, doorbell); 116 EFX_POPULATE_DWORD_1(hdr, EFX_DWORD_0, 0x45789abc);
117 efx_mcdi_writed(efx, &hdr, doorbell);
105} 118}
106 119
107static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) 120static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
108{ 121{
109 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 122 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
110 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); 123 unsigned int pdu = MCDI_PDU(efx);
111 int i; 124 int i;
112 125
113 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); 126 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
114 BUG_ON(outlen & 3 || outlen >= 0x100); 127 BUG_ON(outlen & 3 || outlen >= 0x100);
115 128
116 for (i = 0; i < outlen; i += 4) 129 for (i = 0; i < outlen; i += 4)
117 *((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i); 130 efx_mcdi_readd(efx, (efx_dword_t *)(outbuf + i), pdu + 4 + i);
118} 131}
119 132
120static int efx_mcdi_poll(struct efx_nic *efx) 133static int efx_mcdi_poll(struct efx_nic *efx)
@@ -122,7 +135,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
122 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 135 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
123 unsigned int time, finish; 136 unsigned int time, finish;
124 unsigned int respseq, respcmd, error; 137 unsigned int respseq, respcmd, error;
125 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); 138 unsigned int pdu = MCDI_PDU(efx);
126 unsigned int rc, spins; 139 unsigned int rc, spins;
127 efx_dword_t reg; 140 efx_dword_t reg;
128 141
@@ -148,8 +161,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
148 161
149 time = get_seconds(); 162 time = get_seconds();
150 163
151 rmb(); 164 efx_mcdi_readd(efx, &reg, pdu);
152 efx_readd(efx, &reg, pdu);
153 165
154 /* All 1's indicates that shared memory is in reset (and is 166 /* All 1's indicates that shared memory is in reset (and is
155 * not a valid header). Wait for it to come out reset before 167 * not a valid header). Wait for it to come out reset before
@@ -176,7 +188,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
176 respseq, mcdi->seqno); 188 respseq, mcdi->seqno);
177 rc = EIO; 189 rc = EIO;
178 } else if (error) { 190 } else if (error) {
179 efx_readd(efx, &reg, pdu + 4); 191 efx_mcdi_readd(efx, &reg, pdu + 4);
180 switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) { 192 switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
181#define TRANSLATE_ERROR(name) \ 193#define TRANSLATE_ERROR(name) \
182 case MC_CMD_ERR_ ## name: \ 194 case MC_CMD_ERR_ ## name: \
@@ -210,21 +222,21 @@ out:
210/* Test and clear MC-rebooted flag for this port/function */ 222/* Test and clear MC-rebooted flag for this port/function */
211int efx_mcdi_poll_reboot(struct efx_nic *efx) 223int efx_mcdi_poll_reboot(struct efx_nic *efx)
212{ 224{
213 unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx); 225 unsigned int addr = MCDI_REBOOT_FLAG(efx);
214 efx_dword_t reg; 226 efx_dword_t reg;
215 uint32_t value; 227 uint32_t value;
216 228
217 if (efx_nic_rev(efx) < EFX_REV_SIENA_A0) 229 if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
218 return false; 230 return false;
219 231
220 efx_readd(efx, &reg, addr); 232 efx_mcdi_readd(efx, &reg, addr);
221 value = EFX_DWORD_FIELD(reg, EFX_DWORD_0); 233 value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
222 234
223 if (value == 0) 235 if (value == 0)
224 return 0; 236 return 0;
225 237
226 EFX_ZERO_DWORD(reg); 238 EFX_ZERO_DWORD(reg);
227 efx_writed(efx, &reg, addr); 239 efx_mcdi_writed(efx, &reg, addr);
228 240
229 if (value == MC_STATUS_DWORD_ASSERT) 241 if (value == MC_STATUS_DWORD_ASSERT)
230 return -EINTR; 242 return -EINTR;
@@ -381,7 +393,7 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
381 -rc); 393 -rc);
382 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE); 394 efx_schedule_reset(efx, RESET_TYPE_MC_FAILURE);
383 } else 395 } else
384 netif_err(efx, hw, efx->net_dev, 396 netif_dbg(efx, hw, efx->net_dev,
385 "MC command 0x%x inlen %d failed rc=%d\n", 397 "MC command 0x%x inlen %d failed rc=%d\n",
386 cmd, (int)inlen, -rc); 398 cmd, (int)inlen, -rc);
387 } 399 }
@@ -452,7 +464,7 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
452 * 464 *
453 * There's a race here with efx_mcdi_rpc(), because we might receive 465 * There's a race here with efx_mcdi_rpc(), because we might receive
454 * a REBOOT event *before* the request has been copied out. In polled 466 * a REBOOT event *before* the request has been copied out. In polled
455 * mode (during startup) this is irrelevent, because efx_mcdi_complete() 467 * mode (during startup) this is irrelevant, because efx_mcdi_complete()
456 * is ignored. In event mode, this condition is just an edge-case of 468 * is ignored. In event mode, this condition is just an edge-case of
457 * receiving a REBOOT event after posting the MCDI request. Did the mc 469 * receiving a REBOOT event after posting the MCDI request. Did the mc
458 * reboot before or after the copyout? The best we can do always is 470 * reboot before or after the copyout? The best we can do always is
@@ -463,6 +475,7 @@ static void efx_mcdi_ev_death(struct efx_nic *efx, int rc)
463 if (mcdi->mode == MCDI_MODE_EVENTS) { 475 if (mcdi->mode == MCDI_MODE_EVENTS) {
464 mcdi->resprc = rc; 476 mcdi->resprc = rc;
465 mcdi->resplen = 0; 477 mcdi->resplen = 0;
478 ++mcdi->credits;
466 } 479 }
467 } else 480 } else
468 /* Nobody was waiting for an MCDI request, so trigger a reset */ 481 /* Nobody was waiting for an MCDI request, so trigger a reset */
@@ -601,7 +614,7 @@ void efx_mcdi_process_event(struct efx_channel *channel,
601 ************************************************************************** 614 **************************************************************************
602 */ 615 */
603 616
604int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build) 617void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
605{ 618{
606 u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)]; 619 u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)];
607 size_t outlength; 620 size_t outlength;
@@ -615,29 +628,20 @@ int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build)
615 if (rc) 628 if (rc)
616 goto fail; 629 goto fail;
617 630
618 if (outlength == MC_CMD_GET_VERSION_V0_OUT_LEN) {
619 *version = 0;
620 *build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
621 return 0;
622 }
623
624 if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) { 631 if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) {
625 rc = -EIO; 632 rc = -EIO;
626 goto fail; 633 goto fail;
627 } 634 }
628 635
629 ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION); 636 ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
630 *version = (((u64)le16_to_cpu(ver_words[0]) << 48) | 637 snprintf(buf, len, "%u.%u.%u.%u",
631 ((u64)le16_to_cpu(ver_words[1]) << 32) | 638 le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
632 ((u64)le16_to_cpu(ver_words[2]) << 16) | 639 le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
633 le16_to_cpu(ver_words[3])); 640 return;
634 *build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
635
636 return 0;
637 641
638fail: 642fail:
639 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); 643 netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
640 return rc; 644 buf[0] = 0;
641} 645}
642 646
643int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, 647int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
@@ -1093,8 +1097,8 @@ int efx_mcdi_reset_mc(struct efx_nic *efx)
1093 return rc; 1097 return rc;
1094} 1098}
1095 1099
1096int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type, 1100static int efx_mcdi_wol_filter_set(struct efx_nic *efx, u32 type,
1097 const u8 *mac, int *id_out) 1101 const u8 *mac, int *id_out)
1098{ 1102{
1099 u8 inbuf[MC_CMD_WOL_FILTER_SET_IN_LEN]; 1103 u8 inbuf[MC_CMD_WOL_FILTER_SET_IN_LEN];
1100 u8 outbuf[MC_CMD_WOL_FILTER_SET_OUT_LEN]; 1104 u8 outbuf[MC_CMD_WOL_FILTER_SET_OUT_LEN];