.. | .. |
---|
| 1 | +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) |
---|
1 | 2 | /* QLogic qed NIC Driver |
---|
2 | 3 | * Copyright (c) 2015-2017 QLogic Corporation |
---|
3 | | - * |
---|
4 | | - * This software is available to you under a choice of one of two |
---|
5 | | - * licenses. You may choose to be licensed under the terms of the GNU |
---|
6 | | - * General Public License (GPL) Version 2, available from the file |
---|
7 | | - * COPYING in the main directory of this source tree, or the |
---|
8 | | - * OpenIB.org BSD license below: |
---|
9 | | - * |
---|
10 | | - * Redistribution and use in source and binary forms, with or |
---|
11 | | - * without modification, are permitted provided that the following |
---|
12 | | - * conditions are met: |
---|
13 | | - * |
---|
14 | | - * - Redistributions of source code must retain the above |
---|
15 | | - * copyright notice, this list of conditions and the following |
---|
16 | | - * disclaimer. |
---|
17 | | - * |
---|
18 | | - * - Redistributions in binary form must reproduce the above |
---|
19 | | - * copyright notice, this list of conditions and the following |
---|
20 | | - * disclaimer in the documentation and /or other materials |
---|
21 | | - * provided with the distribution. |
---|
22 | | - * |
---|
23 | | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
---|
24 | | - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
---|
25 | | - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
---|
26 | | - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
---|
27 | | - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
---|
28 | | - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
---|
29 | | - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
---|
30 | | - * SOFTWARE. |
---|
| 4 | + * Copyright (c) 2019-2020 Marvell International Ltd. |
---|
31 | 5 | */ |
---|
32 | 6 | |
---|
33 | 7 | #include <linux/types.h> |
---|
.. | .. |
---|
63 | 37 | #include "qed_sp.h" |
---|
64 | 38 | #include "qed_rdma.h" |
---|
65 | 39 | |
---|
66 | | -#define QED_LL2_RX_REGISTERED(ll2) ((ll2)->rx_queue.b_cb_registred) |
---|
67 | | -#define QED_LL2_TX_REGISTERED(ll2) ((ll2)->tx_queue.b_cb_registred) |
---|
| 40 | +#define QED_LL2_RX_REGISTERED(ll2) ((ll2)->rx_queue.b_cb_registered) |
---|
| 41 | +#define QED_LL2_TX_REGISTERED(ll2) ((ll2)->tx_queue.b_cb_registered) |
---|
68 | 42 | |
---|
69 | 43 | #define QED_LL2_TX_SIZE (256) |
---|
70 | 44 | #define QED_LL2_RX_SIZE (4096) |
---|
.. | .. |
---|
239 | 213 | buffer->phys_addr = new_phys_addr; |
---|
240 | 214 | |
---|
241 | 215 | out_post: |
---|
242 | | - rc = qed_ll2_post_rx_buffer(QED_LEADING_HWFN(cdev), cdev->ll2->handle, |
---|
243 | | - buffer->phys_addr, 0, buffer, 1); |
---|
244 | | - |
---|
| 216 | + rc = qed_ll2_post_rx_buffer(p_hwfn, cdev->ll2->handle, |
---|
| 217 | + buffer->phys_addr, 0, buffer, 1); |
---|
245 | 218 | if (rc) |
---|
246 | 219 | qed_ll2_dealloc_buffer(cdev, buffer); |
---|
247 | 220 | } |
---|
.. | .. |
---|
944 | 917 | return 0; |
---|
945 | 918 | } |
---|
946 | 919 | |
---|
947 | | -static void qed_ll2_stop_ooo(struct qed_dev *cdev) |
---|
| 920 | +static void qed_ll2_stop_ooo(struct qed_hwfn *p_hwfn) |
---|
948 | 921 | { |
---|
949 | | - struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); |
---|
950 | | - u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id; |
---|
| 922 | + u8 *handle = &p_hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id; |
---|
951 | 923 | |
---|
952 | | - DP_VERBOSE(cdev, QED_MSG_STORAGE, "Stopping LL2 OOO queue [%02x]\n", |
---|
953 | | - *handle); |
---|
| 924 | + DP_VERBOSE(p_hwfn, (QED_MSG_STORAGE | QED_MSG_LL2), |
---|
| 925 | + "Stopping LL2 OOO queue [%02x]\n", *handle); |
---|
954 | 926 | |
---|
955 | | - qed_ll2_terminate_connection(hwfn, *handle); |
---|
956 | | - qed_ll2_release_connection(hwfn, *handle); |
---|
| 927 | + qed_ll2_terminate_connection(p_hwfn, *handle); |
---|
| 928 | + qed_ll2_release_connection(p_hwfn, *handle); |
---|
957 | 929 | *handle = QED_LL2_UNUSED_HANDLE; |
---|
958 | 930 | } |
---|
959 | 931 | |
---|
.. | .. |
---|
982 | 954 | return rc; |
---|
983 | 955 | |
---|
984 | 956 | p_ramrod = &p_ent->ramrod.core_rx_queue_start; |
---|
985 | | - |
---|
| 957 | + memset(p_ramrod, 0, sizeof(*p_ramrod)); |
---|
986 | 958 | p_ramrod->sb_id = cpu_to_le16(qed_int_get_sp_sb_id(p_hwfn)); |
---|
987 | 959 | p_ramrod->sb_index = p_rx->rx_sb_index; |
---|
988 | 960 | p_ramrod->complete_event_flg = 1; |
---|
.. | .. |
---|
1016 | 988 | |
---|
1017 | 989 | p_ramrod->action_on_error.error_type = action_on_error; |
---|
1018 | 990 | p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable; |
---|
| 991 | + p_ramrod->zero_prod_flg = 1; |
---|
| 992 | + |
---|
1019 | 993 | return qed_spq_post(p_hwfn, p_ent, NULL); |
---|
1020 | 994 | } |
---|
1021 | 995 | |
---|
.. | .. |
---|
1103 | 1077 | |
---|
1104 | 1078 | p_ramrod->gsi_offload_flag = p_ll2_conn->input.gsi_enable; |
---|
1105 | 1079 | |
---|
1106 | | - return qed_spq_post(p_hwfn, p_ent, NULL); |
---|
| 1080 | + rc = qed_spq_post(p_hwfn, p_ent, NULL); |
---|
| 1081 | + if (rc) |
---|
| 1082 | + return rc; |
---|
| 1083 | + |
---|
| 1084 | + rc = qed_db_recovery_add(p_hwfn->cdev, p_tx->doorbell_addr, |
---|
| 1085 | + &p_tx->db_msg, DB_REC_WIDTH_32B, |
---|
| 1086 | + DB_REC_KERNEL); |
---|
| 1087 | + return rc; |
---|
1107 | 1088 | } |
---|
1108 | 1089 | |
---|
1109 | 1090 | static int qed_sp_ll2_rx_queue_stop(struct qed_hwfn *p_hwfn, |
---|
.. | .. |
---|
1137 | 1118 | static int qed_sp_ll2_tx_queue_stop(struct qed_hwfn *p_hwfn, |
---|
1138 | 1119 | struct qed_ll2_info *p_ll2_conn) |
---|
1139 | 1120 | { |
---|
| 1121 | + struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue; |
---|
1140 | 1122 | struct qed_spq_entry *p_ent = NULL; |
---|
1141 | 1123 | struct qed_sp_init_data init_data; |
---|
1142 | 1124 | int rc = -EINVAL; |
---|
| 1125 | + qed_db_recovery_del(p_hwfn->cdev, p_tx->doorbell_addr, &p_tx->db_msg); |
---|
1143 | 1126 | |
---|
1144 | 1127 | /* Get SPQ entry */ |
---|
1145 | 1128 | memset(&init_data, 0, sizeof(init_data)); |
---|
.. | .. |
---|
1160 | 1143 | qed_ll2_acquire_connection_rx(struct qed_hwfn *p_hwfn, |
---|
1161 | 1144 | struct qed_ll2_info *p_ll2_info) |
---|
1162 | 1145 | { |
---|
| 1146 | + struct qed_chain_init_params params = { |
---|
| 1147 | + .intended_use = QED_CHAIN_USE_TO_CONSUME_PRODUCE, |
---|
| 1148 | + .cnt_type = QED_CHAIN_CNT_TYPE_U16, |
---|
| 1149 | + .num_elems = p_ll2_info->input.rx_num_desc, |
---|
| 1150 | + }; |
---|
| 1151 | + struct qed_dev *cdev = p_hwfn->cdev; |
---|
1163 | 1152 | struct qed_ll2_rx_packet *p_descq; |
---|
1164 | 1153 | u32 capacity; |
---|
1165 | 1154 | int rc = 0; |
---|
.. | .. |
---|
1167 | 1156 | if (!p_ll2_info->input.rx_num_desc) |
---|
1168 | 1157 | goto out; |
---|
1169 | 1158 | |
---|
1170 | | - rc = qed_chain_alloc(p_hwfn->cdev, |
---|
1171 | | - QED_CHAIN_USE_TO_CONSUME_PRODUCE, |
---|
1172 | | - QED_CHAIN_MODE_NEXT_PTR, |
---|
1173 | | - QED_CHAIN_CNT_TYPE_U16, |
---|
1174 | | - p_ll2_info->input.rx_num_desc, |
---|
1175 | | - sizeof(struct core_rx_bd), |
---|
1176 | | - &p_ll2_info->rx_queue.rxq_chain, NULL); |
---|
| 1159 | + params.mode = QED_CHAIN_MODE_NEXT_PTR; |
---|
| 1160 | + params.elem_size = sizeof(struct core_rx_bd); |
---|
| 1161 | + |
---|
| 1162 | + rc = qed_chain_alloc(cdev, &p_ll2_info->rx_queue.rxq_chain, ¶ms); |
---|
1177 | 1163 | if (rc) { |
---|
1178 | 1164 | DP_NOTICE(p_hwfn, "Failed to allocate ll2 rxq chain\n"); |
---|
1179 | 1165 | goto out; |
---|
.. | .. |
---|
1189 | 1175 | } |
---|
1190 | 1176 | p_ll2_info->rx_queue.descq_array = p_descq; |
---|
1191 | 1177 | |
---|
1192 | | - rc = qed_chain_alloc(p_hwfn->cdev, |
---|
1193 | | - QED_CHAIN_USE_TO_CONSUME_PRODUCE, |
---|
1194 | | - QED_CHAIN_MODE_PBL, |
---|
1195 | | - QED_CHAIN_CNT_TYPE_U16, |
---|
1196 | | - p_ll2_info->input.rx_num_desc, |
---|
1197 | | - sizeof(struct core_rx_fast_path_cqe), |
---|
1198 | | - &p_ll2_info->rx_queue.rcq_chain, NULL); |
---|
| 1178 | + params.mode = QED_CHAIN_MODE_PBL; |
---|
| 1179 | + params.elem_size = sizeof(struct core_rx_fast_path_cqe); |
---|
| 1180 | + |
---|
| 1181 | + rc = qed_chain_alloc(cdev, &p_ll2_info->rx_queue.rcq_chain, ¶ms); |
---|
1199 | 1182 | if (rc) { |
---|
1200 | 1183 | DP_NOTICE(p_hwfn, "Failed to allocate ll2 rcq chain\n"); |
---|
1201 | 1184 | goto out; |
---|
.. | .. |
---|
1212 | 1195 | static int qed_ll2_acquire_connection_tx(struct qed_hwfn *p_hwfn, |
---|
1213 | 1196 | struct qed_ll2_info *p_ll2_info) |
---|
1214 | 1197 | { |
---|
| 1198 | + struct qed_chain_init_params params = { |
---|
| 1199 | + .mode = QED_CHAIN_MODE_PBL, |
---|
| 1200 | + .intended_use = QED_CHAIN_USE_TO_CONSUME_PRODUCE, |
---|
| 1201 | + .cnt_type = QED_CHAIN_CNT_TYPE_U16, |
---|
| 1202 | + .num_elems = p_ll2_info->input.tx_num_desc, |
---|
| 1203 | + .elem_size = sizeof(struct core_tx_bd), |
---|
| 1204 | + }; |
---|
1215 | 1205 | struct qed_ll2_tx_packet *p_descq; |
---|
1216 | | - u32 desc_size; |
---|
| 1206 | + size_t desc_size; |
---|
1217 | 1207 | u32 capacity; |
---|
1218 | 1208 | int rc = 0; |
---|
1219 | 1209 | |
---|
1220 | 1210 | if (!p_ll2_info->input.tx_num_desc) |
---|
1221 | 1211 | goto out; |
---|
1222 | 1212 | |
---|
1223 | | - rc = qed_chain_alloc(p_hwfn->cdev, |
---|
1224 | | - QED_CHAIN_USE_TO_CONSUME_PRODUCE, |
---|
1225 | | - QED_CHAIN_MODE_PBL, |
---|
1226 | | - QED_CHAIN_CNT_TYPE_U16, |
---|
1227 | | - p_ll2_info->input.tx_num_desc, |
---|
1228 | | - sizeof(struct core_tx_bd), |
---|
1229 | | - &p_ll2_info->tx_queue.txq_chain, NULL); |
---|
| 1213 | + rc = qed_chain_alloc(p_hwfn->cdev, &p_ll2_info->tx_queue.txq_chain, |
---|
| 1214 | + ¶ms); |
---|
1230 | 1215 | if (rc) |
---|
1231 | 1216 | goto out; |
---|
1232 | 1217 | |
---|
1233 | 1218 | capacity = qed_chain_get_capacity(&p_ll2_info->tx_queue.txq_chain); |
---|
1234 | | - /* First element is part of the packet, rest are flexibly added */ |
---|
1235 | | - desc_size = (sizeof(*p_descq) + |
---|
1236 | | - (p_ll2_info->input.tx_max_bds_per_packet - 1) * |
---|
1237 | | - sizeof(p_descq->bds_set)); |
---|
| 1219 | + /* All bds_set elements are flexibily added. */ |
---|
| 1220 | + desc_size = struct_size(p_descq, bds_set, |
---|
| 1221 | + p_ll2_info->input.tx_max_bds_per_packet); |
---|
1238 | 1222 | |
---|
1239 | 1223 | p_descq = kcalloc(capacity, desc_size, GFP_KERNEL); |
---|
1240 | 1224 | if (!p_descq) { |
---|
.. | .. |
---|
1328 | 1312 | return 0; |
---|
1329 | 1313 | } |
---|
1330 | 1314 | |
---|
| 1315 | +static void _qed_ll2_calc_allowed_conns(struct qed_hwfn *p_hwfn, |
---|
| 1316 | + struct qed_ll2_acquire_data *data, |
---|
| 1317 | + u8 *start_idx, u8 *last_idx) |
---|
| 1318 | +{ |
---|
| 1319 | + /* LL2 queues handles will be split as follows: |
---|
| 1320 | + * First will be the legacy queues, and then the ctx based. |
---|
| 1321 | + */ |
---|
| 1322 | + if (data->input.rx_conn_type == QED_LL2_RX_TYPE_LEGACY) { |
---|
| 1323 | + *start_idx = QED_LL2_LEGACY_CONN_BASE_PF; |
---|
| 1324 | + *last_idx = *start_idx + |
---|
| 1325 | + QED_MAX_NUM_OF_LEGACY_LL2_CONNS_PF; |
---|
| 1326 | + } else { |
---|
| 1327 | + /* QED_LL2_RX_TYPE_CTX */ |
---|
| 1328 | + *start_idx = QED_LL2_CTX_CONN_BASE_PF; |
---|
| 1329 | + *last_idx = *start_idx + |
---|
| 1330 | + QED_MAX_NUM_OF_CTX_LL2_CONNS_PF; |
---|
| 1331 | + } |
---|
| 1332 | +} |
---|
| 1333 | + |
---|
1331 | 1334 | static enum core_error_handle |
---|
1332 | 1335 | qed_ll2_get_error_choice(enum qed_ll2_error_handle err) |
---|
1333 | 1336 | { |
---|
.. | .. |
---|
1348 | 1351 | struct qed_hwfn *p_hwfn = cxt; |
---|
1349 | 1352 | qed_int_comp_cb_t comp_rx_cb, comp_tx_cb; |
---|
1350 | 1353 | struct qed_ll2_info *p_ll2_info = NULL; |
---|
1351 | | - u8 i, *p_tx_max; |
---|
| 1354 | + u8 i, first_idx, last_idx, *p_tx_max; |
---|
1352 | 1355 | int rc; |
---|
1353 | 1356 | |
---|
1354 | 1357 | if (!data->p_connection_handle || !p_hwfn->p_ll2_info) |
---|
1355 | 1358 | return -EINVAL; |
---|
1356 | 1359 | |
---|
| 1360 | + _qed_ll2_calc_allowed_conns(p_hwfn, data, &first_idx, &last_idx); |
---|
| 1361 | + |
---|
1357 | 1362 | /* Find a free connection to be used */ |
---|
1358 | | - for (i = 0; (i < QED_MAX_NUM_OF_LL2_CONNECTIONS); i++) { |
---|
| 1363 | + for (i = first_idx; i < last_idx; i++) { |
---|
1359 | 1364 | mutex_lock(&p_hwfn->p_ll2_info[i].mutex); |
---|
1360 | 1365 | if (p_hwfn->p_ll2_info[i].b_active) { |
---|
1361 | 1366 | mutex_unlock(&p_hwfn->p_ll2_info[i].mutex); |
---|
.. | .. |
---|
1433 | 1438 | &p_hwfn->p_ll2_info[i], |
---|
1434 | 1439 | &p_ll2_info->rx_queue.rx_sb_index, |
---|
1435 | 1440 | &p_ll2_info->rx_queue.p_fw_cons); |
---|
1436 | | - p_ll2_info->rx_queue.b_cb_registred = true; |
---|
| 1441 | + p_ll2_info->rx_queue.b_cb_registered = true; |
---|
1437 | 1442 | } |
---|
1438 | 1443 | |
---|
1439 | 1444 | if (data->input.tx_num_desc) { |
---|
.. | .. |
---|
1442 | 1447 | &p_hwfn->p_ll2_info[i], |
---|
1443 | 1448 | &p_ll2_info->tx_queue.tx_sb_index, |
---|
1444 | 1449 | &p_ll2_info->tx_queue.p_fw_cons); |
---|
1445 | | - p_ll2_info->tx_queue.b_cb_registred = true; |
---|
| 1450 | + p_ll2_info->tx_queue.b_cb_registered = true; |
---|
1446 | 1451 | } |
---|
1447 | 1452 | |
---|
1448 | 1453 | *data->p_connection_handle = i; |
---|
.. | .. |
---|
1459 | 1464 | enum qed_ll2_error_handle error_input; |
---|
1460 | 1465 | enum core_error_handle error_mode; |
---|
1461 | 1466 | u8 action_on_error = 0; |
---|
| 1467 | + int rc; |
---|
1462 | 1468 | |
---|
1463 | 1469 | if (!QED_LL2_RX_REGISTERED(p_ll2_conn)) |
---|
1464 | 1470 | return 0; |
---|
.. | .. |
---|
1472 | 1478 | error_mode = qed_ll2_get_error_choice(error_input); |
---|
1473 | 1479 | SET_FIELD(action_on_error, CORE_RX_ACTION_ON_ERROR_NO_BUFF, error_mode); |
---|
1474 | 1480 | |
---|
1475 | | - return qed_sp_ll2_rx_queue_start(p_hwfn, p_ll2_conn, action_on_error); |
---|
| 1481 | + rc = qed_sp_ll2_rx_queue_start(p_hwfn, p_ll2_conn, action_on_error); |
---|
| 1482 | + if (rc) |
---|
| 1483 | + return rc; |
---|
| 1484 | + |
---|
| 1485 | + if (p_ll2_conn->rx_queue.ctx_based) { |
---|
| 1486 | + rc = qed_db_recovery_add(p_hwfn->cdev, |
---|
| 1487 | + p_ll2_conn->rx_queue.set_prod_addr, |
---|
| 1488 | + &p_ll2_conn->rx_queue.db_data, |
---|
| 1489 | + DB_REC_WIDTH_64B, DB_REC_KERNEL); |
---|
| 1490 | + } |
---|
| 1491 | + |
---|
| 1492 | + return rc; |
---|
1476 | 1493 | } |
---|
1477 | 1494 | |
---|
1478 | 1495 | static void |
---|
.. | .. |
---|
1486 | 1503 | qed_ooo_submit_rx_buffers(p_hwfn, p_ll2_conn); |
---|
1487 | 1504 | } |
---|
1488 | 1505 | |
---|
| 1506 | +static inline u8 qed_ll2_handle_to_queue_id(struct qed_hwfn *p_hwfn, |
---|
| 1507 | + u8 handle, |
---|
| 1508 | + u8 ll2_queue_type) |
---|
| 1509 | +{ |
---|
| 1510 | + u8 qid; |
---|
| 1511 | + |
---|
| 1512 | + if (ll2_queue_type == QED_LL2_RX_TYPE_LEGACY) |
---|
| 1513 | + return p_hwfn->hw_info.resc_start[QED_LL2_RAM_QUEUE] + handle; |
---|
| 1514 | + |
---|
| 1515 | + /* QED_LL2_RX_TYPE_CTX |
---|
| 1516 | + * FW distinguishes between the legacy queues (ram based) and the |
---|
| 1517 | + * ctx based queues by the queue_id. |
---|
| 1518 | + * The first MAX_NUM_LL2_RX_RAM_QUEUES queues are legacy |
---|
| 1519 | + * and the queue ids above that are ctx base. |
---|
| 1520 | + */ |
---|
| 1521 | + qid = p_hwfn->hw_info.resc_start[QED_LL2_CTX_QUEUE] + |
---|
| 1522 | + MAX_NUM_LL2_RX_RAM_QUEUES; |
---|
| 1523 | + |
---|
| 1524 | + /* See comment on the acquire connection for how the ll2 |
---|
| 1525 | + * queues handles are divided. |
---|
| 1526 | + */ |
---|
| 1527 | + qid += (handle - QED_MAX_NUM_OF_LEGACY_LL2_CONNS_PF); |
---|
| 1528 | + |
---|
| 1529 | + return qid; |
---|
| 1530 | +} |
---|
| 1531 | + |
---|
1489 | 1532 | int qed_ll2_establish_connection(void *cxt, u8 connection_handle) |
---|
1490 | 1533 | { |
---|
1491 | | - struct qed_hwfn *p_hwfn = cxt; |
---|
1492 | | - struct qed_ll2_info *p_ll2_conn; |
---|
| 1534 | + struct e4_core_conn_context *p_cxt; |
---|
1493 | 1535 | struct qed_ll2_tx_packet *p_pkt; |
---|
| 1536 | + struct qed_ll2_info *p_ll2_conn; |
---|
| 1537 | + struct qed_hwfn *p_hwfn = cxt; |
---|
1494 | 1538 | struct qed_ll2_rx_queue *p_rx; |
---|
1495 | 1539 | struct qed_ll2_tx_queue *p_tx; |
---|
| 1540 | + struct qed_cxt_info cxt_info; |
---|
1496 | 1541 | struct qed_ptt *p_ptt; |
---|
1497 | 1542 | int rc = -EINVAL; |
---|
1498 | 1543 | u32 i, capacity; |
---|
1499 | | - u32 desc_size; |
---|
| 1544 | + size_t desc_size; |
---|
1500 | 1545 | u8 qid; |
---|
1501 | 1546 | |
---|
1502 | 1547 | p_ptt = qed_ptt_acquire(p_hwfn); |
---|
.. | .. |
---|
1530 | 1575 | INIT_LIST_HEAD(&p_tx->sending_descq); |
---|
1531 | 1576 | spin_lock_init(&p_tx->lock); |
---|
1532 | 1577 | capacity = qed_chain_get_capacity(&p_tx->txq_chain); |
---|
1533 | | - /* First element is part of the packet, rest are flexibly added */ |
---|
1534 | | - desc_size = (sizeof(*p_pkt) + |
---|
1535 | | - (p_ll2_conn->input.tx_max_bds_per_packet - 1) * |
---|
1536 | | - sizeof(p_pkt->bds_set)); |
---|
| 1578 | + /* All bds_set elements are flexibily added. */ |
---|
| 1579 | + desc_size = struct_size(p_pkt, bds_set, |
---|
| 1580 | + p_ll2_conn->input.tx_max_bds_per_packet); |
---|
1537 | 1581 | |
---|
1538 | 1582 | for (i = 0; i < capacity; i++) { |
---|
1539 | 1583 | p_pkt = p_tx->descq_mem + desc_size * i; |
---|
.. | .. |
---|
1550 | 1594 | rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_CORE, &p_ll2_conn->cid); |
---|
1551 | 1595 | if (rc) |
---|
1552 | 1596 | goto out; |
---|
| 1597 | + cxt_info.iid = p_ll2_conn->cid; |
---|
| 1598 | + rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info); |
---|
| 1599 | + if (rc) { |
---|
| 1600 | + DP_NOTICE(p_hwfn, "Cannot find context info for cid=%d\n", |
---|
| 1601 | + p_ll2_conn->cid); |
---|
| 1602 | + goto out; |
---|
| 1603 | + } |
---|
1553 | 1604 | |
---|
1554 | | - qid = p_hwfn->hw_info.resc_start[QED_LL2_QUEUE] + connection_handle; |
---|
| 1605 | + p_cxt = cxt_info.p_cxt; |
---|
| 1606 | + |
---|
| 1607 | + memset(p_cxt, 0, sizeof(*p_cxt)); |
---|
| 1608 | + |
---|
| 1609 | + qid = qed_ll2_handle_to_queue_id(p_hwfn, connection_handle, |
---|
| 1610 | + p_ll2_conn->input.rx_conn_type); |
---|
1555 | 1611 | p_ll2_conn->queue_id = qid; |
---|
1556 | 1612 | p_ll2_conn->tx_stats_id = qid; |
---|
1557 | | - p_rx->set_prod_addr = (u8 __iomem *)p_hwfn->regview + |
---|
1558 | | - GTT_BAR0_MAP_REG_TSDM_RAM + |
---|
1559 | | - TSTORM_LL2_RX_PRODS_OFFSET(qid); |
---|
| 1613 | + |
---|
| 1614 | + DP_VERBOSE(p_hwfn, QED_MSG_LL2, |
---|
| 1615 | + "Establishing ll2 queue. PF %d ctx_based=%d abs qid=%d\n", |
---|
| 1616 | + p_hwfn->rel_pf_id, p_ll2_conn->input.rx_conn_type, qid); |
---|
| 1617 | + |
---|
| 1618 | + if (p_ll2_conn->input.rx_conn_type == QED_LL2_RX_TYPE_LEGACY) { |
---|
| 1619 | + p_rx->set_prod_addr = p_hwfn->regview + |
---|
| 1620 | + GTT_BAR0_MAP_REG_TSDM_RAM + TSTORM_LL2_RX_PRODS_OFFSET(qid); |
---|
| 1621 | + } else { |
---|
| 1622 | + /* QED_LL2_RX_TYPE_CTX - using doorbell */ |
---|
| 1623 | + p_rx->ctx_based = 1; |
---|
| 1624 | + |
---|
| 1625 | + p_rx->set_prod_addr = p_hwfn->doorbells + |
---|
| 1626 | + p_hwfn->dpi_start_offset + |
---|
| 1627 | + DB_ADDR_SHIFT(DQ_PWM_OFFSET_TCM_LL2_PROD_UPDATE); |
---|
| 1628 | + |
---|
| 1629 | + /* prepare db data */ |
---|
| 1630 | + p_rx->db_data.icid = cpu_to_le16((u16)p_ll2_conn->cid); |
---|
| 1631 | + SET_FIELD(p_rx->db_data.params, |
---|
| 1632 | + CORE_PWM_PROD_UPDATE_DATA_AGG_CMD, DB_AGG_CMD_SET); |
---|
| 1633 | + SET_FIELD(p_rx->db_data.params, |
---|
| 1634 | + CORE_PWM_PROD_UPDATE_DATA_RESERVED1, 0); |
---|
| 1635 | + } |
---|
| 1636 | + |
---|
1560 | 1637 | p_tx->doorbell_addr = (u8 __iomem *)p_hwfn->doorbells + |
---|
1561 | 1638 | qed_db_addr(p_ll2_conn->cid, |
---|
1562 | 1639 | DQ_DEMS_LEGACY); |
---|
| 1640 | + /* prepare db data */ |
---|
| 1641 | + SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM); |
---|
| 1642 | + SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET); |
---|
| 1643 | + SET_FIELD(p_tx->db_msg.params, CORE_DB_DATA_AGG_VAL_SEL, |
---|
| 1644 | + DQ_XCM_CORE_TX_BD_PROD_CMD); |
---|
| 1645 | + p_tx->db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD; |
---|
1563 | 1646 | |
---|
1564 | 1647 | rc = qed_ll2_establish_connection_rx(p_hwfn, p_ll2_conn); |
---|
1565 | 1648 | if (rc) |
---|
.. | .. |
---|
1576 | 1659 | |
---|
1577 | 1660 | if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) { |
---|
1578 | 1661 | if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) |
---|
1579 | | - qed_llh_add_protocol_filter(p_hwfn, p_ptt, |
---|
1580 | | - ETH_P_FCOE, 0, |
---|
1581 | | - QED_LLH_FILTER_ETHERTYPE); |
---|
1582 | | - qed_llh_add_protocol_filter(p_hwfn, p_ptt, |
---|
1583 | | - ETH_P_FIP, 0, |
---|
1584 | | - QED_LLH_FILTER_ETHERTYPE); |
---|
| 1662 | + qed_llh_add_protocol_filter(p_hwfn->cdev, 0, |
---|
| 1663 | + QED_LLH_FILTER_ETHERTYPE, |
---|
| 1664 | + ETH_P_FCOE, 0); |
---|
| 1665 | + qed_llh_add_protocol_filter(p_hwfn->cdev, 0, |
---|
| 1666 | + QED_LLH_FILTER_ETHERTYPE, |
---|
| 1667 | + ETH_P_FIP, 0); |
---|
1585 | 1668 | } |
---|
1586 | 1669 | |
---|
1587 | 1670 | out: |
---|
.. | .. |
---|
1594 | 1677 | struct qed_ll2_rx_packet *p_curp) |
---|
1595 | 1678 | { |
---|
1596 | 1679 | struct qed_ll2_rx_packet *p_posting_packet = NULL; |
---|
1597 | | - struct core_ll2_rx_prod rx_prod = { 0, 0, 0 }; |
---|
| 1680 | + struct core_ll2_rx_prod rx_prod = { 0, 0 }; |
---|
1598 | 1681 | bool b_notify_fw = false; |
---|
1599 | 1682 | u16 bd_prod, cq_prod; |
---|
1600 | 1683 | |
---|
.. | .. |
---|
1619 | 1702 | |
---|
1620 | 1703 | bd_prod = qed_chain_get_prod_idx(&p_rx->rxq_chain); |
---|
1621 | 1704 | cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain); |
---|
1622 | | - rx_prod.bd_prod = cpu_to_le16(bd_prod); |
---|
1623 | | - rx_prod.cqe_prod = cpu_to_le16(cq_prod); |
---|
| 1705 | + if (p_rx->ctx_based) { |
---|
| 1706 | + /* update producer by giving a doorbell */ |
---|
| 1707 | + p_rx->db_data.prod.bd_prod = cpu_to_le16(bd_prod); |
---|
| 1708 | + p_rx->db_data.prod.cqe_prod = cpu_to_le16(cq_prod); |
---|
| 1709 | + /* Make sure chain element is updated before ringing the |
---|
| 1710 | + * doorbell |
---|
| 1711 | + */ |
---|
| 1712 | + dma_wmb(); |
---|
| 1713 | + DIRECT_REG_WR64(p_rx->set_prod_addr, |
---|
| 1714 | + *((u64 *)&p_rx->db_data)); |
---|
| 1715 | + } else { |
---|
| 1716 | + rx_prod.bd_prod = cpu_to_le16(bd_prod); |
---|
| 1717 | + rx_prod.cqe_prod = cpu_to_le16(cq_prod); |
---|
1624 | 1718 | |
---|
1625 | | - /* Make sure chain element is updated before ringing the doorbell */ |
---|
1626 | | - dma_wmb(); |
---|
| 1719 | + /* Make sure chain element is updated before ringing the |
---|
| 1720 | + * doorbell |
---|
| 1721 | + */ |
---|
| 1722 | + dma_wmb(); |
---|
1627 | 1723 | |
---|
1628 | | - DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod)); |
---|
| 1724 | + DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod)); |
---|
| 1725 | + } |
---|
1629 | 1726 | } |
---|
1630 | 1727 | |
---|
1631 | 1728 | int qed_ll2_post_rx_buffer(void *cxt, |
---|
.. | .. |
---|
1721 | 1818 | enum core_roce_flavor_type roce_flavor; |
---|
1722 | 1819 | enum core_tx_dest tx_dest; |
---|
1723 | 1820 | u16 bd_data = 0, frag_idx; |
---|
| 1821 | + u16 bitfield1; |
---|
1724 | 1822 | |
---|
1725 | 1823 | roce_flavor = (pkt->qed_roce_flavor == QED_LL2_ROCE) ? CORE_ROCE |
---|
1726 | 1824 | : CORE_RROCE; |
---|
.. | .. |
---|
1752 | 1850 | pkt->remove_stag = true; |
---|
1753 | 1851 | } |
---|
1754 | 1852 | |
---|
1755 | | - SET_FIELD(start_bd->bitfield1, CORE_TX_BD_L4_HDR_OFFSET_W, |
---|
1756 | | - cpu_to_le16(pkt->l4_hdr_offset_w)); |
---|
1757 | | - SET_FIELD(start_bd->bitfield1, CORE_TX_BD_TX_DST, tx_dest); |
---|
| 1853 | + bitfield1 = le16_to_cpu(start_bd->bitfield1); |
---|
| 1854 | + SET_FIELD(bitfield1, CORE_TX_BD_L4_HDR_OFFSET_W, pkt->l4_hdr_offset_w); |
---|
| 1855 | + SET_FIELD(bitfield1, CORE_TX_BD_TX_DST, tx_dest); |
---|
| 1856 | + start_bd->bitfield1 = cpu_to_le16(bitfield1); |
---|
| 1857 | + |
---|
1758 | 1858 | bd_data |= pkt->bd_flags; |
---|
1759 | 1859 | SET_FIELD(bd_data, CORE_TX_BD_DATA_START_BD, 0x1); |
---|
1760 | 1860 | SET_FIELD(bd_data, CORE_TX_BD_DATA_NBDS, pkt->num_of_bds); |
---|
.. | .. |
---|
1804 | 1904 | bool b_notify = p_ll2_conn->tx_queue.cur_send_packet->notify_fw; |
---|
1805 | 1905 | struct qed_ll2_tx_queue *p_tx = &p_ll2_conn->tx_queue; |
---|
1806 | 1906 | struct qed_ll2_tx_packet *p_pkt = NULL; |
---|
1807 | | - struct core_db_data db_msg = { 0, 0, 0 }; |
---|
1808 | 1907 | u16 bd_prod; |
---|
1809 | 1908 | |
---|
1810 | 1909 | /* If there are missing BDs, don't do anything now */ |
---|
.. | .. |
---|
1833 | 1932 | list_move_tail(&p_pkt->list_entry, &p_tx->active_descq); |
---|
1834 | 1933 | } |
---|
1835 | 1934 | |
---|
1836 | | - SET_FIELD(db_msg.params, CORE_DB_DATA_DEST, DB_DEST_XCM); |
---|
1837 | | - SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_CMD, DB_AGG_CMD_SET); |
---|
1838 | | - SET_FIELD(db_msg.params, CORE_DB_DATA_AGG_VAL_SEL, |
---|
1839 | | - DQ_XCM_CORE_TX_BD_PROD_CMD); |
---|
1840 | | - db_msg.agg_flags = DQ_XCM_CORE_DQ_CF_CMD; |
---|
1841 | | - db_msg.spq_prod = cpu_to_le16(bd_prod); |
---|
| 1935 | + p_tx->db_msg.spq_prod = cpu_to_le16(bd_prod); |
---|
1842 | 1936 | |
---|
1843 | 1937 | /* Make sure the BDs data is updated before ringing the doorbell */ |
---|
1844 | 1938 | wmb(); |
---|
1845 | 1939 | |
---|
1846 | | - DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)&db_msg)); |
---|
| 1940 | + DIRECT_REG_WR(p_tx->doorbell_addr, *((u32 *)&p_tx->db_msg)); |
---|
1847 | 1941 | |
---|
1848 | 1942 | DP_VERBOSE(p_hwfn, |
---|
1849 | 1943 | (NETIF_MSG_TX_QUEUED | QED_MSG_LL2), |
---|
1850 | 1944 | "LL2 [q 0x%02x cid 0x%08x type 0x%08x] Doorbelled [producer 0x%04x]\n", |
---|
1851 | 1945 | p_ll2_conn->queue_id, |
---|
1852 | 1946 | p_ll2_conn->cid, |
---|
1853 | | - p_ll2_conn->input.conn_type, db_msg.spq_prod); |
---|
| 1947 | + p_ll2_conn->input.conn_type, p_tx->db_msg.spq_prod); |
---|
1854 | 1948 | } |
---|
1855 | 1949 | |
---|
1856 | 1950 | int qed_ll2_prepare_tx_packet(void *cxt, |
---|
.. | .. |
---|
1964 | 2058 | |
---|
1965 | 2059 | /* Stop Tx & Rx of connection, if needed */ |
---|
1966 | 2060 | if (QED_LL2_TX_REGISTERED(p_ll2_conn)) { |
---|
1967 | | - p_ll2_conn->tx_queue.b_cb_registred = false; |
---|
| 2061 | + p_ll2_conn->tx_queue.b_cb_registered = false; |
---|
1968 | 2062 | smp_wmb(); /* Make sure this is seen by ll2_lb_rxq_completion */ |
---|
1969 | 2063 | rc = qed_sp_ll2_tx_queue_stop(p_hwfn, p_ll2_conn); |
---|
1970 | 2064 | if (rc) |
---|
.. | .. |
---|
1975 | 2069 | } |
---|
1976 | 2070 | |
---|
1977 | 2071 | if (QED_LL2_RX_REGISTERED(p_ll2_conn)) { |
---|
1978 | | - p_ll2_conn->rx_queue.b_cb_registred = false; |
---|
| 2072 | + p_ll2_conn->rx_queue.b_cb_registered = false; |
---|
1979 | 2073 | smp_wmb(); /* Make sure this is seen by ll2_lb_rxq_completion */ |
---|
| 2074 | + |
---|
| 2075 | + if (p_ll2_conn->rx_queue.ctx_based) |
---|
| 2076 | + qed_db_recovery_del(p_hwfn->cdev, |
---|
| 2077 | + p_ll2_conn->rx_queue.set_prod_addr, |
---|
| 2078 | + &p_ll2_conn->rx_queue.db_data); |
---|
| 2079 | + |
---|
1980 | 2080 | rc = qed_sp_ll2_rx_queue_stop(p_hwfn, p_ll2_conn); |
---|
1981 | 2081 | if (rc) |
---|
1982 | 2082 | goto out; |
---|
.. | .. |
---|
1990 | 2090 | |
---|
1991 | 2091 | if (p_ll2_conn->input.conn_type == QED_LL2_TYPE_FCOE) { |
---|
1992 | 2092 | if (!test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits)) |
---|
1993 | | - qed_llh_remove_protocol_filter(p_hwfn, p_ptt, |
---|
1994 | | - ETH_P_FCOE, 0, |
---|
1995 | | - QED_LLH_FILTER_ETHERTYPE); |
---|
1996 | | - qed_llh_remove_protocol_filter(p_hwfn, p_ptt, |
---|
1997 | | - ETH_P_FIP, 0, |
---|
1998 | | - QED_LLH_FILTER_ETHERTYPE); |
---|
| 2093 | + qed_llh_remove_protocol_filter(p_hwfn->cdev, 0, |
---|
| 2094 | + QED_LLH_FILTER_ETHERTYPE, |
---|
| 2095 | + ETH_P_FCOE, 0); |
---|
| 2096 | + qed_llh_remove_protocol_filter(p_hwfn->cdev, 0, |
---|
| 2097 | + QED_LLH_FILTER_ETHERTYPE, |
---|
| 2098 | + ETH_P_FIP, 0); |
---|
1999 | 2099 | } |
---|
2000 | 2100 | |
---|
2001 | 2101 | out: |
---|
.. | .. |
---|
2096 | 2196 | TSTORM_LL2_PORT_STAT_OFFSET(MFW_PORT(p_hwfn)), |
---|
2097 | 2197 | sizeof(port_stats)); |
---|
2098 | 2198 | |
---|
2099 | | - p_stats->gsi_invalid_hdr = HILO_64_REGPAIR(port_stats.gsi_invalid_hdr); |
---|
2100 | | - p_stats->gsi_invalid_pkt_length = |
---|
| 2199 | + p_stats->gsi_invalid_hdr += HILO_64_REGPAIR(port_stats.gsi_invalid_hdr); |
---|
| 2200 | + p_stats->gsi_invalid_pkt_length += |
---|
2101 | 2201 | HILO_64_REGPAIR(port_stats.gsi_invalid_pkt_length); |
---|
2102 | | - p_stats->gsi_unsupported_pkt_typ = |
---|
| 2202 | + p_stats->gsi_unsupported_pkt_typ += |
---|
2103 | 2203 | HILO_64_REGPAIR(port_stats.gsi_unsupported_pkt_typ); |
---|
2104 | | - p_stats->gsi_crcchksm_error = |
---|
| 2204 | + p_stats->gsi_crcchksm_error += |
---|
2105 | 2205 | HILO_64_REGPAIR(port_stats.gsi_crcchksm_error); |
---|
2106 | 2206 | } |
---|
2107 | 2207 | |
---|
.. | .. |
---|
2119 | 2219 | CORE_LL2_TSTORM_PER_QUEUE_STAT_OFFSET(qid); |
---|
2120 | 2220 | qed_memcpy_from(p_hwfn, p_ptt, &tstats, tstats_addr, sizeof(tstats)); |
---|
2121 | 2221 | |
---|
2122 | | - p_stats->packet_too_big_discard = |
---|
| 2222 | + p_stats->packet_too_big_discard += |
---|
2123 | 2223 | HILO_64_REGPAIR(tstats.packet_too_big_discard); |
---|
2124 | | - p_stats->no_buff_discard = HILO_64_REGPAIR(tstats.no_buff_discard); |
---|
| 2224 | + p_stats->no_buff_discard += HILO_64_REGPAIR(tstats.no_buff_discard); |
---|
2125 | 2225 | } |
---|
2126 | 2226 | |
---|
2127 | 2227 | static void _qed_ll2_get_ustats(struct qed_hwfn *p_hwfn, |
---|
.. | .. |
---|
2138 | 2238 | CORE_LL2_USTORM_PER_QUEUE_STAT_OFFSET(qid); |
---|
2139 | 2239 | qed_memcpy_from(p_hwfn, p_ptt, &ustats, ustats_addr, sizeof(ustats)); |
---|
2140 | 2240 | |
---|
2141 | | - p_stats->rcv_ucast_bytes = HILO_64_REGPAIR(ustats.rcv_ucast_bytes); |
---|
2142 | | - p_stats->rcv_mcast_bytes = HILO_64_REGPAIR(ustats.rcv_mcast_bytes); |
---|
2143 | | - p_stats->rcv_bcast_bytes = HILO_64_REGPAIR(ustats.rcv_bcast_bytes); |
---|
2144 | | - p_stats->rcv_ucast_pkts = HILO_64_REGPAIR(ustats.rcv_ucast_pkts); |
---|
2145 | | - p_stats->rcv_mcast_pkts = HILO_64_REGPAIR(ustats.rcv_mcast_pkts); |
---|
2146 | | - p_stats->rcv_bcast_pkts = HILO_64_REGPAIR(ustats.rcv_bcast_pkts); |
---|
| 2241 | + p_stats->rcv_ucast_bytes += HILO_64_REGPAIR(ustats.rcv_ucast_bytes); |
---|
| 2242 | + p_stats->rcv_mcast_bytes += HILO_64_REGPAIR(ustats.rcv_mcast_bytes); |
---|
| 2243 | + p_stats->rcv_bcast_bytes += HILO_64_REGPAIR(ustats.rcv_bcast_bytes); |
---|
| 2244 | + p_stats->rcv_ucast_pkts += HILO_64_REGPAIR(ustats.rcv_ucast_pkts); |
---|
| 2245 | + p_stats->rcv_mcast_pkts += HILO_64_REGPAIR(ustats.rcv_mcast_pkts); |
---|
| 2246 | + p_stats->rcv_bcast_pkts += HILO_64_REGPAIR(ustats.rcv_bcast_pkts); |
---|
2147 | 2247 | } |
---|
2148 | 2248 | |
---|
2149 | 2249 | static void _qed_ll2_get_pstats(struct qed_hwfn *p_hwfn, |
---|
.. | .. |
---|
2160 | 2260 | CORE_LL2_PSTORM_PER_QUEUE_STAT_OFFSET(stats_id); |
---|
2161 | 2261 | qed_memcpy_from(p_hwfn, p_ptt, &pstats, pstats_addr, sizeof(pstats)); |
---|
2162 | 2262 | |
---|
2163 | | - p_stats->sent_ucast_bytes = HILO_64_REGPAIR(pstats.sent_ucast_bytes); |
---|
2164 | | - p_stats->sent_mcast_bytes = HILO_64_REGPAIR(pstats.sent_mcast_bytes); |
---|
2165 | | - p_stats->sent_bcast_bytes = HILO_64_REGPAIR(pstats.sent_bcast_bytes); |
---|
2166 | | - p_stats->sent_ucast_pkts = HILO_64_REGPAIR(pstats.sent_ucast_pkts); |
---|
2167 | | - p_stats->sent_mcast_pkts = HILO_64_REGPAIR(pstats.sent_mcast_pkts); |
---|
2168 | | - p_stats->sent_bcast_pkts = HILO_64_REGPAIR(pstats.sent_bcast_pkts); |
---|
| 2263 | + p_stats->sent_ucast_bytes += HILO_64_REGPAIR(pstats.sent_ucast_bytes); |
---|
| 2264 | + p_stats->sent_mcast_bytes += HILO_64_REGPAIR(pstats.sent_mcast_bytes); |
---|
| 2265 | + p_stats->sent_bcast_bytes += HILO_64_REGPAIR(pstats.sent_bcast_bytes); |
---|
| 2266 | + p_stats->sent_ucast_pkts += HILO_64_REGPAIR(pstats.sent_ucast_pkts); |
---|
| 2267 | + p_stats->sent_mcast_pkts += HILO_64_REGPAIR(pstats.sent_mcast_pkts); |
---|
| 2268 | + p_stats->sent_bcast_pkts += HILO_64_REGPAIR(pstats.sent_bcast_pkts); |
---|
2169 | 2269 | } |
---|
2170 | 2270 | |
---|
2171 | | -int qed_ll2_get_stats(void *cxt, |
---|
2172 | | - u8 connection_handle, struct qed_ll2_stats *p_stats) |
---|
| 2271 | +static int __qed_ll2_get_stats(void *cxt, u8 connection_handle, |
---|
| 2272 | + struct qed_ll2_stats *p_stats) |
---|
2173 | 2273 | { |
---|
2174 | 2274 | struct qed_hwfn *p_hwfn = cxt; |
---|
2175 | 2275 | struct qed_ll2_info *p_ll2_conn = NULL; |
---|
2176 | 2276 | struct qed_ptt *p_ptt; |
---|
2177 | | - |
---|
2178 | | - memset(p_stats, 0, sizeof(*p_stats)); |
---|
2179 | 2277 | |
---|
2180 | 2278 | if ((connection_handle >= QED_MAX_NUM_OF_LL2_CONNECTIONS) || |
---|
2181 | 2279 | !p_hwfn->p_ll2_info) |
---|
.. | .. |
---|
2191 | 2289 | |
---|
2192 | 2290 | if (p_ll2_conn->input.gsi_enable) |
---|
2193 | 2291 | _qed_ll2_get_port_stats(p_hwfn, p_ptt, p_stats); |
---|
| 2292 | + |
---|
2194 | 2293 | _qed_ll2_get_tstats(p_hwfn, p_ptt, p_ll2_conn, p_stats); |
---|
| 2294 | + |
---|
2195 | 2295 | _qed_ll2_get_ustats(p_hwfn, p_ptt, p_ll2_conn, p_stats); |
---|
| 2296 | + |
---|
2196 | 2297 | if (p_ll2_conn->tx_stats_en) |
---|
2197 | 2298 | _qed_ll2_get_pstats(p_hwfn, p_ptt, p_ll2_conn, p_stats); |
---|
2198 | 2299 | |
---|
2199 | 2300 | qed_ptt_release(p_hwfn, p_ptt); |
---|
| 2301 | + |
---|
2200 | 2302 | return 0; |
---|
| 2303 | +} |
---|
| 2304 | + |
---|
| 2305 | +int qed_ll2_get_stats(void *cxt, |
---|
| 2306 | + u8 connection_handle, struct qed_ll2_stats *p_stats) |
---|
| 2307 | +{ |
---|
| 2308 | + memset(p_stats, 0, sizeof(*p_stats)); |
---|
| 2309 | + return __qed_ll2_get_stats(cxt, connection_handle, p_stats); |
---|
2201 | 2310 | } |
---|
2202 | 2311 | |
---|
2203 | 2312 | static void qed_ll2b_release_rx_packet(void *cxt, |
---|
.. | .. |
---|
2219 | 2328 | cdev->ll2->cb_cookie = cookie; |
---|
2220 | 2329 | } |
---|
2221 | 2330 | |
---|
2222 | | -struct qed_ll2_cbs ll2_cbs = { |
---|
| 2331 | +static struct qed_ll2_cbs ll2_cbs = { |
---|
2223 | 2332 | .rx_comp_cb = &qed_ll2b_complete_rx_packet, |
---|
2224 | 2333 | .rx_release_cb = &qed_ll2b_release_rx_packet, |
---|
2225 | 2334 | .tx_comp_cb = &qed_ll2b_complete_tx_packet, |
---|
2226 | 2335 | .tx_release_cb = &qed_ll2b_complete_tx_packet, |
---|
2227 | 2336 | }; |
---|
2228 | 2337 | |
---|
2229 | | -static void qed_ll2_set_conn_data(struct qed_dev *cdev, |
---|
| 2338 | +static void qed_ll2_set_conn_data(struct qed_hwfn *p_hwfn, |
---|
2230 | 2339 | struct qed_ll2_acquire_data *data, |
---|
2231 | 2340 | struct qed_ll2_params *params, |
---|
2232 | 2341 | enum qed_ll2_conn_type conn_type, |
---|
.. | .. |
---|
2242 | 2351 | data->input.tx_num_desc = QED_LL2_TX_SIZE; |
---|
2243 | 2352 | data->p_connection_handle = handle; |
---|
2244 | 2353 | data->cbs = &ll2_cbs; |
---|
2245 | | - ll2_cbs.cookie = QED_LEADING_HWFN(cdev); |
---|
| 2354 | + ll2_cbs.cookie = p_hwfn; |
---|
2246 | 2355 | |
---|
2247 | 2356 | if (lb) { |
---|
2248 | 2357 | data->input.tx_tc = PKT_LB_TC; |
---|
.. | .. |
---|
2253 | 2362 | } |
---|
2254 | 2363 | } |
---|
2255 | 2364 | |
---|
2256 | | -static int qed_ll2_start_ooo(struct qed_dev *cdev, |
---|
| 2365 | +static int qed_ll2_start_ooo(struct qed_hwfn *p_hwfn, |
---|
2257 | 2366 | struct qed_ll2_params *params) |
---|
2258 | 2367 | { |
---|
2259 | | - struct qed_hwfn *hwfn = QED_LEADING_HWFN(cdev); |
---|
2260 | | - u8 *handle = &hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id; |
---|
| 2368 | + u8 *handle = &p_hwfn->pf_params.iscsi_pf_params.ll2_ooo_queue_id; |
---|
2261 | 2369 | struct qed_ll2_acquire_data data; |
---|
2262 | 2370 | int rc; |
---|
2263 | 2371 | |
---|
2264 | | - qed_ll2_set_conn_data(cdev, &data, params, |
---|
| 2372 | + qed_ll2_set_conn_data(p_hwfn, &data, params, |
---|
2265 | 2373 | QED_LL2_TYPE_OOO, handle, true); |
---|
2266 | 2374 | |
---|
2267 | | - rc = qed_ll2_acquire_connection(hwfn, &data); |
---|
| 2375 | + rc = qed_ll2_acquire_connection(p_hwfn, &data); |
---|
2268 | 2376 | if (rc) { |
---|
2269 | | - DP_INFO(cdev, "Failed to acquire LL2 OOO connection\n"); |
---|
| 2377 | + DP_INFO(p_hwfn, "Failed to acquire LL2 OOO connection\n"); |
---|
2270 | 2378 | goto out; |
---|
2271 | 2379 | } |
---|
2272 | 2380 | |
---|
2273 | | - rc = qed_ll2_establish_connection(hwfn, *handle); |
---|
| 2381 | + rc = qed_ll2_establish_connection(p_hwfn, *handle); |
---|
2274 | 2382 | if (rc) { |
---|
2275 | | - DP_INFO(cdev, "Failed to establist LL2 OOO connection\n"); |
---|
| 2383 | + DP_INFO(p_hwfn, "Failed to establish LL2 OOO connection\n"); |
---|
2276 | 2384 | goto fail; |
---|
2277 | 2385 | } |
---|
2278 | 2386 | |
---|
2279 | 2387 | return 0; |
---|
2280 | 2388 | |
---|
2281 | 2389 | fail: |
---|
2282 | | - qed_ll2_release_connection(hwfn, *handle); |
---|
| 2390 | + qed_ll2_release_connection(p_hwfn, *handle); |
---|
2283 | 2391 | out: |
---|
2284 | 2392 | *handle = QED_LL2_UNUSED_HANDLE; |
---|
2285 | 2393 | return rc; |
---|
2286 | 2394 | } |
---|
2287 | 2395 | |
---|
2288 | | -static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params) |
---|
| 2396 | +static bool qed_ll2_is_storage_eng1(struct qed_dev *cdev) |
---|
2289 | 2397 | { |
---|
2290 | | - struct qed_ll2_buffer *buffer, *tmp_buffer; |
---|
2291 | | - enum qed_ll2_conn_type conn_type; |
---|
2292 | | - struct qed_ll2_acquire_data data; |
---|
2293 | | - struct qed_ptt *p_ptt; |
---|
2294 | | - int rc, i; |
---|
| 2398 | + return (QED_IS_FCOE_PERSONALITY(QED_LEADING_HWFN(cdev)) || |
---|
| 2399 | + QED_IS_ISCSI_PERSONALITY(QED_LEADING_HWFN(cdev))) && |
---|
| 2400 | + (QED_AFFIN_HWFN(cdev) != QED_LEADING_HWFN(cdev)); |
---|
| 2401 | +} |
---|
2295 | 2402 | |
---|
| 2403 | +static int __qed_ll2_stop(struct qed_hwfn *p_hwfn) |
---|
| 2404 | +{ |
---|
| 2405 | + struct qed_dev *cdev = p_hwfn->cdev; |
---|
| 2406 | + int rc; |
---|
2296 | 2407 | |
---|
2297 | | - /* Initialize LL2 locks & lists */ |
---|
2298 | | - INIT_LIST_HEAD(&cdev->ll2->list); |
---|
2299 | | - spin_lock_init(&cdev->ll2->lock); |
---|
2300 | | - cdev->ll2->rx_size = NET_SKB_PAD + ETH_HLEN + |
---|
2301 | | - L1_CACHE_BYTES + params->mtu; |
---|
| 2408 | + rc = qed_ll2_terminate_connection(p_hwfn, cdev->ll2->handle); |
---|
| 2409 | + if (rc) |
---|
| 2410 | + DP_INFO(cdev, "Failed to terminate LL2 connection\n"); |
---|
2302 | 2411 | |
---|
2303 | | - /*Allocate memory for LL2 */ |
---|
2304 | | - DP_INFO(cdev, "Allocating LL2 buffers of size %08x bytes\n", |
---|
2305 | | - cdev->ll2->rx_size); |
---|
2306 | | - for (i = 0; i < QED_LL2_RX_SIZE; i++) { |
---|
2307 | | - buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
---|
2308 | | - if (!buffer) { |
---|
2309 | | - DP_INFO(cdev, "Failed to allocate LL2 buffers\n"); |
---|
2310 | | - goto fail; |
---|
2311 | | - } |
---|
| 2412 | + qed_ll2_release_connection(p_hwfn, cdev->ll2->handle); |
---|
2312 | 2413 | |
---|
2313 | | - rc = qed_ll2_alloc_buffer(cdev, (u8 **)&buffer->data, |
---|
2314 | | - &buffer->phys_addr); |
---|
2315 | | - if (rc) { |
---|
2316 | | - kfree(buffer); |
---|
2317 | | - goto fail; |
---|
2318 | | - } |
---|
| 2414 | + return rc; |
---|
| 2415 | +} |
---|
2319 | 2416 | |
---|
2320 | | - list_add_tail(&buffer->list, &cdev->ll2->list); |
---|
| 2417 | +static int qed_ll2_stop(struct qed_dev *cdev) |
---|
| 2418 | +{ |
---|
| 2419 | + bool b_is_storage_eng1 = qed_ll2_is_storage_eng1(cdev); |
---|
| 2420 | + struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev); |
---|
| 2421 | + int rc = 0, rc2 = 0; |
---|
| 2422 | + |
---|
| 2423 | + if (cdev->ll2->handle == QED_LL2_UNUSED_HANDLE) |
---|
| 2424 | + return 0; |
---|
| 2425 | + |
---|
| 2426 | + qed_llh_remove_mac_filter(cdev, 0, cdev->ll2_mac_address); |
---|
| 2427 | + eth_zero_addr(cdev->ll2_mac_address); |
---|
| 2428 | + |
---|
| 2429 | + if (QED_IS_ISCSI_PERSONALITY(p_hwfn)) |
---|
| 2430 | + qed_ll2_stop_ooo(p_hwfn); |
---|
| 2431 | + |
---|
| 2432 | + /* In CMT mode, LL2 is always started on engine 0 for a storage PF */ |
---|
| 2433 | + if (b_is_storage_eng1) { |
---|
| 2434 | + rc2 = __qed_ll2_stop(QED_LEADING_HWFN(cdev)); |
---|
| 2435 | + if (rc2) |
---|
| 2436 | + DP_NOTICE(QED_LEADING_HWFN(cdev), |
---|
| 2437 | + "Failed to stop LL2 on engine 0\n"); |
---|
2321 | 2438 | } |
---|
2322 | 2439 | |
---|
2323 | | - switch (QED_LEADING_HWFN(cdev)->hw_info.personality) { |
---|
| 2440 | + rc = __qed_ll2_stop(p_hwfn); |
---|
| 2441 | + if (rc) |
---|
| 2442 | + DP_NOTICE(p_hwfn, "Failed to stop LL2\n"); |
---|
| 2443 | + |
---|
| 2444 | + qed_ll2_kill_buffers(cdev); |
---|
| 2445 | + |
---|
| 2446 | + cdev->ll2->handle = QED_LL2_UNUSED_HANDLE; |
---|
| 2447 | + |
---|
| 2448 | + return rc | rc2; |
---|
| 2449 | +} |
---|
| 2450 | + |
---|
| 2451 | +static int __qed_ll2_start(struct qed_hwfn *p_hwfn, |
---|
| 2452 | + struct qed_ll2_params *params) |
---|
| 2453 | +{ |
---|
| 2454 | + struct qed_ll2_buffer *buffer, *tmp_buffer; |
---|
| 2455 | + struct qed_dev *cdev = p_hwfn->cdev; |
---|
| 2456 | + enum qed_ll2_conn_type conn_type; |
---|
| 2457 | + struct qed_ll2_acquire_data data; |
---|
| 2458 | + int rc, rx_cnt; |
---|
| 2459 | + |
---|
| 2460 | + switch (p_hwfn->hw_info.personality) { |
---|
2324 | 2461 | case QED_PCI_FCOE: |
---|
2325 | 2462 | conn_type = QED_LL2_TYPE_FCOE; |
---|
2326 | 2463 | break; |
---|
.. | .. |
---|
2331 | 2468 | conn_type = QED_LL2_TYPE_ROCE; |
---|
2332 | 2469 | break; |
---|
2333 | 2470 | default: |
---|
| 2471 | + |
---|
2334 | 2472 | conn_type = QED_LL2_TYPE_TEST; |
---|
2335 | 2473 | } |
---|
2336 | 2474 | |
---|
2337 | | - qed_ll2_set_conn_data(cdev, &data, params, conn_type, |
---|
| 2475 | + qed_ll2_set_conn_data(p_hwfn, &data, params, conn_type, |
---|
2338 | 2476 | &cdev->ll2->handle, false); |
---|
2339 | 2477 | |
---|
2340 | | - rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &data); |
---|
| 2478 | + rc = qed_ll2_acquire_connection(p_hwfn, &data); |
---|
2341 | 2479 | if (rc) { |
---|
2342 | | - DP_INFO(cdev, "Failed to acquire LL2 connection\n"); |
---|
2343 | | - goto fail; |
---|
| 2480 | + DP_INFO(p_hwfn, "Failed to acquire LL2 connection\n"); |
---|
| 2481 | + return rc; |
---|
2344 | 2482 | } |
---|
2345 | 2483 | |
---|
2346 | | - rc = qed_ll2_establish_connection(QED_LEADING_HWFN(cdev), |
---|
2347 | | - cdev->ll2->handle); |
---|
| 2484 | + rc = qed_ll2_establish_connection(p_hwfn, cdev->ll2->handle); |
---|
2348 | 2485 | if (rc) { |
---|
2349 | | - DP_INFO(cdev, "Failed to establish LL2 connection\n"); |
---|
2350 | | - goto release_fail; |
---|
| 2486 | + DP_INFO(p_hwfn, "Failed to establish LL2 connection\n"); |
---|
| 2487 | + goto release_conn; |
---|
2351 | 2488 | } |
---|
2352 | 2489 | |
---|
2353 | 2490 | /* Post all Rx buffers to FW */ |
---|
2354 | 2491 | spin_lock_bh(&cdev->ll2->lock); |
---|
| 2492 | + rx_cnt = cdev->ll2->rx_cnt; |
---|
2355 | 2493 | list_for_each_entry_safe(buffer, tmp_buffer, &cdev->ll2->list, list) { |
---|
2356 | | - rc = qed_ll2_post_rx_buffer(QED_LEADING_HWFN(cdev), |
---|
| 2494 | + rc = qed_ll2_post_rx_buffer(p_hwfn, |
---|
2357 | 2495 | cdev->ll2->handle, |
---|
2358 | 2496 | buffer->phys_addr, 0, buffer, 1); |
---|
2359 | 2497 | if (rc) { |
---|
2360 | | - DP_INFO(cdev, |
---|
| 2498 | + DP_INFO(p_hwfn, |
---|
2361 | 2499 | "Failed to post an Rx buffer; Deleting it\n"); |
---|
2362 | 2500 | dma_unmap_single(&cdev->pdev->dev, buffer->phys_addr, |
---|
2363 | 2501 | cdev->ll2->rx_size, DMA_FROM_DEVICE); |
---|
.. | .. |
---|
2365 | 2503 | list_del(&buffer->list); |
---|
2366 | 2504 | kfree(buffer); |
---|
2367 | 2505 | } else { |
---|
2368 | | - cdev->ll2->rx_cnt++; |
---|
| 2506 | + rx_cnt++; |
---|
2369 | 2507 | } |
---|
2370 | 2508 | } |
---|
2371 | 2509 | spin_unlock_bh(&cdev->ll2->lock); |
---|
2372 | 2510 | |
---|
2373 | | - if (!cdev->ll2->rx_cnt) { |
---|
2374 | | - DP_INFO(cdev, "Failed passing even a single Rx buffer\n"); |
---|
2375 | | - goto release_terminate; |
---|
| 2511 | + if (rx_cnt == cdev->ll2->rx_cnt) { |
---|
| 2512 | + DP_NOTICE(p_hwfn, "Failed passing even a single Rx buffer\n"); |
---|
| 2513 | + goto terminate_conn; |
---|
2376 | 2514 | } |
---|
| 2515 | + cdev->ll2->rx_cnt = rx_cnt; |
---|
| 2516 | + |
---|
| 2517 | + return 0; |
---|
| 2518 | + |
---|
| 2519 | +terminate_conn: |
---|
| 2520 | + qed_ll2_terminate_connection(p_hwfn, cdev->ll2->handle); |
---|
| 2521 | +release_conn: |
---|
| 2522 | + qed_ll2_release_connection(p_hwfn, cdev->ll2->handle); |
---|
| 2523 | + return rc; |
---|
| 2524 | +} |
---|
| 2525 | + |
---|
| 2526 | +static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params) |
---|
| 2527 | +{ |
---|
| 2528 | + bool b_is_storage_eng1 = qed_ll2_is_storage_eng1(cdev); |
---|
| 2529 | + struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev); |
---|
| 2530 | + struct qed_ll2_buffer *buffer; |
---|
| 2531 | + int rx_num_desc, i, rc; |
---|
2377 | 2532 | |
---|
2378 | 2533 | if (!is_valid_ether_addr(params->ll2_mac_address)) { |
---|
2379 | | - DP_INFO(cdev, "Invalid Ethernet address\n"); |
---|
2380 | | - goto release_terminate; |
---|
| 2534 | + DP_NOTICE(cdev, "Invalid Ethernet address\n"); |
---|
| 2535 | + return -EINVAL; |
---|
2381 | 2536 | } |
---|
2382 | 2537 | |
---|
2383 | | - if (QED_LEADING_HWFN(cdev)->hw_info.personality == QED_PCI_ISCSI) { |
---|
2384 | | - DP_VERBOSE(cdev, QED_MSG_STORAGE, "Starting OOO LL2 queue\n"); |
---|
2385 | | - rc = qed_ll2_start_ooo(cdev, params); |
---|
| 2538 | + WARN_ON(!cdev->ll2->cbs); |
---|
| 2539 | + |
---|
| 2540 | + /* Initialize LL2 locks & lists */ |
---|
| 2541 | + INIT_LIST_HEAD(&cdev->ll2->list); |
---|
| 2542 | + spin_lock_init(&cdev->ll2->lock); |
---|
| 2543 | + |
---|
| 2544 | + cdev->ll2->rx_size = NET_SKB_PAD + ETH_HLEN + |
---|
| 2545 | + L1_CACHE_BYTES + params->mtu; |
---|
| 2546 | + |
---|
| 2547 | + /* Allocate memory for LL2. |
---|
| 2548 | + * In CMT mode, in case of a storage PF which is affintized to engine 1, |
---|
| 2549 | + * LL2 is started also on engine 0 and thus we need twofold buffers. |
---|
| 2550 | + */ |
---|
| 2551 | + rx_num_desc = QED_LL2_RX_SIZE * (b_is_storage_eng1 ? 2 : 1); |
---|
| 2552 | + DP_INFO(cdev, "Allocating %d LL2 buffers of size %08x bytes\n", |
---|
| 2553 | + rx_num_desc, cdev->ll2->rx_size); |
---|
| 2554 | + for (i = 0; i < rx_num_desc; i++) { |
---|
| 2555 | + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); |
---|
| 2556 | + if (!buffer) { |
---|
| 2557 | + DP_INFO(cdev, "Failed to allocate LL2 buffers\n"); |
---|
| 2558 | + rc = -ENOMEM; |
---|
| 2559 | + goto err0; |
---|
| 2560 | + } |
---|
| 2561 | + |
---|
| 2562 | + rc = qed_ll2_alloc_buffer(cdev, (u8 **)&buffer->data, |
---|
| 2563 | + &buffer->phys_addr); |
---|
2386 | 2564 | if (rc) { |
---|
2387 | | - DP_INFO(cdev, |
---|
2388 | | - "Failed to initialize the OOO LL2 queue\n"); |
---|
2389 | | - goto release_terminate; |
---|
| 2565 | + kfree(buffer); |
---|
| 2566 | + goto err0; |
---|
| 2567 | + } |
---|
| 2568 | + |
---|
| 2569 | + list_add_tail(&buffer->list, &cdev->ll2->list); |
---|
| 2570 | + } |
---|
| 2571 | + |
---|
| 2572 | + rc = __qed_ll2_start(p_hwfn, params); |
---|
| 2573 | + if (rc) { |
---|
| 2574 | + DP_NOTICE(cdev, "Failed to start LL2\n"); |
---|
| 2575 | + goto err0; |
---|
| 2576 | + } |
---|
| 2577 | + |
---|
| 2578 | + /* In CMT mode, always need to start LL2 on engine 0 for a storage PF, |
---|
| 2579 | + * since broadcast/mutlicast packets are routed to engine 0. |
---|
| 2580 | + */ |
---|
| 2581 | + if (b_is_storage_eng1) { |
---|
| 2582 | + rc = __qed_ll2_start(QED_LEADING_HWFN(cdev), params); |
---|
| 2583 | + if (rc) { |
---|
| 2584 | + DP_NOTICE(QED_LEADING_HWFN(cdev), |
---|
| 2585 | + "Failed to start LL2 on engine 0\n"); |
---|
| 2586 | + goto err1; |
---|
2390 | 2587 | } |
---|
2391 | 2588 | } |
---|
2392 | 2589 | |
---|
2393 | | - p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); |
---|
2394 | | - if (!p_ptt) { |
---|
2395 | | - DP_INFO(cdev, "Failed to acquire PTT\n"); |
---|
2396 | | - goto release_terminate; |
---|
| 2590 | + if (QED_IS_ISCSI_PERSONALITY(p_hwfn)) { |
---|
| 2591 | + DP_VERBOSE(cdev, QED_MSG_STORAGE, "Starting OOO LL2 queue\n"); |
---|
| 2592 | + rc = qed_ll2_start_ooo(p_hwfn, params); |
---|
| 2593 | + if (rc) { |
---|
| 2594 | + DP_NOTICE(cdev, "Failed to start OOO LL2\n"); |
---|
| 2595 | + goto err2; |
---|
| 2596 | + } |
---|
2397 | 2597 | } |
---|
2398 | 2598 | |
---|
2399 | | - rc = qed_llh_add_mac_filter(QED_LEADING_HWFN(cdev), p_ptt, |
---|
2400 | | - params->ll2_mac_address); |
---|
2401 | | - qed_ptt_release(QED_LEADING_HWFN(cdev), p_ptt); |
---|
| 2599 | + rc = qed_llh_add_mac_filter(cdev, 0, params->ll2_mac_address); |
---|
2402 | 2600 | if (rc) { |
---|
2403 | | - DP_ERR(cdev, "Failed to allocate LLH filter\n"); |
---|
2404 | | - goto release_terminate_all; |
---|
| 2601 | + DP_NOTICE(cdev, "Failed to add an LLH filter\n"); |
---|
| 2602 | + goto err3; |
---|
2405 | 2603 | } |
---|
2406 | 2604 | |
---|
2407 | 2605 | ether_addr_copy(cdev->ll2_mac_address, params->ll2_mac_address); |
---|
| 2606 | + |
---|
2408 | 2607 | return 0; |
---|
2409 | 2608 | |
---|
2410 | | -release_terminate_all: |
---|
2411 | | - |
---|
2412 | | -release_terminate: |
---|
2413 | | - qed_ll2_terminate_connection(QED_LEADING_HWFN(cdev), cdev->ll2->handle); |
---|
2414 | | -release_fail: |
---|
2415 | | - qed_ll2_release_connection(QED_LEADING_HWFN(cdev), cdev->ll2->handle); |
---|
2416 | | -fail: |
---|
| 2609 | +err3: |
---|
| 2610 | + if (QED_IS_ISCSI_PERSONALITY(p_hwfn)) |
---|
| 2611 | + qed_ll2_stop_ooo(p_hwfn); |
---|
| 2612 | +err2: |
---|
| 2613 | + if (b_is_storage_eng1) |
---|
| 2614 | + __qed_ll2_stop(QED_LEADING_HWFN(cdev)); |
---|
| 2615 | +err1: |
---|
| 2616 | + __qed_ll2_stop(p_hwfn); |
---|
| 2617 | +err0: |
---|
2417 | 2618 | qed_ll2_kill_buffers(cdev); |
---|
2418 | 2619 | cdev->ll2->handle = QED_LL2_UNUSED_HANDLE; |
---|
2419 | | - return -EINVAL; |
---|
2420 | | -} |
---|
2421 | | - |
---|
2422 | | -static int qed_ll2_stop(struct qed_dev *cdev) |
---|
2423 | | -{ |
---|
2424 | | - struct qed_ptt *p_ptt; |
---|
2425 | | - int rc; |
---|
2426 | | - |
---|
2427 | | - if (cdev->ll2->handle == QED_LL2_UNUSED_HANDLE) |
---|
2428 | | - return 0; |
---|
2429 | | - |
---|
2430 | | - p_ptt = qed_ptt_acquire(QED_LEADING_HWFN(cdev)); |
---|
2431 | | - if (!p_ptt) { |
---|
2432 | | - DP_INFO(cdev, "Failed to acquire PTT\n"); |
---|
2433 | | - goto fail; |
---|
2434 | | - } |
---|
2435 | | - |
---|
2436 | | - qed_llh_remove_mac_filter(QED_LEADING_HWFN(cdev), p_ptt, |
---|
2437 | | - cdev->ll2_mac_address); |
---|
2438 | | - qed_ptt_release(QED_LEADING_HWFN(cdev), p_ptt); |
---|
2439 | | - eth_zero_addr(cdev->ll2_mac_address); |
---|
2440 | | - |
---|
2441 | | - if (QED_LEADING_HWFN(cdev)->hw_info.personality == QED_PCI_ISCSI) |
---|
2442 | | - qed_ll2_stop_ooo(cdev); |
---|
2443 | | - |
---|
2444 | | - rc = qed_ll2_terminate_connection(QED_LEADING_HWFN(cdev), |
---|
2445 | | - cdev->ll2->handle); |
---|
2446 | | - if (rc) |
---|
2447 | | - DP_INFO(cdev, "Failed to terminate LL2 connection\n"); |
---|
2448 | | - |
---|
2449 | | - qed_ll2_kill_buffers(cdev); |
---|
2450 | | - |
---|
2451 | | - qed_ll2_release_connection(QED_LEADING_HWFN(cdev), cdev->ll2->handle); |
---|
2452 | | - cdev->ll2->handle = QED_LL2_UNUSED_HANDLE; |
---|
2453 | | - |
---|
2454 | 2620 | return rc; |
---|
2455 | | -fail: |
---|
2456 | | - return -EINVAL; |
---|
2457 | 2621 | } |
---|
2458 | 2622 | |
---|
2459 | 2623 | static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb, |
---|
2460 | 2624 | unsigned long xmit_flags) |
---|
2461 | 2625 | { |
---|
| 2626 | + struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev); |
---|
2462 | 2627 | struct qed_ll2_tx_pkt_info pkt; |
---|
2463 | 2628 | const skb_frag_t *frag; |
---|
2464 | 2629 | u8 flags = 0, nr_frags; |
---|
.. | .. |
---|
2516 | 2681 | * routine may run and free the SKB, so no dereferencing the SKB |
---|
2517 | 2682 | * beyond this point unless skb has any fragments. |
---|
2518 | 2683 | */ |
---|
2519 | | - rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle, |
---|
| 2684 | + rc = qed_ll2_prepare_tx_packet(p_hwfn, cdev->ll2->handle, |
---|
2520 | 2685 | &pkt, 1); |
---|
2521 | 2686 | if (rc) |
---|
2522 | 2687 | goto err; |
---|
.. | .. |
---|
2534 | 2699 | goto err; |
---|
2535 | 2700 | } |
---|
2536 | 2701 | |
---|
2537 | | - rc = qed_ll2_set_fragment_of_tx_packet(QED_LEADING_HWFN(cdev), |
---|
| 2702 | + rc = qed_ll2_set_fragment_of_tx_packet(p_hwfn, |
---|
2538 | 2703 | cdev->ll2->handle, |
---|
2539 | 2704 | mapping, |
---|
2540 | 2705 | skb_frag_size(frag)); |
---|
2541 | 2706 | |
---|
2542 | 2707 | /* if failed not much to do here, partial packet has been posted |
---|
2543 | | - * we can't free memory, will need to wait for completion. |
---|
| 2708 | + * we can't free memory, will need to wait for completion |
---|
2544 | 2709 | */ |
---|
2545 | 2710 | if (rc) |
---|
2546 | 2711 | goto err2; |
---|
.. | .. |
---|
2550 | 2715 | |
---|
2551 | 2716 | err: |
---|
2552 | 2717 | dma_unmap_single(&cdev->pdev->dev, mapping, skb->len, DMA_TO_DEVICE); |
---|
2553 | | - |
---|
2554 | 2718 | err2: |
---|
2555 | 2719 | return rc; |
---|
2556 | 2720 | } |
---|
2557 | 2721 | |
---|
2558 | 2722 | static int qed_ll2_stats(struct qed_dev *cdev, struct qed_ll2_stats *stats) |
---|
2559 | 2723 | { |
---|
| 2724 | + bool b_is_storage_eng1 = qed_ll2_is_storage_eng1(cdev); |
---|
| 2725 | + struct qed_hwfn *p_hwfn = QED_AFFIN_HWFN(cdev); |
---|
| 2726 | + int rc; |
---|
| 2727 | + |
---|
2560 | 2728 | if (!cdev->ll2) |
---|
2561 | 2729 | return -EINVAL; |
---|
2562 | 2730 | |
---|
2563 | | - return qed_ll2_get_stats(QED_LEADING_HWFN(cdev), |
---|
2564 | | - cdev->ll2->handle, stats); |
---|
| 2731 | + rc = qed_ll2_get_stats(p_hwfn, cdev->ll2->handle, stats); |
---|
| 2732 | + if (rc) { |
---|
| 2733 | + DP_NOTICE(p_hwfn, "Failed to get LL2 stats\n"); |
---|
| 2734 | + return rc; |
---|
| 2735 | + } |
---|
| 2736 | + |
---|
| 2737 | + /* In CMT mode, LL2 is always started on engine 0 for a storage PF */ |
---|
| 2738 | + if (b_is_storage_eng1) { |
---|
| 2739 | + rc = __qed_ll2_get_stats(QED_LEADING_HWFN(cdev), |
---|
| 2740 | + cdev->ll2->handle, stats); |
---|
| 2741 | + if (rc) { |
---|
| 2742 | + DP_NOTICE(QED_LEADING_HWFN(cdev), |
---|
| 2743 | + "Failed to get LL2 stats on engine 0\n"); |
---|
| 2744 | + return rc; |
---|
| 2745 | + } |
---|
| 2746 | + } |
---|
| 2747 | + |
---|
| 2748 | + return 0; |
---|
2565 | 2749 | } |
---|
2566 | 2750 | |
---|
2567 | 2751 | const struct qed_ll2_ops qed_ll2_ops_pass = { |
---|