aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c87
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h21
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h20
-rw-r--r--drivers/net/ethernet/sfc/nic.h16
-rw-r--r--drivers/net/ethernet/sfc/siena.c90
5 files changed, 157 insertions, 77 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 2b9ef282ae8c..d7d3a8a9cd15 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -24,13 +24,6 @@
24 24
25#define MCDI_RPC_TIMEOUT (10 * HZ) 25#define MCDI_RPC_TIMEOUT (10 * HZ)
26 26
27#define MCDI_PDU(efx) \
28 (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST)
29#define MCDI_DOORBELL(efx) \
30 (efx_port_num(efx) ? MC_SMEM_P1_DOORBELL_OFST : MC_SMEM_P0_DOORBELL_OFST)
31#define MCDI_STATUS(efx) \
32 (efx_port_num(efx) ? MC_SMEM_P1_STATUS_OFST : MC_SMEM_P0_STATUS_OFST)
33
34/* A reboot/assertion causes the MCDI status word to be set after the 27/* A reboot/assertion causes the MCDI status word to be set after the
35 * command word is set or a REBOOT event is sent. If we notice a reboot 28 * command word is set or a REBOOT event is sent. If we notice a reboot
36 * via these mechanisms then wait 10ms for the status word to be set. */ 29 * via these mechanisms then wait 10ms for the status word to be set. */
@@ -44,16 +37,18 @@
44 37
45static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) 38static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
46{ 39{
47 struct siena_nic_data *nic_data; 40 EFX_BUG_ON_PARANOID(!efx->mcdi);
48 EFX_BUG_ON_PARANOID(efx_nic_rev(efx) < EFX_REV_SIENA_A0); 41 return &efx->mcdi->iface;
49 nic_data = efx->nic_data;
50 return &nic_data->mcdi;
51} 42}
52 43
53int efx_mcdi_init(struct efx_nic *efx) 44int efx_mcdi_init(struct efx_nic *efx)
54{ 45{
55 struct efx_mcdi_iface *mcdi; 46 struct efx_mcdi_iface *mcdi;
56 47
48 efx->mcdi = kzalloc(sizeof(*efx->mcdi), GFP_KERNEL);
49 if (!efx->mcdi)
50 return -ENOMEM;
51
57 mcdi = efx_mcdi(efx); 52 mcdi = efx_mcdi(efx);
58 init_waitqueue_head(&mcdi->wq); 53 init_waitqueue_head(&mcdi->wq);
59 spin_lock_init(&mcdi->iface_lock); 54 spin_lock_init(&mcdi->iface_lock);
@@ -66,16 +61,19 @@ int efx_mcdi_init(struct efx_nic *efx)
66 return efx_mcdi_handle_assertion(efx); 61 return efx_mcdi_handle_assertion(efx);
67} 62}
68 63
64void efx_mcdi_fini(struct efx_nic *efx)
65{
66 BUG_ON(efx->mcdi &&
67 atomic_read(&efx->mcdi->iface.state) != MCDI_STATE_QUIESCENT);
68 kfree(efx->mcdi);
69}
70
69static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd, 71static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
70 const efx_dword_t *inbuf, size_t inlen) 72 const efx_dword_t *inbuf, size_t inlen)
71{ 73{
72 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 74 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
73 unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
74 unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
75 unsigned int i;
76 efx_dword_t hdr; 75 efx_dword_t hdr;
77 u32 xflags, seqno; 76 u32 xflags, seqno;
78 unsigned int inlen_dw = DIV_ROUND_UP(inlen, 4);
79 77
80 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); 78 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
81 BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V1); 79 BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V1);
@@ -93,31 +91,18 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
93 MCDI_HEADER_SEQ, seqno, 91 MCDI_HEADER_SEQ, seqno,
94 MCDI_HEADER_XFLAGS, xflags); 92 MCDI_HEADER_XFLAGS, xflags);
95 93
96 efx_writed(efx, &hdr, pdu); 94 efx->type->mcdi_request(efx, &hdr, 4, inbuf, inlen);
97
98 for (i = 0; i < inlen_dw; i++)
99 efx_writed(efx, &inbuf[i], pdu + 4 + 4 * i);
100
101 /* Ensure the payload is written out before the header */
102 wmb();
103
104 /* ring the doorbell with a distinctive value */
105 _efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
106} 95}
107 96
108static void 97static void
109efx_mcdi_copyout(struct efx_nic *efx, efx_dword_t *outbuf, size_t outlen) 98efx_mcdi_copyout(struct efx_nic *efx, efx_dword_t *outbuf, size_t outlen)
110{ 99{
111 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 100 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
112 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
113 unsigned int outlen_dw = DIV_ROUND_UP(outlen, 4);
114 int i;
115 101
116 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); 102 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
117 BUG_ON(outlen > MCDI_CTL_SDU_LEN_MAX_V1); 103 BUG_ON(outlen > MCDI_CTL_SDU_LEN_MAX_V1);
118 104
119 for (i = 0; i < outlen_dw; i++) 105 efx->type->mcdi_read_response(efx, outbuf, 4, outlen);
120 efx_readd(efx, &outbuf[i], pdu + 4 + 4 * i);
121} 106}
122 107
123static int efx_mcdi_poll(struct efx_nic *efx) 108static int efx_mcdi_poll(struct efx_nic *efx)
@@ -125,7 +110,6 @@ static int efx_mcdi_poll(struct efx_nic *efx)
125 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 110 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
126 unsigned long time, finish; 111 unsigned long time, finish;
127 unsigned int respseq, respcmd, error; 112 unsigned int respseq, respcmd, error;
128 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
129 unsigned int rc, spins; 113 unsigned int rc, spins;
130 efx_dword_t reg; 114 efx_dword_t reg;
131 115
@@ -152,19 +136,14 @@ static int efx_mcdi_poll(struct efx_nic *efx)
152 time = jiffies; 136 time = jiffies;
153 137
154 rmb(); 138 rmb();
155 efx_readd(efx, &reg, pdu); 139 if (efx->type->mcdi_poll_response(efx))
156
157 /* All 1's indicates that shared memory is in reset (and is
158 * not a valid header). Wait for it to come out reset before
159 * completing the command */
160 if (EFX_DWORD_FIELD(reg, EFX_DWORD_0) != 0xffffffff &&
161 EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE))
162 break; 140 break;
163 141
164 if (time_after(time, finish)) 142 if (time_after(time, finish))
165 return -ETIMEDOUT; 143 return -ETIMEDOUT;
166 } 144 }
167 145
146 efx->type->mcdi_read_response(efx, &reg, 0, 4);
168 mcdi->resplen = EFX_DWORD_FIELD(reg, MCDI_HEADER_DATALEN); 147 mcdi->resplen = EFX_DWORD_FIELD(reg, MCDI_HEADER_DATALEN);
169 respseq = EFX_DWORD_FIELD(reg, MCDI_HEADER_SEQ); 148 respseq = EFX_DWORD_FIELD(reg, MCDI_HEADER_SEQ);
170 respcmd = EFX_DWORD_FIELD(reg, MCDI_HEADER_CODE); 149 respcmd = EFX_DWORD_FIELD(reg, MCDI_HEADER_CODE);
@@ -179,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
179 respseq, mcdi->seqno); 158 respseq, mcdi->seqno);
180 rc = EIO; 159 rc = EIO;
181 } else if (error) { 160 } else if (error) {
182 efx_readd(efx, &reg, pdu + 4); 161 efx->type->mcdi_read_response(efx, &reg, 4, 4);
183 switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) { 162 switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
184#define TRANSLATE_ERROR(name) \ 163#define TRANSLATE_ERROR(name) \
185 case MC_CMD_ERR_ ## name: \ 164 case MC_CMD_ERR_ ## name: \
@@ -215,17 +194,13 @@ out:
215 */ 194 */
216int efx_mcdi_poll_reboot(struct efx_nic *efx) 195int efx_mcdi_poll_reboot(struct efx_nic *efx)
217{ 196{
218 unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx); 197 int rc;
219 efx_dword_t reg;
220 uint32_t value;
221
222 if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
223 return false;
224 198
225 efx_readd(efx, &reg, addr); 199 if (!efx->mcdi)
226 value = EFX_DWORD_FIELD(reg, EFX_DWORD_0); 200 return 0;
227 201
228 if (value == 0) 202 rc = efx->type->mcdi_poll_reboot(efx);
203 if (!rc)
229 return 0; 204 return 0;
230 205
231 /* MAC statistics have been cleared on the NIC; clear our copy 206 /* MAC statistics have been cleared on the NIC; clear our copy
@@ -233,13 +208,7 @@ int efx_mcdi_poll_reboot(struct efx_nic *efx)
233 */ 208 */
234 memset(&efx->mac_stats, 0, sizeof(efx->mac_stats)); 209 memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
235 210
236 EFX_ZERO_DWORD(reg); 211 return rc;
237 efx_writed(efx, &reg, addr);
238
239 if (value == MC_STATUS_DWORD_ASSERT)
240 return -EINTR;
241 else
242 return -EIO;
243} 212}
244 213
245static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi) 214static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
@@ -345,8 +314,6 @@ void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
345{ 314{
346 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 315 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
347 316
348 BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
349
350 efx_mcdi_acquire(mcdi); 317 efx_mcdi_acquire(mcdi);
351 318
352 /* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */ 319 /* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
@@ -364,8 +331,6 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
364 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 331 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
365 int rc; 332 int rc;
366 333
367 BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
368
369 if (mcdi->mode == MCDI_MODE_POLL) 334 if (mcdi->mode == MCDI_MODE_POLL)
370 rc = efx_mcdi_poll(efx); 335 rc = efx_mcdi_poll(efx);
371 else 336 else
@@ -426,7 +391,7 @@ void efx_mcdi_mode_poll(struct efx_nic *efx)
426{ 391{
427 struct efx_mcdi_iface *mcdi; 392 struct efx_mcdi_iface *mcdi;
428 393
429 if (efx_nic_rev(efx) < EFX_REV_SIENA_A0) 394 if (!efx->mcdi)
430 return; 395 return;
431 396
432 mcdi = efx_mcdi(efx); 397 mcdi = efx_mcdi(efx);
@@ -450,7 +415,7 @@ void efx_mcdi_mode_event(struct efx_nic *efx)
450{ 415{
451 struct efx_mcdi_iface *mcdi; 416 struct efx_mcdi_iface *mcdi;
452 417
453 if (efx_nic_rev(efx) < EFX_REV_SIENA_A0) 418 if (!efx->mcdi)
454 return; 419 return;
455 420
456 mcdi = efx_mcdi(efx); 421 mcdi = efx_mcdi(efx);
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 6c58dbd7f581..0bfed2a64399 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -65,7 +65,28 @@ struct efx_mcdi_mon {
65 unsigned int n_attrs; 65 unsigned int n_attrs;
66}; 66};
67 67
68/**
69 * struct efx_mcdi_data - extra state for NICs that implement MCDI
70 * @iface: Interface/protocol state
71 * @hwmon: Hardware monitor state
72 */
73struct efx_mcdi_data {
74 struct efx_mcdi_iface iface;
75#ifdef CONFIG_SFC_MCDI_MON
76 struct efx_mcdi_mon hwmon;
77#endif
78};
79
80#ifdef CONFIG_SFC_MCDI_MON
81static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
82{
83 EFX_BUG_ON_PARANOID(!efx->mcdi);
84 return &efx->mcdi->hwmon;
85}
86#endif
87
68extern int efx_mcdi_init(struct efx_nic *efx); 88extern int efx_mcdi_init(struct efx_nic *efx);
89extern void efx_mcdi_fini(struct efx_nic *efx);
69 90
70extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, 91extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
71 const efx_dword_t *inbuf, size_t inlen, 92 const efx_dword_t *inbuf, size_t inlen,
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index bdded38cbf12..fb9361f384de 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -718,6 +718,7 @@ struct vfdi_status;
718 * @selftest_work: Work item for asynchronous self-test 718 * @selftest_work: Work item for asynchronous self-test
719 * @mtd_list: List of MTDs attached to the NIC 719 * @mtd_list: List of MTDs attached to the NIC
720 * @nic_data: Hardware dependent state 720 * @nic_data: Hardware dependent state
721 * @mcdi: Management-Controller-to-Driver Interface state
721 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode, 722 * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
722 * efx_monitor() and efx_reconfigure_port() 723 * efx_monitor() and efx_reconfigure_port()
723 * @port_enabled: Port enabled indicator. 724 * @port_enabled: Port enabled indicator.
@@ -847,6 +848,7 @@ struct efx_nic {
847#endif 848#endif
848 849
849 void *nic_data; 850 void *nic_data;
851 struct efx_mcdi_data *mcdi;
850 852
851 struct mutex mac_lock; 853 struct mutex mac_lock;
852 struct work_struct mac_work; 854 struct work_struct mac_work;
@@ -956,6 +958,17 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
956 * @test_chip: Test registers. Should use efx_nic_test_registers(), and is 958 * @test_chip: Test registers. Should use efx_nic_test_registers(), and is
957 * expected to reset the NIC. 959 * expected to reset the NIC.
958 * @test_nvram: Test validity of NVRAM contents 960 * @test_nvram: Test validity of NVRAM contents
961 * @mcdi_request: Send an MCDI request with the given header and SDU.
962 * The SDU length may be any value from 0 up to the protocol-
963 * defined maximum, but its buffer will be padded to a multiple
964 * of 4 bytes.
965 * @mcdi_poll_response: Test whether an MCDI response is available.
966 * @mcdi_read_response: Read the MCDI response PDU. The offset will
967 * be a multiple of 4. The length may not be, but the buffer
968 * will be padded so it is safe to round up.
969 * @mcdi_poll_reboot: Test whether the MCDI has rebooted. If so,
970 * return an appropriate error code for aborting any current
971 * request; otherwise return 0.
959 * @revision: Hardware architecture revision 972 * @revision: Hardware architecture revision
960 * @mem_map_size: Memory BAR mapped size 973 * @mem_map_size: Memory BAR mapped size
961 * @txd_ptr_tbl_base: TX descriptor ring base address 974 * @txd_ptr_tbl_base: TX descriptor ring base address
@@ -1004,6 +1017,13 @@ struct efx_nic_type {
1004 void (*resume_wol)(struct efx_nic *efx); 1017 void (*resume_wol)(struct efx_nic *efx);
1005 int (*test_chip)(struct efx_nic *efx, struct efx_self_tests *tests); 1018 int (*test_chip)(struct efx_nic *efx, struct efx_self_tests *tests);
1006 int (*test_nvram)(struct efx_nic *efx); 1019 int (*test_nvram)(struct efx_nic *efx);
1020 void (*mcdi_request)(struct efx_nic *efx,
1021 const efx_dword_t *hdr, size_t hdr_len,
1022 const efx_dword_t *sdu, size_t sdu_len);
1023 bool (*mcdi_poll_response)(struct efx_nic *efx);
1024 void (*mcdi_read_response)(struct efx_nic *efx, efx_dword_t *pdu,
1025 size_t pdu_offset, size_t pdu_len);
1026 int (*mcdi_poll_reboot)(struct efx_nic *efx);
1007 1027
1008 int revision; 1028 int revision;
1009 unsigned int mem_map_size; 1029 unsigned int mem_map_size;
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 0d38cc2e96aa..c699203a210b 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -140,28 +140,12 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
140 140
141/** 141/**
142 * struct siena_nic_data - Siena NIC state 142 * struct siena_nic_data - Siena NIC state
143 * @mcdi: Management-Controller-to-Driver Interface
144 * @wol_filter_id: Wake-on-LAN packet filter id 143 * @wol_filter_id: Wake-on-LAN packet filter id
145 * @hwmon: Hardware monitor state
146 */ 144 */
147struct siena_nic_data { 145struct siena_nic_data {
148 struct efx_mcdi_iface mcdi;
149 int wol_filter_id; 146 int wol_filter_id;
150#ifdef CONFIG_SFC_MCDI_MON
151 struct efx_mcdi_mon hwmon;
152#endif
153}; 147};
154 148
155#ifdef CONFIG_SFC_MCDI_MON
156static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
157{
158 struct siena_nic_data *nic_data;
159 EFX_BUG_ON_PARANOID(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
160 nic_data = efx->nic_data;
161 return &nic_data->hwmon;
162}
163#endif
164
165/* 149/*
166 * On the SFC9000 family each port is associated with 1 PCI physical 150 * On the SFC9000 family each port is associated with 1 PCI physical
167 * function (PF) handled by sfc and a configurable number of virtual 151 * function (PF) handled by sfc and a configurable number of virtual
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 3dca771938f0..73b511af33f9 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -274,6 +274,7 @@ fail4:
274fail3: 274fail3:
275 efx_mcdi_drv_attach(efx, false, NULL); 275 efx_mcdi_drv_attach(efx, false, NULL);
276fail2: 276fail2:
277 efx_mcdi_fini(efx);
277fail1: 278fail1:
278 kfree(efx->nic_data); 279 kfree(efx->nic_data);
279 return rc; 280 return rc;
@@ -367,6 +368,8 @@ static void siena_remove_nic(struct efx_nic *efx)
367 /* Tear down the private nic state */ 368 /* Tear down the private nic state */
368 kfree(efx->nic_data); 369 kfree(efx->nic_data);
369 efx->nic_data = NULL; 370 efx->nic_data = NULL;
371
372 efx_mcdi_fini(efx);
370} 373}
371 374
372static int siena_try_update_nic_stats(struct efx_nic *efx) 375static int siena_try_update_nic_stats(struct efx_nic *efx)
@@ -574,6 +577,89 @@ static void siena_init_wol(struct efx_nic *efx)
574 } 577 }
575} 578}
576 579
580/**************************************************************************
581 *
582 * MCDI
583 *
584 **************************************************************************
585 */
586
587#define MCDI_PDU(efx) \
588 (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST)
589#define MCDI_DOORBELL(efx) \
590 (efx_port_num(efx) ? MC_SMEM_P1_DOORBELL_OFST : MC_SMEM_P0_DOORBELL_OFST)
591#define MCDI_STATUS(efx) \
592 (efx_port_num(efx) ? MC_SMEM_P1_STATUS_OFST : MC_SMEM_P0_STATUS_OFST)
593
594static void siena_mcdi_request(struct efx_nic *efx,
595 const efx_dword_t *hdr, size_t hdr_len,
596 const efx_dword_t *sdu, size_t sdu_len)
597{
598 unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
599 unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
600 unsigned int i;
601 unsigned int inlen_dw = DIV_ROUND_UP(sdu_len, 4);
602
603 EFX_BUG_ON_PARANOID(hdr_len != 4);
604
605 efx_writed(efx, hdr, pdu);
606
607 for (i = 0; i < inlen_dw; i++)
608 efx_writed(efx, &sdu[i], pdu + hdr_len + 4 * i);
609
610 /* Ensure the request is written out before the doorbell */
611 wmb();
612
613 /* ring the doorbell with a distinctive value */
614 _efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
615}
616
617static bool siena_mcdi_poll_response(struct efx_nic *efx)
618{
619 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
620 efx_dword_t hdr;
621
622 efx_readd(efx, &hdr, pdu);
623
624 /* All 1's indicates that shared memory is in reset (and is
625 * not a valid hdr). Wait for it to come out reset before
626 * completing the command
627 */
628 return EFX_DWORD_FIELD(hdr, EFX_DWORD_0) != 0xffffffff &&
629 EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE);
630}
631
632static void siena_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf,
633 size_t offset, size_t outlen)
634{
635 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
636 unsigned int outlen_dw = DIV_ROUND_UP(outlen, 4);
637 int i;
638
639 for (i = 0; i < outlen_dw; i++)
640 efx_readd(efx, &outbuf[i], pdu + offset + 4 * i);
641}
642
643static int siena_mcdi_poll_reboot(struct efx_nic *efx)
644{
645 unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx);
646 efx_dword_t reg;
647 u32 value;
648
649 efx_readd(efx, &reg, addr);
650 value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
651
652 if (value == 0)
653 return 0;
654
655 EFX_ZERO_DWORD(reg);
656 efx_writed(efx, &reg, addr);
657
658 if (value == MC_STATUS_DWORD_ASSERT)
659 return -EINTR;
660 else
661 return -EIO;
662}
577 663
578/************************************************************************** 664/**************************************************************************
579 * 665 *
@@ -613,6 +699,10 @@ const struct efx_nic_type siena_a0_nic_type = {
613 .resume_wol = siena_init_wol, 699 .resume_wol = siena_init_wol,
614 .test_chip = siena_test_chip, 700 .test_chip = siena_test_chip,
615 .test_nvram = efx_mcdi_nvram_test_all, 701 .test_nvram = efx_mcdi_nvram_test_all,
702 .mcdi_request = siena_mcdi_request,
703 .mcdi_poll_response = siena_mcdi_poll_response,
704 .mcdi_read_response = siena_mcdi_read_response,
705 .mcdi_poll_reboot = siena_mcdi_poll_reboot,
616 706
617 .revision = EFX_REV_SIENA_A0, 707 .revision = EFX_REV_SIENA_A0,
618 .mem_map_size = (FR_CZ_MC_TREG_SMEM + 708 .mem_map_size = (FR_CZ_MC_TREG_SMEM +