Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5bb0e98 authored by Ben Hutchings's avatar Ben Hutchings
Browse files

sfc: Use proper macros to declare and access MCDI arrays



A few functions are using heap buffers; change them to use stack
buffers as we really don't need to resort to the heap for a 252
byte buffer in process context.

MC_CMD_MEMCPY is quite weird in that it can use inline data placed in
the request buffer after the array of records.  Thus there are two
variable-length arrays and we can't use the normal accessors for
the second.  So we have to use _MCDI_PTR() in efx_sriov_memcpy().

Signed-off-by: default avatarBen Hutchings <bhutchings@solarflare.com>
parent d0c2ee99
Loading
Loading
Loading
Loading
+29 −32
Original line number Diff line number Diff line
@@ -668,7 +668,7 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
			   u16 *fw_subtype_list, u32 *capabilities)
{
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_BOARD_CFG_OUT_LENMAX);
	size_t outlen, offset, i;
	size_t outlen, i;
	int port_num = efx_port_num(efx);
	int rc;

@@ -684,22 +684,21 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
		goto fail;
	}

	offset = (port_num)
		? MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST
		: MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST;
	if (mac_address)
		memcpy(mac_address, outbuf + offset, ETH_ALEN);
		memcpy(mac_address,
		       port_num ?
		       MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1) :
		       MCDI_PTR(outbuf, GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0),
		       ETH_ALEN);
	if (fw_subtype_list) {
		/* Byte-swap and truncate or zero-pad as necessary */
		offset = MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST;
		for (i = 0;
		     i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM;
		     i++) {
			fw_subtype_list[i] =
				(offset + 2 <= outlen) ?
				le16_to_cpup((__le16 *)(outbuf + offset)) : 0;
			offset += 2;
		}
		     i < MCDI_VAR_ARRAY_LEN(outlen,
					    GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST);
		     i++)
			fw_subtype_list[i] = MCDI_ARRAY_WORD(
				outbuf, GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST, i);
		for (; i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM; i++)
			fw_subtype_list[i] = 0;
	}
	if (capabilities) {
		if (port_num)
@@ -980,7 +979,7 @@ static int efx_mcdi_read_assertion(struct efx_nic *efx)
{
	MCDI_DECLARE_BUF(inbuf, MC_CMD_GET_ASSERTS_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_GET_ASSERTS_OUT_LEN);
	unsigned int flags, index, ofst;
	unsigned int flags, index;
	const char *reason;
	size_t outlen;
	int retry;
@@ -1022,12 +1021,13 @@ static int efx_mcdi_read_assertion(struct efx_nic *efx)
		  MCDI_DWORD(outbuf, GET_ASSERTS_OUT_THREAD_OFFS));

	/* Print out the registers */
	ofst = MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST;
	for (index = 1; index < 32; index++) {
		netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n", index,
			MCDI_DWORD2(outbuf, ofst));
		ofst += sizeof(efx_dword_t);
	}
	for (index = 0;
	     index < MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM;
	     index++)
		netif_err(efx, hw, efx->net_dev, "R%.2d (?): 0x%.8x\n",
			  1 + index,
			  MCDI_ARRAY_DWORD(outbuf, GET_ASSERTS_OUT_GP_REGS_OFFS,
					   index));

	return 0;
}
@@ -1201,34 +1201,31 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx)
{
	struct efx_channel *channel;
	struct efx_rx_queue *rx_queue;
	__le32 *qid;
	MCDI_DECLARE_BUF(inbuf,
			 MC_CMD_FLUSH_RX_QUEUES_IN_LEN(EFX_MAX_CHANNELS));
	int rc, count;

	BUILD_BUG_ON(EFX_MAX_CHANNELS >
		     MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM);

	qid = kmalloc(EFX_MAX_CHANNELS * sizeof(*qid), GFP_KERNEL);
	if (qid == NULL)
		return -ENOMEM;

	count = 0;
	efx_for_each_channel(channel, efx) {
		efx_for_each_channel_rx_queue(rx_queue, channel) {
			if (rx_queue->flush_pending) {
				rx_queue->flush_pending = false;
				atomic_dec(&efx->rxq_flush_pending);
				qid[count++] = cpu_to_le32(
					efx_rx_queue_index(rx_queue));
				MCDI_SET_ARRAY_DWORD(
					inbuf, FLUSH_RX_QUEUES_IN_QID_OFST,
					count, efx_rx_queue_index(rx_queue));
				count++;
			}
		}
	}

	rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, (u8 *)qid,
			  count * sizeof(*qid), NULL, 0, NULL);
	rc = efx_mcdi_rpc(efx, MC_CMD_FLUSH_RX_QUEUES, inbuf,
			  MC_CMD_FLUSH_RX_QUEUES_IN_LEN(count), NULL, 0, NULL);
	WARN_ON(rc < 0);

	kfree(qid);

	return rc;
}

+0 −3
Original line number Diff line number Diff line
@@ -94,9 +94,6 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev);
#define _MCDI_DWORD(_buf, _field)					\
	((efx_dword_t *)MCDI_PTR(_buf, _field))

#define MCDI_DWORD2(_buf, _ofst)                                       \
	EFX_DWORD_FIELD(*(efx_dword_t *)((u8 *)(_buf) + (_ofst)), EFX_DWORD_0)

#define MCDI_SET_DWORD(_buf, _field, _value)				\
	EFX_POPULATE_DWORD_1(*_MCDI_DWORD(_buf, _field), EFX_DWORD_0, _value)
#define MCDI_DWORD(_buf, _field)					\
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ int efx_mcdi_set_mac(struct efx_nic *efx)
	u32 reject, fcntl;
	MCDI_DECLARE_BUF(cmdbytes, MC_CMD_SET_MAC_IN_LEN);

	memcpy(cmdbytes + MC_CMD_SET_MAC_IN_ADDR_OFST,
	memcpy(MCDI_PTR(cmdbytes, SET_MAC_IN_ADDR),
	       efx->net_dev->dev_addr, ETH_ALEN);

	MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_MTU,
+10 −15
Original line number Diff line number Diff line
@@ -615,17 +615,15 @@ static int efx_mcdi_bist(struct efx_nic *efx, unsigned int bist_mode,
	unsigned int retry, i, count = 0;
	size_t outlen;
	u32 status;
	u8 *buf, *ptr;
	MCDI_DECLARE_BUF(inbuf, MC_CMD_START_BIST_IN_LEN);
	MCDI_DECLARE_BUF(outbuf, MC_CMD_POLL_BIST_OUT_SFT9001_LEN);
	u8 *ptr;
	int rc;

	buf = kzalloc(0x100, GFP_KERNEL);
	if (buf == NULL)
		return -ENOMEM;

	BUILD_BUG_ON(MC_CMD_START_BIST_OUT_LEN != 0);
	MCDI_SET_DWORD(buf, START_BIST_IN_TYPE, bist_mode);
	rc = efx_mcdi_rpc(efx, MC_CMD_START_BIST, buf, MC_CMD_START_BIST_IN_LEN,
			  NULL, 0, NULL);
	MCDI_SET_DWORD(inbuf, START_BIST_IN_TYPE, bist_mode);
	rc = efx_mcdi_rpc(efx, MC_CMD_START_BIST,
			  inbuf, MC_CMD_START_BIST_IN_LEN, NULL, 0, NULL);
	if (rc)
		goto out;

@@ -633,11 +631,11 @@ static int efx_mcdi_bist(struct efx_nic *efx, unsigned int bist_mode,
	for (retry = 0; retry < 100; ++retry) {
		BUILD_BUG_ON(MC_CMD_POLL_BIST_IN_LEN != 0);
		rc = efx_mcdi_rpc(efx, MC_CMD_POLL_BIST, NULL, 0,
				  buf, 0x100, &outlen);
				  outbuf, sizeof(outbuf), &outlen);
		if (rc)
			goto out;

		status = MCDI_DWORD(buf, POLL_BIST_OUT_RESULT);
		status = MCDI_DWORD(outbuf, POLL_BIST_OUT_RESULT);
		if (status != MC_CMD_POLL_BIST_RUNNING)
			goto finished;

@@ -654,7 +652,7 @@ finished:
	if (efx->phy_type == PHY_TYPE_SFT9001B &&
	    (bist_mode == MC_CMD_PHY_BIST_CABLE_SHORT ||
	     bist_mode == MC_CMD_PHY_BIST_CABLE_LONG)) {
		ptr = MCDI_PTR(buf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A);
		ptr = MCDI_PTR(outbuf, POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A);
		if (status == MC_CMD_POLL_BIST_PASSED &&
		    outlen >= MC_CMD_POLL_BIST_OUT_SFT9001_LEN) {
			for (i = 0; i < 8; i++) {
@@ -668,8 +666,6 @@ finished:
	rc = count;

out:
	kfree(buf);

	return rc;
}

@@ -785,8 +781,7 @@ static int efx_mcdi_phy_get_module_eeprom(struct efx_nic *efx,
			space_remaining : payload_len;

		memcpy(user_data,
		       outbuf + page_off +
		       MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST,
		       MCDI_PTR(outbuf, GET_PHY_MEDIA_INFO_OUT_DATA) + page_off,
		       to_copy);

		space_remaining -= to_copy;
+20 −15
Original line number Diff line number Diff line
@@ -294,8 +294,7 @@ struct efx_ptp_data {
	struct work_struct pps_work;
	struct workqueue_struct *pps_workwq;
	bool nic_ts_enabled;
	u8 txbuf[ALIGN(MC_CMD_PTP_IN_TRANSMIT_LEN(
			       MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM), 4)];
	MCDI_DECLARE_BUF(txbuf, MC_CMD_PTP_IN_TRANSMIT_LENMAX);
	struct efx_ptp_timeset
	timeset[MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MAXNUM];
};
@@ -396,7 +395,8 @@ static void efx_ptp_send_times(struct efx_nic *efx,
}

/* Read a timeset from the MC's results and partial process. */
static void efx_ptp_read_timeset(u8 *data, struct efx_ptp_timeset *timeset)
static void efx_ptp_read_timeset(MCDI_DECLARE_STRUCT_PTR(data),
				 struct efx_ptp_timeset *timeset)
{
	unsigned start_ns, end_ns;

@@ -425,12 +425,14 @@ static void efx_ptp_read_timeset(u8 *data, struct efx_ptp_timeset *timeset)
 * busy. A number of readings are taken so that, hopefully, at least one good
 * synchronisation will be seen in the results.
 */
static int efx_ptp_process_times(struct efx_nic *efx, u8 *synch_buf,
static int
efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
		      size_t response_length,
		      const struct pps_event_time *last_time)
{
	unsigned number_readings = (response_length /
			       MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN);
	unsigned number_readings =
		MCDI_VAR_ARRAY_LEN(response_length,
				   PTP_OUT_SYNCHRONIZE_TIMESET);
	unsigned i;
	unsigned total;
	unsigned ngood = 0;
@@ -447,8 +449,10 @@ static int efx_ptp_process_times(struct efx_nic *efx, u8 *synch_buf,
	 * appera to be erroneous.
	 */
	for (i = 0; i < number_readings; i++) {
		efx_ptp_read_timeset(synch_buf, &ptp->timeset[i]);
		synch_buf += MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN;
		efx_ptp_read_timeset(
			MCDI_ARRAY_STRUCT_PTR(synch_buf,
					      PTP_OUT_SYNCHRONIZE_TIMESET, i),
			&ptp->timeset[i]);
	}

	/* Find the last good host-MC synchronization result. The MC times
@@ -564,15 +568,15 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
/* Transmit a PTP packet, via the MCDI interface, to the wire. */
static int efx_ptp_xmit_skb(struct efx_nic *efx, struct sk_buff *skb)
{
	u8 *txbuf = efx->ptp_data->txbuf;
	struct efx_ptp_data *ptp_data = efx->ptp_data;
	struct skb_shared_hwtstamps timestamps;
	int rc = -EIO;
	/* MCDI driver requires word aligned lengths */
	size_t len = ALIGN(MC_CMD_PTP_IN_TRANSMIT_LEN(skb->len), 4);
	MCDI_DECLARE_BUF(txtime, MC_CMD_PTP_OUT_TRANSMIT_LEN);

	MCDI_SET_DWORD(txbuf, PTP_IN_OP, MC_CMD_PTP_OP_TRANSMIT);
	MCDI_SET_DWORD(txbuf, PTP_IN_TRANSMIT_LENGTH, skb->len);
	MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_OP, MC_CMD_PTP_OP_TRANSMIT);
	MCDI_SET_DWORD(ptp_data->txbuf, PTP_IN_TRANSMIT_LENGTH, skb->len);
	if (skb_shinfo(skb)->nr_frags != 0) {
		rc = skb_linearize(skb);
		if (rc != 0)
@@ -585,9 +589,10 @@ static int efx_ptp_xmit_skb(struct efx_nic *efx, struct sk_buff *skb)
			goto fail;
	}
	skb_copy_from_linear_data(skb,
				  &txbuf[MC_CMD_PTP_IN_TRANSMIT_PACKET_OFST],
				  MCDI_PTR(ptp_data->txbuf,
					   PTP_IN_TRANSMIT_PACKET),
				  len);
	rc = efx_mcdi_rpc(efx, MC_CMD_PTP, txbuf, len, txtime,
	rc = efx_mcdi_rpc(efx, MC_CMD_PTP, ptp_data->txbuf, len, txtime,
			  sizeof(txtime), &len);
	if (rc != 0)
		goto fail;
Loading