drivers/net/wireless/marvell/mwifiex/cmdevt.c

Source file repositories/reference/linux-study-clean/drivers/net/wireless/marvell/mwifiex/cmdevt.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wireless/marvell/mwifiex/cmdevt.c
Extension
.c
Size
51460 bytes
Lines
1692
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!sleep_cfm_tmp) {
			mwifiex_dbg(adapter, ERROR,
				    "SLEEP_CFM: dev_alloc_skb failed\n");
			return -ENOMEM;
		}

		skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm)
			+ MWIFIEX_TYPE_LEN);
		put_unaligned_le32(MWIFIEX_USB_TYPE_CMD, sleep_cfm_tmp->data);
		memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN,
		       adapter->sleep_cfm->data,
		       sizeof(struct mwifiex_opt_sleep_confirm));
		ret = adapter->if_ops.host_to_card(adapter,
						   MWIFIEX_USB_EP_CMD_EVENT,
						   sleep_cfm_tmp, NULL);
		if (ret != -EBUSY)
			dev_kfree_skb_any(sleep_cfm_tmp);
	} else {
		skb_push(adapter->sleep_cfm, adapter->intf_hdr_len);
		ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD,
						   adapter->sleep_cfm, NULL);
		skb_pull(adapter->sleep_cfm, adapter->intf_hdr_len);
	}

	if (ret == -1) {
		mwifiex_dbg(adapter, ERROR, "SLEEP_CFM: failed\n");
		adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++;
		return -1;
	}

	if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl))
		/* Response is not needed for sleep confirm command */
		adapter->ps_state = PS_STATE_SLEEP;
	else
		adapter->ps_state = PS_STATE_SLEEP_CFM;

	if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) &&
	    (test_bit(MWIFIEX_IS_HS_CONFIGURED, &adapter->work_flags) &&
	     !adapter->sleep_period.period)) {
		adapter->pm_wakeup_card_req = true;
		mwifiex_hs_activated_event(adapter, true);
	}

	return ret;
}

/*
 * This function allocates the command buffers and links them to
 * the command free queue.
 *
 * The driver uses a pre allocated number of command buffers, which
 * are created at driver initializations and freed at driver cleanup.
 * Every command needs to obtain a command buffer from this pool before
 * it can be issued. The command free queue lists the command buffers
 * currently free to use, while the command pending queue lists the
 * command buffers already in use and awaiting handling. Command buffers
 * are returned to the free queue after use.
 */
int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter)
{
	struct cmd_ctrl_node *cmd_array;
	u32 i;

	/* Allocate and initialize struct cmd_ctrl_node */
	cmd_array = kzalloc_objs(struct cmd_ctrl_node,
				 MWIFIEX_NUM_OF_CMD_BUFFER);
	if (!cmd_array)
		return -ENOMEM;

	adapter->cmd_pool = cmd_array;

	/* Allocate and initialize command buffers */
	for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) {
		cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER);
		if (!cmd_array[i].skb) {
			mwifiex_dbg(adapter, ERROR,
				    "unable to allocate command buffer\n");
			return -ENOMEM;
		}
	}

	for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++)
		mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]);

	return 0;
}

/*
 * This function frees the command buffers.
 *

Annotation

Implementation Notes