aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/sfc/mcdi.c31
-rw-r--r--drivers/net/ethernet/sfc/mcdi.h36
-rw-r--r--drivers/net/ethernet/sfc/ptp.c10
3 files changed, 46 insertions, 31 deletions
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index d6d1ff19c918..3f55b16265fc 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -67,7 +67,7 @@ void efx_mcdi_init(struct efx_nic *efx)
67} 67}
68 68
69static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd, 69static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
70 const u8 *inbuf, size_t inlen) 70 const efx_dword_t *inbuf, size_t inlen)
71{ 71{
72 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 72 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
73 unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); 73 unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
@@ -75,9 +75,10 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
75 unsigned int i; 75 unsigned int i;
76 efx_dword_t hdr; 76 efx_dword_t hdr;
77 u32 xflags, seqno; 77 u32 xflags, seqno;
78 unsigned int inlen_dw = DIV_ROUND_UP(inlen, 4);
78 79
79 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); 80 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
80 BUG_ON(inlen & 3 || inlen >= MC_SMEM_PDU_LEN); 81 BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V1);
81 82
82 seqno = mcdi->seqno & SEQ_MASK; 83 seqno = mcdi->seqno & SEQ_MASK;
83 xflags = 0; 84 xflags = 0;
@@ -94,8 +95,8 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
94 95
95 efx_writed(efx, &hdr, pdu); 96 efx_writed(efx, &hdr, pdu);
96 97
97 for (i = 0; i < inlen; i += 4) 98 for (i = 0; i < inlen_dw; i++)
98 _efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i); 99 efx_writed(efx, &inbuf[i], pdu + 4 + 4 * i);
99 100
100 /* Ensure the payload is written out before the header */ 101 /* Ensure the payload is written out before the header */
101 wmb(); 102 wmb();
@@ -104,17 +105,19 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
104 _efx_writed(efx, (__force __le32) 0x45789abc, doorbell); 105 _efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
105} 106}
106 107
107static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) 108static void
109efx_mcdi_copyout(struct efx_nic *efx, efx_dword_t *outbuf, size_t outlen)
108{ 110{
109 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 111 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
110 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); 112 unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
113 unsigned int outlen_dw = DIV_ROUND_UP(outlen, 4);
111 int i; 114 int i;
112 115
113 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); 116 BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
114 BUG_ON(outlen & 3 || outlen >= MC_SMEM_PDU_LEN); 117 BUG_ON(outlen > MCDI_CTL_SDU_LEN_MAX_V1);
115 118
116 for (i = 0; i < outlen; i += 4) 119 for (i = 0; i < outlen_dw; i++)
117 *((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i); 120 efx_readd(efx, &outbuf[i], pdu + 4 + 4 * i);
118} 121}
119 122
120static int efx_mcdi_poll(struct efx_nic *efx) 123static int efx_mcdi_poll(struct efx_nic *efx)
@@ -328,7 +331,8 @@ static void efx_mcdi_ev_cpl(struct efx_nic *efx, unsigned int seqno,
328} 331}
329 332
330int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, 333int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
331 const u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen, 334 const efx_dword_t *inbuf, size_t inlen,
335 efx_dword_t *outbuf, size_t outlen,
332 size_t *outlen_actual) 336 size_t *outlen_actual)
333{ 337{
334 efx_mcdi_rpc_start(efx, cmd, inbuf, inlen); 338 efx_mcdi_rpc_start(efx, cmd, inbuf, inlen);
@@ -336,8 +340,8 @@ int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
336 outbuf, outlen, outlen_actual); 340 outbuf, outlen, outlen_actual);
337} 341}
338 342
339void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, const u8 *inbuf, 343void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
340 size_t inlen) 344 const efx_dword_t *inbuf, size_t inlen)
341{ 345{
342 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 346 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
343 347
@@ -354,7 +358,8 @@ void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, const u8 *inbuf,
354} 358}
355 359
356int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, 360int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
357 u8 *outbuf, size_t outlen, size_t *outlen_actual) 361 efx_dword_t *outbuf, size_t outlen,
362 size_t *outlen_actual)
358{ 363{
359 struct efx_mcdi_iface *mcdi = efx_mcdi(efx); 364 struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
360 int rc; 365 int rc;
@@ -393,7 +398,7 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
393 398
394 if (rc == 0) { 399 if (rc == 0) {
395 efx_mcdi_copyout(efx, outbuf, 400 efx_mcdi_copyout(efx, outbuf,
396 min(outlen, mcdi->resplen + 3) & ~0x3); 401 min(outlen, mcdi->resplen));
397 if (outlen_actual != NULL) 402 if (outlen_actual != NULL)
398 *outlen_actual = resplen; 403 *outlen_actual = resplen;
399 } else if (cmd == MC_CMD_REBOOT && rc == -EIO) 404 } else if (cmd == MC_CMD_REBOOT && rc == -EIO)
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index f8ab64f0efb1..28657a186761 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -67,16 +67,18 @@ struct efx_mcdi_mon {
67 67
68extern void efx_mcdi_init(struct efx_nic *efx); 68extern void efx_mcdi_init(struct efx_nic *efx);
69 69
70extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf, 70extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
71 size_t inlen, u8 *outbuf, size_t outlen, 71 const efx_dword_t *inbuf, size_t inlen,
72 efx_dword_t *outbuf, size_t outlen,
72 size_t *outlen_actual); 73 size_t *outlen_actual);
73 74
74extern void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, 75extern void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
75 const u8 *inbuf, size_t inlen); 76 const efx_dword_t *inbuf, size_t inlen);
76extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, 77extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
77 u8 *outbuf, size_t outlen, 78 efx_dword_t *outbuf, size_t outlen,
78 size_t *outlen_actual); 79 size_t *outlen_actual);
79 80
81
80extern int efx_mcdi_poll_reboot(struct efx_nic *efx); 82extern int efx_mcdi_poll_reboot(struct efx_nic *efx);
81extern void efx_mcdi_mode_poll(struct efx_nic *efx); 83extern void efx_mcdi_mode_poll(struct efx_nic *efx);
82extern void efx_mcdi_mode_event(struct efx_nic *efx); 84extern void efx_mcdi_mode_event(struct efx_nic *efx);
@@ -85,14 +87,21 @@ extern void efx_mcdi_process_event(struct efx_channel *channel,
85 efx_qword_t *event); 87 efx_qword_t *event);
86extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); 88extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
87 89
90/* We expect that 16- and 32-bit fields in MCDI requests and responses
91 * are appropriately aligned. Also, on Siena we must copy to the MC
92 * shared memory strictly 32 bits at a time, so add any necessary
93 * padding.
94 */
88#define MCDI_DECLARE_BUF(_name, _len) \ 95#define MCDI_DECLARE_BUF(_name, _len) \
89 u8 _name[ALIGN(_len, 4)] 96 efx_dword_t _name[DIV_ROUND_UP(_len, 4)]
90#define _MCDI_PTR(_buf, _offset) \ 97#define _MCDI_PTR(_buf, _offset) \
91 ((u8 *)(_buf) + (_offset)) 98 ((u8 *)(_buf) + (_offset))
92#define MCDI_PTR(_buf, _field) \ 99#define MCDI_PTR(_buf, _field) \
93 _MCDI_PTR(_buf, MC_CMD_ ## _field ## _OFST) 100 _MCDI_PTR(_buf, MC_CMD_ ## _field ## _OFST)
101#define _MCDI_CHECK_ALIGN(_ofst, _align) \
102 ((_ofst) + BUILD_BUG_ON_ZERO((_ofst) & (_align - 1)))
94#define _MCDI_DWORD(_buf, _field) \ 103#define _MCDI_DWORD(_buf, _field) \
95 ((efx_dword_t *)MCDI_PTR(_buf, _field)) 104 ((_buf) + (_MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _OFST, 4) >> 2))
96 105
97#define MCDI_SET_DWORD(_buf, _field, _value) \ 106#define MCDI_SET_DWORD(_buf, _field, _value) \
98 EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value) 107 EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
@@ -109,22 +118,23 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
109 (MC_CMD_ ## _type ## _ ## _field ## _LBN & 0x1f) + \ 118 (MC_CMD_ ## _type ## _ ## _field ## _LBN & 0x1f) + \
110 MC_CMD_ ## _type ## _ ## _field ## _WIDTH - 1) 119 MC_CMD_ ## _type ## _ ## _field ## _WIDTH - 1)
111 120
112#define _MCDI_ARRAY_PTR(_buf, _field, _index) \ 121#define _MCDI_ARRAY_PTR(_buf, _field, _index, _align) \
113 (MCDI_PTR(_buf, _field) + \ 122 (_MCDI_PTR(_buf, _MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _OFST, _align))\
114 (_index) * MC_CMD_ ## _field ## _LEN) 123 + (_index) * _MCDI_CHECK_ALIGN(MC_CMD_ ## _field ## _LEN, _align))
115#define MCDI_DECLARE_STRUCT_PTR(_name) \ 124#define MCDI_DECLARE_STRUCT_PTR(_name) \
116 u8 *_name 125 efx_dword_t *_name
117#define MCDI_ARRAY_STRUCT_PTR _MCDI_ARRAY_PTR 126#define MCDI_ARRAY_STRUCT_PTR(_buf, _field, _index) \
127 ((efx_dword_t *)_MCDI_ARRAY_PTR(_buf, _field, _index, 4))
118#define MCDI_VAR_ARRAY_LEN(_len, _field) \ 128#define MCDI_VAR_ARRAY_LEN(_len, _field) \
119 min_t(size_t, MC_CMD_ ## _field ## _MAXNUM, \ 129 min_t(size_t, MC_CMD_ ## _field ## _MAXNUM, \
120 ((_len) - MC_CMD_ ## _field ## _OFST) / MC_CMD_ ## _field ## _LEN) 130 ((_len) - MC_CMD_ ## _field ## _OFST) / MC_CMD_ ## _field ## _LEN)
121#define MCDI_ARRAY_WORD(_buf, _field, _index) \ 131#define MCDI_ARRAY_WORD(_buf, _field, _index) \
122 (BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \ 132 (BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 2) + \
123 le16_to_cpu(*(__force const __le16 *) \ 133 le16_to_cpu(*(__force const __le16 *) \
124 _MCDI_ARRAY_PTR(_buf, _field, _index))) 134 _MCDI_ARRAY_PTR(_buf, _field, _index, 2)))
125#define _MCDI_ARRAY_DWORD(_buf, _field, _index) \ 135#define _MCDI_ARRAY_DWORD(_buf, _field, _index) \
126 (BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 4) + \ 136 (BUILD_BUG_ON_ZERO(MC_CMD_ ## _field ## _LEN != 4) + \
127 (efx_dword_t *)_MCDI_ARRAY_PTR(_buf, _field, _index)) 137 (efx_dword_t *)_MCDI_ARRAY_PTR(_buf, _field, _index, 4))
128#define MCDI_SET_ARRAY_DWORD(_buf, _field, _index, _value) \ 138#define MCDI_SET_ARRAY_DWORD(_buf, _field, _index, _value) \
129 EFX_SET_DWORD_FIELD(*_MCDI_ARRAY_DWORD(_buf, _field, _index), \ 139 EFX_SET_DWORD_FIELD(*_MCDI_ARRAY_DWORD(_buf, _field, _index), \
130 EFX_DWORD_0, _value) 140 EFX_DWORD_0, _value)
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index ec2cf4d7c9b7..5612021d960a 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -571,9 +571,8 @@ static int efx_ptp_xmit_skb(struct efx_nic *efx, struct sk_buff *skb)
571 struct efx_ptp_data *ptp_data = efx->ptp_data; 571 struct efx_ptp_data *ptp_data = efx->ptp_data;
572 struct skb_shared_hwtstamps timestamps; 572 struct skb_shared_hwtstamps timestamps;
573 int rc = -EIO; 573 int rc = -EIO;
574 /* MCDI driver requires word aligned lengths */
575 size_t len = ALIGN(MC_CMD_PTP_IN_TRANSMIT_LEN(skb->len), 4);
576 MCDI_DECLARE_BUF(txtime, MC_CMD_PTP_OUT_TRANSMIT_LEN); 574 MCDI_DECLARE_BUF(txtime, MC_CMD_PTP_OUT_TRANSMIT_LEN);
575 size_t len;
577 576
578 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_OP, MC_CMD_PTP_OP_TRANSMIT); 577 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_OP, MC_CMD_PTP_OP_TRANSMIT);
579 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_TRANSMIT_LENGTH, skb->len); 578 MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_TRANSMIT_LENGTH, skb->len);
@@ -591,9 +590,10 @@ static int efx_ptp_xmit_skb(struct efx_nic *efx, struct sk_buff *skb)
591 skb_copy_from_linear_data(skb, 590 skb_copy_from_linear_data(skb,
592 MCDI_PTR(ptp_data->txbuf, 591 MCDI_PTR(ptp_data->txbuf,
593 PTP_IN_TRANSMIT_PACKET), 592 PTP_IN_TRANSMIT_PACKET),
594 len); 593 skb->len);
595 rc = efx_mcdi_rpc(efx, MC_CMD_PTP, ptp_data->txbuf, len, txtime, 594 rc = efx_mcdi_rpc(efx, MC_CMD_PTP,
596 sizeof(txtime), &len); 595 ptp_data->txbuf, MC_CMD_PTP_IN_TRANSMIT_LEN(skb->len),
596 txtime, sizeof(txtime), &len);
597 if (rc != 0) 597 if (rc != 0)
598 goto fail; 598 goto fail;
599 599