0001
0002
0003
0004 #include "fm10k_common.h"
0005
0006
0007
0008
0009
0010
0011
0012
0013 s32 fm10k_get_bus_info_generic(struct fm10k_hw *hw)
0014 {
0015 u16 link_cap, link_status, device_cap, device_control;
0016
0017
0018 link_cap = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_LINK_CAP);
0019
0020 switch (link_cap & FM10K_PCIE_LINK_WIDTH) {
0021 case FM10K_PCIE_LINK_WIDTH_1:
0022 hw->bus_caps.width = fm10k_bus_width_pcie_x1;
0023 break;
0024 case FM10K_PCIE_LINK_WIDTH_2:
0025 hw->bus_caps.width = fm10k_bus_width_pcie_x2;
0026 break;
0027 case FM10K_PCIE_LINK_WIDTH_4:
0028 hw->bus_caps.width = fm10k_bus_width_pcie_x4;
0029 break;
0030 case FM10K_PCIE_LINK_WIDTH_8:
0031 hw->bus_caps.width = fm10k_bus_width_pcie_x8;
0032 break;
0033 default:
0034 hw->bus_caps.width = fm10k_bus_width_unknown;
0035 break;
0036 }
0037
0038 switch (link_cap & FM10K_PCIE_LINK_SPEED) {
0039 case FM10K_PCIE_LINK_SPEED_2500:
0040 hw->bus_caps.speed = fm10k_bus_speed_2500;
0041 break;
0042 case FM10K_PCIE_LINK_SPEED_5000:
0043 hw->bus_caps.speed = fm10k_bus_speed_5000;
0044 break;
0045 case FM10K_PCIE_LINK_SPEED_8000:
0046 hw->bus_caps.speed = fm10k_bus_speed_8000;
0047 break;
0048 default:
0049 hw->bus_caps.speed = fm10k_bus_speed_unknown;
0050 break;
0051 }
0052
0053
0054 device_cap = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_DEV_CAP);
0055
0056 switch (device_cap & FM10K_PCIE_DEV_CAP_PAYLOAD) {
0057 case FM10K_PCIE_DEV_CAP_PAYLOAD_128:
0058 hw->bus_caps.payload = fm10k_bus_payload_128;
0059 break;
0060 case FM10K_PCIE_DEV_CAP_PAYLOAD_256:
0061 hw->bus_caps.payload = fm10k_bus_payload_256;
0062 break;
0063 case FM10K_PCIE_DEV_CAP_PAYLOAD_512:
0064 hw->bus_caps.payload = fm10k_bus_payload_512;
0065 break;
0066 default:
0067 hw->bus_caps.payload = fm10k_bus_payload_unknown;
0068 break;
0069 }
0070
0071
0072 link_status = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_LINK_STATUS);
0073
0074 switch (link_status & FM10K_PCIE_LINK_WIDTH) {
0075 case FM10K_PCIE_LINK_WIDTH_1:
0076 hw->bus.width = fm10k_bus_width_pcie_x1;
0077 break;
0078 case FM10K_PCIE_LINK_WIDTH_2:
0079 hw->bus.width = fm10k_bus_width_pcie_x2;
0080 break;
0081 case FM10K_PCIE_LINK_WIDTH_4:
0082 hw->bus.width = fm10k_bus_width_pcie_x4;
0083 break;
0084 case FM10K_PCIE_LINK_WIDTH_8:
0085 hw->bus.width = fm10k_bus_width_pcie_x8;
0086 break;
0087 default:
0088 hw->bus.width = fm10k_bus_width_unknown;
0089 break;
0090 }
0091
0092 switch (link_status & FM10K_PCIE_LINK_SPEED) {
0093 case FM10K_PCIE_LINK_SPEED_2500:
0094 hw->bus.speed = fm10k_bus_speed_2500;
0095 break;
0096 case FM10K_PCIE_LINK_SPEED_5000:
0097 hw->bus.speed = fm10k_bus_speed_5000;
0098 break;
0099 case FM10K_PCIE_LINK_SPEED_8000:
0100 hw->bus.speed = fm10k_bus_speed_8000;
0101 break;
0102 default:
0103 hw->bus.speed = fm10k_bus_speed_unknown;
0104 break;
0105 }
0106
0107
0108 device_control = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_DEV_CTRL);
0109
0110 switch (device_control & FM10K_PCIE_DEV_CTRL_PAYLOAD) {
0111 case FM10K_PCIE_DEV_CTRL_PAYLOAD_128:
0112 hw->bus.payload = fm10k_bus_payload_128;
0113 break;
0114 case FM10K_PCIE_DEV_CTRL_PAYLOAD_256:
0115 hw->bus.payload = fm10k_bus_payload_256;
0116 break;
0117 case FM10K_PCIE_DEV_CTRL_PAYLOAD_512:
0118 hw->bus.payload = fm10k_bus_payload_512;
0119 break;
0120 default:
0121 hw->bus.payload = fm10k_bus_payload_unknown;
0122 break;
0123 }
0124
0125 return 0;
0126 }
0127
0128 static u16 fm10k_get_pcie_msix_count_generic(struct fm10k_hw *hw)
0129 {
0130 u16 msix_count;
0131
0132
0133 msix_count = fm10k_read_pci_cfg_word(hw, FM10K_PCI_MSIX_MSG_CTRL);
0134 msix_count &= FM10K_PCI_MSIX_MSG_CTRL_TBL_SZ_MASK;
0135
0136
0137 msix_count++;
0138
0139 if (msix_count > FM10K_MAX_MSIX_VECTORS)
0140 msix_count = FM10K_MAX_MSIX_VECTORS;
0141
0142 return msix_count;
0143 }
0144
0145
0146
0147
0148
0149
0150
0151 s32 fm10k_get_invariants_generic(struct fm10k_hw *hw)
0152 {
0153 struct fm10k_mac_info *mac = &hw->mac;
0154
0155
0156 mac->dglort_map = FM10K_DGLORTMAP_NONE;
0157
0158
0159 mac->max_msix_vectors = fm10k_get_pcie_msix_count_generic(hw);
0160
0161 return 0;
0162 }
0163
0164
0165
0166
0167
0168
0169
0170
0171 s32 fm10k_start_hw_generic(struct fm10k_hw *hw)
0172 {
0173
0174 hw->mac.tx_ready = true;
0175
0176 return 0;
0177 }
0178
0179
0180
0181
0182
0183
0184
0185 s32 fm10k_disable_queues_generic(struct fm10k_hw *hw, u16 q_cnt)
0186 {
0187 u32 reg;
0188 u16 i, time;
0189
0190
0191 hw->mac.tx_ready = false;
0192
0193 if (FM10K_REMOVED(hw->hw_addr))
0194 return 0;
0195
0196
0197 for (i = 0; i < q_cnt; i++) {
0198 reg = fm10k_read_reg(hw, FM10K_TXDCTL(i));
0199 fm10k_write_reg(hw, FM10K_TXDCTL(i),
0200 reg & ~FM10K_TXDCTL_ENABLE);
0201 reg = fm10k_read_reg(hw, FM10K_RXQCTL(i));
0202 fm10k_write_reg(hw, FM10K_RXQCTL(i),
0203 reg & ~FM10K_RXQCTL_ENABLE);
0204 }
0205
0206 fm10k_write_flush(hw);
0207 udelay(1);
0208
0209
0210 for (i = 0, time = FM10K_QUEUE_DISABLE_TIMEOUT; time;) {
0211
0212 if (i == q_cnt)
0213 return 0;
0214
0215
0216 reg = fm10k_read_reg(hw, FM10K_TXDCTL(i));
0217 if (!~reg || !(reg & FM10K_TXDCTL_ENABLE)) {
0218 reg = fm10k_read_reg(hw, FM10K_RXQCTL(i));
0219 if (!~reg || !(reg & FM10K_RXQCTL_ENABLE)) {
0220 i++;
0221 continue;
0222 }
0223 }
0224
0225
0226 time--;
0227 if (time)
0228 udelay(1);
0229 }
0230
0231 return FM10K_ERR_REQUESTS_PENDING;
0232 }
0233
0234
0235
0236
0237
0238
0239 s32 fm10k_stop_hw_generic(struct fm10k_hw *hw)
0240 {
0241 return fm10k_disable_queues_generic(hw, hw->mac.max_queues);
0242 }
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 u32 fm10k_read_hw_stats_32b(struct fm10k_hw *hw, u32 addr,
0254 struct fm10k_hw_stat *stat)
0255 {
0256 u32 delta = fm10k_read_reg(hw, addr) - stat->base_l;
0257
0258 if (FM10K_REMOVED(hw->hw_addr))
0259 stat->base_h = 0;
0260
0261 return delta;
0262 }
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 static u64 fm10k_read_hw_stats_48b(struct fm10k_hw *hw, u32 addr,
0276 struct fm10k_hw_stat *stat)
0277 {
0278 u32 count_l;
0279 u32 count_h;
0280 u32 count_tmp;
0281 u64 delta;
0282
0283 count_h = fm10k_read_reg(hw, addr + 1);
0284
0285
0286 do {
0287 count_tmp = count_h;
0288 count_l = fm10k_read_reg(hw, addr);
0289 count_h = fm10k_read_reg(hw, addr + 1);
0290 } while (count_h != count_tmp);
0291
0292 delta = ((u64)(count_h - stat->base_h) << 32) + count_l;
0293 delta -= stat->base_l;
0294
0295 return delta & FM10K_48_BIT_MASK;
0296 }
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306 static void fm10k_update_hw_base_48b(struct fm10k_hw_stat *stat, u64 delta)
0307 {
0308 if (!delta)
0309 return;
0310
0311
0312 delta += stat->base_l;
0313 stat->base_l = (u32)delta;
0314
0315
0316 stat->base_h += (u32)(delta >> 32);
0317 }
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328 static void fm10k_update_hw_stats_tx_q(struct fm10k_hw *hw,
0329 struct fm10k_hw_stats_q *q,
0330 u32 idx)
0331 {
0332 u32 id_tx, id_tx_prev, tx_packets;
0333 u64 tx_bytes = 0;
0334
0335
0336 id_tx = fm10k_read_reg(hw, FM10K_TXQCTL(idx));
0337
0338
0339 do {
0340 tx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPTC(idx),
0341 &q->tx_packets);
0342
0343 if (tx_packets)
0344 tx_bytes = fm10k_read_hw_stats_48b(hw,
0345 FM10K_QBTC_L(idx),
0346 &q->tx_bytes);
0347
0348
0349 id_tx_prev = id_tx;
0350 id_tx = fm10k_read_reg(hw, FM10K_TXQCTL(idx));
0351 } while ((id_tx ^ id_tx_prev) & FM10K_TXQCTL_ID_MASK);
0352
0353
0354 id_tx &= FM10K_TXQCTL_ID_MASK;
0355 id_tx |= FM10K_STAT_VALID;
0356
0357
0358 if (q->tx_stats_idx == id_tx) {
0359 q->tx_packets.count += tx_packets;
0360 q->tx_bytes.count += tx_bytes;
0361 }
0362
0363
0364 fm10k_update_hw_base_32b(&q->tx_packets, tx_packets);
0365 fm10k_update_hw_base_48b(&q->tx_bytes, tx_bytes);
0366
0367 q->tx_stats_idx = id_tx;
0368 }
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379 static void fm10k_update_hw_stats_rx_q(struct fm10k_hw *hw,
0380 struct fm10k_hw_stats_q *q,
0381 u32 idx)
0382 {
0383 u32 id_rx, id_rx_prev, rx_packets, rx_drops;
0384 u64 rx_bytes = 0;
0385
0386
0387 id_rx = fm10k_read_reg(hw, FM10K_RXQCTL(idx));
0388
0389
0390 do {
0391 rx_drops = fm10k_read_hw_stats_32b(hw, FM10K_QPRDC(idx),
0392 &q->rx_drops);
0393
0394 rx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPRC(idx),
0395 &q->rx_packets);
0396
0397 if (rx_packets)
0398 rx_bytes = fm10k_read_hw_stats_48b(hw,
0399 FM10K_QBRC_L(idx),
0400 &q->rx_bytes);
0401
0402
0403 id_rx_prev = id_rx;
0404 id_rx = fm10k_read_reg(hw, FM10K_RXQCTL(idx));
0405 } while ((id_rx ^ id_rx_prev) & FM10K_RXQCTL_ID_MASK);
0406
0407
0408 id_rx &= FM10K_RXQCTL_ID_MASK;
0409 id_rx |= FM10K_STAT_VALID;
0410
0411
0412 if (q->rx_stats_idx == id_rx) {
0413 q->rx_drops.count += rx_drops;
0414 q->rx_packets.count += rx_packets;
0415 q->rx_bytes.count += rx_bytes;
0416 }
0417
0418
0419 fm10k_update_hw_base_32b(&q->rx_drops, rx_drops);
0420 fm10k_update_hw_base_32b(&q->rx_packets, rx_packets);
0421 fm10k_update_hw_base_48b(&q->rx_bytes, rx_bytes);
0422
0423 q->rx_stats_idx = id_rx;
0424 }
0425
0426
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436 void fm10k_update_hw_stats_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q,
0437 u32 idx, u32 count)
0438 {
0439 u32 i;
0440
0441 for (i = 0; i < count; i++, idx++, q++) {
0442 fm10k_update_hw_stats_tx_q(hw, q, idx);
0443 fm10k_update_hw_stats_rx_q(hw, q, idx);
0444 }
0445 }
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 idx, u32 count)
0457 {
0458 u32 i;
0459
0460 for (i = 0; i < count; i++, idx++, q++) {
0461 q->rx_stats_idx = 0;
0462 q->tx_stats_idx = 0;
0463 }
0464 }
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474 s32 fm10k_get_host_state_generic(struct fm10k_hw *hw, bool *host_ready)
0475 {
0476 struct fm10k_mbx_info *mbx = &hw->mbx;
0477 struct fm10k_mac_info *mac = &hw->mac;
0478 s32 ret_val = 0;
0479 u32 txdctl = fm10k_read_reg(hw, FM10K_TXDCTL(0));
0480
0481
0482 mbx->ops.process(hw, mbx);
0483
0484
0485 if (!(~txdctl) || !(txdctl & FM10K_TXDCTL_ENABLE))
0486 mac->get_host_state = true;
0487
0488
0489 if (!mac->get_host_state || !(~txdctl))
0490 goto out;
0491
0492
0493 if (mac->tx_ready && !(txdctl & FM10K_TXDCTL_ENABLE)) {
0494 ret_val = FM10K_ERR_RESET_REQUESTED;
0495 goto out;
0496 }
0497
0498
0499 if (!mbx->timeout) {
0500 ret_val = FM10K_ERR_RESET_REQUESTED;
0501 goto out;
0502 }
0503
0504
0505 if (mbx->state != FM10K_STATE_OPEN)
0506 goto out;
0507
0508
0509 if (mac->dglort_map == FM10K_DGLORTMAP_NONE) {
0510 if (mac->ops.request_lport_map)
0511 ret_val = mac->ops.request_lport_map(hw);
0512
0513 goto out;
0514 }
0515
0516
0517
0518
0519 mac->get_host_state = false;
0520
0521 out:
0522 *host_ready = !mac->get_host_state;
0523 return ret_val;
0524 }