Skip to content

Commit 6aa53e8

Browse files
jahay1anguy11
authored andcommitted
idpf: implement get LAN MMIO memory regions
The RDMA driver needs to map its own MMIO regions for the sake of performance, meaning the IDPF needs to avoid mapping portions of the BAR space. However, to be HW agnostic, the IDPF cannot assume where these are and must avoid mapping hard coded regions as much as possible. The IDPF maps the bare minimum to load and communicate with the control plane, i.e., the mailbox registers and the reset state registers. Because of how and when mailbox register offsets are initialized, it is easier to adjust the existing defines to be relative to the mailbox region starting address. Use a specific mailbox register write function that uses these relative offsets. The reset state register addresses are calculated the same way as for other registers, described below. The IDPF then calls a new virtchnl op to fetch a list of MMIO regions that it should map. The addresses for the registers in these regions are calculated by determining what region the register resides in, adjusting the offset to be relative to that region, and then adding the register's offset to that region's mapped address. If the new virtchnl op is not supported, the IDPF will fallback to mapping the whole bar. However, it will still map them as separate regions outside the mailbox and reset state registers. This way we can use the same logic in both cases to access the MMIO space. Reviewed-by: Madhu Chittim <[email protected]> Signed-off-by: Joshua Hay <[email protected]> Signed-off-by: Tatyana Nikolova <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent ed6e1c8 commit 6aa53e8

File tree

11 files changed

+376
-52
lines changed

11 files changed

+376
-52
lines changed

drivers/net/ethernet/intel/idpf/idpf.h

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ struct idpf_vport_max_q;
1212
#include <net/pkt_sched.h>
1313
#include <linux/aer.h>
1414
#include <linux/etherdevice.h>
15+
#include <linux/ioport.h>
1516
#include <linux/pci.h>
1617
#include <linux/bitfield.h>
1718
#include <linux/sctp.h>
@@ -197,7 +198,8 @@ struct idpf_vport_max_q {
197198
* @ptp_reg_init: PTP register initialization
198199
*/
199200
struct idpf_reg_ops {
200-
void (*ctlq_reg_init)(struct idpf_ctlq_create_info *cq);
201+
void (*ctlq_reg_init)(struct idpf_adapter *adapter,
202+
struct idpf_ctlq_create_info *cq);
201203
int (*intr_reg_init)(struct idpf_vport *vport);
202204
void (*mb_intr_reg_init)(struct idpf_adapter *adapter);
203205
void (*reset_reg_init)(struct idpf_adapter *adapter);
@@ -206,15 +208,25 @@ struct idpf_reg_ops {
206208
void (*ptp_reg_init)(const struct idpf_adapter *adapter);
207209
};
208210

211+
#define IDPF_MMIO_REG_NUM_STATIC 2
212+
#define IDPF_PF_MBX_REGION_SZ 4096
213+
#define IDPF_PF_RSTAT_REGION_SZ 2048
214+
#define IDPF_VF_MBX_REGION_SZ 10240
215+
#define IDPF_VF_RSTAT_REGION_SZ 2048
216+
209217
/**
210218
* struct idpf_dev_ops - Device specific operations
211219
* @reg_ops: Register operations
212220
* @idc_init: IDC initialization
221+
* @static_reg_info: array of mailbox and rstat register info
213222
*/
214223
struct idpf_dev_ops {
215224
struct idpf_reg_ops reg_ops;
216225

217226
int (*idc_init)(struct idpf_adapter *adapter);
227+
228+
/* static_reg_info[0] is mailbox region, static_reg_info[1] is rstat */
229+
struct resource static_reg_info[IDPF_MMIO_REG_NUM_STATIC];
218230
};
219231

220232
/**
@@ -755,6 +767,34 @@ static inline u8 idpf_get_min_tx_pkt_len(struct idpf_adapter *adapter)
755767
return pkt_len ? pkt_len : IDPF_TX_MIN_PKT_LEN;
756768
}
757769

770+
/**
771+
* idpf_get_mbx_reg_addr - Get BAR0 mailbox register address
772+
* @adapter: private data struct
773+
* @reg_offset: register offset value
774+
*
775+
* Return: BAR0 mailbox register address based on register offset.
776+
*/
777+
static inline void __iomem *idpf_get_mbx_reg_addr(struct idpf_adapter *adapter,
778+
resource_size_t reg_offset)
779+
{
780+
return adapter->hw.mbx.vaddr + reg_offset;
781+
}
782+
783+
/**
784+
* idpf_get_rstat_reg_addr - Get BAR0 rstat register address
785+
* @adapter: private data struct
786+
* @reg_offset: register offset value
787+
*
788+
* Return: BAR0 rstat register address based on register offset.
789+
*/
790+
static inline void __iomem *idpf_get_rstat_reg_addr(struct idpf_adapter *adapter,
791+
resource_size_t reg_offset)
792+
{
793+
reg_offset -= adapter->dev_ops.static_reg_info[1].start;
794+
795+
return adapter->hw.rstat.vaddr + reg_offset;
796+
}
797+
758798
/**
759799
* idpf_get_reg_addr - Get BAR0 register address
760800
* @adapter: private data struct
@@ -765,7 +805,30 @@ static inline u8 idpf_get_min_tx_pkt_len(struct idpf_adapter *adapter)
765805
static inline void __iomem *idpf_get_reg_addr(struct idpf_adapter *adapter,
766806
resource_size_t reg_offset)
767807
{
768-
return (void __iomem *)(adapter->hw.hw_addr + reg_offset);
808+
struct idpf_hw *hw = &adapter->hw;
809+
810+
for (int i = 0; i < hw->num_lan_regs; i++) {
811+
struct idpf_mmio_reg *region = &hw->lan_regs[i];
812+
813+
if (reg_offset >= region->addr_start &&
814+
reg_offset < (region->addr_start + region->addr_len)) {
815+
/* Convert the offset so that it is relative to the
816+
* start of the region. Then add the base address of
817+
* the region to get the final address.
818+
*/
819+
reg_offset -= region->addr_start;
820+
821+
return region->vaddr + reg_offset;
822+
}
823+
}
824+
825+
/* It's impossible to hit this case with offsets from the CP. But if we
826+
* do for any other reason, the kernel will panic on that register
827+
* access. Might as well do it here to make it clear what's happening.
828+
*/
829+
BUG();
830+
831+
return NULL;
769832
}
770833

771834
/**
@@ -779,7 +842,7 @@ static inline bool idpf_is_reset_detected(struct idpf_adapter *adapter)
779842
if (!adapter->hw.arq)
780843
return true;
781844

782-
return !(readl(idpf_get_reg_addr(adapter, adapter->hw.arq->reg.len)) &
845+
return !(readl(idpf_get_mbx_reg_addr(adapter, adapter->hw.arq->reg.len)) &
783846
adapter->hw.arq->reg.len_mask);
784847
}
785848

drivers/net/ethernet/intel/idpf/idpf_controlq.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ static void idpf_ctlq_init_regs(struct idpf_hw *hw, struct idpf_ctlq_info *cq,
3636
{
3737
/* Update tail to post pre-allocated buffers for rx queues */
3838
if (is_rxq)
39-
wr32(hw, cq->reg.tail, (u32)(cq->ring_size - 1));
39+
idpf_mbx_wr32(hw, cq->reg.tail, (u32)(cq->ring_size - 1));
4040

4141
/* For non-Mailbox control queues only TAIL need to be set */
4242
if (cq->q_id != -1)
4343
return;
4444

4545
/* Clear Head for both send or receive */
46-
wr32(hw, cq->reg.head, 0);
46+
idpf_mbx_wr32(hw, cq->reg.head, 0);
4747

4848
/* set starting point */
49-
wr32(hw, cq->reg.bal, lower_32_bits(cq->desc_ring.pa));
50-
wr32(hw, cq->reg.bah, upper_32_bits(cq->desc_ring.pa));
51-
wr32(hw, cq->reg.len, (cq->ring_size | cq->reg.len_ena_mask));
49+
idpf_mbx_wr32(hw, cq->reg.bal, lower_32_bits(cq->desc_ring.pa));
50+
idpf_mbx_wr32(hw, cq->reg.bah, upper_32_bits(cq->desc_ring.pa));
51+
idpf_mbx_wr32(hw, cq->reg.len, (cq->ring_size | cq->reg.len_ena_mask));
5252
}
5353

5454
/**
@@ -329,7 +329,7 @@ int idpf_ctlq_send(struct idpf_hw *hw, struct idpf_ctlq_info *cq,
329329
*/
330330
dma_wmb();
331331

332-
wr32(hw, cq->reg.tail, cq->next_to_use);
332+
idpf_mbx_wr32(hw, cq->reg.tail, cq->next_to_use);
333333

334334
err_unlock:
335335
mutex_unlock(&cq->cq_lock);
@@ -521,7 +521,7 @@ int idpf_ctlq_post_rx_buffs(struct idpf_hw *hw, struct idpf_ctlq_info *cq,
521521

522522
dma_wmb();
523523

524-
wr32(hw, cq->reg.tail, cq->next_to_post);
524+
idpf_mbx_wr32(hw, cq->reg.tail, cq->next_to_post);
525525
}
526526

527527
mutex_unlock(&cq->cq_lock);

drivers/net/ethernet/intel/idpf/idpf_controlq.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,26 @@ struct idpf_mbxq_desc {
9494
u32 pf_vf_id; /* used by CP when sending to PF */
9595
};
9696

97+
/* Max number of MMIO regions not including the mailbox and rstat regions in
98+
* the fallback case when the whole bar is mapped.
99+
*/
100+
#define IDPF_MMIO_MAP_FALLBACK_MAX_REMAINING 3
101+
102+
struct idpf_mmio_reg {
103+
void __iomem *vaddr;
104+
resource_size_t addr_start;
105+
resource_size_t addr_len;
106+
};
107+
97108
/* Define the driver hardware struct to replace other control structs as needed
98109
* Align to ctlq_hw_info
99110
*/
100111
struct idpf_hw {
101-
void __iomem *hw_addr;
102-
resource_size_t hw_addr_len;
112+
struct idpf_mmio_reg mbx;
113+
struct idpf_mmio_reg rstat;
114+
/* Array of remaining LAN BAR regions */
115+
int num_lan_regs;
116+
struct idpf_mmio_reg *lan_regs;
103117

104118
struct idpf_adapter *back;
105119

drivers/net/ethernet/intel/idpf/idpf_dev.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010

1111
/**
1212
* idpf_ctlq_reg_init - initialize default mailbox registers
13+
* @adapter: adapter structure
1314
* @cq: pointer to the array of create control queues
1415
*/
15-
static void idpf_ctlq_reg_init(struct idpf_ctlq_create_info *cq)
16+
static void idpf_ctlq_reg_init(struct idpf_adapter *adapter,
17+
struct idpf_ctlq_create_info *cq)
1618
{
19+
resource_size_t mbx_start = adapter->dev_ops.static_reg_info[0].start;
1720
int i;
1821

1922
for (i = 0; i < IDPF_NUM_DFLT_MBX_Q; i++) {
@@ -22,22 +25,22 @@ static void idpf_ctlq_reg_init(struct idpf_ctlq_create_info *cq)
2225
switch (ccq->type) {
2326
case IDPF_CTLQ_TYPE_MAILBOX_TX:
2427
/* set head and tail registers in our local struct */
25-
ccq->reg.head = PF_FW_ATQH;
26-
ccq->reg.tail = PF_FW_ATQT;
27-
ccq->reg.len = PF_FW_ATQLEN;
28-
ccq->reg.bah = PF_FW_ATQBAH;
29-
ccq->reg.bal = PF_FW_ATQBAL;
28+
ccq->reg.head = PF_FW_ATQH - mbx_start;
29+
ccq->reg.tail = PF_FW_ATQT - mbx_start;
30+
ccq->reg.len = PF_FW_ATQLEN - mbx_start;
31+
ccq->reg.bah = PF_FW_ATQBAH - mbx_start;
32+
ccq->reg.bal = PF_FW_ATQBAL - mbx_start;
3033
ccq->reg.len_mask = PF_FW_ATQLEN_ATQLEN_M;
3134
ccq->reg.len_ena_mask = PF_FW_ATQLEN_ATQENABLE_M;
3235
ccq->reg.head_mask = PF_FW_ATQH_ATQH_M;
3336
break;
3437
case IDPF_CTLQ_TYPE_MAILBOX_RX:
3538
/* set head and tail registers in our local struct */
36-
ccq->reg.head = PF_FW_ARQH;
37-
ccq->reg.tail = PF_FW_ARQT;
38-
ccq->reg.len = PF_FW_ARQLEN;
39-
ccq->reg.bah = PF_FW_ARQBAH;
40-
ccq->reg.bal = PF_FW_ARQBAL;
39+
ccq->reg.head = PF_FW_ARQH - mbx_start;
40+
ccq->reg.tail = PF_FW_ARQT - mbx_start;
41+
ccq->reg.len = PF_FW_ARQLEN - mbx_start;
42+
ccq->reg.bah = PF_FW_ARQBAH - mbx_start;
43+
ccq->reg.bal = PF_FW_ARQBAL - mbx_start;
4144
ccq->reg.len_mask = PF_FW_ARQLEN_ARQLEN_M;
4245
ccq->reg.len_ena_mask = PF_FW_ARQLEN_ARQENABLE_M;
4346
ccq->reg.head_mask = PF_FW_ARQH_ARQH_M;
@@ -130,7 +133,7 @@ static int idpf_intr_reg_init(struct idpf_vport *vport)
130133
*/
131134
static void idpf_reset_reg_init(struct idpf_adapter *adapter)
132135
{
133-
adapter->reset_reg.rstat = idpf_get_reg_addr(adapter, PFGEN_RSTAT);
136+
adapter->reset_reg.rstat = idpf_get_rstat_reg_addr(adapter, PFGEN_RSTAT);
134137
adapter->reset_reg.rstat_m = PFGEN_RSTAT_PFR_STATE_M;
135138
}
136139

@@ -144,9 +147,9 @@ static void idpf_trigger_reset(struct idpf_adapter *adapter,
144147
{
145148
u32 reset_reg;
146149

147-
reset_reg = readl(idpf_get_reg_addr(adapter, PFGEN_CTRL));
150+
reset_reg = readl(idpf_get_rstat_reg_addr(adapter, PFGEN_CTRL));
148151
writel(reset_reg | PFGEN_CTRL_PFSWR,
149-
idpf_get_reg_addr(adapter, PFGEN_CTRL));
152+
idpf_get_rstat_reg_addr(adapter, PFGEN_CTRL));
150153
}
151154

152155
/**
@@ -195,4 +198,9 @@ void idpf_dev_ops_init(struct idpf_adapter *adapter)
195198
idpf_reg_ops_init(adapter);
196199

197200
adapter->dev_ops.idc_init = idpf_idc_register;
201+
202+
resource_set_range(&adapter->dev_ops.static_reg_info[0],
203+
PF_FW_BASE, IDPF_PF_MBX_REGION_SZ);
204+
resource_set_range(&adapter->dev_ops.static_reg_info[1],
205+
PFGEN_RTRIG, IDPF_PF_RSTAT_REGION_SZ);
198206
}

drivers/net/ethernet/intel/idpf/idpf_idc.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
412412
{
413413
struct iidc_rdma_core_dev_info *cdev_info;
414414
struct iidc_rdma_priv_dev_info *privd;
415-
int err;
415+
int err, i;
416416

417417
adapter->cdev_info = kzalloc(sizeof(*cdev_info), GFP_KERNEL);
418418
if (!adapter->cdev_info)
@@ -430,14 +430,36 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
430430
cdev_info->rdma_protocol = IIDC_RDMA_PROTOCOL_ROCEV2;
431431
privd->ftype = ftype;
432432

433+
privd->mapped_mem_regions =
434+
kcalloc(adapter->hw.num_lan_regs,
435+
sizeof(struct iidc_rdma_lan_mapped_mem_region),
436+
GFP_KERNEL);
437+
if (!privd->mapped_mem_regions) {
438+
err = -ENOMEM;
439+
goto err_plug_aux_dev;
440+
}
441+
442+
privd->num_memory_regions = cpu_to_le16(adapter->hw.num_lan_regs);
443+
for (i = 0; i < adapter->hw.num_lan_regs; i++) {
444+
privd->mapped_mem_regions[i].region_addr =
445+
adapter->hw.lan_regs[i].vaddr;
446+
privd->mapped_mem_regions[i].size =
447+
cpu_to_le64(adapter->hw.lan_regs[i].addr_len);
448+
privd->mapped_mem_regions[i].start_offset =
449+
cpu_to_le64(adapter->hw.lan_regs[i].addr_start);
450+
}
451+
433452
idpf_idc_init_msix_data(adapter);
434453

435454
err = idpf_plug_core_aux_dev(cdev_info);
436455
if (err)
437-
goto err_plug_aux_dev;
456+
goto err_free_mem_regions;
438457

439458
return 0;
440459

460+
err_free_mem_regions:
461+
kfree(privd->mapped_mem_regions);
462+
privd->mapped_mem_regions = NULL;
441463
err_plug_aux_dev:
442464
kfree(privd);
443465
err_privd_alloc:
@@ -453,12 +475,16 @@ int idpf_idc_init_aux_core_dev(struct idpf_adapter *adapter,
453475
*/
454476
void idpf_idc_deinit_core_aux_device(struct iidc_rdma_core_dev_info *cdev_info)
455477
{
478+
struct iidc_rdma_priv_dev_info *privd;
479+
456480
if (!cdev_info)
457481
return;
458482

459483
idpf_unplug_aux_dev(cdev_info->adev);
460484

461-
kfree(cdev_info->iidc_priv);
485+
privd = cdev_info->iidc_priv;
486+
kfree(privd->mapped_mem_regions);
487+
kfree(privd);
462488
kfree(cdev_info);
463489
}
464490

drivers/net/ethernet/intel/idpf/idpf_main.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,37 @@ static void idpf_shutdown(struct pci_dev *pdev)
106106
*/
107107
static int idpf_cfg_hw(struct idpf_adapter *adapter)
108108
{
109+
resource_size_t res_start, mbx_start, rstat_start;
109110
struct pci_dev *pdev = adapter->pdev;
110111
struct idpf_hw *hw = &adapter->hw;
112+
struct device *dev = &pdev->dev;
113+
long len;
114+
115+
res_start = pci_resource_start(pdev, 0);
116+
117+
/* Map mailbox space for virtchnl communication */
118+
mbx_start = res_start + adapter->dev_ops.static_reg_info[0].start;
119+
len = resource_size(&adapter->dev_ops.static_reg_info[0]);
120+
hw->mbx.vaddr = devm_ioremap(dev, mbx_start, len);
121+
if (!hw->mbx.vaddr) {
122+
pci_err(pdev, "failed to allocate BAR0 mbx region\n");
123+
124+
return -ENOMEM;
125+
}
126+
hw->mbx.addr_start = adapter->dev_ops.static_reg_info[0].start;
127+
hw->mbx.addr_len = len;
111128

112-
hw->hw_addr = pcim_iomap_table(pdev)[0];
113-
if (!hw->hw_addr) {
114-
pci_err(pdev, "failed to allocate PCI iomap table\n");
129+
/* Map rstat space for resets */
130+
rstat_start = res_start + adapter->dev_ops.static_reg_info[1].start;
131+
len = resource_size(&adapter->dev_ops.static_reg_info[1]);
132+
hw->rstat.vaddr = devm_ioremap(dev, rstat_start, len);
133+
if (!hw->rstat.vaddr) {
134+
pci_err(pdev, "failed to allocate BAR0 rstat region\n");
115135

116136
return -ENOMEM;
117137
}
138+
hw->rstat.addr_start = adapter->dev_ops.static_reg_info[1].start;
139+
hw->rstat.addr_len = len;
118140

119141
hw->back = adapter;
120142

@@ -161,9 +183,9 @@ static int idpf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
161183
if (err)
162184
goto err_free;
163185

164-
err = pcim_iomap_regions(pdev, BIT(0), pci_name(pdev));
186+
err = pcim_request_region(pdev, 0, pci_name(pdev));
165187
if (err) {
166-
pci_err(pdev, "pcim_iomap_regions failed %pe\n", ERR_PTR(err));
188+
pci_err(pdev, "pcim_request_region failed %pe\n", ERR_PTR(err));
167189

168190
goto err_free;
169191
}

0 commit comments

Comments
 (0)