2 * Huawei HiNIC PCI Express Linux driver
3 * Copyright(c) 2017 Huawei Technologies Co., Ltd
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include <linux/pci.h>
17 #include <linux/device.h>
18 #include <linux/errno.h>
20 #include <linux/types.h>
21 #include <linux/bitops.h>
23 #include "hinic_hw_csr.h"
24 #include "hinic_hw_if.h"
26 #define PCIE_ATTR_ENTRY 0
28 #define VALID_MSIX_IDX(attr, msix_index) ((msix_index) < (attr)->num_irqs)
31 * hinic_msix_attr_set - set message attribute for msix entry
32 * @hwif: the HW interface of a pci function device
33 * @msix_index: msix_index
34 * @pending_limit: the maximum pending interrupt events (unit 8)
35 * @coalesc_timer: coalesc period for interrupt (unit 8 us)
36 * @lli_timer: replenishing period for low latency credit (unit 8 us)
37 * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
38 * @resend_timer: maximum wait for resending msix (unit coalesc period)
40 * Return 0 - Success, negative - Failure
42 int hinic_msix_attr_set(struct hinic_hwif
*hwif
, u16 msix_index
,
43 u8 pending_limit
, u8 coalesc_timer
,
44 u8 lli_timer
, u8 lli_credit_limit
,
49 if (!VALID_MSIX_IDX(&hwif
->attr
, msix_index
))
52 msix_ctrl
= HINIC_MSIX_ATTR_SET(pending_limit
, PENDING_LIMIT
) |
53 HINIC_MSIX_ATTR_SET(coalesc_timer
, COALESC_TIMER
) |
54 HINIC_MSIX_ATTR_SET(lli_timer
, LLI_TIMER
) |
55 HINIC_MSIX_ATTR_SET(lli_credit_limit
, LLI_CREDIT
) |
56 HINIC_MSIX_ATTR_SET(resend_timer
, RESEND_TIMER
);
58 addr
= HINIC_CSR_MSIX_CTRL_ADDR(msix_index
);
60 hinic_hwif_write_reg(hwif
, addr
, msix_ctrl
);
65 * hinic_msix_attr_get - get message attribute of msix entry
66 * @hwif: the HW interface of a pci function device
67 * @msix_index: msix_index
68 * @pending_limit: the maximum pending interrupt events (unit 8)
69 * @coalesc_timer: coalesc period for interrupt (unit 8 us)
70 * @lli_timer: replenishing period for low latency credit (unit 8 us)
71 * @lli_credit_limit: maximum credits for low latency msix messages (unit 8)
72 * @resend_timer: maximum wait for resending msix (unit coalesc period)
74 * Return 0 - Success, negative - Failure
76 int hinic_msix_attr_get(struct hinic_hwif
*hwif
, u16 msix_index
,
77 u8
*pending_limit
, u8
*coalesc_timer
,
78 u8
*lli_timer
, u8
*lli_credit_limit
,
83 if (!VALID_MSIX_IDX(&hwif
->attr
, msix_index
))
86 addr
= HINIC_CSR_MSIX_CTRL_ADDR(msix_index
);
87 val
= hinic_hwif_read_reg(hwif
, addr
);
89 *pending_limit
= HINIC_MSIX_ATTR_GET(val
, PENDING_LIMIT
);
90 *coalesc_timer
= HINIC_MSIX_ATTR_GET(val
, COALESC_TIMER
);
91 *lli_timer
= HINIC_MSIX_ATTR_GET(val
, LLI_TIMER
);
92 *lli_credit_limit
= HINIC_MSIX_ATTR_GET(val
, LLI_CREDIT
);
93 *resend_timer
= HINIC_MSIX_ATTR_GET(val
, RESEND_TIMER
);
98 * hinic_msix_attr_cnt_clear - clear message attribute counters for msix entry
99 * @hwif: the HW interface of a pci function device
100 * @msix_index: msix_index
102 * Return 0 - Success, negative - Failure
104 int hinic_msix_attr_cnt_clear(struct hinic_hwif
*hwif
, u16 msix_index
)
108 if (!VALID_MSIX_IDX(&hwif
->attr
, msix_index
))
111 msix_ctrl
= HINIC_MSIX_CNT_SET(1, RESEND_TIMER
);
112 addr
= HINIC_CSR_MSIX_CNT_ADDR(msix_index
);
114 hinic_hwif_write_reg(hwif
, addr
, msix_ctrl
);
119 * hinic_set_pf_action - set action on pf channel
120 * @hwif: the HW interface of a pci function device
121 * @action: action on pf channel
123 * Return 0 - Success, negative - Failure
125 void hinic_set_pf_action(struct hinic_hwif
*hwif
, enum hinic_pf_action action
)
127 u32 attr5
= hinic_hwif_read_reg(hwif
, HINIC_CSR_FUNC_ATTR5_ADDR
);
129 attr5
= HINIC_FA5_CLEAR(attr5
, PF_ACTION
);
130 attr5
|= HINIC_FA5_SET(action
, PF_ACTION
);
132 hinic_hwif_write_reg(hwif
, HINIC_CSR_FUNC_ATTR5_ADDR
, attr5
);
135 enum hinic_outbound_state
hinic_outbound_state_get(struct hinic_hwif
*hwif
)
137 u32 attr4
= hinic_hwif_read_reg(hwif
, HINIC_CSR_FUNC_ATTR4_ADDR
);
139 return HINIC_FA4_GET(attr4
, OUTBOUND_STATE
);
142 void hinic_outbound_state_set(struct hinic_hwif
*hwif
,
143 enum hinic_outbound_state outbound_state
)
145 u32 attr4
= hinic_hwif_read_reg(hwif
, HINIC_CSR_FUNC_ATTR4_ADDR
);
147 attr4
= HINIC_FA4_CLEAR(attr4
, OUTBOUND_STATE
);
148 attr4
|= HINIC_FA4_SET(outbound_state
, OUTBOUND_STATE
);
150 hinic_hwif_write_reg(hwif
, HINIC_CSR_FUNC_ATTR4_ADDR
, attr4
);
153 enum hinic_db_state
hinic_db_state_get(struct hinic_hwif
*hwif
)
155 u32 attr4
= hinic_hwif_read_reg(hwif
, HINIC_CSR_FUNC_ATTR4_ADDR
);
157 return HINIC_FA4_GET(attr4
, DB_STATE
);
160 void hinic_db_state_set(struct hinic_hwif
*hwif
,
161 enum hinic_db_state db_state
)
163 u32 attr4
= hinic_hwif_read_reg(hwif
, HINIC_CSR_FUNC_ATTR4_ADDR
);
165 attr4
= HINIC_FA4_CLEAR(attr4
, DB_STATE
);
166 attr4
|= HINIC_FA4_SET(db_state
, DB_STATE
);
168 hinic_hwif_write_reg(hwif
, HINIC_CSR_FUNC_ATTR4_ADDR
, attr4
);
172 * hwif_ready - test if the HW is ready for use
173 * @hwif: the HW interface of a pci function device
175 * Return 0 - Success, negative - Failure
177 static int hwif_ready(struct hinic_hwif
*hwif
)
179 struct pci_dev
*pdev
= hwif
->pdev
;
182 addr
= HINIC_CSR_FUNC_ATTR1_ADDR
;
183 attr1
= hinic_hwif_read_reg(hwif
, addr
);
185 if (!HINIC_FA1_GET(attr1
, INIT_STATUS
)) {
186 dev_err(&pdev
->dev
, "hwif status is not ready\n");
194 * set_hwif_attr - set the attributes in the relevant members in hwif
195 * @hwif: the HW interface of a pci function device
196 * @attr0: the first attribute that was read from the hw
197 * @attr1: the second attribute that was read from the hw
199 static void set_hwif_attr(struct hinic_hwif
*hwif
, u32 attr0
, u32 attr1
)
201 hwif
->attr
.func_idx
= HINIC_FA0_GET(attr0
, FUNC_IDX
);
202 hwif
->attr
.pf_idx
= HINIC_FA0_GET(attr0
, PF_IDX
);
203 hwif
->attr
.pci_intf_idx
= HINIC_FA0_GET(attr0
, PCI_INTF_IDX
);
204 hwif
->attr
.func_type
= HINIC_FA0_GET(attr0
, FUNC_TYPE
);
206 hwif
->attr
.num_aeqs
= BIT(HINIC_FA1_GET(attr1
, AEQS_PER_FUNC
));
207 hwif
->attr
.num_ceqs
= BIT(HINIC_FA1_GET(attr1
, CEQS_PER_FUNC
));
208 hwif
->attr
.num_irqs
= BIT(HINIC_FA1_GET(attr1
, IRQS_PER_FUNC
));
209 hwif
->attr
.num_dma_attr
= BIT(HINIC_FA1_GET(attr1
, DMA_ATTR_PER_FUNC
));
213 * read_hwif_attr - read the attributes and set members in hwif
214 * @hwif: the HW interface of a pci function device
216 static void read_hwif_attr(struct hinic_hwif
*hwif
)
218 u32 addr
, attr0
, attr1
;
220 addr
= HINIC_CSR_FUNC_ATTR0_ADDR
;
221 attr0
= hinic_hwif_read_reg(hwif
, addr
);
223 addr
= HINIC_CSR_FUNC_ATTR1_ADDR
;
224 attr1
= hinic_hwif_read_reg(hwif
, addr
);
226 set_hwif_attr(hwif
, attr0
, attr1
);
230 * set_ppf - try to set hwif as ppf and set the type of hwif in this case
231 * @hwif: the HW interface of a pci function device
233 static void set_ppf(struct hinic_hwif
*hwif
)
235 struct hinic_func_attr
*attr
= &hwif
->attr
;
236 u32 addr
, val
, ppf_election
;
238 /* Read Modify Write */
239 addr
= HINIC_CSR_PPF_ELECTION_ADDR(HINIC_HWIF_PCI_INTF(hwif
));
241 val
= hinic_hwif_read_reg(hwif
, addr
);
242 val
= HINIC_PPF_ELECTION_CLEAR(val
, IDX
);
244 ppf_election
= HINIC_PPF_ELECTION_SET(HINIC_HWIF_FUNC_IDX(hwif
), IDX
);
247 hinic_hwif_write_reg(hwif
, addr
, val
);
250 val
= hinic_hwif_read_reg(hwif
, addr
);
252 attr
->ppf_idx
= HINIC_PPF_ELECTION_GET(val
, IDX
);
253 if (attr
->ppf_idx
== HINIC_HWIF_FUNC_IDX(hwif
))
254 attr
->func_type
= HINIC_PPF
;
258 * set_dma_attr - set the dma attributes in the HW
259 * @hwif: the HW interface of a pci function device
260 * @entry_idx: the entry index in the dma table
261 * @st: PCIE TLP steering tag
262 * @at: PCIE TLP AT field
263 * @ph: PCIE TLP Processing Hint field
264 * @no_snooping: PCIE TLP No snooping
265 * @tph_en: PCIE TLP Processing Hint Enable
267 static void set_dma_attr(struct hinic_hwif
*hwif
, u32 entry_idx
,
269 enum hinic_pcie_nosnoop no_snooping
,
270 enum hinic_pcie_tph tph_en
)
272 u32 addr
, val
, dma_attr_entry
;
274 /* Read Modify Write */
275 addr
= HINIC_CSR_DMA_ATTR_ADDR(entry_idx
);
277 val
= hinic_hwif_read_reg(hwif
, addr
);
278 val
= HINIC_DMA_ATTR_CLEAR(val
, ST
) &
279 HINIC_DMA_ATTR_CLEAR(val
, AT
) &
280 HINIC_DMA_ATTR_CLEAR(val
, PH
) &
281 HINIC_DMA_ATTR_CLEAR(val
, NO_SNOOPING
) &
282 HINIC_DMA_ATTR_CLEAR(val
, TPH_EN
);
284 dma_attr_entry
= HINIC_DMA_ATTR_SET(st
, ST
) |
285 HINIC_DMA_ATTR_SET(at
, AT
) |
286 HINIC_DMA_ATTR_SET(ph
, PH
) |
287 HINIC_DMA_ATTR_SET(no_snooping
, NO_SNOOPING
) |
288 HINIC_DMA_ATTR_SET(tph_en
, TPH_EN
);
290 val
|= dma_attr_entry
;
291 hinic_hwif_write_reg(hwif
, addr
, val
);
295 * dma_attr_table_init - initialize the the default dma attributes
296 * @hwif: the HW interface of a pci function device
298 static void dma_attr_init(struct hinic_hwif
*hwif
)
300 set_dma_attr(hwif
, PCIE_ATTR_ENTRY
, HINIC_PCIE_ST_DISABLE
,
301 HINIC_PCIE_AT_DISABLE
, HINIC_PCIE_PH_DISABLE
,
302 HINIC_PCIE_SNOOP
, HINIC_PCIE_TPH_DISABLE
);
306 * hinic_init_hwif - initialize the hw interface
307 * @hwif: the HW interface of a pci function device
308 * @pdev: the pci device for acessing PCI resources
310 * Return 0 - Success, negative - Failure
312 int hinic_init_hwif(struct hinic_hwif
*hwif
, struct pci_dev
*pdev
)
318 hwif
->cfg_regs_bar
= pci_ioremap_bar(pdev
, HINIC_PCI_CFG_REGS_BAR
);
319 if (!hwif
->cfg_regs_bar
) {
320 dev_err(&pdev
->dev
, "Failed to map configuration regs\n");
324 err
= hwif_ready(hwif
);
326 dev_err(&pdev
->dev
, "HW interface is not ready\n");
330 read_hwif_attr(hwif
);
332 if (HINIC_IS_PF(hwif
))
335 /* No transactionss before DMA is initialized */
340 iounmap(hwif
->cfg_regs_bar
);
345 * hinic_free_hwif - free the HW interface
346 * @hwif: the HW interface of a pci function device
348 void hinic_free_hwif(struct hinic_hwif
*hwif
)
350 iounmap(hwif
->cfg_regs_bar
);