1 /* QLogic qed NIC Driver
2 * Copyright (c) 2015 QLogic Corporation
4 * This software is available under the terms of the GNU General Public License
5 * (GPL) Version 2, available from the file COPYING in the main directory of
9 #include <linux/types.h>
10 #include <asm/byteorder.h>
11 #include <linux/bitops.h>
12 #include <linux/errno.h>
13 #include <linux/kernel.h>
14 #include <linux/string.h>
16 #include <linux/qed/qed_chain.h>
21 #include "qed_reg_addr.h"
24 int qed_sp_init_request(struct qed_hwfn
*p_hwfn
,
25 struct qed_spq_entry
**pp_ent
,
30 struct qed_sp_init_request_params
*p_params
)
33 struct qed_spq_entry
*p_ent
= NULL
;
34 u32 opaque_cid
= opaque_fid
<< 16 | cid
;
39 rc
= qed_spq_get_entry(p_hwfn
, pp_ent
);
46 p_ent
->elem
.hdr
.cid
= cpu_to_le32(opaque_cid
);
47 p_ent
->elem
.hdr
.cmd_id
= cmd
;
48 p_ent
->elem
.hdr
.protocol_id
= protocol
;
50 p_ent
->priority
= QED_SPQ_PRIORITY_NORMAL
;
51 p_ent
->comp_mode
= p_params
->comp_mode
;
52 p_ent
->comp_done
.done
= 0;
54 switch (p_ent
->comp_mode
) {
55 case QED_SPQ_MODE_EBLOCK
:
56 p_ent
->comp_cb
.cookie
= &p_ent
->comp_done
;
59 case QED_SPQ_MODE_BLOCK
:
60 if (!p_params
->p_comp_data
)
63 p_ent
->comp_cb
.cookie
= p_params
->p_comp_data
->cookie
;
67 if (!p_params
->p_comp_data
)
68 p_ent
->comp_cb
.function
= NULL
;
70 p_ent
->comp_cb
= *p_params
->p_comp_data
;
74 DP_NOTICE(p_hwfn
, "Unknown SPQE completion mode %d\n",
79 DP_VERBOSE(p_hwfn
, QED_MSG_SPQ
,
80 "Initialized: CID %08x cmd %02x protocol %02x data_addr %lu comp_mode [%s]\n",
81 opaque_cid
, cmd
, protocol
,
82 (unsigned long)&p_ent
->ramrod
,
83 D_TRINE(p_ent
->comp_mode
, QED_SPQ_MODE_EBLOCK
,
84 QED_SPQ_MODE_BLOCK
, "MODE_EBLOCK", "MODE_BLOCK",
86 if (p_params
->ramrod_data_size
)
87 memset(&p_ent
->ramrod
, 0, p_params
->ramrod_data_size
);
92 int qed_sp_pf_start(struct qed_hwfn
*p_hwfn
,
95 struct qed_sp_init_request_params params
;
96 struct pf_start_ramrod_data
*p_ramrod
= NULL
;
97 u16 sb
= qed_int_get_sp_sb_id(p_hwfn
);
98 u8 sb_index
= p_hwfn
->p_eq
->eq_sb_index
;
99 struct qed_spq_entry
*p_ent
= NULL
;
102 /* update initial eq producer */
103 qed_eq_prod_update(p_hwfn
,
104 qed_chain_get_prod_idx(&p_hwfn
->p_eq
->chain
));
106 memset(¶ms
, 0, sizeof(params
));
107 params
.ramrod_data_size
= sizeof(*p_ramrod
);
108 params
.comp_mode
= QED_SPQ_MODE_EBLOCK
;
110 rc
= qed_sp_init_request(p_hwfn
,
112 qed_spq_get_cid(p_hwfn
),
113 p_hwfn
->hw_info
.opaque_fid
,
114 COMMON_RAMROD_PF_START
,
120 p_ramrod
= &p_ent
->ramrod
.pf_start
;
122 p_ramrod
->event_ring_sb_id
= cpu_to_le16(sb
);
123 p_ramrod
->event_ring_sb_index
= sb_index
;
124 p_ramrod
->path_id
= QED_PATH_ID(p_hwfn
);
125 p_ramrod
->dont_log_ramrods
= 0;
126 p_ramrod
->log_type_mask
= cpu_to_le16(0xf);
127 p_ramrod
->mf_mode
= mode
;
128 p_ramrod
->outer_tag
= p_hwfn
->hw_info
.ovlan
;
130 /* Place EQ address in RAMROD */
131 p_ramrod
->event_ring_pbl_addr
.hi
=
132 DMA_HI_LE(p_hwfn
->p_eq
->chain
.pbl
.p_phys_table
);
133 p_ramrod
->event_ring_pbl_addr
.lo
=
134 DMA_LO_LE(p_hwfn
->p_eq
->chain
.pbl
.p_phys_table
);
135 p_ramrod
->event_ring_num_pages
= (u8
)p_hwfn
->p_eq
->chain
.page_cnt
;
137 p_ramrod
->consolid_q_pbl_addr
.hi
=
138 DMA_HI_LE(p_hwfn
->p_consq
->chain
.pbl
.p_phys_table
);
139 p_ramrod
->consolid_q_pbl_addr
.lo
=
140 DMA_LO_LE(p_hwfn
->p_consq
->chain
.pbl
.p_phys_table
);
142 p_hwfn
->hw_info
.personality
= PERSONALITY_ETH
;
144 DP_VERBOSE(p_hwfn
, QED_MSG_SPQ
,
145 "Setting event_ring_sb [id %04x index %02x], mf [%s] outer_tag [%d]\n",
147 (p_ramrod
->mf_mode
== SF
) ? "SF" : "Multi-Pf",
148 p_ramrod
->outer_tag
);
150 return qed_spq_post(p_hwfn
, p_ent
, NULL
);
153 int qed_sp_pf_stop(struct qed_hwfn
*p_hwfn
)
155 struct qed_sp_init_request_params params
;
156 struct qed_spq_entry
*p_ent
= NULL
;
159 memset(¶ms
, 0, sizeof(params
));
160 params
.comp_mode
= QED_SPQ_MODE_EBLOCK
;
162 rc
= qed_sp_init_request(p_hwfn
, &p_ent
, qed_spq_get_cid(p_hwfn
),
163 p_hwfn
->hw_info
.opaque_fid
,
164 COMMON_RAMROD_PF_STOP
, PROTOCOLID_COMMON
,
169 return qed_spq_post(p_hwfn
, p_ent
, NULL
);