summaryrefslogtreecommitdiffstats
path: root/net/ncsi
diff options
context:
space:
mode:
authorVijay Khemka <vijaykhemka@fb.com>2018-10-16 15:13:19 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-18 01:14:54 -0400
commitcb10c7c0dfd9e6fd3d69ced98b05cbd198c48cf6 (patch)
tree937a12372c7962c90d4c27863225ea615267e362 /net/ncsi
parent1010c17ec5b496b54785dfb96f739d0f880484b3 (diff)
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>
Diffstat (limited to 'net/ncsi')
-rw-r--r--net/ncsi/Kconfig6
-rw-r--r--net/ncsi/internal.h9
-rw-r--r--net/ncsi/ncsi-manage.c82
-rw-r--r--net/ncsi/ncsi-pkt.h8
-rw-r--r--net/ncsi/ncsi-rsp.c44
5 files changed, 147 insertions, 2 deletions
diff --git a/net/ncsi/Kconfig b/net/ncsi/Kconfig
index 08a8a6031fd7..7f2b46108a24 100644
--- a/net/ncsi/Kconfig
+++ b/net/ncsi/Kconfig
@@ -10,3 +10,9 @@ config NET_NCSI
10 support. Enable this only if your system connects to a network 10 support. Enable this only if your system connects to a network
11 device via NCSI and the ethernet driver you're using supports 11 device via NCSI and the ethernet driver you're using supports
12 the protocol explicitly. 12 the protocol explicitly.
13config 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.
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index 13c9b5eeb3b7..1dae77c54009 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -71,6 +71,13 @@ enum {
71/* OEM Vendor Manufacture ID */ 71/* OEM Vendor Manufacture ID */
72#define NCSI_OEM_MFR_MLX_ID 0x8119 72#define NCSI_OEM_MFR_MLX_ID 0x8119
73#define NCSI_OEM_MFR_BCM_ID 0x113d 73#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
74 81
75struct ncsi_channel_version { 82struct ncsi_channel_version {
76 u32 version; /* Supported BCD encoded NCSI version */ 83 u32 version; /* Supported BCD encoded NCSI version */
@@ -246,6 +253,7 @@ enum {
246 ncsi_dev_state_probe_dp, 253 ncsi_dev_state_probe_dp,
247 ncsi_dev_state_config_sp = 0x0301, 254 ncsi_dev_state_config_sp = 0x0301,
248 ncsi_dev_state_config_cis, 255 ncsi_dev_state_config_cis,
256 ncsi_dev_state_config_oem_gma,
249 ncsi_dev_state_config_clear_vids, 257 ncsi_dev_state_config_clear_vids,
250 ncsi_dev_state_config_svf, 258 ncsi_dev_state_config_svf,
251 ncsi_dev_state_config_ev, 259 ncsi_dev_state_config_ev,
@@ -279,6 +287,7 @@ struct ncsi_dev_priv {
279#define NCSI_DEV_PROBED 1 /* Finalized NCSI topology */ 287#define NCSI_DEV_PROBED 1 /* Finalized NCSI topology */
280#define NCSI_DEV_HWA 2 /* Enabled HW arbitration */ 288#define NCSI_DEV_HWA 2 /* Enabled HW arbitration */
281#define NCSI_DEV_RESHUFFLE 4 289#define NCSI_DEV_RESHUFFLE 4
290 unsigned int gma_flag; /* OEM GMA flag */
282 spinlock_t lock; /* Protect the NCSI device */ 291 spinlock_t lock; /* Protect the NCSI device */
283#if IS_ENABLED(CONFIG_IPV6) 292#if IS_ENABLED(CONFIG_IPV6)
284 unsigned int inet6_addr_num; /* Number of IPv6 addresses */ 293 unsigned int inet6_addr_num; /* Number of IPv6 addresses */
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 6aa0614d2d28..bfc43b28c7a6 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -651,6 +651,72 @@ static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,
651 return 0; 651 return 0;
652} 652}
653 653
654#if IS_ENABLED(CONFIG_NCSI_OEM_CMD_GET_MAC)
655
656/* NCSI OEM Command APIs */
657static 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 */
679static 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
686static 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
654static void ncsi_configure_channel(struct ncsi_dev_priv *ndp) 720static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
655{ 721{
656 struct ncsi_dev *nd = &ndp->ndev; 722 struct ncsi_dev *nd = &ndp->ndev;
@@ -701,7 +767,23 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
701 goto error; 767 goto error;
702 } 768 }
703 769
770 nd->state = ncsi_dev_state_config_oem_gma;
771 break;
772 case ncsi_dev_state_config_oem_gma:
704 nd->state = ncsi_dev_state_config_clear_vids; 773 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
705 break; 787 break;
706 case ncsi_dev_state_config_clear_vids: 788 case ncsi_dev_state_config_clear_vids:
707 case ncsi_dev_state_config_svf: 789 case ncsi_dev_state_config_svf:
diff --git a/net/ncsi/ncsi-pkt.h b/net/ncsi/ncsi-pkt.h
index 0f2087c8d42a..4d3f06be38bd 100644
--- a/net/ncsi/ncsi-pkt.h
+++ b/net/ncsi/ncsi-pkt.h
@@ -165,6 +165,14 @@ struct ncsi_rsp_oem_pkt {
165 unsigned char data[]; /* Payload data */ 165 unsigned char data[]; /* Payload data */
166}; 166};
167 167
168/* Broadcom Response Data */
169struct 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
168/* Get Link Status */ 176/* Get Link Status */
169struct ncsi_rsp_gls_pkt { 177struct ncsi_rsp_gls_pkt {
170 struct ncsi_rsp_pkt_hdr rsp; /* Response header */ 178 struct ncsi_rsp_pkt_hdr rsp; /* Response header */
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c
index 85fa59afae34..77e07ba3f493 100644
--- a/net/ncsi/ncsi-rsp.c
+++ b/net/ncsi/ncsi-rsp.c
@@ -611,19 +611,59 @@ static int ncsi_rsp_handler_snfc(struct ncsi_request *nr)
611 return 0; 611 return 0;
612} 612}
613 613
614/* Response handler for Broadcom command Get Mac Address */
615static 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 */
640static 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
614static struct ncsi_rsp_oem_handler { 654static struct ncsi_rsp_oem_handler {
615 unsigned int mfr_id; 655 unsigned int mfr_id;
616 int (*handler)(struct ncsi_request *nr); 656 int (*handler)(struct ncsi_request *nr);
617} ncsi_rsp_oem_handlers[] = { 657} ncsi_rsp_oem_handlers[] = {
618 { NCSI_OEM_MFR_MLX_ID, NULL }, 658 { NCSI_OEM_MFR_MLX_ID, NULL },
619 { NCSI_OEM_MFR_BCM_ID, NULL } 659 { NCSI_OEM_MFR_BCM_ID, ncsi_rsp_handler_oem_bcm }
620}; 660};
621 661
622/* Response handler for OEM command */ 662/* Response handler for OEM command */
623static int ncsi_rsp_handler_oem(struct ncsi_request *nr) 663static int ncsi_rsp_handler_oem(struct ncsi_request *nr)
624{ 664{
625 struct ncsi_rsp_oem_pkt *rsp;
626 struct ncsi_rsp_oem_handler *nrh = NULL; 665 struct ncsi_rsp_oem_handler *nrh = NULL;
666 struct ncsi_rsp_oem_pkt *rsp;
627 unsigned int mfr_id, i; 667 unsigned int mfr_id, i;
628 668
629 /* Get the response header */ 669 /* Get the response header */