diff options
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.c | 31 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/mcdi.h | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/sfc/ptp.c | 10 |
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 | ||
69 | static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd, | 69 | static 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 | ||
107 | static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) | 108 | static void |
109 | efx_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 | ||
120 | static int efx_mcdi_poll(struct efx_nic *efx) | 123 | static 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 | ||
330 | int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, | 333 | int 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 | ||
339 | void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, const u8 *inbuf, | 343 | void 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 | ||
356 | int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, | 360 | int 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 | ||
68 | extern void efx_mcdi_init(struct efx_nic *efx); | 68 | extern void efx_mcdi_init(struct efx_nic *efx); |
69 | 69 | ||
70 | extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd, const u8 *inbuf, | 70 | extern 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 | ||
74 | extern void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, | 75 | extern 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); |
76 | extern int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, | 77 | extern 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 | |||
80 | extern int efx_mcdi_poll_reboot(struct efx_nic *efx); | 82 | extern int efx_mcdi_poll_reboot(struct efx_nic *efx); |
81 | extern void efx_mcdi_mode_poll(struct efx_nic *efx); | 83 | extern void efx_mcdi_mode_poll(struct efx_nic *efx); |
82 | extern void efx_mcdi_mode_event(struct efx_nic *efx); | 84 | extern 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); |
86 | extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); | 88 | extern 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 | ||