diff options
author | Sunil Goutham <sgoutham@marvell.com> | 2018-10-22 13:55:55 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-22 23:15:38 -0400 |
commit | 4b05528ebf0c3ffd61543cfcca78844f05d8eb9d (patch) | |
tree | d812cb4126823bc07fcaba50e82f254f9ec983ba | |
parent | 52d3d327a2595be7b69c956b45ad44de4ea6f692 (diff) |
octeontx2-af: Update bcast list upon NIXLF alloc/free
Upon NIXLF ALLOC/FREE, add or remove corresponding PF_FUNC from
the broadcast packet replication list of the CGX LMAC mapped
RVU PF.
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index 947424a9600f..833328330519 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include "rvu.h" | 16 | #include "rvu.h" |
17 | #include "cgx.h" | 17 | #include "cgx.h" |
18 | 18 | ||
19 | static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add); | ||
20 | |||
19 | enum mc_tbl_sz { | 21 | enum mc_tbl_sz { |
20 | MC_TBL_SZ_256, | 22 | MC_TBL_SZ_256, |
21 | MC_TBL_SZ_512, | 23 | MC_TBL_SZ_512, |
@@ -108,6 +110,7 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf) | |||
108 | struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); | 110 | struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); |
109 | u8 cgx_id, lmac_id; | 111 | u8 cgx_id, lmac_id; |
110 | int pkind, pf; | 112 | int pkind, pf; |
113 | int err; | ||
111 | 114 | ||
112 | pf = rvu_get_pf(pcifunc); | 115 | pf = rvu_get_pf(pcifunc); |
113 | if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK) | 116 | if (!is_pf_cgxmapped(rvu, pf) && type != NIX_INTF_TYPE_LBK) |
@@ -130,9 +133,30 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf) | |||
130 | case NIX_INTF_TYPE_LBK: | 133 | case NIX_INTF_TYPE_LBK: |
131 | break; | 134 | break; |
132 | } | 135 | } |
136 | |||
137 | /* Add this PF_FUNC to bcast pkt replication list */ | ||
138 | err = nix_update_bcast_mce_list(rvu, pcifunc, true); | ||
139 | if (err) { | ||
140 | dev_err(rvu->dev, | ||
141 | "Bcast list, failed to enable PF_FUNC 0x%x\n", | ||
142 | pcifunc); | ||
143 | } | ||
133 | return 0; | 144 | return 0; |
134 | } | 145 | } |
135 | 146 | ||
147 | static void nix_interface_deinit(struct rvu *rvu, u16 pcifunc, u8 nixlf) | ||
148 | { | ||
149 | int err; | ||
150 | |||
151 | /* Remove this PF_FUNC from bcast pkt replication list */ | ||
152 | err = nix_update_bcast_mce_list(rvu, pcifunc, false); | ||
153 | if (err) { | ||
154 | dev_err(rvu->dev, | ||
155 | "Bcast list, failed to disable PF_FUNC 0x%x\n", | ||
156 | pcifunc); | ||
157 | } | ||
158 | } | ||
159 | |||
136 | static void nix_setup_lso_tso_l3(struct rvu *rvu, int blkaddr, | 160 | static void nix_setup_lso_tso_l3(struct rvu *rvu, int blkaddr, |
137 | u64 format, bool v4, u64 *fidx) | 161 | u64 format, bool v4, u64 *fidx) |
138 | { | 162 | { |
@@ -786,6 +810,8 @@ int rvu_mbox_handler_NIX_LF_FREE(struct rvu *rvu, struct msg_req *req, | |||
786 | if (nixlf < 0) | 810 | if (nixlf < 0) |
787 | return NIX_AF_ERR_AF_LF_INVALID; | 811 | return NIX_AF_ERR_AF_LF_INVALID; |
788 | 812 | ||
813 | nix_interface_deinit(rvu, pcifunc, nixlf); | ||
814 | |||
789 | /* Reset this NIX LF */ | 815 | /* Reset this NIX LF */ |
790 | err = rvu_lf_reset(rvu, block, nixlf); | 816 | err = rvu_lf_reset(rvu, block, nixlf); |
791 | if (err) { | 817 | if (err) { |
@@ -1147,6 +1173,113 @@ static int nix_setup_mce(struct rvu *rvu, int mce, u8 op, | |||
1147 | return 0; | 1173 | return 0; |
1148 | } | 1174 | } |
1149 | 1175 | ||
1176 | static int nix_update_mce_list(struct nix_mce_list *mce_list, | ||
1177 | u16 pcifunc, int idx, bool add) | ||
1178 | { | ||
1179 | struct mce *mce, *tail = NULL; | ||
1180 | bool delete = false; | ||
1181 | |||
1182 | /* Scan through the current list */ | ||
1183 | hlist_for_each_entry(mce, &mce_list->head, node) { | ||
1184 | /* If already exists, then delete */ | ||
1185 | if (mce->pcifunc == pcifunc && !add) { | ||
1186 | delete = true; | ||
1187 | break; | ||
1188 | } | ||
1189 | tail = mce; | ||
1190 | } | ||
1191 | |||
1192 | if (delete) { | ||
1193 | hlist_del(&mce->node); | ||
1194 | kfree(mce); | ||
1195 | mce_list->count--; | ||
1196 | return 0; | ||
1197 | } | ||
1198 | |||
1199 | if (!add) | ||
1200 | return 0; | ||
1201 | |||
1202 | /* Add a new one to the list, at the tail */ | ||
1203 | mce = kzalloc(sizeof(*mce), GFP_KERNEL); | ||
1204 | if (!mce) | ||
1205 | return -ENOMEM; | ||
1206 | mce->idx = idx; | ||
1207 | mce->pcifunc = pcifunc; | ||
1208 | if (!tail) | ||
1209 | hlist_add_head(&mce->node, &mce_list->head); | ||
1210 | else | ||
1211 | hlist_add_behind(&mce->node, &tail->node); | ||
1212 | mce_list->count++; | ||
1213 | return 0; | ||
1214 | } | ||
1215 | |||
1216 | static int nix_update_bcast_mce_list(struct rvu *rvu, u16 pcifunc, bool add) | ||
1217 | { | ||
1218 | int err = 0, idx, next_idx, count; | ||
1219 | struct nix_mce_list *mce_list; | ||
1220 | struct mce *mce, *next_mce; | ||
1221 | struct nix_mcast *mcast; | ||
1222 | struct nix_hw *nix_hw; | ||
1223 | struct rvu_pfvf *pfvf; | ||
1224 | int blkaddr; | ||
1225 | |||
1226 | blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc); | ||
1227 | if (blkaddr < 0) | ||
1228 | return 0; | ||
1229 | |||
1230 | nix_hw = get_nix_hw(rvu->hw, blkaddr); | ||
1231 | if (!nix_hw) | ||
1232 | return 0; | ||
1233 | |||
1234 | mcast = &nix_hw->mcast; | ||
1235 | |||
1236 | /* Get this PF/VF func's MCE index */ | ||
1237 | pfvf = rvu_get_pfvf(rvu, pcifunc & ~RVU_PFVF_FUNC_MASK); | ||
1238 | idx = pfvf->bcast_mce_idx + (pcifunc & RVU_PFVF_FUNC_MASK); | ||
1239 | |||
1240 | mce_list = &pfvf->bcast_mce_list; | ||
1241 | if (idx > (pfvf->bcast_mce_idx + mce_list->max)) { | ||
1242 | dev_err(rvu->dev, | ||
1243 | "%s: Idx %d > max MCE idx %d, for PF%d bcast list\n", | ||
1244 | __func__, idx, mce_list->max, | ||
1245 | pcifunc >> RVU_PFVF_PF_SHIFT); | ||
1246 | return -EINVAL; | ||
1247 | } | ||
1248 | |||
1249 | spin_lock(&mcast->mce_lock); | ||
1250 | |||
1251 | err = nix_update_mce_list(mce_list, pcifunc, idx, add); | ||
1252 | if (err) | ||
1253 | goto end; | ||
1254 | |||
1255 | /* Disable MCAM entry in NPC */ | ||
1256 | |||
1257 | if (!mce_list->count) | ||
1258 | goto end; | ||
1259 | count = mce_list->count; | ||
1260 | |||
1261 | /* Dump the updated list to HW */ | ||
1262 | hlist_for_each_entry(mce, &mce_list->head, node) { | ||
1263 | next_idx = 0; | ||
1264 | count--; | ||
1265 | if (count) { | ||
1266 | next_mce = hlist_entry(mce->node.next, | ||
1267 | struct mce, node); | ||
1268 | next_idx = next_mce->idx; | ||
1269 | } | ||
1270 | /* EOL should be set in last MCE */ | ||
1271 | err = nix_setup_mce(rvu, mce->idx, | ||
1272 | NIX_AQ_INSTOP_WRITE, mce->pcifunc, | ||
1273 | next_idx, count ? false : true); | ||
1274 | if (err) | ||
1275 | goto end; | ||
1276 | } | ||
1277 | |||
1278 | end: | ||
1279 | spin_unlock(&mcast->mce_lock); | ||
1280 | return err; | ||
1281 | } | ||
1282 | |||
1150 | static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw) | 1283 | static int nix_setup_bcast_tables(struct rvu *rvu, struct nix_hw *nix_hw) |
1151 | { | 1284 | { |
1152 | struct nix_mcast *mcast = &nix_hw->mcast; | 1285 | struct nix_mcast *mcast = &nix_hw->mcast; |