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;
139 struct switchtec_fab_port_info list[SWITCHTEC_MAX_PORTS];
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;
201 struct switchtec_fab_port_info list[SWITCHTEC_MAX_PORTS];
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);
631 ret = gfms_dump_get(dev, MRPC_GFMS_DB_DUMP_HVD_DETAIL, total_len_dw,
638 ret = gfms_dump_finish(dev, MRPC_GFMS_DB_DUMP_HVD_DETAIL);
644 memcpy(&hvd_detail->hdr, data,
sizeof(hvd_detail->hdr));
649 hvd_detail->body.hvd_inst_id = body->hvd_inst_id;
650 hvd_detail->body.phy_pid = body->phy_pid;
651 hvd_detail->body.hfid = body->hfid;
652 hvd_detail->body.vep_count = body->vep_count;
653 hvd_detail->body.usp_status = body->usp_status;
656 len =
sizeof(body->vep_region[0]) * body->vep_count;
657 memcpy(hvd_detail->body.vep_region, body->vep_region, len);
660 len =
sizeof(hvd_detail->body.log_dsp_count);
661 memcpy(&hvd_detail->body.log_dsp_count, p, len);
664 len =
sizeof(hvd_detail->body.usp_bdf);
665 memcpy(&hvd_detail->body.usp_bdf, p, len);
668 len =
sizeof(hvd_detail->body.log_port_region[0]) *
669 le16toh(hvd_detail->body.log_dsp_count) *
670 SWITCHTEC_FABRIC_MULTI_FUNC_NUM;
671 memcpy(hvd_detail->body.log_port_region, p, len);
674 len =
sizeof(hvd_detail->body.log_port_p2p_enable_bitmap_low);
675 memcpy(&hvd_detail->body.log_port_p2p_enable_bitmap_low, p, len);
678 len =
sizeof(hvd_detail->body.log_port_p2p_enable_bitmap_high);
679 memcpy(&hvd_detail->body.log_port_p2p_enable_bitmap_high, p, len);
682 bitmap = le32toh(hvd_detail->body.log_port_p2p_enable_bitmap_high);
684 bitmap |= le32toh(hvd_detail->body.log_port_p2p_enable_bitmap_low);
686 hvd_detail->body.log_port_count = 0;
687 for (i = 0; i < (
sizeof(bitmap) * 8); i++)
688 if (bitmap >> i && 0x1)
689 hvd_detail->body.log_port_count++;
691 len =
sizeof(hvd_detail->body.log_port_p2p_bitmap[0]) *
692 hvd_detail->body.log_port_count;
693 memcpy(hvd_detail->body.log_port_p2p_bitmap, p, len);
699int switchtec_fab_gfms_db_dump_fab_port(
700 struct switchtec_dev *dev,
708 .subcmd = MRPC_GFMS_DB_DUMP_FAB_PORT,
712 return switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
713 fab_port,
sizeof(*fab_port));
716static int gfms_ep_port_start(
struct switchtec_dev *dev,
718 uint32_t *total_len_dw)
728 .subcmd = MRPC_GFMS_DB_DUMP_EP_PORT,
729 .fab_ep_pid = fab_ep_pid,
735 uint32_t num_of_switch;
738 ret =
switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
740 *total_len_dw = rsp.dw_len;
745static int gfms_ep_port_get(
struct switchtec_dev *dev,
747 uint32_t total_len_dw,
759 .subcmd = MRPC_GFMS_DB_DUMP_EP_PORT,
760 .fab_ep_pid = fab_ep_pid,
769 uint8_t data[MRPC_MAX_DATA_LEN - 12];
776 ret =
switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
777 &rsp, MRPC_MAX_DATA_LEN);
782 if (rsp.size_dw > 0xf0)
787 memcpy(data + (cmd.offset_dw * 4), rsp.data, rsp.size_dw * 4);
789 cmd.offset_dw += rsp.size_dw;
791 }
while (total_len_dw > rsp.offset_dw + rsp.size_dw);
796static int gfms_ep_port_finish(
struct switchtec_dev *dev)
803 .subcmd = MRPC_GFMS_DB_DUMP_EP_PORT,
807 return switchtec_cmd(dev, MRPC_GFMS_DB_DUMP, &cmd,
sizeof(cmd),
811static size_t gfms_ep_port_attached_ep_parse(
812 struct switchtec_dev *dev,
820 len =
sizeof(ep_port_ep->ep_hdr);
821 memcpy(&ep_port_ep->ep_hdr, p, len);
825 len = ep_port_ep->ep_hdr.size_dw * 4 -
sizeof(ep_port_ep->ep_hdr);
826 memcpy(ep_port_ep->functions, p, len);
832static size_t gfms_ep_port_attache_switch_parse(
833 struct switchtec_dev *dev,
841 len =
sizeof(ep_port_switch->sw_hdr);
842 memcpy(&ep_port_switch->sw_hdr, p, len);
846 len =
sizeof(ep_port_switch->ds_switch.internal_functions[0]);
847 len = ep_port_switch->sw_hdr.function_number * len;
848 memcpy(ep_port_switch->ds_switch.internal_functions, p, len);
855static size_t gfms_ep_port_sub_section_parse(
856 struct switchtec_dev *dev,
862 size_t remaining_len;
866 len =
sizeof(ep_port->port_hdr);
867 memcpy(&ep_port->port_hdr, p, len);
868 remaining_len = ep_port->port_hdr.size_dw * 4;
871 remaining_len -= len;
873 if (ep_port->port_hdr.type == SWITCHTEC_GFMS_DB_TYPE_SWITCH) {
874 len = gfms_ep_port_attache_switch_parse(dev, p,
875 &ep_port->ep_switch);
878 remaining_len -= len;
881 while (remaining_len) {
882 len = gfms_ep_port_attached_ep_parse(
884 &ep_port->ep_switch.switch_eps[i++]);
887 remaining_len -= len;
889 }
else if (ep_port->port_hdr.type == SWITCHTEC_GFMS_DB_TYPE_EP) {
890 len = gfms_ep_port_attached_ep_parse(dev, p, &ep_port->ep_ep);
893 }
else if (ep_port->port_hdr.type == SWITCHTEC_GFMS_DB_TYPE_NON) {
899static size_t gfms_ep_port_section_parse(
900 struct switchtec_dev *dev,
908 len =
sizeof(ep_port_section->hdr);
909 memcpy(&ep_port_section->hdr, p, len);
913 len = ep_port_section->hdr.resp_size_dw * 4 - len;
914 len = gfms_ep_port_sub_section_parse(dev, p, &ep_port_section->ep_port);
920int switchtec_fab_gfms_db_dump_ep_port(
921 struct switchtec_dev *dev,
925 uint32_t total_len_dw;
930 ret = gfms_ep_port_start(dev, phy_pid, &total_len_dw);
934 data = malloc(total_len_dw * 4);
939 ret = gfms_ep_port_get(dev, phy_pid, total_len_dw, data);
943 ret = gfms_ep_port_finish(dev);
947 parsed_len = gfms_ep_port_section_parse(dev, data, ep_port_section);
948 if (parsed_len != total_len_dw * 4)
957static size_t gfms_ep_port_all_section_parse(
958 struct switchtec_dev *dev,
964 size_t remaining_len;
969 len =
sizeof(ep_port_all->hdr);
970 memcpy(&ep_port_all->hdr, data, len);
974 remaining_len = ep_port_all->hdr.resp_size_dw * 4 -
975 sizeof(ep_port_all->hdr);
978 while (remaining_len) {
979 ep_port = &ep_port_all->ep_ports[i];
981 len = gfms_ep_port_sub_section_parse(dev, p, ep_port);
984 remaining_len -= len;
987 ep_port_all->ep_port_count = i;
993static size_t gfms_pax_all_parse(
struct switchtec_dev *dev,
1004 len = gfms_pax_general_section_parse(dev, data, &pax_all->pax_general);
1008 len = gfms_hvd_all_section_parse(dev, p, &pax_all->hvd_all);
1012 len = gfms_ep_port_all_section_parse(dev, p, &pax_all->ep_port_all);
1018int switchtec_fab_gfms_db_dump_pax_all(
1019 struct switchtec_dev *dev,
1022 uint32_t total_len_dw;
1027 ret = gfms_dump_start(dev, MRPC_GFMS_DB_DUMP_PAX_ALL, 0, &total_len_dw);
1031 data = malloc(total_len_dw * 4);
1034 ret = gfms_dump_get(dev, MRPC_GFMS_DB_DUMP_PAX_ALL, total_len_dw, data);
1040 ret = gfms_dump_finish(dev, MRPC_GFMS_DB_DUMP_PAX_ALL);
1046 parsed_len = gfms_pax_all_parse(dev, data, total_len_dw * 4, pax_all);
1048 if (parsed_len != total_len_dw * 4)
1055int switchtec_get_gfms_events(
struct switchtec_dev *dev,
1057 size_t elist_len,
int *overflow,
1058 size_t *remain_number)
1062 uint16_t req_num = elist_len;
1063 uint16_t remain_num;
1080 uint16_t remain_num_flag;
1081 uint8_t data[MRPC_MAX_DATA_LEN - 4];
1093 sizeof(req), &resp,
sizeof(resp));
1097 if ((resp.remain_num_flag & 0x8000) && overflow)
1101 for (i = 0; i < resp.num; i++) {
1102 hdr = (
struct entry *)p;
1103 e->event_code = hdr->event_code;
1104 e->src_sw_id = hdr->src_sw_id;
1105 d_len = le32toh(hdr->entry_len) -
1106 offsetof(
struct entry, data);
1107 memcpy(e->data.byte, hdr->data, d_len);
1108 p += hdr->entry_len;
1111 event_cnt += resp.num;
1112 remain_num = resp.remain_num_flag & 0x7fff;
1113 req_num -= resp.num;
1114 }
while (req_num && remain_num);
1117 *remain_number = remain_num;
1122int switchtec_clear_gfms_events(
struct switchtec_dev *dev)
1125 uint32_t subcmd = 0;
1127 ret =
switchtec_cmd(dev, MRPC_GFMS_EVENT, &subcmd,
sizeof(subcmd),
1135int switchtec_device_manage(
struct switchtec_dev *dev,
1141 req->hdr.expected_rsp_len = htole16(req->hdr.expected_rsp_len);
1142 req->hdr.pdfid = htole16(req->hdr.pdfid);
1148 rsp->hdr.rsp_len = le16toh(rsp->hdr.rsp_len);
1153int switchtec_ep_tunnel_config(
struct switchtec_dev *dev, uint16_t subcmd,
1154 uint16_t pdfid, uint16_t expected_rsp_len,
1155 uint8_t *meta_data, uint16_t meta_data_len,
1164 uint16_t expected_rsp_len;
1165 uint16_t meta_data_len;
1166 uint8_t meta_data[MRPC_MAX_DATA_LEN - 8];
1168 .subcmd = htole16(subcmd),
1169 .pdfid = htole16(pdfid),
1170 .expected_rsp_len = htole16(expected_rsp_len),
1175 uint8_t data[MRPC_MAX_DATA_LEN - 4];
1178 if (meta_data_len >
sizeof(req.meta_data))
1181 req.meta_data_len = htole16(meta_data_len);
1184 memcpy(req.meta_data, meta_data, meta_data_len);
1186 payload_len = offsetof(
struct cfg_req, meta_data) + meta_data_len;
1189 payload_len, &rsp,
sizeof(rsp));
1194 rsp.len = le32toh(rsp.len);
1196 if (rsp_data && rsp.len)
1197 memcpy(rsp_data, rsp.data, rsp.len);
1202int switchtec_ep_tunnel_enable(
struct switchtec_dev *dev, uint16_t pdfid)
1204 return switchtec_ep_tunnel_config(dev, MRPC_EP_TUNNEL_ENABLE,
1205 pdfid, 0, NULL, 0, NULL);
1208int switchtec_ep_tunnel_disable(
struct switchtec_dev *dev, uint16_t pdfid)
1210 return switchtec_ep_tunnel_config(dev, MRPC_EP_TUNNEL_DISABLE,
1211 pdfid, 0, NULL, 0, NULL);
1214int switchtec_ep_tunnel_status(
struct switchtec_dev *dev, uint16_t pdfid,
1219 ret = switchtec_ep_tunnel_config(dev, MRPC_EP_TUNNEL_STATUS,
1220 pdfid,
sizeof(*status), NULL,
1221 0, (uint8_t *)status);
1222 *status = le32toh(*status);
1227static int ep_csr_read(
struct switchtec_dev *dev,
1228 uint16_t pdfid,
void *dest,
1229 uint16_t src,
size_t n)
1233 if (n > SWITCHTEC_EP_CSR_MAX_READ_LEN)
1234 n = SWITCHTEC_EP_CSR_MAX_READ_LEN;
1239 struct ep_cfg_read {
1248 .pdfid = htole16(pdfid),
1249 .addr = htole16(src),
1258 sizeof(cmd), &rsp, 4);
1262 memcpy(dest, &rsp.data, n);
1266int switchtec_ep_csr_read8(
struct switchtec_dev *dev, uint16_t pdfid,
1267 uint16_t addr, uint8_t *val)
1269 return ep_csr_read(dev, pdfid, val, addr, 1);
1272int switchtec_ep_csr_read16(
struct switchtec_dev *dev, uint16_t pdfid,
1273 uint16_t addr, uint16_t *val)
1277 ret = ep_csr_read(dev, pdfid, val, addr, 2);
1278 *val = le16toh(*val);
1283int switchtec_ep_csr_read32(
struct switchtec_dev *dev, uint16_t pdfid,
1284 uint16_t addr, uint32_t *val)
1288 ret = ep_csr_read(dev, pdfid, val, addr, 4);
1289 *val = le32toh(*val);
1294static int ep_csr_write(
struct switchtec_dev *dev, uint16_t pdfid,
1295 uint16_t addr,
const void *val,
size_t n)
1297 if (n > SWITCHTEC_EP_CSR_MAX_WRITE_LEN)
1298 n = SWITCHTEC_EP_CSR_MAX_WRITE_LEN;
1303 struct ep_cfg_write {
1313 .pdfid = htole16(pdfid),
1314 .addr = htole16(addr),
1318 memcpy(&cmd.data, val, n);
1321 sizeof(cmd), NULL, 0);
1324int switchtec_ep_csr_write8(
struct switchtec_dev *dev, uint16_t pdfid,
1325 uint8_t val, uint16_t addr)
1327 return ep_csr_write(dev, pdfid, addr, &val, 1);
1330int switchtec_ep_csr_write16(
struct switchtec_dev *dev, uint16_t pdfid,
1331 uint16_t val, uint16_t addr)
1334 return ep_csr_write(dev, pdfid, addr, &val, 2);
1337int switchtec_ep_csr_write32(
struct switchtec_dev *dev, uint16_t pdfid,
1338 uint32_t val, uint16_t addr)
1341 return ep_csr_write(dev, pdfid, addr, &val, 4);
1344static size_t ep_bar_read(
struct switchtec_dev *dev, uint16_t pdfid,
1345 uint8_t bar,
void *dest,
1346 uint64_t src,
size_t n)
1348 if (n > SWITCHTEC_EP_BAR_MAX_READ_LEN)
1349 n = SWITCHTEC_EP_BAR_MAX_READ_LEN;
1356 struct ep_bar_read {
1367 .pdfid = htole16(pdfid),
1369 .addr_low = (uint32_t)src,
1370 .addr_high = (uint32_t)(src >> 32),
1371 .bytes= htole16((uint16_t)n),
1375 sizeof(cmd), dest, n);
1378int switchtec_ep_bar_read8(
struct switchtec_dev *dev, uint16_t pdfid,
1379 uint8_t bar, uint64_t addr, uint8_t *val)
1381 return ep_bar_read(dev, pdfid, bar, val, addr, 1);
1384int switchtec_ep_bar_read16(
struct switchtec_dev *dev, uint16_t pdfid,
1385 uint8_t bar, uint64_t addr, uint16_t *val)
1389 ret = ep_bar_read(dev, pdfid, bar, val, addr, 2);
1390 *val = le16toh(*val);
1395int switchtec_ep_bar_read32(
struct switchtec_dev *dev, uint16_t pdfid,
1396 uint8_t bar, uint64_t addr, uint32_t *val)
1400 ret = ep_bar_read(dev, pdfid, bar, val, addr, 4);
1401 *val = le32toh(*val);
1406int switchtec_ep_bar_read64(
struct switchtec_dev *dev, uint16_t pdfid,
1407 uint8_t bar, uint64_t addr, uint64_t *val)
1411 ret = ep_bar_read(dev, pdfid, bar, val, addr, 8);
1412 *val = le64toh(*val);
1417static int ep_bar_write(
struct switchtec_dev *dev, uint16_t pdfid,
1418 uint8_t bar, uint64_t addr,
1419 const void *val,
size_t n)
1421 if (n > SWITCHTEC_EP_BAR_MAX_WRITE_LEN)
1422 n = SWITCHTEC_EP_BAR_MAX_WRITE_LEN;
1427 addr = htole64(addr);
1429 struct ep_bar_write {
1441 .pdfid = htole16(pdfid),
1443 .bytes= htole16((uint16_t)n),
1444 .addr_low = (uint32_t)addr,
1445 .addr_high = (uint32_t)(addr >> 32),
1448 memcpy(&cmd.data, val, n);
1451 &cmd,
sizeof(cmd), NULL, 0);
1454int switchtec_ep_bar_write8(
struct switchtec_dev *dev, uint16_t pdfid,
1455 uint8_t bar, uint8_t val, uint64_t addr)
1457 return ep_bar_write(dev, pdfid, bar, addr, &val, 1);
1460int switchtec_ep_bar_write16(
struct switchtec_dev *dev, uint16_t pdfid,
1461 uint8_t bar, uint16_t val, uint64_t addr)
1464 return ep_bar_write(dev, pdfid, bar, addr, &val, 2);
1467int switchtec_ep_bar_write32(
struct switchtec_dev *dev, uint16_t pdfid,
1468 uint8_t bar, uint32_t val, uint64_t addr)
1471 return ep_bar_write(dev, pdfid, bar, addr, &val, 4);
1474int switchtec_ep_bar_write64(
struct switchtec_dev *dev, uint16_t pdfid,
1475 uint8_t bar, uint64_t val, uint64_t addr)
1478 return ep_bar_write(dev, pdfid, bar, addr, &val, 8);
1481static int admin_passthru_start(
struct switchtec_dev *dev, uint16_t pdfid,
1482 size_t data_len,
void *data,
1487 uint16_t offset = 0;
1493 uint16_t expected_rsp_len;
1496 uint16_t data_offset;
1498 uint8_t data[MRPC_MAX_DATA_LEN - 16];
1500 .subcmd = MRPC_NVME_ADMIN_PASSTHRU_START,
1501 .pdfid = htole16(pdfid)
1509 if (data_len && data != NULL) {
1510 cmd.more_data = data_len >
sizeof(cmd.data);
1511 while (cmd.more_data) {
1512 copy_len =
sizeof(cmd.data);
1513 memcpy(cmd.data, data + offset, copy_len);
1515 cmd.data_offset = htole16(offset);
1516 cmd.data_len = htole16(copy_len);
1519 &cmd,
sizeof(cmd), NULL, 0);
1524 data_len -= copy_len;
1525 cmd.more_data = data_len >
sizeof(cmd.data);
1529 memcpy(cmd.data, data + offset, data_len);
1531 cmd.data_offset = htole16(offset);
1532 cmd.data_len = htole16(data_len);
1535 cmd.data_offset = 0;
1539 cmd.expected_rsp_len = htole16(*rsp_len);
1542 &cmd,
sizeof(cmd), &reply,
sizeof(reply));
1548 *rsp_len = le16toh(reply.rsp_len);
1552static int admin_passthru_data(
struct switchtec_dev *dev, uint16_t pdfid,
1553 size_t rsp_len,
void *rsp)
1563 .subcmd = MRPC_NVME_ADMIN_PASSTHRU_DATA,
1564 .pdfid = htole16(pdfid),
1570 uint8_t data[MRPC_MAX_DATA_LEN - 4];
1573 while (offset < rsp_len) {
1574 cmd.offset = htole16(offset);
1577 &cmd,
sizeof(cmd), &reply,
1582 memcpy((uint8_t*)rsp + offset, reply.data,
1583 htole16(reply.len));
1584 offset += htole16(reply.len);
1590static int admin_passthru_end(
struct switchtec_dev *dev, uint16_t pdfid)
1599 cmd.subcmd = MRPC_NVME_ADMIN_PASSTHRU_END;
1600 cmd.pdfid = htole16(pdfid);
1603 &cmd,
sizeof(cmd), NULL, 0);
1616int switchtec_nvme_admin_passthru(
struct switchtec_dev *dev, uint16_t pdfid,
1617 size_t data_len,
void *data,
1618 size_t *rsp_len,
void *rsp)
1622 ret = admin_passthru_start(dev, pdfid, data_len, data, rsp_len);
1626 if (*rsp_len && rsp != NULL) {
1627 ret = admin_passthru_data(dev, pdfid, *rsp_len, rsp);
1634 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 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).