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

Commit fb4ee675 authored by Vijay Khemka's avatar Vijay Khemka Committed by David S. Miller
Browse files

net/ncsi: Add NCSI OEM command support



This patch adds OEM commands and response handling. It also defines OEM
command and response structure as per NCSI specification along with its
handlers.

ncsi_cmd_handler_oem: This is a generic command request handler for OEM
commands
ncsi_rsp_handler_oem: This is a generic response handler for OEM commands

Signed-off-by: default avatarVijay Khemka <vijaykhemka@fb.com>
Reviewed-by: default avatarJustin Lee <justin.lee1@dell.com>
Reviewed-by: default avatarSamuel Mendoza-Jonas <sam@mendozajonas.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6f847492
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -68,6 +68,10 @@ enum {
	NCSI_MODE_MAX
};

/* OEM Vendor Manufacture ID */
#define NCSI_OEM_MFR_MLX_ID             0x8119
#define NCSI_OEM_MFR_BCM_ID             0x113d

struct ncsi_channel_version {
	u32 version;		/* Supported BCD encoded NCSI version */
	u32 alpha2;		/* Supported BCD encoded NCSI version */
@@ -305,6 +309,7 @@ struct ncsi_cmd_arg {
		unsigned short words[8];
		unsigned int   dwords[4];
	};
	unsigned char        *data;       /* NCSI OEM data                 */
};

extern struct list_head ncsi_dev_list;
+27 −3
Original line number Diff line number Diff line
@@ -211,6 +211,25 @@ static int ncsi_cmd_handler_snfc(struct sk_buff *skb,
	return 0;
}

static int ncsi_cmd_handler_oem(struct sk_buff *skb,
				struct ncsi_cmd_arg *nca)
{
	struct ncsi_cmd_oem_pkt *cmd;
	unsigned int len;

	len = sizeof(struct ncsi_cmd_pkt_hdr) + 4;
	if (nca->payload < 26)
		len += 26;
	else
		len += nca->payload;

	cmd = skb_put_zero(skb, len);
	memcpy(&cmd->mfr_id, nca->data, nca->payload);
	ncsi_cmd_build_header(&cmd->cmd.common, nca);

	return 0;
}

static struct ncsi_cmd_handler {
	unsigned char type;
	int           payload;
@@ -244,7 +263,7 @@ static struct ncsi_cmd_handler {
	{ NCSI_PKT_CMD_GNS,    0, ncsi_cmd_handler_default },
	{ NCSI_PKT_CMD_GNPTS,  0, ncsi_cmd_handler_default },
	{ NCSI_PKT_CMD_GPS,    0, ncsi_cmd_handler_default },
	{ NCSI_PKT_CMD_OEM,    0, NULL                     },
	{ NCSI_PKT_CMD_OEM,   -1, ncsi_cmd_handler_oem     },
	{ NCSI_PKT_CMD_PLDM,   0, NULL                     },
	{ NCSI_PKT_CMD_GPUUID, 0, ncsi_cmd_handler_default }
};
@@ -316,7 +335,12 @@ int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca)
		return -ENOENT;
	}

	/* Get packet payload length and allocate the request */
	/* Get packet payload length and allocate the request
	 * It is expected that if length set as negative in
	 * handler structure means caller is initializing it
	 * and setting length in nca before calling xmit function
	 */
	if (nch->payload >= 0)
		nca->payload = nch->payload;
	nr = ncsi_alloc_command(nca);
	if (!nr)
+14 −0
Original line number Diff line number Diff line
@@ -151,6 +151,20 @@ struct ncsi_cmd_snfc_pkt {
	unsigned char           pad[22];
};

/* OEM Request Command as per NCSI Specification */
struct ncsi_cmd_oem_pkt {
	struct ncsi_cmd_pkt_hdr cmd;         /* Command header    */
	__be32                  mfr_id;      /* Manufacture ID    */
	unsigned char           data[];      /* OEM Payload Data  */
};

/* OEM Response Packet as per NCSI Specification */
struct ncsi_rsp_oem_pkt {
	struct ncsi_rsp_pkt_hdr rsp;         /* Command header    */
	__be32                  mfr_id;      /* Manufacture ID    */
	unsigned char           data[];      /* Payload data      */
};

/* Get Link Status */
struct ncsi_rsp_gls_pkt {
	struct ncsi_rsp_pkt_hdr rsp;        /* Response header   */
+42 −1
Original line number Diff line number Diff line
@@ -596,6 +596,47 @@ static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
	return 0;
}

static struct ncsi_rsp_oem_handler {
	unsigned int	mfr_id;
	int		(*handler)(struct ncsi_request *nr);
} ncsi_rsp_oem_handlers[] = {
	{ NCSI_OEM_MFR_MLX_ID, NULL },
	{ NCSI_OEM_MFR_BCM_ID, NULL }
};

/* Response handler for OEM command */
static int ncsi_rsp_handler_oem(struct ncsi_request *nr)
{
	struct ncsi_rsp_oem_pkt *rsp;
	struct ncsi_rsp_oem_handler *nrh = NULL;
	unsigned int mfr_id, i;

	/* Get the response header */
	rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
	mfr_id = ntohl(rsp->mfr_id);

	/* Check for manufacturer id and Find the handler */
	for (i = 0; i < ARRAY_SIZE(ncsi_rsp_oem_handlers); i++) {
		if (ncsi_rsp_oem_handlers[i].mfr_id == mfr_id) {
			if (ncsi_rsp_oem_handlers[i].handler)
				nrh = &ncsi_rsp_oem_handlers[i];
			else
				nrh = NULL;

			break;
		}
	}

	if (!nrh) {
		netdev_err(nr->ndp->ndev.dev, "Received unrecognized OEM packet with MFR-ID (0x%x)\n",
			   mfr_id);
		return -ENOENT;
	}

	/* Process the packet */
	return nrh->handler(nr);
}

static int ncsi_rsp_handler_gvi(struct ncsi_request *nr)
{
	struct ncsi_rsp_gvi_pkt *rsp;
@@ -932,7 +973,7 @@ static struct ncsi_rsp_handler {
	{ NCSI_PKT_RSP_GNS,   172, ncsi_rsp_handler_gns     },
	{ NCSI_PKT_RSP_GNPTS, 172, ncsi_rsp_handler_gnpts   },
	{ NCSI_PKT_RSP_GPS,     8, ncsi_rsp_handler_gps     },
	{ NCSI_PKT_RSP_OEM,     0, NULL                     },
	{ NCSI_PKT_RSP_OEM,    -1, ncsi_rsp_handler_oem     },
	{ NCSI_PKT_RSP_PLDM,    0, NULL                     },
	{ NCSI_PKT_RSP_GPUUID, 20, ncsi_rsp_handler_gpuuid  }
};