23
23
#include <linux/sizes.h>
24
24
#include <linux/atomic.h>
25
25
#include <linux/skbuff.h>
26
+ #include <linux/io.h>
26
27
#include <asm/barrier.h>
27
28
#include <asm/byteorder.h>
28
29
32
33
#include "hinic_hw_wq.h"
33
34
#include "hinic_hw_qp_ctxt.h"
34
35
#include "hinic_hw_qp.h"
36
+ #include "hinic_hw_io.h"
35
37
36
38
#define SQ_DB_OFF SZ_2K
37
39
53
55
(((max_rqs) + (max_sqs)) * CTXT_RSVD + \
54
56
(max_sqs + (q_id)) * Q_CTXT_SIZE)
55
57
56
- #define SIZE_16BYTES (size ) (ALIGN(size, 16) >> 4)
57
- #define SIZE_8BYTES (size ) (ALIGN(size, 8) >> 3)
58
+ #define SIZE_16BYTES (size ) (ALIGN(size, 16) >> 4)
59
+ #define SIZE_8BYTES (size ) (ALIGN(size, 8) >> 3)
60
+ #define SECT_SIZE_FROM_8BYTES (size ) ((size) << 3)
58
61
62
+ #define SQ_DB_PI_HI_SHIFT 8
63
+ #define SQ_DB_PI_HI (prod_idx ) ((prod_idx) >> SQ_DB_PI_HI_SHIFT)
64
+
65
+ #define SQ_DB_PI_LOW_MASK 0xFF
66
+ #define SQ_DB_PI_LOW (prod_idx ) ((prod_idx) & SQ_DB_PI_LOW_MASK)
67
+
68
+ #define SQ_DB_ADDR (sq , pi ) ((u64 *)((sq)->db_base) + SQ_DB_PI_LOW(pi))
69
+
70
+ #define SQ_MASKED_IDX (sq , idx ) ((idx) & (sq)->wq->mask)
59
71
#define RQ_MASKED_IDX (rq , idx ) ((idx) & (rq)->wq->mask)
60
72
73
+ #define TX_MAX_MSS_DEFAULT 0x3E00
74
+
75
+ enum sq_wqe_type {
76
+ SQ_NORMAL_WQE = 0 ,
77
+ };
78
+
61
79
enum rq_completion_fmt {
62
80
RQ_COMPLETE_SGE = 1
63
81
};
@@ -435,6 +453,19 @@ void hinic_clean_rq(struct hinic_rq *rq)
435
453
free_rq_skb_arr (rq );
436
454
}
437
455
456
+ /**
457
+ * hinic_get_sq_free_wqebbs - return number of free wqebbs for use
458
+ * @sq: send queue
459
+ *
460
+ * Return number of free wqebbs
461
+ **/
462
+ int hinic_get_sq_free_wqebbs (struct hinic_sq * sq )
463
+ {
464
+ struct hinic_wq * wq = sq -> wq ;
465
+
466
+ return atomic_read (& wq -> delta ) - 1 ;
467
+ }
468
+
438
469
/**
439
470
* hinic_get_rq_free_wqebbs - return number of free wqebbs for use
440
471
* @rq: recv queue
@@ -448,6 +479,228 @@ int hinic_get_rq_free_wqebbs(struct hinic_rq *rq)
448
479
return atomic_read (& wq -> delta ) - 1 ;
449
480
}
450
481
482
+ static void sq_prepare_ctrl (struct hinic_sq_ctrl * ctrl , u16 prod_idx ,
483
+ int nr_descs )
484
+ {
485
+ u32 ctrl_size , task_size , bufdesc_size ;
486
+
487
+ ctrl_size = SIZE_8BYTES (sizeof (struct hinic_sq_ctrl ));
488
+ task_size = SIZE_8BYTES (sizeof (struct hinic_sq_task ));
489
+ bufdesc_size = nr_descs * sizeof (struct hinic_sq_bufdesc );
490
+ bufdesc_size = SIZE_8BYTES (bufdesc_size );
491
+
492
+ ctrl -> ctrl_info = HINIC_SQ_CTRL_SET (bufdesc_size , BUFDESC_SECT_LEN ) |
493
+ HINIC_SQ_CTRL_SET (task_size , TASKSECT_LEN ) |
494
+ HINIC_SQ_CTRL_SET (SQ_NORMAL_WQE , DATA_FORMAT ) |
495
+ HINIC_SQ_CTRL_SET (ctrl_size , LEN );
496
+
497
+ ctrl -> queue_info = HINIC_SQ_CTRL_SET (TX_MAX_MSS_DEFAULT ,
498
+ QUEUE_INFO_MSS );
499
+ }
500
+
501
+ static void sq_prepare_task (struct hinic_sq_task * task )
502
+ {
503
+ task -> pkt_info0 =
504
+ HINIC_SQ_TASK_INFO0_SET (0 , L2HDR_LEN ) |
505
+ HINIC_SQ_TASK_INFO0_SET (HINIC_L4_OFF_DISABLE , L4_OFFLOAD ) |
506
+ HINIC_SQ_TASK_INFO0_SET (HINIC_OUTER_L3TYPE_UNKNOWN ,
507
+ INNER_L3TYPE ) |
508
+ HINIC_SQ_TASK_INFO0_SET (HINIC_VLAN_OFF_DISABLE ,
509
+ VLAN_OFFLOAD ) |
510
+ HINIC_SQ_TASK_INFO0_SET (HINIC_PKT_NOT_PARSED , PARSE_FLAG );
511
+
512
+ task -> pkt_info1 =
513
+ HINIC_SQ_TASK_INFO1_SET (HINIC_MEDIA_UNKNOWN , MEDIA_TYPE ) |
514
+ HINIC_SQ_TASK_INFO1_SET (0 , INNER_L4_LEN ) |
515
+ HINIC_SQ_TASK_INFO1_SET (0 , INNER_L3_LEN );
516
+
517
+ task -> pkt_info2 =
518
+ HINIC_SQ_TASK_INFO2_SET (0 , TUNNEL_L4_LEN ) |
519
+ HINIC_SQ_TASK_INFO2_SET (0 , OUTER_L3_LEN ) |
520
+ HINIC_SQ_TASK_INFO2_SET (HINIC_TUNNEL_L4TYPE_UNKNOWN ,
521
+ TUNNEL_L4TYPE ) |
522
+ HINIC_SQ_TASK_INFO2_SET (HINIC_OUTER_L3TYPE_UNKNOWN ,
523
+ OUTER_L3TYPE );
524
+
525
+ task -> ufo_v6_identify = 0 ;
526
+
527
+ task -> pkt_info4 = HINIC_SQ_TASK_INFO4_SET (HINIC_L2TYPE_ETH , L2TYPE );
528
+
529
+ task -> zero_pad = 0 ;
530
+ }
531
+
532
+ /**
533
+ * hinic_sq_prepare_wqe - prepare wqe before insert to the queue
534
+ * @sq: send queue
535
+ * @prod_idx: pi value
536
+ * @sq_wqe: wqe to prepare
537
+ * @sges: sges for use by the wqe for send for buf addresses
538
+ * @nr_sges: number of sges
539
+ **/
540
+ void hinic_sq_prepare_wqe (struct hinic_sq * sq , u16 prod_idx ,
541
+ struct hinic_sq_wqe * sq_wqe , struct hinic_sge * sges ,
542
+ int nr_sges )
543
+ {
544
+ int i ;
545
+
546
+ sq_prepare_ctrl (& sq_wqe -> ctrl , prod_idx , nr_sges );
547
+
548
+ sq_prepare_task (& sq_wqe -> task );
549
+
550
+ for (i = 0 ; i < nr_sges ; i ++ )
551
+ sq_wqe -> buf_descs [i ].sge = sges [i ];
552
+ }
553
+
554
+ /**
555
+ * sq_prepare_db - prepare doorbell to write
556
+ * @sq: send queue
557
+ * @prod_idx: pi value for the doorbell
558
+ * @cos: cos of the doorbell
559
+ *
560
+ * Return db value
561
+ **/
562
+ static u32 sq_prepare_db (struct hinic_sq * sq , u16 prod_idx , unsigned int cos )
563
+ {
564
+ struct hinic_qp * qp = container_of (sq , struct hinic_qp , sq );
565
+ u8 hi_prod_idx = SQ_DB_PI_HI (SQ_MASKED_IDX (sq , prod_idx ));
566
+
567
+ /* Data should be written to HW in Big Endian Format */
568
+ return cpu_to_be32 (HINIC_SQ_DB_INFO_SET (hi_prod_idx , PI_HI ) |
569
+ HINIC_SQ_DB_INFO_SET (HINIC_DB_SQ_TYPE , TYPE ) |
570
+ HINIC_SQ_DB_INFO_SET (HINIC_DATA_PATH , PATH ) |
571
+ HINIC_SQ_DB_INFO_SET (cos , COS ) |
572
+ HINIC_SQ_DB_INFO_SET (qp -> q_id , QID ));
573
+ }
574
+
575
+ /**
576
+ * hinic_sq_write_db- write doorbell
577
+ * @sq: send queue
578
+ * @prod_idx: pi value for the doorbell
579
+ * @wqe_size: wqe size
580
+ * @cos: cos of the wqe
581
+ **/
582
+ void hinic_sq_write_db (struct hinic_sq * sq , u16 prod_idx , unsigned int wqe_size ,
583
+ unsigned int cos )
584
+ {
585
+ struct hinic_wq * wq = sq -> wq ;
586
+
587
+ /* increment prod_idx to the next */
588
+ prod_idx += ALIGN (wqe_size , wq -> wqebb_size ) / wq -> wqebb_size ;
589
+
590
+ wmb (); /* Write all before the doorbell */
591
+
592
+ writel (sq_prepare_db (sq , prod_idx , cos ), SQ_DB_ADDR (sq , prod_idx ));
593
+ }
594
+
595
+ /**
596
+ * hinic_sq_get_wqe - get wqe ptr in the current pi and update the pi
597
+ * @sq: sq to get wqe from
598
+ * @wqe_size: wqe size
599
+ * @prod_idx: returned pi
600
+ *
601
+ * Return wqe pointer
602
+ **/
603
+ struct hinic_sq_wqe * hinic_sq_get_wqe (struct hinic_sq * sq ,
604
+ unsigned int wqe_size , u16 * prod_idx )
605
+ {
606
+ struct hinic_hw_wqe * hw_wqe = hinic_get_wqe (sq -> wq , wqe_size ,
607
+ prod_idx );
608
+
609
+ if (IS_ERR (hw_wqe ))
610
+ return NULL ;
611
+
612
+ return & hw_wqe -> sq_wqe ;
613
+ }
614
+
615
+ /**
616
+ * hinic_sq_write_wqe - write the wqe to the sq
617
+ * @sq: send queue
618
+ * @prod_idx: pi of the wqe
619
+ * @sq_wqe: the wqe to write
620
+ * @skb: skb to save
621
+ * @wqe_size: the size of the wqe
622
+ **/
623
+ void hinic_sq_write_wqe (struct hinic_sq * sq , u16 prod_idx ,
624
+ struct hinic_sq_wqe * sq_wqe ,
625
+ struct sk_buff * skb , unsigned int wqe_size )
626
+ {
627
+ struct hinic_hw_wqe * hw_wqe = (struct hinic_hw_wqe * )sq_wqe ;
628
+
629
+ sq -> saved_skb [prod_idx ] = skb ;
630
+
631
+ /* The data in the HW should be in Big Endian Format */
632
+ hinic_cpu_to_be32 (sq_wqe , wqe_size );
633
+
634
+ hinic_write_wqe (sq -> wq , hw_wqe , wqe_size );
635
+ }
636
+
637
+ /**
638
+ * hinic_sq_read_wqe - read wqe ptr in the current ci and update the ci
639
+ * @sq: send queue
640
+ * @skb: return skb that was saved
641
+ * @wqe_size: the size of the wqe
642
+ * @cons_idx: consumer index of the wqe
643
+ *
644
+ * Return wqe in ci position
645
+ **/
646
+ struct hinic_sq_wqe * hinic_sq_read_wqe (struct hinic_sq * sq ,
647
+ struct sk_buff * * skb ,
648
+ unsigned int * wqe_size , u16 * cons_idx )
649
+ {
650
+ struct hinic_hw_wqe * hw_wqe ;
651
+ struct hinic_sq_wqe * sq_wqe ;
652
+ struct hinic_sq_ctrl * ctrl ;
653
+ unsigned int buf_sect_len ;
654
+ u32 ctrl_info ;
655
+
656
+ /* read the ctrl section for getting wqe size */
657
+ hw_wqe = hinic_read_wqe (sq -> wq , sizeof (* ctrl ), cons_idx );
658
+ if (IS_ERR (hw_wqe ))
659
+ return NULL ;
660
+
661
+ sq_wqe = & hw_wqe -> sq_wqe ;
662
+ ctrl = & sq_wqe -> ctrl ;
663
+ ctrl_info = be32_to_cpu (ctrl -> ctrl_info );
664
+ buf_sect_len = HINIC_SQ_CTRL_GET (ctrl_info , BUFDESC_SECT_LEN );
665
+
666
+ * wqe_size = sizeof (* ctrl ) + sizeof (sq_wqe -> task );
667
+ * wqe_size += SECT_SIZE_FROM_8BYTES (buf_sect_len );
668
+
669
+ * skb = sq -> saved_skb [* cons_idx ];
670
+
671
+ /* using the real wqe size to read wqe again */
672
+ hw_wqe = hinic_read_wqe (sq -> wq , * wqe_size , cons_idx );
673
+
674
+ return & hw_wqe -> sq_wqe ;
675
+ }
676
+
677
+ /**
678
+ * hinic_sq_put_wqe - release the ci for new wqes
679
+ * @sq: send queue
680
+ * @wqe_size: the size of the wqe
681
+ **/
682
+ void hinic_sq_put_wqe (struct hinic_sq * sq , unsigned int wqe_size )
683
+ {
684
+ hinic_put_wqe (sq -> wq , wqe_size );
685
+ }
686
+
687
+ /**
688
+ * hinic_sq_get_sges - get sges from the wqe
689
+ * @sq_wqe: wqe to get the sges from its buffer addresses
690
+ * @sges: returned sges
691
+ * @nr_sges: number sges to return
692
+ **/
693
+ void hinic_sq_get_sges (struct hinic_sq_wqe * sq_wqe , struct hinic_sge * sges ,
694
+ int nr_sges )
695
+ {
696
+ int i ;
697
+
698
+ for (i = 0 ; i < nr_sges && i < HINIC_MAX_SQ_BUFDESCS ; i ++ ) {
699
+ sges [i ] = sq_wqe -> buf_descs [i ].sge ;
700
+ hinic_be32_to_cpu (& sges [i ], sizeof (sges [i ]));
701
+ }
702
+ }
703
+
451
704
/**
452
705
* hinic_rq_get_wqe - get wqe ptr in the current pi and update the pi
453
706
* @rq: rq to get wqe from
0 commit comments