net/ncsi: Add NCSI Broadcom OEM command
This patch adds OEM Broadcom commands and response handling. It also defines OEM Get MAC Address handler to get and configure the device. ncsi_oem_gma_handler_bcm: This handler send NCSI broadcom command for getting mac address. ncsi_rsp_handler_oem_bcm: This handles response received for all broadcom OEM commands. ncsi_rsp_handler_oem_bcm_gma: This handles get mac address response and set it to device. Signed-off-by: Vijay Khemka <vijaykhemka@fb.com> Reviewed-by: Samuel Mendoza-Jonas <sam@mendozajonas.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1010c17ec5
commit
cb10c7c0df
|
@ -10,3 +10,9 @@ config NET_NCSI
|
||||||
support. Enable this only if your system connects to a network
|
support. Enable this only if your system connects to a network
|
||||||
device via NCSI and the ethernet driver you're using supports
|
device via NCSI and the ethernet driver you're using supports
|
||||||
the protocol explicitly.
|
the protocol explicitly.
|
||||||
|
config NCSI_OEM_CMD_GET_MAC
|
||||||
|
bool "Get NCSI OEM MAC Address"
|
||||||
|
depends on NET_NCSI
|
||||||
|
---help---
|
||||||
|
This allows to get MAC address from NCSI firmware and set them back to
|
||||||
|
controller.
|
||||||
|
|
|
@ -71,6 +71,13 @@ enum {
|
||||||
/* OEM Vendor Manufacture ID */
|
/* OEM Vendor Manufacture ID */
|
||||||
#define NCSI_OEM_MFR_MLX_ID 0x8119
|
#define NCSI_OEM_MFR_MLX_ID 0x8119
|
||||||
#define NCSI_OEM_MFR_BCM_ID 0x113d
|
#define NCSI_OEM_MFR_BCM_ID 0x113d
|
||||||
|
/* Broadcom specific OEM Command */
|
||||||
|
#define NCSI_OEM_BCM_CMD_GMA 0x01 /* CMD ID for Get MAC */
|
||||||
|
/* OEM Command payload lengths*/
|
||||||
|
#define NCSI_OEM_BCM_CMD_GMA_LEN 12
|
||||||
|
/* Mac address offset in OEM response */
|
||||||
|
#define BCM_MAC_ADDR_OFFSET 28
|
||||||
|
|
||||||
|
|
||||||
struct ncsi_channel_version {
|
struct ncsi_channel_version {
|
||||||
u32 version; /* Supported BCD encoded NCSI version */
|
u32 version; /* Supported BCD encoded NCSI version */
|
||||||
|
@ -246,6 +253,7 @@ enum {
|
||||||
ncsi_dev_state_probe_dp,
|
ncsi_dev_state_probe_dp,
|
||||||
ncsi_dev_state_config_sp = 0x0301,
|
ncsi_dev_state_config_sp = 0x0301,
|
||||||
ncsi_dev_state_config_cis,
|
ncsi_dev_state_config_cis,
|
||||||
|
ncsi_dev_state_config_oem_gma,
|
||||||
ncsi_dev_state_config_clear_vids,
|
ncsi_dev_state_config_clear_vids,
|
||||||
ncsi_dev_state_config_svf,
|
ncsi_dev_state_config_svf,
|
||||||
ncsi_dev_state_config_ev,
|
ncsi_dev_state_config_ev,
|
||||||
|
@ -279,6 +287,7 @@ struct ncsi_dev_priv {
|
||||||
#define NCSI_DEV_PROBED 1 /* Finalized NCSI topology */
|
#define NCSI_DEV_PROBED 1 /* Finalized NCSI topology */
|
||||||
#define NCSI_DEV_HWA 2 /* Enabled HW arbitration */
|
#define NCSI_DEV_HWA 2 /* Enabled HW arbitration */
|
||||||
#define NCSI_DEV_RESHUFFLE 4
|
#define NCSI_DEV_RESHUFFLE 4
|
||||||
|
unsigned int gma_flag; /* OEM GMA flag */
|
||||||
spinlock_t lock; /* Protect the NCSI device */
|
spinlock_t lock; /* Protect the NCSI device */
|
||||||
#if IS_ENABLED(CONFIG_IPV6)
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
unsigned int inet6_addr_num; /* Number of IPv6 addresses */
|
unsigned int inet6_addr_num; /* Number of IPv6 addresses */
|
||||||
|
|
|
@ -651,6 +651,72 @@ static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
|
||||||
|
|
||||||
|
/* NCSI OEM Command APIs */
|
||||||
|
static int ncsi_oem_gma_handler_bcm(struct ncsi_cmd_arg *nca)
|
||||||
|
{
|
||||||
|
unsigned char data[NCSI_OEM_BCM_CMD_GMA_LEN];
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
nca->payload = NCSI_OEM_BCM_CMD_GMA_LEN;
|
||||||
|
|
||||||
|
memset(data, 0, NCSI_OEM_BCM_CMD_GMA_LEN);
|
||||||
|
*(unsigned int *)data = ntohl(NCSI_OEM_MFR_BCM_ID);
|
||||||
|
data[5] = NCSI_OEM_BCM_CMD_GMA;
|
||||||
|
|
||||||
|
nca->data = data;
|
||||||
|
|
||||||
|
ret = ncsi_xmit_cmd(nca);
|
||||||
|
if (ret)
|
||||||
|
netdev_err(nca->ndp->ndev.dev,
|
||||||
|
"NCSI: Failed to transmit cmd 0x%x during configure\n",
|
||||||
|
nca->type);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* OEM Command handlers initialization */
|
||||||
|
static struct ncsi_oem_gma_handler {
|
||||||
|
unsigned int mfr_id;
|
||||||
|
int (*handler)(struct ncsi_cmd_arg *nca);
|
||||||
|
} ncsi_oem_gma_handlers[] = {
|
||||||
|
{ NCSI_OEM_MFR_BCM_ID, ncsi_oem_gma_handler_bcm }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)
|
||||||
|
{
|
||||||
|
struct ncsi_oem_gma_handler *nch = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* This function should only be called once, return if flag set */
|
||||||
|
if (nca->ndp->gma_flag == 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Find gma handler for given manufacturer id */
|
||||||
|
for (i = 0; i < ARRAY_SIZE(ncsi_oem_gma_handlers); i++) {
|
||||||
|
if (ncsi_oem_gma_handlers[i].mfr_id == mf_id) {
|
||||||
|
if (ncsi_oem_gma_handlers[i].handler)
|
||||||
|
nch = &ncsi_oem_gma_handlers[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!nch) {
|
||||||
|
netdev_err(nca->ndp->ndev.dev,
|
||||||
|
"NCSI: No GMA handler available for MFR-ID (0x%x)\n",
|
||||||
|
mf_id);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the flag for GMA command which should only be called once */
|
||||||
|
nca->ndp->gma_flag = 1;
|
||||||
|
|
||||||
|
/* Get Mac address from NCSI device */
|
||||||
|
return nch->handler(nca);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
|
||||||
|
|
||||||
static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
|
static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
|
||||||
{
|
{
|
||||||
struct ncsi_dev *nd = &ndp->ndev;
|
struct ncsi_dev *nd = &ndp->ndev;
|
||||||
|
@ -701,7 +767,23 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nd->state = ncsi_dev_state_config_oem_gma;
|
||||||
|
break;
|
||||||
|
case ncsi_dev_state_config_oem_gma:
|
||||||
nd->state = ncsi_dev_state_config_clear_vids;
|
nd->state = ncsi_dev_state_config_clear_vids;
|
||||||
|
ret = -1;
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
|
||||||
|
nca.type = NCSI_PKT_CMD_OEM;
|
||||||
|
nca.package = np->id;
|
||||||
|
nca.channel = nc->id;
|
||||||
|
ndp->pending_req_num = 1;
|
||||||
|
ret = ncsi_gma_handler(&nca, nc->version.mf_id);
|
||||||
|
#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
schedule_work(&ndp->work);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case ncsi_dev_state_config_clear_vids:
|
case ncsi_dev_state_config_clear_vids:
|
||||||
case ncsi_dev_state_config_svf:
|
case ncsi_dev_state_config_svf:
|
||||||
|
|
|
@ -165,6 +165,14 @@ struct ncsi_rsp_oem_pkt {
|
||||||
unsigned char data[]; /* Payload data */
|
unsigned char data[]; /* Payload data */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Broadcom Response Data */
|
||||||
|
struct ncsi_rsp_oem_bcm_pkt {
|
||||||
|
unsigned char ver; /* Payload Version */
|
||||||
|
unsigned char type; /* OEM Command type */
|
||||||
|
__be16 len; /* Payload Length */
|
||||||
|
unsigned char data[]; /* Cmd specific Data */
|
||||||
|
};
|
||||||
|
|
||||||
/* Get Link Status */
|
/* Get Link Status */
|
||||||
struct ncsi_rsp_gls_pkt {
|
struct ncsi_rsp_gls_pkt {
|
||||||
struct ncsi_rsp_pkt_hdr rsp; /* Response header */
|
struct ncsi_rsp_pkt_hdr rsp; /* Response header */
|
||||||
|
|
|
@ -611,19 +611,59 @@ static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Response handler for Broadcom command Get Mac Address */
|
||||||
|
static int ncsi_rsp_handler_oem_bcm_gma(struct ncsi_request *nr)
|
||||||
|
{
|
||||||
|
struct ncsi_dev_priv *ndp = nr->ndp;
|
||||||
|
struct net_device *ndev = ndp->ndev.dev;
|
||||||
|
const struct net_device_ops *ops = ndev->netdev_ops;
|
||||||
|
struct ncsi_rsp_oem_pkt *rsp;
|
||||||
|
struct sockaddr saddr;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Get the response header */
|
||||||
|
rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
|
||||||
|
|
||||||
|
saddr.sa_family = ndev->type;
|
||||||
|
ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
|
||||||
|
memcpy(saddr.sa_data, &rsp->data[BCM_MAC_ADDR_OFFSET], ETH_ALEN);
|
||||||
|
/* Increase mac address by 1 for BMC's address */
|
||||||
|
saddr.sa_data[ETH_ALEN - 1]++;
|
||||||
|
ret = ops->ndo_set_mac_address(ndev, &saddr);
|
||||||
|
if (ret < 0)
|
||||||
|
netdev_warn(ndev, "NCSI: 'Writing mac address to device failed\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Response handler for Broadcom card */
|
||||||
|
static int ncsi_rsp_handler_oem_bcm(struct ncsi_request *nr)
|
||||||
|
{
|
||||||
|
struct ncsi_rsp_oem_bcm_pkt *bcm;
|
||||||
|
struct ncsi_rsp_oem_pkt *rsp;
|
||||||
|
|
||||||
|
/* Get the response header */
|
||||||
|
rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
|
||||||
|
bcm = (struct ncsi_rsp_oem_bcm_pkt *)(rsp->data);
|
||||||
|
|
||||||
|
if (bcm->type == NCSI_OEM_BCM_CMD_GMA)
|
||||||
|
return ncsi_rsp_handler_oem_bcm_gma(nr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ncsi_rsp_oem_handler {
|
static struct ncsi_rsp_oem_handler {
|
||||||
unsigned int mfr_id;
|
unsigned int mfr_id;
|
||||||
int (*handler)(struct ncsi_request *nr);
|
int (*handler)(struct ncsi_request *nr);
|
||||||
} ncsi_rsp_oem_handlers[] = {
|
} ncsi_rsp_oem_handlers[] = {
|
||||||
{ NCSI_OEM_MFR_MLX_ID, NULL },
|
{ NCSI_OEM_MFR_MLX_ID, NULL },
|
||||||
{ NCSI_OEM_MFR_BCM_ID, NULL }
|
{ NCSI_OEM_MFR_BCM_ID, ncsi_rsp_handler_oem_bcm }
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Response handler for OEM command */
|
/* Response handler for OEM command */
|
||||||
static int ncsi_rsp_handler_oem(struct ncsi_request *nr)
|
static int ncsi_rsp_handler_oem(struct ncsi_request *nr)
|
||||||
{
|
{
|
||||||
struct ncsi_rsp_oem_pkt *rsp;
|
|
||||||
struct ncsi_rsp_oem_handler *nrh = NULL;
|
struct ncsi_rsp_oem_handler *nrh = NULL;
|
||||||
|
struct ncsi_rsp_oem_pkt *rsp;
|
||||||
unsigned int mfr_id, i;
|
unsigned int mfr_id, i;
|
||||||
|
|
||||||
/* Get the response header */
|
/* Get the response header */
|
||||||
|
|
Loading…
Reference in New Issue