diff options
| -rw-r--r-- | drivers/net/sfc/mcdi.c | 49 | ||||
| -rw-r--r-- | drivers/net/sfc/nic.h | 2 | ||||
| -rw-r--r-- | drivers/net/sfc/siena.c | 25 |
3 files changed, 53 insertions, 23 deletions
diff --git a/drivers/net/sfc/mcdi.c b/drivers/net/sfc/mcdi.c index d98479030ef2..3dd45ed61f0a 100644 --- a/drivers/net/sfc/mcdi.c +++ b/drivers/net/sfc/mcdi.c | |||
| @@ -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 | ||
| 53 | static inline void | ||
| 54 | efx_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 | |||
| 60 | static inline void | ||
| 61 | efx_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 | |||
| 53 | void efx_mcdi_init(struct efx_nic *efx) | 67 | void 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,30 +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 | /* use wmb() within loop to inhibit write combining */ | 113 | pdu + 4 + i); |
| 100 | wmb(); | ||
| 101 | } | ||
| 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); |
| 105 | wmb(); | 117 | efx_mcdi_writed(efx, &hdr, doorbell); |
| 106 | } | 118 | } |
| 107 | 119 | ||
| 108 | static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) | 120 | static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) |
| 109 | { | 121 | { |
| 110 | struct efx_mcdi_iface *mcdi = efx_mcdi(efx); | 122 | struct efx_mcdi_iface *mcdi = efx_mcdi(efx); |
| 111 | unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); | 123 | unsigned int pdu = MCDI_PDU(efx); |
| 112 | int i; | 124 | int i; |
| 113 | 125 | ||
| 114 | BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); | 126 | BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT); |
| 115 | BUG_ON(outlen & 3 || outlen >= 0x100); | 127 | BUG_ON(outlen & 3 || outlen >= 0x100); |
| 116 | 128 | ||
| 117 | for (i = 0; i < outlen; i += 4) | 129 | for (i = 0; i < outlen; i += 4) |
| 118 | *((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i); | 130 | efx_mcdi_readd(efx, (efx_dword_t *)(outbuf + i), pdu + 4 + i); |
| 119 | } | 131 | } |
| 120 | 132 | ||
| 121 | static int efx_mcdi_poll(struct efx_nic *efx) | 133 | static int efx_mcdi_poll(struct efx_nic *efx) |
| @@ -123,7 +135,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) | |||
| 123 | struct efx_mcdi_iface *mcdi = efx_mcdi(efx); | 135 | struct efx_mcdi_iface *mcdi = efx_mcdi(efx); |
| 124 | unsigned int time, finish; | 136 | unsigned int time, finish; |
| 125 | unsigned int respseq, respcmd, error; | 137 | unsigned int respseq, respcmd, error; |
| 126 | unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); | 138 | unsigned int pdu = MCDI_PDU(efx); |
| 127 | unsigned int rc, spins; | 139 | unsigned int rc, spins; |
| 128 | efx_dword_t reg; | 140 | efx_dword_t reg; |
| 129 | 141 | ||
| @@ -149,8 +161,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) | |||
| 149 | 161 | ||
| 150 | time = get_seconds(); | 162 | time = get_seconds(); |
| 151 | 163 | ||
| 152 | rmb(); | 164 | efx_mcdi_readd(efx, ®, pdu); |
| 153 | efx_readd(efx, ®, pdu); | ||
| 154 | 165 | ||
| 155 | /* 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 |
| 156 | * 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 |
| @@ -177,7 +188,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) | |||
| 177 | respseq, mcdi->seqno); | 188 | respseq, mcdi->seqno); |
| 178 | rc = EIO; | 189 | rc = EIO; |
| 179 | } else if (error) { | 190 | } else if (error) { |
| 180 | efx_readd(efx, ®, pdu + 4); | 191 | efx_mcdi_readd(efx, ®, pdu + 4); |
| 181 | switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) { | 192 | switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) { |
| 182 | #define TRANSLATE_ERROR(name) \ | 193 | #define TRANSLATE_ERROR(name) \ |
| 183 | case MC_CMD_ERR_ ## name: \ | 194 | case MC_CMD_ERR_ ## name: \ |
| @@ -211,21 +222,21 @@ out: | |||
| 211 | /* Test and clear MC-rebooted flag for this port/function */ | 222 | /* Test and clear MC-rebooted flag for this port/function */ |
| 212 | int efx_mcdi_poll_reboot(struct efx_nic *efx) | 223 | int efx_mcdi_poll_reboot(struct efx_nic *efx) |
| 213 | { | 224 | { |
| 214 | unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx); | 225 | unsigned int addr = MCDI_REBOOT_FLAG(efx); |
| 215 | efx_dword_t reg; | 226 | efx_dword_t reg; |
| 216 | uint32_t value; | 227 | uint32_t value; |
| 217 | 228 | ||
| 218 | if (efx_nic_rev(efx) < EFX_REV_SIENA_A0) | 229 | if (efx_nic_rev(efx) < EFX_REV_SIENA_A0) |
| 219 | return false; | 230 | return false; |
| 220 | 231 | ||
| 221 | efx_readd(efx, ®, addr); | 232 | efx_mcdi_readd(efx, ®, addr); |
| 222 | value = EFX_DWORD_FIELD(reg, EFX_DWORD_0); | 233 | value = EFX_DWORD_FIELD(reg, EFX_DWORD_0); |
| 223 | 234 | ||
| 224 | if (value == 0) | 235 | if (value == 0) |
| 225 | return 0; | 236 | return 0; |
| 226 | 237 | ||
| 227 | EFX_ZERO_DWORD(reg); | 238 | EFX_ZERO_DWORD(reg); |
| 228 | efx_writed(efx, ®, addr); | 239 | efx_mcdi_writed(efx, ®, addr); |
| 229 | 240 | ||
| 230 | if (value == MC_STATUS_DWORD_ASSERT) | 241 | if (value == MC_STATUS_DWORD_ASSERT) |
| 231 | return -EINTR; | 242 | return -EINTR; |
diff --git a/drivers/net/sfc/nic.h b/drivers/net/sfc/nic.h index a42db6e35be3..d91701abd331 100644 --- a/drivers/net/sfc/nic.h +++ b/drivers/net/sfc/nic.h | |||
| @@ -143,10 +143,12 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx) | |||
| 143 | /** | 143 | /** |
| 144 | * struct siena_nic_data - Siena NIC state | 144 | * struct siena_nic_data - Siena NIC state |
| 145 | * @mcdi: Management-Controller-to-Driver Interface | 145 | * @mcdi: Management-Controller-to-Driver Interface |
| 146 | * @mcdi_smem: MCDI shared memory mapping. The mapping is always uncacheable. | ||
| 146 | * @wol_filter_id: Wake-on-LAN packet filter id | 147 | * @wol_filter_id: Wake-on-LAN packet filter id |
| 147 | */ | 148 | */ |
| 148 | struct siena_nic_data { | 149 | struct siena_nic_data { |
| 149 | struct efx_mcdi_iface mcdi; | 150 | struct efx_mcdi_iface mcdi; |
| 151 | void __iomem *mcdi_smem; | ||
| 150 | int wol_filter_id; | 152 | int wol_filter_id; |
| 151 | }; | 153 | }; |
| 152 | 154 | ||
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index e4dd8986b1fe..837869b71db9 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c | |||
| @@ -220,12 +220,26 @@ static int siena_probe_nic(struct efx_nic *efx) | |||
| 220 | efx_reado(efx, ®, FR_AZ_CS_DEBUG); | 220 | efx_reado(efx, ®, FR_AZ_CS_DEBUG); |
| 221 | efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1; | 221 | efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1; |
| 222 | 222 | ||
| 223 | /* Initialise MCDI */ | ||
| 224 | nic_data->mcdi_smem = ioremap_nocache(efx->membase_phys + | ||
| 225 | FR_CZ_MC_TREG_SMEM, | ||
| 226 | FR_CZ_MC_TREG_SMEM_STEP * | ||
| 227 | FR_CZ_MC_TREG_SMEM_ROWS); | ||
| 228 | if (!nic_data->mcdi_smem) { | ||
| 229 | netif_err(efx, probe, efx->net_dev, | ||
| 230 | "could not map MCDI at %llx+%x\n", | ||
| 231 | (unsigned long long)efx->membase_phys + | ||
| 232 | FR_CZ_MC_TREG_SMEM, | ||
| 233 | FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS); | ||
| 234 | rc = -ENOMEM; | ||
| 235 | goto fail1; | ||
| 236 | } | ||
| 223 | efx_mcdi_init(efx); | 237 | efx_mcdi_init(efx); |
| 224 | 238 | ||
| 225 | /* Recover from a failed assertion before probing */ | 239 | /* Recover from a failed assertion before probing */ |
| 226 | rc = efx_mcdi_handle_assertion(efx); | 240 | rc = efx_mcdi_handle_assertion(efx); |
| 227 | if (rc) | 241 | if (rc) |
| 228 | goto fail1; | 242 | goto fail2; |
| 229 | 243 | ||
| 230 | /* Let the BMC know that the driver is now in charge of link and | 244 | /* Let the BMC know that the driver is now in charge of link and |
| 231 | * filter settings. We must do this before we reset the NIC */ | 245 | * filter settings. We must do this before we reset the NIC */ |
| @@ -280,6 +294,7 @@ fail4: | |||
| 280 | fail3: | 294 | fail3: |
| 281 | efx_mcdi_drv_attach(efx, false, NULL); | 295 | efx_mcdi_drv_attach(efx, false, NULL); |
| 282 | fail2: | 296 | fail2: |
| 297 | iounmap(nic_data->mcdi_smem); | ||
| 283 | fail1: | 298 | fail1: |
| 284 | kfree(efx->nic_data); | 299 | kfree(efx->nic_data); |
| 285 | return rc; | 300 | return rc; |
| @@ -359,6 +374,8 @@ static int siena_init_nic(struct efx_nic *efx) | |||
| 359 | 374 | ||
| 360 | static void siena_remove_nic(struct efx_nic *efx) | 375 | static void siena_remove_nic(struct efx_nic *efx) |
| 361 | { | 376 | { |
| 377 | struct siena_nic_data *nic_data = efx->nic_data; | ||
| 378 | |||
| 362 | efx_nic_free_buffer(efx, &efx->irq_status); | 379 | efx_nic_free_buffer(efx, &efx->irq_status); |
| 363 | 380 | ||
| 364 | siena_reset_hw(efx, RESET_TYPE_ALL); | 381 | siena_reset_hw(efx, RESET_TYPE_ALL); |
| @@ -368,7 +385,8 @@ static void siena_remove_nic(struct efx_nic *efx) | |||
| 368 | efx_mcdi_drv_attach(efx, false, NULL); | 385 | efx_mcdi_drv_attach(efx, false, NULL); |
| 369 | 386 | ||
| 370 | /* Tear down the private nic state */ | 387 | /* Tear down the private nic state */ |
| 371 | kfree(efx->nic_data); | 388 | iounmap(nic_data->mcdi_smem); |
| 389 | kfree(nic_data); | ||
| 372 | efx->nic_data = NULL; | 390 | efx->nic_data = NULL; |
| 373 | } | 391 | } |
| 374 | 392 | ||
| @@ -606,8 +624,7 @@ struct efx_nic_type siena_a0_nic_type = { | |||
| 606 | .default_mac_ops = &efx_mcdi_mac_operations, | 624 | .default_mac_ops = &efx_mcdi_mac_operations, |
| 607 | 625 | ||
| 608 | .revision = EFX_REV_SIENA_A0, | 626 | .revision = EFX_REV_SIENA_A0, |
| 609 | .mem_map_size = (FR_CZ_MC_TREG_SMEM + | 627 | .mem_map_size = FR_CZ_MC_TREG_SMEM, /* MC_TREG_SMEM mapped separately */ |
| 610 | FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS), | ||
| 611 | .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, | 628 | .txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL, |
| 612 | .rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL, | 629 | .rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL, |
| 613 | .buf_tbl_base = FR_BZ_BUF_FULL_TBL, | 630 | .buf_tbl_base = FR_BZ_BUF_FULL_TBL, |
