| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | | - * |
|---|
| 3 | + * Copyright (c) 2003-2019, Intel Corporation. All rights reserved. |
|---|
| 3 | 4 | * Intel Management Engine Interface (Intel MEI) Linux driver |
|---|
| 4 | | - * Copyright (c) 2003-2018, Intel Corporation. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 7 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 8 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 13 | | - * more details. |
|---|
| 14 | | - * |
|---|
| 15 | 5 | */ |
|---|
| 16 | 6 | |
|---|
| 17 | 7 | #ifndef _MEI_DEV_H_ |
|---|
| .. | .. |
|---|
| 122 | 112 | unsigned char *data; |
|---|
| 123 | 113 | }; |
|---|
| 124 | 114 | |
|---|
| 115 | +/** |
|---|
| 116 | + * struct mei_dma_dscr - dma address descriptor |
|---|
| 117 | + * |
|---|
| 118 | + * @vaddr: dma buffer virtual address |
|---|
| 119 | + * @daddr: dma buffer physical address |
|---|
| 120 | + * @size : dma buffer size |
|---|
| 121 | + */ |
|---|
| 122 | +struct mei_dma_dscr { |
|---|
| 123 | + void *vaddr; |
|---|
| 124 | + dma_addr_t daddr; |
|---|
| 125 | + size_t size; |
|---|
| 126 | +}; |
|---|
| 127 | + |
|---|
| 125 | 128 | /* Maximum number of processed FW status registers */ |
|---|
| 126 | 129 | #define MEI_FW_STATUS_MAX 6 |
|---|
| 127 | 130 | /* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */ |
|---|
| .. | .. |
|---|
| 171 | 174 | * @fop_type: file operation type |
|---|
| 172 | 175 | * @buf: buffer for data associated with the callback |
|---|
| 173 | 176 | * @buf_idx: last read index |
|---|
| 177 | + * @vtag: virtual tag |
|---|
| 174 | 178 | * @fp: pointer to file structure |
|---|
| 175 | 179 | * @status: io status of the cb |
|---|
| 176 | 180 | * @internal: communication between driver and FW flag |
|---|
| .. | .. |
|---|
| 182 | 186 | enum mei_cb_file_ops fop_type; |
|---|
| 183 | 187 | struct mei_msg_data buf; |
|---|
| 184 | 188 | size_t buf_idx; |
|---|
| 189 | + u8 vtag; |
|---|
| 185 | 190 | const struct file *fp; |
|---|
| 186 | 191 | int status; |
|---|
| 187 | 192 | u32 internal:1; |
|---|
| 188 | 193 | u32 blocking:1; |
|---|
| 194 | +}; |
|---|
| 195 | + |
|---|
| 196 | +/** |
|---|
| 197 | + * struct mei_cl_vtag - file pointer to vtag mapping structure |
|---|
| 198 | + * |
|---|
| 199 | + * @list: link in map queue |
|---|
| 200 | + * @fp: file pointer |
|---|
| 201 | + * @vtag: corresponding vtag |
|---|
| 202 | + * @pending_read: the read is pending on this file |
|---|
| 203 | + */ |
|---|
| 204 | +struct mei_cl_vtag { |
|---|
| 205 | + struct list_head list; |
|---|
| 206 | + const struct file *fp; |
|---|
| 207 | + u8 vtag; |
|---|
| 208 | + u8 pending_read:1; |
|---|
| 189 | 209 | }; |
|---|
| 190 | 210 | |
|---|
| 191 | 211 | /** |
|---|
| .. | .. |
|---|
| 204 | 224 | * @me_cl: fw client connected |
|---|
| 205 | 225 | * @fp: file associated with client |
|---|
| 206 | 226 | * @host_client_id: host id |
|---|
| 227 | + * @vtag_map: vtag map |
|---|
| 207 | 228 | * @tx_flow_ctrl_creds: transmit flow credentials |
|---|
| 208 | 229 | * @rx_flow_ctrl_creds: receive flow credentials |
|---|
| 209 | 230 | * @timer_count: watchdog timer for operation completion |
|---|
| .. | .. |
|---|
| 212 | 233 | * @tx_cb_queued: number of tx callbacks in queue |
|---|
| 213 | 234 | * @writing_state: state of the tx |
|---|
| 214 | 235 | * @rd_pending: pending read credits |
|---|
| 236 | + * @rd_completed_lock: protects rd_completed queue |
|---|
| 215 | 237 | * @rd_completed: completed read |
|---|
| 216 | 238 | * |
|---|
| 217 | 239 | * @cldev: device on the mei client bus |
|---|
| .. | .. |
|---|
| 229 | 251 | struct mei_me_client *me_cl; |
|---|
| 230 | 252 | const struct file *fp; |
|---|
| 231 | 253 | u8 host_client_id; |
|---|
| 254 | + struct list_head vtag_map; |
|---|
| 232 | 255 | u8 tx_flow_ctrl_creds; |
|---|
| 233 | 256 | u8 rx_flow_ctrl_creds; |
|---|
| 234 | 257 | u8 timer_count; |
|---|
| .. | .. |
|---|
| 237 | 260 | u8 tx_cb_queued; |
|---|
| 238 | 261 | enum mei_file_transaction_states writing_state; |
|---|
| 239 | 262 | struct list_head rd_pending; |
|---|
| 263 | + spinlock_t rd_completed_lock; /* protects rd_completed queue */ |
|---|
| 240 | 264 | struct list_head rd_completed; |
|---|
| 241 | 265 | |
|---|
| 242 | 266 | struct mei_cl_device *cldev; |
|---|
| .. | .. |
|---|
| 257 | 281 | * @hw_config : configure hw |
|---|
| 258 | 282 | * |
|---|
| 259 | 283 | * @fw_status : get fw status registers |
|---|
| 284 | + * @trc_status : get trc status register |
|---|
| 260 | 285 | * @pg_state : power gating state of the device |
|---|
| 261 | 286 | * @pg_in_transition : is device now in pg transition |
|---|
| 262 | 287 | * @pg_is_enabled : is power gating enabled |
|---|
| .. | .. |
|---|
| 284 | 309 | bool (*hw_is_ready)(struct mei_device *dev); |
|---|
| 285 | 310 | int (*hw_reset)(struct mei_device *dev, bool enable); |
|---|
| 286 | 311 | int (*hw_start)(struct mei_device *dev); |
|---|
| 287 | | - void (*hw_config)(struct mei_device *dev); |
|---|
| 312 | + int (*hw_config)(struct mei_device *dev); |
|---|
| 288 | 313 | |
|---|
| 289 | 314 | int (*fw_status)(struct mei_device *dev, struct mei_fw_status *fw_sts); |
|---|
| 315 | + int (*trc_status)(struct mei_device *dev, u32 *trc); |
|---|
| 316 | + |
|---|
| 290 | 317 | enum mei_pg_state (*pg_state)(struct mei_device *dev); |
|---|
| 291 | 318 | bool (*pg_in_transition)(struct mei_device *dev); |
|---|
| 292 | 319 | bool (*pg_is_enabled)(struct mei_device *dev); |
|---|
| .. | .. |
|---|
| 407 | 434 | * |
|---|
| 408 | 435 | * @rd_msg_buf : control messages buffer |
|---|
| 409 | 436 | * @rd_msg_hdr : read message header storage |
|---|
| 437 | + * @rd_msg_hdr_count : how many dwords were already read from header |
|---|
| 410 | 438 | * |
|---|
| 411 | 439 | * @hbuf_is_ready : query if the host host/write buffer is ready |
|---|
| 440 | + * @dr_dscr: DMA ring descriptors: TX, RX, and CTRL |
|---|
| 412 | 441 | * |
|---|
| 413 | 442 | * @version : HBM protocol version in use |
|---|
| 414 | 443 | * @hbm_f_pg_supported : hbm feature pgi protocol |
|---|
| .. | .. |
|---|
| 419 | 448 | * @hbm_f_ie_supported : hbm feature immediate reply to enum request |
|---|
| 420 | 449 | * @hbm_f_os_supported : hbm feature support OS ver message |
|---|
| 421 | 450 | * @hbm_f_dr_supported : hbm feature dma ring supported |
|---|
| 451 | + * @hbm_f_vt_supported : hbm feature vtag supported |
|---|
| 452 | + * @hbm_f_cap_supported : hbm feature capabilities message supported |
|---|
| 422 | 453 | * |
|---|
| 423 | 454 | * @fw_ver : FW versions |
|---|
| 424 | 455 | * |
|---|
| .. | .. |
|---|
| 437 | 468 | * |
|---|
| 438 | 469 | * @device_list : mei client bus list |
|---|
| 439 | 470 | * @cl_bus_lock : client bus list lock |
|---|
| 471 | + * |
|---|
| 472 | + * @kind : kind of mei device |
|---|
| 440 | 473 | * |
|---|
| 441 | 474 | * @dbgfs_dir : debugfs mei root directory |
|---|
| 442 | 475 | * |
|---|
| .. | .. |
|---|
| 485 | 518 | #endif /* CONFIG_PM */ |
|---|
| 486 | 519 | |
|---|
| 487 | 520 | unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; |
|---|
| 488 | | - u32 rd_msg_hdr; |
|---|
| 521 | + u32 rd_msg_hdr[MEI_RD_MSG_BUF_SIZE]; |
|---|
| 522 | + int rd_msg_hdr_count; |
|---|
| 489 | 523 | |
|---|
| 490 | 524 | /* write buffer */ |
|---|
| 491 | 525 | bool hbuf_is_ready; |
|---|
| 526 | + |
|---|
| 527 | + struct mei_dma_dscr dr_dscr[DMA_DSCR_NUM]; |
|---|
| 492 | 528 | |
|---|
| 493 | 529 | struct hbm_version version; |
|---|
| 494 | 530 | unsigned int hbm_f_pg_supported:1; |
|---|
| .. | .. |
|---|
| 499 | 535 | unsigned int hbm_f_ie_supported:1; |
|---|
| 500 | 536 | unsigned int hbm_f_os_supported:1; |
|---|
| 501 | 537 | unsigned int hbm_f_dr_supported:1; |
|---|
| 538 | + unsigned int hbm_f_vt_supported:1; |
|---|
| 539 | + unsigned int hbm_f_cap_supported:1; |
|---|
| 502 | 540 | |
|---|
| 503 | 541 | struct mei_fw_version fw_ver[MEI_MAX_FW_VER_BLOCKS]; |
|---|
| 504 | 542 | |
|---|
| .. | .. |
|---|
| 519 | 557 | struct list_head device_list; |
|---|
| 520 | 558 | struct mutex cl_bus_lock; |
|---|
| 521 | 559 | |
|---|
| 560 | + const char *kind; |
|---|
| 561 | + |
|---|
| 522 | 562 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
|---|
| 523 | 563 | struct dentry *dbgfs_dir; |
|---|
| 524 | 564 | #endif /* CONFIG_DEBUG_FS */ |
|---|
| 525 | 565 | |
|---|
| 526 | | - |
|---|
| 527 | 566 | const struct mei_hw_ops *ops; |
|---|
| 528 | | - char hw[0] __aligned(sizeof(void *)); |
|---|
| 567 | + char hw[] __aligned(sizeof(void *)); |
|---|
| 529 | 568 | }; |
|---|
| 530 | 569 | |
|---|
| 531 | 570 | static inline unsigned long mei_secs_to_jiffies(unsigned long sec) |
|---|
| .. | .. |
|---|
| 582 | 621 | void mei_stop(struct mei_device *dev); |
|---|
| 583 | 622 | void mei_cancel_work(struct mei_device *dev); |
|---|
| 584 | 623 | |
|---|
| 624 | +void mei_set_devstate(struct mei_device *dev, enum mei_dev_state state); |
|---|
| 625 | + |
|---|
| 626 | +int mei_dmam_ring_alloc(struct mei_device *dev); |
|---|
| 627 | +void mei_dmam_ring_free(struct mei_device *dev); |
|---|
| 628 | +bool mei_dma_ring_is_allocated(struct mei_device *dev); |
|---|
| 629 | +void mei_dma_ring_reset(struct mei_device *dev); |
|---|
| 630 | +void mei_dma_ring_read(struct mei_device *dev, unsigned char *buf, u32 len); |
|---|
| 631 | +void mei_dma_ring_write(struct mei_device *dev, unsigned char *buf, u32 len); |
|---|
| 632 | +u32 mei_dma_ring_empty_slots(struct mei_device *dev); |
|---|
| 633 | + |
|---|
| 585 | 634 | /* |
|---|
| 586 | 635 | * MEI interrupt functions prototype |
|---|
| 587 | 636 | */ |
|---|
| .. | .. |
|---|
| 599 | 648 | */ |
|---|
| 600 | 649 | |
|---|
| 601 | 650 | |
|---|
| 602 | | -static inline void mei_hw_config(struct mei_device *dev) |
|---|
| 651 | +static inline int mei_hw_config(struct mei_device *dev) |
|---|
| 603 | 652 | { |
|---|
| 604 | | - dev->ops->hw_config(dev); |
|---|
| 653 | + return dev->ops->hw_config(dev); |
|---|
| 605 | 654 | } |
|---|
| 606 | 655 | |
|---|
| 607 | 656 | static inline enum mei_pg_state mei_pg_state(struct mei_device *dev) |
|---|
| .. | .. |
|---|
| 696 | 745 | return dev->ops->rdbuf_full_slots(dev); |
|---|
| 697 | 746 | } |
|---|
| 698 | 747 | |
|---|
| 748 | +static inline int mei_trc_status(struct mei_device *dev, u32 *trc) |
|---|
| 749 | +{ |
|---|
| 750 | + if (dev->ops->trc_status) |
|---|
| 751 | + return dev->ops->trc_status(dev, trc); |
|---|
| 752 | + return -EOPNOTSUPP; |
|---|
| 753 | +} |
|---|
| 754 | + |
|---|
| 699 | 755 | static inline int mei_fw_status(struct mei_device *dev, |
|---|
| 700 | 756 | struct mei_fw_status *fw_status) |
|---|
| 701 | 757 | { |
|---|
| .. | .. |
|---|
| 707 | 763 | bool mei_write_is_idle(struct mei_device *dev); |
|---|
| 708 | 764 | |
|---|
| 709 | 765 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
|---|
| 710 | | -int mei_dbgfs_register(struct mei_device *dev, const char *name); |
|---|
| 766 | +void mei_dbgfs_register(struct mei_device *dev, const char *name); |
|---|
| 711 | 767 | void mei_dbgfs_deregister(struct mei_device *dev); |
|---|
| 712 | 768 | #else |
|---|
| 713 | | -static inline int mei_dbgfs_register(struct mei_device *dev, const char *name) |
|---|
| 714 | | -{ |
|---|
| 715 | | - return 0; |
|---|
| 716 | | -} |
|---|
| 769 | +static inline void mei_dbgfs_register(struct mei_device *dev, const char *name) {} |
|---|
| 717 | 770 | static inline void mei_dbgfs_deregister(struct mei_device *dev) {} |
|---|
| 718 | 771 | #endif /* CONFIG_DEBUG_FS */ |
|---|
| 719 | 772 | |
|---|
| 720 | 773 | int mei_register(struct mei_device *dev, struct device *parent); |
|---|
| 721 | 774 | void mei_deregister(struct mei_device *dev); |
|---|
| 722 | 775 | |
|---|
| 723 | | -#define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d dma=%1d internal=%1d comp=%1d" |
|---|
| 776 | +#define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d dma=%1d ext=%1d internal=%1d comp=%1d" |
|---|
| 724 | 777 | #define MEI_HDR_PRM(hdr) \ |
|---|
| 725 | 778 | (hdr)->host_addr, (hdr)->me_addr, \ |
|---|
| 726 | | - (hdr)->length, (hdr)->dma_ring, (hdr)->internal, (hdr)->msg_complete |
|---|
| 779 | + (hdr)->length, (hdr)->dma_ring, (hdr)->extended, \ |
|---|
| 780 | + (hdr)->internal, (hdr)->msg_complete |
|---|
| 727 | 781 | |
|---|
| 728 | 782 | ssize_t mei_fw_status2str(struct mei_fw_status *fw_sts, char *buf, size_t len); |
|---|
| 729 | 783 | /** |
|---|