diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/mei/main.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mei/main.c | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 112cc362e8e7..d9733aaf6f6e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -119,6 +119,7 @@ struct iwl_sap_shared_mem_ctrl_blk { struct iwl_mei_shared_mem_ptrs { struct iwl_sap_shared_mem_ctrl_blk *ctrl; void *q_head[SAP_DIRECTION_MAX][SAP_QUEUE_IDX_MAX]; + size_t q_size[SAP_DIRECTION_MAX][SAP_QUEUE_IDX_MAX]; }; struct iwl_mei_filters { @@ -174,7 +175,7 @@ struct iwl_mei { }; /** - * iwl_mei_cache - cache for the parameters from iwlwifi + * struct iwl_mei_cache - cache for the parameters from iwlwifi * @ops: Callbacks to iwlwifi. * @netdev: The netdev that will be used to transmit / receive packets. * @conn_info: The connection info message triggered by iwlwifi's association. @@ -190,7 +191,7 @@ struct iwl_mei { * is cached here so that we can buffer the configuration even if we don't have * a bind from the mei bus and hence, on iwl_mei structure. */ -static struct { +struct iwl_mei_cache { const struct iwl_mei_ops *ops; struct net_device __rcu *netdev; const struct iwl_sap_notif_connection_info *conn_info; @@ -200,7 +201,9 @@ static struct { u8 mac_address[6]; u8 nvm_address[6]; void *priv; -} iwl_mei_cache = { +}; + +static struct iwl_mei_cache iwl_mei_cache = { .rf_kill = SAP_HW_RFKILL_DEASSERTED | SAP_SW_RFKILL_DEASSERTED }; @@ -209,7 +212,7 @@ static void iwl_mei_free_shared_mem(struct mei_cl_device *cldev) struct iwl_mei *mei = mei_cldev_get_drvdata(cldev); if (mei_cldev_dma_unmap(cldev)) - dev_err(&cldev->dev, "Coudln't unmap the shared mem properly\n"); + dev_err(&cldev->dev, "Couldn't unmap the shared mem properly\n"); memset(&mei->shared_mem, 0, sizeof(mei->shared_mem)); } @@ -271,6 +274,8 @@ static void iwl_mei_init_shared_mem(struct iwl_mei *mei) mem->q_head[dir][queue] = q_head; q_head += le32_to_cpu(mem->ctrl->dir[dir].q_ctrl_blk[queue].size); + mem->q_size[dir][queue] = + le32_to_cpu(mem->ctrl->dir[dir].q_ctrl_blk[queue].size); } } @@ -280,11 +285,11 @@ static void iwl_mei_init_shared_mem(struct iwl_mei *mei) static ssize_t iwl_mei_write_cyclic_buf(struct mei_cl_device *cldev, struct iwl_sap_q_ctrl_blk *notif_q, u8 *q_head, - const struct iwl_sap_hdr *hdr) + const struct iwl_sap_hdr *hdr, + u32 q_sz) { u32 rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr)); u32 wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr)); - u32 q_sz = le32_to_cpu(notif_q->size); size_t room_in_buf; size_t tx_sz = sizeof(*hdr) + le16_to_cpu(hdr->len); @@ -382,6 +387,7 @@ static int iwl_mei_send_sap_msg_payload(struct mei_cl_device *cldev, struct iwl_sap_q_ctrl_blk *notif_q; struct iwl_sap_dir *dir; void *q_head; + u32 q_sz; int ret; lockdep_assert_held(&iwl_mei_mutex); @@ -404,7 +410,8 @@ static int iwl_mei_send_sap_msg_payload(struct mei_cl_device *cldev, dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_HOST_TO_ME]; notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_NOTIF]; q_head = mei->shared_mem.q_head[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF]; - ret = iwl_mei_write_cyclic_buf(q_head, notif_q, q_head, hdr); + q_sz = mei->shared_mem.q_size[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_NOTIF]; + ret = iwl_mei_write_cyclic_buf(q_head, notif_q, q_head, hdr, q_sz); if (ret < 0) return ret; @@ -454,10 +461,10 @@ void iwl_mei_add_data_to_ring(struct sk_buff *skb, bool cb_tx) dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_HOST_TO_ME]; notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_DATA]; q_head = mei->shared_mem.q_head[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_DATA]; + q_sz = mei->shared_mem.q_size[SAP_DIRECTION_HOST_TO_ME][SAP_QUEUE_IDX_DATA]; rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr)); wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr)); - q_sz = le32_to_cpu(notif_q->size); hdr_sz = cb_tx ? sizeof(struct iwl_sap_cb_data) : sizeof(struct iwl_sap_hdr); tx_sz = skb->len + hdr_sz; @@ -627,6 +634,8 @@ static void iwl_mei_handle_csme_filters(struct mei_cl_device *cldev, lockdep_is_held(&iwl_mei_mutex)); new_filters = kzalloc(sizeof(*new_filters), GFP_KERNEL); + if (!new_filters) + return; /* Copy the OOB filters */ new_filters->filters = filters->filters; @@ -1074,11 +1083,11 @@ static void iwl_mei_handle_sap_rx_cmd(struct mei_cl_device *cldev, static void iwl_mei_handle_sap_rx(struct mei_cl_device *cldev, struct iwl_sap_q_ctrl_blk *notif_q, const u8 *q_head, - struct sk_buff_head *skbs) + struct sk_buff_head *skbs, + u32 q_sz) { u32 rd = le32_to_cpu(READ_ONCE(notif_q->rd_ptr)); u32 wr = le32_to_cpu(READ_ONCE(notif_q->wr_ptr)); - u32 q_sz = le32_to_cpu(notif_q->size); ssize_t valid_rx_sz; if (rd > q_sz || wr > q_sz) { @@ -1110,6 +1119,7 @@ static void iwl_mei_handle_check_shared_area(struct mei_cl_device *cldev) struct sk_buff_head tx_skbs; struct iwl_sap_dir *dir; void *q_head; + u32 q_sz; if (!mei->shared_mem.ctrl) return; @@ -1117,22 +1127,24 @@ static void iwl_mei_handle_check_shared_area(struct mei_cl_device *cldev) dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_ME_TO_HOST]; notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_NOTIF]; q_head = mei->shared_mem.q_head[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_NOTIF]; + q_sz = mei->shared_mem.q_size[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_NOTIF]; /* * Do not hold the mutex here, but rather each and every message * handler takes it. * This allows message handlers to take it at a certain time. */ - iwl_mei_handle_sap_rx(cldev, notif_q, q_head, NULL); + iwl_mei_handle_sap_rx(cldev, notif_q, q_head, NULL, q_sz); mutex_lock(&iwl_mei_mutex); dir = &mei->shared_mem.ctrl->dir[SAP_DIRECTION_ME_TO_HOST]; notif_q = &dir->q_ctrl_blk[SAP_QUEUE_IDX_DATA]; q_head = mei->shared_mem.q_head[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_DATA]; + q_sz = mei->shared_mem.q_size[SAP_DIRECTION_ME_TO_HOST][SAP_QUEUE_IDX_DATA]; __skb_queue_head_init(&tx_skbs); - iwl_mei_handle_sap_rx(cldev, notif_q, q_head, &tx_skbs); + iwl_mei_handle_sap_rx(cldev, notif_q, q_head, &tx_skbs, q_sz); if (skb_queue_empty(&tx_skbs)) { mutex_unlock(&iwl_mei_mutex); @@ -1693,6 +1705,7 @@ void iwl_mei_unregister_complete(void) mei_cldev_get_drvdata(iwl_mei_global_cldev); iwl_mei_send_sap_msg(mei->cldev, SAP_MSG_NOTIF_WIFIDR_DOWN); + mei->got_ownership = false; } mutex_unlock(&iwl_mei_mutex); @@ -1754,7 +1767,7 @@ static void iwl_mei_dbgfs_register(struct iwl_mei *mei) mei->dbgfs_dir, &iwl_mei_status); debugfs_create_file("send_start_message", S_IWUSR, mei->dbgfs_dir, mei, &iwl_mei_dbgfs_send_start_message_ops); - debugfs_create_file("req_ownserhip", S_IWUSR, mei->dbgfs_dir, + debugfs_create_file("req_ownership", S_IWUSR, mei->dbgfs_dir, mei, &iwl_mei_dbgfs_req_ownership_ops); } @@ -1771,7 +1784,7 @@ static void iwl_mei_dbgfs_unregister(struct iwl_mei *mei) {} #endif /* CONFIG_DEBUG_FS */ -/** +/* * iwl_mei_probe - the probe function called by the mei bus enumeration * * This allocates the data needed by iwlmei and sets a pointer to this data @@ -1799,6 +1812,12 @@ static int iwl_mei_probe(struct mei_cl_device *cldev, mei_cldev_set_drvdata(cldev, mei); mei->cldev = cldev; + /* + * The CSME firmware needs to boot the internal WLAN client. Wait here + * so that the DMA map request will succeed. + */ + msleep(20); + ret = iwl_mei_alloc_shared_mem(cldev); if (ret) goto free; |