29#include "switchtec/fabric.h"
30#include "switchtec_priv.h"
32#include "switchtec/errors.h"
33#include "switchtec/endian.h"
35static int topo_info_dump_start(
struct switchtec_dev *dev)
37 uint8_t subcmd = MRPC_TOPO_INFO_DUMP_START;
40 return switchtec_cmd(dev, MRPC_TOPO_INFO_DUMP, &subcmd,
sizeof(subcmd),
41 &status,
sizeof(status));
44static int topo_info_dump_status_get(
struct switchtec_dev *dev,
45 int *status, uint16_t *info_len)
49 uint8_t subcmd = MRPC_TOPO_INFO_DUMP_STATUS_GET;
57 ret =
switchtec_cmd(dev, MRPC_TOPO_INFO_DUMP, &subcmd,
sizeof(subcmd),
58 &result,
sizeof(result));
60 *status = result.status;
61 *info_len = result.data_len_dw * 4;
66#define SWITCHTEC_TOPO_INFO_DUMP_DATA_LENGTH_MAX 1000
67static int topo_info_dump_data_get(
struct switchtec_dev *dev, uint16_t offset,
68 char *buf, uint16_t *len)
78 .subcmd = MRPC_TOPO_INFO_DUMP_DATA_GET,
85 uint8_t data[SWITCHTEC_TOPO_INFO_DUMP_DATA_LENGTH_MAX];
89 cmd.subcmd = MRPC_TOPO_INFO_DUMP_DATA_GET_GEN5;
91 buf_len =
sizeof(result);
93 if(*len < SWITCHTEC_TOPO_INFO_DUMP_DATA_LENGTH_MAX)
94 buf_len = *len +
sizeof(result)
95 - SWITCHTEC_TOPO_INFO_DUMP_DATA_LENGTH_MAX;
100 sizeof(cmd), &result, buf_len);
102 *len = result.data_len_dw * 4;
104 memcpy(buf, &(result.data), *len);
109static int topo_info_dump_finish(
struct switchtec_dev *dev)
111 uint8_t subcmd = MRPC_TOPO_INFO_DUMP_FINISH;
114 return switchtec_cmd(dev, MRPC_TOPO_INFO_DUMP, &subcmd,
sizeof(subcmd),
115 &status,
sizeof(status));
118enum switchtec_fab_topo_info_dump_status {
119 SWITCHTEC_FAB_TOPO_INFO_DUMP_NOT_START = 1,
120 SWITCHTEC_FAB_TOPO_INFO_DUMP_WAIT = 2,
121 SWITCHTEC_FAB_TOPO_INFO_DUMP_READY = 3,
122 SWITCHTEC_FAB_TOPO_INFO_DUMP_FAILED = 4,
123 SWITCHTEC_FAB_TOPO_INFO_DUMP_WRONG_SUB_CMD = 5,
126static int topo_info_dump_gen4(
struct switchtec_dev *dev,
131 uint16_t total_info_len, offset, buf_len;
132 struct topo_info_reply_gen4 {
135 uint32_t stack_bif[7];
136 uint8_t route_port[16];
137 uint64_t port_bitmap;
142 char *buf = (
char *)&reply;
144 ret = topo_info_dump_start(dev);
149 ret = topo_info_dump_status_get(dev, &status, &total_info_len);
152 }
while (status == SWITCHTEC_FAB_TOPO_INFO_DUMP_WAIT);
154 if (status != SWITCHTEC_FAB_TOPO_INFO_DUMP_READY)
157 if (total_info_len >
sizeof(reply))
161 buf_len =
sizeof(reply);
163 while (offset < total_info_len) {
164 ret = topo_info_dump_data_get(dev, offset,
165 buf + offset, &buf_len);
170 buf_len =
sizeof(reply) - offset;
173 ret = topo_info_dump_finish(dev);
177 topo_info->
sw_idx = reply.sw_idx;
179 memcpy(topo_info->
stack_bif, reply.stack_bif, 7 *
sizeof(uint32_t));
180 memcpy(topo_info->
route_port, reply.route_port, 16 *
sizeof(uint8_t));
183 total_info_len - (
sizeof(reply) -
sizeof(reply.list)));
188static int topo_info_dump_gen5(
struct switchtec_dev *dev,
193 uint16_t total_info_len, offset, buf_len;
194 struct topo_info_reply_gen5 {
197 uint32_t stack_bif[8];
198 uint8_t route_port[16];
199 uint64_t port_bitmap;
204 char *buf = (
char *)&reply;
206 ret = topo_info_dump_start(dev);
211 ret = topo_info_dump_status_get(dev, &status, &total_info_len);
214 }
while (status == SWITCHTEC_FAB_TOPO_INFO_DUMP_WAIT);
216 if (status != SWITCHTEC_FAB_TOPO_INFO_DUMP_READY)
219 if (total_info_len >
sizeof(reply))
223 buf_len =
sizeof(reply);
225 while (offset < total_info_len) {
226 ret = topo_info_dump_data_get(dev, offset,
227 buf + offset, &buf_len);
232 buf_len =
sizeof(reply) - offset;
235 ret = topo_info_dump_finish(dev);
239 topo_info->
sw_idx = reply.sw_idx;
241 memcpy(topo_info->
stack_bif, reply.stack_bif, 8 *
sizeof(uint32_t));
242 memcpy(topo_info->
route_port, reply.route_port, 16 *
sizeof(uint8_t));
245 total_info_len - (
sizeof(reply) -
sizeof(reply.list)));
256int switchtec_topo_info_dump(
struct switchtec_dev *dev,
265 return topo_info_dump_gen4(dev, topo_info);
267 return topo_info_dump_gen5(dev, topo_info);
270int switchtec_gfms_bind(
struct switchtec_dev *dev,
278 uint8_t host_phys_port_id;
279 uint8_t host_log_port_id;
284 } function[SWITCHTEC_FABRIC_MULTI_FUNC_NUM];
292 cmd.subcmd = MRPC_GFMS_BIND;
293 cmd.host_sw_idx = req->host_sw_idx;
294 cmd.host_phys_port_id = req->host_phys_port_id;
295 cmd.host_log_port_id = req->host_log_port_id;
297 for (i = 0; i < req->ep_number; i++) {
298 cmd.function[i].pdfid = req->ep_pdfid[i];
299 cmd.function[i].next_valid = 0;
301 cmd.function[i - 1].next_valid = 1;
304 return switchtec_cmd(dev, MRPC_GFMS_BIND_UNBIND, &cmd,
sizeof(cmd),
305 &result,
sizeof(result));
308int switchtec_gfms_unbind(
struct switchtec_dev *dev,
314 uint8_t host_phys_port_id;
315 uint8_t host_log_port_id;
325 cmd.subcmd = MRPC_GFMS_UNBIND;
326 cmd.host_sw_idx = req->host_sw_idx;
327 cmd.host_phys_port_id = req->host_phys_port_id;
328 cmd.host_log_port_id = req->host_log_port_id;
329 cmd.pdfid = req->pdfid;
330 cmd.option = req->option;
332 return switchtec_cmd(dev, MRPC_GFMS_BIND_UNBIND, &cmd,
sizeof(cmd),
333 &result,
sizeof(result));
336int switchtec_port_control(
struct switchtec_dev *dev, uint8_t control_type,
337 uint8_t phys_port_id, uint8_t hot_reset_flag)
342 uint8_t control_type;
343 uint8_t phys_port_id;
344 uint8_t hot_reset_flag;
348 cmd.control_type = control_type;
349 cmd.phys_port_id = phys_port_id;
350 cmd.hot_reset_flag = hot_reset_flag;
352 ret =
switchtec_cmd(dev, MRPC_PORT_CONTROL, &cmd,
sizeof(cmd), NULL, 0);
364int switchtec_fab_port_config_get(
struct switchtec_dev *dev,
365 uint8_t phys_port_id,
372 uint8_t phys_port_id;
376 cmd.subcmd = MRPC_PORT_CONFIG_GET;
377 cmd.phys_port_id = phys_port_id;
379 ret =
switchtec_cmd(dev, MRPC_PORT_CONFIG, &cmd,
sizeof(cmd),
392int switchtec_fab_port_config_set(
struct switchtec_dev *dev,
393 uint8_t phys_port_id,
400 uint8_t phys_port_id;
402 uint8_t clock_source;
408 cmd.subcmd = MRPC_PORT_CONFIG_SET;
409 cmd.phys_port_id = phys_port_id;
415 ret =
switchtec_cmd(dev, MRPC_PORT_CONFIG, &cmd,
sizeof(cmd),
421int switchtec_fab_gfms_db_dump_fabric_general(
422 struct switchtec_dev *dev,
425 uint8_t subcmd = MRPC_GFMS_DB_DUMP_FABRIC;
427 return switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &subcmd,
sizeof(subcmd),
428 fabric_general,
sizeof(*fabric_general));
431static size_t gfms_hvd_all_section_parse(
432 struct switchtec_dev *dev,
440 size_t remaining_len;
445 len =
sizeof(hvd_all->hdr);
446 memcpy(&hvd_all->hdr, data, len);
449 remaining_len = hvd_all->hdr.resp_size_dw * 4 - len;
452 while (remaining_len) {
453 hvd_body = &hvd_all->bodies[i];
456 memcpy(hvd_body, p, len);
458 remaining_len -= len;
461 len = hvd_body->logical_port_count *
462 SWITCHTEC_FABRIC_MULTI_FUNC_NUM * 4;
463 memcpy(&hvd_body->bound[0], p, len);
465 remaining_len -= len;
469 hvd_all->hvd_count = i;
475static size_t gfms_pax_general_section_parse(
476 struct switchtec_dev *dev,
482 parsed_len =
sizeof(*pax_general);
484 memcpy(pax_general, data, parsed_len);
489int switchtec_fab_gfms_db_dump_pax_general(
490 struct switchtec_dev *dev,
493 uint8_t subcmd = MRPC_GFMS_DB_DUMP_PAX;
495 return switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &subcmd,
sizeof(subcmd),
496 pax_general,
sizeof(*pax_general));
499static int gfms_dump_start(
struct switchtec_dev *dev, uint8_t subcmd,
500 uint8_t param, uint32_t *total_len_dw)
517 uint32_t num_of_switch;
520 ret =
switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
522 *total_len_dw = rsp.dw_len;
527static int gfms_dump_get(
struct switchtec_dev *dev, uint8_t subcmd,
528 uint32_t total_len_dw, uint8_t *data)
547 uint8_t data[MRPC_MAX_DATA_LEN - 12];
553 ret =
switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
554 &rsp, MRPC_MAX_DATA_LEN);
561 memcpy(data + (cmd.offset_dw * 4), rsp.data, rsp.size_dw * 4);
563 cmd.offset_dw += rsp.size_dw;
565 }
while(total_len_dw > rsp.offset_dw + rsp.size_dw);
570static int gfms_dump_finish(
struct switchtec_dev *dev, uint8_t subcmd)
581 return switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
585int switchtec_fab_gfms_db_dump_hvd(
struct switchtec_dev *dev,
589 uint32_t total_len_dw;
592 ret = gfms_dump_start(dev, MRPC_GFMS_DB_DUMP_HVD,
593 hvd_idx, &total_len_dw);
597 ret = gfms_dump_get(dev, MRPC_GFMS_DB_DUMP_HVD, total_len_dw,
602 ret = gfms_dump_finish(dev, MRPC_GFMS_DB_DUMP_HVD);
609int switchtec_fab_gfms_db_dump_hvd_detail(
610 struct switchtec_dev *dev,
614 uint32_t total_len_dw;
623 ret = gfms_dump_start(dev, MRPC_GFMS_DB_DUMP_HVD_DETAIL,
624 hvd_idx, &total_len_dw);
628 data = malloc(total_len_dw * 4);
629 ret = gfms_dump_get(dev, MRPC_GFMS_DB_DUMP_HVD_DETAIL, total_len_dw,
636 ret = gfms_dump_finish(dev, MRPC_GFMS_DB_DUMP_HVD_DETAIL);
642 memcpy(&hvd_detail->hdr, data,
sizeof(hvd_detail->hdr));
647 hvd_detail->body.hvd_inst_id = body->hvd_inst_id;
648 hvd_detail->body.phy_pid = body->phy_pid;
649 hvd_detail->body.hfid = body->hfid;
650 hvd_detail->body.vep_count = body->vep_count;
651 hvd_detail->body.usp_status = body->usp_status;
654 len =
sizeof(body->vep_region[0]) * body->vep_count;
655 memcpy(hvd_detail->body.vep_region, body->vep_region, len);
658 len =
sizeof(hvd_detail->body.log_dsp_count);
659 memcpy(&hvd_detail->body.log_dsp_count, p, len);
662 len =
sizeof(hvd_detail->body.usp_bdf);
663 memcpy(&hvd_detail->body.usp_bdf, p, len);
666 len =
sizeof(hvd_detail->body.log_port_region[0]) *
667 le16toh(hvd_detail->body.log_dsp_count) *
668 SWITCHTEC_FABRIC_MULTI_FUNC_NUM;
669 memcpy(hvd_detail->body.log_port_region, p, len);
672 len =
sizeof(hvd_detail->body.log_port_p2p_enable_bitmap_low);
673 memcpy(&hvd_detail->body.log_port_p2p_enable_bitmap_low, p, len);
676 len =
sizeof(hvd_detail->body.log_port_p2p_enable_bitmap_high);
677 memcpy(&hvd_detail->body.log_port_p2p_enable_bitmap_high, p, len);
680 bitmap = le32toh(hvd_detail->body.log_port_p2p_enable_bitmap_high);
682 bitmap |= le32toh(hvd_detail->body.log_port_p2p_enable_bitmap_low);
684 hvd_detail->body.log_port_count = 0;
685 for (i = 0; i < (
sizeof(bitmap) * 8); i++)
686 if (bitmap >> i && 0x1)
687 hvd_detail->body.log_port_count++;
689 len =
sizeof(hvd_detail->body.log_port_p2p_bitmap[0]) *
690 hvd_detail->body.log_port_count;
691 memcpy(hvd_detail->body.log_port_p2p_bitmap, p, len);
697int switchtec_fab_gfms_db_dump_fab_port(
698 struct switchtec_dev *dev,
706 .subcmd = MRPC_GFMS_DB_DUMP_FAB_PORT,
710 return switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
711 fab_port,
sizeof(*fab_port));
714static int gfms_ep_port_start(
struct switchtec_dev *dev,
716 uint32_t *total_len_dw)
726 .subcmd = MRPC_GFMS_DB_DUMP_EP_PORT,
727 .fab_ep_pid = fab_ep_pid,
733 uint32_t num_of_switch;
736 ret =
switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
738 *total_len_dw = rsp.dw_len;
743static int gfms_ep_port_get(
struct switchtec_dev *dev,
745 uint32_t total_len_dw,
757 .subcmd = MRPC_GFMS_DB_DUMP_EP_PORT,
758 .fab_ep_pid = fab_ep_pid,
767 uint8_t data[MRPC_MAX_DATA_LEN - 12];
774 ret =
switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
775 &rsp, MRPC_MAX_DATA_LEN);
780 if (rsp.size_dw > 0xf0)
785 memcpy(data + (cmd.offset_dw * 4), rsp.data, rsp.size_dw * 4);
787 cmd.offset_dw += rsp.size_dw;
789 }
while(total_len_dw > rsp.offset_dw + rsp.size_dw);
794static int gfms_ep_port_finish(
struct switchtec_dev *dev)
801 .subcmd = MRPC_GFMS_DB_DUMP_EP_PORT,
805 return switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
809static size_t gfms_ep_port_attached_ep_parse(
810 struct switchtec_dev *dev,
818 len =
sizeof(ep_port_ep->ep_hdr);
819 memcpy(&ep_port_ep->ep_hdr, p, len);
823 len = ep_port_ep->ep_hdr.size_dw * 4 -
sizeof(ep_port_ep->ep_hdr);
824 memcpy(ep_port_ep->functions, p, len);
830static size_t gfms_ep_port_attache_switch_parse(
831 struct switchtec_dev *dev,
839 len =
sizeof(ep_port_switch->sw_hdr);
840 memcpy(&ep_port_switch->sw_hdr, p, len);
844 len =
sizeof(ep_port_switch->ds_switch.internal_functions[0]);
845 len = ep_port_switch->sw_hdr.function_number * len;
846 memcpy(ep_port_switch->ds_switch.internal_functions, p, len);
853static size_t gfms_ep_port_sub_section_parse(
854 struct switchtec_dev *dev,
860 size_t remaining_len;
864 len =
sizeof(ep_port->port_hdr);
865 memcpy(&ep_port->port_hdr, p, len);
866 remaining_len = ep_port->port_hdr.size_dw * 4;
869 remaining_len -= len;
871 if (ep_port->port_hdr.type == SWITCHTEC_GFMS_DB_TYPE_SWITCH) {
872 len = gfms_ep_port_attache_switch_parse(dev, p,
873 &ep_port->ep_switch);
876 remaining_len -= len;
879 while (remaining_len) {
880 len = gfms_ep_port_attached_ep_parse(
882 &ep_port->ep_switch.switch_eps[i++]);
885 remaining_len -= len;
887 }
else if (ep_port->port_hdr.type == SWITCHTEC_GFMS_DB_TYPE_EP) {
888 len = gfms_ep_port_attached_ep_parse(dev, p, &ep_port->ep_ep);
891 }
else if (ep_port->port_hdr.type == SWITCHTEC_GFMS_DB_TYPE_NON) {
897static size_t gfms_ep_port_section_parse(
898 struct switchtec_dev *dev,
906 len =
sizeof(ep_port_section->hdr);
907 memcpy(&ep_port_section->hdr, p, len);
911 len = ep_port_section->hdr.resp_size_dw * 4 - len;
912 len = gfms_ep_port_sub_section_parse(dev, p, &ep_port_section->ep_port);
918int switchtec_fab_gfms_db_dump_ep_port(
919 struct switchtec_dev *dev,
923 uint32_t total_len_dw;
928 ret = gfms_ep_port_start(dev, phy_pid, &total_len_dw);
932 data = malloc(total_len_dw * 4);
933 ret = gfms_ep_port_get(dev, phy_pid, total_len_dw, data);
937 ret = gfms_ep_port_finish(dev);
941 parsed_len = gfms_ep_port_section_parse(dev, data, ep_port_section);
942 if (parsed_len != total_len_dw * 4)
951static size_t gfms_ep_port_all_section_parse(
952 struct switchtec_dev *dev,
958 size_t remaining_len;
963 len =
sizeof(ep_port_all->hdr);
964 memcpy(&ep_port_all->hdr, data, len);
968 remaining_len = ep_port_all->hdr.resp_size_dw * 4 -
969 sizeof(ep_port_all->hdr);
972 while (remaining_len) {
973 ep_port = &ep_port_all->ep_ports[i];
975 len = gfms_ep_port_sub_section_parse(dev, p, ep_port);
978 remaining_len -= len;
981 ep_port_all->ep_port_count = i;
987static size_t gfms_pax_all_parse(
struct switchtec_dev *dev,
998 len = gfms_pax_general_section_parse(dev, data, &pax_all->pax_general);
1002 len = gfms_hvd_all_section_parse(dev, p, &pax_all->hvd_all);
1006 len = gfms_ep_port_all_section_parse(dev, p, &pax_all->ep_port_all);
1012int switchtec_fab_gfms_db_dump_pax_all(
1013 struct switchtec_dev *dev,
1016 uint32_t total_len_dw;
1021 ret = gfms_dump_start(dev, MRPC_GFMS_DB_DUMP_PAX_ALL, 0, &total_len_dw);
1025 data = malloc(total_len_dw * 4);
1026 ret = gfms_dump_get(dev, MRPC_GFMS_DB_DUMP_PAX_ALL, total_len_dw, data);
1032 ret = gfms_dump_finish(dev, MRPC_GFMS_DB_DUMP_PAX_ALL);
1038 parsed_len = gfms_pax_all_parse(dev, data, total_len_dw * 4, pax_all);
1040 if (parsed_len != total_len_dw * 4)
1047int switchtec_get_gfms_events(
struct switchtec_dev *dev,
1049 size_t elist_len,
int *overflow,
1050 size_t *remain_number)
1054 uint16_t req_num = elist_len;
1055 uint16_t remain_num;
1072 uint16_t remain_num_flag;
1073 uint8_t data[MRPC_MAX_DATA_LEN - 4];
1085 sizeof(req), &resp,
sizeof(resp));
1089 if ((resp.remain_num_flag & 0x8000) && overflow)
1093 for (i = 0; i < resp.num; i++) {
1094 hdr = (
struct entry *)p;
1095 e->event_code = hdr->event_code;
1096 e->src_sw_id = hdr->src_sw_id;
1097 d_len = le32toh(hdr->entry_len) -
1098 offsetof(
struct entry, data);
1099 memcpy(e->data.byte, hdr->data, d_len);
1100 p += hdr->entry_len;
1103 event_cnt += resp.num;
1104 remain_num = resp.remain_num_flag & 0x7fff;
1105 req_num -= resp.num;
1106 }
while (req_num && remain_num);
1109 *remain_number = remain_num;
1114int switchtec_clear_gfms_events(
struct switchtec_dev *dev)
1117 uint32_t subcmd = 0;
1119 ret =
switchtec_cmd(dev, MRPC_GFMS_EVENT, &subcmd,
sizeof(subcmd),
1127int switchtec_device_manage(
struct switchtec_dev *dev,
1133 req->hdr.expected_rsp_len = htole16(req->hdr.expected_rsp_len);
1134 req->hdr.pdfid = htole16(req->hdr.pdfid);
1140 rsp->hdr.rsp_len = le16toh(rsp->hdr.rsp_len);
1145int switchtec_ep_tunnel_config(
struct switchtec_dev *dev, uint16_t subcmd,
1146 uint16_t pdfid, uint16_t expected_rsp_len,
1147 uint8_t *meta_data, uint16_t meta_data_len,
1156 uint16_t expected_rsp_len;
1157 uint16_t meta_data_len;
1158 uint8_t meta_data[MRPC_MAX_DATA_LEN - 8];
1160 .subcmd = htole16(subcmd),
1161 .pdfid = htole16(pdfid),
1162 .expected_rsp_len = htole16(expected_rsp_len),
1167 uint8_t data[MRPC_MAX_DATA_LEN - 4];
1170 if (meta_data_len >
sizeof(req.meta_data))
1173 req.meta_data_len = htole16(meta_data_len);
1176 memcpy(req.meta_data, meta_data, meta_data_len);
1178 payload_len = offsetof(
struct cfg_req, meta_data) + meta_data_len;
1181 payload_len, &rsp,
sizeof(rsp));
1186 rsp.len = le32toh(rsp.len);
1188 if (rsp_data && rsp.len)
1189 memcpy(rsp_data, rsp.data, rsp.len);
1194int switchtec_ep_tunnel_enable(
struct switchtec_dev *dev, uint16_t pdfid)
1196 return switchtec_ep_tunnel_config(dev, MRPC_EP_TUNNEL_ENABLE,
1197 pdfid, 0, NULL, 0, NULL);
1200int switchtec_ep_tunnel_disable(
struct switchtec_dev *dev, uint16_t pdfid)
1202 return switchtec_ep_tunnel_config(dev, MRPC_EP_TUNNEL_DISABLE,
1203 pdfid, 0, NULL, 0, NULL);
1206int switchtec_ep_tunnel_status(
struct switchtec_dev *dev, uint16_t pdfid,
1211 ret = switchtec_ep_tunnel_config(dev, MRPC_EP_TUNNEL_STATUS,
1212 pdfid,
sizeof(*status), NULL,
1213 0, (uint8_t *)status);
1214 *status = le32toh(*status);
1219static int ep_csr_read(
struct switchtec_dev *dev,
1220 uint16_t pdfid,
void *dest,
1221 uint16_t src,
size_t n)
1225 if (n > SWITCHTEC_EP_CSR_MAX_READ_LEN)
1226 n = SWITCHTEC_EP_CSR_MAX_READ_LEN;
1231 struct ep_cfg_read {
1240 .pdfid = htole16(pdfid),
1241 .addr = htole16(src),
1250 sizeof(cmd), &rsp, 4);
1254 memcpy(dest, &rsp.data, n);
1258int switchtec_ep_csr_read8(
struct switchtec_dev *dev, uint16_t pdfid,
1259 uint16_t addr, uint8_t *val)
1261 return ep_csr_read(dev, pdfid, val, addr, 1);
1264int switchtec_ep_csr_read16(
struct switchtec_dev *dev, uint16_t pdfid,
1265 uint16_t addr, uint16_t *val)
1269 ret = ep_csr_read(dev, pdfid, val, addr, 2);
1270 *val = le16toh(*val);
1275int switchtec_ep_csr_read32(
struct switchtec_dev *dev, uint16_t pdfid,
1276 uint16_t addr, uint32_t *val)
1280 ret = ep_csr_read(dev, pdfid, val, addr, 4);
1281 *val = le32toh(*val);
1286static int ep_csr_write(
struct switchtec_dev *dev, uint16_t pdfid,
1287 uint16_t addr,
const void *val,
size_t n)
1289 if (n > SWITCHTEC_EP_CSR_MAX_WRITE_LEN)
1290 n = SWITCHTEC_EP_CSR_MAX_WRITE_LEN;
1295 struct ep_cfg_write {
1305 .pdfid = htole16(pdfid),
1306 .addr = htole16(addr),
1310 memcpy(&cmd.data, val, n);
1313 sizeof(cmd), NULL, 0);
1316int switchtec_ep_csr_write8(
struct switchtec_dev *dev, uint16_t pdfid,
1317 uint8_t val, uint16_t addr)
1319 return ep_csr_write(dev, pdfid, addr, &val, 1);
1322int switchtec_ep_csr_write16(
struct switchtec_dev *dev, uint16_t pdfid,
1323 uint16_t val, uint16_t addr)
1326 return ep_csr_write(dev, pdfid, addr, &val, 2);
1329int switchtec_ep_csr_write32(
struct switchtec_dev *dev, uint16_t pdfid,
1330 uint32_t val, uint16_t addr)
1333 return ep_csr_write(dev, pdfid, addr, &val, 4);
1336static size_t ep_bar_read(
struct switchtec_dev *dev, uint16_t pdfid,
1337 uint8_t bar,
void *dest,
1338 uint64_t src,
size_t n)
1340 if (n > SWITCHTEC_EP_BAR_MAX_READ_LEN)
1341 n = SWITCHTEC_EP_BAR_MAX_READ_LEN;
1348 struct ep_bar_read {
1359 .pdfid = htole16(pdfid),
1361 .addr_low = (uint32_t)src,
1362 .addr_high = (uint32_t)(src >> 32),
1363 .bytes= htole16((uint16_t)n),
1367 sizeof(cmd), dest, n);
1370int switchtec_ep_bar_read8(
struct switchtec_dev *dev, uint16_t pdfid,
1371 uint8_t bar, uint64_t addr, uint8_t *val)
1373 return ep_bar_read(dev, pdfid, bar, val, addr, 1);
1376int switchtec_ep_bar_read16(
struct switchtec_dev *dev, uint16_t pdfid,
1377 uint8_t bar, uint64_t addr, uint16_t *val)
1381 ret = ep_bar_read(dev, pdfid, bar, val, addr, 2);
1382 *val = le16toh(*val);
1387int switchtec_ep_bar_read32(
struct switchtec_dev *dev, uint16_t pdfid,
1388 uint8_t bar, uint64_t addr, uint32_t *val)
1392 ret = ep_bar_read(dev, pdfid, bar, val, addr, 4);
1393 *val = le32toh(*val);
1398int switchtec_ep_bar_read64(
struct switchtec_dev *dev, uint16_t pdfid,
1399 uint8_t bar, uint64_t addr, uint64_t *val)
1403 ret = ep_bar_read(dev, pdfid, bar, val, addr, 8);
1404 *val = le64toh(*val);
1409static int ep_bar_write(
struct switchtec_dev *dev, uint16_t pdfid,
1410 uint8_t bar, uint64_t addr,
1411 const void *val,
size_t n)
1413 if (n > SWITCHTEC_EP_BAR_MAX_WRITE_LEN)
1414 n = SWITCHTEC_EP_BAR_MAX_WRITE_LEN;
1419 addr = htole64(addr);
1421 struct ep_bar_write {
1433 .pdfid = htole16(pdfid),
1435 .bytes= htole16((uint16_t)n),
1436 .addr_low = (uint32_t)addr,
1437 .addr_high = (uint32_t)(addr >> 32),
1440 memcpy(&cmd.data, val, n);
1443 &cmd,
sizeof(cmd), NULL, 0);
1446int switchtec_ep_bar_write8(
struct switchtec_dev *dev, uint16_t pdfid,
1447 uint8_t bar, uint8_t val, uint64_t addr)
1449 return ep_bar_write(dev, pdfid, bar, addr, &val, 1);
1452int switchtec_ep_bar_write16(
struct switchtec_dev *dev, uint16_t pdfid,
1453 uint8_t bar, uint16_t val, uint64_t addr)
1456 return ep_bar_write(dev, pdfid, bar, addr, &val, 2);
1459int switchtec_ep_bar_write32(
struct switchtec_dev *dev, uint16_t pdfid,
1460 uint8_t bar, uint32_t val, uint64_t addr)
1463 return ep_bar_write(dev, pdfid, bar, addr, &val, 4);
1466int switchtec_ep_bar_write64(
struct switchtec_dev *dev, uint16_t pdfid,
1467 uint8_t bar, uint64_t val, uint64_t addr)
1470 return ep_bar_write(dev, pdfid, bar, addr, &val, 8);
1473static int admin_passthru_start(
struct switchtec_dev *dev, uint16_t pdfid,
1474 size_t data_len,
void *data,
1479 uint16_t offset = 0;
1485 uint16_t expected_rsp_len;
1488 uint16_t data_offset;
1490 uint8_t data[MRPC_MAX_DATA_LEN - 16];
1492 .subcmd = MRPC_NVME_ADMIN_PASSTHRU_START,
1493 .pdfid = htole16(pdfid)
1501 if (data_len && data != NULL) {
1502 cmd.more_data = data_len >
sizeof(cmd.data);
1503 while (cmd.more_data) {
1504 copy_len =
sizeof(cmd.data);
1505 memcpy(cmd.data, data + offset, copy_len);
1507 cmd.data_offset = htole16(offset);
1508 cmd.data_len = htole16(copy_len);
1511 &cmd,
sizeof(cmd), NULL, 0);
1516 data_len -= copy_len;
1517 cmd.more_data = data_len >
sizeof(cmd.data);
1521 memcpy(cmd.data, data + offset, data_len);
1523 cmd.data_offset = htole16(offset);
1524 cmd.data_len = htole16(data_len);
1527 cmd.data_offset = 0;
1531 cmd.expected_rsp_len = htole16(*rsp_len);
1534 &cmd,
sizeof(cmd), &reply,
sizeof(reply));
1540 *rsp_len = le16toh(reply.rsp_len);
1544static int admin_passthru_data(
struct switchtec_dev *dev, uint16_t pdfid,
1545 size_t rsp_len,
void *rsp)
1555 .subcmd = MRPC_NVME_ADMIN_PASSTHRU_DATA,
1556 .pdfid = htole16(pdfid),
1562 uint8_t data[MRPC_MAX_DATA_LEN - 4];
1565 while (offset < rsp_len) {
1566 cmd.offset = htole16(offset);
1569 &cmd,
sizeof(cmd), &reply,
1574 memcpy((uint8_t*)rsp + offset, reply.data,
1575 htole16(reply.len));
1576 offset += htole16(reply.len);
1582static int admin_passthru_end(
struct switchtec_dev *dev, uint16_t pdfid)
1591 cmd.subcmd = MRPC_NVME_ADMIN_PASSTHRU_END;
1592 cmd.pdfid = htole16(pdfid);
1595 &cmd,
sizeof(cmd), NULL, 0);
1608int switchtec_nvme_admin_passthru(
struct switchtec_dev *dev, uint16_t pdfid,
1609 size_t data_len,
void *data,
1610 size_t *rsp_len,
void *rsp)
1614 ret = admin_passthru_start(dev, pdfid, data_len, data, rsp_len);
1618 if (*rsp_len && rsp != NULL) {
1619 ret = admin_passthru_data(dev, pdfid, *rsp_len, rsp);
1626 ret = admin_passthru_end(dev, pdfid);
int switchtec_cmd(struct switchtec_dev *dev, uint32_t cmd, const void *payload, size_t payload_len, void *resp, size_t resp_len)
Execute an MRPC command.
uint8_t clock_sris
Port clock sris, enable/disable.
uint8_t hvd_inst
HVM domain instance index for USP.
uint8_t port_type
Port type.
uint8_t clock_source
CSU channel index for port clock source(0-2)
Represents each port in the in topology info.
Represents the topology info.
struct switchtec_fab_port_info port_info_list[SWITCHTEC_MAX_PORTS]
Port info list.
uint8_t sw_idx
Switch index.
int num_stack_bif
Number of port bifurcation fields.
uint8_t route_port[16]
Route port.
uint32_t stack_bif[8]
Port bifurcation.
uint64_t port_bitmap
Enabled physical port bitmap.
Represents the GFMS event.
static int switchtec_is_gen4(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 4 device.
static int switchtec_is_gen5(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 5 device.
static int switchtec_is_pax_all(struct switchtec_dev *dev)
Return whether a Switchtec device is PAX(A).