Skip to content

Commit e85c9a7

Browse files
Hariprasad Shenaidavem330
authored andcommitted
cxgb4/cxgb4vf: Add code to calculate T5 BAR2 Offsets for SGE Queue Registers
Add new Common Code facilities for calculating T5 BAR2 Offsets for SGE Queue Registers. This new code can handle situations where Queues Per Page * SGE BAR2 Queue Register Area Size > Page Size Based on original work by Casey Leedom <[email protected]> Signed-off-by: Hariprasad Shenai <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e0a8b34 commit e85c9a7

File tree

5 files changed

+247
-7
lines changed

5 files changed

+247
-7
lines changed

drivers/net/ethernet/chelsio/cxgb4/cxgb4.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ struct tp_err_stats {
222222
u32 ofldCongDefer;
223223
};
224224

225+
struct sge_params {
226+
u32 hps; /* host page size for our PF/VF */
227+
u32 eq_qpp; /* egress queues/page for our PF/VF */
228+
u32 iq_qpp; /* egress queues/page for our PF/VF */
229+
};
230+
225231
struct tp_params {
226232
unsigned int ntxchan; /* # of Tx channels */
227233
unsigned int tre; /* log2 of core clocks per TP tick */
@@ -285,6 +291,7 @@ enum chip_type {
285291
};
286292

287293
struct adapter_params {
294+
struct sge_params sge;
288295
struct tp_params tp;
289296
struct vpd_params vpd;
290297
struct pci_params pci;
@@ -995,6 +1002,15 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
9951002
const u8 *fw_data, unsigned int fw_size,
9961003
struct fw_hdr *card_fw, enum dev_state state, int *reset);
9971004
int t4_prep_adapter(struct adapter *adapter);
1005+
1006+
enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
1007+
int t4_bar2_sge_qregs(struct adapter *adapter,
1008+
unsigned int qid,
1009+
enum t4_bar2_qtype qtype,
1010+
u64 *pbar2_qoffset,
1011+
unsigned int *pbar2_qid);
1012+
1013+
int t4_init_sge_params(struct adapter *adapter);
9981014
int t4_init_tp_params(struct adapter *adap);
9991015
int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
10001016
int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);

drivers/net/ethernet/chelsio/cxgb4/t4_hw.c

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4002,6 +4002,126 @@ int t4_prep_adapter(struct adapter *adapter)
40024002
return 0;
40034003
}
40044004

4005+
/**
4006+
* t4_bar2_sge_qregs - return BAR2 SGE Queue register information
4007+
* @adapter: the adapter
4008+
* @qid: the Queue ID
4009+
* @qtype: the Ingress or Egress type for @qid
4010+
* @pbar2_qoffset: BAR2 Queue Offset
4011+
* @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
4012+
*
4013+
* Returns the BAR2 SGE Queue Registers information associated with the
4014+
* indicated Absolute Queue ID. These are passed back in return value
4015+
* pointers. @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue
4016+
* and T4_BAR2_QTYPE_INGRESS for Ingress Queues.
4017+
*
4018+
* This may return an error which indicates that BAR2 SGE Queue
4019+
* registers aren't available. If an error is not returned, then the
4020+
* following values are returned:
4021+
*
4022+
* *@pbar2_qoffset: the BAR2 Offset of the @qid Registers
4023+
* *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid
4024+
*
4025+
* If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which
4026+
* require the "Inferred Queue ID" ability may be used. E.g. the
4027+
* Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0,
4028+
* then these "Inferred Queue ID" register may not be used.
4029+
*/
4030+
int t4_bar2_sge_qregs(struct adapter *adapter,
4031+
unsigned int qid,
4032+
enum t4_bar2_qtype qtype,
4033+
u64 *pbar2_qoffset,
4034+
unsigned int *pbar2_qid)
4035+
{
4036+
unsigned int page_shift, page_size, qpp_shift, qpp_mask;
4037+
u64 bar2_page_offset, bar2_qoffset;
4038+
unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
4039+
4040+
/* T4 doesn't support BAR2 SGE Queue registers.
4041+
*/
4042+
if (is_t4(adapter->params.chip))
4043+
return -EINVAL;
4044+
4045+
/* Get our SGE Page Size parameters.
4046+
*/
4047+
page_shift = adapter->params.sge.hps + 10;
4048+
page_size = 1 << page_shift;
4049+
4050+
/* Get the right Queues per Page parameters for our Queue.
4051+
*/
4052+
qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS
4053+
? adapter->params.sge.eq_qpp
4054+
: adapter->params.sge.iq_qpp);
4055+
qpp_mask = (1 << qpp_shift) - 1;
4056+
4057+
/* Calculate the basics of the BAR2 SGE Queue register area:
4058+
* o The BAR2 page the Queue registers will be in.
4059+
* o The BAR2 Queue ID.
4060+
* o The BAR2 Queue ID Offset into the BAR2 page.
4061+
*/
4062+
bar2_page_offset = ((qid >> qpp_shift) << page_shift);
4063+
bar2_qid = qid & qpp_mask;
4064+
bar2_qid_offset = bar2_qid * SGE_UDB_SIZE;
4065+
4066+
/* If the BAR2 Queue ID Offset is less than the Page Size, then the
4067+
* hardware will infer the Absolute Queue ID simply from the writes to
4068+
* the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a
4069+
* BAR2 Queue ID of 0 for those writes). Otherwise, we'll simply
4070+
* write to the first BAR2 SGE Queue Area within the BAR2 Page with
4071+
* the BAR2 Queue ID and the hardware will infer the Absolute Queue ID
4072+
* from the BAR2 Page and BAR2 Queue ID.
4073+
*
4074+
* One important censequence of this is that some BAR2 SGE registers
4075+
* have a "Queue ID" field and we can write the BAR2 SGE Queue ID
4076+
* there. But other registers synthesize the SGE Queue ID purely
4077+
* from the writes to the registers -- the Write Combined Doorbell
4078+
* Buffer is a good example. These BAR2 SGE Registers are only
4079+
* available for those BAR2 SGE Register areas where the SGE Absolute
4080+
* Queue ID can be inferred from simple writes.
4081+
*/
4082+
bar2_qoffset = bar2_page_offset;
4083+
bar2_qinferred = (bar2_qid_offset < page_size);
4084+
if (bar2_qinferred) {
4085+
bar2_qoffset += bar2_qid_offset;
4086+
bar2_qid = 0;
4087+
}
4088+
4089+
*pbar2_qoffset = bar2_qoffset;
4090+
*pbar2_qid = bar2_qid;
4091+
return 0;
4092+
}
4093+
4094+
/**
4095+
* t4_init_sge_params - initialize adap->params.sge
4096+
* @adapter: the adapter
4097+
*
4098+
* Initialize various fields of the adapter's SGE Parameters structure.
4099+
*/
4100+
int t4_init_sge_params(struct adapter *adapter)
4101+
{
4102+
struct sge_params *sge_params = &adapter->params.sge;
4103+
u32 hps, qpp;
4104+
unsigned int s_hps, s_qpp;
4105+
4106+
/* Extract the SGE Page Size for our PF.
4107+
*/
4108+
hps = t4_read_reg(adapter, SGE_HOST_PAGE_SIZE);
4109+
s_hps = (HOSTPAGESIZEPF0_S +
4110+
(HOSTPAGESIZEPF1_S - HOSTPAGESIZEPF0_S) * adapter->fn);
4111+
sge_params->hps = ((hps >> s_hps) & HOSTPAGESIZEPF0_M);
4112+
4113+
/* Extract the SGE Egress and Ingess Queues Per Page for our PF.
4114+
*/
4115+
s_qpp = (QUEUESPERPAGEPF0_S +
4116+
(QUEUESPERPAGEPF1_S - QUEUESPERPAGEPF0_S) * adapter->fn);
4117+
qpp = t4_read_reg(adapter, SGE_EGRESS_QUEUES_PER_PAGE_PF);
4118+
sge_params->eq_qpp = ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
4119+
qpp = t4_read_reg(adapter, SGE_INGRESS_QUEUES_PER_PAGE_PF);
4120+
sge_params->iq_qpp = ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
4121+
4122+
return 0;
4123+
}
4124+
40054125
/**
40064126
* t4_init_tp_params - initialize adap->params.tp
40074127
* @adap: the adapter

drivers/net/ethernet/chelsio/cxgb4/t4_regs.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,13 @@
155155
#define HOSTPAGESIZEPF2_SHIFT 8
156156
#define HOSTPAGESIZEPF2(x) ((x) << HOSTPAGESIZEPF2_SHIFT)
157157

158-
#define HOSTPAGESIZEPF1_MASK 0x0000000fU
159-
#define HOSTPAGESIZEPF1_SHIFT 4
160-
#define HOSTPAGESIZEPF1(x) ((x) << HOSTPAGESIZEPF1_SHIFT)
158+
#define HOSTPAGESIZEPF1_M 0x0000000fU
159+
#define HOSTPAGESIZEPF1_S 4
160+
#define HOSTPAGESIZEPF1(x) ((x) << HOSTPAGESIZEPF1_S)
161161

162-
#define HOSTPAGESIZEPF0_MASK 0x0000000fU
163-
#define HOSTPAGESIZEPF0_SHIFT 0
164-
#define HOSTPAGESIZEPF0(x) ((x) << HOSTPAGESIZEPF0_SHIFT)
162+
#define HOSTPAGESIZEPF0_M 0x0000000fU
163+
#define HOSTPAGESIZEPF0_S 0
164+
#define HOSTPAGESIZEPF0(x) ((x) << HOSTPAGESIZEPF0_S)
165165

166166
#define SGE_EGRESS_QUEUES_PER_PAGE_PF 0x1010
167167
#define SGE_EGRESS_QUEUES_PER_PAGE_VF_A 0x1014

drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ struct sge_params {
138138
u32 sge_host_page_size; /* PF0-7 page sizes */
139139
u32 sge_egress_queues_per_page; /* PF0-7 egress queues/page */
140140
u32 sge_ingress_queues_per_page;/* PF0-7 ingress queues/page */
141+
u32 sge_vf_hps; /* host page size for our vf */
141142
u32 sge_vf_eq_qpp; /* egress queues/page for our VF */
142143
u32 sge_vf_iq_qpp; /* ingress queues/page for our VF */
143144
u32 sge_fl_buffer_size[16]; /* free list buffer sizes */
@@ -282,6 +283,13 @@ int t4vf_port_init(struct adapter *, int);
282283
int t4vf_fw_reset(struct adapter *);
283284
int t4vf_set_params(struct adapter *, unsigned int, const u32 *, const u32 *);
284285

286+
enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
287+
int t4_bar2_sge_qregs(struct adapter *adapter,
288+
unsigned int qid,
289+
enum t4_bar2_qtype qtype,
290+
u64 *pbar2_qoffset,
291+
unsigned int *pbar2_qid);
292+
285293
int t4vf_get_sge_params(struct adapter *);
286294
int t4vf_get_vpd_params(struct adapter *);
287295
int t4vf_get_dev_params(struct adapter *);

drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,95 @@ int t4vf_set_params(struct adapter *adapter, unsigned int nparams,
429429
return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
430430
}
431431

432+
/**
433+
* t4_bar2_sge_qregs - return BAR2 SGE Queue register information
434+
* @adapter: the adapter
435+
* @qid: the Queue ID
436+
* @qtype: the Ingress or Egress type for @qid
437+
* @pbar2_qoffset: BAR2 Queue Offset
438+
* @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
439+
*
440+
* Returns the BAR2 SGE Queue Registers information associated with the
441+
* indicated Absolute Queue ID. These are passed back in return value
442+
* pointers. @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue
443+
* and T4_BAR2_QTYPE_INGRESS for Ingress Queues.
444+
*
445+
* This may return an error which indicates that BAR2 SGE Queue
446+
* registers aren't available. If an error is not returned, then the
447+
* following values are returned:
448+
*
449+
* *@pbar2_qoffset: the BAR2 Offset of the @qid Registers
450+
* *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid
451+
*
452+
* If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which
453+
* require the "Inferred Queue ID" ability may be used. E.g. the
454+
* Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0,
455+
* then these "Inferred Queue ID" register may not be used.
456+
*/
457+
int t4_bar2_sge_qregs(struct adapter *adapter,
458+
unsigned int qid,
459+
enum t4_bar2_qtype qtype,
460+
u64 *pbar2_qoffset,
461+
unsigned int *pbar2_qid)
462+
{
463+
unsigned int page_shift, page_size, qpp_shift, qpp_mask;
464+
u64 bar2_page_offset, bar2_qoffset;
465+
unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
466+
467+
/* T4 doesn't support BAR2 SGE Queue registers.
468+
*/
469+
if (is_t4(adapter->params.chip))
470+
return -EINVAL;
471+
472+
/* Get our SGE Page Size parameters.
473+
*/
474+
page_shift = adapter->params.sge.sge_vf_hps + 10;
475+
page_size = 1 << page_shift;
476+
477+
/* Get the right Queues per Page parameters for our Queue.
478+
*/
479+
qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS
480+
? adapter->params.sge.sge_vf_eq_qpp
481+
: adapter->params.sge.sge_vf_iq_qpp);
482+
qpp_mask = (1 << qpp_shift) - 1;
483+
484+
/* Calculate the basics of the BAR2 SGE Queue register area:
485+
* o The BAR2 page the Queue registers will be in.
486+
* o The BAR2 Queue ID.
487+
* o The BAR2 Queue ID Offset into the BAR2 page.
488+
*/
489+
bar2_page_offset = ((qid >> qpp_shift) << page_shift);
490+
bar2_qid = qid & qpp_mask;
491+
bar2_qid_offset = bar2_qid * SGE_UDB_SIZE;
492+
493+
/* If the BAR2 Queue ID Offset is less than the Page Size, then the
494+
* hardware will infer the Absolute Queue ID simply from the writes to
495+
* the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a
496+
* BAR2 Queue ID of 0 for those writes). Otherwise, we'll simply
497+
* write to the first BAR2 SGE Queue Area within the BAR2 Page with
498+
* the BAR2 Queue ID and the hardware will infer the Absolute Queue ID
499+
* from the BAR2 Page and BAR2 Queue ID.
500+
*
501+
* One important censequence of this is that some BAR2 SGE registers
502+
* have a "Queue ID" field and we can write the BAR2 SGE Queue ID
503+
* there. But other registers synthesize the SGE Queue ID purely
504+
* from the writes to the registers -- the Write Combined Doorbell
505+
* Buffer is a good example. These BAR2 SGE Registers are only
506+
* available for those BAR2 SGE Register areas where the SGE Absolute
507+
* Queue ID can be inferred from simple writes.
508+
*/
509+
bar2_qoffset = bar2_page_offset;
510+
bar2_qinferred = (bar2_qid_offset < page_size);
511+
if (bar2_qinferred) {
512+
bar2_qoffset += bar2_qid_offset;
513+
bar2_qid = 0;
514+
}
515+
516+
*pbar2_qoffset = bar2_qoffset;
517+
*pbar2_qid = bar2_qid;
518+
return 0;
519+
}
520+
432521
/**
433522
* t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
434523
* @adapter: the adapter
@@ -507,7 +596,7 @@ int t4vf_get_sge_params(struct adapter *adapter)
507596
*/
508597
if (!is_t4(adapter->params.chip)) {
509598
u32 whoami;
510-
unsigned int pf, s_qpp;
599+
unsigned int pf, s_hps, s_qpp;
511600

512601
params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) |
513602
FW_PARAMS_PARAM_XYZ_V(
@@ -533,6 +622,13 @@ int t4vf_get_sge_params(struct adapter *adapter)
533622
whoami = t4_read_reg(adapter,
534623
T4VF_PL_BASE_ADDR + A_PL_VF_WHOAMI);
535624
pf = SOURCEPF_GET(whoami);
625+
626+
s_hps = (HOSTPAGESIZEPF0_S +
627+
(HOSTPAGESIZEPF1_S - HOSTPAGESIZEPF0_S) * pf);
628+
sge_params->sge_vf_hps =
629+
((sge_params->sge_host_page_size >> s_hps)
630+
& HOSTPAGESIZEPF0_M);
631+
536632
s_qpp = (QUEUESPERPAGEPF0_S +
537633
(QUEUESPERPAGEPF1_S - QUEUESPERPAGEPF0_S) * pf);
538634
sge_params->sge_vf_eq_qpp =

0 commit comments

Comments
 (0)