Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ice: Allocate flow profile

Create an extraction sequence based on the packet header protocols to be
programmed and allocate a flow profile for the extraction sequence.

Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Henry Tieman <henry.w.tieman@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

authored by

Tony Nguyen and committed by
Jeff Kirsher
31ad4e4e c90ed40c

+863 -39
+6
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
··· 232 232 */ 233 233 #define ICE_AQC_RES_TYPE_VSI_LIST_REP 0x03 234 234 #define ICE_AQC_RES_TYPE_VSI_LIST_PRUNE 0x04 235 + #define ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID 0x60 236 + 237 + #define ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM BIT(12) 238 + #define ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX BIT(13) 239 + 240 + #define ICE_AQC_RES_TYPE_FLAG_DEDICATED 0x00 235 241 236 242 /* Allocate Resources command (indirect 0x0208) 237 243 * Free Resources command (indirect 0x0209)
+75
drivers/net/ethernet/intel/ice/ice_common.c
··· 1498 1498 } 1499 1499 1500 1500 /** 1501 + * ice_aq_alloc_free_res - command to allocate/free resources 1502 + * @hw: pointer to the HW struct 1503 + * @num_entries: number of resource entries in buffer 1504 + * @buf: Indirect buffer to hold data parameters and response 1505 + * @buf_size: size of buffer for indirect commands 1506 + * @opc: pass in the command opcode 1507 + * @cd: pointer to command details structure or NULL 1508 + * 1509 + * Helper function to allocate/free resources using the admin queue commands 1510 + */ 1511 + enum ice_status 1512 + ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, 1513 + struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, 1514 + enum ice_adminq_opc opc, struct ice_sq_cd *cd) 1515 + { 1516 + struct ice_aqc_alloc_free_res_cmd *cmd; 1517 + struct ice_aq_desc desc; 1518 + 1519 + cmd = &desc.params.sw_res_ctrl; 1520 + 1521 + if (!buf) 1522 + return ICE_ERR_PARAM; 1523 + 1524 + if (buf_size < (num_entries * sizeof(buf->elem[0]))) 1525 + return ICE_ERR_PARAM; 1526 + 1527 + ice_fill_dflt_direct_cmd_desc(&desc, opc); 1528 + 1529 + desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 1530 + 1531 + cmd->num_entries = cpu_to_le16(num_entries); 1532 + 1533 + return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 1534 + } 1535 + 1536 + /** 1537 + * ice_alloc_hw_res - allocate resource 1538 + * @hw: pointer to the HW struct 1539 + * @type: type of resource 1540 + * @num: number of resources to allocate 1541 + * @btm: allocate from bottom 1542 + * @res: pointer to array that will receive the resources 1543 + */ 1544 + enum ice_status 1545 + ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res) 1546 + { 1547 + struct ice_aqc_alloc_free_res_elem *buf; 1548 + enum ice_status status; 1549 + u16 buf_len; 1550 + 1551 + buf_len = struct_size(buf, elem, num - 1); 1552 + buf = kzalloc(buf_len, GFP_KERNEL); 1553 + if (!buf) 1554 + return ICE_ERR_NO_MEMORY; 1555 + 1556 + /* Prepare buffer to allocate resource. */ 1557 + buf->num_elems = cpu_to_le16(num); 1558 + buf->res_type = cpu_to_le16(type | ICE_AQC_RES_TYPE_FLAG_DEDICATED | 1559 + ICE_AQC_RES_TYPE_FLAG_IGNORE_INDEX); 1560 + if (btm) 1561 + buf->res_type |= cpu_to_le16(ICE_AQC_RES_TYPE_FLAG_SCAN_BOTTOM); 1562 + 1563 + status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, 1564 + ice_aqc_opc_alloc_res, NULL); 1565 + if (status) 1566 + goto ice_alloc_res_exit; 1567 + 1568 + memcpy(res, buf->elem, sizeof(buf->elem) * num); 1569 + 1570 + ice_alloc_res_exit: 1571 + kfree(buf); 1572 + return status; 1573 + } 1574 + 1575 + /** 1501 1576 * ice_get_num_per_func - determine number of resources per PF 1502 1577 * @hw: pointer to the HW structure 1503 1578 * @max: value to be evenly split between each PF
+6
drivers/net/ethernet/intel/ice/ice_common.h
··· 34 34 ice_acquire_res(struct ice_hw *hw, enum ice_aq_res_ids res, 35 35 enum ice_aq_res_access_type access, u32 timeout); 36 36 void ice_release_res(struct ice_hw *hw, enum ice_aq_res_ids res); 37 + enum ice_status 38 + ice_alloc_hw_res(struct ice_hw *hw, u16 type, u16 num, bool btm, u16 *res); 37 39 enum ice_status ice_init_nvm(struct ice_hw *hw); 38 40 enum ice_status 39 41 ice_read_sr_buf(struct ice_hw *hw, u16 offset, u16 *words, u16 *data); 42 + enum ice_status 43 + ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, 44 + struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, 45 + enum ice_adminq_opc opc, struct ice_sq_cd *cd); 40 46 enum ice_status 41 47 ice_sq_send_cmd(struct ice_hw *hw, struct ice_ctl_q_info *cq, 42 48 struct ice_aq_desc *desc, void *buf, u16 buf_size,
+216
drivers/net/ethernet/intel/ice/ice_flex_pipe.c
··· 1118 1118 return 0; 1119 1119 } 1120 1120 1121 + /** 1122 + * ice_find_prof_id - find profile ID for a given field vector 1123 + * @hw: pointer to the hardware structure 1124 + * @blk: HW block 1125 + * @fv: field vector to search for 1126 + * @prof_id: receives the profile ID 1127 + */ 1128 + static enum ice_status 1129 + ice_find_prof_id(struct ice_hw *hw, enum ice_block blk, 1130 + struct ice_fv_word *fv, u8 *prof_id) 1131 + { 1132 + struct ice_es *es = &hw->blk[blk].es; 1133 + u16 off, i; 1134 + 1135 + for (i = 0; i < es->count; i++) { 1136 + off = i * es->fvw; 1137 + 1138 + if (memcmp(&es->t[off], fv, es->fvw * sizeof(*fv))) 1139 + continue; 1140 + 1141 + *prof_id = i; 1142 + return 0; 1143 + } 1144 + 1145 + return ICE_ERR_DOES_NOT_EXIST; 1146 + } 1147 + 1148 + /** 1149 + * ice_prof_id_rsrc_type - get profile ID resource type for a block type 1150 + * @blk: the block type 1151 + * @rsrc_type: pointer to variable to receive the resource type 1152 + */ 1153 + static bool ice_prof_id_rsrc_type(enum ice_block blk, u16 *rsrc_type) 1154 + { 1155 + switch (blk) { 1156 + case ICE_BLK_RSS: 1157 + *rsrc_type = ICE_AQC_RES_TYPE_HASH_PROF_BLDR_PROFID; 1158 + break; 1159 + default: 1160 + return false; 1161 + } 1162 + return true; 1163 + } 1164 + 1165 + /** 1166 + * ice_alloc_prof_id - allocate profile ID 1167 + * @hw: pointer to the HW struct 1168 + * @blk: the block to allocate the profile ID for 1169 + * @prof_id: pointer to variable to receive the profile ID 1170 + * 1171 + * This function allocates a new profile ID, which also corresponds to a Field 1172 + * Vector (Extraction Sequence) entry. 1173 + */ 1174 + static enum ice_status 1175 + ice_alloc_prof_id(struct ice_hw *hw, enum ice_block blk, u8 *prof_id) 1176 + { 1177 + enum ice_status status; 1178 + u16 res_type; 1179 + u16 get_prof; 1180 + 1181 + if (!ice_prof_id_rsrc_type(blk, &res_type)) 1182 + return ICE_ERR_PARAM; 1183 + 1184 + status = ice_alloc_hw_res(hw, res_type, 1, false, &get_prof); 1185 + if (!status) 1186 + *prof_id = (u8)get_prof; 1187 + 1188 + return status; 1189 + } 1190 + 1191 + /** 1192 + * ice_prof_inc_ref - increment reference count for profile 1193 + * @hw: pointer to the HW struct 1194 + * @blk: the block from which to free the profile ID 1195 + * @prof_id: the profile ID for which to increment the reference count 1196 + */ 1197 + static enum ice_status 1198 + ice_prof_inc_ref(struct ice_hw *hw, enum ice_block blk, u8 prof_id) 1199 + { 1200 + if (prof_id > hw->blk[blk].es.count) 1201 + return ICE_ERR_PARAM; 1202 + 1203 + hw->blk[blk].es.ref_count[prof_id]++; 1204 + 1205 + return 0; 1206 + } 1207 + 1208 + /** 1209 + * ice_write_es - write an extraction sequence to hardware 1210 + * @hw: pointer to the HW struct 1211 + * @blk: the block in which to write the extraction sequence 1212 + * @prof_id: the profile ID to write 1213 + * @fv: pointer to the extraction sequence to write - NULL to clear extraction 1214 + */ 1215 + static void 1216 + ice_write_es(struct ice_hw *hw, enum ice_block blk, u8 prof_id, 1217 + struct ice_fv_word *fv) 1218 + { 1219 + u16 off; 1220 + 1221 + off = prof_id * hw->blk[blk].es.fvw; 1222 + if (!fv) { 1223 + memset(&hw->blk[blk].es.t[off], 0, 1224 + hw->blk[blk].es.fvw * sizeof(*fv)); 1225 + hw->blk[blk].es.written[prof_id] = false; 1226 + } else { 1227 + memcpy(&hw->blk[blk].es.t[off], fv, 1228 + hw->blk[blk].es.fvw * sizeof(*fv)); 1229 + } 1230 + } 1231 + 1121 1232 /* Block / table section IDs */ 1122 1233 static const u32 ice_blk_sids[ICE_BLK_COUNT][ICE_SID_OFF_COUNT] = { 1123 1234 /* SWITCH */ ··· 1686 1575 err: 1687 1576 ice_free_hw_tbls(hw); 1688 1577 return ICE_ERR_NO_MEMORY; 1578 + } 1579 + 1580 + /** 1581 + * ice_add_prof - add profile 1582 + * @hw: pointer to the HW struct 1583 + * @blk: hardware block 1584 + * @id: profile tracking ID 1585 + * @ptypes: array of bitmaps indicating ptypes (ICE_FLOW_PTYPE_MAX bits) 1586 + * @es: extraction sequence (length of array is determined by the block) 1587 + * 1588 + * This function registers a profile, which matches a set of PTGs with a 1589 + * particular extraction sequence. While the hardware profile is allocated 1590 + * it will not be written until the first call to ice_add_flow that specifies 1591 + * the ID value used here. 1592 + */ 1593 + enum ice_status 1594 + ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], 1595 + struct ice_fv_word *es) 1596 + { 1597 + u32 bytes = DIV_ROUND_UP(ICE_FLOW_PTYPE_MAX, BITS_PER_BYTE); 1598 + DECLARE_BITMAP(ptgs_used, ICE_XLT1_CNT); 1599 + struct ice_prof_map *prof; 1600 + enum ice_status status; 1601 + u32 byte = 0; 1602 + u8 prof_id; 1603 + 1604 + bitmap_zero(ptgs_used, ICE_XLT1_CNT); 1605 + 1606 + mutex_lock(&hw->blk[blk].es.prof_map_lock); 1607 + 1608 + /* search for existing profile */ 1609 + status = ice_find_prof_id(hw, blk, es, &prof_id); 1610 + if (status) { 1611 + /* allocate profile ID */ 1612 + status = ice_alloc_prof_id(hw, blk, &prof_id); 1613 + if (status) 1614 + goto err_ice_add_prof; 1615 + 1616 + /* and write new es */ 1617 + ice_write_es(hw, blk, prof_id, es); 1618 + } 1619 + 1620 + ice_prof_inc_ref(hw, blk, prof_id); 1621 + 1622 + /* add profile info */ 1623 + prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*prof), GFP_KERNEL); 1624 + if (!prof) 1625 + goto err_ice_add_prof; 1626 + 1627 + prof->profile_cookie = id; 1628 + prof->prof_id = prof_id; 1629 + prof->ptg_cnt = 0; 1630 + prof->context = 0; 1631 + 1632 + /* build list of ptgs */ 1633 + while (bytes && prof->ptg_cnt < ICE_MAX_PTG_PER_PROFILE) { 1634 + u32 bit; 1635 + 1636 + if (!ptypes[byte]) { 1637 + bytes--; 1638 + byte++; 1639 + continue; 1640 + } 1641 + 1642 + /* Examine 8 bits per byte */ 1643 + for_each_set_bit(bit, (unsigned long *)&ptypes[byte], 1644 + BITS_PER_BYTE) { 1645 + u16 ptype; 1646 + u8 ptg; 1647 + u8 m; 1648 + 1649 + ptype = byte * BITS_PER_BYTE + bit; 1650 + 1651 + /* The package should place all ptypes in a non-zero 1652 + * PTG, so the following call should never fail. 1653 + */ 1654 + if (ice_ptg_find_ptype(hw, blk, ptype, &ptg)) 1655 + continue; 1656 + 1657 + /* If PTG is already added, skip and continue */ 1658 + if (test_bit(ptg, ptgs_used)) 1659 + continue; 1660 + 1661 + set_bit(ptg, ptgs_used); 1662 + prof->ptg[prof->ptg_cnt] = ptg; 1663 + 1664 + if (++prof->ptg_cnt >= ICE_MAX_PTG_PER_PROFILE) 1665 + break; 1666 + 1667 + /* nothing left in byte, then exit */ 1668 + m = ~((1 << (bit + 1)) - 1); 1669 + if (!(ptypes[byte] & m)) 1670 + break; 1671 + } 1672 + 1673 + bytes--; 1674 + byte++; 1675 + } 1676 + 1677 + list_add(&prof->list, &hw->blk[blk].es.prof_map); 1678 + status = 0; 1679 + 1680 + err_ice_add_prof: 1681 + mutex_unlock(&hw->blk[blk].es.prof_map_lock); 1682 + return status; 1689 1683 }
+3
drivers/net/ethernet/intel/ice/ice_flex_pipe.h
··· 18 18 19 19 #define ICE_PKG_CNT 4 20 20 21 + enum ice_status 22 + ice_add_prof(struct ice_hw *hw, enum ice_block blk, u64 id, u8 ptypes[], 23 + struct ice_fv_word *es); 21 24 enum ice_status ice_init_pkg(struct ice_hw *hw, u8 *buff, u32 len); 22 25 enum ice_status 23 26 ice_copy_and_init_pkg(struct ice_hw *hw, const u8 *buf, u32 len);
+15
drivers/net/ethernet/intel/ice/ice_flex_type.h
··· 3 3 4 4 #ifndef _ICE_FLEX_TYPE_H_ 5 5 #define _ICE_FLEX_TYPE_H_ 6 + 7 + #define ICE_FV_OFFSET_INVAL 0x1FF 8 + 6 9 /* Extraction Sequence (Field Vector) Table */ 7 10 struct ice_fv_word { 8 11 u8 prot_id; ··· 283 280 u8 ptg; 284 281 }; 285 282 283 + #define ICE_MAX_PTG_PER_PROFILE 32 284 + 285 + struct ice_prof_map { 286 + struct list_head list; 287 + u64 profile_cookie; 288 + u64 context; 289 + u8 prof_id; 290 + u8 ptg_cnt; 291 + u8 ptg[ICE_MAX_PTG_PER_PROFILE]; 292 + }; 293 + 286 294 struct ice_vsig_entry { 287 295 struct list_head prop_lst; 288 296 struct ice_vsig_vsi *first_vsi; ··· 385 371 u8 is_list_init; 386 372 }; 387 373 374 + #define ICE_FLOW_PTYPE_MAX ICE_XLT1_CNT 388 375 #endif /* _ICE_FLEX_TYPE_H_ */
+485 -3
drivers/net/ethernet/intel/ice/ice_flow.c
··· 40 40 ICE_FLOW_FLD_INFO(ICE_FLOW_SEG_HDR_UDP, 2, sizeof(__be16)), 41 41 }; 42 42 43 + /* Bitmaps indicating relevant packet types for a particular protocol header 44 + * 45 + * Packet types for packets with an Outer/First/Single IPv4 header 46 + */ 47 + static const u32 ice_ptypes_ipv4_ofos[] = { 48 + 0x1DC00000, 0x04000800, 0x00000000, 0x00000000, 49 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 50 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 51 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 52 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 53 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 54 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 55 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 56 + }; 57 + 58 + /* Packet types for packets with an Innermost/Last IPv4 header */ 59 + static const u32 ice_ptypes_ipv4_il[] = { 60 + 0xE0000000, 0xB807700E, 0x80000003, 0xE01DC03B, 61 + 0x0000000E, 0x00000000, 0x00000000, 0x00000000, 62 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 63 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 64 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 65 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 66 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 67 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 68 + }; 69 + 70 + /* Packet types for packets with an Outer/First/Single IPv6 header */ 71 + static const u32 ice_ptypes_ipv6_ofos[] = { 72 + 0x00000000, 0x00000000, 0x77000000, 0x10002000, 73 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 74 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 75 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 76 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 77 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 78 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 79 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 80 + }; 81 + 82 + /* Packet types for packets with an Innermost/Last IPv6 header */ 83 + static const u32 ice_ptypes_ipv6_il[] = { 84 + 0x00000000, 0x03B80770, 0x000001DC, 0x0EE00000, 85 + 0x00000770, 0x00000000, 0x00000000, 0x00000000, 86 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 87 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 88 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 89 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 90 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 91 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 92 + }; 93 + 94 + /* UDP Packet types for non-tunneled packets or tunneled 95 + * packets with inner UDP. 96 + */ 97 + static const u32 ice_ptypes_udp_il[] = { 98 + 0x81000000, 0x20204040, 0x04000010, 0x80810102, 99 + 0x00000040, 0x00000000, 0x00000000, 0x00000000, 100 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 101 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 102 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 103 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 104 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 105 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 106 + }; 107 + 108 + /* Packet types for packets with an Innermost/Last TCP header */ 109 + static const u32 ice_ptypes_tcp_il[] = { 110 + 0x04000000, 0x80810102, 0x10000040, 0x02040408, 111 + 0x00000102, 0x00000000, 0x00000000, 0x00000000, 112 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 113 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 114 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 115 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 116 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 117 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 118 + }; 119 + 120 + /* Packet types for packets with an Innermost/Last SCTP header */ 121 + static const u32 ice_ptypes_sctp_il[] = { 122 + 0x08000000, 0x01020204, 0x20000081, 0x04080810, 123 + 0x00000204, 0x00000000, 0x00000000, 0x00000000, 124 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 125 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 126 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 127 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 128 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 129 + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 130 + }; 131 + 132 + /* Manage parameters and info. used during the creation of a flow profile */ 133 + struct ice_flow_prof_params { 134 + enum ice_block blk; 135 + u16 entry_length; /* # of bytes formatted entry will require */ 136 + u8 es_cnt; 137 + struct ice_flow_prof *prof; 138 + 139 + /* For ACL, the es[0] will have the data of ICE_RX_MDID_PKT_FLAGS_15_0 140 + * This will give us the direction flags. 141 + */ 142 + struct ice_fv_word es[ICE_MAX_FV_WORDS]; 143 + DECLARE_BITMAP(ptypes, ICE_FLOW_PTYPE_MAX); 144 + }; 145 + 146 + #define ICE_FLOW_SEG_HDRS_L3_MASK \ 147 + (ICE_FLOW_SEG_HDR_IPV4 | ICE_FLOW_SEG_HDR_IPV6) 148 + #define ICE_FLOW_SEG_HDRS_L4_MASK \ 149 + (ICE_FLOW_SEG_HDR_TCP | ICE_FLOW_SEG_HDR_UDP | ICE_FLOW_SEG_HDR_SCTP) 150 + 151 + /** 152 + * ice_flow_val_hdrs - validates packet segments for valid protocol headers 153 + * @segs: array of one or more packet segments that describe the flow 154 + * @segs_cnt: number of packet segments provided 155 + */ 156 + static enum ice_status 157 + ice_flow_val_hdrs(struct ice_flow_seg_info *segs, u8 segs_cnt) 158 + { 159 + u8 i; 160 + 161 + for (i = 0; i < segs_cnt; i++) { 162 + /* Multiple L3 headers */ 163 + if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK && 164 + !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L3_MASK)) 165 + return ICE_ERR_PARAM; 166 + 167 + /* Multiple L4 headers */ 168 + if (segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK && 169 + !is_power_of_2(segs[i].hdrs & ICE_FLOW_SEG_HDRS_L4_MASK)) 170 + return ICE_ERR_PARAM; 171 + } 172 + 173 + return 0; 174 + } 175 + 176 + /** 177 + * ice_flow_proc_seg_hdrs - process protocol headers present in pkt segments 178 + * @params: information about the flow to be processed 179 + * 180 + * This function identifies the packet types associated with the protocol 181 + * headers being present in packet segments of the specified flow profile. 182 + */ 183 + static enum ice_status 184 + ice_flow_proc_seg_hdrs(struct ice_flow_prof_params *params) 185 + { 186 + struct ice_flow_prof *prof; 187 + u8 i; 188 + 189 + memset(params->ptypes, 0xff, sizeof(params->ptypes)); 190 + 191 + prof = params->prof; 192 + 193 + for (i = 0; i < params->prof->segs_cnt; i++) { 194 + const unsigned long *src; 195 + u32 hdrs; 196 + 197 + hdrs = prof->segs[i].hdrs; 198 + 199 + if (hdrs & ICE_FLOW_SEG_HDR_IPV4) { 200 + src = !i ? (const unsigned long *)ice_ptypes_ipv4_ofos : 201 + (const unsigned long *)ice_ptypes_ipv4_il; 202 + bitmap_and(params->ptypes, params->ptypes, src, 203 + ICE_FLOW_PTYPE_MAX); 204 + } else if (hdrs & ICE_FLOW_SEG_HDR_IPV6) { 205 + src = !i ? (const unsigned long *)ice_ptypes_ipv6_ofos : 206 + (const unsigned long *)ice_ptypes_ipv6_il; 207 + bitmap_and(params->ptypes, params->ptypes, src, 208 + ICE_FLOW_PTYPE_MAX); 209 + } 210 + 211 + if (hdrs & ICE_FLOW_SEG_HDR_UDP) { 212 + src = (const unsigned long *)ice_ptypes_udp_il; 213 + bitmap_and(params->ptypes, params->ptypes, src, 214 + ICE_FLOW_PTYPE_MAX); 215 + } else if (hdrs & ICE_FLOW_SEG_HDR_TCP) { 216 + bitmap_and(params->ptypes, params->ptypes, 217 + (const unsigned long *)ice_ptypes_tcp_il, 218 + ICE_FLOW_PTYPE_MAX); 219 + } else if (hdrs & ICE_FLOW_SEG_HDR_SCTP) { 220 + src = (const unsigned long *)ice_ptypes_sctp_il; 221 + bitmap_and(params->ptypes, params->ptypes, src, 222 + ICE_FLOW_PTYPE_MAX); 223 + } 224 + } 225 + 226 + return 0; 227 + } 228 + 229 + /** 230 + * ice_flow_xtract_fld - Create an extraction sequence entry for the given field 231 + * @hw: pointer to the HW struct 232 + * @params: information about the flow to be processed 233 + * @seg: packet segment index of the field to be extracted 234 + * @fld: ID of field to be extracted 235 + * 236 + * This function determines the protocol ID, offset, and size of the given 237 + * field. It then allocates one or more extraction sequence entries for the 238 + * given field, and fill the entries with protocol ID and offset information. 239 + */ 240 + static enum ice_status 241 + ice_flow_xtract_fld(struct ice_hw *hw, struct ice_flow_prof_params *params, 242 + u8 seg, enum ice_flow_field fld) 243 + { 244 + enum ice_prot_id prot_id = ICE_PROT_ID_INVAL; 245 + u8 fv_words = hw->blk[params->blk].es.fvw; 246 + struct ice_flow_fld_info *flds; 247 + u16 cnt, ese_bits, i; 248 + u16 off; 249 + 250 + flds = params->prof->segs[seg].fields; 251 + 252 + switch (fld) { 253 + case ICE_FLOW_FIELD_IDX_IPV4_SA: 254 + case ICE_FLOW_FIELD_IDX_IPV4_DA: 255 + prot_id = seg == 0 ? ICE_PROT_IPV4_OF_OR_S : ICE_PROT_IPV4_IL; 256 + break; 257 + case ICE_FLOW_FIELD_IDX_IPV6_SA: 258 + case ICE_FLOW_FIELD_IDX_IPV6_DA: 259 + prot_id = seg == 0 ? ICE_PROT_IPV6_OF_OR_S : ICE_PROT_IPV6_IL; 260 + break; 261 + case ICE_FLOW_FIELD_IDX_TCP_SRC_PORT: 262 + case ICE_FLOW_FIELD_IDX_TCP_DST_PORT: 263 + prot_id = ICE_PROT_TCP_IL; 264 + break; 265 + case ICE_FLOW_FIELD_IDX_UDP_SRC_PORT: 266 + case ICE_FLOW_FIELD_IDX_UDP_DST_PORT: 267 + prot_id = ICE_PROT_UDP_IL_OR_S; 268 + break; 269 + default: 270 + return ICE_ERR_NOT_IMPL; 271 + } 272 + 273 + /* Each extraction sequence entry is a word in size, and extracts a 274 + * word-aligned offset from a protocol header. 275 + */ 276 + ese_bits = ICE_FLOW_FV_EXTRACT_SZ * BITS_PER_BYTE; 277 + 278 + flds[fld].xtrct.prot_id = prot_id; 279 + flds[fld].xtrct.off = (ice_flds_info[fld].off / ese_bits) * 280 + ICE_FLOW_FV_EXTRACT_SZ; 281 + flds[fld].xtrct.disp = (u8)(ice_flds_info[fld].off % ese_bits); 282 + flds[fld].xtrct.idx = params->es_cnt; 283 + 284 + /* Adjust the next field-entry index after accommodating the number of 285 + * entries this field consumes 286 + */ 287 + cnt = DIV_ROUND_UP(flds[fld].xtrct.disp + ice_flds_info[fld].size, 288 + ese_bits); 289 + 290 + /* Fill in the extraction sequence entries needed for this field */ 291 + off = flds[fld].xtrct.off; 292 + for (i = 0; i < cnt; i++) { 293 + u8 idx; 294 + 295 + /* Make sure the number of extraction sequence required 296 + * does not exceed the block's capability 297 + */ 298 + if (params->es_cnt >= fv_words) 299 + return ICE_ERR_MAX_LIMIT; 300 + 301 + /* some blocks require a reversed field vector layout */ 302 + if (hw->blk[params->blk].es.reverse) 303 + idx = fv_words - params->es_cnt - 1; 304 + else 305 + idx = params->es_cnt; 306 + 307 + params->es[idx].prot_id = prot_id; 308 + params->es[idx].off = off; 309 + params->es_cnt++; 310 + 311 + off += ICE_FLOW_FV_EXTRACT_SZ; 312 + } 313 + 314 + return 0; 315 + } 316 + 317 + /** 318 + * ice_flow_create_xtrct_seq - Create an extraction sequence for given segments 319 + * @hw: pointer to the HW struct 320 + * @params: information about the flow to be processed 321 + * 322 + * This function iterates through all matched fields in the given segments, and 323 + * creates an extraction sequence for the fields. 324 + */ 325 + static enum ice_status 326 + ice_flow_create_xtrct_seq(struct ice_hw *hw, 327 + struct ice_flow_prof_params *params) 328 + { 329 + struct ice_flow_prof *prof = params->prof; 330 + enum ice_status status = 0; 331 + u8 i; 332 + 333 + for (i = 0; i < prof->segs_cnt; i++) { 334 + u8 j; 335 + 336 + for_each_set_bit(j, (unsigned long *)&prof->segs[i].match, 337 + ICE_FLOW_FIELD_IDX_MAX) { 338 + status = ice_flow_xtract_fld(hw, params, i, 339 + (enum ice_flow_field)j); 340 + if (status) 341 + return status; 342 + } 343 + } 344 + 345 + return status; 346 + } 347 + 348 + /** 349 + * ice_flow_proc_segs - process all packet segments associated with a profile 350 + * @hw: pointer to the HW struct 351 + * @params: information about the flow to be processed 352 + */ 353 + static enum ice_status 354 + ice_flow_proc_segs(struct ice_hw *hw, struct ice_flow_prof_params *params) 355 + { 356 + enum ice_status status; 357 + 358 + status = ice_flow_proc_seg_hdrs(params); 359 + if (status) 360 + return status; 361 + 362 + status = ice_flow_create_xtrct_seq(hw, params); 363 + if (status) 364 + return status; 365 + 366 + switch (params->blk) { 367 + case ICE_BLK_RSS: 368 + /* Only header information is provided for RSS configuration. 369 + * No further processing is needed. 370 + */ 371 + status = 0; 372 + break; 373 + default: 374 + return ICE_ERR_NOT_IMPL; 375 + } 376 + 377 + return status; 378 + } 379 + 380 + /** 381 + * ice_flow_add_prof_sync - Add a flow profile for packet segments and fields 382 + * @hw: pointer to the HW struct 383 + * @blk: classification stage 384 + * @dir: flow direction 385 + * @prof_id: unique ID to identify this flow profile 386 + * @segs: array of one or more packet segments that describe the flow 387 + * @segs_cnt: number of packet segments provided 388 + * @prof: stores the returned flow profile added 389 + * 390 + * Assumption: the caller has acquired the lock to the profile list 391 + */ 392 + static enum ice_status 393 + ice_flow_add_prof_sync(struct ice_hw *hw, enum ice_block blk, 394 + enum ice_flow_dir dir, u64 prof_id, 395 + struct ice_flow_seg_info *segs, u8 segs_cnt, 396 + struct ice_flow_prof **prof) 397 + { 398 + struct ice_flow_prof_params params; 399 + enum ice_status status; 400 + u8 i; 401 + 402 + if (!prof) 403 + return ICE_ERR_BAD_PTR; 404 + 405 + memset(&params, 0, sizeof(params)); 406 + params.prof = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*params.prof), 407 + GFP_KERNEL); 408 + if (!params.prof) 409 + return ICE_ERR_NO_MEMORY; 410 + 411 + /* initialize extraction sequence to all invalid (0xff) */ 412 + for (i = 0; i < ICE_MAX_FV_WORDS; i++) { 413 + params.es[i].prot_id = ICE_PROT_INVALID; 414 + params.es[i].off = ICE_FV_OFFSET_INVAL; 415 + } 416 + 417 + params.blk = blk; 418 + params.prof->id = prof_id; 419 + params.prof->dir = dir; 420 + params.prof->segs_cnt = segs_cnt; 421 + 422 + /* Make a copy of the segments that need to be persistent in the flow 423 + * profile instance 424 + */ 425 + for (i = 0; i < segs_cnt; i++) 426 + memcpy(&params.prof->segs[i], &segs[i], sizeof(*segs)); 427 + 428 + status = ice_flow_proc_segs(hw, &params); 429 + if (status) { 430 + ice_debug(hw, ICE_DBG_FLOW, 431 + "Error processing a flow's packet segments\n"); 432 + goto out; 433 + } 434 + 435 + /* Add a HW profile for this flow profile */ 436 + status = ice_add_prof(hw, blk, prof_id, (u8 *)params.ptypes, params.es); 437 + if (status) { 438 + ice_debug(hw, ICE_DBG_FLOW, "Error adding a HW flow profile\n"); 439 + goto out; 440 + } 441 + 442 + INIT_LIST_HEAD(&params.prof->entries); 443 + mutex_init(&params.prof->entries_lock); 444 + *prof = params.prof; 445 + 446 + out: 447 + if (status) 448 + devm_kfree(ice_hw_to_dev(hw), params.prof); 449 + 450 + return status; 451 + } 452 + 453 + /** 454 + * ice_flow_add_prof - Add a flow profile for packet segments and matched fields 455 + * @hw: pointer to the HW struct 456 + * @blk: classification stage 457 + * @dir: flow direction 458 + * @prof_id: unique ID to identify this flow profile 459 + * @segs: array of one or more packet segments that describe the flow 460 + * @segs_cnt: number of packet segments provided 461 + */ 462 + static enum ice_status 463 + ice_flow_add_prof(struct ice_hw *hw, enum ice_block blk, enum ice_flow_dir dir, 464 + u64 prof_id, struct ice_flow_seg_info *segs, u8 segs_cnt) 465 + { 466 + struct ice_flow_prof *prof = NULL; 467 + enum ice_status status; 468 + 469 + if (segs_cnt > ICE_FLOW_SEG_MAX) 470 + return ICE_ERR_MAX_LIMIT; 471 + 472 + if (!segs_cnt) 473 + return ICE_ERR_PARAM; 474 + 475 + if (!segs) 476 + return ICE_ERR_BAD_PTR; 477 + 478 + status = ice_flow_val_hdrs(segs, segs_cnt); 479 + if (status) 480 + return status; 481 + 482 + mutex_lock(&hw->fl_profs_locks[blk]); 483 + 484 + status = ice_flow_add_prof_sync(hw, blk, dir, prof_id, segs, segs_cnt, 485 + &prof); 486 + if (!status) 487 + list_add(&prof->l_entry, &hw->fl_profs[blk]); 488 + 489 + mutex_unlock(&hw->fl_profs_locks[blk]); 490 + 491 + return status; 492 + } 493 + 43 494 /** 44 495 * ice_flow_set_fld_ext - specifies locations of field from entry's input buffer 45 496 * @seg: packet segment the field being set belongs to ··· 612 161 return 0; 613 162 } 614 163 164 + #define ICE_FLOW_PROF_HASH_S 0 165 + #define ICE_FLOW_PROF_HASH_M (0xFFFFFFFFULL << ICE_FLOW_PROF_HASH_S) 166 + #define ICE_FLOW_PROF_HDR_S 32 167 + #define ICE_FLOW_PROF_HDR_M (0x3FFFFFFFULL << ICE_FLOW_PROF_HDR_S) 168 + #define ICE_FLOW_PROF_ENCAP_S 63 169 + #define ICE_FLOW_PROF_ENCAP_M (BIT_ULL(ICE_FLOW_PROF_ENCAP_S)) 170 + 615 171 #define ICE_RSS_OUTER_HEADERS 1 172 + 173 + /* Flow profile ID format: 174 + * [0:31] - Packet match fields 175 + * [32:62] - Protocol header 176 + * [63] - Encapsulation flag, 0 if non-tunneled, 1 if tunneled 177 + */ 178 + #define ICE_FLOW_GEN_PROFID(hash, hdr, segs_cnt) \ 179 + (u64)(((u64)(hash) & ICE_FLOW_PROF_HASH_M) | \ 180 + (((u64)(hdr) << ICE_FLOW_PROF_HDR_S) & ICE_FLOW_PROF_HDR_M) | \ 181 + ((u8)((segs_cnt) - 1) ? ICE_FLOW_PROF_ENCAP_M : 0)) 616 182 617 183 /** 618 184 * ice_add_rss_cfg_sync - add an RSS configuration 185 + * @hw: pointer to the hardware structure 619 186 * @hashed_flds: hash bit fields (ICE_FLOW_HASH_*) to configure 620 187 * @addl_hdrs: protocol header fields 621 188 * @segs_cnt: packet segment count ··· 641 172 * Assumption: lock has already been acquired for RSS list 642 173 */ 643 174 static enum ice_status 644 - ice_add_rss_cfg_sync(u64 hashed_flds, u32 addl_hdrs, u8 segs_cnt) 175 + ice_add_rss_cfg_sync(struct ice_hw *hw, u64 hashed_flds, u32 addl_hdrs, 176 + u8 segs_cnt) 645 177 { 646 178 struct ice_flow_seg_info *segs; 647 179 enum ice_status status; ··· 657 187 /* Construct the packet segment info from the hashed fields */ 658 188 status = ice_flow_set_rss_seg_info(&segs[segs_cnt - 1], hashed_flds, 659 189 addl_hdrs); 190 + if (status) 191 + goto exit; 660 192 193 + /* Create a new flow profile with generated profile and packet 194 + * segment information. 195 + */ 196 + status = ice_flow_add_prof(hw, ICE_BLK_RSS, ICE_FLOW_RX, 197 + ICE_FLOW_GEN_PROFID(hashed_flds, 198 + segs[segs_cnt - 1].hdrs, 199 + segs_cnt), 200 + segs, segs_cnt); 201 + 202 + exit: 661 203 kfree(segs); 662 204 return status; 663 205 } ··· 696 214 return ICE_ERR_PARAM; 697 215 698 216 mutex_lock(&hw->rss_locks); 699 - status = ice_add_rss_cfg_sync(hashed_flds, addl_hdrs, 217 + status = ice_add_rss_cfg_sync(hw, hashed_flds, addl_hdrs, 700 218 ICE_RSS_OUTER_HEADERS); 701 219 mutex_unlock(&hw->rss_locks); 702 220 ··· 719 237 mutex_lock(&hw->rss_locks); 720 238 list_for_each_entry(r, &hw->rss_list_head, l_entry) { 721 239 if (test_bit(vsi_handle, r->vsis)) { 722 - status = ice_add_rss_cfg_sync(r->hashed_flds, 240 + status = ice_add_rss_cfg_sync(hw, r->hashed_flds, 723 241 r->packet_hdr, 724 242 ICE_RSS_OUTER_HEADERS); 725 243 if (status)
+23
drivers/net/ethernet/intel/ice/ice_flow.h
··· 56 56 ICE_FLOW_FIELD_IDX_MAX 57 57 }; 58 58 59 + enum ice_flow_dir { 60 + ICE_FLOW_RX = 0x02, 61 + }; 62 + 59 63 #define ICE_FLOW_SEG_MAX 2 64 + #define ICE_FLOW_FV_EXTRACT_SZ 2 65 + 60 66 #define ICE_FLOW_SET_HDRS(seg, val) ((seg)->hdrs |= (u32)(val)) 61 67 62 68 struct ice_flow_seg_xtrct { ··· 103 97 u64 range; /* Bitmask indicating header fields matched as ranges */ 104 98 105 99 struct ice_flow_fld_info fields[ICE_FLOW_FIELD_IDX_MAX]; 100 + }; 101 + 102 + struct ice_flow_prof { 103 + struct list_head l_entry; 104 + 105 + u64 id; 106 + enum ice_flow_dir dir; 107 + u8 segs_cnt; 108 + 109 + /* Keep track of flow entries associated with this flow profile */ 110 + struct mutex entries_lock; 111 + struct list_head entries; 112 + 113 + struct ice_flow_seg_info segs[ICE_FLOW_SEG_MAX]; 114 + 115 + /* software VSI handles referenced by this flow profile */ 116 + DECLARE_BITMAP(vsis, ICE_MAX_VSI); 106 117 }; 107 118 108 119 struct ice_rss_cfg {
+8
drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
··· 199 199 /* Receive Flex Descriptor Rx opcode values */ 200 200 #define ICE_RX_OPC_MDID 0x01 201 201 202 + /* Receive Descriptor MDID values that access packet flags */ 203 + enum ice_flex_mdid_pkt_flags { 204 + ICE_RX_MDID_PKT_FLAGS_15_0 = 20, 205 + ICE_RX_MDID_PKT_FLAGS_31_16, 206 + ICE_RX_MDID_PKT_FLAGS_47_32, 207 + ICE_RX_MDID_PKT_FLAGS_63_48, 208 + }; 209 + 202 210 /* Receive Descriptor MDID values */ 203 211 enum ice_flex_rx_mdid { 204 212 ICE_RX_MDID_FLOW_ID_LOWER = 5,
+24
drivers/net/ethernet/intel/ice/ice_protocol_type.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (c) 2019, Intel Corporation. */ 3 + 4 + #ifndef _ICE_PROTOCOL_TYPE_H_ 5 + #define _ICE_PROTOCOL_TYPE_H_ 6 + /* Decoders for ice_prot_id: 7 + * - F: First 8 + * - I: Inner 9 + * - L: Last 10 + * - O: Outer 11 + * - S: Single 12 + */ 13 + enum ice_prot_id { 14 + ICE_PROT_ID_INVAL = 0, 15 + ICE_PROT_IPV4_OF_OR_S = 32, 16 + ICE_PROT_IPV4_IL = 33, 17 + ICE_PROT_IPV6_OF_OR_S = 40, 18 + ICE_PROT_IPV6_IL = 41, 19 + ICE_PROT_TCP_IL = 49, 20 + ICE_PROT_UDP_IL_OR_S = 53, 21 + ICE_PROT_META_ID = 255, /* when offset == metadata */ 22 + ICE_PROT_INVALID = 255 /* when offset == ICE_FV_OFFSET_INVAL */ 23 + }; 24 + #endif /* _ICE_PROTOCOL_TYPE_H_ */
-36
drivers/net/ethernet/intel/ice/ice_switch.c
··· 50 50 ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi))) 51 51 52 52 /** 53 - * ice_aq_alloc_free_res - command to allocate/free resources 54 - * @hw: pointer to the HW struct 55 - * @num_entries: number of resource entries in buffer 56 - * @buf: Indirect buffer to hold data parameters and response 57 - * @buf_size: size of buffer for indirect commands 58 - * @opc: pass in the command opcode 59 - * @cd: pointer to command details structure or NULL 60 - * 61 - * Helper function to allocate/free resources using the admin queue commands 62 - */ 63 - static enum ice_status 64 - ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries, 65 - struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size, 66 - enum ice_adminq_opc opc, struct ice_sq_cd *cd) 67 - { 68 - struct ice_aqc_alloc_free_res_cmd *cmd; 69 - struct ice_aq_desc desc; 70 - 71 - cmd = &desc.params.sw_res_ctrl; 72 - 73 - if (!buf) 74 - return ICE_ERR_PARAM; 75 - 76 - if (buf_size < (num_entries * sizeof(buf->elem[0]))) 77 - return ICE_ERR_PARAM; 78 - 79 - ice_fill_dflt_direct_cmd_desc(&desc, opc); 80 - 81 - desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); 82 - 83 - cmd->num_entries = cpu_to_le16(num_entries); 84 - 85 - return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); 86 - } 87 - 88 - /** 89 53 * ice_init_def_sw_recp - initialize the recipe book keeping tables 90 54 * @hw: pointer to the HW struct 91 55 *
+2
drivers/net/ethernet/intel/ice/ice_type.h
··· 13 13 #include "ice_controlq.h" 14 14 #include "ice_lan_tx_rx.h" 15 15 #include "ice_flex_type.h" 16 + #include "ice_protocol_type.h" 16 17 17 18 static inline bool ice_is_tc_ena(unsigned long bitmap, u8 tc) 18 19 { ··· 42 41 #define ICE_DBG_QCTX BIT_ULL(6) 43 42 #define ICE_DBG_NVM BIT_ULL(7) 44 43 #define ICE_DBG_LAN BIT_ULL(8) 44 + #define ICE_DBG_FLOW BIT_ULL(9) 45 45 #define ICE_DBG_SW BIT_ULL(13) 46 46 #define ICE_DBG_SCHED BIT_ULL(14) 47 47 #define ICE_DBG_PKG BIT_ULL(16)