0001
0002
0003
0004
0005
0006 #include "hfi.h"
0007
0008
0009 #define SOP_DISTANCE (TXE_PIO_SIZE / 2)
0010 #define PIO_BLOCK_MASK (PIO_BLOCK_SIZE - 1)
0011
0012 #define PIO_BLOCK_QWS (PIO_BLOCK_SIZE / sizeof(u64))
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 void pio_copy(struct hfi1_devdata *dd, struct pio_buf *pbuf, u64 pbc,
0031 const void *from, size_t count)
0032 {
0033 void __iomem *dest = pbuf->start + SOP_DISTANCE;
0034 void __iomem *send = dest + PIO_BLOCK_SIZE;
0035 void __iomem *dend;
0036
0037
0038 writeq(pbc, dest);
0039 dest += sizeof(u64);
0040
0041
0042 dend = dest + ((count >> 1) * sizeof(u64));
0043
0044 if (dend < send) {
0045
0046
0047
0048
0049
0050 while (dest < dend) {
0051 writeq(*(u64 *)from, dest);
0052 from += sizeof(u64);
0053 dest += sizeof(u64);
0054 }
0055
0056
0057
0058
0059
0060
0061
0062 } else {
0063
0064
0065
0066 while (dest < send) {
0067 writeq(*(u64 *)from, dest);
0068 from += sizeof(u64);
0069 dest += sizeof(u64);
0070 }
0071
0072 dest -= SOP_DISTANCE;
0073 dend -= SOP_DISTANCE;
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 if (pbuf->end <= dend) {
0085 while (dest < pbuf->end) {
0086 writeq(*(u64 *)from, dest);
0087 from += sizeof(u64);
0088 dest += sizeof(u64);
0089 }
0090
0091 dest -= pbuf->sc->size;
0092 dend -= pbuf->sc->size;
0093 }
0094
0095
0096 while (dest < dend) {
0097 writeq(*(u64 *)from, dest);
0098 from += sizeof(u64);
0099 dest += sizeof(u64);
0100 }
0101 }
0102
0103
0104
0105 if (count & 1) {
0106 union mix val;
0107
0108 val.val64 = 0;
0109 val.val32[0] = *(u32 *)from;
0110 writeq(val.val64, dest);
0111 dest += sizeof(u64);
0112 }
0113
0114
0115
0116
0117 while (((unsigned long)dest & PIO_BLOCK_MASK) != 0) {
0118 writeq(0, dest);
0119 dest += sizeof(u64);
0120 }
0121
0122
0123 this_cpu_dec(*pbuf->sc->buffers_allocated);
0124 preempt_enable();
0125 }
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 #define zshift(x) (8 * (8 - (x)))
0138
0139
0140
0141
0142
0143 #define mshift(x) (8 * (x))
0144
0145
0146
0147
0148 static inline void jcopy(u8 *dest, const u8 *src, u32 n)
0149 {
0150 switch (n) {
0151 case 7:
0152 *dest++ = *src++;
0153 fallthrough;
0154 case 6:
0155 *dest++ = *src++;
0156 fallthrough;
0157 case 5:
0158 *dest++ = *src++;
0159 fallthrough;
0160 case 4:
0161 *dest++ = *src++;
0162 fallthrough;
0163 case 3:
0164 *dest++ = *src++;
0165 fallthrough;
0166 case 2:
0167 *dest++ = *src++;
0168 fallthrough;
0169 case 1:
0170 *dest++ = *src++;
0171 }
0172 }
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183 static inline void read_low_bytes(struct pio_buf *pbuf, const void *from,
0184 unsigned int nbytes)
0185 {
0186 pbuf->carry.val64 = 0;
0187 jcopy(&pbuf->carry.val8[0], from, nbytes);
0188 pbuf->carry_bytes = nbytes;
0189 }
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199 static inline void read_extra_bytes(struct pio_buf *pbuf,
0200 const void *from, unsigned int nbytes)
0201 {
0202 jcopy(&pbuf->carry.val8[pbuf->carry_bytes], from, nbytes);
0203 pbuf->carry_bytes += nbytes;
0204 }
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 static inline void merge_write8(
0216 struct pio_buf *pbuf,
0217 void __iomem *dest,
0218 const void *src)
0219 {
0220 u64 new, temp;
0221
0222 new = *(u64 *)src;
0223 temp = pbuf->carry.val64 | (new << mshift(pbuf->carry_bytes));
0224 writeq(temp, dest);
0225 pbuf->carry.val64 = new >> zshift(pbuf->carry_bytes);
0226 }
0227
0228
0229
0230
0231 static inline void carry8_write8(union mix carry, void __iomem *dest)
0232 {
0233 writeq(carry.val64, dest);
0234 }
0235
0236
0237
0238
0239
0240
0241 static inline int carry_write8(struct pio_buf *pbuf, void __iomem *dest)
0242 {
0243 if (pbuf->carry_bytes) {
0244
0245 writeq(pbuf->carry.val64, dest);
0246 return 1;
0247 }
0248
0249 return 0;
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262 void seg_pio_copy_start(struct pio_buf *pbuf, u64 pbc,
0263 const void *from, size_t nbytes)
0264 {
0265 void __iomem *dest = pbuf->start + SOP_DISTANCE;
0266 void __iomem *send = dest + PIO_BLOCK_SIZE;
0267 void __iomem *dend;
0268
0269 writeq(pbc, dest);
0270 dest += sizeof(u64);
0271
0272
0273 dend = dest + ((nbytes >> 3) * sizeof(u64));
0274
0275 if (dend < send) {
0276
0277
0278
0279
0280
0281 while (dest < dend) {
0282 writeq(*(u64 *)from, dest);
0283 from += sizeof(u64);
0284 dest += sizeof(u64);
0285 }
0286
0287
0288
0289
0290
0291
0292
0293 } else {
0294
0295
0296
0297 while (dest < send) {
0298 writeq(*(u64 *)from, dest);
0299 from += sizeof(u64);
0300 dest += sizeof(u64);
0301 }
0302
0303 dest -= SOP_DISTANCE;
0304 dend -= SOP_DISTANCE;
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315 if (pbuf->end <= dend) {
0316 while (dest < pbuf->end) {
0317 writeq(*(u64 *)from, dest);
0318 from += sizeof(u64);
0319 dest += sizeof(u64);
0320 }
0321
0322 dest -= pbuf->sc->size;
0323 dend -= pbuf->sc->size;
0324 }
0325
0326
0327 while (dest < dend) {
0328 writeq(*(u64 *)from, dest);
0329 from += sizeof(u64);
0330 dest += sizeof(u64);
0331 }
0332 }
0333
0334
0335
0336
0337
0338 read_low_bytes(pbuf, from, nbytes & 0x7);
0339
0340 pbuf->qw_written = 1 + (nbytes >> 3);
0341 }
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 static void mid_copy_mix(struct pio_buf *pbuf, const void *from, size_t nbytes)
0356 {
0357 void __iomem *dest = pbuf->start + (pbuf->qw_written * sizeof(u64));
0358 void __iomem *dend;
0359 unsigned long qw_to_write = nbytes >> 3;
0360 unsigned long bytes_left = nbytes & 0x7;
0361
0362
0363 dend = dest + (qw_to_write * sizeof(u64));
0364
0365 if (pbuf->qw_written < PIO_BLOCK_QWS) {
0366
0367
0368
0369
0370
0371 void __iomem *send;
0372 void __iomem *xend;
0373
0374
0375
0376
0377
0378 send = pbuf->start + PIO_BLOCK_SIZE;
0379 xend = min(send, dend);
0380
0381
0382 dest += SOP_DISTANCE;
0383 xend += SOP_DISTANCE;
0384
0385
0386 while (dest < xend) {
0387 merge_write8(pbuf, dest, from);
0388 from += sizeof(u64);
0389 dest += sizeof(u64);
0390 }
0391
0392
0393 dest -= SOP_DISTANCE;
0394 }
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412 if (pbuf->end <= dend) {
0413 while (dest < pbuf->end) {
0414 merge_write8(pbuf, dest, from);
0415 from += sizeof(u64);
0416 dest += sizeof(u64);
0417 }
0418
0419 dest -= pbuf->sc->size;
0420 dend -= pbuf->sc->size;
0421 }
0422
0423
0424 while (dest < dend) {
0425 merge_write8(pbuf, dest, from);
0426 from += sizeof(u64);
0427 dest += sizeof(u64);
0428 }
0429
0430 pbuf->qw_written += qw_to_write;
0431
0432
0433 if (pbuf->carry_bytes + bytes_left >= 8) {
0434 unsigned long nread;
0435
0436
0437 nread = 8 - pbuf->carry_bytes;
0438 read_extra_bytes(pbuf, from, nread);
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452 if (dest >= pbuf->end)
0453 dest -= pbuf->sc->size;
0454
0455 else if (pbuf->qw_written < PIO_BLOCK_QWS)
0456 dest += SOP_DISTANCE;
0457
0458
0459 carry8_write8(pbuf->carry, dest);
0460 pbuf->qw_written++;
0461
0462
0463 bytes_left -= nread;
0464 from += nread;
0465 read_low_bytes(pbuf, from, bytes_left);
0466 } else {
0467
0468 read_extra_bytes(pbuf, from, bytes_left);
0469 }
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482 static void mid_copy_straight(struct pio_buf *pbuf,
0483 const void *from, size_t nbytes)
0484 {
0485 void __iomem *dest = pbuf->start + (pbuf->qw_written * sizeof(u64));
0486 void __iomem *dend;
0487
0488
0489 dend = dest + ((nbytes >> 3) * sizeof(u64));
0490
0491 if (pbuf->qw_written < PIO_BLOCK_QWS) {
0492
0493
0494
0495
0496
0497 void __iomem *send;
0498 void __iomem *xend;
0499
0500
0501
0502
0503
0504 send = pbuf->start + PIO_BLOCK_SIZE;
0505 xend = min(send, dend);
0506
0507
0508 dest += SOP_DISTANCE;
0509 xend += SOP_DISTANCE;
0510
0511
0512 while (dest < xend) {
0513 writeq(*(u64 *)from, dest);
0514 from += sizeof(u64);
0515 dest += sizeof(u64);
0516 }
0517
0518
0519 dest -= SOP_DISTANCE;
0520 }
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538 if (pbuf->end <= dend) {
0539 while (dest < pbuf->end) {
0540 writeq(*(u64 *)from, dest);
0541 from += sizeof(u64);
0542 dest += sizeof(u64);
0543 }
0544
0545 dest -= pbuf->sc->size;
0546 dend -= pbuf->sc->size;
0547 }
0548
0549
0550 while (dest < dend) {
0551 writeq(*(u64 *)from, dest);
0552 from += sizeof(u64);
0553 dest += sizeof(u64);
0554 }
0555
0556
0557 read_low_bytes(pbuf, from, nbytes & 0x7);
0558
0559 pbuf->qw_written += nbytes >> 3;
0560 }
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571 void seg_pio_copy_mid(struct pio_buf *pbuf, const void *from, size_t nbytes)
0572 {
0573 unsigned long from_align = (unsigned long)from & 0x7;
0574
0575 if (pbuf->carry_bytes + nbytes < 8) {
0576
0577 read_extra_bytes(pbuf, from, nbytes);
0578 return;
0579 }
0580
0581 if (from_align) {
0582
0583 unsigned long to_align;
0584
0585
0586 to_align = 8 - from_align;
0587
0588
0589
0590
0591
0592
0593
0594 if (pbuf->carry_bytes + to_align < 8) {
0595
0596 read_extra_bytes(pbuf, from, to_align);
0597 from += to_align;
0598 nbytes -= to_align;
0599 } else {
0600
0601 unsigned long to_fill = 8 - pbuf->carry_bytes;
0602
0603 unsigned long extra = to_align - to_fill;
0604 void __iomem *dest;
0605
0606
0607 read_extra_bytes(pbuf, from, to_fill);
0608 from += to_fill;
0609 nbytes -= to_fill;
0610
0611 if (extra > nbytes)
0612 extra = nbytes;
0613
0614
0615 dest = pbuf->start + (pbuf->qw_written * sizeof(u64));
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626 if (dest >= pbuf->end)
0627 dest -= pbuf->sc->size;
0628
0629 else if (pbuf->qw_written < PIO_BLOCK_QWS)
0630 dest += SOP_DISTANCE;
0631
0632 carry8_write8(pbuf->carry, dest);
0633 pbuf->qw_written++;
0634
0635
0636
0637 read_low_bytes(pbuf, from, extra);
0638 from += extra;
0639 nbytes -= extra;
0640
0641
0642
0643
0644
0645
0646
0647 if (nbytes == 0)
0648 return;
0649 }
0650
0651
0652 }
0653
0654 if (pbuf->carry_bytes)
0655 mid_copy_mix(pbuf, from, nbytes);
0656 else
0657 mid_copy_straight(pbuf, from, nbytes);
0658 }
0659
0660
0661
0662
0663
0664
0665
0666
0667 void seg_pio_copy_end(struct pio_buf *pbuf)
0668 {
0669 void __iomem *dest = pbuf->start + (pbuf->qw_written * sizeof(u64));
0670
0671
0672
0673
0674
0675
0676
0677
0678
0679 if (dest >= pbuf->end)
0680 dest -= pbuf->sc->size;
0681
0682 else if (pbuf->qw_written < PIO_BLOCK_QWS)
0683 dest += SOP_DISTANCE;
0684
0685
0686 if (carry_write8(pbuf, dest)) {
0687 dest += sizeof(u64);
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703
0704 }
0705
0706
0707 while (((unsigned long)dest & PIO_BLOCK_MASK) != 0) {
0708 writeq(0, dest);
0709 dest += sizeof(u64);
0710 }
0711
0712
0713 this_cpu_dec(*pbuf->sc->buffers_allocated);
0714 preempt_enable();
0715 }