net: wwan: t7xx: fw flashing & coredump support
Subsystems (6)
v4 cover net: wwan: t7xx: fw flashing & coredump support
From: M Chetan Kumar <[email protected]>
This patch series brings-in the support for FM350 wwan device firmware flashing & coredump collection using devlink interface.
Below is the high level description of individual patches. Refer to individual patch commit message for details.
PATCH1: Enables AP CLDMA communication for firmware flashing & coredump collection.
PATCH2: Enables the infrastructure & queue configuration required for early ports enumeration.
PATCH3: Implements device reset and rescan logic required to enter or exit fastboot mode.
PATCH4: Implements devlink interface & uses the fastboot protocol for fw flashing and coredump collection.
PATCH5: t7xx devlink commands documentation.
Version History:
================
v4: Address review comments given by Jesse Brandeburg & Bagas Sanjaya.
v3: Repost the series by setting format.thread git-config option to
shallow as suggested by Brandeburg, Jesse.
v2: Address review comments given by Jarvinen, Ilpo Johannes and
Sergey Ryazanov. Refer to Individual patches on v2 changes.
v1: Initial Version.
Haijun Liu (1):
net: wwan: t7xx: Add AP CLDMA
M Chetan Kumar (4):
net: wwan: t7xx: Infrastructure for early port configuration
net: wwan: t7xx: PCIe reset rescan
net: wwan: t7xx: Enable devlink based fw flashing and coredump
collection
net: wwan: t7xx: Devlink documentation
Documentation/networking/devlink/index.rst | 1 + Documentation/networking/devlink/t7xx.rst | 224 +++++++ drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/t7xx/Makefile | 5 +- drivers/net/wwan/t7xx/t7xx_hif_cldma.c | 64 +- drivers/net/wwan/t7xx/t7xx_hif_cldma.h | 20 +- drivers/net/wwan/t7xx/t7xx_mhccif.h | 1 + drivers/net/wwan/t7xx/t7xx_modem_ops.c | 81 ++- drivers/net/wwan/t7xx/t7xx_modem_ops.h | 2 + drivers/net/wwan/t7xx/t7xx_pci.c | 72 ++- drivers/net/wwan/t7xx/t7xx_pci.h | 2 + drivers/net/wwan/t7xx/t7xx_pci_rescan.c | 96 +++ drivers/net/wwan/t7xx/t7xx_pci_rescan.h | 28 + drivers/net/wwan/t7xx/t7xx_port.h | 12 +- drivers/net/wwan/t7xx/t7xx_port_ap_msg.c | 79 +++ drivers/net/wwan/t7xx/t7xx_port_ap_msg.h | 11 + drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c | 8 +- drivers/net/wwan/t7xx/t7xx_port_devlink.c | 669 +++++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_port_devlink.h | 86 +++ drivers/net/wwan/t7xx/t7xx_port_proxy.c | 135 ++++- drivers/net/wwan/t7xx/t7xx_port_proxy.h | 16 +- drivers/net/wwan/t7xx/t7xx_port_wwan.c | 25 +- drivers/net/wwan/t7xx/t7xx_reg.h | 30 +- drivers/net/wwan/t7xx/t7xx_state_monitor.c | 133 +++- drivers/net/wwan/t7xx/t7xx_state_monitor.h | 3 + 25 files changed, 1700 insertions(+), 104 deletions(-) create mode 100644 Documentation/networking/devlink/t7xx.rst create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.c create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.h create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.h create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.h
--
2.34.1
PATCH v4 1/5 net: wwan: t7xx: Add AP CLDMA
From: Haijun Liu <[email protected]>
The t7xx device contains two Cross Layer DMA (CLDMA) interfaces to communicate with AP and Modem processors respectively. So far only MD-CLDMA was being used, this patch enables AP-CLDMA.
Rename small Application Processor (sAP) to AP.
--
v4:
* No Change.
v3:
* No Change.
v2:
* Reuse handshake_wq for AP work.
* Remove AP trace port tx/rx channel id.
* Rename t7xx_md_port_conf to t7xx_port_conf.
--- drivers/net/wwan/t7xx/t7xx_hif_cldma.c | 17 +++-- drivers/net/wwan/t7xx/t7xx_hif_cldma.h | 2 +- drivers/net/wwan/t7xx/t7xx_mhccif.h | 1 + drivers/net/wwan/t7xx/t7xx_modem_ops.c | 76 +++++++++++++++++----- drivers/net/wwan/t7xx/t7xx_modem_ops.h | 2 + drivers/net/wwan/t7xx/t7xx_port.h | 6 +- drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c | 8 ++- drivers/net/wwan/t7xx/t7xx_port_proxy.c | 18 ++++- drivers/net/wwan/t7xx/t7xx_reg.h | 2 +- drivers/net/wwan/t7xx/t7xx_state_monitor.c | 13 +++- drivers/net/wwan/t7xx/t7xx_state_monitor.h | 2 + 11 files changed, 116 insertions(+), 31 deletions(-)
drivers/net/wwan/t7xx/t7xx_hif_cldma.c +11 -6
@@ -1066,13 +1066,18 @@ static void t7xx_hw_info_init(struct cldma_ctrl *md_ctrl)struct t7xx_cldma_hw *hw_info = &md_ctrl->hw_info;u32 phy_ao_base, phy_pd_base; -if (md_ctrl->hif_id !=CLDMA_ID_MD ) -return ; - - phy_ao_base =CLDMA1_AO_BASE ; - phy_pd_base =CLDMA1_PD_BASE ; - hw_info->phy_interrupt_id =CLDMA1_INT ; hw_info->hw_mode =MODE_BIT_64 ; + +if (md_ctrl->hif_id ==CLDMA_ID_MD ) { + phy_ao_base =CLDMA1_AO_BASE ; + phy_pd_base =CLDMA1_PD_BASE ; + hw_info->phy_interrupt_id =CLDMA1_INT ; + }else { + phy_ao_base =CLDMA0_AO_BASE ; + phy_pd_base =CLDMA0_PD_BASE ; + hw_info->phy_interrupt_id =CLDMA0_INT ; + } + hw_info->ap_ao_base =t7xx_pcie_addr_transfer (pbase->pcie_ext_reg_base, pbase->pcie_dev_reg_trsl_addr, phy_ao_base); hw_info->ap_pdn_base = t7xx_pcie_addr_transfer(pbase->pcie_ext_reg_base,
drivers/net/wwan/t7xx/t7xx_hif_cldma.h +1 -1
@@ -34,7 +34,7 @@/** * enum cldma_id - Identifiers for CLDMA HW units. * @CLDMA_ID_MD: Modem control channel. -* @CLDMA_ID_AP: Application Processor control channel (not used at the moment). +* @CLDMA_ID_AP: Application Processor control channel. * @CLDMA_NUM: Number of CLDMA HW units available. */ enum cldma_id {
drivers/net/wwan/t7xx/t7xx_mhccif.h +1 -0
@@ -25,6 +25,7 @@ D2H_INT_EXCEPTION_CLEARQ_DONE | \ D2H_INT_EXCEPTION_ALLQ_RESET | \ D2H_INT_PORT_ENUM | \ + D2H_INT_ASYNC_AP_HK | \ D2H_INT_ASYNC_MD_HK)void t7xx_mhccif_mask_set (struct t7xx_pci_dev *t7xx_dev,u32 val);
drivers/net/wwan/t7xx/t7xx_modem_ops.c +61 -15
175 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_modem_ops.h +2 -0
@@ -66,10 +66,12 @@ struct t7xx_modem {struct cldma_ctrl *md_ctrl[CLDMA_NUM ];struct t7xx_pci_dev *t7xx_dev;struct t7xx_sys_info core_md; +struct t7xx_sys_info core_ap;bool md_init_finish;bool rgu_irq_asserted;struct workqueue_struct *handshake_wq;struct work_struct handshake_work; +struct work_struct ap_handshake_work;struct t7xx_fsm_ctl *fsm_ctl;struct port_proxy *port_prox;unsigned int exp_id;
drivers/net/wwan/t7xx/t7xx_port.h +5 -1
@@ -36,9 +36,13 @@/* Channel ID and Message ID definitions. * The channel number consists of peer_id(15:12) , channel_id(11:0) * peer_id: -* 0:reserved, 1: to sAP, 2: to MD +* 0:reserved, 1: to AP, 2: to MD */ enum port_ch { +/* to AP */ +PORT_CH_AP_CONTROL_RX =0x1000 , +PORT_CH_AP_CONTROL_TX =0x1001 , +/* to MD */ PORT_CH_CONTROL_RX =0x2000 ,PORT_CH_CONTROL_TX =0x2001 ,
drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c +6 -2
@@ -167,8 +167,12 @@ static int control_msg_handler(struct t7xx_port *port, struct sk_buff *skb)case CTL_ID_HS2_MSG :skb_pull (skb,sizeof (*ctrl_msg_h)); -if (port_conf->rx_ch ==PORT_CH_CONTROL_RX ) { - ret =t7xx_fsm_append_event (ctl,FSM_EVENT_MD_HS2 , skb->data, +if (port_conf->rx_ch ==PORT_CH_CONTROL_RX || + port_conf->rx_ch ==PORT_CH_AP_CONTROL_RX ) { +int event = port_conf->rx_ch ==PORT_CH_CONTROL_RX ? +FSM_EVENT_MD_HS2 :FSM_EVENT_AP_HS2 ; + + ret =t7xx_fsm_append_event (ctl, event, skb->data,le32_to_cpu (ctrl_msg_h->data_length));if (ret)dev_err (port->dev,"Failed to append Handshake 2 event" );
drivers/net/wwan/t7xx/t7xx_port_proxy.c +15 -3
@@ -48,7 +48,7 @@ i < (proxy)->port_count; \ i++, (p) = &(proxy)->ports[i]) -static const struct t7xx_port_conf t7xx_md_port_conf[] = { +static const struct t7xx_port_conf t7xx_port_conf[] = { { .tx_ch =PORT_CH_UART2_TX , .rx_ch =PORT_CH_UART2_RX ,
@@ -89,6 +89,14 @@ static const struct t7xx_port_conf t7xx_md_port_conf[] = { .path_id = CLDMA_ID_MD, .ops = &ctl_port_ops, .name = "t7xx_ctrl", + }, { + .tx_ch = PORT_CH_AP_CONTROL_TX, + .rx_ch = PORT_CH_AP_CONTROL_RX, + .txq_index = Q_IDX_CTRL, + .rxq_index = Q_IDX_CTRL, + .path_id = CLDMA_ID_AP, + .ops = &ctl_port_ops, + .name = "t7xx_ap_ctrl", }, };
@@ -428,6 +436,9 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)if (port_conf->tx_ch ==PORT_CH_CONTROL_TX ) md->core_md.ctl_port = port; +if (port_conf->tx_ch ==PORT_CH_AP_CONTROL_TX ) + md->core_ap.ctl_port = port; + port->t7xx_dev = md->t7xx_dev; port->dev = &md->t7xx_dev->pdev->dev;spin_lock_init (&port->port_update_lock);
@@ -442,7 +453,7 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)static int t7xx_proxy_alloc (struct t7xx_modem *md) { -unsigned int port_count =ARRAY_SIZE (t7xx_md_port_conf); +unsigned int port_count =ARRAY_SIZE (t7xx_port_conf);struct device *dev = &md->t7xx_dev->pdev->dev;struct port_proxy *port_prox;int i;
@@ -456,7 +467,7 @@ static int t7xx_proxy_alloc(struct t7xx_modem *md) port_prox->dev = dev;for (i =0 ; i < port_count; i++) - port_prox->ports[i].port_conf = &t7xx_md_port_conf[i]; + port_prox->ports[i].port_conf = &t7xx_port_conf[i]; port_prox->port_count = port_count;t7xx_proxy_init_all_ports (md);
@@ -481,6 +492,7 @@ int t7xx_port_proxy_init(struct t7xx_modem *md)if (ret)return ret; +t7xx_cldma_set_recv_skb (md->md_ctrl[CLDMA_ID_AP ], t7xx_port_proxy_recv_skb);t7xx_cldma_set_recv_skb (md->md_ctrl[CLDMA_ID_MD ], t7xx_port_proxy_recv_skb);return 0 ; }
drivers/net/wwan/t7xx/t7xx_reg.h +1 -1
@@ -56,7 +56,7 @@#define D2H_INT_RESUME_ACK BIT(12)#define D2H_INT_SUSPEND_ACK_AP BIT(13)#define D2H_INT_RESUME_ACK_AP BIT(14) -#define D2H_INT_ASYNC_SAP_HK BIT(15) +#define D2H_INT_ASYNC_AP_HK BIT(15)#define D2H_INT_ASYNC_MD_HK BIT(16)/* Register base */
drivers/net/wwan/t7xx/t7xx_state_monitor.c +11 -2
@@ -285,8 +285,9 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl)t7xx_fsm_broadcast_state (ctl,MD_STATE_WAITING_FOR_HS1 );t7xx_md_event_notify (md,FSM_START ); -wait_event_interruptible_timeout (ctl->async_hk_wq, md->core_md.ready || ctl->exp_flg, -HZ *60 ); +wait_event_interruptible_timeout (ctl->async_hk_wq, + (md->core_md.ready && md->core_ap.ready) || + ctl->exp_flg,HZ *60 ); dev = &md->t7xx_dev->pdev->dev;if (ctl->exp_flg)
@@ -297,6 +298,13 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl)if (md->core_md.handshake_ongoing)t7xx_fsm_append_event (ctl,FSM_EVENT_MD_HS2_EXIT ,NULL ,0 ); +fsm_routine_exception (ctl,NULL ,EXCEPTION_HS_TIMEOUT ); +return -ETIMEDOUT ; + }else if (!md->core_ap.ready) { +dev_err (dev,"AP handshake timeout\n" ); +if (md->core_ap.handshake_ongoing) +t7xx_fsm_append_event (ctl,FSM_EVENT_AP_HS2_EXIT ,NULL ,0 ); +fsm_routine_exception (ctl,NULL ,EXCEPTION_HS_TIMEOUT );return -ETIMEDOUT ; }
@@ -335,6 +343,7 @@ static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commandreturn ; } +t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_AP ]);t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_MD ]);fsm_finish_command (ctl, cmd,fsm_routine_starting (ctl)); }
drivers/net/wwan/t7xx/t7xx_state_monitor.h +2 -0
@@ -38,10 +38,12 @@ enum t7xx_fsm_state {enum t7xx_fsm_event_state {FSM_EVENT_INVALID ,FSM_EVENT_MD_HS2 , +FSM_EVENT_AP_HS2 ,FSM_EVENT_MD_EX ,FSM_EVENT_MD_EX_REC_OK ,FSM_EVENT_MD_EX_PASS ,FSM_EVENT_MD_HS2_EXIT , +FSM_EVENT_AP_HS2_EXIT ,FSM_EVENT_MAX };
Signature · 1 line
2.34.1
PATCH v4 2/5 net: wwan: t7xx: Infrastructure for early port configuration
In reply to [email protected]From: M Chetan Kumar <[email protected]>
To support cases such as FW update or Core dump, the t7xx device is capable of signaling the host that a special port needs to be created before the handshake phase.
Adds the infrastructure required to create the early ports which also requires a different configuration of CLDMA queues.
--
v4:
* Remove "this patch" in commit message.
* MISC_DEV_STATUS_MASK & MISC_DEV_STATUS_INVALID is unused, drop it.
* Drop unnecessary assignement for ret var inside fsm_routine_start.
* cppcheck - reduce variableScope for stage var in fsm_routine_start.
v3:
* No Change.
v2:
* Move recv_skb handler to cldma_queue.
* Drop cldma_queue_type.
* Restore prototype of t7xx_port_send_raw_skb().
* Remove PORT_CFG_ID_INVALID check in t7xx_port_proxy_set_cfg().
* Add space before */.
* Drop unnecessary logs.
* Use WARN_ON on early port.
* Use new MISC_DEV_STATUS_INVALID instead of MISC_DEV_STATUS.
* Use macros instead of const identifiers.
* Change ports member type from pointer to array type.
* Prefix LK_EVENT_XX with MISC prefix.
* Use t7xx prefix for device_stage enums.
* Correct log messages.
* Dont override pkt_size for non-download port under dedicated Queue.
* Drop cldma_txq_rxq_ids.
* Use macro for txq/rxq index.
* Use warn_on for rxq_idx comparison.
* Drop t7xx_port_proxy_get_port_by_name().
* Replace fsm poll with read_poll_timeout().
* Use "\n" consistently across log message.
* Remove local var _dev prefixes in fsm_routine_start().
* Use max_t.
--- drivers/net/wwan/t7xx/t7xx_hif_cldma.c | 47 ++++++++---- drivers/net/wwan/t7xx/t7xx_hif_cldma.h | 18 +++-- drivers/net/wwan/t7xx/t7xx_modem_ops.c | 4 +- drivers/net/wwan/t7xx/t7xx_port.h | 4 + drivers/net/wwan/t7xx/t7xx_port_proxy.c | 89 +++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_port_proxy.h | 12 ++- drivers/net/wwan/t7xx/t7xx_port_wwan.c | 3 +- drivers/net/wwan/t7xx/t7xx_reg.h | 22 +++++- drivers/net/wwan/t7xx/t7xx_state_monitor.c | 85 ++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_state_monitor.h | 1 + 10 files changed, 235 insertions(+), 50 deletions(-)
drivers/net/wwan/t7xx/t7xx_hif_cldma.c +32 -15
@@ -57,8 +57,6 @@#define CHECK_Q_STOP_TIMEOUT_US 1000000#define CHECK_Q_STOP_STEP_US 10000 -#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) -static void md_cd_queue_struct_reset (struct cldma_queue *queue,struct cldma_ctrl *md_ctrl,enum mtk_txrx tx_rx,unsigned int index) {
@@ -161,7 +159,7 @@ static int t7xx_cldma_gpd_rx_from_q(struct cldma_queue *queue, int budget, boolskb_reset_tail_pointer (skb);skb_put (skb,le16_to_cpu (gpd->data_buff_len)); - ret = md_ctrl->recv_skb (queue, skb); + ret = queue->recv_skb (queue, skb);/* Break processing, will try again later */ if (ret <0 )return ret;
@@ -897,13 +895,13 @@ static void t7xx_cldma_hw_start_send(struct cldma_ctrl *md_ctrl, int qno,/** * t7xx_cldma_set_recv_skb() - Set the callback to handle RX packets. -* @md_ctrl: CLDMA context structure. +* @queue: CLDMA queue. * @recv_skb: Receiving skb callback. */ -void t7xx_cldma_set_recv_skb (struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb (struct cldma_queue *queue,int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb)) { - md_ctrl->recv_skb = recv_skb; + queue->recv_skb = recv_skb; }/**
@@ -993,6 +991,28 @@ int t7xx_cldma_send_skb(struct cldma_ctrl *md_ctrl, int qno, struct sk_buff *skbreturn ret; } +static void t7xx_cldma_adjust_config (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id) +{ +int qno; + +for (qno =0 ; qno <CLDMA_RXQ_NUM ; qno++) { + md_ctrl->rx_ring[qno].pkt_size =CLDMA_SHARED_Q_BUFF_SZ ; +t7xx_cldma_set_recv_skb (&md_ctrl->rxq[qno], t7xx_port_proxy_recv_skb); + } + + md_ctrl->rx_ring[CLDMA_RXQ_NUM -1 ].pkt_size =CLDMA_JUMBO_BUFF_SZ ; + +for (qno =0 ; qno <CLDMA_TXQ_NUM ; qno++) + md_ctrl->tx_ring[qno].pkt_size =CLDMA_SHARED_Q_BUFF_SZ ; + +if (cfg_id ==CLDMA_DEDICATED_Q_CFG ) { + md_ctrl->tx_ring[CLDMA_Q_IDX_DUMP ].pkt_size =CLDMA_DEDICATED_Q_BUFF_SZ ; + md_ctrl->rx_ring[CLDMA_Q_IDX_DUMP ].pkt_size =CLDMA_DEDICATED_Q_BUFF_SZ ; +t7xx_cldma_set_recv_skb (&md_ctrl->rxq[CLDMA_Q_IDX_DUMP ], + t7xx_port_proxy_recv_skb_from_dedicated_queue); + } +} +static int t7xx_cldma_late_init (struct cldma_ctrl *md_ctrl) {char dma_pool_name[32 ];
@@ -1018,16 +1038,9 @@ static int t7xx_cldma_late_init(struct cldma_ctrl *md_ctrl)dev_err (md_ctrl->dev,"control TX ring init fail\n" ); goto err_free_tx_ring; } - - md_ctrl->tx_ring[i].pkt_size =CLDMA_MTU ; }for (j =0 ; j <CLDMA_RXQ_NUM ; j++) { - md_ctrl->rx_ring[j].pkt_size =CLDMA_MTU ; - -if (j ==CLDMA_RXQ_NUM -1 ) - md_ctrl->rx_ring[j].pkt_size =CLDMA_JUMBO_BUFF_SZ ; - ret =t7xx_cldma_rx_ring_init (md_ctrl, &md_ctrl->rx_ring[j]);if (ret) {dev_err (md_ctrl->dev,"Control RX ring init fail\n" );
@@ -1094,6 +1107,7 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) {struct device *dev = &t7xx_dev->pdev->dev;struct cldma_ctrl *md_ctrl; +int qno; md_ctrl =devm_kzalloc (dev,sizeof (*md_ctrl),GFP_KERNEL );if (!md_ctrl)
@@ -1102,7 +1116,9 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) md_ctrl->t7xx_dev = t7xx_dev; md_ctrl->dev = dev; md_ctrl->hif_id = hif_id; - md_ctrl->recv_skb = t7xx_cldma_default_recv_skb; +for (qno =0 ; qno <CLDMA_RXQ_NUM ; qno++) + md_ctrl->rxq[qno].recv_skb = t7xx_cldma_default_recv_skb; +t7xx_hw_info_init (md_ctrl); t7xx_dev->md->md_ctrl[hif_id] = md_ctrl;return 0 ;
@@ -1331,9 +1347,10 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl)return -ENOMEM ; } -void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl) +void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id) {t7xx_cldma_late_release (md_ctrl); +t7xx_cldma_adjust_config (md_ctrl, cfg_id);t7xx_cldma_late_init (md_ctrl); }
drivers/net/wwan/t7xx/t7xx_hif_cldma.h +13 -5
@@ -31,6 +31,10 @@#include "t7xx_cldma.h" #include "t7xx_pci.h" +#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) +#define CLDMA_SHARED_Q_BUFF_SZ 3584 +#define CLDMA_DEDICATED_Q_BUFF_SZ 2048 +/** * enum cldma_id - Identifiers for CLDMA HW units. * @CLDMA_ID_MD: Modem control channel.
@@ -55,6 +59,11 @@ struct cldma_gpd {__le16 not_used2; }; +enum cldma_cfg { +CLDMA_SHARED_Q_CFG , +CLDMA_DEDICATED_Q_CFG , +}; +struct cldma_request {struct cldma_gpd *gpd;/* Virtual address for CPU */ dma_addr_t gpd_addr;/* Physical address for DMA */
@@ -82,6 +91,7 @@ struct cldma_queue {wait_queue_head_t req_wq;/* Only for TX */ struct workqueue_struct *worker;struct work_struct cldma_work; +int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb); };struct cldma_ctrl {
@@ -101,24 +111,22 @@ struct cldma_ctrl {struct md_pm_entity *pm_entity;struct t7xx_cldma_hw hw_info;bool is_late_init; -int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb); }; +#define CLDMA_Q_IDX_DUMP 1#define GPD_FLAGS_HWO BIT(0)#define GPD_FLAGS_IOC BIT(7)#define GPD_DMAPOOL_ALIGN 16 -#define CLDMA_MTU 3584/* 3.5kB */ -int t7xx_cldma_alloc (enum cldma_id hif_id,struct t7xx_pci_dev *t7xx_dev);void t7xx_cldma_hif_hw_init (struct cldma_ctrl *md_ctrl);int t7xx_cldma_init (struct cldma_ctrl *md_ctrl);void t7xx_cldma_exit (struct cldma_ctrl *md_ctrl); -void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl); +void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id);void t7xx_cldma_start (struct cldma_ctrl *md_ctrl);int t7xx_cldma_stop (struct cldma_ctrl *md_ctrl);void t7xx_cldma_reset (struct cldma_ctrl *md_ctrl); -void t7xx_cldma_set_recv_skb (struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb (struct cldma_queue *queue,int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb));int t7xx_cldma_send_skb (struct cldma_ctrl *md_ctrl,int qno,struct sk_buff *skb);void t7xx_cldma_stop_all_qs (struct cldma_ctrl *md_ctrl,enum mtk_txrx tx_rx);
drivers/net/wwan/t7xx/t7xx_modem_ops.c +2 -2
@@ -529,7 +529,7 @@ static void t7xx_md_hk_wq(struct work_struct *work)/* Clear the HS2 EXIT event appended in core_reset() */ t7xx_fsm_clr_event (ctl,FSM_EVENT_MD_HS2_EXIT ); -t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_MD ]); +t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_MD ],CLDMA_SHARED_Q_CFG );t7xx_cldma_start (md->md_ctrl[CLDMA_ID_MD ]);t7xx_fsm_broadcast_state (ctl,MD_STATE_WAITING_FOR_HS2 ); md->core_md.handshake_ongoing = true;
@@ -544,7 +544,7 @@ static void t7xx_ap_hk_wq(struct work_struct *work)/* Clear the HS2 EXIT event appended in t7xx_core_reset(). */ t7xx_fsm_clr_event (ctl,FSM_EVENT_AP_HS2_EXIT );t7xx_cldma_stop (md->md_ctrl[CLDMA_ID_AP ]); -t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_AP ]); +t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_AP ],CLDMA_SHARED_Q_CFG );t7xx_cldma_start (md->md_ctrl[CLDMA_ID_AP ]); md->core_ap.handshake_ongoing = true;t7xx_core_hk_handler (md, &md->core_ap, ctl,FSM_EVENT_AP_HS2 ,FSM_EVENT_AP_HS2_EXIT );
drivers/net/wwan/t7xx/t7xx_port.h +4 -0
@@ -75,6 +75,8 @@ enum port_ch {PORT_CH_DSS6_TX =0x20df ,PORT_CH_DSS7_RX =0x20e0 ,PORT_CH_DSS7_TX =0x20e1 , + + PORT_CH_ID_UNIMPORTANT = 0xffff, };struct t7xx_port ;
@@ -135,9 +137,11 @@ struct t7xx_port { }; }; +int t7xx_get_port_mtu (struct t7xx_port *port);struct sk_buff *t7xx_port_alloc_skb (int payload);struct sk_buff *t7xx_ctrl_alloc_skb (int payload);int t7xx_port_enqueue_skb (struct t7xx_port *port,struct sk_buff *skb); +int t7xx_port_send_raw_skb (struct t7xx_port *port,struct sk_buff *skb);int t7xx_port_send_skb (struct t7xx_port *port,struct sk_buff *skb,unsigned int pkt_header,unsigned int ex_msg); int t7xx_port_send_ctl_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int msg,
drivers/net/wwan/t7xx/t7xx_port_proxy.c +77 -12
137 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_port_proxy.h +11 -1
@@ -31,12 +31,19 @@#define RX_QUEUE_MAXLEN 32#define CTRL_QUEUE_MAXLEN 16 +enum port_cfg_id { +PORT_CFG_ID_INVALID , +PORT_CFG_ID_NORMAL , +PORT_CFG_ID_EARLY , +}; +struct port_proxy {int port_count;struct list_head rx_ch_ports[PORT_CH_ID_MASK +1 ];struct list_head queue_ports[CLDMA_NUM ][MTK_QUEUES ];struct device *dev; -struct t7xx_port ports[]; +enum port_cfg_id cfg_id; +struct t7xx_port ports[]; };struct ccci_header {
@@ -98,5 +105,8 @@ void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned intint t7xx_port_enum_msg_handler (struct t7xx_modem *md,void *msg);int t7xx_port_proxy_chl_enable_disable (struct port_proxy *port_prox,unsigned int ch_id,bool en_flag); +void t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id); +int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb); +int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb);#endif /* __T7XX_PORT_PROXY_H__ */
drivers/net/wwan/t7xx/t7xx_port_wwan.c +2 -1
@@ -54,7 +54,7 @@ static void t7xx_port_ctrl_stop(struct wwan_port *port)static int t7xx_port_ctrl_tx (struct wwan_port *port,struct sk_buff *skb) {struct t7xx_port *port_private =wwan_port_get_drvdata (port); -size_t len, offset, chunk_len =0 , txq_mtu =CLDMA_MTU ; +size_t len, offset, chunk_len =0 , txq_mtu;const struct t7xx_port_conf *port_conf;struct t7xx_fsm_ctl *ctl;enum md_state md_state;
@@ -72,6 +72,7 @@ static int t7xx_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)return -ENODEV ; } + txq_mtu =t7xx_get_port_mtu (port_private);for (offset =0 ; offset < len; offset += chunk_len) {struct sk_buff *skb_ccci;int ret;
drivers/net/wwan/t7xx/t7xx_reg.h +19 -3
@@ -102,10 +102,26 @@ enum t7xx_pm_resume_state { };#define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c -#define MISC_STAGE_MASK GENMASK(2, 0) -#define MISC_RESET_TYPE_PLDR BIT(26)#define MISC_RESET_TYPE_FLDR BIT(27) -#define LINUX_STAGE 4 +#define MISC_RESET_TYPE_PLDR BIT(26) +#define MISC_LK_EVENT_MASK GENMASK(11, 8) + +enum lk_event_id { +LK_EVENT_NORMAL =0 , +LK_EVENT_CREATE_PD_PORT =1 , +LK_EVENT_CREATE_POST_DL_PORT =2 , +LK_EVENT_RESET =7 , +}; + +#define MISC_STAGE_MASK GENMASK(2, 0) + +enum t7xx_device_stage { +T7XX_DEV_STAGE_INIT =0 , +T7XX_DEV_STAGE_BROM_PRE =1 , +T7XX_DEV_STAGE_BROM_POST =2 , +T7XX_DEV_STAGE_LK =3 , +T7XX_DEV_STAGE_LINUX =4 , +};#define T7XX_PCIE_RESOURCE_STATUS 0x0d28#define T7XX_PCIE_RESOURCE_STS_MSK GENMASK(4, 0)
drivers/net/wwan/t7xx/t7xx_state_monitor.c +74 -11
116 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_state_monitor.h +1 -0
@@ -96,6 +96,7 @@ struct t7xx_fsm_ctl {bool exp_flg;spinlock_t notifier_lock;/* Protects notifier list */ struct list_head notifier_list; +u32 prev_status; };struct t7xx_fsm_event {
Signature · 1 line
2.34.1
Re: [PATCH v4 net-next 2/5] net: wwan: t7xx: Infrastructure for early port configuration
Quoted 8 lines · On Mon, 16 Jan 2023, [email protected] wrote:
From: M Chetan Kumar <[email protected]>
To support cases such as FW update or Core dump, the t7xx device is capable of signaling the host that a special port needs to be created before the handshake phase.
Adds the infrastructure required to create the early ports which also requires a different configuration of CLDMA queues.
This doesn't go into details why CLDMA_MTU -> CLDMA_SHARED_Q_BUFF_SZ rename was done (if it wouldn't have been in the same change at all, I could have immediately seen that, ah, it was just moving code around but now I had to go to check if the defines yield same values).
Quoted 322 lines
Signed-off-by Haijun Liu <[email protected]>Co-developed-by Madhusmita Sahu <[email protected]>Signed-off-by Madhusmita Sahu <[email protected]>Signed-off-by Ricardo Martinez <[email protected]>Signed-off-by Devegowda Chandrashekar <[email protected]>Signed-off-by M Chetan Kumar <[email protected]>--
v4:
* Remove "this patch" in commit message.
*MISC_DEV_STATUS_MASK&MISC_DEV_STATUS_INVALIDis unused, drop it.
* Drop unnecessary assignement for ret var insidefsm_routine_start.
* cppcheck - reduce variableScope for stage var infsm_routine_start.
v3:
* No Change.
v2:
* Moverecv_skbhandler tocldma_queue.
* Dropcldma_queue_type.
* Restore prototype oft7xx_port_send_raw_skb().
* RemovePORT_CFG_ID_INVALIDcheck int7xx_port_proxy_set_cfg().
* Add space before */.
* Drop unnecessary logs.
* UseWARN_ONon early port.
* Use newMISC_DEV_STATUS_INVALIDinstead ofMISC_DEV_STATUS.
* Use macros instead of const identifiers.
* Change ports member type from pointer to array type.
* PrefixLK_EVENT_XXwith MISC prefix.
* Use t7xx prefix fordevice_stageenums.
* Correct log messages.
* Dont overridepkt_sizefor non-download port under dedicated Queue.
* Dropcldma_txq_rxq_ids.
* Use macro for txq/rxq index.
* Usewarn_onforrxq_idxcomparison.
* Dropt7xx_port_proxy_get_port_by_name().
* Replace fsm poll withread_poll_timeout().
* Use "\n" consistently across log message.
* Remove local var_devprefixes infsm_routine_start().
* Usemax_t.--- drivers/net/wwan/t7xx/t7xx_hif_cldma.c | 47 ++++++++---- drivers/net/wwan/t7xx/t7xx_hif_cldma.h | 18 +++-- drivers/net/wwan/t7xx/t7xx_modem_ops.c | 4 +- drivers/net/wwan/t7xx/t7xx_port.h | 4 + drivers/net/wwan/t7xx/t7xx_port_proxy.c | 89 +++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_port_proxy.h | 12 ++- drivers/net/wwan/t7xx/t7xx_port_wwan.c | 3 +- drivers/net/wwan/t7xx/t7xx_reg.h | 22 +++++- drivers/net/wwan/t7xx/t7xx_state_monitor.c | 85 ++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_state_monitor.h | 1 + 10 files changed, 235 insertions(+), 50 deletions(-)drivers/net/wwan/t7xx/t7xx_hif_cldma.c +32
-15@@ -57,8 +57,6 @@#define CHECK_Q_STOP_TIMEOUT_US 1000000#define CHECK_Q_STOP_STEP_US 10000 -#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) -static void md_cd_queue_struct_reset (struct cldma_queue *queue,struct cldma_ctrl *md_ctrl,enum mtk_txrx tx_rx,unsigned int index) {@@ -161,7 +159,7 @@ static int t7xx_cldma_gpd_rx_from_q(struct cldma_queue *queue, int budget, boolskb_reset_tail_pointer (skb);skb_put (skb,le16_to_cpu (gpd->data_buff_len)); - ret = md_ctrl->recv_skb (queue, skb); + ret = queue->recv_skb (queue, skb);/* Break processing, will try again later */ if (ret <0 )return ret;@@ -897,13 +895,13 @@ static void t7xx_cldma_hw_start_send(struct cldma_ctrl *md_ctrl, int qno,/** * t7xx_cldma_set_recv_skb() - Set the callback to handle RX packets. -* @md_ctrl: CLDMA context structure. +* @queue: CLDMA queue. * @recv_skb: Receiving skb callback. */ -void t7xx_cldma_set_recv_skb (struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb (struct cldma_queue *queue,int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb)) { - md_ctrl->recv_skb = recv_skb; + queue->recv_skb = recv_skb; }/** @@ -993,6 +991,28 @@ int t7xx_cldma_send_skb(struct cldma_ctrl *md_ctrl, int qno, struct sk_buff *skbreturn ret; } +static void t7xx_cldma_adjust_config (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id) +{ +int qno; + +for (qno =0 ; qno <CLDMA_RXQ_NUM ; qno++) { + md_ctrl->rx_ring[qno].pkt_size =CLDMA_SHARED_Q_BUFF_SZ ; +t7xx_cldma_set_recv_skb (&md_ctrl->rxq[qno], t7xx_port_proxy_recv_skb); + } + + md_ctrl->rx_ring[CLDMA_RXQ_NUM -1 ].pkt_size =CLDMA_JUMBO_BUFF_SZ ; + +for (qno =0 ; qno <CLDMA_TXQ_NUM ; qno++) + md_ctrl->tx_ring[qno].pkt_size =CLDMA_SHARED_Q_BUFF_SZ ; + +if (cfg_id ==CLDMA_DEDICATED_Q_CFG ) { + md_ctrl->tx_ring[CLDMA_Q_IDX_DUMP ].pkt_size =CLDMA_DEDICATED_Q_BUFF_SZ ; + md_ctrl->rx_ring[CLDMA_Q_IDX_DUMP ].pkt_size =CLDMA_DEDICATED_Q_BUFF_SZ ; +t7xx_cldma_set_recv_skb (&md_ctrl->rxq[CLDMA_Q_IDX_DUMP ], + t7xx_port_proxy_recv_skb_from_dedicated_queue); + } +} +static int t7xx_cldma_late_init (struct cldma_ctrl *md_ctrl) {char dma_pool_name[32 ];@@ -1018,16 +1038,9 @@ static int t7xx_cldma_late_init(struct cldma_ctrl *md_ctrl)dev_err (md_ctrl->dev,"control TX ring init fail\n" ); goto err_free_tx_ring; } - - md_ctrl->tx_ring[i].pkt_size =CLDMA_MTU ; }for (j =0 ; j <CLDMA_RXQ_NUM ; j++) { - md_ctrl->rx_ring[j].pkt_size =CLDMA_MTU ; - -if (j ==CLDMA_RXQ_NUM -1 ) - md_ctrl->rx_ring[j].pkt_size =CLDMA_JUMBO_BUFF_SZ ; - ret =t7xx_cldma_rx_ring_init (md_ctrl, &md_ctrl->rx_ring[j]);if (ret) {dev_err (md_ctrl->dev,"Control RX ring init fail\n" );@@ -1094,6 +1107,7 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) {struct device *dev = &t7xx_dev->pdev->dev;struct cldma_ctrl *md_ctrl; +int qno; md_ctrl =devm_kzalloc (dev,sizeof (*md_ctrl),GFP_KERNEL );if (!md_ctrl)@@ -1102,7 +1116,9 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) md_ctrl->t7xx_dev = t7xx_dev; md_ctrl->dev = dev; md_ctrl->hif_id = hif_id; - md_ctrl->recv_skb = t7xx_cldma_default_recv_skb; +for (qno =0 ; qno <CLDMA_RXQ_NUM ; qno++) + md_ctrl->rxq[qno].recv_skb = t7xx_cldma_default_recv_skb; +t7xx_hw_info_init (md_ctrl); t7xx_dev->md->md_ctrl[hif_id] = md_ctrl;return 0 ;@@ -1331,9 +1347,10 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl)return -ENOMEM ; } -void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl) +void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id) {t7xx_cldma_late_release (md_ctrl); +t7xx_cldma_adjust_config (md_ctrl, cfg_id);t7xx_cldma_late_init (md_ctrl); }drivers/net/wwan/t7xx/t7xx_hif_cldma.h +13
-5@@ -31,6 +31,10 @@#include "t7xx_cldma.h" #include "t7xx_pci.h" +#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) +#define CLDMA_SHARED_Q_BUFF_SZ 3584 +#define CLDMA_DEDICATED_Q_BUFF_SZ 2048 +/** * enum cldma_id - Identifiers for CLDMA HW units. * @CLDMA_ID_MD: Modem control channel. @@ -55,6 +59,11 @@ struct cldma_gpd {__le16 not_used2; }; +enum cldma_cfg { +CLDMA_SHARED_Q_CFG , +CLDMA_DEDICATED_Q_CFG , +}; +struct cldma_request {struct cldma_gpd *gpd;/* Virtual address for CPU */ dma_addr_t gpd_addr;/* Physical address for DMA */ @@ -82,6 +91,7 @@ struct cldma_queue {wait_queue_head_t req_wq;/* Only for TX */ struct workqueue_struct *worker;struct work_struct cldma_work; +int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb); };struct cldma_ctrl {@@ -101,24 +111,22 @@ struct cldma_ctrl {struct md_pm_entity *pm_entity;struct t7xx_cldma_hw hw_info;bool is_late_init; -int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb); }; +#define CLDMA_Q_IDX_DUMP 1#define GPD_FLAGS_HWO BIT(0)#define GPD_FLAGS_IOC BIT(7)#define GPD_DMAPOOL_ALIGN 16 -#define CLDMA_MTU 3584/* 3.5kB */ -int t7xx_cldma_alloc (enum cldma_id hif_id,struct t7xx_pci_dev *t7xx_dev);void t7xx_cldma_hif_hw_init (struct cldma_ctrl *md_ctrl);int t7xx_cldma_init (struct cldma_ctrl *md_ctrl);void t7xx_cldma_exit (struct cldma_ctrl *md_ctrl); -void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl); +void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id);void t7xx_cldma_start (struct cldma_ctrl *md_ctrl);int t7xx_cldma_stop (struct cldma_ctrl *md_ctrl);void t7xx_cldma_reset (struct cldma_ctrl *md_ctrl); -void t7xx_cldma_set_recv_skb (struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb (struct cldma_queue *queue,int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb));int t7xx_cldma_send_skb (struct cldma_ctrl *md_ctrl,int qno,struct sk_buff *skb);void t7xx_cldma_stop_all_qs (struct cldma_ctrl *md_ctrl,enum mtk_txrx tx_rx);drivers/net/wwan/t7xx/t7xx_modem_ops.c +2
-2@@ -529,7 +529,7 @@ static void t7xx_md_hk_wq(struct work_struct *work)/* Clear the HS2 EXIT event appended in core_reset() */ t7xx_fsm_clr_event (ctl,FSM_EVENT_MD_HS2_EXIT ); -t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_MD ]); +t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_MD ],CLDMA_SHARED_Q_CFG );t7xx_cldma_start (md->md_ctrl[CLDMA_ID_MD ]);t7xx_fsm_broadcast_state (ctl,MD_STATE_WAITING_FOR_HS2 ); md->core_md.handshake_ongoing = true;@@ -544,7 +544,7 @@ static void t7xx_ap_hk_wq(struct work_struct *work)/* Clear the HS2 EXIT event appended in t7xx_core_reset(). */ t7xx_fsm_clr_event (ctl,FSM_EVENT_AP_HS2_EXIT );t7xx_cldma_stop (md->md_ctrl[CLDMA_ID_AP ]); -t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_AP ]); +t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_AP ],CLDMA_SHARED_Q_CFG );t7xx_cldma_start (md->md_ctrl[CLDMA_ID_AP ]); md->core_ap.handshake_ongoing = true;t7xx_core_hk_handler (md, &md->core_ap, ctl,FSM_EVENT_AP_HS2 ,FSM_EVENT_AP_HS2_EXIT );drivers/net/wwan/t7xx/t7xx_port.h +4
-0@@ -75,6 +75,8 @@ enum port_ch {PORT_CH_DSS6_TX =0x20df ,PORT_CH_DSS7_RX =0x20e0 ,PORT_CH_DSS7_TX =0x20e1 , + + PORT_CH_ID_UNIMPORTANT = 0xffff, };struct t7xx_port ;@@ -135,9 +137,11 @@ struct t7xx_port { }; }; +int t7xx_get_port_mtu (struct t7xx_port *port);struct sk_buff *t7xx_port_alloc_skb (int payload);struct sk_buff *t7xx_ctrl_alloc_skb (int payload);int t7xx_port_enqueue_skb (struct t7xx_port *port,struct sk_buff *skb); +int t7xx_port_send_raw_skb (struct t7xx_port *port,struct sk_buff *skb);int t7xx_port_send_skb (struct t7xx_port *port,struct sk_buff *skb,unsigned int pkt_header,unsigned int ex_msg); int t7xx_port_send_ctl_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int msg,drivers/net/wwan/t7xx/t7xx_port_proxy.c +23
-1@@ -100,6 +100,18 @@ static const struct t7xx_port_conf t7xx_port_conf[] = { }, }; +static struct t7xx_port_conf t7xx_early_port_conf[] = { + { + .tx_ch =PORT_CH_ID_UNIMPORTANT , + .rx_ch =PORT_CH_ID_UNIMPORTANT , + .txq_index =CLDMA_Q_IDX_DUMP , + .rxq_index =CLDMA_Q_IDX_DUMP , + .txq_exp_index =CLDMA_Q_IDX_DUMP , + .rxq_exp_index =CLDMA_Q_IDX_DUMP , + .path_id =CLDMA_ID_AP , + }, +}; +static struct t7xx_port *t7xx_proxy_get_port_by_ch (struct port_proxy *port_prox,enum port_ch ch) {const struct t7xx_port_conf *port_conf;@@ -214,7 +226,17 @@ int t7xx_port_enqueue_skb(struct t7xx_port *port, struct sk_buff *skb)return 0 ; } -static int t7xx_port_send_raw_skb (struct t7xx_port *port,struct sk_buff *skb) +int t7xx_get_port_mtu (struct t7xx_port *port) +{ +enum cldma_id path_id = port->port_conf->path_id; +int tx_qno =t7xx_port_get_queue_no (port); +struct cldma_ctrl *md_ctrl; + + md_ctrl = port->t7xx_dev->md->md_ctrl[path_id]; +return md_ctrl->tx_ring[tx_qno].pkt_size; +} + +int t7xx_port_send_raw_skb (struct t7xx_port *port,struct sk_buff *skb) {enum cldma_id path_id = port->port_conf->path_id;struct cldma_ctrl *md_ctrl;@@ -329,6 +351,30 @@ static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox) } }
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox) · line 363
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +10
-0+int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb) +{ +struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev; +struct port_proxy *port_prox = t7xx_dev->md->port_prox; +const struct t7xx_port_conf *port_conf; +struct t7xx_port *port; +int ret; + + port = &port_prox->ports[0 ]; +if (WARN_ON (port->port_conf->rxq_index != queue->index)) {
WARN_ON_ONCE would seem enough to alert to this problem and not as spammy?
Quoted 49 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +34
-1+dev_kfree_skb_any (skb); +return -EINVAL ; + } + + port_conf = port->port_conf; + ret = port_conf->ops->recv_skb (port, skb); +if (ret <0 && ret != -ENOBUFS ) { +dev_err (port->dev,"drop on RX ch %d, %d\n" , port_conf->rx_ch, ret); +dev_kfree_skb_any (skb); + } + +return ret; +} +static struct t7xx_port *t7xx_port_proxy_find_port (struct t7xx_pci_dev *t7xx_dev,struct cldma_queue *queue,u16 channel) {@@ -359,7 +405,7 @@ static struct t7xx_port *t7xx_port_proxy_find_port(struct t7xx_pci_dev *t7xx_dev** 0 - Packet consumed. ** -ERROR - Failed to process skb. */ -static int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb) +int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb) {struct ccci_header *ccci_h = (struct ccci_header *)skb->data;struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev;@@ -451,26 +497,47 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)t7xx_proxy_setup_ch_mapping (port_prox); } +void t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id) +{ +struct port_proxy *port_prox = md->port_prox; +const struct t7xx_port_conf *port_conf; +u32 port_count; +int i; + +t7xx_port_proxy_uninit (port_prox); + +if (cfg_id ==PORT_CFG_ID_EARLY ) { + port_conf = t7xx_early_port_conf; + port_count =ARRAY_SIZE (t7xx_early_port_conf); + }else { + port_conf = t7xx_port_conf; + port_count =ARRAY_SIZE (t7xx_port_conf); + } + +for (i =0 ; i < port_count; i++) + port_prox->ports[i].port_conf = &port_conf[i];
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) · line 528
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +7
-0+ + port_prox->cfg_id = cfg_id; + port_prox->port_count = port_count; +t7xx_proxy_init_all_ports (md); +} +static int t7xx_proxy_alloc (struct t7xx_modem *md) { +u32 early_port_count =ARRAY_SIZE (t7xx_early_port_conf);unsigned int port_count =ARRAY_SIZE (t7xx_port_conf);
Why these are of different types?
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) · line 532
Quoted 7 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +1
-3struct device *dev = &md->t7xx_dev->pdev->dev;struct port_proxy *port_prox; -int i; - port_prox =devm_kzalloc (dev,sizeof (*port_prox) +sizeof (struct t7xx_port ) * port_count, -GFP_KERNEL ); + port_count =max_t (u32, port_count, early_port_count);
If vars are using same type, you could do just max()
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) · line 533
Quoted 1 line
drivers/net/wwan/t7xx/t7xx_port_proxy.c +1
-0+ port_prox =devm_kzalloc (dev,struct_size (port_prox, ports, port_count),GFP_KERNEL );
include <linux/overflow.h> missing?
This opencoding -> struct_size() seems independent change, no? If so, it should be in a separate patch. (It's a good change still and should be done.)
Quoted 36 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +1
-7if (!port_prox)return -ENOMEM ; md->port_prox = port_prox; port_prox->dev = dev; +t7xx_port_proxy_set_cfg (md,PORT_CFG_ID_EARLY ); -for (i =0 ; i < port_count; i++) - port_prox->ports[i].port_conf = &t7xx_port_conf[i]; - - port_prox->port_count = port_count; -t7xx_proxy_init_all_ports (md);return 0 ; }@@ -492,8 +559,6 @@ int t7xx_port_proxy_init(struct t7xx_modem *md)if (ret)return ret; -t7xx_cldma_set_recv_skb (md->md_ctrl[CLDMA_ID_AP ], t7xx_port_proxy_recv_skb); -t7xx_cldma_set_recv_skb (md->md_ctrl[CLDMA_ID_MD ], t7xx_port_proxy_recv_skb);return 0 ; }drivers/net/wwan/t7xx/t7xx_port_proxy.h +4
-0@@ -31,12 +31,19 @@#define RX_QUEUE_MAXLEN 32#define CTRL_QUEUE_MAXLEN 16 +enum port_cfg_id { +PORT_CFG_ID_INVALID , +PORT_CFG_ID_NORMAL , +PORT_CFG_ID_EARLY ,
drivers/net/wwan/t7xx/t7xx_port_proxy.h line 46
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.h +4
-1+}; +struct port_proxy {int port_count;struct list_head rx_ch_ports[PORT_CH_ID_MASK +1 ];struct list_head queue_ports[CLDMA_NUM ][MTK_QUEUES ];struct device *dev; -struct t7xx_port ports[]; +enum port_cfg_id cfg_id; +struct t7xx_port ports[];
Spurious space change.
Quoted 125 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.h +3
-0};struct ccci_header {@@ -98,5 +105,8 @@ void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned intint t7xx_port_enum_msg_handler (struct t7xx_modem *md,void *msg);int t7xx_port_proxy_chl_enable_disable (struct port_proxy *port_prox,unsigned int ch_id,bool en_flag); +void t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id); +int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb); +int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb);#endif /* __T7XX_PORT_PROXY_H__ */ drivers/net/wwan/t7xx/t7xx_port_wwan.c +2
-1@@ -54,7 +54,7 @@ static void t7xx_port_ctrl_stop(struct wwan_port *port)static int t7xx_port_ctrl_tx (struct wwan_port *port,struct sk_buff *skb) {struct t7xx_port *port_private =wwan_port_get_drvdata (port); -size_t len, offset, chunk_len =0 , txq_mtu =CLDMA_MTU ; +size_t len, offset, chunk_len =0 , txq_mtu;const struct t7xx_port_conf *port_conf;struct t7xx_fsm_ctl *ctl;enum md_state md_state;@@ -72,6 +72,7 @@ static int t7xx_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)return -ENODEV ; } + txq_mtu =t7xx_get_port_mtu (port_private);for (offset =0 ; offset < len; offset += chunk_len) {struct sk_buff *skb_ccci;int ret;drivers/net/wwan/t7xx/t7xx_reg.h +18
-3@@ -102,10 +102,26 @@ enum t7xx_pm_resume_state { };#define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c -#define MISC_STAGE_MASK GENMASK(2, 0) -#define MISC_RESET_TYPE_PLDR BIT(26)#define MISC_RESET_TYPE_FLDR BIT(27) -#define LINUX_STAGE 4 +#define MISC_RESET_TYPE_PLDR BIT(26) +#define MISC_LK_EVENT_MASK GENMASK(11, 8) + +enum lk_event_id { +LK_EVENT_NORMAL =0 , +LK_EVENT_CREATE_PD_PORT =1 , +LK_EVENT_CREATE_POST_DL_PORT =2 , +LK_EVENT_RESET =7 , +}; + +#define MISC_STAGE_MASK GENMASK(2, 0) +enum t7xx_device_stage { +T7XX_DEV_STAGE_INIT =0 , +T7XX_DEV_STAGE_BROM_PRE =1 , +T7XX_DEV_STAGE_BROM_POST =2 , +T7XX_DEV_STAGE_LK =3 , +T7XX_DEV_STAGE_LINUX =4 , +};#define T7XX_PCIE_RESOURCE_STATUS 0x0d28#define T7XX_PCIE_RESOURCE_STS_MSK GENMASK(4, 0)drivers/net/wwan/t7xx/t7xx_state_monitor.c +31
-3@@ -206,6 +206,34 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commfsm_finish_command (ctl, cmd,0 ); } +static void t7xx_lk_stage_event_handling (struct t7xx_fsm_ctl *ctl,unsigned int status) +{ +struct t7xx_modem *md = ctl->md; +struct cldma_ctrl *md_ctrl; +enum lk_event_id lk_event; +struct device *dev; + + dev = &md->t7xx_dev->pdev->dev; + lk_event =FIELD_GET (MISC_LK_EVENT_MASK , status); +switch (lk_event) { +case LK_EVENT_NORMAL : +case LK_EVENT_RESET : +break ; + +case LK_EVENT_CREATE_PD_PORT : + md_ctrl = md->md_ctrl[CLDMA_ID_AP ]; +t7xx_cldma_hif_hw_init (md_ctrl); +t7xx_cldma_stop (md_ctrl); +t7xx_cldma_switch_cfg (md_ctrl,CLDMA_DEDICATED_Q_CFG ); +t7xx_cldma_start (md_ctrl); +break ; + +default : +dev_err (dev,"Invalid LK event %d\n" , lk_event); +break ; + } +} +static int fsm_stopped_handler (struct t7xx_fsm_ctl *ctl) { ctl->curr_state =FSM_STATE_STOPPED ;@@ -317,7 +345,8 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl)static void fsm_routine_start (struct t7xx_fsm_ctl *ctl,struct t7xx_fsm_command *cmd) {struct t7xx_modem *md = ctl->md; -u32 dev_status; +struct device *dev; +u32 status;int ret;if (!md)@@ -329,23 +358,56 @@ static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commandreturn ; } + dev = &md->t7xx_dev->pdev->dev; ctl->curr_state =FSM_STATE_PRE_START ;t7xx_md_event_notify (md,FSM_PRE_START ); - ret = read_poll_timeout(ioread32, dev_status, - (dev_status & MISC_STAGE_MASK) == LINUX_STAGE, 20000, 2000000,
drivers/net/wwan/t7xx/t7xx_state_monitor.c static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command · line 372
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +7
-2- false, IREG_BASE(md->t7xx_dev) + T7XX_PCIE_MISC_DEV_STATUS); + ret =read_poll_timeout (ioread32, status, + ((status &MISC_STAGE_MASK ) ==T7XX_DEV_STAGE_LINUX ) || + ((status &MISC_STAGE_MASK ) ==T7XX_DEV_STAGE_LK ),100000 , +20000000 , false,IREG_BASE (md->t7xx_dev) + +T7XX_PCIE_MISC_DEV_STATUS ); +if (ret) { -struct device *dev = &md->t7xx_dev->pdev->dev; + ret = -ETIMEDOUT ;
Is this necessary? Can read_poll_timeout() return anything else than -ETIMEDOUT??
drivers/net/wwan/t7xx/t7xx_state_monitor.c static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command · line 373
Quoted 1 line
drivers/net/wwan/t7xx/t7xx_state_monitor.c +1
-0+dev_err (dev,"read poll %d\n" , ret);
read poll timeout ?
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +2
-1+ goto finish_command; + } -fsm_finish_command (ctl, cmd, -ETIMEDOUT );
drivers/net/wwan/t7xx/t7xx_state_monitor.c static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command · line 384
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +8
-2-dev_err (dev,"Invalid device status 0x%lx\n" , dev_status &MISC_STAGE_MASK ); -return ; +if (status != ctl->prev_status) { +u32 stage =FIELD_GET (MISC_STAGE_MASK , status); + +switch (stage) { +case T7XX_DEV_STAGE_INIT : +case T7XX_DEV_STAGE_BROM_PRE : +case T7XX_DEV_STAGE_BROM_POST : +dev_info (dev,"BROM_STAGE Entered\n" );
Somewhat questionable if info level is really desirable for these?
Quoted 53 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +25
-3+ ret =t7xx_fsm_append_cmd (ctl,FSM_CMD_START ,0 ); +break ; + +case T7XX_DEV_STAGE_LK : +dev_info (dev,"LK_STAGE Entered\n" ); +t7xx_lk_stage_event_handling (ctl, status); +break ; + +case T7XX_DEV_STAGE_LINUX : +dev_info (dev,"LINUX_STAGE Entered\n" ); +t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_AP ]); +t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_MD ]); +t7xx_mhccif_mask_clr (md->t7xx_dev,D2H_INT_PORT_ENUM | +D2H_INT_ASYNC_MD_HK |D2H_INT_ASYNC_AP_HK ); +t7xx_port_proxy_set_cfg (md,PORT_CFG_ID_NORMAL ); + ret =fsm_routine_starting (ctl); +break ; + +default : +break ; + } + ctl->prev_status = status; } -t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_AP ]); -t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_MD ]); -fsm_finish_command (ctl, cmd,fsm_routine_starting (ctl)); +finish_command: +fsm_finish_command (ctl, cmd, ret); }static int fsm_main_thread (void *data)@@ -516,6 +578,7 @@ void t7xx_fsm_reset(struct t7xx_modem *md)fsm_flush_event_cmd_qs (ctl); ctl->curr_state =FSM_STATE_STOPPED ; ctl->exp_flg = false; + ctl->prev_status =0 ; }int t7xx_fsm_init (struct t7xx_modem *md)drivers/net/wwan/t7xx/t7xx_state_monitor.h +1
-0@@ -96,6 +96,7 @@ struct t7xx_fsm_ctl {bool exp_flg;spinlock_t notifier_lock;/* Protects notifier list */ struct list_head notifier_list; +u32 prev_status; };struct t7xx_fsm_event {
Signature · 1 line
i.
Re: [PATCH v4 net-next 2/5] net: wwan: t7xx: Infrastructure for early port configuration
Hi Ilpo,
Thank you for the feedback.
Quoted 338 lines · Ilpo Järvinen
Quoted 8 lines · On Mon, 16 Jan 2023, [email protected] wrote:
From: M Chetan Kumar <[email protected]>
To support cases such as FW update or Core dump, the t7xx device is capable of signaling the host that a special port needs to be created before the handshake phase.
Adds the infrastructure required to create the early ports which also requires a different configuration of CLDMA queues.
This doesn't go into details why
CLDMA_MTU->CLDMA_SHARED_Q_BUFF_SZrename was done (if it wouldn't have been in the same change at all, I could have immediately seen that, ah, it was just moving code around but now I had to go to check if the defines yield same values).Quoted 322 lines
Signed-off-by Haijun Liu <[email protected]>Co-developed-by Madhusmita Sahu <[email protected]>Signed-off-by Madhusmita Sahu <[email protected]>Signed-off-by Ricardo Martinez <[email protected]>Signed-off-by Devegowda Chandrashekar <[email protected]>Signed-off-by M Chetan Kumar <[email protected]>--
v4:
* Remove "this patch" in commit message.
*MISC_DEV_STATUS_MASK&MISC_DEV_STATUS_INVALIDis unused, drop it.
* Drop unnecessary assignement for ret var insidefsm_routine_start.
* cppcheck - reduce variableScope for stage var infsm_routine_start.
v3:
* No Change.
v2:
* Moverecv_skbhandler tocldma_queue.
* Dropcldma_queue_type.
* Restore prototype oft7xx_port_send_raw_skb().
* RemovePORT_CFG_ID_INVALIDcheck int7xx_port_proxy_set_cfg().
* Add space before */.
* Drop unnecessary logs.
* UseWARN_ONon early port.
* Use newMISC_DEV_STATUS_INVALIDinstead ofMISC_DEV_STATUS.
* Use macros instead of const identifiers.
* Change ports member type from pointer to array type.
* PrefixLK_EVENT_XXwith MISC prefix.
* Use t7xx prefix fordevice_stageenums.
* Correct log messages.
* Dont overridepkt_sizefor non-download port under dedicated Queue.
* Dropcldma_txq_rxq_ids.
* Use macro for txq/rxq index.
* Usewarn_onforrxq_idxcomparison.
* Dropt7xx_port_proxy_get_port_by_name().
* Replace fsm poll withread_poll_timeout().
* Use "\n" consistently across log message.
* Remove local var_devprefixes infsm_routine_start().
* Usemax_t.--- drivers/net/wwan/t7xx/t7xx_hif_cldma.c | 47 ++++++++---- drivers/net/wwan/t7xx/t7xx_hif_cldma.h | 18 +++-- drivers/net/wwan/t7xx/t7xx_modem_ops.c | 4 +- drivers/net/wwan/t7xx/t7xx_port.h | 4 + drivers/net/wwan/t7xx/t7xx_port_proxy.c | 89 +++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_port_proxy.h | 12 ++- drivers/net/wwan/t7xx/t7xx_port_wwan.c | 3 +- drivers/net/wwan/t7xx/t7xx_reg.h | 22 +++++- drivers/net/wwan/t7xx/t7xx_state_monitor.c | 85 ++++++++++++++++++--- drivers/net/wwan/t7xx/t7xx_state_monitor.h | 1 + 10 files changed, 235 insertions(+), 50 deletions(-)drivers/net/wwan/t7xx/t7xx_hif_cldma.c +32
-15@@ -57,8 +57,6 @@#define CHECK_Q_STOP_TIMEOUT_US 1000000#define CHECK_Q_STOP_STEP_US 10000 -#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) -static void md_cd_queue_struct_reset (struct cldma_queue *queue,struct cldma_ctrl *md_ctrl,enum mtk_txrx tx_rx,unsigned int index) {@@ -161,7 +159,7 @@ static int t7xx_cldma_gpd_rx_from_q(struct cldma_queue *queue, int budget, boolskb_reset_tail_pointer (skb);skb_put (skb,le16_to_cpu (gpd->data_buff_len)); - ret = md_ctrl->recv_skb (queue, skb); + ret = queue->recv_skb (queue, skb);/* Break processing, will try again later */ if (ret <0 )return ret;@@ -897,13 +895,13 @@ static void t7xx_cldma_hw_start_send(struct cldma_ctrl *md_ctrl, int qno,/** * t7xx_cldma_set_recv_skb() - Set the callback to handle RX packets. -* @md_ctrl: CLDMA context structure. +* @queue: CLDMA queue. * @recv_skb: Receiving skb callback. */ -void t7xx_cldma_set_recv_skb (struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb (struct cldma_queue *queue,int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb)) { - md_ctrl->recv_skb = recv_skb; + queue->recv_skb = recv_skb; }/** @@ -993,6 +991,28 @@ int t7xx_cldma_send_skb(struct cldma_ctrl *md_ctrl, int qno, struct sk_buff *skbreturn ret; } +static void t7xx_cldma_adjust_config (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id) +{ +int qno; + +for (qno =0 ; qno <CLDMA_RXQ_NUM ; qno++) { + md_ctrl->rx_ring[qno].pkt_size =CLDMA_SHARED_Q_BUFF_SZ ; +t7xx_cldma_set_recv_skb (&md_ctrl->rxq[qno], t7xx_port_proxy_recv_skb); + } + + md_ctrl->rx_ring[CLDMA_RXQ_NUM -1 ].pkt_size =CLDMA_JUMBO_BUFF_SZ ; + +for (qno =0 ; qno <CLDMA_TXQ_NUM ; qno++) + md_ctrl->tx_ring[qno].pkt_size =CLDMA_SHARED_Q_BUFF_SZ ; + +if (cfg_id ==CLDMA_DEDICATED_Q_CFG ) { + md_ctrl->tx_ring[CLDMA_Q_IDX_DUMP ].pkt_size =CLDMA_DEDICATED_Q_BUFF_SZ ; + md_ctrl->rx_ring[CLDMA_Q_IDX_DUMP ].pkt_size =CLDMA_DEDICATED_Q_BUFF_SZ ; +t7xx_cldma_set_recv_skb (&md_ctrl->rxq[CLDMA_Q_IDX_DUMP ], + t7xx_port_proxy_recv_skb_from_dedicated_queue); + } +} +static int t7xx_cldma_late_init (struct cldma_ctrl *md_ctrl) {char dma_pool_name[32 ];@@ -1018,16 +1038,9 @@ static int t7xx_cldma_late_init(struct cldma_ctrl *md_ctrl)dev_err (md_ctrl->dev,"control TX ring init fail\n" ); goto err_free_tx_ring; } - - md_ctrl->tx_ring[i].pkt_size =CLDMA_MTU ; }for (j =0 ; j <CLDMA_RXQ_NUM ; j++) { - md_ctrl->rx_ring[j].pkt_size =CLDMA_MTU ; - -if (j ==CLDMA_RXQ_NUM -1 ) - md_ctrl->rx_ring[j].pkt_size =CLDMA_JUMBO_BUFF_SZ ; - ret =t7xx_cldma_rx_ring_init (md_ctrl, &md_ctrl->rx_ring[j]);if (ret) {dev_err (md_ctrl->dev,"Control RX ring init fail\n" );@@ -1094,6 +1107,7 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) {struct device *dev = &t7xx_dev->pdev->dev;struct cldma_ctrl *md_ctrl; +int qno; md_ctrl =devm_kzalloc (dev,sizeof (*md_ctrl),GFP_KERNEL );if (!md_ctrl)@@ -1102,7 +1116,9 @@ int t7xx_cldma_alloc(enum cldma_id hif_id, struct t7xx_pci_dev *t7xx_dev) md_ctrl->t7xx_dev = t7xx_dev; md_ctrl->dev = dev; md_ctrl->hif_id = hif_id; - md_ctrl->recv_skb = t7xx_cldma_default_recv_skb; +for (qno =0 ; qno <CLDMA_RXQ_NUM ; qno++) + md_ctrl->rxq[qno].recv_skb = t7xx_cldma_default_recv_skb; +t7xx_hw_info_init (md_ctrl); t7xx_dev->md->md_ctrl[hif_id] = md_ctrl;return 0 ;@@ -1331,9 +1347,10 @@ int t7xx_cldma_init(struct cldma_ctrl *md_ctrl)return -ENOMEM ; } -void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl) +void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id) {t7xx_cldma_late_release (md_ctrl); +t7xx_cldma_adjust_config (md_ctrl, cfg_id);t7xx_cldma_late_init (md_ctrl); }drivers/net/wwan/t7xx/t7xx_hif_cldma.h +13
-5@@ -31,6 +31,10 @@#include "t7xx_cldma.h" #include "t7xx_pci.h" +#define CLDMA_JUMBO_BUFF_SZ (63 * 1024 + sizeof(struct ccci_header)) +#define CLDMA_SHARED_Q_BUFF_SZ 3584 +#define CLDMA_DEDICATED_Q_BUFF_SZ 2048 +/** * enum cldma_id - Identifiers for CLDMA HW units. * @CLDMA_ID_MD: Modem control channel. @@ -55,6 +59,11 @@ struct cldma_gpd {__le16 not_used2; }; +enum cldma_cfg { +CLDMA_SHARED_Q_CFG , +CLDMA_DEDICATED_Q_CFG , +}; +struct cldma_request {struct cldma_gpd *gpd;/* Virtual address for CPU */ dma_addr_t gpd_addr;/* Physical address for DMA */ @@ -82,6 +91,7 @@ struct cldma_queue {wait_queue_head_t req_wq;/* Only for TX */ struct workqueue_struct *worker;struct work_struct cldma_work; +int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb); };struct cldma_ctrl {@@ -101,24 +111,22 @@ struct cldma_ctrl {struct md_pm_entity *pm_entity;struct t7xx_cldma_hw hw_info;bool is_late_init; -int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb); }; +#define CLDMA_Q_IDX_DUMP 1#define GPD_FLAGS_HWO BIT(0)#define GPD_FLAGS_IOC BIT(7)#define GPD_DMAPOOL_ALIGN 16 -#define CLDMA_MTU 3584/* 3.5kB */ -int t7xx_cldma_alloc (enum cldma_id hif_id,struct t7xx_pci_dev *t7xx_dev);void t7xx_cldma_hif_hw_init (struct cldma_ctrl *md_ctrl);int t7xx_cldma_init (struct cldma_ctrl *md_ctrl);void t7xx_cldma_exit (struct cldma_ctrl *md_ctrl); -void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl); +void t7xx_cldma_switch_cfg (struct cldma_ctrl *md_ctrl,enum cldma_cfg cfg_id);void t7xx_cldma_start (struct cldma_ctrl *md_ctrl);int t7xx_cldma_stop (struct cldma_ctrl *md_ctrl);void t7xx_cldma_reset (struct cldma_ctrl *md_ctrl); -void t7xx_cldma_set_recv_skb (struct cldma_ctrl *md_ctrl, +void t7xx_cldma_set_recv_skb (struct cldma_queue *queue,int (*recv_skb)(struct cldma_queue *queue,struct sk_buff *skb));int t7xx_cldma_send_skb (struct cldma_ctrl *md_ctrl,int qno,struct sk_buff *skb);void t7xx_cldma_stop_all_qs (struct cldma_ctrl *md_ctrl,enum mtk_txrx tx_rx);drivers/net/wwan/t7xx/t7xx_modem_ops.c +2
-2@@ -529,7 +529,7 @@ static void t7xx_md_hk_wq(struct work_struct *work)/* Clear the HS2 EXIT event appended in core_reset() */ t7xx_fsm_clr_event (ctl,FSM_EVENT_MD_HS2_EXIT ); -t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_MD ]); +t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_MD ],CLDMA_SHARED_Q_CFG );t7xx_cldma_start (md->md_ctrl[CLDMA_ID_MD ]);t7xx_fsm_broadcast_state (ctl,MD_STATE_WAITING_FOR_HS2 ); md->core_md.handshake_ongoing = true;@@ -544,7 +544,7 @@ static void t7xx_ap_hk_wq(struct work_struct *work)/* Clear the HS2 EXIT event appended in t7xx_core_reset(). */ t7xx_fsm_clr_event (ctl,FSM_EVENT_AP_HS2_EXIT );t7xx_cldma_stop (md->md_ctrl[CLDMA_ID_AP ]); -t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_AP ]); +t7xx_cldma_switch_cfg (md->md_ctrl[CLDMA_ID_AP ],CLDMA_SHARED_Q_CFG );t7xx_cldma_start (md->md_ctrl[CLDMA_ID_AP ]); md->core_ap.handshake_ongoing = true;t7xx_core_hk_handler (md, &md->core_ap, ctl,FSM_EVENT_AP_HS2 ,FSM_EVENT_AP_HS2_EXIT );drivers/net/wwan/t7xx/t7xx_port.h +4
-0@@ -75,6 +75,8 @@ enum port_ch {PORT_CH_DSS6_TX =0x20df ,PORT_CH_DSS7_RX =0x20e0 ,PORT_CH_DSS7_TX =0x20e1 , + + PORT_CH_ID_UNIMPORTANT = 0xffff, };struct t7xx_port ;@@ -135,9 +137,11 @@ struct t7xx_port { }; }; +int t7xx_get_port_mtu (struct t7xx_port *port);struct sk_buff *t7xx_port_alloc_skb (int payload);struct sk_buff *t7xx_ctrl_alloc_skb (int payload);int t7xx_port_enqueue_skb (struct t7xx_port *port,struct sk_buff *skb); +int t7xx_port_send_raw_skb (struct t7xx_port *port,struct sk_buff *skb);int t7xx_port_send_skb (struct t7xx_port *port,struct sk_buff *skb,unsigned int pkt_header,unsigned int ex_msg); int t7xx_port_send_ctl_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned int msg,drivers/net/wwan/t7xx/t7xx_port_proxy.c +23
-1@@ -100,6 +100,18 @@ static const struct t7xx_port_conf t7xx_port_conf[] = { }, }; +static struct t7xx_port_conf t7xx_early_port_conf[] = { + { + .tx_ch =PORT_CH_ID_UNIMPORTANT , + .rx_ch =PORT_CH_ID_UNIMPORTANT , + .txq_index =CLDMA_Q_IDX_DUMP , + .rxq_index =CLDMA_Q_IDX_DUMP , + .txq_exp_index =CLDMA_Q_IDX_DUMP , + .rxq_exp_index =CLDMA_Q_IDX_DUMP , + .path_id =CLDMA_ID_AP , + }, +}; +static struct t7xx_port *t7xx_proxy_get_port_by_ch (struct port_proxy *port_prox,enum port_ch ch) {const struct t7xx_port_conf *port_conf;@@ -214,7 +226,17 @@ int t7xx_port_enqueue_skb(struct t7xx_port *port, struct sk_buff *skb)return 0 ; } -static int t7xx_port_send_raw_skb (struct t7xx_port *port,struct sk_buff *skb) +int t7xx_get_port_mtu (struct t7xx_port *port) +{ +enum cldma_id path_id = port->port_conf->path_id; +int tx_qno =t7xx_port_get_queue_no (port); +struct cldma_ctrl *md_ctrl; + + md_ctrl = port->t7xx_dev->md->md_ctrl[path_id]; +return md_ctrl->tx_ring[tx_qno].pkt_size; +} + +int t7xx_port_send_raw_skb (struct t7xx_port *port,struct sk_buff *skb) {enum cldma_id path_id = port->port_conf->path_id;struct cldma_ctrl *md_ctrl;@@ -329,6 +351,30 @@ static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox) } }
Quoted 12 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_setup_ch_mapping(struct port_proxy *port_prox) · line 363
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +10
-0+int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb) +{ +struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev; +struct port_proxy *port_prox = t7xx_dev->md->port_prox; +const struct t7xx_port_conf *port_conf; +struct t7xx_port *port; +int ret; + + port = &port_prox->ports[0 ]; +if (WARN_ON (port->port_conf->rxq_index != queue->index)) {
WARN_ON_ONCEwould seem enough to alert to this problem and not as spammy?
Will change it to WARN_ON_ONCE.
Quoted 54 lines
Quoted 54 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +38
-1+dev_kfree_skb_any (skb); +return -EINVAL ; + } + + port_conf = port->port_conf; + ret = port_conf->ops->recv_skb (port, skb); +if (ret <0 && ret != -ENOBUFS ) { +dev_err (port->dev,"drop on RX ch %d, %d\n" , port_conf->rx_ch, ret); +dev_kfree_skb_any (skb); + } + +return ret; +} +static struct t7xx_port *t7xx_port_proxy_find_port (struct t7xx_pci_dev *t7xx_dev,struct cldma_queue *queue,u16 channel) {@@ -359,7 +405,7 @@ static struct t7xx_port *t7xx_port_proxy_find_port(struct t7xx_pci_dev *t7xx_dev** 0 - Packet consumed. ** -ERROR - Failed to process skb. */ -static int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb) +int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb) {struct ccci_header *ccci_h = (struct ccci_header *)skb->data;struct t7xx_pci_dev *t7xx_dev = queue->md_ctrl->t7xx_dev;@@ -451,26 +497,47 @@ static void t7xx_proxy_init_all_ports(struct t7xx_modem *md)t7xx_proxy_setup_ch_mapping (port_prox); } +void t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id) +{ +struct port_proxy *port_prox = md->port_prox; +const struct t7xx_port_conf *port_conf; +u32 port_count; +int i; + +t7xx_port_proxy_uninit (port_prox); + +if (cfg_id ==PORT_CFG_ID_EARLY ) { + port_conf = t7xx_early_port_conf; + port_count =ARRAY_SIZE (t7xx_early_port_conf); + }else { + port_conf = t7xx_port_conf; + port_count =ARRAY_SIZE (t7xx_port_conf); + } + +for (i =0 ; i < port_count; i++) + port_prox->ports[i].port_conf = &port_conf[i]; + + port_prox->cfg_id = cfg_id; + port_prox->port_count = port_count; +t7xx_proxy_init_all_ports (md);
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) · line 528
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +3
-0+} +static int t7xx_proxy_alloc (struct t7xx_modem *md) { +u32 early_port_count =ARRAY_SIZE (t7xx_early_port_conf);unsigned int port_count =ARRAY_SIZE (t7xx_port_conf);Why these are of different types?
Will keep type of early_port_count same as port_count.
Quoted 11 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) · line 532
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +1
-3struct device *dev = &md->t7xx_dev->pdev->dev;struct port_proxy *port_prox; -int i; - port_prox =devm_kzalloc (dev,sizeof (*port_prox) +sizeof (struct t7xx_port ) * port_count, -GFP_KERNEL ); + port_count =max_t (u32, port_count, early_port_count);If vars are using same type, you could do just
max()
Quoted 7 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c static void t7xx_proxy_init_all_ports(struct t7xx_modem *md) · line 533
Quoted 1 line
drivers/net/wwan/t7xx/t7xx_port_proxy.c +1
-0+ port_prox =devm_kzalloc (dev,struct_size (port_prox, ports, port_count),GFP_KERNEL );include <
linux/overflow.h> missing?This opencoding ->
struct_size()seems independent change, no? If so, it should be in a separate patch. (It's a good change still and should be done.)
Ya. this is an independent change.
I will drop it from this patch and push it as a seperate patch.
Quoted 33 lines
Quoted 33 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.c +1
-7if (!port_prox)return -ENOMEM ; md->port_prox = port_prox; port_prox->dev = dev; +t7xx_port_proxy_set_cfg (md,PORT_CFG_ID_EARLY ); -for (i =0 ; i < port_count; i++) - port_prox->ports[i].port_conf = &t7xx_port_conf[i]; - - port_prox->port_count = port_count; -t7xx_proxy_init_all_ports (md);return 0 ; }@@ -492,8 +559,6 @@ int t7xx_port_proxy_init(struct t7xx_modem *md)if (ret)return ret; -t7xx_cldma_set_recv_skb (md->md_ctrl[CLDMA_ID_AP ], t7xx_port_proxy_recv_skb); -t7xx_cldma_set_recv_skb (md->md_ctrl[CLDMA_ID_MD ], t7xx_port_proxy_recv_skb);return 0 ; }drivers/net/wwan/t7xx/t7xx_port_proxy.h +0
-0@@ -31,12 +31,19 @@#define RX_QUEUE_MAXLEN 32#define CTRL_QUEUE_MAXLEN 16
Quoted 16 lines
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.h +4
-0+enum port_cfg_id { +PORT_CFG_ID_INVALID , +PORT_CFG_ID_NORMAL , +PORT_CFG_ID_EARLY ,drivers/net/wwan/t7xx/t7xx_port_proxy.h line 46
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.h +4
-1+}; +struct port_proxy {int port_count;struct list_head rx_ch_ports[PORT_CH_ID_MASK +1 ];struct list_head queue_ports[CLDMA_NUM ][MTK_QUEUES ];struct device *dev; -struct t7xx_port ports[]; +enum port_cfg_id cfg_id; +struct t7xx_port ports[];Spurious space change.
Will check and fix it.
Quoted 124 lines
Quoted 124 lines
drivers/net/wwan/t7xx/t7xx_port_proxy.h +3
-0};struct ccci_header {@@ -98,5 +105,8 @@ void t7xx_port_proxy_md_status_notify(struct port_proxy *port_prox, unsigned intint t7xx_port_enum_msg_handler (struct t7xx_modem *md,void *msg);int t7xx_port_proxy_chl_enable_disable (struct port_proxy *port_prox,unsigned int ch_id,bool en_flag); +void t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id); +int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb); +int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb);#endif /* __T7XX_PORT_PROXY_H__ */ drivers/net/wwan/t7xx/t7xx_port_wwan.c +2
-1@@ -54,7 +54,7 @@ static void t7xx_port_ctrl_stop(struct wwan_port *port)static int t7xx_port_ctrl_tx (struct wwan_port *port,struct sk_buff *skb) {struct t7xx_port *port_private =wwan_port_get_drvdata (port); -size_t len, offset, chunk_len =0 , txq_mtu =CLDMA_MTU ; +size_t len, offset, chunk_len =0 , txq_mtu;const struct t7xx_port_conf *port_conf;struct t7xx_fsm_ctl *ctl;enum md_state md_state;@@ -72,6 +72,7 @@ static int t7xx_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)return -ENODEV ; } + txq_mtu =t7xx_get_port_mtu (port_private);for (offset =0 ; offset < len; offset += chunk_len) {struct sk_buff *skb_ccci;int ret;drivers/net/wwan/t7xx/t7xx_reg.h +18
-3@@ -102,10 +102,26 @@ enum t7xx_pm_resume_state { };#define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c -#define MISC_STAGE_MASK GENMASK(2, 0) -#define MISC_RESET_TYPE_PLDR BIT(26)#define MISC_RESET_TYPE_FLDR BIT(27) -#define LINUX_STAGE 4 +#define MISC_RESET_TYPE_PLDR BIT(26) +#define MISC_LK_EVENT_MASK GENMASK(11, 8) + +enum lk_event_id { +LK_EVENT_NORMAL =0 , +LK_EVENT_CREATE_PD_PORT =1 , +LK_EVENT_CREATE_POST_DL_PORT =2 , +LK_EVENT_RESET =7 , +}; + +#define MISC_STAGE_MASK GENMASK(2, 0) +enum t7xx_device_stage { +T7XX_DEV_STAGE_INIT =0 , +T7XX_DEV_STAGE_BROM_PRE =1 , +T7XX_DEV_STAGE_BROM_POST =2 , +T7XX_DEV_STAGE_LK =3 , +T7XX_DEV_STAGE_LINUX =4 , +};#define T7XX_PCIE_RESOURCE_STATUS 0x0d28#define T7XX_PCIE_RESOURCE_STS_MSK GENMASK(4, 0)drivers/net/wwan/t7xx/t7xx_state_monitor.c +31
-1@@ -206,6 +206,34 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commfsm_finish_command (ctl, cmd,0 ); } +static void t7xx_lk_stage_event_handling (struct t7xx_fsm_ctl *ctl,unsigned int status) +{ +struct t7xx_modem *md = ctl->md; +struct cldma_ctrl *md_ctrl; +enum lk_event_id lk_event; +struct device *dev; + + dev = &md->t7xx_dev->pdev->dev; + lk_event =FIELD_GET (MISC_LK_EVENT_MASK , status); +switch (lk_event) { +case LK_EVENT_NORMAL : +case LK_EVENT_RESET : +break ; + +case LK_EVENT_CREATE_PD_PORT : + md_ctrl = md->md_ctrl[CLDMA_ID_AP ]; +t7xx_cldma_hif_hw_init (md_ctrl); +t7xx_cldma_stop (md_ctrl); +t7xx_cldma_switch_cfg (md_ctrl,CLDMA_DEDICATED_Q_CFG ); +t7xx_cldma_start (md_ctrl); +break ; + +default : +dev_err (dev,"Invalid LK event %d\n" , lk_event); +break ; + } +} +static int fsm_stopped_handler (struct t7xx_fsm_ctl *ctl) { ctl->curr_state =FSM_STATE_STOPPED ;@@ -317,7 +345,8 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl)static void fsm_routine_start (struct t7xx_fsm_ctl *ctl,struct t7xx_fsm_command *cmd) {struct t7xx_modem *md = ctl->md; -u32 dev_status; +struct device *dev; +u32 status;int ret;if (!md)@@ -329,23 +358,56 @@ static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commandreturn ; } + dev = &md->t7xx_dev->pdev->dev; ctl->curr_state =FSM_STATE_PRE_START ;t7xx_md_event_notify (md,FSM_PRE_START );
Quoted 15 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command · line 372
Quoted 12 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +7
-4- ret =read_poll_timeout (ioread32, dev_status, - (dev_status &MISC_STAGE_MASK ) ==LINUX_STAGE ,20000 ,2000000 , - false,IREG_BASE (md->t7xx_dev) +T7XX_PCIE_MISC_DEV_STATUS ); + ret =read_poll_timeout (ioread32, status, + ((status &MISC_STAGE_MASK ) ==T7XX_DEV_STAGE_LINUX ) || + ((status &MISC_STAGE_MASK ) ==T7XX_DEV_STAGE_LK ),100000 , +20000000 , false,IREG_BASE (md->t7xx_dev) + +T7XX_PCIE_MISC_DEV_STATUS ); +if (ret) { -struct device *dev = &md->t7xx_dev->pdev->dev; + ret = -ETIMEDOUT ;Is this necessary? Can
read_poll_timeout()return anything else than-ETIMEDOUT??
Not required will use return of read_poll_timeout().
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command · line 373
Quoted 2 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +1
-0+dev_err (dev,"read poll %d\n" , ret);read poll timeout ?
Will change it to "read poll timeout".
Quoted 4 lines
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +2
-0+ goto finish_command; + }
Quoted 13 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command · line 384
Quoted 11 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +8
-3-fsm_finish_command (ctl, cmd, -ETIMEDOUT ); -dev_err (dev,"Invalid device status 0x%lx\n" , dev_status &MISC_STAGE_MASK ); -return ; +if (status != ctl->prev_status) { +u32 stage =FIELD_GET (MISC_STAGE_MASK , status); + +switch (stage) { +case T7XX_DEV_STAGE_INIT : +case T7XX_DEV_STAGE_BROM_PRE : +case T7XX_DEV_STAGE_BROM_POST : +dev_info (dev,"BROM_STAGE Entered\n" );Somewhat questionable if info level is really desirable for these?
Will change it dev_dbg.
Quoted 55 lines
Quoted 54 lines
drivers/net/wwan/t7xx/t7xx_state_monitor.c +25
-3+ ret =t7xx_fsm_append_cmd (ctl,FSM_CMD_START ,0 ); +break ; + +case T7XX_DEV_STAGE_LK : +dev_info (dev,"LK_STAGE Entered\n" ); +t7xx_lk_stage_event_handling (ctl, status); +break ; + +case T7XX_DEV_STAGE_LINUX : +dev_info (dev,"LINUX_STAGE Entered\n" ); +t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_AP ]); +t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_MD ]); +t7xx_mhccif_mask_clr (md->t7xx_dev,D2H_INT_PORT_ENUM | +D2H_INT_ASYNC_MD_HK |D2H_INT_ASYNC_AP_HK ); +t7xx_port_proxy_set_cfg (md,PORT_CFG_ID_NORMAL ); + ret =fsm_routine_starting (ctl); +break ; + +default : +break ; + } + ctl->prev_status = status; } -t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_AP ]); -t7xx_cldma_hif_hw_init (md->md_ctrl[CLDMA_ID_MD ]); -fsm_finish_command (ctl, cmd,fsm_routine_starting (ctl)); +finish_command: +fsm_finish_command (ctl, cmd, ret); }static int fsm_main_thread (void *data)@@ -516,6 +578,7 @@ void t7xx_fsm_reset(struct t7xx_modem *md)fsm_flush_event_cmd_qs (ctl); ctl->curr_state =FSM_STATE_STOPPED ; ctl->exp_flg = false; + ctl->prev_status =0 ; }int t7xx_fsm_init (struct t7xx_modem *md)drivers/net/wwan/t7xx/t7xx_state_monitor.h +1
-0@@ -96,6 +96,7 @@ struct t7xx_fsm_ctl {bool exp_flg;spinlock_t notifier_lock;/* Protects notifier list */ struct list_head notifier_list; +u32 prev_status; };struct t7xx_fsm_event {
Signature · 1 line
Chetan
PATCH v4 3/5 net: wwan: t7xx: PCIe reset rescan
In reply to [email protected]From: M Chetan Kumar <[email protected]>
PCI rescan module implements "rescan work queue". In firmware flashing or coredump collection procedure WWAN device is programmed to boot in fastboot mode and a work item is scheduled for removal & detection.
The WWAN device is reset using APCI call as part driver removal flow. Work queue rescans pci bus at fixed interval for device detection, later when device is detect work queue exits.
--
v4:
* Change "is still exist" to "still exists".
v3:
* No Change.
v2:
* Drop empty line inside critical sections.
* Correct log message.
* Correct logic inside t7xx_always_match().
* Drop hp_enable changes.
* Drop g_ prefix from t7xx_rescan_ctx.
* Use tab before comment in struct decl.
* Remove extra white space.
* Drop modem exception state check.
* Crit section newlines.
* Remove unnecessary header files inclusion.
* Drop spinlock around reset and rescan flow.
--- drivers/net/wwan/t7xx/Makefile | 3 +- drivers/net/wwan/t7xx/t7xx_modem_ops.c | 3 + drivers/net/wwan/t7xx/t7xx_pci.c | 56 ++++++++++++++- drivers/net/wwan/t7xx/t7xx_pci_rescan.c | 96 +++++++++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_pci_rescan.h | 28 ++++++++ 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.c create mode 100644 drivers/net/wwan/t7xx/t7xx_pci_rescan.h
drivers/net/wwan/t7xx/Makefile +2 -1
@@ -17,7 +17,8 @@ mtk_t7xx-y:= t7xx_pci.o \ t7xx_hif_dpmaif_tx.o \ t7xx_hif_dpmaif_rx.o \ t7xx_dpmaif.o \ - t7xx_netdev.o + t7xx_netdev.o \ + t7xx_pci_rescan.o mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \ t7xx_port_trace.o \
drivers/net/wwan/t7xx/t7xx_modem_ops.c +3 -0
@@ -37,6 +37,7 @@#include "t7xx_modem_ops.h" #include "t7xx_netdev.h" #include "t7xx_pci.h" +#include "t7xx_pci_rescan.h" #include "t7xx_pcie_mac.h" #include "t7xx_port.h" #include "t7xx_port_proxy.h"
@@ -194,6 +195,8 @@ static irqreturn_t t7xx_rgu_isr_thread(int irq, void *data)msleep (RGU_RESET_DELAY_MS );t7xx_reset_device_via_pmic (t7xx_dev); +t7xx_rescan_queue_work (t7xx_dev->pdev); +return IRQ_HANDLED ; }
drivers/net/wwan/t7xx/t7xx_pci.c +55 -1
74 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_pci_rescan.c new file +96 -0
96 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_pci_rescan.h new file +28 -0
@@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: GPL-2.0-only +* +* Copyright (c) 2021, MediaTek Inc. +* Copyright (c) 2021-2023, Intel Corporation. +*/ + +#ifndef __T7XX_PCI_RESCAN_H__ +#define __T7XX_PCI_RESCAN_H__ + +#define MTK_RESCAN_WQ "mtk_rescan_wq" + +#define DELAY_RESCAN_MTIME 1000 +#define RESCAN_RETRIES 35 + +struct remove_rescan_context { +struct work_struct service_task; +struct workqueue_struct *pcie_rescan_wq; +struct pci_dev *dev; +atomic_t rescan_done; +}; + +void t7xx_pci_dev_rescan (void ); +void t7xx_rescan_queue_work (struct pci_dev *pdev); +int t7xx_rescan_init (void ); +void t7xx_rescan_deinit (void ); +void t7xx_rescan_done (void ); + +#endif /* __T7XX_PCI_RESCAN_H__ */
Signature · 1 line
2.34.1
PATCH v4 4/5 net: wwan: t7xx: Enable devlink based fw flashing and coredump collection
In reply to [email protected]From: M Chetan Kumar <[email protected]>
Adds support for t7xx wwan device firmware flashing & coredump collection using devlink.
1> Driver Registers with Devlink framework.
2> Implements devlink ops flash_update callback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.
On early detection of wwan device in fastboot mode driver sets up CLDMA0 HW tx/rx queues for raw data transfer and then registers to devlink framework. On user space application issuing command for firmware update the driver sends fastboot flash command & firmware to program NAND.
In flashing procedure the fastboot command & response are exchanged between driver and device. Once firmware flashing is success completion status is reported to user space application.
Below is the devlink command usage for firmware flashing
$devlink dev flash pci/$BDF file ABC.img component ABC
Note: ABC.img is the firmware to be programmed to "ABC" partition.
In case of coredump collection when wwan device encounters an exception it reboots & stays in fastboot mode for coredump collection by host driver. On detecting exception state driver collects the core dump, creates the devlink region & reports an event to user space application for dump collection. The user space application invokes devlink region read command for dump collection.
Below are the devlink commands used for coredump collection.
devlink region new pci/$BDF/mr_dump
devlink region read pci/$BDF/mr_dump snapshot $ID address $ADD length $LEN devlink region del pci/$BDF/mr_dump snapshot $ID
--
v4:
* cppcheck - reduce variableScope for
- skb_ccci & ret var in t7xx_port_ap_msg_tx.
- ret in t7xx_devlink_port_read.
- len, skb & ret in t7xx_devlink_port_write.
v3:
* No Change.
v2:
* Remove devlink pointer inside the port state container.
* Rename t7xx_devlink_region_list to t7xx_devlink_region_infos &
use region index in initialization.
* Change t7xx_devlink_region_infos to const.
* Handle remaining packet data if the buffer is less than the skb data.
* Drop t7xx_devlink_fb_send_buffer(), push fragmentation logic to t7xx_devlink_port_write().
* Add "\n" to log message.
* Move mrdump_region allocation to devlink initialization.
* Drop snprintf for CTS command fill.
* Drop intermediate mdata buffer & zipsize.
* For mcmd use strcmp instead of strncmp.
* Drop set_fastboot_dl instead use devlink param for fastboot operational mode.
* Drop unnecessary logs.
* Change t7xx_devlink_create_region to t7xx_devlink_create_regions.
* Use BUILD_BUG_ON on array size checks.
* Use ARRAY_SIZE inside loop.
* Correct indentation.
* Drop odd empty line.
* Push common devlink initialization code to t7xx_devlink_init.
* Use skb_queue_purge instead of running loop to free skbs.
* Change t7xx_regions index to enums.
* Remove dev in devlink container.
* Refactor struct to separate out devlink static and dynamic data structs.
* Use min_t.
* Drop unnecessary var assginment during initialization.
* Change while() to for().
* Correct size check.
* Rename result to ret.
* Clean-up error handling path in t7xx_devlink_fb_get_core & t7xx_devlink_fb_dump_log.
* Drop __func__ in log message.
* Change NOTY to NOTIFY.
* Push channel enable or disable cb to port proxy.
* Use array index in t7xx_devlink_region_list initialization.
* Drop t7xx_port_proxy_get_port_by_name() instead access port name directly via port_prox.
* Drop udev based event reporting logic.
* Drop get_core prefix in goto label.
* Remove unnessary header files.
* Allocate memory for mrdump_region->buf inside get_core.
* Remove 'region->buf' in t7xx_devlink_region_snapshot.
* Destroy workqueue on following error case in 'devlink_init'.
* Remove useless checks(dl->mode) and condition(dl->wq).
* Support devlink component versioning.
* Kconfig changes to select devlink.
--- drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/t7xx/Makefile | 4 +- drivers/net/wwan/t7xx/t7xx_pci.c | 16 +- drivers/net/wwan/t7xx/t7xx_pci.h | 2 + drivers/net/wwan/t7xx/t7xx_port.h | 2 + drivers/net/wwan/t7xx/t7xx_port_ap_msg.c | 79 +++ drivers/net/wwan/t7xx/t7xx_port_ap_msg.h | 11 + drivers/net/wwan/t7xx/t7xx_port_devlink.c | 669 +++++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_port_devlink.h | 86 +++ drivers/net/wwan/t7xx/t7xx_port_proxy.c | 32 + drivers/net/wwan/t7xx/t7xx_port_proxy.h | 4 + drivers/net/wwan/t7xx/t7xx_port_wwan.c | 22 +- drivers/net/wwan/t7xx/t7xx_reg.h | 6 + drivers/net/wwan/t7xx/t7xx_state_monitor.c | 37 +- 14 files changed, 945 insertions(+), 26 deletions(-) create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.h create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.h
drivers/net/wwan/Kconfig +1 -0
@@ -108,6 +108,7 @@ config IOSM config MTK_T7XX tristate "MediaTek PCIe 5G WWAN modem T7xx device" depends on PCI + select NET_DEVLINK select RELAY if WWAN_DEBUGFS help Enables MediaTek PCIe based 5G WWAN modem (T7xx series) device.
drivers/net/wwan/t7xx/Makefile +3 -1
@@ -18,7 +18,9 @@ mtk_t7xx-y:= t7xx_pci.o \ t7xx_hif_dpmaif_rx.o \ t7xx_dpmaif.o \ t7xx_netdev.o \ - t7xx_pci_rescan.o + t7xx_pci_rescan.o \ + t7xx_port_devlink.o \ + t7xx_port_ap_msg.o mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \ t7xx_port_trace.o \
drivers/net/wwan/t7xx/t7xx_pci.c +13 -3
@@ -40,6 +40,7 @@#include "t7xx_pci.h" #include "t7xx_pci_rescan.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_devlink.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h"
@@ -107,7 +108,7 @@ static int t7xx_pci_pm_init(struct t7xx_pci_dev *t7xx_dev)pm_runtime_set_autosuspend_delay (&pdev->dev,PM_AUTOSUSPEND_MS );pm_runtime_use_autosuspend (&pdev->dev); -return t7xx_wait_pm_config (t7xx_dev); +return 0 ; }void t7xx_pci_pm_init_late (struct t7xx_pci_dev *t7xx_dev)
@@ -704,16 +705,20 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)t7xx_pci_infracfg_ao_calc (t7xx_dev);t7xx_mhccif_init (t7xx_dev); - ret =t7xx_md_init (t7xx_dev); + ret =t7xx_devlink_register (t7xx_dev);if (ret)return ret; + ret =t7xx_md_init (t7xx_dev); +if (ret) + goto err_devlink_unregister; +t7xx_pcie_mac_interrupts_dis (t7xx_dev); ret =t7xx_interrupt_init (t7xx_dev);if (ret) {t7xx_md_exit (t7xx_dev); -return ret; + goto err_devlink_unregister; }t7xx_rescan_done ();
@@ -721,6 +726,10 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)t7xx_pcie_mac_interrupts_en (t7xx_dev);return 0 ; + +err_devlink_unregister: +t7xx_devlink_unregister (t7xx_dev); +return ret; }static void t7xx_pci_remove (struct pci_dev *pdev)
@@ -730,6 +739,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev) t7xx_dev =pci_get_drvdata (pdev);t7xx_md_exit (t7xx_dev); +t7xx_devlink_unregister (t7xx_dev);for (i =0 ; i <EXT_INT_NUM ; i++) {if (!t7xx_dev->intr_handler[i])
drivers/net/wwan/t7xx/t7xx_pci.h +2 -0
@@ -59,6 +59,7 @@ typedef irqreturn_t (*t7xx_intr_callback)(int irq, void *param);* @md_pm_lock: protects PCIe sleep lock * @sleep_disable_count: PCIe L1.2 lock counter * @sleep_lock_acquire: indicates that sleep has been disabled +* @dl: devlink struct */ struct t7xx_pci_dev {t7xx_intr_callback intr_handler[EXT_INT_NUM ];
@@ -81,6 +82,7 @@ struct t7xx_pci_dev {#ifdef CONFIG_WWAN_DEBUGFS struct dentry *debugfs_dir;#endif +struct t7xx_devlink *dl; };enum t7xx_pm_id {
drivers/net/wwan/t7xx/t7xx_port.h +2 -0
@@ -42,6 +42,8 @@ enum port_ch {/* to AP */ PORT_CH_AP_CONTROL_RX =0x1000 ,PORT_CH_AP_CONTROL_TX =0x1001 , +PORT_CH_AP_MSG_RX =0x101E , +PORT_CH_AP_MSG_TX =0x101F ,/* to MD */ PORT_CH_CONTROL_RX = 0x2000,
drivers/net/wwan/t7xx/t7xx_port_ap_msg.c new file +79 -0
79 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_port_ap_msg.h new file +11 -0
@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only +* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#ifndef __T7XX_PORT_AP_MSG_H__ +#define __T7XX_PORT_AP_MSG_H__ + +int t7xx_port_ap_msg_tx (struct t7xx_port *port,char *buff,size_t len); + +#endif /* __T7XX_PORT_AP_MSG_H__ */
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +669 -0
669 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_port_devlink.h new file +86 -0
86 lines not on this page · raw message
drivers/net/wwan/t7xx/t7xx_port_proxy.c +32 -0
@@ -40,6 +40,7 @@#define Q_IDX_CTRL 0#define Q_IDX_MBIM 2#define Q_IDX_AT_CMD 5 +#define Q_IDX_AP_MSG 2#define INVALID_SEQ_NUM GENMASK(15, 0)
@@ -97,7 +98,18 @@ static const struct t7xx_port_conf t7xx_port_conf[] = { .path_id = CLDMA_ID_AP, .ops = &ctl_port_ops, .name = "t7xx_ap_ctrl", + }, { + .tx_ch = PORT_CH_AP_MSG_TX, + .rx_ch = PORT_CH_AP_MSG_RX, + .txq_index = Q_IDX_AP_MSG, + .rxq_index = Q_IDX_AP_MSG, + .txq_exp_index = Q_IDX_AP_MSG, + .rxq_exp_index = Q_IDX_AP_MSG, + .path_id = CLDMA_ID_AP, + .ops = &ap_msg_port_ops, + .name = "ap_msg", }, + };static struct t7xx_port_conf t7xx_early_port_conf[] = {
@@ -109,6 +121,8 @@ static struct t7xx_port_conf t7xx_early_port_conf[] = { .txq_exp_index = CLDMA_Q_IDX_DUMP, .rxq_exp_index = CLDMA_Q_IDX_DUMP, .path_id = CLDMA_ID_AP, + .ops = &devlink_port_ops, + .name = "devlink", }, };
@@ -325,6 +339,24 @@ int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned intreturn t7xx_port_send_ccci_skb (port, skb, pkt_header, ex_msg); } +int t7xx_port_enable_chl (struct t7xx_port *port) +{ +spin_lock (&port->port_update_lock); + port->chan_enable = true; +spin_unlock (&port->port_update_lock); + +return 0 ; +} + +int t7xx_port_disable_chl (struct t7xx_port *port) +{ +spin_lock (&port->port_update_lock); + port->chan_enable = false; +spin_unlock (&port->port_update_lock); + +return 0 ; +} +static void t7xx_proxy_setup_ch_mapping (struct port_proxy *port_prox) {struct t7xx_port *port;
drivers/net/wwan/t7xx/t7xx_port_proxy.h +4 -0
@@ -93,6 +93,8 @@ struct ctrl_msg_header {/* Port operations mapping */ extern struct port_ops wwan_sub_port_ops;extern struct port_ops ctl_port_ops; +extern struct port_ops devlink_port_ops; +extern struct port_ops ap_msg_port_ops;#ifdef CONFIG_WWAN_DEBUGFS extern struct port_ops t7xx_trace_port_ops;
@@ -108,5 +110,7 @@ int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned invoid t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id);int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb);int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb); +int t7xx_port_enable_chl (struct t7xx_port *port); +int t7xx_port_disable_chl (struct t7xx_port *port);#endif /* __T7XX_PORT_PROXY_H__ */
drivers/net/wwan/t7xx/t7xx_port_wwan.c +2 -20
@@ -134,24 +134,6 @@ static int t7xx_port_wwan_recv_skb(struct t7xx_port *port, struct sk_buff *skb)return 0 ; } -static int t7xx_port_wwan_enable_chl (struct t7xx_port *port) -{ -spin_lock (&port->port_update_lock); - port->chan_enable = true; -spin_unlock (&port->port_update_lock); - -return 0 ; -} - -static int t7xx_port_wwan_disable_chl (struct t7xx_port *port) -{ -spin_lock (&port->port_update_lock); - port->chan_enable = false; -spin_unlock (&port->port_update_lock); - -return 0 ; -} -static void t7xx_port_wwan_md_state_notify (struct t7xx_port *port,unsigned int state) {const struct t7xx_port_conf *port_conf = port->port_conf;
@@ -171,7 +153,7 @@ struct port_ops wwan_sub_port_ops = { .init = t7xx_port_wwan_init, .recv_skb = t7xx_port_wwan_recv_skb, .uninit = t7xx_port_wwan_uninit, - .enable_chl = t7xx_port_wwan_enable_chl, - .disable_chl = t7xx_port_wwan_disable_chl, + .enable_chl = t7xx_port_enable_chl, + .disable_chl = t7xx_port_disable_chl, .md_state_notify = t7xx_port_wwan_md_state_notify, };
drivers/net/wwan/t7xx/t7xx_reg.h +6 -0
@@ -101,10 +101,16 @@ enum t7xx_pm_resume_state { PM_RESUME_REG_STATE_L2_EXP, }; +enum host_event_e { +HOST_EVENT_INIT =0 , +FASTBOOT_DL_NOTIFY =0x3 , +}; +#define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c#define MISC_RESET_TYPE_FLDR BIT(27)#define MISC_RESET_TYPE_PLDR BIT(26)#define MISC_LK_EVENT_MASK GENMASK(11, 8) +#define HOST_EVENT_MASK GENMASK(31, 28)enum lk_event_id {LK_EVENT_NORMAL =0 ,
drivers/net/wwan/t7xx/t7xx_state_monitor.c +35 -2
@@ -37,6 +37,7 @@#include "t7xx_modem_ops.h" #include "t7xx_pci.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_devlink.h" #include "t7xx_port_proxy.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h"
@@ -206,11 +207,22 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commfsm_finish_command (ctl, cmd,0 ); } +static void t7xx_host_event_notify (struct t7xx_modem *md,unsigned int event_id) +{ +u32 value; + + value =ioread32 (IREG_BASE (md->t7xx_dev) +T7XX_PCIE_MISC_DEV_STATUS ); + value &= ~HOST_EVENT_MASK ; + value |=FIELD_PREP (HOST_EVENT_MASK , event_id); +iowrite32 (value,IREG_BASE (md->t7xx_dev) +T7XX_PCIE_MISC_DEV_STATUS ); +} +static void t7xx_lk_stage_event_handling (struct t7xx_fsm_ctl *ctl,unsigned int status) {struct t7xx_modem *md = ctl->md;struct cldma_ctrl *md_ctrl;enum lk_event_id lk_event; +struct t7xx_port *port;struct device *dev; dev = &md->t7xx_dev->pdev->dev;
@@ -221,10 +233,21 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned intbreak ;case LK_EVENT_CREATE_PD_PORT : +case LK_EVENT_CREATE_POST_DL_PORT : md_ctrl = md->md_ctrl[CLDMA_ID_AP ];t7xx_cldma_hif_hw_init (md_ctrl);t7xx_cldma_stop (md_ctrl);t7xx_cldma_switch_cfg (md_ctrl,CLDMA_DEDICATED_Q_CFG ); + port = ctl->md->t7xx_dev->dl->port; +if (WARN_ON (!port)) +return ; + +if (lk_event ==LK_EVENT_CREATE_PD_PORT ) + md->t7xx_dev->dl->mode =T7XX_FB_DUMP_MODE ; +else + md->t7xx_dev->dl->mode =T7XX_FB_DL_MODE ; + + port->port_conf->ops->enable_chl (port);t7xx_cldma_start (md_ctrl);break ;
@@ -271,13 +294,23 @@ static void fsm_routine_stopping(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commat7xx_cldma_stop (md_ctrl);if (!ctl->md->rgu_irq_asserted) { +if (t7xx_devlink_param_get_fastboot (t7xx_dev->dl->ctx)) +t7xx_host_event_notify (ctl->md,FASTBOOT_DL_NOTIFY ); +t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DRM_DISABLE_AP );/* Wait for the DRM disable to take effect */ msleep (FSM_DRM_DISABLE_DELAY_MS ); - err =t7xx_acpi_fldr_func (t7xx_dev); -if (err) +if (t7xx_devlink_param_get_fastboot (t7xx_dev->dl->ctx)) { +/* Do not try fldr because device will always wait for +* MHCCIF bit 13 in fastboot download flow. +*/ t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DEVICE_RESET ); + }else { + err =t7xx_acpi_fldr_func (t7xx_dev); +if (err) +t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DEVICE_RESET ); + } }fsm_finish_command (ctl, cmd,fsm_stopped_handler (ctl));
Signature · 1 line
2.34.1
Re: [PATCH v4 net-next 4/5] net: wwan: t7xx: Enable devlink based fw flashing and coredump collection
Quoted 432 lines · On Mon, 16 Jan 2023, [email protected] wrote:
From: M Chetan Kumar <[email protected]>
Adds support for t7xx wwan device firmware flashing & coredump collection using devlink.
1> Driver Registers with Devlink framework.
2> Implements devlink opsflash_updatecallback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.On early detection of wwan device in fastboot mode driver sets up CLDMA0 HW tx/rx queues for raw data transfer and then registers to devlink framework. On user space application issuing command for firmware update the driver sends fastboot flash command & firmware to program NAND.
In flashing procedure the fastboot command & response are exchanged between driver and device. Once firmware flashing is success completion status is reported to user space application.
Below is the devlink command usage for firmware flashing
$devlink dev flash pci/$BDF file ABC.img component ABC
Note: ABC.img is the firmware to be programmed to "ABC" partition.
In case of coredump collection when wwan device encounters an exception it reboots & stays in fastboot mode for coredump collection by host driver. On detecting exception state driver collects the core dump, creates the devlink region & reports an event to user space application for dump collection. The user space application invokes devlink region read command for dump collection.
Below are the devlink commands used for coredump collection.
devlink region new pci/$BDF/mr_dump
devlink region read pci/$BDF/mr_dump snapshot $ID address $ADD length $LEN devlink region del pci/$BDF/mr_dump snapshot $IDSigned-off-by M Chetan Kumar <[email protected]>Signed-off-by Devegowda Chandrashekar <[email protected]>Signed-off-by Mishra Soumya Prakash <[email protected]>Reviewed-by Jesse Brandeburg <[email protected]>--
v4:
* cppcheck - reduce variableScope for
-skb_ccci& ret var int7xx_port_ap_msg_tx.
- ret int7xx_devlink_port_read.
- len, skb & ret int7xx_devlink_port_write.
v3:
* No Change.
v2:
* Remove devlink pointer inside the port state container.
* Renamet7xx_devlink_region_listtot7xx_devlink_region_infos&
use region index in initialization.
* Changet7xx_devlink_region_infosto const.
* Handle remaining packet data if the buffer is less than the skb data.
* Dropt7xx_devlink_fb_send_buffer(), push fragmentation logic tot7xx_devlink_port_write().
* Add "\n" to log message.
* Movemrdump_regionallocation to devlink initialization.
* Drop snprintf for CTS command fill.
* Drop intermediate mdata buffer & zipsize.
* For mcmd use strcmp instead of strncmp.
* Dropset_fastboot_dlinstead use devlink param for fastboot operational mode.
* Drop unnecessary logs.
* Changet7xx_devlink_create_regiontot7xx_devlink_create_regions.
* UseBUILD_BUG_ONon array size checks.
* UseARRAY_SIZEinside loop.
* Correct indentation.
* Drop odd empty line.
* Push common devlink initialization code tot7xx_devlink_init.
* Useskb_queue_purgeinstead of running loop to free skbs.
* Changet7xx_regionsindex to enums.
* Remove dev in devlink container.
* Refactor struct to separate out devlink static and dynamic data structs.
* Usemin_t.
* Drop unnecessary var assginment during initialization.
* Changewhile()tofor().
* Correct size check.
* Rename result to ret.
* Clean-up error handling path int7xx_devlink_fb_get_core&t7xx_devlink_fb_dump_log.
* Drop__func__in log message.
* Change NOTY to NOTIFY.
* Push channel enable or disable cb to port proxy.
* Use array index int7xx_devlink_region_listinitialization.
* Dropt7xx_port_proxy_get_port_by_name()instead access port name directly viaport_prox.
* Drop udev based event reporting logic.
* Dropget_coreprefix in goto label.
* Remove unnessary header files.
* Allocate memory formrdump_region->bufinsideget_core.
* Remove 'region->buf' int7xx_devlink_region_snapshot.
* Destroy workqueue on following error case in 'devlink_init'.
* Remove uselesschecks(dl->mode)andcondition(dl->wq).
* Support devlink component versioning.
*Kconfigchanges to select devlink.--- drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/t7xx/Makefile | 4 +- drivers/net/wwan/t7xx/t7xx_pci.c | 16 +- drivers/net/wwan/t7xx/t7xx_pci.h | 2 + drivers/net/wwan/t7xx/t7xx_port.h | 2 + drivers/net/wwan/t7xx/t7xx_port_ap_msg.c | 79 +++ drivers/net/wwan/t7xx/t7xx_port_ap_msg.h | 11 + drivers/net/wwan/t7xx/t7xx_port_devlink.c | 669 +++++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_port_devlink.h | 86 +++ drivers/net/wwan/t7xx/t7xx_port_proxy.c | 32 + drivers/net/wwan/t7xx/t7xx_port_proxy.h | 4 + drivers/net/wwan/t7xx/t7xx_port_wwan.c | 22 +- drivers/net/wwan/t7xx/t7xx_reg.h | 6 + drivers/net/wwan/t7xx/t7xx_state_monitor.c | 37 +- 14 files changed, 945 insertions(+), 26 deletions(-) create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_ap_msg.h create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.c create mode 100644 drivers/net/wwan/t7xx/t7xx_port_devlink.hdrivers/net/wwan/Kconfig +1
-0@@ -108,6 +108,7 @@ config IOSM config MTK_T7XX tristate "MediaTek PCIe 5G WWAN modem T7xx device" depends on PCI + select NET_DEVLINK select RELAY if WWAN_DEBUGFS help Enables MediaTek PCIe based 5G WWAN modem (T7xx series) device.drivers/net/wwan/t7xx/Makefile +3
-1@@ -18,7 +18,9 @@ mtk_t7xx-y:= t7xx_pci.o \ t7xx_hif_dpmaif_rx.o \ t7xx_dpmaif.o \ t7xx_netdev.o \ - t7xx_pci_rescan.o + t7xx_pci_rescan.o \ + t7xx_port_devlink.o \ + t7xx_port_ap_msg.o mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \ t7xx_port_trace.o \drivers/net/wwan/t7xx/t7xx_pci.c +13
-3@@ -40,6 +40,7 @@#include "t7xx_pci.h" #include "t7xx_pci_rescan.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_devlink.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h" @@ -107,7 +108,7 @@ static int t7xx_pci_pm_init(struct t7xx_pci_dev *t7xx_dev)pm_runtime_set_autosuspend_delay (&pdev->dev,PM_AUTOSUSPEND_MS );pm_runtime_use_autosuspend (&pdev->dev); -return t7xx_wait_pm_config (t7xx_dev); +return 0 ; }void t7xx_pci_pm_init_late (struct t7xx_pci_dev *t7xx_dev)@@ -704,16 +705,20 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)t7xx_pci_infracfg_ao_calc (t7xx_dev);t7xx_mhccif_init (t7xx_dev); - ret =t7xx_md_init (t7xx_dev); + ret =t7xx_devlink_register (t7xx_dev);if (ret)return ret; + ret =t7xx_md_init (t7xx_dev); +if (ret) + goto err_devlink_unregister; +t7xx_pcie_mac_interrupts_dis (t7xx_dev); ret =t7xx_interrupt_init (t7xx_dev);if (ret) {t7xx_md_exit (t7xx_dev); -return ret; + goto err_devlink_unregister; }t7xx_rescan_done ();@@ -721,6 +726,10 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)t7xx_pcie_mac_interrupts_en (t7xx_dev);return 0 ; + +err_devlink_unregister: +t7xx_devlink_unregister (t7xx_dev); +return ret; }static void t7xx_pci_remove (struct pci_dev *pdev)@@ -730,6 +739,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev) t7xx_dev =pci_get_drvdata (pdev);t7xx_md_exit (t7xx_dev); +t7xx_devlink_unregister (t7xx_dev);for (i =0 ; i <EXT_INT_NUM ; i++) {if (!t7xx_dev->intr_handler[i])drivers/net/wwan/t7xx/t7xx_pci.h +2
-0@@ -59,6 +59,7 @@ typedef irqreturn_t (*t7xx_intr_callback)(int irq, void *param);* @md_pm_lock: protects PCIe sleep lock * @sleep_disable_count: PCIe L1.2 lock counter * @sleep_lock_acquire: indicates that sleep has been disabled +* @dl: devlink struct */ struct t7xx_pci_dev {t7xx_intr_callback intr_handler[EXT_INT_NUM ];@@ -81,6 +82,7 @@ struct t7xx_pci_dev {#ifdef CONFIG_WWAN_DEBUGFS struct dentry *debugfs_dir;#endif +struct t7xx_devlink *dl; };enum t7xx_pm_id {drivers/net/wwan/t7xx/t7xx_port.h +2
-0@@ -42,6 +42,8 @@ enum port_ch {/* to AP */ PORT_CH_AP_CONTROL_RX =0x1000 ,PORT_CH_AP_CONTROL_TX =0x1001 , +PORT_CH_AP_MSG_RX =0x101E , +PORT_CH_AP_MSG_TX =0x101F ,/* to MD */ PORT_CH_CONTROL_RX = 0x2000,drivers/net/wwan/t7xx/t7xx_port_ap_msg.c new file +79
-0@@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#include "t7xx_port.h" +#include "t7xx_port_ap_msg.h" +#include "t7xx_port_devlink.h" +#include "t7xx_port_proxy.h" +#include "t7xx_state_monitor.h" + +int t7xx_port_ap_msg_tx (struct t7xx_port *port,char *buff,size_t len) +{ +const struct t7xx_port_conf *port_conf; +size_t offset, chunk_len =0 , txq_mtu; +struct t7xx_fsm_ctl *ctl; +enum md_state md_state; + +if (!len || !port->chan_enable) +return -EINVAL ; + + port_conf = port->port_conf; + ctl = port->t7xx_dev->md->fsm_ctl; + md_state =t7xx_fsm_get_md_state (ctl); +if (md_state ==MD_STATE_WAITING_FOR_HS1 || md_state ==MD_STATE_WAITING_FOR_HS2 ) { +dev_warn (port->dev,"Cannot write to %s port when md_state=%d\n" , + port_conf->name, md_state); +return -ENODEV ; + } + + txq_mtu =t7xx_get_port_mtu (port); +for (offset =0 ; offset < len; offset += chunk_len) { +struct sk_buff *skb_ccci; +int ret; + + chunk_len =min (len - offset, txq_mtu -sizeof (struct ccci_header )); + skb_ccci =t7xx_port_alloc_skb (chunk_len); +if (!skb_ccci) +return -ENOMEM ; + +skb_put_data (skb_ccci, buff + offset, chunk_len); + ret =t7xx_port_send_skb (port, skb_ccci,0 ,0 ); +if (ret) { +dev_kfree_skb_any (skb_ccci); +dev_err (port->dev,"Write error on %s port, %d\n" , + port_conf->name, ret); +return ret; + } + } + +return len; +} + +static int t7xx_port_ap_msg_init (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; + + port->rx_length_th =T7XX_MAX_QUEUE_LENGTH ; + dl->status =T7XX_DEVLINK_IDLE ; + dl->port = port; + +return 0 ; +} + +static void t7xx_port_ap_msg_uninit (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; + + dl->mode =T7XX_NORMAL_MODE ; +skb_queue_purge (&port->rx_skb_list); +} + +struct port_ops ap_msg_port_ops = { + .init = &t7xx_port_ap_msg_init, + .recv_skb = &t7xx_port_enqueue_skb, + .uninit = &t7xx_port_ap_msg_uninit, + .enable_chl = &t7xx_port_enable_chl, + .disable_chl = &t7xx_port_disable_chl, +};drivers/net/wwan/t7xx/t7xx_port_ap_msg.h new file +11
-0@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only +* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#ifndef __T7XX_PORT_AP_MSG_H__ +#define __T7XX_PORT_AP_MSG_H__ + +int t7xx_port_ap_msg_tx (struct t7xx_port *port,char *buff,size_t len); + +#endif /* __T7XX_PORT_AP_MSG_H__ */ drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +86
-0@@ -0,0 +1,669 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#include <linux/vmalloc.h> + +#include "t7xx_hif_cldma.h" +#include "t7xx_pci_rescan.h" +#include "t7xx_port.h" +#include "t7xx_port_ap_msg.h" +#include "t7xx_port_devlink.h" +#include "t7xx_port_proxy.h" +#include "t7xx_state_monitor.h" + +static struct t7xx_devlink_region_info t7xx_devlink_region_infos[] = { + [T7XX_MRDUMP_INDEX ] = {"mr_dump" ,T7XX_MRDUMP_SIZE }, + [T7XX_LKDUMP_INDEX ] = {"lk_dump" ,T7XX_LKDUMP_SIZE }, +}; + +static int t7xx_devlink_port_read (struct t7xx_port *port,char *buf,size_t count) +{ +struct sk_buff *skb; +int read_len; + +spin_lock_irq (&port->rx_wq.lock); +if (skb_queue_empty (&port->rx_skb_list)) { +int ret =wait_event_interruptible_locked_irq (port->rx_wq, + !skb_queue_empty (&port->rx_skb_list)); +if (ret == -ERESTARTSYS ) { +spin_unlock_irq (&port->rx_wq.lock); +return -EINTR ; + } + } + skb =skb_dequeue (&port->rx_skb_list); +spin_unlock_irq (&port->rx_wq.lock); + + read_len =min_t (size_t, count, skb->len); +memcpy (buf, skb->data, read_len); + +if (read_len < skb->len) { +skb_pull (skb, read_len); +skb_queue_head (&port->rx_skb_list, skb); + }else { +consume_skb (skb); + } + +return read_len; +} + +static int t7xx_devlink_port_write (struct t7xx_port *port,const char *buf,size_t count) +{ +const struct t7xx_port_conf *port_conf = port->port_conf; +size_t actual = count, offset =0 ; +int txq_mtu; + + txq_mtu =t7xx_get_port_mtu (port); +if (txq_mtu <0 ) +return -EINVAL ; + +while (actual) { +int len =min_t (size_t, actual, txq_mtu); +struct sk_buff *skb; +int ret; + + skb =__dev_alloc_skb (len,GFP_KERNEL ); +if (!skb) +return -ENOMEM ; + +skb_put_data (skb, buf + offset, len); + ret =t7xx_port_send_raw_skb (port, skb); +if (ret) { +dev_err (port->dev,"write error on %s, size: %d, ret: %d\n" , + port_conf->name, len, ret); +dev_kfree_skb (skb); +return ret; + } + + offset += len; + actual -= len; + } + +return count; +} + +static int t7xx_devlink_fb_handle_response (struct t7xx_port *port,char *data)
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 96
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+{ +char status[T7XX_FB_RESPONSE_SIZE +1 ]; +int ret =0 , index; + +for (index =0 ; index <T7XX_FB_RESP_COUNT ; index++) { +int read_bytes =t7xx_devlink_port_read (port, status,T7XX_FB_RESPONSE_SIZE ); + +if (read_bytes <0 ) { +dev_err (port->dev,"status read interrupted\n" ); + ret = -EIO ;
First t7xx_devlink_port_read does -ERESTARTSYS -> -EINTR and then here you do -ERESTARTSYS -> -EIO.
Quoted 123 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +123
-0+break ; + } + + status[read_bytes] ='\0' ; +dev_dbg (port->dev,"raw response from device: %s\n" , status); +if (!strncmp (status,T7XX_FB_RESP_INFO ,strlen (T7XX_FB_RESP_INFO ))) { +break ; + }else if (!strncmp (status,T7XX_FB_RESP_OKAY ,strlen (T7XX_FB_RESP_OKAY ))) { +break ; + }else if (!strncmp (status,T7XX_FB_RESP_FAIL ,strlen (T7XX_FB_RESP_FAIL ))) { + ret = -EPROTO ; +break ; + }else if (!strncmp (status,T7XX_FB_RESP_DATA ,strlen (T7XX_FB_RESP_DATA ))) { +if (data) +snprintf (data,T7XX_FB_RESPONSE_SIZE ,"%s" , + status +strlen (T7XX_FB_RESP_DATA )); +break ; + } + } + +return ret; +} + +static int t7xx_devlink_fb_raw_command (char *cmd,struct t7xx_port *port,char *data) +{ +int ret, cmd_size =strlen (cmd); + +if (cmd_size >T7XX_FB_COMMAND_SIZE ) { +dev_err (port->dev,"command length %d is long\n" , cmd_size); +return -EINVAL ; + } + +if (cmd_size !=t7xx_devlink_port_write (port, cmd, cmd_size)) { +dev_err (port->dev,"raw command = %s write failed\n" , cmd); +return -EIO ; + } + +dev_dbg (port->dev,"raw command = %s written to the device\n" , cmd); + ret =t7xx_devlink_fb_handle_response (port, data); +if (ret) +dev_err (port->dev,"raw command = %s response FAILURE:%d\n" , cmd, ret); + +return ret; +} + +static int t7xx_devlink_fb_download_command (struct t7xx_port *port,size_t size) +{ +char download_command[T7XX_FB_COMMAND_SIZE ]; + +snprintf (download_command,sizeof (download_command),"%s:%08zx" , +T7XX_FB_CMD_DOWNLOAD , size); +return t7xx_devlink_fb_raw_command (download_command, port,NULL ); +} + +static int t7xx_devlink_fb_download (struct t7xx_port *port,const u8 *buf,size_t size) +{ +int ret; + +if (!size) +return -EINVAL ; + + ret =t7xx_devlink_fb_download_command (port, size); +if (ret) +return ret; + + ret =t7xx_devlink_port_write (port, buf, size); +if (ret <0 ) +return ret; + +return t7xx_devlink_fb_handle_response (port,NULL ); +} + +static int t7xx_devlink_fb_flash (struct t7xx_port *port,const char *cmd) +{ +char flash_command[T7XX_FB_COMMAND_SIZE ]; + +snprintf (flash_command,sizeof (flash_command),"%s:%s" ,T7XX_FB_CMD_FLASH , cmd); +return t7xx_devlink_fb_raw_command (flash_command, port,NULL ); +} + +static int t7xx_devlink_get_part_ver_fb_mode (struct t7xx_port *port,const char *cmd,char *data) +{ +char req_command[T7XX_FB_COMMAND_SIZE ]; + +snprintf (req_command,sizeof (req_command),"%s:%s" ,T7XX_FB_CMD_GET_VER , cmd); +return t7xx_devlink_fb_raw_command (req_command, port, data); +} + +static int t7xx_devlink_get_part_ver_norm_mode (struct t7xx_port *port,const char *cmd,char *data) +{ +char req_command[T7XX_FB_COMMAND_SIZE ]; +int len; + + len =snprintf (req_command,sizeof (req_command),"%s:%s" ,T7XX_FB_CMD_GET_VER , cmd); +t7xx_port_ap_msg_tx (port, req_command, len); + +return t7xx_devlink_fb_handle_response (port, data); +} + +static int t7xx_devlink_fb_flash_partition (struct t7xx_port *port,const char *partition, +const u8 *buf,size_t size) +{ +int ret; + + ret =t7xx_devlink_fb_download (port, buf, size); +if (ret <0 ) +return ret; + +return t7xx_devlink_fb_flash (port, partition); +} + +static int t7xx_devlink_fb_get_core (struct t7xx_port *port) +{ +u32 mrd_mb =T7XX_MRDUMP_SIZE / (1024 *1024 ); +struct t7xx_devlink *dl = port->t7xx_dev->dl; +char mcmd[T7XX_FB_MCMD_SIZE +1 ]; +size_t offset_dlen =0 ; +int clen, dlen, ret; + + dl->regions[T7XX_MRDUMP_INDEX ].buf =vmalloc (dl->regions[T7XX_MRDUMP_INDEX ].info->size); +if (!dl->regions[T7XX_MRDUMP_INDEX ].buf) +return -ENOMEM ; +
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 229
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+set_bit (T7XX_MRDUMP_STATUS , &dl->status); + ret =t7xx_devlink_fb_raw_command (T7XX_FB_CMD_OEM_MRDUMP , port,NULL ); +if (ret) { +dev_err (port->dev,"%s command failed\n" ,T7XX_FB_CMD_OEM_MRDUMP ); + goto free_mem; + } + +while (dl->regions[T7XX_MRDUMP_INDEX ].info->size > offset_dlen) { + clen =t7xx_devlink_port_read (port, mcmd,sizeof (mcmd) -1 ); + mcmd[clen] ='\0' ;
What if clen < 0?
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 230
Quoted 1 line
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +1
-0+if (clen ==strlen (T7XX_FB_CMD_RTS ) && (!strcmp (mcmd,T7XX_FB_CMD_RTS ))) {
How is this different from just !strcmp()?
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 233
Quoted 3 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +3
-0+memset (mcmd,0 ,sizeof (mcmd)); +if (t7xx_devlink_port_write (port,T7XX_FB_CMD_CTS ,strlen (T7XX_FB_CMD_CTS )) + !=strlen (T7XX_FB_CMD_CTS )) {
Split into two lines using a variable for the result, it's much more readable then. Or perhaps create a helper?
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 243
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+dev_err (port->dev,"write for _CTS failed:%zu\n" , +strlen (T7XX_FB_CMD_CTS )); + goto free_mem; + } + + dlen =t7xx_devlink_port_read (port, dl->regions[T7XX_MRDUMP_INDEX ].buf + + offset_dlen,T7XX_FB_MDATA_SIZE ); +if (dlen <=0 ) { +dev_err (port->dev,"read data error(%d)\n" , dlen); + ret = -EPROTO ;
-RESTARTSYS/-EINTR -> -EPROTO ???
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 252
Quoted 9 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +9
-0+ goto free_mem; + } + offset_dlen += dlen; + +if (t7xx_devlink_port_write (port,T7XX_FB_CMD_FIN ,strlen (T7XX_FB_CMD_FIN )) + !=strlen (T7XX_FB_CMD_FIN )) { +dev_err (port->dev,"_FIN failed, (Read %05zu:%05zu)\n" , +strlen (T7XX_FB_CMD_FIN ), offset_dlen); + ret = -EPROTO ;
Ditto.
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 257
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ goto free_mem; + } +continue ; + }else if ((clen ==strlen (T7XX_FB_RESP_MRDUMP_DONE )) && + (!strcmp (mcmd,T7XX_FB_RESP_MRDUMP_DONE ))) {
!strcmp()?
Quoted 32 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +32
-0+dev_dbg (port->dev,"%s! size:%zd\n" ,T7XX_FB_RESP_MRDUMP_DONE , offset_dlen); +clear_bit (T7XX_MRDUMP_STATUS , &dl->status); +return 0 ; + } +dev_err (port->dev,"getcore protocol error (read len %05d, response %s)\n" , + clen, mcmd); + ret = -EPROTO ; + goto free_mem; + } + +dev_err (port->dev,"mrdump exceeds %uMB size. Discarded!\n" , mrd_mb); + +free_mem: +vfree (dl->regions[T7XX_MRDUMP_INDEX ].buf); +clear_bit (T7XX_MRDUMP_STATUS , &dl->status); +return ret; +} + +static int t7xx_devlink_fb_dump_log (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +struct t7xx_devlink_region *lkdump_region; +char rsp[T7XX_FB_RESPONSE_SIZE ]; +int datasize =0 , ret; +size_t offset =0 ; + +if (dl->status !=T7XX_DEVLINK_IDLE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is busy!\n" ); +return -EBUSY ; + } + +set_bit (T7XX_LKDUMP_STATUS , &dl->status);
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 299
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+ ret =t7xx_devlink_fb_raw_command (T7XX_FB_CMD_OEM_LKDUMP , port, rsp); +if (ret) { +dev_err (port->dev,"%s command returns failure\n" ,T7XX_FB_CMD_OEM_LKDUMP ); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return ret; + } + + ret =kstrtoint (rsp,16 , &datasize); +if (ret) { +dev_err (port->dev,"kstrtoint error!\n" );
Maybe something looking more English than "kstrtoint" would make the user happier... :-)
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 300
Quoted 1 line
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +1
-0+clear_bit (T7XX_LKDUMP_STATUS , &dl->status);
I'd goto into unroll path rather than sprinkle this clear_bit() everywhere in this function.
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 309
Quoted 9 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +9
-0+return ret; + } + + lkdump_region = &dl->regions[T7XX_LKDUMP_INDEX ]; +if (datasize > lkdump_region->info->size) { +dev_err (port->dev,"lkdump size is more than %dKB. Discarded!\n" , +T7XX_LKDUMP_SIZE /1024 ); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return -EPROTO ;
-EFBIG ?
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ } + + lkdump_region->buf =vmalloc (lkdump_region->info->size); +if (!lkdump_region->buf) { +clear_bit (T7XX_LKDUMP_STATUS , &dl->status);
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 324
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+return -ENOMEM ; + } + +while (datasize >0 ) { +int dlen =t7xx_devlink_port_read (port, lkdump_region->buf + offset, datasize); + +if (dlen <=0 ) { +dev_err (port->dev,"lkdump read error ret = %d\n" , dlen); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return -EPROTO ;
-ERESTARTSYS/-EINTR -> -EPROTO?
Quoted 38 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +38
-0+ } + + datasize -= dlen; + offset += dlen; + } + +dev_dbg (port->dev,"LKDUMP DONE! size:%zd\n" , offset); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return t7xx_devlink_fb_handle_response (port,NULL ); +} + +static int t7xx_devlink_flash_update (struct devlink *devlink, +struct devlink_flash_update_params *params, +struct netlink_ext_ack *extack) +{ +struct t7xx_devlink *dl =devlink_priv (devlink); +const char *component = params->component; +const struct firmware *fw = params->fw; +struct t7xx_port *port; +int ret; + +if (dl->mode !=T7XX_FB_DL_MODE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is not in fastboot download mode!\n" ); + ret = -EPERM ; + goto err_out; + } + +if (dl->status !=T7XX_DEVLINK_IDLE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is busy!\n" ); + ret = -EBUSY ; + goto err_out; + } + +if (!component || !fw->data) { + ret = -EINVAL ; + goto err_out; + } +
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 372
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+set_bit (T7XX_FLASH_STATUS , &dl->status); + port = dl->port; +dev_dbg (port->dev,"flash partition name:%s binary size:%zu\n" , component, fw->size); + ret =t7xx_devlink_fb_flash_partition (port, component, fw->data, fw->size); +if (ret) { +devlink_flash_update_status_notify (devlink,"flashing failure!" , + params->component,0 ,0 ); + }else { +devlink_flash_update_status_notify (devlink,"flashing success!" , + params->component,0 ,0 );
One could use %s and !ret ? "success" : "failure"
Quoted 45 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +45
-0+ } +clear_bit (T7XX_FLASH_STATUS , &dl->status); + +err_out: +return ret; +} + +enum t7xx_devlink_param_id { +T7XX_DEVLINK_PARAM_ID_BASE =DEVLINK_PARAM_GENERIC_ID_MAX , +T7XX_DEVLINK_PARAM_ID_FASTBOOT , +}; + +static const struct devlink_param t7xx_devlink_params[] = { +DEVLINK_PARAM_DRIVER (T7XX_DEVLINK_PARAM_ID_FASTBOOT , +"fastboot" ,DEVLINK_PARAM_TYPE_BOOL , +BIT (DEVLINK_PARAM_CMODE_DRIVERINIT ), +NULL ,NULL ,NULL ), +}; + +bool t7xx_devlink_param_get_fastboot (struct devlink *devlink) +{ +union devlink_param_value saved_value; + +devlink_param_driverinit_value_get (devlink,T7XX_DEVLINK_PARAM_ID_FASTBOOT , + &saved_value); +return saved_value.vbool; +} + +static int t7xx_devlink_reload_down (struct devlink *devlink,bool netns_change, +enum devlink_reload_action action, +enum devlink_reload_limit limit, +struct netlink_ext_ack *extack) +{ +struct t7xx_devlink *dl =devlink_priv (devlink); + +switch (action) { +case DEVLINK_RELOAD_ACTION_DRIVER_REINIT : +return 0 ; +case DEVLINK_RELOAD_ACTION_FW_ACTIVATE : +if (!dl->mode) +return -EPERM ; +return t7xx_devlink_fb_raw_command (T7XX_FB_CMD_REBOOT , dl->port,NULL ); +default : +/* Unsupported action should not get to this function */ +return -EOPNOTSUPP ;
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 427
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+ } +} + +static int t7xx_devlink_reload_up (struct devlink *devlink, +enum devlink_reload_action action, +enum devlink_reload_limit limit, +u32 *actions_performed, +struct netlink_ext_ack *extack) +{ +struct t7xx_devlink *dl =devlink_priv (devlink);
Add newline.
Quoted 34 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +34
-0+ *actions_performed =BIT (action); +switch (action) { +case DEVLINK_RELOAD_ACTION_DRIVER_REINIT : +case DEVLINK_RELOAD_ACTION_FW_ACTIVATE : +t7xx_rescan_queue_work (dl->t7xx_dev->pdev); +return 0 ; +default : +/* Unsupported action should not get to this function */ +return -EOPNOTSUPP ; + } +} + +static int t7xx_devlink_info_get (struct devlink *devlink,struct devlink_info_req *req, +struct netlink_ext_ack *extack) +{ +struct t7xx_devlink *dl =devlink_priv (devlink); +char *part_name, *ver, *part_no, *data; +int ret, total_part, i, ver_len; +struct t7xx_port *port; + + port = dl->port; + port->port_conf->ops->enable_chl (port); + +if (dl->status !=T7XX_DEVLINK_IDLE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is busy!\n" ); +return -EBUSY ; + } + + data =kzalloc (T7XX_FB_RESPONSE_SIZE ,GFP_KERNEL ); +if (!data) +return -ENOMEM ; + +set_bit (T7XX_GET_INFO , &dl->status); +if (dl->mode ==T7XX_FB_DL_MODE )
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 471
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+ ret =t7xx_devlink_get_part_ver_fb_mode (port,"" , data); + else + ret =t7xx_devlink_get_part_ver_norm_mode (port,"" , data); + +if (ret <0 ) + goto err_clear_bit; + + part_no =strsep (&data,"," ); +if (kstrtoint (part_no,16 , &total_part)) { +dev_err (&dl->t7xx_dev->pdev->dev,"kstrtoint error!\n" );
More meaningful error msg.
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 476
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ ret = -EINVAL ; + goto err_clear_bit; + } + +for (i =0 ; i < total_part; i++) {
The whole operation below is quite fancy, I'd add some comment telling the intent.
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 478
Quoted 2 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +2
-0+ part_name =strsep (&data,"," ); + ver =strsep (&data,"," );
Can ver become NULL here?
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 481
Quoted 3 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +3
-0+ ver_len =strlen (ver); +if (ver[ver_len -2 ] ==0x5C && ver[ver_len -1 ] ==0x6E ) + ver[ver_len -4 ] ='\0' ;
Is ver_len guaranteed to be large enough?
Quoted 56 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +56
-0+ ret =devlink_info_version_running_put_ext (req, part_name, ver, +DEVLINK_INFO_VERSION_TYPE_COMPONENT ); + } + +err_clear_bit: +clear_bit (T7XX_GET_INFO , &dl->status); +kfree (data); +return ret; +} + +/* Call back function for devlink ops */ +static const struct devlink_ops devlink_flash_ops = { + .supported_flash_update_params =DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK , + .flash_update = t7xx_devlink_flash_update, + .reload_actions =BIT (DEVLINK_RELOAD_ACTION_DRIVER_REINIT ) | +BIT (DEVLINK_RELOAD_ACTION_FW_ACTIVATE ), + .info_get = t7xx_devlink_info_get, + .reload_down = t7xx_devlink_reload_down, + .reload_up = t7xx_devlink_reload_up, +}; + +static int t7xx_devlink_region_snapshot (struct devlink *dl,const struct devlink_region_ops *ops, +struct netlink_ext_ack *extack,u8 **data) +{ +struct t7xx_devlink *t7xx_dl =devlink_priv (dl); +struct t7xx_devlink_region *region = ops->priv; +struct t7xx_port *port = t7xx_dl->port; +u8 *snapshot_mem; + +if (t7xx_dl->status !=T7XX_DEVLINK_IDLE ) +return -EBUSY ; + +if (!strncmp (ops->name,"mr_dump" ,strlen ("mr_dump" ))) { + snapshot_mem =vmalloc (region->info->size); +memcpy (snapshot_mem, region->buf, region->info->size); + *data = snapshot_mem; + }else if (!strncmp (ops->name,"lk_dump" ,strlen ("lk_dump" ))) { +int ret; + + ret =t7xx_devlink_fb_dump_log (port); +if (ret) +return ret; + + *data = region->buf; + } + +return 0 ; +} + +/* To create regions for dump files */ +static int t7xx_devlink_create_regions (struct t7xx_devlink *dl) +{ +int ret, i; + +BUILD_BUG_ON (ARRAY_SIZE (t7xx_devlink_region_infos) >ARRAY_SIZE (dl->regions)); +for (i =0 ; i <ARRAY_SIZE (t7xx_devlink_region_infos); i++) {
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 547
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+ dl->regions[i].info = &t7xx_devlink_region_infos[i]; + dl->regions[i].ops.name = dl->regions[i].info->name; + dl->regions[i].ops.snapshot = t7xx_devlink_region_snapshot; + dl->regions[i].ops.destructor = vfree; + dl->regions[i].dlreg =devlink_region_create (dl->ctx, &dl->regions[i].ops, +T7XX_MAX_SNAPSHOTS , + t7xx_devlink_region_infos[i].size); +if (IS_ERR (dl->regions[i].dlreg)) { + ret =PTR_ERR (dl->regions[i].dlreg); +dev_err (dl->port->dev,"devlink region fail,err %d\n" , ret);
creating devlink region failed ?
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 549
Quoted 2 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +2
-0+for ( ; i >=0 ; i--) +devlink_region_destroy (dl->regions[i].dlreg);
while (i >= 0) + ...regions[i--]... is simpler and equal.
Quoted 86 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +86
-0+ +return ret; + } + + dl->regions[i].ops.priv = &dl->regions[i]; + } + +return 0 ; +} + +int t7xx_devlink_register (struct t7xx_pci_dev *t7xx_dev) +{ +union devlink_param_value value; +struct devlink *dl_ctx; + + dl_ctx =devlink_alloc (&devlink_flash_ops,sizeof (struct t7xx_devlink ), + &t7xx_dev->pdev->dev); +if (!dl_ctx) +return -ENOMEM ; + + t7xx_dev->dl =devlink_priv (dl_ctx); + t7xx_dev->dl->ctx = dl_ctx; + t7xx_dev->dl->t7xx_dev = t7xx_dev; +devlink_params_register (dl_ctx, t7xx_devlink_params,ARRAY_SIZE (t7xx_devlink_params)); + value.vbool = false; +devlink_param_driverinit_value_set (dl_ctx,T7XX_DEVLINK_PARAM_ID_FASTBOOT , value); +devlink_set_features (dl_ctx,DEVLINK_F_RELOAD ); +devlink_register (dl_ctx); + +return 0 ; +} + +void t7xx_devlink_unregister (struct t7xx_pci_dev *t7xx_dev) +{ +struct devlink *dl_ctx = t7xx_dev->dl->ctx; + +devlink_unregister (dl_ctx); +devlink_params_unregister (dl_ctx, t7xx_devlink_params,ARRAY_SIZE (t7xx_devlink_params)); +devlink_free (dl_ctx); +} + +static void t7xx_devlink_work (struct work_struct *work) +{ +struct t7xx_devlink *dl; + + dl = container_of(work, struct t7xx_devlink, ws); +t7xx_devlink_fb_get_core (dl->port); +} + +/** +* t7xx_devlink_init - Initialize devlink to t7xx driver +* @port: Pointer to port structure +* +* Returns: 0 on success and error values on failure +*/ +static int t7xx_devlink_init (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +struct workqueue_struct *dl_wq; +int rc; + + dl_wq =create_workqueue ("t7xx_devlink" ); +if (!dl_wq) { +dev_err (port->dev,"create_workqueue failed\n" ); +return -ENODATA ; + } + +INIT_WORK (&dl->ws, t7xx_devlink_work); + port->rx_length_th =T7XX_MAX_QUEUE_LENGTH ; + + dl->mode =T7XX_NORMAL_MODE ; + dl->status =T7XX_DEVLINK_IDLE ; + dl->wq = dl_wq; + dl->port = port; + + rc =t7xx_devlink_create_regions (dl); +if (rc) { +destroy_workqueue (dl->wq); +dev_err (port->dev,"devlink region creation failed, rc %d\n" , rc); +return -ENOMEM ; + } + +return 0 ; +} + +static void t7xx_devlink_uninit (struct t7xx_port *port)
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 645
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +int i; + +vfree (dl->regions[T7XX_MRDUMP_INDEX ].buf); + + dl->mode =T7XX_NORMAL_MODE ; +destroy_workqueue (dl->wq); + +BUILD_BUG_ON (ARRAY_SIZE (t7xx_devlink_region_infos) >ARRAY_SIZE (dl->regions));
The same BUILD_BUG_ON again? Maybe just make a single static_assert() outside of the functions.
Quoted 346 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +24
-0+for (i =0 ; i <ARRAY_SIZE (t7xx_devlink_region_infos); ++i) +devlink_region_destroy (dl->regions[i].dlreg); + +skb_queue_purge (&port->rx_skb_list); +} + +static int t7xx_devlink_enable_chl (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; + +t7xx_port_enable_chl (port); +if (dl->mode ==T7XX_FB_DUMP_MODE ) +queue_work (dl->wq, &dl->ws); + +return 0 ; +} + +struct port_ops devlink_port_ops = { + .init = &t7xx_devlink_init, + .recv_skb = &t7xx_port_enqueue_skb, + .uninit = &t7xx_devlink_uninit, + .enable_chl = &t7xx_devlink_enable_chl, + .disable_chl = &t7xx_port_disable_chl, +};drivers/net/wwan/t7xx/t7xx_port_devlink.h new file +86
-0@@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only +* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#ifndef __T7XX_PORT_DEVLINK_H__ +#define __T7XX_PORT_DEVLINK_H__ + +#include <net/devlink.h> +#include <linux/string.h> + +#include "t7xx_pci.h" + +#define T7XX_MAX_QUEUE_LENGTH 32 +#define T7XX_FB_COMMAND_SIZE 64 +#define T7XX_FB_RESPONSE_SIZE 512 +#define T7XX_FB_MCMD_SIZE 64 +#define T7XX_FB_MDATA_SIZE 1024 +#define T7XX_FB_RESP_COUNT 30 + +#define T7XX_FB_CMD_RTS "_RTS" +#define T7XX_FB_CMD_CTS "_CTS" +#define T7XX_FB_CMD_FIN "_FIN" +#define T7XX_FB_CMD_OEM_MRDUMP "oem mrdump" +#define T7XX_FB_CMD_OEM_LKDUMP "oem dump_pllk_log" +#define T7XX_FB_CMD_DOWNLOAD "download" +#define T7XX_FB_CMD_FLASH "flash" +#define T7XX_FB_CMD_REBOOT "reboot" +#define T7XX_FB_RESP_MRDUMP_DONE "MRDUMP08_DONE" +#define T7XX_FB_RESP_OKAY "OKAY" +#define T7XX_FB_RESP_FAIL "FAIL" +#define T7XX_FB_RESP_DATA "DATA" +#define T7XX_FB_RESP_INFO "INFO" +#define T7XX_FB_CMD_GET_VER "get_version" + +#define T7XX_FB_EVENT_SIZE 50 + +#define T7XX_MAX_SNAPSHOTS 1 +#define T7XX_MRDUMP_SIZE (160 * 1024 * 1024) +#define T7XX_LKDUMP_SIZE (256 * 1024) +#define T7XX_TOTAL_REGIONS 2 + +#define T7XX_FLASH_STATUS 0 +#define T7XX_MRDUMP_STATUS 1 +#define T7XX_LKDUMP_STATUS 2 +#define T7XX_GET_INFO 3 +#define T7XX_DEVLINK_IDLE 0 + +#define T7XX_NORMAL_MODE 0 +#define T7XX_FB_DL_MODE 1 +#define T7XX_FB_DUMP_MODE 2 + +/* Internal region indexes */ +enum t7xx_regions { +T7XX_MRDUMP_INDEX , +T7XX_LKDUMP_INDEX , +}; + +struct t7xx_devlink_region_info { +const char *name; +size_t size; +}; + +struct t7xx_devlink_region { +struct t7xx_devlink_region_info *info; +struct devlink_region_ops ops; +struct devlink_region *dlreg; +void *buf; +}; + +struct t7xx_devlink { +struct t7xx_devlink_region regions[T7XX_TOTAL_REGIONS ]; +struct t7xx_pci_dev *t7xx_dev; +struct workqueue_struct *wq; +struct t7xx_port *port; +struct work_struct ws; +struct devlink *ctx; +unsigned long status; +u8 mode; +}; + +bool t7xx_devlink_param_get_fastboot (struct devlink *devlink); +int t7xx_devlink_register (struct t7xx_pci_dev *t7xx_dev); +void t7xx_devlink_unregister (struct t7xx_pci_dev *t7xx_dev); + +#endif /*__T7XX_PORT_DEVLINK_H__*/ drivers/net/wwan/t7xx/t7xx_port_proxy.c +32
-0@@ -40,6 +40,7 @@#define Q_IDX_CTRL 0#define Q_IDX_MBIM 2#define Q_IDX_AT_CMD 5 +#define Q_IDX_AP_MSG 2#define INVALID_SEQ_NUM GENMASK(15, 0)@@ -97,7 +98,18 @@ static const struct t7xx_port_conf t7xx_port_conf[] = { .path_id = CLDMA_ID_AP, .ops = &ctl_port_ops, .name = "t7xx_ap_ctrl", + }, { + .tx_ch = PORT_CH_AP_MSG_TX, + .rx_ch = PORT_CH_AP_MSG_RX, + .txq_index = Q_IDX_AP_MSG, + .rxq_index = Q_IDX_AP_MSG, + .txq_exp_index = Q_IDX_AP_MSG, + .rxq_exp_index = Q_IDX_AP_MSG, + .path_id = CLDMA_ID_AP, + .ops = &ap_msg_port_ops, + .name = "ap_msg", }, + };static struct t7xx_port_conf t7xx_early_port_conf[] = {@@ -109,6 +121,8 @@ static struct t7xx_port_conf t7xx_early_port_conf[] = { .txq_exp_index = CLDMA_Q_IDX_DUMP, .rxq_exp_index = CLDMA_Q_IDX_DUMP, .path_id = CLDMA_ID_AP, + .ops = &devlink_port_ops, + .name = "devlink", }, };@@ -325,6 +339,24 @@ int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned intreturn t7xx_port_send_ccci_skb (port, skb, pkt_header, ex_msg); } +int t7xx_port_enable_chl (struct t7xx_port *port) +{ +spin_lock (&port->port_update_lock); + port->chan_enable = true; +spin_unlock (&port->port_update_lock); + +return 0 ; +} + +int t7xx_port_disable_chl (struct t7xx_port *port) +{ +spin_lock (&port->port_update_lock); + port->chan_enable = false; +spin_unlock (&port->port_update_lock); + +return 0 ; +} +static void t7xx_proxy_setup_ch_mapping (struct port_proxy *port_prox) {struct t7xx_port *port;drivers/net/wwan/t7xx/t7xx_port_proxy.h +4
-0@@ -93,6 +93,8 @@ struct ctrl_msg_header {/* Port operations mapping */ extern struct port_ops wwan_sub_port_ops;extern struct port_ops ctl_port_ops; +extern struct port_ops devlink_port_ops; +extern struct port_ops ap_msg_port_ops;#ifdef CONFIG_WWAN_DEBUGFS extern struct port_ops t7xx_trace_port_ops;@@ -108,5 +110,7 @@ int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned invoid t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id);int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb);int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb); +int t7xx_port_enable_chl (struct t7xx_port *port); +int t7xx_port_disable_chl (struct t7xx_port *port);#endif /* __T7XX_PORT_PROXY_H__ */ drivers/net/wwan/t7xx/t7xx_port_wwan.c +2
-20@@ -134,24 +134,6 @@ static int t7xx_port_wwan_recv_skb(struct t7xx_port *port, struct sk_buff *skb)return 0 ; } -static int t7xx_port_wwan_enable_chl (struct t7xx_port *port) -{ -spin_lock (&port->port_update_lock); - port->chan_enable = true; -spin_unlock (&port->port_update_lock); - -return 0 ; -} - -static int t7xx_port_wwan_disable_chl (struct t7xx_port *port) -{ -spin_lock (&port->port_update_lock); - port->chan_enable = false; -spin_unlock (&port->port_update_lock); - -return 0 ; -} -static void t7xx_port_wwan_md_state_notify (struct t7xx_port *port,unsigned int state) {const struct t7xx_port_conf *port_conf = port->port_conf;@@ -171,7 +153,7 @@ struct port_ops wwan_sub_port_ops = { .init = t7xx_port_wwan_init, .recv_skb = t7xx_port_wwan_recv_skb, .uninit = t7xx_port_wwan_uninit, - .enable_chl = t7xx_port_wwan_enable_chl, - .disable_chl = t7xx_port_wwan_disable_chl, + .enable_chl = t7xx_port_enable_chl, + .disable_chl = t7xx_port_disable_chl, .md_state_notify = t7xx_port_wwan_md_state_notify, };drivers/net/wwan/t7xx/t7xx_reg.h +6
-0@@ -101,10 +101,16 @@ enum t7xx_pm_resume_state { PM_RESUME_REG_STATE_L2_EXP, }; +enum host_event_e { +HOST_EVENT_INIT =0 , +FASTBOOT_DL_NOTIFY =0x3 , +}; +#define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c#define MISC_RESET_TYPE_FLDR BIT(27)#define MISC_RESET_TYPE_PLDR BIT(26)#define MISC_LK_EVENT_MASK GENMASK(11, 8) +#define HOST_EVENT_MASK GENMASK(31, 28)enum lk_event_id {LK_EVENT_NORMAL =0 ,drivers/net/wwan/t7xx/t7xx_state_monitor.c +35
-2@@ -37,6 +37,7 @@#include "t7xx_modem_ops.h" #include "t7xx_pci.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_devlink.h" #include "t7xx_port_proxy.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h" @@ -206,11 +207,22 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commfsm_finish_command (ctl, cmd,0 ); } +static void t7xx_host_event_notify (struct t7xx_modem *md,unsigned int event_id) +{ +u32 value; + + value =ioread32 (IREG_BASE (md->t7xx_dev) +T7XX_PCIE_MISC_DEV_STATUS ); + value &= ~HOST_EVENT_MASK ; + value |=FIELD_PREP (HOST_EVENT_MASK , event_id); +iowrite32 (value,IREG_BASE (md->t7xx_dev) +T7XX_PCIE_MISC_DEV_STATUS ); +} +static void t7xx_lk_stage_event_handling (struct t7xx_fsm_ctl *ctl,unsigned int status) {struct t7xx_modem *md = ctl->md;struct cldma_ctrl *md_ctrl;enum lk_event_id lk_event; +struct t7xx_port *port;struct device *dev; dev = &md->t7xx_dev->pdev->dev;@@ -221,10 +233,21 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned intbreak ;case LK_EVENT_CREATE_PD_PORT : +case LK_EVENT_CREATE_POST_DL_PORT : md_ctrl = md->md_ctrl[CLDMA_ID_AP ];t7xx_cldma_hif_hw_init (md_ctrl);t7xx_cldma_stop (md_ctrl);t7xx_cldma_switch_cfg (md_ctrl,CLDMA_DEDICATED_Q_CFG ); + port = ctl->md->t7xx_dev->dl->port; +if (WARN_ON (!port)) +return ; + +if (lk_event ==LK_EVENT_CREATE_PD_PORT ) + md->t7xx_dev->dl->mode =T7XX_FB_DUMP_MODE ; +else + md->t7xx_dev->dl->mode =T7XX_FB_DL_MODE ; + + port->port_conf->ops->enable_chl (port);t7xx_cldma_start (md_ctrl);break ;@@ -271,13 +294,23 @@ static void fsm_routine_stopping(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commat7xx_cldma_stop (md_ctrl);if (!ctl->md->rgu_irq_asserted) { +if (t7xx_devlink_param_get_fastboot (t7xx_dev->dl->ctx)) +t7xx_host_event_notify (ctl->md,FASTBOOT_DL_NOTIFY ); +t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DRM_DISABLE_AP );/* Wait for the DRM disable to take effect */ msleep (FSM_DRM_DISABLE_DELAY_MS ); - err =t7xx_acpi_fldr_func (t7xx_dev); -if (err) +if (t7xx_devlink_param_get_fastboot (t7xx_dev->dl->ctx)) { +/* Do not try fldr because device will always wait for +* MHCCIF bit 13 in fastboot download flow. +*/ t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DEVICE_RESET ); + }else { + err =t7xx_acpi_fldr_func (t7xx_dev); +if (err) +t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DEVICE_RESET ); + } }fsm_finish_command (ctl, cmd,fsm_stopped_handler (ctl));
Signature · 1 line
i.
Re: [PATCH v4 net-next 4/5] net: wwan: t7xx: Enable devlink based fw flashing and coredump collection
Hi Ilpo,
Thank you for the feedback.
Quoted 439 lines · Ilpo Järvinen
Quoted 437 lines · On Mon, 16 Jan 2023, [email protected] wrote:
From: M Chetan Kumar <[email protected]>
Adds support for t7xx wwan device firmware flashing & coredump collection using devlink.
1> Driver Registers with Devlink framework.
2> Implements devlink opsflash_updatecallback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.On early detection of wwan device in fastboot mode driver sets up CLDMA0 HW tx/rx queues for raw data transfer and then registers to devlink framework. On user space application issuing command for firmware update the driver sends fastboot flash command & firmware to program NAND.
In flashing procedure the fastboot command & response are exchanged between driver and device. Once firmware flashing is success completion status is reported to user space application.
Below is the devlink command usage for firmware flashing
$devlink dev flash pci/$BDF file ABC.img component ABC
Note: ABC.img is the firmware to be programmed to "ABC" partition.
In case of coredump collection when wwan device encounters an exception it reboots & stays in fastboot mode for coredump collection by host driver. On detecting exception state driver collects the core dump, creates the devlink region & reports an event to user space application for dump collection. The user space application invokes devlink region read command for dump collection.
Below are the devlink commands used for coredump collection.
devlink region new pci/$BDF/mr_dump
devlink region read pci/$BDF/mr_dump snapshot $ID address $ADD length $LEN devlink region del pci/$BDF/mr_dump snapshot $IDSigned-off-by M Chetan Kumar <[email protected]>Signed-off-by Devegowda Chandrashekar <[email protected]>Signed-off-by Mishra Soumya Prakash <[email protected]>Reviewed-by Jesse Brandeburg <[email protected]>--
v4:
* cppcheck - reduce variableScope for
-skb_ccci& ret var int7xx_port_ap_msg_tx.
- ret int7xx_devlink_port_read.
- len, skb & ret int7xx_devlink_port_write.
v3:
* No Change.
v2:
* Remove devlink pointer inside the port state container.
* Renamet7xx_devlink_region_listtot7xx_devlink_region_infos& use region index in initialization.
* Changet7xx_devlink_region_infosto const.
* Handle remaining packet data if the buffer is less than the skb data.
* Dropt7xx_devlink_fb_send_buffer(), push fragmentation logic tot7xx_devlink_port_write(). * Add "\n" to log message. * Move mrdump_region allocation to devlink initialization. * Drop snprintf for CTS command fill. * Drop intermediate mdata buffer & zipsize. * For mcmd use strcmp instead of strncmp. * Drop set_fastboot_dl instead use devlink param for fastboot operational mode. * Drop unnecessary logs. * Change t7xx_devlink_create_region to t7xx_devlink_create_regions. * Use BUILD_BUG_ON on array size checks. * Use ARRAY_SIZE inside loop. * Correct indentation. * Drop odd empty line. * Push common devlink initialization code to t7xx_devlink_init. * Use skb_queue_purge instead of running loop to free skbs. * Change t7xx_regions index to enums. * Remove dev in devlink container. * Refactor struct to separate out devlink static and dynamic data structs. * Use min_t. * Drop unnecessary var assginment during initialization. * Change while() to for(). * Correct size check. * Rename result to ret. * Clean-up error handling path in t7xx_devlink_fb_get_core & t7xx_devlink_fb_dump_log. * Drop __func__ in log message. * Change NOTY to NOTIFY. * Push channel enable or disable cb to port proxy. * Use array index in t7xx_devlink_region_list initialization. * Drop t7xx_port_proxy_get_port_by_name() instead access port name directly via port_prox. * Drop udev based event reporting logic. * Drop get_core prefix in goto label. * Remove unnessary header files. * Allocate memory for mrdump_region->buf inside get_core. * Remove 'region->buf' in t7xx_devlink_region_snapshot. * Destroy workqueue on following error case in 'devlink_init'. * Remove useless checks(dl->mode) and condition(dl->wq). * Support devlink component versioning. * Kconfig changes to select devlink. --- drivers/net/wwan/Kconfig | 1 + drivers/net/wwan/t7xx/Makefile | 4 +- drivers/net/wwan/t7xx/t7xx_pci.c | 16 +- drivers/net/wwan/t7xx/t7xx_pci.h | 2 + drivers/net/wwan/t7xx/t7xx_port.h | 2 + drivers/net/wwan/t7xx/t7xx_port_ap_msg.c | 79 +++ drivers/net/wwan/t7xx/t7xx_port_ap_msg.h | 11 + drivers/net/wwan/t7xx/t7xx_port_devlink.c | 669 +++++++++++++++++++++ drivers/net/wwan/t7xx/t7xx_port_devlink.h | 86 +++ drivers/net/wwan/t7xx/t7xx_port_proxy.c | 32 + drivers/net/wwan/t7xx/t7xx_port_proxy.h | 4 + drivers/net/wwan/t7xx/t7xx_port_wwan.c | 22 +- drivers/net/wwan/t7xx/t7xx_reg.h | 6 + drivers/net/wwan/t7xx/t7xx_state_monitor.c | 37 +- 14 files changed, 945 insertions(+), 26 deletions(-)create mode 100644
drivers/net/wwan/t7xx/t7xx_port_ap_msg.ccreate mode 100644drivers/net/wwan/t7xx/t7xx_port_ap_msg.hcreate mode 100644drivers/net/wwan/t7xx/t7xx_port_devlink.ccreate mode 100644drivers/net/wwan/t7xx/t7xx_port_devlink.hdrivers/net/wwan/Kconfig +1
-0@@ -108,6 +108,7 @@ config IOSM config MTK_T7XX tristate "MediaTek PCIe 5G WWAN modem T7xx device" depends on PCI + select NET_DEVLINK select RELAY if WWAN_DEBUGFS help Enables MediaTek PCIe based 5G WWAN modem (T7xx series) device.drivers/net/wwan/t7xx/Makefile +3
-1@@ -18,7 +18,9 @@ mtk_t7xx-y:= t7xx_pci.o \ t7xx_hif_dpmaif_rx.o \ t7xx_dpmaif.o \ t7xx_netdev.o \ - t7xx_pci_rescan.o + t7xx_pci_rescan.o \ + t7xx_port_devlink.o \ + t7xx_port_ap_msg.o mtk_t7xx-$(CONFIG_WWAN_DEBUGFS) += \ t7xx_port_trace.o \drivers/net/wwan/t7xx/t7xx_pci.c +13
-3@@ -40,6 +40,7 @@#include "t7xx_pci.h" #include "t7xx_pci_rescan.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_devlink.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h" @@ -107,7 +108,7 @@ static int t7xx_pci_pm_init(struct t7xx_pci_dev *t7xx_dev)pm_runtime_set_autosuspend_delay (&pdev->dev,PM_AUTOSUSPEND_MS );pm_runtime_use_autosuspend (&pdev->dev); -return t7xx_wait_pm_config (t7xx_dev); +return 0 ; }void t7xx_pci_pm_init_late (struct t7xx_pci_dev *t7xx_dev)@@ -704,16 +705,20 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)t7xx_pci_infracfg_ao_calc (t7xx_dev);t7xx_mhccif_init (t7xx_dev); - ret =t7xx_md_init (t7xx_dev); + ret =t7xx_devlink_register (t7xx_dev);if (ret)return ret; + ret =t7xx_md_init (t7xx_dev); +if (ret) + goto err_devlink_unregister; +t7xx_pcie_mac_interrupts_dis (t7xx_dev); ret =t7xx_interrupt_init (t7xx_dev);if (ret) {t7xx_md_exit (t7xx_dev); -return ret; + goto err_devlink_unregister; }t7xx_rescan_done ();@@ -721,6 +726,10 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)t7xx_pcie_mac_interrupts_en (t7xx_dev);return 0 ; + +err_devlink_unregister: +t7xx_devlink_unregister (t7xx_dev); +return ret; }static void t7xx_pci_remove (struct pci_dev *pdev)@@ -730,6 +739,7 @@ static void t7xx_pci_remove(struct pci_dev *pdev) t7xx_dev =pci_get_drvdata (pdev);t7xx_md_exit (t7xx_dev); +t7xx_devlink_unregister (t7xx_dev);for (i =0 ; i <EXT_INT_NUM ; i++) {if (!t7xx_dev->intr_handler[i])drivers/net/wwan/t7xx/t7xx_pci.h +2
-0@@ -59,6 +59,7 @@ typedef irqreturn_t (*t7xx_intr_callback)(int irq, void *param);* @md_pm_lock: protects PCIe sleep lock * @sleep_disable_count: PCIe L1.2 lock counter * @sleep_lock_acquire: indicates that sleep has been disabled +* @dl: devlink struct */ struct t7xx_pci_dev {t7xx_intr_callback intr_handler[EXT_INT_NUM ];@@ -81,6 +82,7 @@ struct t7xx_pci_dev {#ifdef CONFIG_WWAN_DEBUGFS struct dentry *debugfs_dir;#endif +struct t7xx_devlink *dl; };enum t7xx_pm_id {drivers/net/wwan/t7xx/t7xx_port.h +2
-0@@ -42,6 +42,8 @@ enum port_ch {/* to AP */ PORT_CH_AP_CONTROL_RX =0x1000 ,PORT_CH_AP_CONTROL_TX =0x1001 , +PORT_CH_AP_MSG_RX =0x101E , +PORT_CH_AP_MSG_TX =0x101F ,/* to MD */ PORT_CH_CONTROL_RX = 0x2000,drivers/net/wwan/t7xx/t7xx_port_ap_msg.c new file +79
-0@@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#include "t7xx_port.h" +#include "t7xx_port_ap_msg.h" +#include "t7xx_port_devlink.h" +#include "t7xx_port_proxy.h" +#include "t7xx_state_monitor.h" + +int t7xx_port_ap_msg_tx (struct t7xx_port *port,char *buff,size_t len) +{ +const struct t7xx_port_conf *port_conf; +size_t offset, chunk_len =0 , txq_mtu; +struct t7xx_fsm_ctl *ctl; +enum md_state md_state; + +if (!len || !port->chan_enable) +return -EINVAL ; + + port_conf = port->port_conf; + ctl = port->t7xx_dev->md->fsm_ctl; + md_state =t7xx_fsm_get_md_state (ctl); +if (md_state ==MD_STATE_WAITING_FOR_HS1 || md_state ==MD_STATE_WAITING_FOR_HS2 ) { +dev_warn (port->dev,"Cannot write to %s port when md_state=%d\n" , + port_conf->name, md_state); +return -ENODEV ; + } + + txq_mtu =t7xx_get_port_mtu (port); +for (offset =0 ; offset < len; offset += chunk_len) { +struct sk_buff *skb_ccci; +int ret; + + chunk_len =min (len - offset, txq_mtu -sizeof (struct ccci_header )); + skb_ccci =t7xx_port_alloc_skb (chunk_len); +if (!skb_ccci) +return -ENOMEM ; + +skb_put_data (skb_ccci, buff + offset, chunk_len); + ret =t7xx_port_send_skb (port, skb_ccci,0 ,0 ); +if (ret) { +dev_kfree_skb_any (skb_ccci); +dev_err (port->dev,"Write error on %s port, %d\n" , + port_conf->name, ret); +return ret; + } + } + +return len; +} + +static int t7xx_port_ap_msg_init (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; + + port->rx_length_th =T7XX_MAX_QUEUE_LENGTH ; + dl->status =T7XX_DEVLINK_IDLE ; + dl->port = port; + +return 0 ; +} + +static void t7xx_port_ap_msg_uninit (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; + + dl->mode =T7XX_NORMAL_MODE ; +skb_queue_purge (&port->rx_skb_list); +} + +struct port_ops ap_msg_port_ops = { + .init = &t7xx_port_ap_msg_init, + .recv_skb = &t7xx_port_enqueue_skb, + .uninit = &t7xx_port_ap_msg_uninit, + .enable_chl = &t7xx_port_enable_chl, + .disable_chl = &t7xx_port_disable_chl, +};drivers/net/wwan/t7xx/t7xx_port_ap_msg.h new file +11
-0@@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only +* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#ifndef __T7XX_PORT_AP_MSG_H__ +#define __T7XX_PORT_AP_MSG_H__ + +int t7xx_port_ap_msg_tx (struct t7xx_port *port,char *buff,size_t len); + +#endif /* __T7XX_PORT_AP_MSG_H__ */ drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +91
-0@@ -0,0 +1,669 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#include <linux/vmalloc.h> + +#include "t7xx_hif_cldma.h" +#include "t7xx_pci_rescan.h" +#include "t7xx_port.h" +#include "t7xx_port_ap_msg.h" +#include "t7xx_port_devlink.h" +#include "t7xx_port_proxy.h" +#include "t7xx_state_monitor.h" + +static struct t7xx_devlink_region_info t7xx_devlink_region_infos[] = { + [T7XX_MRDUMP_INDEX ] = {"mr_dump" ,T7XX_MRDUMP_SIZE }, + [T7XX_LKDUMP_INDEX ] = {"lk_dump" ,T7XX_LKDUMP_SIZE }, +}; + +static int t7xx_devlink_port_read (struct t7xx_port *port,char *buf,size_t count) +{ +struct sk_buff *skb; +int read_len; + +spin_lock_irq (&port->rx_wq.lock); +if (skb_queue_empty (&port->rx_skb_list)) { +int ret =wait_event_interruptible_locked_irq (port->rx_wq, + !skb_queue_empty (&port->rx_skb_list)); +if (ret == -ERESTARTSYS ) { +spin_unlock_irq (&port->rx_wq.lock); +return -EINTR ; + } + } + skb =skb_dequeue (&port->rx_skb_list); +spin_unlock_irq (&port->rx_wq.lock); + + read_len =min_t (size_t, count, skb->len); +memcpy (buf, skb->data, read_len); + +if (read_len < skb->len) { +skb_pull (skb, read_len); +skb_queue_head (&port->rx_skb_list, skb); + }else { +consume_skb (skb); + } + +return read_len; +} + +static int t7xx_devlink_port_write (struct t7xx_port *port,const char *buf,size_t count) +{ +const struct t7xx_port_conf *port_conf = port->port_conf; +size_t actual = count, offset =0 ; +int txq_mtu; + + txq_mtu =t7xx_get_port_mtu (port); +if (txq_mtu <0 ) +return -EINVAL ; + +while (actual) { +int len =min_t (size_t, actual, txq_mtu); +struct sk_buff *skb; +int ret; + + skb =__dev_alloc_skb (len,GFP_KERNEL ); +if (!skb) +return -ENOMEM ; + +skb_put_data (skb, buf + offset, len); + ret =t7xx_port_send_raw_skb (port, skb); +if (ret) { +dev_err (port->dev,"write error on %s, size: %d, ret: %d\n" , + port_conf->name, len, ret); +dev_kfree_skb (skb); +return ret; + } + + offset += len; + actual -= len; + } + +return count; +} + +static int t7xx_devlink_fb_handle_response (struct t7xx_port *port,char *data) +{ +char status[T7XX_FB_RESPONSE_SIZE +1 ]; +int ret =0 , index; + +for (index =0 ; index <T7XX_FB_RESP_COUNT ; index++) {
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 96
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+int read_bytes =t7xx_devlink_port_read (port, status,T7XX_FB_RESPONSE_SIZE ); + +if (read_bytes <0 ) { +dev_err (port->dev,"status read interrupted\n" ); + ret = -EIO ;First
t7xx_devlink_port_readdoes-ERESTARTSYS->-EINTRand then here you do-ERESTARTSYS->-EIO.
Will drop return update inside t7xx_devlink_port_read & return the same from t7xx_devlink_fb_handle_response.
Will correct it other places too.
Quoted 128 lines
Quoted 128 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +127
-0+break ; + } + + status[read_bytes] ='\0' ; +dev_dbg (port->dev,"raw response from device: %s\n" , status); +if (!strncmp (status,T7XX_FB_RESP_INFO ,strlen (T7XX_FB_RESP_INFO ))) { +break ; + }else if (!strncmp (status,T7XX_FB_RESP_OKAY ,strlen (T7XX_FB_RESP_OKAY ))) { +break ; + }else if (!strncmp (status,T7XX_FB_RESP_FAIL ,strlen (T7XX_FB_RESP_FAIL ))) { + ret = -EPROTO ; +break ; + }else if (!strncmp (status,T7XX_FB_RESP_DATA ,strlen (T7XX_FB_RESP_DATA ))) { +if (data) +snprintf (data,T7XX_FB_RESPONSE_SIZE ,"%s" , + status +strlen (T7XX_FB_RESP_DATA )); +break ; + } + } + +return ret; +} + +static int t7xx_devlink_fb_raw_command (char *cmd,struct t7xx_port *port,char *data) +{ +int ret, cmd_size =strlen (cmd); + +if (cmd_size >T7XX_FB_COMMAND_SIZE ) { +dev_err (port->dev,"command length %d is long\n" , cmd_size); +return -EINVAL ; + } + +if (cmd_size !=t7xx_devlink_port_write (port, cmd, cmd_size)) { +dev_err (port->dev,"raw command = %s write failed\n" , cmd); +return -EIO ; + } + +dev_dbg (port->dev,"raw command = %s written to the device\n" , cmd); + ret =t7xx_devlink_fb_handle_response (port, data); +if (ret) +dev_err (port->dev,"raw command = %s response FAILURE:%d\n" , cmd, ret); + +return ret; +} + +static int t7xx_devlink_fb_download_command (struct t7xx_port *port,size_t size) +{ +char download_command[T7XX_FB_COMMAND_SIZE ]; + +snprintf (download_command,sizeof (download_command),"%s:%08zx" , +T7XX_FB_CMD_DOWNLOAD , size); +return t7xx_devlink_fb_raw_command (download_command, port,NULL ); +} + +static int t7xx_devlink_fb_download (struct t7xx_port *port,const u8 *buf,size_t size) +{ +int ret; + +if (!size) +return -EINVAL ; + + ret =t7xx_devlink_fb_download_command (port, size); +if (ret) +return ret; + + ret =t7xx_devlink_port_write (port, buf, size); +if (ret <0 ) +return ret; + +return t7xx_devlink_fb_handle_response (port,NULL ); +} + +static int t7xx_devlink_fb_flash (struct t7xx_port *port,const char *cmd) +{ +char flash_command[T7XX_FB_COMMAND_SIZE ]; + +snprintf (flash_command,sizeof (flash_command),"%s:%s" ,T7XX_FB_CMD_FLASH , cmd); +return t7xx_devlink_fb_raw_command (flash_command, port,NULL ); +} + +static int t7xx_devlink_get_part_ver_fb_mode (struct t7xx_port *port,const char *cmd,char *data) +{ +char req_command[T7XX_FB_COMMAND_SIZE ]; + +snprintf (req_command,sizeof (req_command),"%s:%s" ,T7XX_FB_CMD_GET_VER , cmd); +return t7xx_devlink_fb_raw_command (req_command, port, data); +} + +static int t7xx_devlink_get_part_ver_norm_mode (struct t7xx_port *port,const char *cmd,char *data) +{ +char req_command[T7XX_FB_COMMAND_SIZE ]; +int len; + + len =snprintf (req_command,sizeof (req_command),"%s:%s" ,T7XX_FB_CMD_GET_VER , cmd); +t7xx_port_ap_msg_tx (port, req_command, len); + +return t7xx_devlink_fb_handle_response (port, data); +} + +static int t7xx_devlink_fb_flash_partition (struct t7xx_port *port,const char *partition, +const u8 *buf,size_t size) +{ +int ret; + + ret =t7xx_devlink_fb_download (port, buf, size); +if (ret <0 ) +return ret; + +return t7xx_devlink_fb_flash (port, partition); +} + +static int t7xx_devlink_fb_get_core (struct t7xx_port *port) +{ +u32 mrd_mb =T7XX_MRDUMP_SIZE / (1024 *1024 ); +struct t7xx_devlink *dl = port->t7xx_dev->dl; +char mcmd[T7XX_FB_MCMD_SIZE +1 ]; +size_t offset_dlen =0 ; +int clen, dlen, ret; + + dl->regions[T7XX_MRDUMP_INDEX ].buf =vmalloc (dl->regions[T7XX_MRDUMP_INDEX ].info->size); +if (!dl->regions[T7XX_MRDUMP_INDEX ].buf) +return -ENOMEM ; + +set_bit (T7XX_MRDUMP_STATUS , &dl->status); + ret =t7xx_devlink_fb_raw_command (T7XX_FB_CMD_OEM_MRDUMP , port,NULL ); +if (ret) { +dev_err (port->dev,"%s command failed\n" ,T7XX_FB_CMD_OEM_MRDUMP );
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 229
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +6
-0+ goto free_mem; + } + +while (dl->regions[T7XX_MRDUMP_INDEX ].info->size > offset_dlen) { + clen =t7xx_devlink_port_read (port, mcmd,sizeof (mcmd) -1 ); + mcmd[clen] ='\0' ;What if clen < 0?
On safer note will add clen check.
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 230
Quoted 2 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +1
-0+if (clen ==strlen (T7XX_FB_CMD_RTS ) && (!strcmp (mcmd,T7XX_FB_CMD_RTS ))) {How is this different from just !strcmp()?
Will drop the first condition.
Quoted 7 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 233
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +3
-0+memset (mcmd,0 ,sizeof (mcmd)); +if (t7xx_devlink_port_write (port,T7XX_FB_CMD_CTS ,strlen (T7XX_FB_CMD_CTS )) + !=strlen (T7XX_FB_CMD_CTS )) {Split into two lines using a variable for the result, it's much more readable then. Or perhaps create a helper?
Such change is present below as well. Will create a helper & use it.
Quoted 25 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 243
Quoted 11 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+dev_err (port->dev,"write for _CTS failed:%zu\n" , +strlen (T7XX_FB_CMD_CTS )); + goto free_mem; + } + + dlen =t7xx_devlink_port_read (port, dl->regions[T7XX_MRDUMP_INDEX ].buf + + offset_dlen,T7XX_FB_MDATA_SIZE ); +if (dlen <=0 ) { +dev_err (port->dev,"read data error(%d)\n" , dlen); + ret = -EPROTO ;-RESTARTSYS/-EINTR ->
-EPROTO??? >drivers/net/wwan/t7xx/t7xx_port_devlink.c line 252
Quoted 9 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +9
-0+ goto free_mem; + } + offset_dlen += dlen; + +if (t7xx_devlink_port_write (port,T7XX_FB_CMD_FIN ,strlen (T7XX_FB_CMD_FIN )) + !=strlen (T7XX_FB_CMD_FIN )) { +dev_err (port->dev,"_FIN failed, (Read %05zu:%05zu)\n" , +strlen (T7XX_FB_CMD_FIN ), offset_dlen); + ret = -EPROTO ;Ditto.
Quoted 7 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 257
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ goto free_mem; + } +continue ; + }else if ((clen ==strlen (T7XX_FB_RESP_MRDUMP_DONE )) && + (!strcmp (mcmd,T7XX_FB_RESP_MRDUMP_DONE ))) {!strcmp()?
Will drop the first condition.
Quoted 38 lines
Quoted 38 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +37
-0+dev_dbg (port->dev,"%s! size:%zd\n" ,T7XX_FB_RESP_MRDUMP_DONE , offset_dlen); +clear_bit (T7XX_MRDUMP_STATUS , &dl->status); +return 0 ; + } +dev_err (port->dev,"getcore protocol error (read len %05d, response %s)\n" , + clen, mcmd); + ret = -EPROTO ; + goto free_mem; + } + +dev_err (port->dev,"mrdump exceeds %uMB size. Discarded!\n" , mrd_mb); + +free_mem: +vfree (dl->regions[T7XX_MRDUMP_INDEX ].buf); +clear_bit (T7XX_MRDUMP_STATUS , &dl->status); +return ret; +} + +static int t7xx_devlink_fb_dump_log (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +struct t7xx_devlink_region *lkdump_region; +char rsp[T7XX_FB_RESPONSE_SIZE ]; +int datasize =0 , ret; +size_t offset =0 ; + +if (dl->status !=T7XX_DEVLINK_IDLE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is busy!\n" ); +return -EBUSY ; + } + +set_bit (T7XX_LKDUMP_STATUS , &dl->status); + ret =t7xx_devlink_fb_raw_command (T7XX_FB_CMD_OEM_LKDUMP , port, rsp); +if (ret) { +dev_err (port->dev,"%s command returns failure\n" ,T7XX_FB_CMD_OEM_LKDUMP ); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return ret;
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 299
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ } + + ret =kstrtoint (rsp,16 , &datasize); +if (ret) { +dev_err (port->dev,"kstrtoint error!\n" );Maybe something looking more English than "kstrtoint" would make the user happier... :-)
Will correct it.
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 300
Quoted 2 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +1
-0+clear_bit (T7XX_LKDUMP_STATUS , &dl->status);I'd goto into unroll path rather than sprinkle this
clear_bit()everywhere in this function.
Quoted 11 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 309
Quoted 9 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +9
-0+return ret; + } + + lkdump_region = &dl->regions[T7XX_LKDUMP_INDEX ]; +if (datasize > lkdump_region->info->size) { +dev_err (port->dev,"lkdump size is more than %dKB. Discarded!\n" , +T7XX_LKDUMP_SIZE /1024 ); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return -EPROTO ;
-EFBIG?
Will -EPROTO to -EFBIG.
Quoted 61 lines
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ } + + lkdump_region->buf =vmalloc (lkdump_region->info->size); +if (!lkdump_region->buf) { +clear_bit (T7XX_LKDUMP_STATUS , &dl->status);drivers/net/wwan/t7xx/t7xx_port_devlink.c line 324
Quoted 10 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +10
-0+return -ENOMEM ; + } + +while (datasize >0 ) { +int dlen =t7xx_devlink_port_read (port, lkdump_region->buf + offset, datasize); + +if (dlen <=0 ) { +dev_err (port->dev,"lkdump read error ret = %d\n" , dlen); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return -EPROTO ;-ERESTARTSYS/-EINTR ->
-EPROTO?Quoted 42 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +42
-0+ } + + datasize -= dlen; + offset += dlen; + } + +dev_dbg (port->dev,"LKDUMP DONE! size:%zd\n" , offset); +clear_bit (T7XX_LKDUMP_STATUS , &dl->status); +return t7xx_devlink_fb_handle_response (port,NULL ); +} + +static int t7xx_devlink_flash_update (struct devlink *devlink, +struct devlink_flash_update_params *params, +struct netlink_ext_ack *extack) +{ +struct t7xx_devlink *dl =devlink_priv (devlink); +const char *component = params->component; +const struct firmware *fw = params->fw; +struct t7xx_port *port; +int ret; + +if (dl->mode !=T7XX_FB_DL_MODE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is not in fastboot download mode!\n" ); + ret = -EPERM ; + goto err_out; + } + +if (dl->status !=T7XX_DEVLINK_IDLE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is busy!\n" ); + ret = -EBUSY ; + goto err_out; + } + +if (!component || !fw->data) { + ret = -EINVAL ; + goto err_out; + } + +set_bit (T7XX_FLASH_STATUS , &dl->status); + port = dl->port; +dev_dbg (port->dev,"flash partition name:%s binary size:%zu\n" , component, fw->size); + ret =t7xx_devlink_fb_flash_partition (port, component, fw->data, fw->size);
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 372
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +6
-0+if (ret) { +devlink_flash_update_status_notify (devlink,"flashing failure!" , + params->component,0 ,0 ); + }else { +devlink_flash_update_status_notify (devlink,"flashing success!" , + params->component,0 ,0 );One could use %s and !ret ? "success" : "failure"
Will change it as per your suggestion.
Quoted 50 lines
Quoted 50 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +49
-0+ } +clear_bit (T7XX_FLASH_STATUS , &dl->status); + +err_out: +return ret; +} + +enum t7xx_devlink_param_id { +T7XX_DEVLINK_PARAM_ID_BASE =DEVLINK_PARAM_GENERIC_ID_MAX , +T7XX_DEVLINK_PARAM_ID_FASTBOOT , +}; + +static const struct devlink_param t7xx_devlink_params[] = { +DEVLINK_PARAM_DRIVER (T7XX_DEVLINK_PARAM_ID_FASTBOOT , +"fastboot" ,DEVLINK_PARAM_TYPE_BOOL , +BIT (DEVLINK_PARAM_CMODE_DRIVERINIT ), +NULL ,NULL ,NULL ), +}; + +bool t7xx_devlink_param_get_fastboot (struct devlink *devlink) +{ +union devlink_param_value saved_value; + +devlink_param_driverinit_value_get (devlink,T7XX_DEVLINK_PARAM_ID_FASTBOOT , + &saved_value); +return saved_value.vbool; +} + +static int t7xx_devlink_reload_down (struct devlink *devlink,bool netns_change, +enum devlink_reload_action action, +enum devlink_reload_limit limit, +struct netlink_ext_ack *extack) +{ +struct t7xx_devlink *dl =devlink_priv (devlink); + +switch (action) { +case DEVLINK_RELOAD_ACTION_DRIVER_REINIT : +return 0 ; +case DEVLINK_RELOAD_ACTION_FW_ACTIVATE : +if (!dl->mode) +return -EPERM ; +return t7xx_devlink_fb_raw_command (T7XX_FB_CMD_REBOOT , dl->port,NULL ); +default : +/* Unsupported action should not get to this function */ +return -EOPNOTSUPP ; + } +} + +static int t7xx_devlink_reload_up(struct devlink *devlink,
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 427
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +6
-0+enum devlink_reload_action action, + enum devlink_reload_limit limit, + u32 *actions_performed, + struct netlink_ext_ack *extack) +{ + struct t7xx_devlink *dl = devlink_priv(devlink);Add newline.
Ok.
Quoted 39 lines
Quoted 39 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +38
-0+ *actions_performed =BIT (action); +switch (action) { +case DEVLINK_RELOAD_ACTION_DRIVER_REINIT : +case DEVLINK_RELOAD_ACTION_FW_ACTIVATE : +t7xx_rescan_queue_work (dl->t7xx_dev->pdev); +return 0 ; +default : +/* Unsupported action should not get to this function */ +return -EOPNOTSUPP ; + } +} + +static int t7xx_devlink_info_get (struct devlink *devlink,struct devlink_info_req *req, +struct netlink_ext_ack *extack) +{ +struct t7xx_devlink *dl =devlink_priv (devlink); +char *part_name, *ver, *part_no, *data; +int ret, total_part, i, ver_len; +struct t7xx_port *port; + + port = dl->port; + port->port_conf->ops->enable_chl (port); + +if (dl->status !=T7XX_DEVLINK_IDLE ) { +dev_err (&dl->t7xx_dev->pdev->dev,"Modem is busy!\n" ); +return -EBUSY ; + } + + data =kzalloc (T7XX_FB_RESPONSE_SIZE ,GFP_KERNEL ); +if (!data) +return -ENOMEM ; + +set_bit (T7XX_GET_INFO , &dl->status); +if (dl->mode ==T7XX_FB_DL_MODE ) + ret =t7xx_devlink_get_part_ver_fb_mode (port,"" , data); +else + ret =t7xx_devlink_get_part_ver_norm_mode (port,"" , data); +
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 471
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +6
-0+if (ret <0 ) + goto err_clear_bit; + + part_no =strsep (&data,"," ); +if (kstrtoint (part_no,16 , &total_part)) { +dev_err (&dl->t7xx_dev->pdev->dev,"kstrtoint error!\n" );More meaningful error msg.
Will correct it.
Quoted 9 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 476
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ ret = -EINVAL ; + goto err_clear_bit; + } + +for (i =0 ; i < total_part; i++) {The whole operation below is quite fancy, I'd add some comment telling the intent.
Device returns firmware name & version in string format. Using below logic to decode it.
Will add some comment.
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 478
Quoted 3 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +2
-0+ part_name =strsep (&data,"," ); + ver =strsep (&data,"," );Can ver become NULL here?
It should not be the case. As part of component fw version query device is expected to send the complete list for fw components.
On safer note will add NULL check.
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 481
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +3
-0+ ver_len =strlen (ver); +if (ver[ver_len -2 ] ==0x5C && ver[ver_len -1 ] ==0x6E ) + ver[ver_len -4 ] ='\0' ;Is
ver_lenguaranteed to be large enough?
fw version query response message will not cross 512 bytes. It is aligned with device implementation.
Quoted 61 lines
Quoted 61 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +60
-0+ ret =devlink_info_version_running_put_ext (req, part_name, ver, +DEVLINK_INFO_VERSION_TYPE_COMPONENT ); + } + +err_clear_bit: +clear_bit (T7XX_GET_INFO , &dl->status); +kfree (data); +return ret; +} + +/* Call back function for devlink ops */ +static const struct devlink_ops devlink_flash_ops = { + .supported_flash_update_params =DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK , + .flash_update = t7xx_devlink_flash_update, + .reload_actions =BIT (DEVLINK_RELOAD_ACTION_DRIVER_REINIT ) | +BIT (DEVLINK_RELOAD_ACTION_FW_ACTIVATE ), + .info_get = t7xx_devlink_info_get, + .reload_down = t7xx_devlink_reload_down, + .reload_up = t7xx_devlink_reload_up, +}; + +static int t7xx_devlink_region_snapshot (struct devlink *dl,const struct devlink_region_ops *ops, +struct netlink_ext_ack *extack,u8 **data) +{ +struct t7xx_devlink *t7xx_dl =devlink_priv (dl); +struct t7xx_devlink_region *region = ops->priv; +struct t7xx_port *port = t7xx_dl->port; +u8 *snapshot_mem; + +if (t7xx_dl->status !=T7XX_DEVLINK_IDLE ) +return -EBUSY ; + +if (!strncmp (ops->name,"mr_dump" ,strlen ("mr_dump" ))) { + snapshot_mem =vmalloc (region->info->size); +memcpy (snapshot_mem, region->buf, region->info->size); + *data = snapshot_mem; + }else if (!strncmp (ops->name,"lk_dump" ,strlen ("lk_dump" ))) { +int ret; + + ret =t7xx_devlink_fb_dump_log (port); +if (ret) +return ret; + + *data = region->buf; + } + +return 0 ; +} + +/* To create regions for dump files */ +static int t7xx_devlink_create_regions (struct t7xx_devlink *dl) +{ +int ret, i; + +BUILD_BUG_ON (ARRAY_SIZE (t7xx_devlink_region_infos) >ARRAY_SIZE (dl->regions)); +for (i =0 ; i <ARRAY_SIZE (t7xx_devlink_region_infos); i++) { + dl->regions[i].info = &t7xx_devlink_region_infos[i]; + dl->regions[i].ops.name = dl->regions[i].info->name; + dl->regions[i].ops.snapshot = t7xx_devlink_region_snapshot; + dl->regions[i].ops.destructor = vfree;
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 547
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +6
-0+ dl->regions[i].dlreg =devlink_region_create (dl->ctx, &dl->regions[i].ops, +T7XX_MAX_SNAPSHOTS , + t7xx_devlink_region_infos[i].size); +if (IS_ERR (dl->regions[i].dlreg)) { + ret =PTR_ERR (dl->regions[i].dlreg); +dev_err (dl->port->dev,"devlink region fail,err %d\n" , ret);creating devlink region failed ?
Will change log message to "creating devlink region failed".
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 549
Quoted 3 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +2
-0+for ( ; i >=0 ; i--) +devlink_region_destroy (dl->regions[i].dlreg);while (i >= 0) + ...regions[i--]... is simpler and equal.
Sure. will change it.
Quoted 92 lines
Quoted 92 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +91
-0+ +return ret; + } + + dl->regions[i].ops.priv = &dl->regions[i]; + } + +return 0 ; +} + +int t7xx_devlink_register (struct t7xx_pci_dev *t7xx_dev) +{ +union devlink_param_value value; +struct devlink *dl_ctx; + + dl_ctx =devlink_alloc (&devlink_flash_ops,sizeof (struct t7xx_devlink ), + &t7xx_dev->pdev->dev); +if (!dl_ctx) +return -ENOMEM ; + + t7xx_dev->dl =devlink_priv (dl_ctx); + t7xx_dev->dl->ctx = dl_ctx; + t7xx_dev->dl->t7xx_dev = t7xx_dev; +devlink_params_register (dl_ctx, t7xx_devlink_params,ARRAY_SIZE (t7xx_devlink_params)); + value.vbool = false; +devlink_param_driverinit_value_set (dl_ctx,T7XX_DEVLINK_PARAM_ID_FASTBOOT , value); +devlink_set_features (dl_ctx,DEVLINK_F_RELOAD ); +devlink_register (dl_ctx); + +return 0 ; +} + +void t7xx_devlink_unregister (struct t7xx_pci_dev *t7xx_dev) +{ +struct devlink *dl_ctx = t7xx_dev->dl->ctx; + +devlink_unregister (dl_ctx); +devlink_params_unregister (dl_ctx, t7xx_devlink_params,ARRAY_SIZE (t7xx_devlink_params)); +devlink_free (dl_ctx); +} + +static void t7xx_devlink_work (struct work_struct *work) +{ +struct t7xx_devlink *dl; + + dl = container_of(work, struct t7xx_devlink, ws); +t7xx_devlink_fb_get_core (dl->port); +} + +/** +* t7xx_devlink_init - Initialize devlink to t7xx driver +* @port: Pointer to port structure +* +* Returns: 0 on success and error values on failure +*/ +static int t7xx_devlink_init (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +struct workqueue_struct *dl_wq; +int rc; + + dl_wq =create_workqueue ("t7xx_devlink" ); +if (!dl_wq) { +dev_err (port->dev,"create_workqueue failed\n" ); +return -ENODATA ; + } + +INIT_WORK (&dl->ws, t7xx_devlink_work); + port->rx_length_th =T7XX_MAX_QUEUE_LENGTH ; + + dl->mode =T7XX_NORMAL_MODE ; + dl->status =T7XX_DEVLINK_IDLE ; + dl->wq = dl_wq; + dl->port = port; + + rc =t7xx_devlink_create_regions (dl); +if (rc) { +destroy_workqueue (dl->wq); +dev_err (port->dev,"devlink region creation failed, rc %d\n" , rc); +return -ENOMEM ; + } + +return 0 ; +} + +static void t7xx_devlink_uninit (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +int i; + +vfree (dl->regions[T7XX_MRDUMP_INDEX ].buf);
Quoted 8 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 645
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +5
-0+ + dl->mode =T7XX_NORMAL_MODE ; +destroy_workqueue (dl->wq); + +BUILD_BUG_ON (ARRAY_SIZE (t7xx_devlink_region_infos) >ARRAY_SIZE (dl->regions));The same
BUILD_BUG_ONagain? Maybe just make a singlestatic_assert()outside of the functions.
Should i change it as below ? please suggest.
static_assert(ARRAY_SIZE(t7xx_devlink_region_infos) ==
(sizeof(typeof_member(struct t7xx_devlink, regions)) /
sizeof(struct t7xx_devlink_region)));
static void t7xx_devlink_uninit(struct t7xx_port *port)
{
..
Quoted 348 lines
Quoted 347 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +24
-0+for (i =0 ; i <ARRAY_SIZE (t7xx_devlink_region_infos); ++i) +devlink_region_destroy (dl->regions[i].dlreg); + +skb_queue_purge (&port->rx_skb_list); +} + +static int t7xx_devlink_enable_chl (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; + +t7xx_port_enable_chl (port); +if (dl->mode ==T7XX_FB_DUMP_MODE ) +queue_work (dl->wq, &dl->ws); + +return 0 ; +} + +struct port_ops devlink_port_ops = { + .init = &t7xx_devlink_init, + .recv_skb = &t7xx_port_enqueue_skb, + .uninit = &t7xx_devlink_uninit, + .enable_chl = &t7xx_devlink_enable_chl, + .disable_chl = &t7xx_port_disable_chl, +};drivers/net/wwan/t7xx/t7xx_port_devlink.h new file +86
-0@@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0-only +* +* Copyright (c) 2022-2023, Intel Corporation. +*/ + +#ifndef __T7XX_PORT_DEVLINK_H__ +#define __T7XX_PORT_DEVLINK_H__ + +#include <net/devlink.h> +#include <linux/string.h> + +#include "t7xx_pci.h" + +#define T7XX_MAX_QUEUE_LENGTH 32 +#define T7XX_FB_COMMAND_SIZE 64 +#define T7XX_FB_RESPONSE_SIZE 512 +#define T7XX_FB_MCMD_SIZE 64 +#define T7XX_FB_MDATA_SIZE 1024 +#define T7XX_FB_RESP_COUNT 30 + +#define T7XX_FB_CMD_RTS "_RTS" +#define T7XX_FB_CMD_CTS "_CTS" +#define T7XX_FB_CMD_FIN "_FIN" +#define T7XX_FB_CMD_OEM_MRDUMP "oem mrdump" +#define T7XX_FB_CMD_OEM_LKDUMP "oem dump_pllk_log" +#define T7XX_FB_CMD_DOWNLOAD "download" +#define T7XX_FB_CMD_FLASH "flash" +#define T7XX_FB_CMD_REBOOT "reboot" +#define T7XX_FB_RESP_MRDUMP_DONE "MRDUMP08_DONE" +#define T7XX_FB_RESP_OKAY "OKAY" +#define T7XX_FB_RESP_FAIL "FAIL" +#define T7XX_FB_RESP_DATA "DATA" +#define T7XX_FB_RESP_INFO "INFO" +#define T7XX_FB_CMD_GET_VER "get_version" + +#define T7XX_FB_EVENT_SIZE 50 + +#define T7XX_MAX_SNAPSHOTS 1 +#define T7XX_MRDUMP_SIZE (160 * 1024 * 1024) +#define T7XX_LKDUMP_SIZE (256 * 1024) +#define T7XX_TOTAL_REGIONS 2 + +#define T7XX_FLASH_STATUS 0 +#define T7XX_MRDUMP_STATUS 1 +#define T7XX_LKDUMP_STATUS 2 +#define T7XX_GET_INFO 3 +#define T7XX_DEVLINK_IDLE 0 + +#define T7XX_NORMAL_MODE 0 +#define T7XX_FB_DL_MODE 1 +#define T7XX_FB_DUMP_MODE 2 + +/* Internal region indexes */ +enum t7xx_regions { +T7XX_MRDUMP_INDEX , +T7XX_LKDUMP_INDEX , +}; + +struct t7xx_devlink_region_info { +const char *name; +size_t size; +}; + +struct t7xx_devlink_region { +struct t7xx_devlink_region_info *info; +struct devlink_region_ops ops; +struct devlink_region *dlreg; +void *buf; +}; + +struct t7xx_devlink { +struct t7xx_devlink_region regions[T7XX_TOTAL_REGIONS ]; +struct t7xx_pci_dev *t7xx_dev; +struct workqueue_struct *wq; +struct t7xx_port *port; +struct work_struct ws; +struct devlink *ctx; +unsigned long status; +u8 mode; +}; + +bool t7xx_devlink_param_get_fastboot (struct devlink *devlink); +int t7xx_devlink_register (struct t7xx_pci_dev *t7xx_dev); +void t7xx_devlink_unregister (struct t7xx_pci_dev *t7xx_dev); + +#endif /*__T7XX_PORT_DEVLINK_H__*/ drivers/net/wwan/t7xx/t7xx_port_proxy.c +32
-0@@ -40,6 +40,7 @@#define Q_IDX_CTRL 0#define Q_IDX_MBIM 2#define Q_IDX_AT_CMD 5 +#define Q_IDX_AP_MSG 2#define INVALID_SEQ_NUM GENMASK(15, 0)@@ -97,7 +98,18 @@ static const struct t7xx_port_conf t7xx_port_conf[] = { .path_id = CLDMA_ID_AP, .ops = &ctl_port_ops, .name = "t7xx_ap_ctrl", + }, { + .tx_ch = PORT_CH_AP_MSG_TX, + .rx_ch = PORT_CH_AP_MSG_RX, + .txq_index = Q_IDX_AP_MSG, + .rxq_index = Q_IDX_AP_MSG, + .txq_exp_index = Q_IDX_AP_MSG, + .rxq_exp_index = Q_IDX_AP_MSG, + .path_id = CLDMA_ID_AP, + .ops = &ap_msg_port_ops, + .name = "ap_msg", }, + };static struct t7xx_port_conf t7xx_early_port_conf[] = {@@ -109,6 +121,8 @@ static struct t7xx_port_conf t7xx_early_port_conf[] = { .txq_exp_index = CLDMA_Q_IDX_DUMP, .rxq_exp_index = CLDMA_Q_IDX_DUMP, .path_id = CLDMA_ID_AP, + .ops = &devlink_port_ops, + .name = "devlink", }, };@@ -325,6 +339,24 @@ int t7xx_port_send_skb(struct t7xx_port *port, struct sk_buff *skb, unsigned intreturn t7xx_port_send_ccci_skb (port, skb, pkt_header, ex_msg); } +int t7xx_port_enable_chl (struct t7xx_port *port) +{ +spin_lock (&port->port_update_lock); + port->chan_enable = true; +spin_unlock (&port->port_update_lock); + +return 0 ; +} + +int t7xx_port_disable_chl (struct t7xx_port *port) +{ +spin_lock (&port->port_update_lock); + port->chan_enable = false; +spin_unlock (&port->port_update_lock); + +return 0 ; +} +static void t7xx_proxy_setup_ch_mapping (struct port_proxy *port_prox) {struct t7xx_port *port;drivers/net/wwan/t7xx/t7xx_port_proxy.h +4
-0@@ -93,6 +93,8 @@ struct ctrl_msg_header {/* Port operations mapping */ extern struct port_ops wwan_sub_port_ops;extern struct port_ops ctl_port_ops; +extern struct port_ops devlink_port_ops; +extern struct port_ops ap_msg_port_ops;#ifdef CONFIG_WWAN_DEBUGFS extern struct port_ops t7xx_trace_port_ops;@@ -108,5 +110,7 @@ int t7xx_port_proxy_chl_enable_disable(struct port_proxy *port_prox, unsigned invoid t7xx_port_proxy_set_cfg (struct t7xx_modem *md,enum port_cfg_id cfg_id);int t7xx_port_proxy_recv_skb (struct cldma_queue *queue,struct sk_buff *skb);int t7xx_port_proxy_recv_skb_from_dedicated_queue (struct cldma_queue *queue,struct sk_buff *skb); +int t7xx_port_enable_chl (struct t7xx_port *port); +int t7xx_port_disable_chl (struct t7xx_port *port);#endif /* __T7XX_PORT_PROXY_H__ */ drivers/net/wwan/t7xx/t7xx_port_wwan.c +2
-20@@ -134,24 +134,6 @@ static int t7xx_port_wwan_recv_skb(struct t7xx_port *port, struct sk_buff *skb)return 0 ; } -static int t7xx_port_wwan_enable_chl (struct t7xx_port *port) -{ -spin_lock (&port->port_update_lock); - port->chan_enable = true; -spin_unlock (&port->port_update_lock); - -return 0 ; -} - -static int t7xx_port_wwan_disable_chl (struct t7xx_port *port) -{ -spin_lock (&port->port_update_lock); - port->chan_enable = false; -spin_unlock (&port->port_update_lock); - -return 0 ; -} -static void t7xx_port_wwan_md_state_notify (struct t7xx_port *port,unsigned int state) {const struct t7xx_port_conf *port_conf = port->port_conf;@@ -171,7 +153,7 @@ struct port_ops wwan_sub_port_ops = { .init = t7xx_port_wwan_init, .recv_skb = t7xx_port_wwan_recv_skb, .uninit = t7xx_port_wwan_uninit, - .enable_chl = t7xx_port_wwan_enable_chl, - .disable_chl = t7xx_port_wwan_disable_chl, + .enable_chl = t7xx_port_enable_chl, + .disable_chl = t7xx_port_disable_chl, .md_state_notify = t7xx_port_wwan_md_state_notify, };drivers/net/wwan/t7xx/t7xx_reg.h +6
-0@@ -101,10 +101,16 @@ enum t7xx_pm_resume_state { PM_RESUME_REG_STATE_L2_EXP, }; +enum host_event_e { +HOST_EVENT_INIT =0 , +FASTBOOT_DL_NOTIFY =0x3 , +}; +#define T7XX_PCIE_MISC_DEV_STATUS 0x0d1c#define MISC_RESET_TYPE_FLDR BIT(27)#define MISC_RESET_TYPE_PLDR BIT(26)#define MISC_LK_EVENT_MASK GENMASK(11, 8) +#define HOST_EVENT_MASK GENMASK(31, 28)enum lk_event_id {LK_EVENT_NORMAL =0 ,drivers/net/wwan/t7xx/t7xx_state_monitor.c +35
-2@@ -37,6 +37,7 @@#include "t7xx_modem_ops.h" #include "t7xx_pci.h" #include "t7xx_pcie_mac.h" +#include "t7xx_port_devlink.h" #include "t7xx_port_proxy.h" #include "t7xx_reg.h" #include "t7xx_state_monitor.h" @@ -206,11 +207,22 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commfsm_finish_command (ctl, cmd,0 ); } +static void t7xx_host_event_notify (struct t7xx_modem *md,unsigned int event_id) +{ +u32 value; + + value =ioread32 (IREG_BASE (md->t7xx_dev) +T7XX_PCIE_MISC_DEV_STATUS ); + value &= ~HOST_EVENT_MASK ; + value |=FIELD_PREP (HOST_EVENT_MASK , event_id); +iowrite32 (value,IREG_BASE (md->t7xx_dev) +T7XX_PCIE_MISC_DEV_STATUS ); +} +static void t7xx_lk_stage_event_handling (struct t7xx_fsm_ctl *ctl,unsigned int status) {struct t7xx_modem *md = ctl->md;struct cldma_ctrl *md_ctrl;enum lk_event_id lk_event; +struct t7xx_port *port;struct device *dev; dev = &md->t7xx_dev->pdev->dev;@@ -221,10 +233,21 @@ static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned intbreak ;case LK_EVENT_CREATE_PD_PORT : +case LK_EVENT_CREATE_POST_DL_PORT : md_ctrl = md->md_ctrl[CLDMA_ID_AP ];t7xx_cldma_hif_hw_init (md_ctrl);t7xx_cldma_stop (md_ctrl);t7xx_cldma_switch_cfg (md_ctrl,CLDMA_DEDICATED_Q_CFG ); + port = ctl->md->t7xx_dev->dl->port; +if (WARN_ON (!port)) +return ; + +if (lk_event ==LK_EVENT_CREATE_PD_PORT ) + md->t7xx_dev->dl->mode =T7XX_FB_DUMP_MODE ; +else + md->t7xx_dev->dl->mode =T7XX_FB_DL_MODE ; + + port->port_conf->ops->enable_chl (port);t7xx_cldma_start (md_ctrl);break ;@@ -271,13 +294,23 @@ static void fsm_routine_stopping(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_commat7xx_cldma_stop (md_ctrl);if (!ctl->md->rgu_irq_asserted) { +if (t7xx_devlink_param_get_fastboot (t7xx_dev->dl->ctx)) +t7xx_host_event_notify (ctl->md,FASTBOOT_DL_NOTIFY ); +t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DRM_DISABLE_AP );/* Wait for the DRM disable to take effect */ msleep (FSM_DRM_DISABLE_DELAY_MS ); - err =t7xx_acpi_fldr_func (t7xx_dev); -if (err) +if (t7xx_devlink_param_get_fastboot (t7xx_dev->dl->ctx)) { +/* Do not try fldr because device will always wait for +* MHCCIF bit 13 in fastboot download flow. +*/ t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DEVICE_RESET ); + }else { + err =t7xx_acpi_fldr_func (t7xx_dev); +if (err) +t7xx_mhccif_h2d_swint_trigger (t7xx_dev,H2D_CH_DEVICE_RESET ); + } }fsm_finish_command (ctl, cmd,fsm_stopped_handler (ctl));
Signature · 1 line
Chetan
Re: [PATCH v4 net-next 4/5] net: wwan: t7xx: Enable devlink based fw flashing and coredump collection
Quoted 75 lines · M Chetan
Hi Ilpo,
Thank you for the feedback.Quoted 49 lines · Ilpo Järvinen
Quoted 46 lines · On Mon, 16 Jan 2023, [email protected] wrote:
From: M Chetan Kumar <[email protected]>
Adds support for t7xx wwan device firmware flashing & coredump collection using devlink.
1> Driver Registers with Devlink framework.
2> Implements devlink opsflash_updatecallback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.On early detection of wwan device in fastboot mode driver sets up CLDMA0 HW
tx/rx queues for raw data transfer and then registers to devlink framework.
On user space application issuing command for firmware update the driver sends fastboot flash command & firmware to program NAND.In flashing procedure the fastboot command & response are exchanged between
driver and device. Once firmware flashing is success completion status is reported to user space application.Below is the devlink command usage for firmware flashing
$devlink dev flash pci/$BDF file ABC.img component ABC
Note: ABC.img is the firmware to be programmed to "ABC" partition.
In case of coredump collection when wwan device encounters an exception it reboots & stays in fastboot mode for coredump collection by host driver.
On detecting exception state driver collects the core dump, creates the devlink region & reports an event to user space application for dump collection. The user space application invokes devlink region read command for dump collection.Below are the devlink commands used for coredump collection.
devlink region new pci/$BDF/mr_dump
devlink region read pci/$BDF/mr_dump snapshot $ID address $ADD length $LEN devlink region del pci/$BDF/mr_dump snapshot $IDSigned-off-by M Chetan Kumar <[email protected]>Signed-off-by Devegowda Chandrashekar <[email protected]>Signed-off-by Mishra Soumya Prakash <[email protected]>Reviewed-by Jesse Brandeburg <[email protected]>--
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 476
Quoted 1 line
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +1
-0+for (i =0 ; i < total_part; i++) {The whole operation below is quite fancy, I'd add some comment telling the intent.
Device returns firmware name & version in string format. Using below logic to decode it.
Will add some comment.
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 478
Quoted 3 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +2
-0+ part_name =strsep (&data,"," ); + ver =strsep (&data,"," );Can ver become NULL here?
It should not be the case. As part of component fw version query device is expected to send the complete list for fw components.
On safer note will add NULL check.
Quoted 1 line
Quoted 8 lines
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 481
Quoted 3 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +3
-0+ ver_len =strlen (ver); +if (ver[ver_len -2 ] ==0x5C && ver[ver_len -1 ] ==0x6E ) + ver[ver_len -4 ] ='\0' ;Is
ver_lenguaranteed to be large enough?fw version query response message will not cross 512 bytes. It is aligned with device implementation.
I meant the other way around, is ver_len guaranteed to large enough that it is safe to do ver_len - 4 (or even -1).
Quoted 28 lines
Quoted 12 lines
Quoted 11 lines
(quoted diff) +1
-0+ ret = devlink_info_version_running_put_ext(req, part_name,ver,
+DEVLINK_INFO_VERSION_TYPE_COMPONENT);drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +7
-0+ } + +err_clear_bit: +clear_bit (T7XX_GET_INFO , &dl->status); +kfree (data); +return ret; +}Quoted 15 lines
Quoted 11 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +11
-0+static void t7xx_devlink_uninit (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +int i; + +vfree (dl->regions[T7XX_MRDUMP_INDEX ].buf); + + dl->mode =T7XX_NORMAL_MODE ; +destroy_workqueue (dl->wq); + + BUILD_BUG_ON(ARRAY_SIZE(t7xx_devlink_region_infos) >Quoted 1 line
ARRAY_SIZE(dl->regions));The same
BUILD_BUG_ONagain? Maybe just make a singlestatic_assert()outside of the functions.
Quoted 8 lines
Should i change it as below ? please suggest.
static_assert(ARRAY_SIZE(t7xx_devlink_region_infos) ==
(sizeof(typeof_member(struct t7xx_devlink, regions))/
sizeof(struct t7xx_devlink_region)));
static voidt7xx_devlink_uninit(struct t7xx_port *port)
{
..
I see, it's not that easy so perhaps just leave it as is.
I guess something like this might work but seems bit hacky to me (untested):
static_assert(ARRAY_SIZE(t7xx_devlink_region_infos) ==
ARRAY_SIZE(((struct t7xx_devlink *)NULL)->regions));
Signature · 1 line
i.
Re: [PATCH v4 net-next 4/5] net: wwan: t7xx: Enable devlink based fw flashing and coredump collection
Quoted 83 lines · Ilpo Järvinen
Quoted 81 lines · M Chetan
Hi Ilpo,
Thank you for the feedback.Quoted 49 lines · Ilpo Järvinen
Quoted 46 lines · On Mon, 16 Jan 2023, [email protected] wrote:
From: M Chetan Kumar <[email protected]>
Adds support for t7xx wwan device firmware flashing & coredump collection using devlink.
1> Driver Registers with Devlink framework.
2> Implements devlink opsflash_updatecallback that programs modem fw. 3> Creates region & snapshot required for device coredump log collection.On early detection of wwan device in fastboot mode driver sets up CLDMA0 HW
tx/rx queues for raw data transfer and then registers to devlink framework.
On user space application issuing command for firmware update the driver sends fastboot flash command & firmware to program NAND.In flashing procedure the fastboot command & response are exchanged between
driver and device. Once firmware flashing is success completion status is reported to user space application.Below is the devlink command usage for firmware flashing
$devlink dev flash pci/$BDF file ABC.img component ABC
Note: ABC.img is the firmware to be programmed to "ABC" partition.
In case of coredump collection when wwan device encounters an exception it reboots & stays in fastboot mode for coredump collection by host driver.
On detecting exception state driver collects the core dump, creates the devlink region & reports an event to user space application for dump collection. The user space application invokes devlink region read command for dump collection.Below are the devlink commands used for coredump collection.
devlink region new pci/$BDF/mr_dump
devlink region read pci/$BDF/mr_dump snapshot $ID address $ADD length $LEN devlink region del pci/$BDF/mr_dump snapshot $IDSigned-off-by M Chetan Kumar <[email protected]>Signed-off-by Devegowda Chandrashekar <[email protected]>Signed-off-by Mishra Soumya Prakash <[email protected]>Reviewed-by Jesse Brandeburg <[email protected]>--
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 476
Quoted 1 line
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +1
-0+for (i =0 ; i < total_part; i++) {The whole operation below is quite fancy, I'd add some comment telling the intent.
Device returns firmware name & version in string format. Using below logic to decode it.
Will add some comment.
Quoted 5 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 478
Quoted 3 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +2
-0+ part_name =strsep (&data,"," ); + ver =strsep (&data,"," );Can ver become NULL here?
It should not be the case. As part of component fw version query device is expected to send the complete list for fw components.
On safer note will add NULL check.
Quoted 6 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c line 481
Quoted 4 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +3
-0+ ver_len =strlen (ver); +if (ver[ver_len -2 ] ==0x5C && ver[ver_len -1 ] ==0x6E ) + ver[ver_len -4 ] ='\0' ;Is
ver_lenguaranteed to be large enough?
Quoted 5 lines
Quoted 2 lines
fw version query response message will not cross 512 bytes. It is aligned with device implementation.
I meant the other way around, is
ver_lenguaranteed to large enough that it is safe to dover_len- 4 (or even -1).
For negative cases, it is not guaranteed.
Will guard with below check.
if ((i == total_part - 1) && ver_len >= 4)
Quoted 38 lines
Quoted 29 lines
Quoted 13 lines
Quoted 12 lines
(quoted diff) +1
-0+ ret = devlink_info_version_running_put_ext(req, part_name,ver,
+DEVLINK_INFO_VERSION_TYPE_COMPONENT);drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +7
-0+ } + +err_clear_bit: +clear_bit (T7XX_GET_INFO , &dl->status); +kfree (data); +return ret; +}Quoted 15 lines
Quoted 11 lines
drivers/net/wwan/t7xx/t7xx_port_devlink.c new file +11
-0+static void t7xx_devlink_uninit (struct t7xx_port *port) +{ +struct t7xx_devlink *dl = port->t7xx_dev->dl; +int i; + +vfree (dl->regions[T7XX_MRDUMP_INDEX ].buf); + + dl->mode =T7XX_NORMAL_MODE ; +destroy_workqueue (dl->wq); + + BUILD_BUG_ON(ARRAY_SIZE(t7xx_devlink_region_infos) >Quoted 1 line
ARRAY_SIZE(dl->regions));The same
BUILD_BUG_ONagain? Maybe just make a singlestatic_assert()outside of the functions.Quoted 8 lines
Should i change it as below ? please suggest.
static_assert(ARRAY_SIZE(t7xx_devlink_region_infos) ==
(sizeof(typeof_member(struct t7xx_devlink, regions))/
sizeof(struct t7xx_devlink_region)));
static voidt7xx_devlink_uninit(struct t7xx_port *port)
{
..
Quoted 8 lines
I see, it's not that easy so perhaps just leave it as is.
I guess something like this might work but seems bit hacky to me (untested):
static_assert(ARRAY_SIZE(t7xx_devlink_region_infos) ==
ARRAY_SIZE(((struct t7xx_devlink *)NULL)->regions));
I tested your code, it works.
If you are OK, I will keep it.
--
Chetan
PATCH v4 5/5 net: wwan: t7xx: Devlink documentation
In reply to [email protected]From: M Chetan Kumar <[email protected]>
Document the t7xx devlink commands usage for firmware flashing & coredump collection.
--
v4:
* Spell out fw as firmware.
* Drop "Refer to t7xx.rst file for details" in commit message.
* Move explanation below commands under flash update.
* Move firmware image type list under flash commands.
* Keyword formatting.
* Trim the unneeded trailing colon.
* Describe region commands.
v3:
* No change.
v2:
* Documentation correction.
* Add param details.
--- Documentation/networking/devlink/index.rst | 1 + Documentation/networking/devlink/t7xx.rst | 224 +++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 Documentation/networking/devlink/t7xx.rst
Documentation/networking/devlink/index.rst +1 -0
@@ -66,3 +66,4 @@ parameters, info versions, and other features it supports. prestera iosm octeontx2 + t7xx
Documentation/networking/devlink/t7xx.rst new file +224 -0
224 lines not on this page · raw message
Signature · 1 line
2.34.1