Skip to content

Commit cb10c7c

Browse files
vijaykhemkadavem330
authored andcommitted
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 <[email protected]> Reviewed-by: Samuel Mendoza-Jonas <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1010c17 commit cb10c7c

File tree

5 files changed

+147
-2
lines changed

5 files changed

+147
-2
lines changed

net/ncsi/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,9 @@ config NET_NCSI
1010
support. Enable this only if your system connects to a network
1111
device via NCSI and the ethernet driver you're using supports
1212
the protocol explicitly.
13+
config NCSI_OEM_CMD_GET_MAC
14+
bool "Get NCSI OEM MAC Address"
15+
depends on NET_NCSI
16+
---help---
17+
This allows to get MAC address from NCSI firmware and set them back to
18+
controller.

net/ncsi/internal.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ enum {
7171
/* OEM Vendor Manufacture ID */
7272
#define NCSI_OEM_MFR_MLX_ID 0x8119
7373
#define NCSI_OEM_MFR_BCM_ID 0x113d
74+
/* Broadcom specific OEM Command */
75+
#define NCSI_OEM_BCM_CMD_GMA 0x01 /* CMD ID for Get MAC */
76+
/* OEM Command payload lengths*/
77+
#define NCSI_OEM_BCM_CMD_GMA_LEN 12
78+
/* Mac address offset in OEM response */
79+
#define BCM_MAC_ADDR_OFFSET 28
80+
7481

7582
struct ncsi_channel_version {
7683
u32 version; /* Supported BCD encoded NCSI version */
@@ -246,6 +253,7 @@ enum {
246253
ncsi_dev_state_probe_dp,
247254
ncsi_dev_state_config_sp = 0x0301,
248255
ncsi_dev_state_config_cis,
256+
ncsi_dev_state_config_oem_gma,
249257
ncsi_dev_state_config_clear_vids,
250258
ncsi_dev_state_config_svf,
251259
ncsi_dev_state_config_ev,
@@ -279,6 +287,7 @@ struct ncsi_dev_priv {
279287
#define NCSI_DEV_PROBED 1 /* Finalized NCSI topology */
280288
#define NCSI_DEV_HWA 2 /* Enabled HW arbitration */
281289
#define NCSI_DEV_RESHUFFLE 4
290+
unsigned int gma_flag; /* OEM GMA flag */
282291
spinlock_t lock; /* Protect the NCSI device */
283292
#if IS_ENABLED(CONFIG_IPV6)
284293
unsigned int inet6_addr_num; /* Number of IPv6 addresses */

net/ncsi/ncsi-manage.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,72 @@ static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
651651
return 0;
652652
}
653653

654+
#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
655+
656+
/* NCSI OEM Command APIs */
657+
static int ncsi_oem_gma_handler_bcm(struct ncsi_cmd_arg *nca)
658+
{
659+
unsigned char data[NCSI_OEM_BCM_CMD_GMA_LEN];
660+
int ret = 0;
661+
662+
nca->payload = NCSI_OEM_BCM_CMD_GMA_LEN;
663+
664+
memset(data, 0, NCSI_OEM_BCM_CMD_GMA_LEN);
665+
*(unsigned int *)data = ntohl(NCSI_OEM_MFR_BCM_ID);
666+
data[5] = NCSI_OEM_BCM_CMD_GMA;
667+
668+
nca->data = data;
669+
670+
ret = ncsi_xmit_cmd(nca);
671+
if (ret)
672+
netdev_err(nca->ndp->ndev.dev,
673+
"NCSI: Failed to transmit cmd 0x%x during configure\n",
674+
nca->type);
675+
return ret;
676+
}
677+
678+
/* OEM Command handlers initialization */
679+
static struct ncsi_oem_gma_handler {
680+
unsigned int mfr_id;
681+
int (*handler)(struct ncsi_cmd_arg *nca);
682+
} ncsi_oem_gma_handlers[] = {
683+
{ NCSI_OEM_MFR_BCM_ID, ncsi_oem_gma_handler_bcm }
684+
};
685+
686+
static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)
687+
{
688+
struct ncsi_oem_gma_handler *nch = NULL;
689+
int i;
690+
691+
/* This function should only be called once, return if flag set */
692+
if (nca->ndp->gma_flag == 1)
693+
return -1;
694+
695+
/* Find gma handler for given manufacturer id */
696+
for (i = 0; i < ARRAY_SIZE(ncsi_oem_gma_handlers); i++) {
697+
if (ncsi_oem_gma_handlers[i].mfr_id == mf_id) {
698+
if (ncsi_oem_gma_handlers[i].handler)
699+
nch = &ncsi_oem_gma_handlers[i];
700+
break;
701+
}
702+
}
703+
704+
if (!nch) {
705+
netdev_err(nca->ndp->ndev.dev,
706+
"NCSI: No GMA handler available for MFR-ID (0x%x)\n",
707+
mf_id);
708+
return -1;
709+
}
710+
711+
/* Set the flag for GMA command which should only be called once */
712+
nca->ndp->gma_flag = 1;
713+
714+
/* Get Mac address from NCSI device */
715+
return nch->handler(nca);
716+
}
717+
718+
#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
719+
654720
static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
655721
{
656722
struct ncsi_dev *nd = &ndp->ndev;
@@ -701,7 +767,23 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
701767
goto error;
702768
}
703769

770+
nd->state = ncsi_dev_state_config_oem_gma;
771+
break;
772+
case ncsi_dev_state_config_oem_gma:
704773
nd->state = ncsi_dev_state_config_clear_vids;
774+
ret = -1;
775+
776+
#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
777+
nca.type = NCSI_PKT_CMD_OEM;
778+
nca.package = np->id;
779+
nca.channel = nc->id;
780+
ndp->pending_req_num = 1;
781+
ret = ncsi_gma_handler(&nca, nc->version.mf_id);
782+
#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */
783+
784+
if (ret < 0)
785+
schedule_work(&ndp->work);
786+
705787
break;
706788
case ncsi_dev_state_config_clear_vids:
707789
case ncsi_dev_state_config_svf:

net/ncsi/ncsi-pkt.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ struct ncsi_rsp_oem_pkt {
165165
unsigned char data[]; /* Payload data */
166166
};
167167

168+
/* Broadcom Response Data */
169+
struct ncsi_rsp_oem_bcm_pkt {
170+
unsigned char ver; /* Payload Version */
171+
unsigned char type; /* OEM Command type */
172+
__be16 len; /* Payload Length */
173+
unsigned char data[]; /* Cmd specific Data */
174+
};
175+
168176
/* Get Link Status */
169177
struct ncsi_rsp_gls_pkt {
170178
struct ncsi_rsp_pkt_hdr rsp; /* Response header */

net/ncsi/ncsi-rsp.c

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -611,19 +611,59 @@ static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
611611
return 0;
612612
}
613613

614+
/* Response handler for Broadcom command Get Mac Address */
615+
static int ncsi_rsp_handler_oem_bcm_gma(struct ncsi_request *nr)
616+
{
617+
struct ncsi_dev_priv *ndp = nr->ndp;
618+
struct net_device *ndev = ndp->ndev.dev;
619+
const struct net_device_ops *ops = ndev->netdev_ops;
620+
struct ncsi_rsp_oem_pkt *rsp;
621+
struct sockaddr saddr;
622+
int ret = 0;
623+
624+
/* Get the response header */
625+
rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
626+
627+
saddr.sa_family = ndev->type;
628+
ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
629+
memcpy(saddr.sa_data, &rsp->data[BCM_MAC_ADDR_OFFSET], ETH_ALEN);
630+
/* Increase mac address by 1 for BMC's address */
631+
saddr.sa_data[ETH_ALEN - 1]++;
632+
ret = ops->ndo_set_mac_address(ndev, &saddr);
633+
if (ret < 0)
634+
netdev_warn(ndev, "NCSI: 'Writing mac address to device failed\n");
635+
636+
return ret;
637+
}
638+
639+
/* Response handler for Broadcom card */
640+
static int ncsi_rsp_handler_oem_bcm(struct ncsi_request *nr)
641+
{
642+
struct ncsi_rsp_oem_bcm_pkt *bcm;
643+
struct ncsi_rsp_oem_pkt *rsp;
644+
645+
/* Get the response header */
646+
rsp = (struct ncsi_rsp_oem_pkt *)skb_network_header(nr->rsp);
647+
bcm = (struct ncsi_rsp_oem_bcm_pkt *)(rsp->data);
648+
649+
if (bcm->type == NCSI_OEM_BCM_CMD_GMA)
650+
return ncsi_rsp_handler_oem_bcm_gma(nr);
651+
return 0;
652+
}
653+
614654
static struct ncsi_rsp_oem_handler {
615655
unsigned int mfr_id;
616656
int (*handler)(struct ncsi_request *nr);
617657
} ncsi_rsp_oem_handlers[] = {
618658
{ NCSI_OEM_MFR_MLX_ID, NULL },
619-
{ NCSI_OEM_MFR_BCM_ID, NULL }
659+
{ NCSI_OEM_MFR_BCM_ID, ncsi_rsp_handler_oem_bcm }
620660
};
621661

622662
/* Response handler for OEM command */
623663
static int ncsi_rsp_handler_oem(struct ncsi_request *nr)
624664
{
625-
struct ncsi_rsp_oem_pkt *rsp;
626665
struct ncsi_rsp_oem_handler *nrh = NULL;
666+
struct ncsi_rsp_oem_pkt *rsp;
627667
unsigned int mfr_id, i;
628668

629669
/* Get the response header */

0 commit comments

Comments
 (0)