From efe779b749cc9da0f36a01fba38c98864e6b8748 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:18 +0300 Subject: [PATCH 01/11] net: aquantia: Introduce new device ids and constants New set of aquantia devices has an upgraded hardware (B1). The hardware interface is identical to B0. The difference will be in firmware which is incompatible with old one. Reorganized and removed duplicate speed and devid definitions Introduced explicit flow control configuration defines Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/aq_cfg.h | 8 ++++- .../ethernet/aquantia/atlantic/aq_common.h | 34 +++++++++++++++++++ .../net/ethernet/aquantia/atlantic/aq_nic.h | 13 ------- .../ethernet/aquantia/atlantic/aq_pci_func.c | 28 ++++++++++++--- .../aquantia/atlantic/hw_atl/hw_atl_a0.c | 20 +++++------ .../aquantia/atlantic/hw_atl/hw_atl_a0.h | 13 ------- .../atlantic/hw_atl/hw_atl_a0_internal.h | 16 +++------ .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 20 +++++------ .../aquantia/atlantic/hw_atl/hw_atl_b0.h | 13 ------- .../atlantic/hw_atl/hw_atl_b0_internal.h | 16 +++------ 10 files changed, 94 insertions(+), 87 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h index 105fdb958cefb..0b49f1aeebd3d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h @@ -65,7 +65,13 @@ /*#define AQ_CFG_MAC_ADDR_PERMANENT {0x30, 0x0E, 0xE3, 0x12, 0x34, 0x56}*/ -#define AQ_CFG_FC_MODE 3U +#define AQ_NIC_FC_OFF 0U +#define AQ_NIC_FC_TX 1U +#define AQ_NIC_FC_RX 2U +#define AQ_NIC_FC_FULL 3U +#define AQ_NIC_FC_AUTO 4U + +#define AQ_CFG_FC_MODE AQ_NIC_FC_FULL #define AQ_CFG_SPEED_MSK 0xFFFFU /* 0xFFFFU==auto_neg */ diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h index f79da4b5900b9..35054c3a3ada2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h @@ -19,4 +19,38 @@ #include "aq_cfg.h" #include "aq_utils.h" +#define PCI_VENDOR_ID_AQUANTIA 0x1D6A + +#define AQ_DEVICE_ID_0001 0x0001 +#define AQ_DEVICE_ID_D100 0xD100 +#define AQ_DEVICE_ID_D107 0xD107 +#define AQ_DEVICE_ID_D108 0xD108 +#define AQ_DEVICE_ID_D109 0xD109 + +#define AQ_DEVICE_ID_AQC100 0x00B1 +#define AQ_DEVICE_ID_AQC107 0x07B1 +#define AQ_DEVICE_ID_AQC108 0x08B1 +#define AQ_DEVICE_ID_AQC109 0x09B1 +#define AQ_DEVICE_ID_AQC111 0x11B1 +#define AQ_DEVICE_ID_AQC112 0x12B1 + +#define AQ_DEVICE_ID_AQC100S 0x80B1 +#define AQ_DEVICE_ID_AQC107S 0x87B1 +#define AQ_DEVICE_ID_AQC108S 0x88B1 +#define AQ_DEVICE_ID_AQC109S 0x89B1 +#define AQ_DEVICE_ID_AQC111S 0x91B1 +#define AQ_DEVICE_ID_AQC112S 0x92B1 + +#define AQ_DEVICE_ID_AQC111E 0x51B1 +#define AQ_DEVICE_ID_AQC112E 0x52B1 + +#define HW_ATL_NIC_NAME "aQuantia AQtion 10Gbit Network Adapter" + +#define AQ_NIC_RATE_10G BIT(0) +#define AQ_NIC_RATE_5G BIT(1) +#define AQ_NIC_RATE_5GSR BIT(2) +#define AQ_NIC_RATE_2GS BIT(3) +#define AQ_NIC_RATE_1G BIT(4) +#define AQ_NIC_RATE_100M BIT(5) + #endif /* AQ_COMMON_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 1cd7d728e91ba..17a228f6f26bf 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -22,19 +22,6 @@ struct aq_hw_ops; struct aq_fw_s; struct aq_vec_s; -#define AQ_NIC_FC_OFF 0U -#define AQ_NIC_FC_TX 1U -#define AQ_NIC_FC_RX 2U -#define AQ_NIC_FC_FULL 3U -#define AQ_NIC_FC_AUTO 4U - -#define AQ_NIC_RATE_10G BIT(0) -#define AQ_NIC_RATE_5G BIT(1) -#define AQ_NIC_RATE_5GSR BIT(2) -#define AQ_NIC_RATE_2GS BIT(3) -#define AQ_NIC_RATE_1G BIT(4) -#define AQ_NIC_RATE_100M BIT(5) - struct aq_nic_cfg_s { const struct aq_hw_caps_s *aq_hw_caps; u64 hw_features; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index 78ef7d2deffee..95a6ae416b18b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -34,11 +34,29 @@ struct aq_pci_func_s { }; static const struct pci_device_id aq_pci_tbl[] = { - { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_0001), }, - { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D100), }, - { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D107), }, - { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D108), }, - { PCI_VDEVICE(AQUANTIA, HW_ATL_DEVICE_ID_D109), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_0001), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D100), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D107), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D108), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D109), }, + + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112), }, + + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC100S), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC107S), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC108S), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC109S), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111S), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112S), }, + + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC111E), }, + { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_AQC112E), }, + {} }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 4a1c1b96b8b69..4a47796190124 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -25,12 +25,12 @@ static int hw_atl_a0_get_hw_caps(struct aq_hw_s *self, { memcpy(aq_hw_caps, &hw_atl_a0_hw_caps_, sizeof(*aq_hw_caps)); - if (device == HW_ATL_DEVICE_ID_D108 && subsystem_device == 0x0001) - aq_hw_caps->link_speed_msk &= ~HW_ATL_A0_RATE_10G; + if (device == AQ_DEVICE_ID_D108 && subsystem_device == 0x0001) + aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; - if (device == HW_ATL_DEVICE_ID_D109 && subsystem_device == 0x0001) { - aq_hw_caps->link_speed_msk &= ~HW_ATL_A0_RATE_10G; - aq_hw_caps->link_speed_msk &= ~HW_ATL_A0_RATE_5G; + if (device == AQ_DEVICE_ID_D109 && subsystem_device == 0x0001) { + aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; + aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_5G; } return 0; @@ -907,11 +907,11 @@ static const struct aq_hw_ops hw_atl_ops_ = { const struct aq_hw_ops *hw_atl_a0_get_ops_by_id(struct pci_dev *pdev) { bool is_vid_ok = (pdev->vendor == PCI_VENDOR_ID_AQUANTIA); - bool is_did_ok = ((pdev->device == HW_ATL_DEVICE_ID_0001) || - (pdev->device == HW_ATL_DEVICE_ID_D100) || - (pdev->device == HW_ATL_DEVICE_ID_D107) || - (pdev->device == HW_ATL_DEVICE_ID_D108) || - (pdev->device == HW_ATL_DEVICE_ID_D109)); + bool is_did_ok = ((pdev->device == AQ_DEVICE_ID_0001) || + (pdev->device == AQ_DEVICE_ID_D100) || + (pdev->device == AQ_DEVICE_ID_D107) || + (pdev->device == AQ_DEVICE_ID_D108) || + (pdev->device == AQ_DEVICE_ID_D109)); bool is_rev_ok = (pdev->revision == 1U); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h index 4fdd51b670974..a4da1065fb5b2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h @@ -16,19 +16,6 @@ #include "../aq_common.h" -#ifndef PCI_VENDOR_ID_AQUANTIA - -#define PCI_VENDOR_ID_AQUANTIA 0x1D6A -#define HW_ATL_DEVICE_ID_0001 0x0001 -#define HW_ATL_DEVICE_ID_D100 0xD100 -#define HW_ATL_DEVICE_ID_D107 0xD107 -#define HW_ATL_DEVICE_ID_D108 0xD108 -#define HW_ATL_DEVICE_ID_D109 0xD109 - -#define HW_ATL_NIC_NAME "aQuantia AQtion 5Gbit Network Adapter" - -#endif - const struct aq_hw_ops *hw_atl_a0_get_ops_by_id(struct pci_dev *pdev); #endif /* HW_ATL_A0_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h index 7a71330252bdb..cc1d237377a61 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h @@ -62,12 +62,6 @@ #define HW_ATL_A0_MPI_SPEED_MSK 0xFFFFU #define HW_ATL_A0_MPI_SPEED_SHIFT 16U -#define HW_ATL_A0_RATE_10G BIT(0) -#define HW_ATL_A0_RATE_5G BIT(1) -#define HW_ATL_A0_RATE_2G5 BIT(3) -#define HW_ATL_A0_RATE_1G BIT(4) -#define HW_ATL_A0_RATE_100M BIT(5) - #define HW_ATL_A0_TXBUF_MAX 160U #define HW_ATL_A0_RXBUF_MAX 320U @@ -111,11 +105,11 @@ static struct aq_hw_caps_s hw_atl_a0_hw_caps_ = { NETIF_F_SG | NETIF_F_TSO, .hw_priv_flags = IFF_UNICAST_FLT, - .link_speed_msk = (HW_ATL_A0_RATE_10G | - HW_ATL_A0_RATE_5G | - HW_ATL_A0_RATE_2G5 | - HW_ATL_A0_RATE_1G | - HW_ATL_A0_RATE_100M), + .link_speed_msk = (AQ_NIC_RATE_10G | + AQ_NIC_RATE_5G | + AQ_NIC_RATE_2GS | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M), .flow_control = true, .mtu = HW_ATL_A0_MTU_JUMBO, .mac_regs_count = 88, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 0b090161ed793..edb9823e36e55 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -26,12 +26,12 @@ static int hw_atl_b0_get_hw_caps(struct aq_hw_s *self, { memcpy(aq_hw_caps, &hw_atl_b0_hw_caps_, sizeof(*aq_hw_caps)); - if (device == HW_ATL_DEVICE_ID_D108 && subsystem_device == 0x0001) - aq_hw_caps->link_speed_msk &= ~HW_ATL_B0_RATE_10G; + if (device == AQ_DEVICE_ID_D108 && subsystem_device == 0x0001) + aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; - if (device == HW_ATL_DEVICE_ID_D109 && subsystem_device == 0x0001) { - aq_hw_caps->link_speed_msk &= ~HW_ATL_B0_RATE_10G; - aq_hw_caps->link_speed_msk &= ~HW_ATL_B0_RATE_5G; + if (device == AQ_DEVICE_ID_D109 && subsystem_device == 0x0001) { + aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; + aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_5G; } return 0; @@ -981,11 +981,11 @@ static const struct aq_hw_ops hw_atl_ops_ = { const struct aq_hw_ops *hw_atl_b0_get_ops_by_id(struct pci_dev *pdev) { bool is_vid_ok = (pdev->vendor == PCI_VENDOR_ID_AQUANTIA); - bool is_did_ok = ((pdev->device == HW_ATL_DEVICE_ID_0001) || - (pdev->device == HW_ATL_DEVICE_ID_D100) || - (pdev->device == HW_ATL_DEVICE_ID_D107) || - (pdev->device == HW_ATL_DEVICE_ID_D108) || - (pdev->device == HW_ATL_DEVICE_ID_D109)); + bool is_did_ok = ((pdev->device == AQ_DEVICE_ID_0001) || + (pdev->device == AQ_DEVICE_ID_D100) || + (pdev->device == AQ_DEVICE_ID_D107) || + (pdev->device == AQ_DEVICE_ID_D108) || + (pdev->device == AQ_DEVICE_ID_D109)); bool is_rev_ok = (pdev->revision == 2U); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h index 3e10969c1df57..099799333eaaa 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h @@ -16,19 +16,6 @@ #include "../aq_common.h" -#ifndef PCI_VENDOR_ID_AQUANTIA - -#define PCI_VENDOR_ID_AQUANTIA 0x1D6A -#define HW_ATL_DEVICE_ID_0001 0x0001 -#define HW_ATL_DEVICE_ID_D100 0xD100 -#define HW_ATL_DEVICE_ID_D107 0xD107 -#define HW_ATL_DEVICE_ID_D108 0xD108 -#define HW_ATL_DEVICE_ID_D109 0xD109 - -#define HW_ATL_NIC_NAME "aQuantia AQtion 5Gbit Network Adapter" - -#endif - const struct aq_hw_ops *hw_atl_b0_get_ops_by_id(struct pci_dev *pdev); #endif /* HW_ATL_B0_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h index 740ff73c6d675..dcba2167a237c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h @@ -67,12 +67,6 @@ #define HW_ATL_B0_MPI_SPEED_MSK 0xFFFFU #define HW_ATL_B0_MPI_SPEED_SHIFT 16U -#define HW_ATL_B0_RATE_10G BIT(0) -#define HW_ATL_B0_RATE_5G BIT(1) -#define HW_ATL_B0_RATE_2G5 BIT(3) -#define HW_ATL_B0_RATE_1G BIT(4) -#define HW_ATL_B0_RATE_100M BIT(5) - #define HW_ATL_B0_TXBUF_MAX 160U #define HW_ATL_B0_RXBUF_MAX 320U @@ -166,11 +160,11 @@ static struct aq_hw_caps_s hw_atl_b0_hw_caps_ = { NETIF_F_TSO | NETIF_F_LRO, .hw_priv_flags = IFF_UNICAST_FLT, - .link_speed_msk = (HW_ATL_B0_RATE_10G | - HW_ATL_B0_RATE_5G | - HW_ATL_B0_RATE_2G5 | - HW_ATL_B0_RATE_1G | - HW_ATL_B0_RATE_100M), + .link_speed_msk = (AQ_NIC_RATE_10G | + AQ_NIC_RATE_5G | + AQ_NIC_RATE_2GS | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M), .flow_control = true, .mtu = HW_ATL_B0_MTU_JUMBO, .mac_regs_count = 88, From 4948293ff963e5451a8f0c21be8f1dfc2c7f65f5 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:19 +0300 Subject: [PATCH 02/11] net: aquantia: Introduce new AQC devices and capabilities A number of new AQC devices is going to be released. To support more flexible capabilities management a number of static caps instances is now declared. Devices now are mainly differs by supported speeds, but in future more parameters will be customized. A set of AQC100 devices have fibre media, not twisted pair - this is also reflected in new capabilities definitions. HW level also now directly exports hw_ops for each of A0/B0 hardware. PCI configuration now uses a device configuration table where each device ID is explicitly mapped with hardware OPs and capabilities structures. Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../ethernet/aquantia/atlantic/aq_common.h | 4 + .../net/ethernet/aquantia/atlantic/aq_hw.h | 9 +- .../net/ethernet/aquantia/atlantic/aq_nic.c | 9 +- .../net/ethernet/aquantia/atlantic/aq_nic.h | 3 +- .../ethernet/aquantia/atlantic/aq_pci_func.c | 74 ++++++++++++--- .../ethernet/aquantia/atlantic/aq_pci_func.h | 9 +- .../aquantia/atlantic/hw_atl/hw_atl_a0.c | 90 +++++++++++------- .../aquantia/atlantic/hw_atl/hw_atl_a0.h | 7 +- .../atlantic/hw_atl/hw_atl_a0_internal.h | 40 ++------ .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 91 ++++++++++++------- .../aquantia/atlantic/hw_atl/hw_atl_b0.h | 23 ++++- .../atlantic/hw_atl/hw_atl_b0_internal.h | 39 ++------ 12 files changed, 239 insertions(+), 159 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_common.h b/drivers/net/ethernet/aquantia/atlantic/aq_common.h index 35054c3a3ada2..d52b088ff8f07 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_common.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_common.h @@ -46,6 +46,10 @@ #define HW_ATL_NIC_NAME "aQuantia AQtion 10Gbit Network Adapter" +#define AQ_HWREV_ANY 0 +#define AQ_HWREV_1 1 +#define AQ_HWREV_2 2 + #define AQ_NIC_RATE_10G BIT(0) #define AQ_NIC_RATE_5G BIT(1) #define AQ_NIC_RATE_5GSR BIT(2) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 5d67f1335f4d0..5792a7c359986 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -23,6 +23,7 @@ struct aq_hw_caps_s { u64 hw_features; u64 link_speed_msk; unsigned int hw_priv_flags; + u32 media_type; u32 rxds; u32 txds; u32 txhwb_alignment; @@ -95,6 +96,9 @@ struct aq_stats_s { #define AQ_NIC_FLAGS_IS_NOT_TX_READY (AQ_NIC_FLAGS_IS_NOT_READY | \ AQ_NIC_LINK_DOWN) +#define AQ_HW_MEDIA_TYPE_TP 1U +#define AQ_HW_MEDIA_TYPE_FIBRE 2U + struct aq_hw_s { atomic_t flags; struct aq_nic_cfg_s *aq_nic_cfg; @@ -128,11 +132,6 @@ struct aq_hw_ops { void (*destroy)(struct aq_hw_s *self); - int (*get_hw_caps)(struct aq_hw_s *self, - struct aq_hw_caps_s *aq_hw_caps, - unsigned short device, - unsigned short subsystem_device); - int (*hw_ring_tx_xmit)(struct aq_hw_s *self, struct aq_ring_s *aq_ring, unsigned int frags); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index d98251371ee47..07bf77a39ffb2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -208,7 +208,8 @@ static void aq_nic_polling_timer_cb(struct timer_list *t) struct aq_nic_s *aq_nic_alloc_cold(struct pci_dev *pdev, struct aq_pci_func_s *aq_pci_func, unsigned int port, - const struct aq_hw_ops *aq_hw_ops) + const struct aq_hw_ops *aq_hw_ops, + const struct aq_hw_caps_s *aq_hw_caps) { struct net_device *ndev = NULL; struct aq_nic_s *self = NULL; @@ -230,16 +231,12 @@ struct aq_nic_s *aq_nic_alloc_cold(struct pci_dev *pdev, self->aq_pci_func = aq_pci_func; self->aq_hw_ops = *aq_hw_ops; + self->aq_hw_caps = *aq_hw_caps; self->port = (u8)port; self->aq_hw = self->aq_hw_ops.create(aq_pci_func, self->port); self->aq_hw->aq_nic_cfg = &self->aq_nic_cfg; - err = self->aq_hw_ops.get_hw_caps(self->aq_hw, &self->aq_hw_caps, - pdev->device, pdev->subsystem_device); - if (err < 0) - goto err_exit; - aq_nic_cfg_init_defaults(self); err_exit: diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 17a228f6f26bf..a49212aa44836 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -92,7 +92,8 @@ static inline struct device *aq_nic_get_dev(struct aq_nic_s *self) struct aq_nic_s *aq_nic_alloc_cold(struct pci_dev *pdev, struct aq_pci_func_s *aq_pci_func, unsigned int port, - const struct aq_hw_ops *aq_hw_ops); + const struct aq_hw_ops *aq_hw_ops, + const struct aq_hw_caps_s *aq_hw_caps); int aq_nic_ndev_init(struct aq_nic_s *self); struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev); void aq_nic_set_tx_ring(struct aq_nic_s *self, unsigned int idx, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index 95a6ae416b18b..e426e3ef629fb 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -60,20 +60,66 @@ static const struct pci_device_id aq_pci_tbl[] = { {} }; +const struct aq_board_revision_s hw_atl_boards[] = { + { AQ_DEVICE_ID_0001, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, }, + { AQ_DEVICE_ID_D100, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc100, }, + { AQ_DEVICE_ID_D107, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc107, }, + { AQ_DEVICE_ID_D108, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc108, }, + { AQ_DEVICE_ID_D109, AQ_HWREV_1, &hw_atl_ops_a0, &hw_atl_a0_caps_aqc109, }, + + { AQ_DEVICE_ID_0001, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, }, + { AQ_DEVICE_ID_D100, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc100, }, + { AQ_DEVICE_ID_D107, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc107, }, + { AQ_DEVICE_ID_D108, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc108, }, + { AQ_DEVICE_ID_D109, AQ_HWREV_2, &hw_atl_ops_b0, &hw_atl_b0_caps_aqc109, }, + + { AQ_DEVICE_ID_AQC100, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, + { AQ_DEVICE_ID_AQC107, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107, }, + { AQ_DEVICE_ID_AQC108, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108, }, + { AQ_DEVICE_ID_AQC109, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109, }, + { AQ_DEVICE_ID_AQC111, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111, }, + { AQ_DEVICE_ID_AQC112, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112, }, + + { AQ_DEVICE_ID_AQC100S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc100s, }, + { AQ_DEVICE_ID_AQC107S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc107s, }, + { AQ_DEVICE_ID_AQC108S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc108s, }, + { AQ_DEVICE_ID_AQC109S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc109s, }, + { AQ_DEVICE_ID_AQC111S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111s, }, + { AQ_DEVICE_ID_AQC112S, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112s, }, + + { AQ_DEVICE_ID_AQC111E, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc111e, }, + { AQ_DEVICE_ID_AQC112E, AQ_HWREV_ANY, &hw_atl_ops_b1, &hw_atl_b0_caps_aqc112e, }, +}; + MODULE_DEVICE_TABLE(pci, aq_pci_tbl); -static const struct aq_hw_ops *aq_pci_probe_get_hw_ops_by_id(struct pci_dev *pdev) +static int aq_pci_probe_get_hw_by_id(struct pci_dev *pdev, + const struct aq_hw_ops **ops, + const struct aq_hw_caps_s **caps) { - const struct aq_hw_ops *ops = NULL; + int i = 0; + + if (pdev->vendor != PCI_VENDOR_ID_AQUANTIA) + return -EINVAL; + + for (i = 0; i < ARRAY_SIZE(hw_atl_boards); i++) { + if (hw_atl_boards[i].devid == pdev->device && + (hw_atl_boards[i].revision == AQ_HWREV_ANY || + hw_atl_boards[i].revision == pdev->revision)) { + *ops = hw_atl_boards[i].ops; + *caps = hw_atl_boards[i].caps; + break; + } + } - ops = hw_atl_a0_get_ops_by_id(pdev); - if (!ops) - ops = hw_atl_b0_get_ops_by_id(pdev); + if (i == ARRAY_SIZE(hw_atl_boards)) + return -EINVAL; - return ops; + return 0; } struct aq_pci_func_s *aq_pci_func_alloc(const struct aq_hw_ops *aq_hw_ops, + const struct aq_hw_caps_s *aq_hw_caps, struct pci_dev *pdev) { struct aq_pci_func_s *self = NULL; @@ -92,17 +138,14 @@ struct aq_pci_func_s *aq_pci_func_alloc(const struct aq_hw_ops *aq_hw_ops, pci_set_drvdata(pdev, self); self->pdev = pdev; - - err = aq_hw_ops->get_hw_caps(NULL, &self->aq_hw_caps, pdev->device, - pdev->subsystem_device); - if (err < 0) - goto err_exit; + self->aq_hw_caps = *aq_hw_caps; self->ports = self->aq_hw_caps.ports; for (port = 0; port < self->ports; ++port) { struct aq_nic_s *aq_nic = aq_nic_alloc_cold(pdev, self, - port, aq_hw_ops); + port, aq_hw_ops, + aq_hw_caps); if (!aq_nic) { err = -ENOMEM; @@ -343,14 +386,17 @@ static int aq_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id) { const struct aq_hw_ops *aq_hw_ops = NULL; + const struct aq_hw_caps_s *aq_hw_caps = NULL; struct aq_pci_func_s *aq_pci_func = NULL; int err = 0; err = pci_enable_device(pdev); if (err < 0) goto err_exit; - aq_hw_ops = aq_pci_probe_get_hw_ops_by_id(pdev); - aq_pci_func = aq_pci_func_alloc(aq_hw_ops, pdev); + err = aq_pci_probe_get_hw_by_id(pdev, &aq_hw_ops, &aq_hw_caps); + if (err < 0) + goto err_exit; + aq_pci_func = aq_pci_func_alloc(aq_hw_ops, aq_hw_caps, pdev); if (!aq_pci_func) { err = -ENOMEM; goto err_exit; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h index 5f100ea1b0d67..701c99611c284 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h @@ -15,8 +15,13 @@ #include "aq_common.h" #include "aq_nic.h" -struct aq_pci_func_s *aq_pci_func_alloc(const struct aq_hw_ops *hw_ops, - struct pci_dev *pdev); +struct aq_board_revision_s { + unsigned short devid; + unsigned short revision; + const struct aq_hw_ops *ops; + const struct aq_hw_caps_s *caps; +}; + int aq_pci_func_init(struct aq_pci_func_s *self); int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i, char *name, void *aq_vec, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 4a47796190124..491a901b6d226 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -18,23 +18,67 @@ #include "hw_atl_llh.h" #include "hw_atl_a0_internal.h" -static int hw_atl_a0_get_hw_caps(struct aq_hw_s *self, - struct aq_hw_caps_s *aq_hw_caps, - unsigned short device, - unsigned short subsystem_device) -{ - memcpy(aq_hw_caps, &hw_atl_a0_hw_caps_, sizeof(*aq_hw_caps)); +#define DEFAULT_A0_BOARD_BASIC_CAPABILITIES \ + .is_64_dma = true, \ + .msix_irqs = 4U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL_A0_RSS_MAX, \ + .tcs = HW_ATL_A0_TC_MAX, \ + .rxd_alignment = 1U, \ + .rxd_size = HW_ATL_A0_RXD_SIZE, \ + .rxds = 248U, \ + .txd_alignment = 1U, \ + .txd_size = HW_ATL_A0_TXD_SIZE, \ + .txds = 8U * 1024U, \ + .txhwb_alignment = 4096U, \ + .tx_rings = HW_ATL_A0_TX_RINGS, \ + .rx_rings = HW_ATL_A0_RX_RINGS, \ + .hw_features = NETIF_F_HW_CSUM | \ + NETIF_F_RXHASH | \ + NETIF_F_RXCSUM | \ + NETIF_F_SG | \ + NETIF_F_TSO, \ + .hw_priv_flags = IFF_UNICAST_FLT, \ + .flow_control = true, \ + .mtu = HW_ATL_A0_MTU_JUMBO, \ + .mac_regs_count = 88 + +const struct aq_hw_caps_s hw_atl_a0_caps_aqc100 = { + DEFAULT_A0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_FIBRE, + .link_speed_msk = HW_ATL_A0_RATE_5G | + HW_ATL_A0_RATE_2G5 | + HW_ATL_A0_RATE_1G | + HW_ATL_A0_RATE_100M, +}; - if (device == AQ_DEVICE_ID_D108 && subsystem_device == 0x0001) - aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; +const struct aq_hw_caps_s hw_atl_a0_caps_aqc107 = { + DEFAULT_A0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = HW_ATL_A0_RATE_10G | + HW_ATL_A0_RATE_5G | + HW_ATL_A0_RATE_2G5 | + HW_ATL_A0_RATE_1G | + HW_ATL_A0_RATE_100M, +}; - if (device == AQ_DEVICE_ID_D109 && subsystem_device == 0x0001) { - aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; - aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_5G; - } +const struct aq_hw_caps_s hw_atl_a0_caps_aqc108 = { + DEFAULT_A0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = HW_ATL_A0_RATE_5G | + HW_ATL_A0_RATE_2G5 | + HW_ATL_A0_RATE_1G | + HW_ATL_A0_RATE_100M, +}; + +const struct aq_hw_caps_s hw_atl_a0_caps_aqc109 = { + DEFAULT_A0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = HW_ATL_A0_RATE_2G5 | + HW_ATL_A0_RATE_1G | + HW_ATL_A0_RATE_100M, +}; - return 0; -} static struct aq_hw_s *hw_atl_a0_create(struct aq_pci_func_s *aq_pci_func, unsigned int port) @@ -861,11 +905,9 @@ static int hw_atl_a0_hw_set_speed(struct aq_hw_s *self, u32 speed) return err; } -static const struct aq_hw_ops hw_atl_ops_ = { +const struct aq_hw_ops hw_atl_ops_a0 = { .create = hw_atl_a0_create, .destroy = hw_atl_a0_destroy, - .get_hw_caps = hw_atl_a0_get_hw_caps, - .hw_get_mac_permanent = hw_atl_utils_get_mac_permanent, .hw_set_mac_address = hw_atl_a0_hw_mac_addr_set, .hw_get_link_status = hw_atl_utils_mpi_get_link_status, @@ -903,17 +945,3 @@ static const struct aq_hw_ops hw_atl_ops_ = { .hw_get_hw_stats = hw_atl_utils_get_hw_stats, .hw_get_fw_version = hw_atl_utils_get_fw_version, }; - -const struct aq_hw_ops *hw_atl_a0_get_ops_by_id(struct pci_dev *pdev) -{ - bool is_vid_ok = (pdev->vendor == PCI_VENDOR_ID_AQUANTIA); - bool is_did_ok = ((pdev->device == AQ_DEVICE_ID_0001) || - (pdev->device == AQ_DEVICE_ID_D100) || - (pdev->device == AQ_DEVICE_ID_D107) || - (pdev->device == AQ_DEVICE_ID_D108) || - (pdev->device == AQ_DEVICE_ID_D109)); - - bool is_rev_ok = (pdev->revision == 1U); - - return (is_vid_ok && is_did_ok && is_rev_ok) ? &hw_atl_ops_ : NULL; -} diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h index a4da1065fb5b2..25fe954def03b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.h @@ -16,6 +16,11 @@ #include "../aq_common.h" -const struct aq_hw_ops *hw_atl_a0_get_ops_by_id(struct pci_dev *pdev); +extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc100; +extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc107; +extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc108; +extern const struct aq_hw_caps_s hw_atl_a0_caps_aqc109; + +extern const struct aq_hw_ops hw_atl_ops_a0; #endif /* HW_ATL_A0_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h index cc1d237377a61..1d8855558d74b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0_internal.h @@ -62,6 +62,12 @@ #define HW_ATL_A0_MPI_SPEED_MSK 0xFFFFU #define HW_ATL_A0_MPI_SPEED_SHIFT 16U +#define HW_ATL_A0_RATE_10G BIT(0) +#define HW_ATL_A0_RATE_5G BIT(1) +#define HW_ATL_A0_RATE_2G5 BIT(3) +#define HW_ATL_A0_RATE_1G BIT(4) +#define HW_ATL_A0_RATE_100M BIT(5) + #define HW_ATL_A0_TXBUF_MAX 160U #define HW_ATL_A0_RXBUF_MAX 320U @@ -82,38 +88,4 @@ #define HW_ATL_A0_FW_VER_EXPECTED 0x01050006U -/* HW layer capabilities */ -static struct aq_hw_caps_s hw_atl_a0_hw_caps_ = { - .ports = 1U, - .is_64_dma = true, - .msix_irqs = 4U, - .irq_mask = ~0U, - .vecs = HW_ATL_A0_RSS_MAX, - .tcs = HW_ATL_A0_TC_MAX, - .rxd_alignment = 1U, - .rxd_size = HW_ATL_A0_RXD_SIZE, - .rxds = 248U, - .txd_alignment = 1U, - .txd_size = HW_ATL_A0_TXD_SIZE, - .txds = 8U * 1024U, - .txhwb_alignment = 4096U, - .tx_rings = HW_ATL_A0_TX_RINGS, - .rx_rings = HW_ATL_A0_RX_RINGS, - .hw_features = NETIF_F_HW_CSUM | - NETIF_F_RXCSUM | - NETIF_F_RXHASH | - NETIF_F_SG | - NETIF_F_TSO, - .hw_priv_flags = IFF_UNICAST_FLT, - .link_speed_msk = (AQ_NIC_RATE_10G | - AQ_NIC_RATE_5G | - AQ_NIC_RATE_2GS | - AQ_NIC_RATE_1G | - AQ_NIC_RATE_100M), - .flow_control = true, - .mtu = HW_ATL_A0_MTU_JUMBO, - .mac_regs_count = 88, - .fw_ver_expected = HW_ATL_A0_FW_VER_EXPECTED, -}; - #endif /* HW_ATL_A0_INTERNAL_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index edb9823e36e55..87e7d0f04ee8a 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -19,23 +19,68 @@ #include "hw_atl_b0_internal.h" #include "hw_atl_llh_internal.h" -static int hw_atl_b0_get_hw_caps(struct aq_hw_s *self, - struct aq_hw_caps_s *aq_hw_caps, - unsigned short device, - unsigned short subsystem_device) -{ - memcpy(aq_hw_caps, &hw_atl_b0_hw_caps_, sizeof(*aq_hw_caps)); +#define DEFAULT_B0_BOARD_BASIC_CAPABILITIES \ + .is_64_dma = true, \ + .msix_irqs = 4U, \ + .irq_mask = ~0U, \ + .vecs = HW_ATL_B0_RSS_MAX, \ + .tcs = HW_ATL_B0_TC_MAX, \ + .rxd_alignment = 1U, \ + .rxd_size = HW_ATL_B0_RXD_SIZE, \ + .rxds = 4U * 1024U, \ + .txd_alignment = 1U, \ + .txd_size = HW_ATL_B0_TXD_SIZE, \ + .txds = 8U * 1024U, \ + .txhwb_alignment = 4096U, \ + .tx_rings = HW_ATL_B0_TX_RINGS, \ + .rx_rings = HW_ATL_B0_RX_RINGS, \ + .hw_features = NETIF_F_HW_CSUM | \ + NETIF_F_RXCSUM | \ + NETIF_F_RXHASH | \ + NETIF_F_SG | \ + NETIF_F_TSO | \ + NETIF_F_LRO, \ + .hw_priv_flags = IFF_UNICAST_FLT, \ + .flow_control = true, \ + .mtu = HW_ATL_B0_MTU_JUMBO, \ + .mac_regs_count = 88 + +const struct aq_hw_caps_s hw_atl_b0_caps_aqc100 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_FIBRE, + .link_speed_msk = HW_ATL_B0_RATE_10G | + HW_ATL_B0_RATE_5G | + HW_ATL_B0_RATE_2G5 | + HW_ATL_B0_RATE_1G | + HW_ATL_B0_RATE_100M, +}; - if (device == AQ_DEVICE_ID_D108 && subsystem_device == 0x0001) - aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; +const struct aq_hw_caps_s hw_atl_b0_caps_aqc107 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = HW_ATL_B0_RATE_10G | + HW_ATL_B0_RATE_5G | + HW_ATL_B0_RATE_2G5 | + HW_ATL_B0_RATE_1G | + HW_ATL_B0_RATE_100M, +}; - if (device == AQ_DEVICE_ID_D109 && subsystem_device == 0x0001) { - aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_10G; - aq_hw_caps->link_speed_msk &= ~AQ_NIC_RATE_5G; - } +const struct aq_hw_caps_s hw_atl_b0_caps_aqc108 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = HW_ATL_B0_RATE_5G | + HW_ATL_B0_RATE_2G5 | + HW_ATL_B0_RATE_1G | + HW_ATL_B0_RATE_100M, +}; - return 0; -} +const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = HW_ATL_B0_RATE_2G5 | + HW_ATL_B0_RATE_1G | + HW_ATL_B0_RATE_100M, +}; static struct aq_hw_s *hw_atl_b0_create(struct aq_pci_func_s *aq_pci_func, unsigned int port) @@ -935,11 +980,9 @@ static int hw_atl_b0_hw_set_speed(struct aq_hw_s *self, u32 speed) return err; } -static const struct aq_hw_ops hw_atl_ops_ = { +const struct aq_hw_ops hw_atl_ops_b0 = { .create = hw_atl_b0_create, .destroy = hw_atl_b0_destroy, - .get_hw_caps = hw_atl_b0_get_hw_caps, - .hw_get_mac_permanent = hw_atl_utils_get_mac_permanent, .hw_set_mac_address = hw_atl_b0_hw_mac_addr_set, .hw_get_link_status = hw_atl_utils_mpi_get_link_status, @@ -977,17 +1020,3 @@ static const struct aq_hw_ops hw_atl_ops_ = { .hw_get_hw_stats = hw_atl_utils_get_hw_stats, .hw_get_fw_version = hw_atl_utils_get_fw_version, }; - -const struct aq_hw_ops *hw_atl_b0_get_ops_by_id(struct pci_dev *pdev) -{ - bool is_vid_ok = (pdev->vendor == PCI_VENDOR_ID_AQUANTIA); - bool is_did_ok = ((pdev->device == AQ_DEVICE_ID_0001) || - (pdev->device == AQ_DEVICE_ID_D100) || - (pdev->device == AQ_DEVICE_ID_D107) || - (pdev->device == AQ_DEVICE_ID_D108) || - (pdev->device == AQ_DEVICE_ID_D109)); - - bool is_rev_ok = (pdev->revision == 2U); - - return (is_vid_ok && is_did_ok && is_rev_ok) ? &hw_atl_ops_ : NULL; -} diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h index 099799333eaaa..2cc8dacfdc271 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h @@ -16,6 +16,27 @@ #include "../aq_common.h" -const struct aq_hw_ops *hw_atl_b0_get_ops_by_id(struct pci_dev *pdev); +extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc100; +extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc107; +extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc108; +extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc109; + +#define hw_atl_b0_caps_aqc111 hw_atl_b0_caps_aqc108 +#define hw_atl_b0_caps_aqc112 hw_atl_b0_caps_aqc109 + +#define hw_atl_b0_caps_aqc100s hw_atl_b0_caps_aqc100 +#define hw_atl_b0_caps_aqc107s hw_atl_b0_caps_aqc107 +#define hw_atl_b0_caps_aqc108s hw_atl_b0_caps_aqc108 +#define hw_atl_b0_caps_aqc109s hw_atl_b0_caps_aqc109 + +#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc108 +#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc109 + +#define hw_atl_b0_caps_aqc111e hw_atl_b0_caps_aqc108 +#define hw_atl_b0_caps_aqc112e hw_atl_b0_caps_aqc109 + +extern const struct aq_hw_ops hw_atl_ops_b0; + +#define hw_atl_ops_b1 hw_atl_ops_b0 #endif /* HW_ATL_B0_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h index dcba2167a237c..405d1455c2225 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h @@ -67,6 +67,12 @@ #define HW_ATL_B0_MPI_SPEED_MSK 0xFFFFU #define HW_ATL_B0_MPI_SPEED_SHIFT 16U +#define HW_ATL_B0_RATE_10G BIT(0) +#define HW_ATL_B0_RATE_5G BIT(1) +#define HW_ATL_B0_RATE_2G5 BIT(3) +#define HW_ATL_B0_RATE_1G BIT(4) +#define HW_ATL_B0_RATE_100M BIT(5) + #define HW_ATL_B0_TXBUF_MAX 160U #define HW_ATL_B0_RXBUF_MAX 320U @@ -137,38 +143,5 @@ #define HW_ATL_INTR_MODER_MIN 0xFF /* HW layer capabilities */ -static struct aq_hw_caps_s hw_atl_b0_hw_caps_ = { - .ports = 1U, - .is_64_dma = true, - .msix_irqs = 4U, - .irq_mask = ~0U, - .vecs = HW_ATL_B0_RSS_MAX, - .tcs = HW_ATL_B0_TC_MAX, - .rxd_alignment = 1U, - .rxd_size = HW_ATL_B0_RXD_SIZE, - .rxds = 8U * 1024U, - .txd_alignment = 1U, - .txd_size = HW_ATL_B0_TXD_SIZE, - .txds = 8U * 1024U, - .txhwb_alignment = 4096U, - .tx_rings = HW_ATL_B0_TX_RINGS, - .rx_rings = HW_ATL_B0_RX_RINGS, - .hw_features = NETIF_F_HW_CSUM | - NETIF_F_RXCSUM | - NETIF_F_RXHASH | - NETIF_F_SG | - NETIF_F_TSO | - NETIF_F_LRO, - .hw_priv_flags = IFF_UNICAST_FLT, - .link_speed_msk = (AQ_NIC_RATE_10G | - AQ_NIC_RATE_5G | - AQ_NIC_RATE_2GS | - AQ_NIC_RATE_1G | - AQ_NIC_RATE_100M), - .flow_control = true, - .mtu = HW_ATL_B0_MTU_JUMBO, - .mac_regs_count = 88, - .fw_ver_expected = HW_ATL_B0_FW_VER_EXPECTED, -}; #endif /* HW_ATL_B0_INTERNAL_H */ From 8fcb98f462e6504e6d1ab2dab87c6db803c206b6 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:20 +0300 Subject: [PATCH 03/11] net: aquantia: Convert hw and caps structures to const static pointers This removes unnecessary structure copying, and prepares the driver for separate firmware ops table introduction. We also remove extra copy of capabilities structure (which is const actually) and also replace it with a const pointer in aq_nic_cfg. Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/aq_nic.c | 97 ++++++++++--------- .../net/ethernet/aquantia/atlantic/aq_nic.h | 3 +- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 07bf77a39ffb2..c5fd90cc310cb 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -66,8 +66,6 @@ static void aq_nic_cfg_init_defaults(struct aq_nic_s *self) { struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; - cfg->aq_hw_caps = &self->aq_hw_caps; - cfg->vecs = AQ_CFG_VECS_DEF; cfg->tcs = AQ_CFG_TCS_DEF; @@ -123,20 +121,20 @@ int aq_nic_cfg_start(struct aq_nic_s *self) cfg->irq_type = aq_pci_func_get_irq_type(self->aq_pci_func); if ((cfg->irq_type == AQ_HW_IRQ_LEGACY) || - (self->aq_hw_caps.vecs == 1U) || + (cfg->aq_hw_caps->vecs == 1U) || (cfg->vecs == 1U)) { cfg->is_rss = 0U; cfg->vecs = 1U; } - cfg->link_speed_msk &= self->aq_hw_caps.link_speed_msk; - cfg->hw_features = self->aq_hw_caps.hw_features; + cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk; + cfg->hw_features = cfg->aq_hw_caps->hw_features; return 0; } static int aq_nic_update_link_status(struct aq_nic_s *self) { - int err = self->aq_hw_ops.hw_get_link_status(self->aq_hw); + int err = self->aq_hw_ops->hw_get_link_status(self->aq_hw); if (err) return err; @@ -178,8 +176,8 @@ static void aq_nic_service_timer_cb(struct timer_list *t) if (err) goto err_exit; - if (self->aq_hw_ops.hw_update_stats) - self->aq_hw_ops.hw_update_stats(self->aq_hw); + if (self->aq_hw_ops->hw_update_stats) + self->aq_hw_ops->hw_update_stats(self->aq_hw); aq_nic_update_ndev_stats(self); @@ -230,12 +228,14 @@ struct aq_nic_s *aq_nic_alloc_cold(struct pci_dev *pdev, self->aq_pci_func = aq_pci_func; - self->aq_hw_ops = *aq_hw_ops; - self->aq_hw_caps = *aq_hw_caps; + self->aq_hw_ops = aq_hw_ops; + self->aq_nic_cfg.aq_hw_caps = aq_hw_caps; + self->aq_hw->aq_nic_cfg = &self->aq_nic_cfg; self->port = (u8)port; - self->aq_hw = self->aq_hw_ops.create(aq_pci_func, self->port); - self->aq_hw->aq_nic_cfg = &self->aq_nic_cfg; + self->aq_hw = self->aq_hw_ops->create(aq_pci_func, self->port); + if (err < 0) + goto err_exit; aq_nic_cfg_init_defaults(self); @@ -255,7 +255,7 @@ int aq_nic_ndev_register(struct aq_nic_s *self) err = -EINVAL; goto err_exit; } - err = self->aq_hw_ops.hw_get_mac_permanent(self->aq_hw, + err = self->aq_hw_ops->hw_get_mac_permanent(self->aq_hw, self->ndev->dev_addr); if (err < 0) goto err_exit; @@ -289,7 +289,7 @@ int aq_nic_ndev_init(struct aq_nic_s *self) self->ndev->features = aq_hw_caps->hw_features; self->ndev->priv_flags = aq_hw_caps->hw_priv_flags; self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN; - self->ndev->max_mtu = self->aq_hw_caps.mtu - ETH_FCS_LEN - ETH_HLEN; + self->ndev->max_mtu = aq_hw_caps->mtu - ETH_FCS_LEN - ETH_HLEN; return 0; } @@ -303,7 +303,7 @@ void aq_nic_ndev_free(struct aq_nic_s *self) unregister_netdev(self->ndev); if (self->aq_hw) - self->aq_hw_ops.destroy(self->aq_hw); + self->aq_hw_ops->destroy(self->aq_hw); free_netdev(self->ndev); @@ -365,18 +365,18 @@ int aq_nic_init(struct aq_nic_s *self) unsigned int i = 0U; self->power_state = AQ_HW_POWER_STATE_D0; - err = self->aq_hw_ops.hw_reset(self->aq_hw); + err = self->aq_hw_ops->hw_reset(self->aq_hw); if (err < 0) goto err_exit; - err = self->aq_hw_ops.hw_init(self->aq_hw, + err = self->aq_hw_ops->hw_init(self->aq_hw, aq_nic_get_ndev(self)->dev_addr); if (err < 0) goto err_exit; for (i = 0U, aq_vec = self->aq_vec[0]; self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) - aq_vec_init(aq_vec, &self->aq_hw_ops, self->aq_hw); + aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw); err_exit: return err; @@ -388,13 +388,13 @@ int aq_nic_start(struct aq_nic_s *self) int err = 0; unsigned int i = 0U; - err = self->aq_hw_ops.hw_multicast_list_set(self->aq_hw, + err = self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, self->mc_list.ar, self->mc_list.count); if (err < 0) goto err_exit; - err = self->aq_hw_ops.hw_packet_filter_set(self->aq_hw, + err = self->aq_hw_ops->hw_packet_filter_set(self->aq_hw, self->packet_filter); if (err < 0) goto err_exit; @@ -406,7 +406,7 @@ int aq_nic_start(struct aq_nic_s *self) goto err_exit; } - err = self->aq_hw_ops.hw_start(self->aq_hw); + err = self->aq_hw_ops->hw_start(self->aq_hw); if (err < 0) goto err_exit; @@ -431,7 +431,7 @@ int aq_nic_start(struct aq_nic_s *self) goto err_exit; } - err = self->aq_hw_ops.hw_irq_enable(self->aq_hw, + err = self->aq_hw_ops->hw_irq_enable(self->aq_hw, AQ_CFG_IRQ_MASK); if (err < 0) goto err_exit; @@ -616,7 +616,7 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) frags = aq_nic_map_skb(self, skb, ring); if (likely(frags)) { - err = self->aq_hw_ops.hw_ring_tx_xmit(self->aq_hw, + err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw, ring, frags); if (err >= 0) { @@ -633,14 +633,14 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self) { - return self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw); + return self->aq_hw_ops->hw_interrupt_moderation_set(self->aq_hw); } int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags) { int err = 0; - err = self->aq_hw_ops.hw_packet_filter_set(self->aq_hw, flags); + err = self->aq_hw_ops->hw_packet_filter_set(self->aq_hw, flags); if (err < 0) goto err_exit; @@ -672,11 +672,11 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) * multicast mask */ self->packet_filter |= IFF_ALLMULTI; - self->aq_hw->aq_nic_cfg->mc_list_count = 0; - return self->aq_hw_ops.hw_packet_filter_set(self->aq_hw, + self->aq_nic_cfg.mc_list_count = 0; + return self->aq_hw_ops->hw_packet_filter_set(self->aq_hw, self->packet_filter); } else { - return self->aq_hw_ops.hw_multicast_list_set(self->aq_hw, + return self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, self->mc_list.ar, self->mc_list.count); } @@ -691,7 +691,7 @@ int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu) int aq_nic_set_mac(struct aq_nic_s *self, struct net_device *ndev) { - return self->aq_hw_ops.hw_set_mac_address(self->aq_hw, ndev->dev_addr); + return self->aq_hw_ops->hw_set_mac_address(self->aq_hw, ndev->dev_addr); } unsigned int aq_nic_get_link_speed(struct aq_nic_s *self) @@ -706,8 +706,9 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p) regs->version = 1; - err = self->aq_hw_ops.hw_get_regs(self->aq_hw, - &self->aq_hw_caps, regs_buff); + err = self->aq_hw_ops->hw_get_regs(self->aq_hw, + self->aq_nic_cfg.aq_hw_caps, + regs_buff); if (err < 0) goto err_exit; @@ -717,7 +718,7 @@ int aq_nic_get_regs(struct aq_nic_s *self, struct ethtool_regs *regs, void *p) int aq_nic_get_regs_count(struct aq_nic_s *self) { - return self->aq_hw_caps.mac_regs_count; + return self->aq_nic_cfg.aq_hw_caps->mac_regs_count; } void aq_nic_get_stats(struct aq_nic_s *self, u64 *data) @@ -725,7 +726,7 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data) unsigned int i = 0U; unsigned int count = 0U; struct aq_vec_s *aq_vec = NULL; - struct aq_stats_s *stats = self->aq_hw_ops.hw_get_hw_stats(self->aq_hw); + struct aq_stats_s *stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw); if (!stats) goto err_exit; @@ -770,7 +771,7 @@ err_exit:; static void aq_nic_update_ndev_stats(struct aq_nic_s *self) { struct net_device *ndev = self->ndev; - struct aq_stats_s *stats = self->aq_hw_ops.hw_get_hw_stats(self->aq_hw); + struct aq_stats_s *stats = self->aq_hw_ops->hw_get_hw_stats(self->aq_hw); ndev->stats.rx_packets = stats->uprc + stats->mprc + stats->bprc; ndev->stats.rx_bytes = stats->ubrc + stats->mbrc + stats->bbrc; @@ -791,27 +792,27 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, ethtool_link_ksettings_zero_link_mode(cmd, supported); - if (self->aq_hw_caps.link_speed_msk & AQ_NIC_RATE_10G) + if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_10G) ethtool_link_ksettings_add_link_mode(cmd, supported, 10000baseT_Full); - if (self->aq_hw_caps.link_speed_msk & AQ_NIC_RATE_5G) + if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_5G) ethtool_link_ksettings_add_link_mode(cmd, supported, 5000baseT_Full); - if (self->aq_hw_caps.link_speed_msk & AQ_NIC_RATE_2GS) + if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_2GS) ethtool_link_ksettings_add_link_mode(cmd, supported, 2500baseT_Full); - if (self->aq_hw_caps.link_speed_msk & AQ_NIC_RATE_1G) + if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_1G) ethtool_link_ksettings_add_link_mode(cmd, supported, 1000baseT_Full); - if (self->aq_hw_caps.link_speed_msk & AQ_NIC_RATE_100M) + if (self->aq_nic_cfg.aq_hw_caps->link_speed_msk & AQ_NIC_RATE_100M) ethtool_link_ksettings_add_link_mode(cmd, supported, 100baseT_Full); - if (self->aq_hw_caps.flow_control) + if (self->aq_nic_cfg.aq_hw_caps->flow_control) ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); @@ -858,7 +859,7 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, int err = 0; if (cmd->base.autoneg == AUTONEG_ENABLE) { - rate = self->aq_hw_caps.link_speed_msk; + rate = self->aq_nic_cfg.aq_hw_caps->link_speed_msk; self->aq_nic_cfg.is_autoneg = true; } else { speed = cmd->base.speed; @@ -889,7 +890,7 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, goto err_exit; break; } - if (!(self->aq_hw_caps.link_speed_msk & rate)) { + if (!(self->aq_nic_cfg.aq_hw_caps->link_speed_msk & rate)) { err = -1; goto err_exit; } @@ -897,7 +898,7 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, self->aq_nic_cfg.is_autoneg = false; } - err = self->aq_hw_ops.hw_set_link_speed(self->aq_hw, rate); + err = self->aq_hw_ops->hw_set_link_speed(self->aq_hw, rate); if (err < 0) goto err_exit; @@ -916,7 +917,7 @@ u32 aq_nic_get_fw_version(struct aq_nic_s *self) { u32 fw_version = 0U; - self->aq_hw_ops.hw_get_fw_version(self->aq_hw, &fw_version); + self->aq_hw_ops->hw_get_fw_version(self->aq_hw, &fw_version); return fw_version; } @@ -931,7 +932,7 @@ int aq_nic_stop(struct aq_nic_s *self) del_timer_sync(&self->service_timer); - self->aq_hw_ops.hw_irq_disable(self->aq_hw, AQ_CFG_IRQ_MASK); + self->aq_hw_ops->hw_irq_disable(self->aq_hw, AQ_CFG_IRQ_MASK); if (self->aq_nic_cfg.is_polling) del_timer_sync(&self->polling_timer); @@ -942,7 +943,7 @@ int aq_nic_stop(struct aq_nic_s *self) self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) aq_vec_stop(aq_vec); - return self->aq_hw_ops.hw_stop(self->aq_hw); + return self->aq_hw_ops->hw_stop(self->aq_hw); } void aq_nic_deinit(struct aq_nic_s *self) @@ -958,9 +959,9 @@ void aq_nic_deinit(struct aq_nic_s *self) aq_vec_deinit(aq_vec); if (self->power_state == AQ_HW_POWER_STATE_D0) { - (void)self->aq_hw_ops.hw_deinit(self->aq_hw); + (void)self->aq_hw_ops->hw_deinit(self->aq_hw); } else { - (void)self->aq_hw_ops.hw_set_power(self->aq_hw, + (void)self->aq_hw_ops->hw_set_power(self->aq_hw, self->power_state); } diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index a49212aa44836..8e6e54213c369 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -69,8 +69,7 @@ struct aq_nic_s { unsigned int packet_filter; unsigned int power_state; u8 port; - struct aq_hw_ops aq_hw_ops; - struct aq_hw_caps_s aq_hw_caps; + const struct aq_hw_ops *aq_hw_ops; struct aq_nic_cfg_s aq_nic_cfg; struct timer_list service_timer; struct timer_list polling_timer; From 23ee07ad3c2fd5adf6e9ef21afb9aec489dc3b4e Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:21 +0300 Subject: [PATCH 04/11] net: aquantia: Cleanup pci functions module Driver contained a dead code of maintaining multiple pci port instances. That will never be used since for each pci function a separate NIC instance is created. Simplify this, making pci module only responsible for pci resource management. NIC initialization is also simplified accordingly. Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/aq_hw.h | 1 - .../net/ethernet/aquantia/atlantic/aq_main.c | 14 +- .../net/ethernet/aquantia/atlantic/aq_nic.c | 157 ++------ .../net/ethernet/aquantia/atlantic/aq_nic.h | 13 +- .../ethernet/aquantia/atlantic/aq_pci_func.c | 340 ++++++------------ .../ethernet/aquantia/atlantic/aq_pci_func.h | 14 +- .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 2 - 7 files changed, 156 insertions(+), 385 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 5792a7c359986..8219157e2d7c5 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -31,7 +31,6 @@ struct aq_hw_caps_s { u32 vecs; u32 mtu; u32 mac_regs_count; - u8 ports; u8 msix_irqs; u8 tcs; u8 rxd_alignment; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c index 887bc846375a8..ba5fe8c4125d8 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c @@ -43,14 +43,9 @@ struct net_device *aq_ndev_alloc(void) static int aq_ndev_open(struct net_device *ndev) { - struct aq_nic_s *aq_nic = NULL; int err = 0; + struct aq_nic_s *aq_nic = netdev_priv(ndev); - aq_nic = aq_nic_alloc_hot(ndev); - if (!aq_nic) { - err = -ENOMEM; - goto err_exit; - } err = aq_nic_init(aq_nic); if (err < 0) goto err_exit; @@ -73,7 +68,6 @@ static int aq_ndev_close(struct net_device *ndev) if (err < 0) goto err_exit; aq_nic_deinit(aq_nic); - aq_nic_free_hot_resources(aq_nic); err_exit: return err; @@ -145,15 +139,13 @@ static void aq_ndev_set_multicast_settings(struct net_device *ndev) err = aq_nic_set_packet_filter(aq_nic, ndev->flags); if (err < 0) - goto err_exit; + return; if (netdev_mc_count(ndev)) { err = aq_nic_set_multicast_list(aq_nic, ndev); if (err < 0) - goto err_exit; + return; } - -err_exit:; } static const struct net_device_ops aq_ndev_ops = { diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index c5fd90cc310cb..c5450b9887ace 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -14,7 +14,6 @@ #include "aq_vec.h" #include "aq_hw.h" #include "aq_pci_func.h" -#include "aq_main.h" #include #include @@ -61,17 +60,13 @@ static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues) rss_params->indirection_table[i] = i & (num_rss_queues - 1); } -/* Fills aq_nic_cfg with valid defaults */ -static void aq_nic_cfg_init_defaults(struct aq_nic_s *self) +/* Checks hw_caps and 'corrects' aq_nic_cfg in runtime */ +void aq_nic_cfg_start(struct aq_nic_s *self) { struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; - cfg->vecs = AQ_CFG_VECS_DEF; cfg->tcs = AQ_CFG_TCS_DEF; - cfg->rxds = AQ_CFG_RXDS_DEF; - cfg->txds = AQ_CFG_TXDS_DEF; - cfg->is_polling = AQ_CFG_IS_POLLING_DEF; cfg->itr = aq_itr; @@ -92,19 +87,13 @@ static void aq_nic_cfg_init_defaults(struct aq_nic_s *self) cfg->vlan_id = 0U; aq_nic_rss_init(self, cfg->num_rss_queues); -} - -/* Checks hw_caps and 'corrects' aq_nic_cfg in runtime */ -int aq_nic_cfg_start(struct aq_nic_s *self) -{ - struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; /*descriptors */ - cfg->rxds = min(cfg->rxds, cfg->aq_hw_caps->rxds); - cfg->txds = min(cfg->txds, cfg->aq_hw_caps->txds); + cfg->rxds = min(cfg->aq_hw_caps->rxds, AQ_CFG_RXDS_DEF); + cfg->txds = min(cfg->aq_hw_caps->txds, AQ_CFG_TXDS_DEF); /*rss rings */ - cfg->vecs = min(cfg->vecs, cfg->aq_hw_caps->vecs); + cfg->vecs = min(cfg->aq_hw_caps->vecs, AQ_CFG_VECS_DEF); cfg->vecs = min(cfg->vecs, num_online_cpus()); /* cfg->vecs should be power of 2 for RSS */ if (cfg->vecs >= 8U) @@ -118,7 +107,7 @@ int aq_nic_cfg_start(struct aq_nic_s *self) cfg->num_rss_queues = min(cfg->vecs, AQ_CFG_NUM_RSS_QUEUES_DEF); - cfg->irq_type = aq_pci_func_get_irq_type(self->aq_pci_func); + cfg->irq_type = aq_pci_func_get_irq_type(self); if ((cfg->irq_type == AQ_HW_IRQ_LEGACY) || (cfg->aq_hw_caps->vecs == 1U) || @@ -129,7 +118,6 @@ int aq_nic_cfg_start(struct aq_nic_s *self) cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk; cfg->hw_features = cfg->aq_hw_caps->hw_features; - return 0; } static int aq_nic_update_link_status(struct aq_nic_s *self) @@ -203,50 +191,6 @@ static void aq_nic_polling_timer_cb(struct timer_list *t) AQ_CFG_POLLING_TIMER_INTERVAL); } -struct aq_nic_s *aq_nic_alloc_cold(struct pci_dev *pdev, - struct aq_pci_func_s *aq_pci_func, - unsigned int port, - const struct aq_hw_ops *aq_hw_ops, - const struct aq_hw_caps_s *aq_hw_caps) -{ - struct net_device *ndev = NULL; - struct aq_nic_s *self = NULL; - int err = 0; - - ndev = aq_ndev_alloc(); - if (!ndev) { - err = -ENOMEM; - goto err_exit; - } - - self = netdev_priv(ndev); - - SET_NETDEV_DEV(ndev, &pdev->dev); - - ndev->if_port = port; - self->ndev = ndev; - - self->aq_pci_func = aq_pci_func; - - self->aq_hw_ops = aq_hw_ops; - self->aq_nic_cfg.aq_hw_caps = aq_hw_caps; - self->aq_hw->aq_nic_cfg = &self->aq_nic_cfg; - self->port = (u8)port; - - self->aq_hw = self->aq_hw_ops->create(aq_pci_func, self->port); - if (err < 0) - goto err_exit; - - aq_nic_cfg_init_defaults(self); - -err_exit: - if (err < 0) { - aq_nic_free_hot_resources(self); - self = NULL; - } - return self; -} - int aq_nic_ndev_register(struct aq_nic_s *self) { int err = 0; @@ -255,9 +199,10 @@ int aq_nic_ndev_register(struct aq_nic_s *self) err = -EINVAL; goto err_exit; } + err = self->aq_hw_ops->hw_get_mac_permanent(self->aq_hw, self->ndev->dev_addr); - if (err < 0) + if (err) goto err_exit; #if defined(AQ_CFG_MAC_ADDR_PERMANENT) @@ -268,19 +213,29 @@ int aq_nic_ndev_register(struct aq_nic_s *self) } #endif + for (self->aq_vecs = 0; self->aq_vecs < aq_nic_get_cfg(self)->vecs; + self->aq_vecs++) { + self->aq_vec[self->aq_vecs] = + aq_vec_alloc(self, self->aq_vecs, aq_nic_get_cfg(self)); + if (!self->aq_vec[self->aq_vecs]) { + err = -ENOMEM; + goto err_exit; + } + } + netif_carrier_off(self->ndev); netif_tx_disable(self->ndev); err = register_netdev(self->ndev); - if (err < 0) + if (err) goto err_exit; err_exit: return err; } -int aq_nic_ndev_init(struct aq_nic_s *self) +void aq_nic_ndev_init(struct aq_nic_s *self) { const struct aq_hw_caps_s *aq_hw_caps = self->aq_nic_cfg.aq_hw_caps; struct aq_nic_cfg_s *aq_nic_cfg = &self->aq_nic_cfg; @@ -291,60 +246,6 @@ int aq_nic_ndev_init(struct aq_nic_s *self) self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN; self->ndev->max_mtu = aq_hw_caps->mtu - ETH_FCS_LEN - ETH_HLEN; - return 0; -} - -void aq_nic_ndev_free(struct aq_nic_s *self) -{ - if (!self->ndev) - goto err_exit; - - if (self->ndev->reg_state == NETREG_REGISTERED) - unregister_netdev(self->ndev); - - if (self->aq_hw) - self->aq_hw_ops->destroy(self->aq_hw); - - free_netdev(self->ndev); - -err_exit:; -} - -struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev) -{ - struct aq_nic_s *self = NULL; - int err = 0; - - if (!ndev) { - err = -EINVAL; - goto err_exit; - } - self = netdev_priv(ndev); - - if (!self) { - err = -EINVAL; - goto err_exit; - } - if (netif_running(ndev)) - netif_tx_disable(ndev); - netif_carrier_off(self->ndev); - - for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs; - self->aq_vecs++) { - self->aq_vec[self->aq_vecs] = - aq_vec_alloc(self, self->aq_vecs, &self->aq_nic_cfg); - if (!self->aq_vec[self->aq_vecs]) { - err = -ENOMEM; - goto err_exit; - } - } - -err_exit: - if (err < 0) { - aq_nic_free_hot_resources(self); - self = NULL; - } - return self; } void aq_nic_set_tx_ring(struct aq_nic_s *self, unsigned int idx, @@ -370,7 +271,7 @@ int aq_nic_init(struct aq_nic_s *self) goto err_exit; err = self->aq_hw_ops->hw_init(self->aq_hw, - aq_nic_get_ndev(self)->dev_addr); + aq_nic_get_ndev(self)->dev_addr); if (err < 0) goto err_exit; @@ -378,6 +279,8 @@ int aq_nic_init(struct aq_nic_s *self) self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) aq_vec_init(aq_vec, self->aq_hw_ops, self->aq_hw); + netif_carrier_off(self->ndev); + err_exit: return err; } @@ -424,9 +327,9 @@ int aq_nic_start(struct aq_nic_s *self) } else { for (i = 0U, aq_vec = self->aq_vec[0]; self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) { - err = aq_pci_func_alloc_irq(self->aq_pci_func, i, + err = aq_pci_func_alloc_irq(self, i, self->ndev->name, aq_vec, - aq_vec_get_affinity_mask(aq_vec)); + aq_vec_get_affinity_mask(aq_vec)); if (err < 0) goto err_exit; } @@ -617,8 +520,7 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) if (likely(frags)) { err = self->aq_hw_ops->hw_ring_tx_xmit(self->aq_hw, - ring, - frags); + ring, frags); if (err >= 0) { ++ring->stats.tx.packets; ring->stats.tx.bytes += skb->len; @@ -674,7 +576,7 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) self->packet_filter |= IFF_ALLMULTI; self->aq_nic_cfg.mc_list_count = 0; return self->aq_hw_ops->hw_packet_filter_set(self->aq_hw, - self->packet_filter); + self->packet_filter); } else { return self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, self->mc_list.ar, @@ -757,7 +659,6 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data) i++; data += i; - count = 0U; for (i = 0U, aq_vec = self->aq_vec[0]; aq_vec && self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) { @@ -937,7 +838,7 @@ int aq_nic_stop(struct aq_nic_s *self) if (self->aq_nic_cfg.is_polling) del_timer_sync(&self->polling_timer); else - aq_pci_func_free_irqs(self->aq_pci_func); + aq_pci_func_free_irqs(self); for (i = 0U, aq_vec = self->aq_vec[0]; self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) @@ -968,7 +869,7 @@ void aq_nic_deinit(struct aq_nic_s *self) err_exit:; } -void aq_nic_free_hot_resources(struct aq_nic_s *self) +void aq_nic_free_vectors(struct aq_nic_s *self) { unsigned int i = 0U; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 8e6e54213c369..a85b08a34ed41 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -17,7 +17,6 @@ #include "aq_hw.h" struct aq_ring_s; -struct aq_pci_func_s; struct aq_hw_ops; struct aq_fw_s; struct aq_vec_s; @@ -64,7 +63,6 @@ struct aq_nic_s { struct aq_ring_s *aq_ring_tx[AQ_CFG_VECS_MAX * AQ_CFG_TCS_MAX]; struct aq_hw_s *aq_hw; struct net_device *ndev; - struct aq_pci_func_s *aq_pci_func; unsigned int aq_vecs; unsigned int packet_filter; unsigned int power_state; @@ -88,19 +86,13 @@ static inline struct device *aq_nic_get_dev(struct aq_nic_s *self) return self->ndev->dev.parent; } -struct aq_nic_s *aq_nic_alloc_cold(struct pci_dev *pdev, - struct aq_pci_func_s *aq_pci_func, - unsigned int port, - const struct aq_hw_ops *aq_hw_ops, - const struct aq_hw_caps_s *aq_hw_caps); -int aq_nic_ndev_init(struct aq_nic_s *self); +void aq_nic_ndev_init(struct aq_nic_s *self); struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev); void aq_nic_set_tx_ring(struct aq_nic_s *self, unsigned int idx, struct aq_ring_s *ring); -struct device *aq_nic_get_dev(struct aq_nic_s *self); struct net_device *aq_nic_get_ndev(struct aq_nic_s *self); int aq_nic_init(struct aq_nic_s *self); -int aq_nic_cfg_start(struct aq_nic_s *self); +void aq_nic_cfg_start(struct aq_nic_s *self); int aq_nic_ndev_register(struct aq_nic_s *self); void aq_nic_ndev_free(struct aq_nic_s *self); int aq_nic_start(struct aq_nic_s *self); @@ -111,6 +103,7 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data); int aq_nic_stop(struct aq_nic_s *self); void aq_nic_deinit(struct aq_nic_s *self); void aq_nic_free_hot_resources(struct aq_nic_s *self); +void aq_nic_free_vectors(struct aq_nic_s *self); int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu); int aq_nic_set_mac(struct aq_nic_s *self, struct net_device *ndev); int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index e426e3ef629fb..f5dd5f75a40f3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -12,27 +12,14 @@ #include #include -#include "aq_pci_func.h" +#include "aq_main.h" #include "aq_nic.h" #include "aq_vec.h" #include "aq_hw.h" +#include "aq_pci_func.h" #include "hw_atl/hw_atl_a0.h" #include "hw_atl/hw_atl_b0.h" -struct aq_pci_func_s { - struct pci_dev *pdev; - struct aq_nic_s *port[AQ_CFG_PCI_FUNC_PORTS]; - void __iomem *mmio; - void *aq_vec[AQ_CFG_PCI_FUNC_MSIX_IRQS]; - resource_size_t mmio_pa; - unsigned int msix_entry_mask; - unsigned int ports; - bool is_pci_enabled; - bool is_regions; - bool is_pci_using_dac; - struct aq_hw_caps_s aq_hw_caps; -}; - static const struct pci_device_id aq_pci_tbl[] = { { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_0001), }, { PCI_VDEVICE(AQUANTIA, AQ_DEVICE_ID_D100), }, @@ -118,156 +105,39 @@ static int aq_pci_probe_get_hw_by_id(struct pci_dev *pdev, return 0; } -struct aq_pci_func_s *aq_pci_func_alloc(const struct aq_hw_ops *aq_hw_ops, - const struct aq_hw_caps_s *aq_hw_caps, - struct pci_dev *pdev) -{ - struct aq_pci_func_s *self = NULL; - int err = 0; - unsigned int port = 0U; - - if (!aq_hw_ops) { - err = -EFAULT; - goto err_exit; - } - self = kzalloc(sizeof(*self), GFP_KERNEL); - if (!self) { - err = -ENOMEM; - goto err_exit; - } - - pci_set_drvdata(pdev, self); - self->pdev = pdev; - self->aq_hw_caps = *aq_hw_caps; - - self->ports = self->aq_hw_caps.ports; - - for (port = 0; port < self->ports; ++port) { - struct aq_nic_s *aq_nic = aq_nic_alloc_cold(pdev, self, - port, aq_hw_ops, - aq_hw_caps); - - if (!aq_nic) { - err = -ENOMEM; - goto err_exit; - } - self->port[port] = aq_nic; - } - -err_exit: - if (err < 0) { - if (self) - aq_pci_func_free(self); - self = NULL; - } - - (void)err; - return self; -} - -int aq_pci_func_init(struct aq_pci_func_s *self) +int aq_pci_func_init(struct pci_dev *pdev) { int err = 0; - unsigned int bar = 0U; - unsigned int port = 0U; - unsigned int numvecs = 0U; - - err = pci_enable_device(self->pdev); - if (err < 0) - goto err_exit; - self->is_pci_enabled = true; - - err = pci_set_dma_mask(self->pdev, DMA_BIT_MASK(64)); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64)); if (!err) { - err = pci_set_consistent_dma_mask(self->pdev, DMA_BIT_MASK(64)); - self->is_pci_using_dac = 1; + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); + } if (err) { - err = pci_set_dma_mask(self->pdev, DMA_BIT_MASK(32)); + err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (!err) - err = pci_set_consistent_dma_mask(self->pdev, + err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - self->is_pci_using_dac = 0; } if (err != 0) { err = -ENOSR; goto err_exit; } - err = pci_request_regions(self->pdev, AQ_CFG_DRV_NAME "_mmio"); + err = pci_request_regions(pdev, AQ_CFG_DRV_NAME "_mmio"); if (err < 0) goto err_exit; - self->is_regions = true; + pci_set_master(pdev); - pci_set_master(self->pdev); - - for (bar = 0; bar < 4; ++bar) { - if (IORESOURCE_MEM & pci_resource_flags(self->pdev, bar)) { - resource_size_t reg_sz; - - self->mmio_pa = pci_resource_start(self->pdev, bar); - if (self->mmio_pa == 0U) { - err = -EIO; - goto err_exit; - } - - reg_sz = pci_resource_len(self->pdev, bar); - if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) { - err = -EIO; - goto err_exit; - } - - self->mmio = ioremap_nocache(self->mmio_pa, reg_sz); - if (!self->mmio) { - err = -EIO; - goto err_exit; - } - break; - } - } - - numvecs = min((u8)AQ_CFG_VECS_DEF, self->aq_hw_caps.msix_irqs); - numvecs = min(numvecs, num_online_cpus()); - - /* enable interrupts */ -#if !AQ_CFG_FORCE_LEGACY_INT - err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs, PCI_IRQ_MSIX); - - if (err < 0) { - err = pci_alloc_irq_vectors(self->pdev, 1, 1, - PCI_IRQ_MSI | PCI_IRQ_LEGACY); - if (err < 0) - goto err_exit; - } -#endif /* AQ_CFG_FORCE_LEGACY_INT */ - - /* net device init */ - for (port = 0; port < self->ports; ++port) { - if (!self->port[port]) - continue; - - err = aq_nic_cfg_start(self->port[port]); - if (err < 0) - goto err_exit; - - err = aq_nic_ndev_init(self->port[port]); - if (err < 0) - goto err_exit; - - err = aq_nic_ndev_register(self->port[port]); - if (err < 0) - goto err_exit; - } + return 0; err_exit: - if (err < 0) - aq_pci_func_deinit(self); return err; } -int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i, +int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i, char *name, void *aq_vec, cpumask_t *affinity_mask) { struct pci_dev *pdev = self->pdev; @@ -288,11 +158,10 @@ int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i, irq_set_affinity_hint(pci_irq_vector(pdev, i), affinity_mask); } - return err; } -void aq_pci_func_free_irqs(struct aq_pci_func_s *self) +void aq_pci_func_free_irqs(struct aq_nic_s *self) { struct pci_dev *pdev = self->pdev; unsigned int i = 0U; @@ -308,12 +177,7 @@ void aq_pci_func_free_irqs(struct aq_pci_func_s *self) } } -void __iomem *aq_pci_func_get_mmio(struct aq_pci_func_s *self) -{ - return self->mmio; -} - -unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s *self) +unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self) { if (self->pdev->msix_enabled) return AQ_HW_IRQ_MSIX; @@ -322,118 +186,148 @@ unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s *self) return AQ_HW_IRQ_LEGACY; } -void aq_pci_func_deinit(struct aq_pci_func_s *self) +static void aq_pci_free_irq_vectors(struct aq_nic_s *self) { - if (!self) - goto err_exit; - - aq_pci_func_free_irqs(self); pci_free_irq_vectors(self->pdev); +} - if (self->is_regions) - pci_release_regions(self->pdev); +static int aq_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *pci_id) +{ + struct aq_nic_s *self = NULL; + int err = 0; + struct net_device *ndev; + resource_size_t mmio_pa; + u32 bar; + u32 numvecs; - if (self->is_pci_enabled) - pci_disable_device(self->pdev); + err = pci_enable_device(pdev); + if (err) + return err; -err_exit:; -} + err = aq_pci_func_init(pdev); + if (err) + goto err_pci_func; -void aq_pci_func_free(struct aq_pci_func_s *self) -{ - unsigned int port = 0U; + ndev = aq_ndev_alloc(); + if (!ndev) + goto err_ndev; - if (!self) - goto err_exit; + self = netdev_priv(ndev); + self->pdev = pdev; + SET_NETDEV_DEV(ndev, &pdev->dev); + pci_set_drvdata(pdev, self); - for (port = 0; port < self->ports; ++port) { - if (!self->port[port]) - continue; + err = aq_pci_probe_get_hw_by_id(pdev, &self->aq_hw_ops, + &aq_nic_get_cfg(self)->aq_hw_caps); + if (err) + goto err_ioremap; - aq_nic_ndev_free(self->port[port]); - } + self->aq_hw = kzalloc(sizeof(*self->aq_hw), GFP_KERNEL); + self->aq_hw->aq_nic_cfg = aq_nic_get_cfg(self); - if (self->mmio) - iounmap(self->mmio); + for (bar = 0; bar < 4; ++bar) { + if (IORESOURCE_MEM & pci_resource_flags(pdev, bar)) { + resource_size_t reg_sz; - kfree(self); + mmio_pa = pci_resource_start(pdev, bar); + if (mmio_pa == 0U) { + err = -EIO; + goto err_ioremap; + } -err_exit:; -} + reg_sz = pci_resource_len(pdev, bar); + if ((reg_sz <= 24 /*ATL_REGS_SIZE*/)) { + err = -EIO; + goto err_ioremap; + } -int aq_pci_func_change_pm_state(struct aq_pci_func_s *self, - pm_message_t *pm_msg) -{ - int err = 0; - unsigned int port = 0U; + self->aq_hw->mmio = ioremap_nocache(mmio_pa, reg_sz); + if (!self->aq_hw->mmio) { + err = -EIO; + goto err_ioremap; + } + break; + } + } - if (!self) { - err = -EFAULT; - goto err_exit; + if (bar == 4) { + err = -EIO; + goto err_ioremap; } - for (port = 0; port < self->ports; ++port) { - if (!self->port[port]) - continue; - (void)aq_nic_change_pm_state(self->port[port], pm_msg); + numvecs = min((u8)AQ_CFG_VECS_DEF, + aq_nic_get_cfg(self)->aq_hw_caps->msix_irqs); + numvecs = min(numvecs, num_online_cpus()); + /*enable interrupts */ +#if !AQ_CFG_FORCE_LEGACY_INT + err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs, + PCI_IRQ_MSIX); + + if (err < 0) { + err = pci_alloc_irq_vectors(self->pdev, 1, 1, + PCI_IRQ_MSI | PCI_IRQ_LEGACY); + if (err < 0) + goto err_hwinit; } +#endif -err_exit: - return err; -} + /* net device init */ + aq_nic_cfg_start(self); -static int aq_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *pci_id) -{ - const struct aq_hw_ops *aq_hw_ops = NULL; - const struct aq_hw_caps_s *aq_hw_caps = NULL; - struct aq_pci_func_s *aq_pci_func = NULL; - int err = 0; + aq_nic_ndev_init(self); - err = pci_enable_device(pdev); - if (err < 0) - goto err_exit; - err = aq_pci_probe_get_hw_by_id(pdev, &aq_hw_ops, &aq_hw_caps); - if (err < 0) - goto err_exit; - aq_pci_func = aq_pci_func_alloc(aq_hw_ops, aq_hw_caps, pdev); - if (!aq_pci_func) { - err = -ENOMEM; - goto err_exit; - } - err = aq_pci_func_init(aq_pci_func); + err = aq_nic_ndev_register(self); if (err < 0) - goto err_exit; + goto err_register; -err_exit: - if (err < 0) { - if (aq_pci_func) - aq_pci_func_free(aq_pci_func); - } + return 0; + +err_register: + aq_nic_free_vectors(self); + aq_pci_free_irq_vectors(self); +err_hwinit: + iounmap(self->aq_hw->mmio); +err_ioremap: + free_netdev(ndev); +err_pci_func: + pci_release_regions(pdev); +err_ndev: + pci_disable_device(pdev); return err; } static void aq_pci_remove(struct pci_dev *pdev) { - struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev); + struct aq_nic_s *self = pci_get_drvdata(pdev); + + if (self->ndev) { + if (self->ndev->reg_state == NETREG_REGISTERED) + unregister_netdev(self->ndev); + aq_nic_free_vectors(self); + aq_pci_free_irq_vectors(self); + iounmap(self->aq_hw->mmio); + kfree(self->aq_hw); + pci_release_regions(pdev); + free_netdev(self->ndev); + } - aq_pci_func_deinit(aq_pci_func); - aq_pci_func_free(aq_pci_func); + pci_disable_device(pdev); } static int aq_pci_suspend(struct pci_dev *pdev, pm_message_t pm_msg) { - struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev); + struct aq_nic_s *self = pci_get_drvdata(pdev); - return aq_pci_func_change_pm_state(aq_pci_func, &pm_msg); + return aq_nic_change_pm_state(self, &pm_msg); } static int aq_pci_resume(struct pci_dev *pdev) { - struct aq_pci_func_s *aq_pci_func = pci_get_drvdata(pdev); + struct aq_nic_s *self = pci_get_drvdata(pdev); pm_message_t pm_msg = PMSG_RESTORE; - return aq_pci_func_change_pm_state(aq_pci_func, &pm_msg); + return aq_nic_change_pm_state(self, &pm_msg); } static struct pci_driver aq_pci_ops = { diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h index 701c99611c284..aeee67bf69fab 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.h @@ -22,17 +22,11 @@ struct aq_board_revision_s { const struct aq_hw_caps_s *caps; }; -int aq_pci_func_init(struct aq_pci_func_s *self); -int aq_pci_func_alloc_irq(struct aq_pci_func_s *self, unsigned int i, +int aq_pci_func_init(struct pci_dev *pdev); +int aq_pci_func_alloc_irq(struct aq_nic_s *self, unsigned int i, char *name, void *aq_vec, cpumask_t *affinity_mask); -void aq_pci_func_free_irqs(struct aq_pci_func_s *self); -int aq_pci_func_start(struct aq_pci_func_s *self); -void __iomem *aq_pci_func_get_mmio(struct aq_pci_func_s *self); -unsigned int aq_pci_func_get_irq_type(struct aq_pci_func_s *self); -void aq_pci_func_deinit(struct aq_pci_func_s *self); -void aq_pci_func_free(struct aq_pci_func_s *self); -int aq_pci_func_change_pm_state(struct aq_pci_func_s *self, - pm_message_t *pm_msg); +void aq_pci_func_free_irqs(struct aq_nic_s *self); +unsigned int aq_pci_func_get_irq_type(struct aq_nic_s *self); #endif /* AQ_PCI_FUNC_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 9c7e9161b4db9..f4418c7da9dc5 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -369,8 +369,6 @@ int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, u32 l = 0U; u32 mac_addr[2]; - self->mmio = aq_pci_func_get_mmio(self->aq_pci_func); - hw_atl_utils_hw_chip_features_init(self, &self->chip_features); From ef24175d9fd2457e20c4122a1904a4b1ccfb661a Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:22 +0300 Subject: [PATCH 05/11] net: aquantia: Remove create/destroy from hw ops These ops are not related to HW and are now implemented in pci module. Thus, remove these ops pointers and implementation. Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/aq_hw.h | 5 ---- .../aquantia/atlantic/hw_atl/hw_atl_a0.c | 25 ------------------- .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 24 ------------------ 3 files changed, 54 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 8219157e2d7c5..5566486358cc7 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -101,7 +101,6 @@ struct aq_stats_s { struct aq_hw_s { atomic_t flags; struct aq_nic_cfg_s *aq_nic_cfg; - struct aq_pci_func_s *aq_pci_func; void __iomem *mmio; unsigned int not_ff_addr; struct aq_hw_link_status_s aq_link_status; @@ -126,10 +125,6 @@ struct aq_nic_cfg_s; struct sk_buff; struct aq_hw_ops { - struct aq_hw_s *(*create)(struct aq_pci_func_s *aq_pci_func, - unsigned int port); - - void (*destroy)(struct aq_hw_s *self); int (*hw_ring_tx_xmit)(struct aq_hw_s *self, struct aq_ring_s *aq_ring, unsigned int frags); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 491a901b6d226..9c9fb1e8b4530 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -79,29 +79,6 @@ const struct aq_hw_caps_s hw_atl_a0_caps_aqc109 = { HW_ATL_A0_RATE_100M, }; - -static struct aq_hw_s *hw_atl_a0_create(struct aq_pci_func_s *aq_pci_func, - unsigned int port) -{ - struct aq_hw_s *self = NULL; - - self = kzalloc(sizeof(*self), GFP_KERNEL); - if (!self) - goto err_exit; - - self->aq_pci_func = aq_pci_func; - - self->not_ff_addr = 0x10U; - -err_exit: - return self; -} - -static void hw_atl_a0_destroy(struct aq_hw_s *self) -{ - kfree(self); -} - static int hw_atl_a0_hw_reset(struct aq_hw_s *self) { int err = 0; @@ -906,8 +883,6 @@ static int hw_atl_a0_hw_set_speed(struct aq_hw_s *self, u32 speed) } const struct aq_hw_ops hw_atl_ops_a0 = { - .create = hw_atl_a0_create, - .destroy = hw_atl_a0_destroy, .hw_get_mac_permanent = hw_atl_utils_get_mac_permanent, .hw_set_mac_address = hw_atl_a0_hw_mac_addr_set, .hw_get_link_status = hw_atl_utils_mpi_get_link_status, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 87e7d0f04ee8a..00edad1085f88 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -82,28 +82,6 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = { HW_ATL_B0_RATE_100M, }; -static struct aq_hw_s *hw_atl_b0_create(struct aq_pci_func_s *aq_pci_func, - unsigned int port) -{ - struct aq_hw_s *self = NULL; - - self = kzalloc(sizeof(*self), GFP_KERNEL); - if (!self) - goto err_exit; - - self->aq_pci_func = aq_pci_func; - - self->not_ff_addr = 0x10U; - -err_exit: - return self; -} - -static void hw_atl_b0_destroy(struct aq_hw_s *self) -{ - kfree(self); -} - static int hw_atl_b0_hw_reset(struct aq_hw_s *self) { int err = 0; @@ -981,8 +959,6 @@ static int hw_atl_b0_hw_set_speed(struct aq_hw_s *self, u32 speed) } const struct aq_hw_ops hw_atl_ops_b0 = { - .create = hw_atl_b0_create, - .destroy = hw_atl_b0_destroy, .hw_get_mac_permanent = hw_atl_utils_get_mac_permanent, .hw_set_mac_address = hw_atl_b0_hw_mac_addr_set, .hw_get_link_status = hw_atl_utils_mpi_get_link_status, From 76c19c6cfa8f7e4f8c7d5407f77237b80095e5d9 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:23 +0300 Subject: [PATCH 06/11] net: aquantia: Change confusing no_ff_addr to more meaningful name The address to check if HW is not dead/hang could be stored in capabilities, since it is a constant. Change its name to better reflect the idea. Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/aq_hw.h | 2 +- drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c | 5 ++++- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c | 3 ++- drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c | 3 ++- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 5566486358cc7..a8bf387910791 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -31,6 +31,7 @@ struct aq_hw_caps_s { u32 vecs; u32 mtu; u32 mac_regs_count; + u32 hw_alive_check_addr; u8 msix_irqs; u8 tcs; u8 rxd_alignment; @@ -102,7 +103,6 @@ struct aq_hw_s { atomic_t flags; struct aq_nic_cfg_s *aq_nic_cfg; void __iomem *mmio; - unsigned int not_ff_addr; struct aq_hw_link_status_s aq_link_status; struct hw_aq_atl_utils_mbox mbox; struct hw_atl_stats_s last_stats; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c index 27e250d61da7f..d526c4f19d343 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.c @@ -13,6 +13,7 @@ #include "aq_hw_utils.h" #include "aq_hw.h" +#include "aq_nic.h" void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, u32 shift, u32 val) @@ -39,7 +40,9 @@ u32 aq_hw_read_reg(struct aq_hw_s *hw, u32 reg) { u32 value = readl(hw->mmio + reg); - if ((~0U) == value && (~0U) == readl(hw->mmio + hw->not_ff_addr)) + if ((~0U) == value && + (~0U) == readl(hw->mmio + + hw->aq_nic_cfg->aq_hw_caps->hw_alive_check_addr)) aq_utils_obj_set(&hw->flags, AQ_HW_FLAG_ERR_UNPLUG); return value; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 9c9fb1e8b4530..52f2eb543ee40 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -41,7 +41,8 @@ .hw_priv_flags = IFF_UNICAST_FLT, \ .flow_control = true, \ .mtu = HW_ATL_A0_MTU_JUMBO, \ - .mac_regs_count = 88 + .mac_regs_count = 88, \ + .hw_alive_check_addr = 0x10U const struct aq_hw_caps_s hw_atl_a0_caps_aqc100 = { DEFAULT_A0_BOARD_BASIC_CAPABILITIES, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 00edad1085f88..f601230166eea 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -43,7 +43,8 @@ .hw_priv_flags = IFF_UNICAST_FLT, \ .flow_control = true, \ .mtu = HW_ATL_B0_MTU_JUMBO, \ - .mac_regs_count = 88 + .mac_regs_count = 88, \ + .hw_alive_check_addr = 0x10U const struct aq_hw_caps_s hw_atl_b0_caps_aqc100 = { DEFAULT_B0_BOARD_BASIC_CAPABILITIES, From 0c58c35f02c2e99bb10137b32e8ec96dcbdcc705 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:24 +0300 Subject: [PATCH 07/11] net: aquantia: Introduce firmware ops callbacks New AQC cards will have an updated firmware with new binary interface. This patch extracts firmware specific operations into a separate table and prepares for the introduction of new fw 2.x and 3.x Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/aq_hw.h | 27 ++++--- .../ethernet/aquantia/atlantic/aq_hw_utils.h | 3 + .../net/ethernet/aquantia/atlantic/aq_nic.c | 14 ++-- .../net/ethernet/aquantia/atlantic/aq_nic.h | 1 + .../aquantia/atlantic/hw_atl/hw_atl_a0.c | 23 +----- .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 23 +----- .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 81 +++++++++++++------ .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 10 ++- 8 files changed, 101 insertions(+), 81 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index a8bf387910791..33a7c14c3bc6a 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -102,6 +102,7 @@ struct aq_stats_s { struct aq_hw_s { atomic_t flags; struct aq_nic_cfg_s *aq_nic_cfg; + const struct aq_fw_ops *aq_fw_ops; void __iomem *mmio; struct aq_hw_link_status_s aq_link_status; struct hw_aq_atl_utils_mbox mbox; @@ -121,7 +122,6 @@ struct aq_hw_s { struct aq_ring_s; struct aq_ring_param_s; -struct aq_nic_cfg_s; struct sk_buff; struct aq_hw_ops { @@ -138,15 +138,8 @@ struct aq_hw_ops { int (*hw_ring_tx_head_update)(struct aq_hw_s *self, struct aq_ring_s *aq_ring); - int (*hw_get_mac_permanent)(struct aq_hw_s *self, - u8 *mac); - int (*hw_set_mac_address)(struct aq_hw_s *self, u8 *mac_addr); - int (*hw_get_link_status)(struct aq_hw_s *self); - - int (*hw_set_link_speed)(struct aq_hw_s *self, u32 speed); - int (*hw_reset)(struct aq_hw_s *self); int (*hw_init)(struct aq_hw_s *self, u8 *mac_addr); @@ -200,8 +193,6 @@ struct aq_hw_ops { const struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff); - int (*hw_update_stats)(struct aq_hw_s *self); - struct aq_stats_s *(*hw_get_hw_stats)(struct aq_hw_s *self); int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version); @@ -211,4 +202,20 @@ struct aq_hw_ops { int (*hw_set_power)(struct aq_hw_s *self, unsigned int power_state); }; +struct aq_fw_ops { + int (*init)(struct aq_hw_s *self); + + int (*reset)(struct aq_hw_s *self); + + int (*get_mac_permanent)(struct aq_hw_s *self, u8 *mac); + + int (*set_link_speed)(struct aq_hw_s *self, u32 speed); + + int (*set_state)(struct aq_hw_s *self, enum hal_atl_utils_fw_state_e state); + + int (*update_link_status)(struct aq_hw_s *self); + + int (*update_stats)(struct aq_hw_s *self); +}; + #endif /* AQ_HW_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h index 03b72ddbffb98..dc88a1221f1de 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h @@ -35,6 +35,9 @@ do { \ } \ } while (0) +#define aq_pr_err(...) pr_err(AQ_CFG_DRV_NAME ": " __VA_ARGS__) +#define aq_pr_trace(...) pr_info(AQ_CFG_DRV_NAME ": " __VA_ARGS__) + struct aq_hw_s; void aq_hw_write_reg_bit(struct aq_hw_s *aq_hw, u32 addr, u32 msk, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index c5450b9887ace..3087a3044bb31 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -122,7 +122,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self) static int aq_nic_update_link_status(struct aq_nic_s *self) { - int err = self->aq_hw_ops->hw_get_link_status(self->aq_hw); + int err = self->aq_fw_ops->update_link_status(self->aq_hw); if (err) return err; @@ -164,8 +164,8 @@ static void aq_nic_service_timer_cb(struct timer_list *t) if (err) goto err_exit; - if (self->aq_hw_ops->hw_update_stats) - self->aq_hw_ops->hw_update_stats(self->aq_hw); + if (self->aq_fw_ops->update_stats) + self->aq_fw_ops->update_stats(self->aq_hw); aq_nic_update_ndev_stats(self); @@ -200,7 +200,11 @@ int aq_nic_ndev_register(struct aq_nic_s *self) goto err_exit; } - err = self->aq_hw_ops->hw_get_mac_permanent(self->aq_hw, + err = hw_atl_utils_initfw(self->aq_hw, &self->aq_fw_ops); + if (err) + goto err_exit; + + err = self->aq_fw_ops->get_mac_permanent(self->aq_hw, self->ndev->dev_addr); if (err) goto err_exit; @@ -799,7 +803,7 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, self->aq_nic_cfg.is_autoneg = false; } - err = self->aq_hw_ops->hw_set_link_speed(self->aq_hw, rate); + err = self->aq_fw_ops->set_link_speed(self->aq_hw, rate); if (err < 0) goto err_exit; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index a85b08a34ed41..d16b0f1a95aa4 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -68,6 +68,7 @@ struct aq_nic_s { unsigned int power_state; u8 port; const struct aq_hw_ops *aq_hw_ops; + const struct aq_fw_ops *aq_fw_ops; struct aq_nic_cfg_s aq_nic_cfg; struct timer_list service_timer; struct timer_list polling_timer; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index 52f2eb543ee40..67e2f9fb9402f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -105,7 +105,7 @@ static int hw_atl_a0_hw_reset(struct aq_hw_s *self) if (err < 0) goto err_exit; - hw_atl_utils_mpi_set(self, MPI_RESET, 0x0U); + self->aq_fw_ops->set_state(self, MPI_RESET); err = aq_hw_err_from_flags(self); @@ -354,7 +354,8 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr) hw_atl_a0_hw_mac_addr_set(self, mac_addr); - hw_atl_utils_mpi_set(self, MPI_INIT, aq_nic_cfg->link_speed_msk); + self->aq_fw_ops->set_link_speed(self, aq_nic_cfg->link_speed_msk); + self->aq_fw_ops->set_state(self, MPI_INIT); hw_atl_reg_tx_dma_debug_ctl_set(self, 0x800000b8U); hw_atl_reg_tx_dma_debug_ctl_set(self, 0x000000b8U); @@ -365,7 +366,7 @@ static int hw_atl_a0_hw_init(struct aq_hw_s *self, u8 *mac_addr) /* Reset link status and read out initial hardware counters */ self->aq_link_status.mbps = 0; - hw_atl_utils_update_stats(self); + self->aq_fw_ops->update_stats(self); err = aq_hw_err_from_flags(self); if (err < 0) @@ -871,23 +872,8 @@ static int hw_atl_a0_hw_ring_rx_stop(struct aq_hw_s *self, return aq_hw_err_from_flags(self); } -static int hw_atl_a0_hw_set_speed(struct aq_hw_s *self, u32 speed) -{ - int err = 0; - - err = hw_atl_utils_mpi_set_speed(self, speed, MPI_INIT); - if (err < 0) - goto err_exit; - -err_exit: - return err; -} - const struct aq_hw_ops hw_atl_ops_a0 = { - .hw_get_mac_permanent = hw_atl_utils_get_mac_permanent, .hw_set_mac_address = hw_atl_a0_hw_mac_addr_set, - .hw_get_link_status = hw_atl_utils_mpi_get_link_status, - .hw_set_link_speed = hw_atl_a0_hw_set_speed, .hw_init = hw_atl_a0_hw_init, .hw_deinit = hw_atl_utils_hw_deinit, .hw_set_power = hw_atl_utils_hw_set_power, @@ -917,7 +903,6 @@ const struct aq_hw_ops hw_atl_ops_a0 = { .hw_rss_set = hw_atl_a0_hw_rss_set, .hw_rss_hash_set = hw_atl_a0_hw_rss_hash_set, .hw_get_regs = hw_atl_utils_hw_get_regs, - .hw_update_stats = hw_atl_utils_update_stats, .hw_get_hw_stats = hw_atl_utils_get_hw_stats, .hw_get_fw_version = hw_atl_utils_get_fw_version, }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index f601230166eea..29abbc2588c6d 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -108,7 +108,7 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self) if (err < 0) goto err_exit; - hw_atl_utils_mpi_set(self, MPI_RESET, 0x0U); + self->aq_fw_ops->set_state(self, MPI_RESET); err = aq_hw_err_from_flags(self); @@ -403,7 +403,8 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) hw_atl_b0_hw_mac_addr_set(self, mac_addr); - hw_atl_utils_mpi_set(self, MPI_INIT, aq_nic_cfg->link_speed_msk); + self->aq_fw_ops->set_link_speed(self, aq_nic_cfg->link_speed_msk); + self->aq_fw_ops->set_state(self, MPI_INIT); hw_atl_b0_hw_qos_set(self); hw_atl_b0_hw_rss_set(self, &aq_nic_cfg->aq_rss); @@ -422,7 +423,7 @@ static int hw_atl_b0_hw_init(struct aq_hw_s *self, u8 *mac_addr) /* Reset link status and read out initial hardware counters */ self->aq_link_status.mbps = 0; - hw_atl_utils_update_stats(self); + self->aq_fw_ops->update_stats(self); err = aq_hw_err_from_flags(self); if (err < 0) @@ -947,23 +948,8 @@ static int hw_atl_b0_hw_ring_rx_stop(struct aq_hw_s *self, return aq_hw_err_from_flags(self); } -static int hw_atl_b0_hw_set_speed(struct aq_hw_s *self, u32 speed) -{ - int err = 0; - - err = hw_atl_utils_mpi_set_speed(self, speed, MPI_INIT); - if (err < 0) - goto err_exit; - -err_exit: - return err; -} - const struct aq_hw_ops hw_atl_ops_b0 = { - .hw_get_mac_permanent = hw_atl_utils_get_mac_permanent, .hw_set_mac_address = hw_atl_b0_hw_mac_addr_set, - .hw_get_link_status = hw_atl_utils_mpi_get_link_status, - .hw_set_link_speed = hw_atl_b0_hw_set_speed, .hw_init = hw_atl_b0_hw_init, .hw_deinit = hw_atl_utils_hw_deinit, .hw_set_power = hw_atl_utils_hw_set_power, @@ -993,7 +979,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = { .hw_rss_set = hw_atl_b0_hw_rss_set, .hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set, .hw_get_regs = hw_atl_utils_hw_get_regs, - .hw_update_stats = hw_atl_utils_update_stats, .hw_get_hw_stats = hw_atl_utils_get_hw_stats, .hw_get_fw_version = hw_atl_utils_get_fw_version, }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index f4418c7da9dc5..616475ea5b2f3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -13,23 +13,49 @@ #include "../aq_nic.h" #include "../aq_hw_utils.h" -#include "../aq_pci_func.h" #include "hw_atl_utils.h" #include "hw_atl_llh.h" +#include "hw_atl_llh_internal.h" #include #define HW_ATL_UCP_0X370_REG 0x0370U #define HW_ATL_FW_SM_RAM 0x2U +#define HW_ATL_MPI_FW_VERSION 0x18 #define HW_ATL_MPI_CONTROL_ADR 0x0368U #define HW_ATL_MPI_STATE_ADR 0x036CU #define HW_ATL_MPI_STATE_MSK 0x00FFU #define HW_ATL_MPI_STATE_SHIFT 0U -#define HW_ATL_MPI_SPEED_MSK 0xFFFFU +#define HW_ATL_MPI_SPEED_MSK 0xFFFF0000U #define HW_ATL_MPI_SPEED_SHIFT 16U +#define HW_ATL_FW_VER_1X 0x01050006U + +static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); + +int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) +{ + int err = 0; + + hw_atl_utils_hw_chip_features_init(self, + &self->chip_features); + + hw_atl_utils_get_fw_version(self, &self->fw_ver_actual); + + if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, self->fw_ver_actual) == 0) + *fw_ops = &aq_fw_1x_ops; + else { + aq_pr_err("Bad FW version detected: %x\n", + self->fw_ver_actual); + return -EOPNOTSUPP; + } + self->aq_fw_ops = *fw_ops; + err = self->aq_fw_ops->init(self); + return err; +} + static int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) { @@ -137,14 +163,6 @@ static int hw_atl_utils_init_ucp(struct aq_hw_s *self, AQ_HW_WAIT_FOR(0U != (self->mbox_addr = aq_hw_read_reg(self, 0x360U)), 1000U, 10U); - err = hw_atl_utils_ver_match(aq_hw_caps->fw_ver_expected, - aq_hw_read_reg(self, 0x18U)); - - if (err < 0) - pr_err("%s: Bad FW version detected: expected=%x, actual=%x\n", - AQ_CFG_DRV_NAME, - aq_hw_caps->fw_ver_expected, - aq_hw_read_reg(self, 0x18U)); return err; } @@ -286,19 +304,19 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self, err_exit:; } -int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed, - enum hal_atl_utils_fw_state_e state) +int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed) { - u32 ucp_0x368 = 0; + u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR); - ucp_0x368 = (speed << HW_ATL_MPI_SPEED_SHIFT) | state; - aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, ucp_0x368); + val = (val & HW_ATL_MPI_STATE_MSK) | (speed << HW_ATL_MPI_SPEED_SHIFT); + aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val); return 0; } void hw_atl_utils_mpi_set(struct aq_hw_s *self, - enum hal_atl_utils_fw_state_e state, u32 speed) + enum hal_atl_utils_fw_state_e state, + u32 speed) { int err = 0; u32 transaction_id = 0; @@ -317,11 +335,22 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self, goto err_exit; } - err = hw_atl_utils_mpi_set_speed(self, speed, state); + aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, + (speed << HW_ATL_MPI_SPEED_SHIFT) | state); err_exit:; } +static int hw_atl_utils_mpi_set_state(struct aq_hw_s *self, + enum hal_atl_utils_fw_state_e state) +{ + u32 val = aq_hw_read_reg(self, HW_ATL_MPI_CONTROL_ADR); + + val = state | (val & HW_ATL_MPI_SPEED_MSK); + aq_hw_write_reg(self, HW_ATL_MPI_CONTROL_ADR, val); + return 0; +} + int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) { u32 cp0x036C = aq_hw_read_reg(self, HW_ATL_MPI_STATE_ADR); @@ -369,13 +398,6 @@ int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, u32 l = 0U; u32 mac_addr[2]; - hw_atl_utils_hw_chip_features_init(self, - &self->chip_features); - - err = hw_atl_utils_mpi_create(self); - if (err < 0) - goto err_exit; - if (!aq_hw_read_reg(self, HW_ATL_UCP_0X370_REG)) { unsigned int rnd = 0; unsigned int ucp_0x370 = 0; @@ -421,7 +443,6 @@ int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, mac[0] = (u8)(0xFFU & h); } -err_exit: return err; } @@ -578,3 +599,13 @@ int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version) *fw_version = aq_hw_read_reg(self, 0x18U); return 0; } + +const struct aq_fw_ops aq_fw_1x_ops = { + .init = hw_atl_utils_mpi_create, + .reset = NULL, + .get_mac_permanent = hw_atl_utils_get_mac_permanent, + .set_link_speed = hw_atl_utils_mpi_set_speed, + .set_state = hw_atl_utils_mpi_set_state, + .update_link_status = hw_atl_utils_mpi_get_link_status, + .update_stats = hw_atl_utils_update_stats, +}; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h index 40e2319c65d57..d6d05e5eb9397 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h @@ -181,9 +181,14 @@ enum hal_atl_utils_fw_state_e { #define HAL_ATLANTIC_RATE_INVALID BIT(6) struct aq_hw_s; +struct aq_fw_ops; struct aq_hw_caps_s; struct aq_hw_link_status_s; +int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops); + +int hw_atl_utils_soft_reset(struct aq_hw_s *self); + void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p); int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self, @@ -196,9 +201,6 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self, enum hal_atl_utils_fw_state_e state, u32 speed); -int hw_atl_utils_mpi_set_speed(struct aq_hw_s *self, u32 speed, - enum hal_atl_utils_fw_state_e state); - int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self); int hw_atl_utils_get_mac_permanent(struct aq_hw_s *self, @@ -221,4 +223,6 @@ int hw_atl_utils_update_stats(struct aq_hw_s *self); struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self); +extern const struct aq_fw_ops aq_fw_1x_ops; + #endif /* HW_ATL_UTILS_H */ From a57d3929b838204efd026e0f6d5eaed5bb65cce7 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:25 +0300 Subject: [PATCH 08/11] net: aquantia: Introduce support for new firmware on AQC cards This defines fw2x operations table and corresponding methods. Some of the functions are being shared with 1.x firmware Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/Makefile | 1 + .../net/ethernet/aquantia/atlantic/aq_hw.h | 1 - .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 12 +- .../aquantia/atlantic/hw_atl/hw_atl_utils.h | 63 +++++- .../atlantic/hw_atl/hw_atl_utils_fw2x.c | 184 ++++++++++++++++++ 5 files changed, 257 insertions(+), 4 deletions(-) create mode 100644 drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c diff --git a/drivers/net/ethernet/aquantia/atlantic/Makefile b/drivers/net/ethernet/aquantia/atlantic/Makefile index e4ae696920eff..686f6d8c9e796 100644 --- a/drivers/net/ethernet/aquantia/atlantic/Makefile +++ b/drivers/net/ethernet/aquantia/atlantic/Makefile @@ -39,4 +39,5 @@ atlantic-objs := aq_main.o \ hw_atl/hw_atl_a0.o \ hw_atl/hw_atl_b0.o \ hw_atl/hw_atl_utils.o \ + hw_atl/hw_atl_utils_fw2x.o \ hw_atl/hw_atl_llh.o diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 33a7c14c3bc6a..51b55694a1f6b 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -42,7 +42,6 @@ struct aq_hw_caps_s { u8 rx_rings; bool flow_control; bool is_64_dma; - u32 fw_ver_expected; }; struct aq_hw_link_status_s { diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 616475ea5b2f3..56fb048c4ddc7 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -32,6 +32,8 @@ #define HW_ATL_MPI_SPEED_SHIFT 16U #define HW_ATL_FW_VER_1X 0x01050006U +#define HW_ATL_FW_VER_2X 0x02000000U +#define HW_ATL_FW_VER_3X 0x03000000U static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); @@ -46,6 +48,12 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, self->fw_ver_actual) == 0) *fw_ops = &aq_fw_1x_ops; + else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, + self->fw_ver_actual) == 0) + *fw_ops = &aq_fw_2x_ops; + else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, + self->fw_ver_actual) == 0) + *fw_ops = &aq_fw_2x_ops; else { aq_pr_err("Bad FW version detected: %x\n", self->fw_ver_actual); @@ -56,8 +64,8 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) return err; } -static int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, - u32 *p, u32 cnt) +int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, + u32 *p, u32 cnt) { int err = 0; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h index d6d05e5eb9397..2c690947910a3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h @@ -163,7 +163,7 @@ struct __packed hw_aq_atl_utils_mbox { #define HAL_ATLANTIC_UTILS_CHIP_REVISION_B0 0x02000000U #define IS_CHIP_FEATURE(_F_) (HAL_ATLANTIC_UTILS_CHIP_##_F_ & \ - self->chip_features) + self->chip_features) enum hal_atl_utils_fw_state_e { MPI_DEINIT = 0, @@ -180,6 +180,64 @@ enum hal_atl_utils_fw_state_e { #define HAL_ATLANTIC_RATE_100M BIT(5) #define HAL_ATLANTIC_RATE_INVALID BIT(6) +enum hw_atl_fw2x_rate { + FW2X_RATE_100M = 0x20, + FW2X_RATE_1G = 0x100, + FW2X_RATE_2G5 = 0x200, + FW2X_RATE_5G = 0x400, + FW2X_RATE_10G = 0x800, +}; + +enum hw_atl_fw2x_caps_lo { + CAPS_LO_10BASET_HD = 0x00, + CAPS_LO_10BASET_FD, + CAPS_LO_100BASETX_HD, + CAPS_LO_100BASET4_HD, + CAPS_LO_100BASET2_HD, + CAPS_LO_100BASETX_FD, + CAPS_LO_100BASET2_FD, + CAPS_LO_1000BASET_HD, + CAPS_LO_1000BASET_FD, + CAPS_LO_2P5GBASET_FD, + CAPS_LO_5GBASET_FD, + CAPS_LO_10GBASET_FD, +}; + +enum hw_atl_fw2x_caps_hi { + CAPS_HI_RESERVED1 = 0x00, + CAPS_HI_10BASET_EEE, + CAPS_HI_RESERVED2, + CAPS_HI_PAUSE, + CAPS_HI_ASYMMETRIC_PAUSE, + CAPS_HI_100BASETX_EEE, + CAPS_HI_RESERVED3, + CAPS_HI_RESERVED4, + CAPS_HI_1000BASET_FD_EEE, + CAPS_HI_2P5GBASET_FD_EEE, + CAPS_HI_5GBASET_FD_EEE, + CAPS_HI_10GBASET_FD_EEE, + CAPS_HI_RESERVED5, + CAPS_HI_RESERVED6, + CAPS_HI_RESERVED7, + CAPS_HI_RESERVED8, + CAPS_HI_RESERVED9, + CAPS_HI_CABLE_DIAG, + CAPS_HI_TEMPERATURE, + CAPS_HI_DOWNSHIFT, + CAPS_HI_PTP_AVB_EN, + CAPS_HI_MEDIA_DETECT, + CAPS_HI_LINK_DROP, + CAPS_HI_SLEEP_PROXY, + CAPS_HI_WOL, + CAPS_HI_MAC_STOP, + CAPS_HI_EXT_LOOPBACK, + CAPS_HI_INT_LOOPBACK, + CAPS_HI_EFUSE_AGENT, + CAPS_HI_WOL_TIMER, + CAPS_HI_STATISTICS, + CAPS_HI_TRANSACTION_ID, +}; + struct aq_hw_s; struct aq_fw_ops; struct aq_hw_caps_s; @@ -222,7 +280,10 @@ int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version); int hw_atl_utils_update_stats(struct aq_hw_s *self); struct aq_stats_s *hw_atl_utils_get_hw_stats(struct aq_hw_s *self); +int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, + u32 *p, u32 cnt); extern const struct aq_fw_ops aq_fw_1x_ops; +extern const struct aq_fw_ops aq_fw_2x_ops; #endif /* HW_ATL_UTILS_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c new file mode 100644 index 0000000000000..8cfce95c82fcf --- /dev/null +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -0,0 +1,184 @@ +/* + * aQuantia Corporation Network Driver + * Copyright (C) 2014-2017 aQuantia Corporation. All rights reserved + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +/* File hw_atl_utils_fw2x.c: Definition of firmware 2.x functions for + * Atlantic hardware abstraction layer. + */ + +#include "../aq_hw.h" +#include "../aq_hw_utils.h" +#include "../aq_pci_func.h" +#include "../aq_ring.h" +#include "../aq_vec.h" +#include "hw_atl_utils.h" +#include "hw_atl_llh.h" + +#define HW_ATL_FW2X_MPI_EFUSE_ADDR 0x364 +#define HW_ATL_FW2X_MPI_MBOX_ADDR 0x360 + +#define HW_ATL_FW2X_MPI_CONTROL_ADDR 0x368 +#define HW_ATL_FW2X_MPI_CONTROL2_ADDR 0x36C + +#define HW_ATL_FW2X_MPI_STATE_ADDR 0x370 +#define HW_ATL_FW2X_MPI_STATE2_ADDR 0x374 + +static int aq_fw2x_init(struct aq_hw_s *self) +{ + int err = 0; + + /* check 10 times by 1ms */ + AQ_HW_WAIT_FOR(0U != (self->mbox_addr = + aq_hw_read_reg(self, HW_ATL_FW2X_MPI_MBOX_ADDR)), + 1000U, 10U); + return err; +} + +static enum hw_atl_fw2x_rate link_speed_mask_2fw2x_ratemask(u32 speed) +{ + enum hw_atl_fw2x_rate rate = 0; + + if (speed & AQ_NIC_RATE_10G) + rate |= FW2X_RATE_10G; + + if (speed & AQ_NIC_RATE_5G) + rate |= FW2X_RATE_5G; + + if (speed & AQ_NIC_RATE_5GSR) + rate |= FW2X_RATE_5G; + + if (speed & AQ_NIC_RATE_2GS) + rate |= FW2X_RATE_2G5; + + if (speed & AQ_NIC_RATE_1G) + rate |= FW2X_RATE_1G; + + if (speed & AQ_NIC_RATE_100M) + rate |= FW2X_RATE_100M; + + return rate; +} + +static int aq_fw2x_set_link_speed(struct aq_hw_s *self, u32 speed) +{ + u32 val = link_speed_mask_2fw2x_ratemask(speed); + + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL_ADDR, val); + + return 0; +} + +static int aq_fw2x_set_state(struct aq_hw_s *self, + enum hal_atl_utils_fw_state_e state) +{ + /* No explicit state in 2x fw */ + return 0; +} + +static int aq_fw2x_update_link_status(struct aq_hw_s *self) +{ + u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE_ADDR); + u32 speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G | + FW2X_RATE_2G5 | FW2X_RATE_5G | FW2X_RATE_10G); + struct aq_hw_link_status_s *link_status = &self->aq_link_status; + + if (speed) { + if (speed & FW2X_RATE_10G) + link_status->mbps = 10000; + else if (speed & FW2X_RATE_5G) + link_status->mbps = 5000; + else if (speed & FW2X_RATE_2G5) + link_status->mbps = 2500; + else if (speed & FW2X_RATE_1G) + link_status->mbps = 1000; + else if (speed & FW2X_RATE_100M) + link_status->mbps = 100; + else + link_status->mbps = 10000; + } else { + link_status->mbps = 0; + } + + return 0; +} + +int aq_fw2x_get_mac_permanent(struct aq_hw_s *self, u8 *mac) +{ + int err = 0; + u32 h = 0U; + u32 l = 0U; + u32 mac_addr[2] = { 0 }; + u32 efuse_addr = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_EFUSE_ADDR); + + if (efuse_addr != 0) { + err = hw_atl_utils_fw_downld_dwords(self, + efuse_addr + (40U * 4U), + mac_addr, + ARRAY_SIZE(mac_addr)); + if (err) + return err; + mac_addr[0] = __swab32(mac_addr[0]); + mac_addr[1] = __swab32(mac_addr[1]); + } + + ether_addr_copy(mac, (u8 *)mac_addr); + + if ((mac[0] & 0x01U) || ((mac[0] | mac[1] | mac[2]) == 0x00U)) { + unsigned int rnd = 0; + + get_random_bytes(&rnd, sizeof(unsigned int)); + + l = 0xE3000000U + | (0xFFFFU & rnd) + | (0x00 << 16); + h = 0x8001300EU; + + mac[5] = (u8)(0xFFU & l); + l >>= 8; + mac[4] = (u8)(0xFFU & l); + l >>= 8; + mac[3] = (u8)(0xFFU & l); + l >>= 8; + mac[2] = (u8)(0xFFU & l); + mac[1] = (u8)(0xFFU & h); + h >>= 8; + mac[0] = (u8)(0xFFU & h); + } + return err; +} + +static int aq_fw2x_update_stats(struct aq_hw_s *self) +{ + int err = 0; + u32 mpi_opts = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR); + u32 orig_stats_val = mpi_opts & BIT(CAPS_HI_STATISTICS); + + /* Toggle statistics bit for FW to update */ + mpi_opts = mpi_opts ^ BIT(CAPS_HI_STATISTICS); + aq_hw_write_reg(self, HW_ATL_FW2X_MPI_CONTROL2_ADDR, mpi_opts); + + /* Wait FW to report back */ + AQ_HW_WAIT_FOR(orig_stats_val != + (aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR) & + BIT(CAPS_HI_STATISTICS)), + 1U, 10000U); + if (err) + return err; + + return hw_atl_utils_update_stats(self); +} + +const struct aq_fw_ops aq_fw_2x_ops = { + .init = aq_fw2x_init, + .reset = NULL, + .get_mac_permanent = aq_fw2x_get_mac_permanent, + .set_link_speed = aq_fw2x_set_link_speed, + .set_state = aq_fw2x_set_state, + .update_link_status = aq_fw2x_update_link_status, + .update_stats = aq_fw2x_update_stats, +}; From c8c82eb387abcfa9a362f3e75106a9d2c7d2b67f Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:26 +0300 Subject: [PATCH 09/11] net: aquantia: Introduce global AQC hardware reset sequence The detailed reset sequence ensures all HW components are in aligned state before NIC startup. It also supports cards with signed firmware (RBL) and checks if their FW is valid. Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- .../net/ethernet/aquantia/atlantic/aq_hw.h | 1 + .../aquantia/atlantic/hw_atl/hw_atl_b0.c | 24 +-- .../aquantia/atlantic/hw_atl/hw_atl_utils.c | 187 +++++++++++++++++- 3 files changed, 183 insertions(+), 29 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index 51b55694a1f6b..a2d416b24ffc2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -100,6 +100,7 @@ struct aq_stats_s { struct aq_hw_s { atomic_t flags; + u8 rbl_enabled:1; struct aq_nic_cfg_s *aq_nic_cfg; const struct aq_fw_ops *aq_fw_ops; void __iomem *mmio; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 29abbc2588c6d..819f6bcf9b4ee 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -87,32 +87,14 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self) { int err = 0; - hw_atl_glb_glb_reg_res_dis_set(self, 1U); - hw_atl_pci_pci_reg_res_dis_set(self, 0U); - hw_atl_rx_rx_reg_res_dis_set(self, 0U); - hw_atl_tx_tx_reg_res_dis_set(self, 0U); - - HW_ATL_FLUSH(); - hw_atl_glb_soft_res_set(self, 1); - - /* check 10 times by 1ms */ - AQ_HW_WAIT_FOR(hw_atl_glb_soft_res_get(self) == 0, 1000U, 10U); - if (err < 0) - goto err_exit; - - hw_atl_itr_irq_reg_res_dis_set(self, 0U); - hw_atl_itr_res_irq_set(self, 1U); - - /* check 10 times by 1ms */ - AQ_HW_WAIT_FOR(hw_atl_itr_res_irq_get(self) == 0, 1000U, 10U); - if (err < 0) - goto err_exit; + err = hw_atl_utils_soft_reset(self); + if (err) + return err; self->aq_fw_ops->set_state(self, MPI_RESET); err = aq_hw_err_from_flags(self); -err_exit: return err; } diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 56fb048c4ddc7..967f0fd07fcf2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -31,32 +31,45 @@ #define HW_ATL_MPI_SPEED_MSK 0xFFFF0000U #define HW_ATL_MPI_SPEED_SHIFT 16U +#define HW_ATL_MPI_DAISY_CHAIN_STATUS 0x704 +#define HW_ATL_MPI_BOOT_EXIT_CODE 0x388 + +#define HW_ATL_MAC_PHY_CONTROL 0x4000 +#define HW_ATL_MAC_PHY_MPI_RESET_BIT 0x1D + #define HW_ATL_FW_VER_1X 0x01050006U #define HW_ATL_FW_VER_2X 0x02000000U #define HW_ATL_FW_VER_3X 0x03000000U +#define FORCE_FLASHLESS 0 + static int hw_atl_utils_ver_match(u32 ver_expected, u32 ver_actual); int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) { int err = 0; + err = hw_atl_utils_soft_reset(self); + if (err) + return err; + hw_atl_utils_hw_chip_features_init(self, &self->chip_features); hw_atl_utils_get_fw_version(self, &self->fw_ver_actual); - if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, self->fw_ver_actual) == 0) + if (hw_atl_utils_ver_match(HW_ATL_FW_VER_1X, + self->fw_ver_actual) == 0) { *fw_ops = &aq_fw_1x_ops; - else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, - self->fw_ver_actual) == 0) + } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_2X, + self->fw_ver_actual) == 0) { *fw_ops = &aq_fw_2x_ops; - else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, - self->fw_ver_actual) == 0) + } else if (hw_atl_utils_ver_match(HW_ATL_FW_VER_3X, + self->fw_ver_actual) == 0) { *fw_ops = &aq_fw_2x_ops; - else { + } else { aq_pr_err("Bad FW version detected: %x\n", - self->fw_ver_actual); + self->fw_ver_actual); return -EOPNOTSUPP; } self->aq_fw_ops = *fw_ops; @@ -64,6 +77,164 @@ int hw_atl_utils_initfw(struct aq_hw_s *self, const struct aq_fw_ops **fw_ops) return err; } +static int hw_atl_utils_soft_reset_flb(struct aq_hw_s *self) +{ + int k = 0; + u32 gsr; + + aq_hw_write_reg(self, 0x404, 0x40e1); + AQ_HW_SLEEP(50); + + /* Cleanup SPI */ + aq_hw_write_reg(self, 0x534, 0xA0); + aq_hw_write_reg(self, 0x100, 0x9F); + aq_hw_write_reg(self, 0x100, 0x809F); + + gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR); + aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000); + + /* Kickstart MAC */ + aq_hw_write_reg(self, 0x404, 0x80e0); + aq_hw_write_reg(self, 0x32a8, 0x0); + aq_hw_write_reg(self, 0x520, 0x1); + AQ_HW_SLEEP(10); + aq_hw_write_reg(self, 0x404, 0x180e0); + + for (k = 0; k < 1000; k++) { + u32 flb_status = aq_hw_read_reg(self, + HW_ATL_MPI_DAISY_CHAIN_STATUS); + + flb_status = flb_status & 0x10; + if (flb_status) + break; + AQ_HW_SLEEP(10); + } + if (k == 1000) { + aq_pr_err("MAC kickstart failed\n"); + return -EIO; + } + + /* FW reset */ + aq_hw_write_reg(self, 0x404, 0x80e0); + AQ_HW_SLEEP(50); + aq_hw_write_reg(self, 0x3a0, 0x1); + + /* Kickstart PHY - skipped */ + + /* Global software reset*/ + hw_atl_rx_rx_reg_res_dis_set(self, 0U); + hw_atl_tx_tx_reg_res_dis_set(self, 0U); + aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL, + BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT), + HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0); + gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR); + aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, (gsr & 0xBFFF) | 0x8000); + + for (k = 0; k < 1000; k++) { + u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION); + + if (fw_state) + break; + AQ_HW_SLEEP(10); + } + if (k == 1000) { + aq_pr_err("FW kickstart failed\n"); + return -EIO; + } + + return 0; +} + +static int hw_atl_utils_soft_reset_rbl(struct aq_hw_s *self) +{ + u32 gsr, rbl_status; + int k; + + aq_hw_write_reg(self, 0x404, 0x40e1); + aq_hw_write_reg(self, 0x3a0, 0x1); + aq_hw_write_reg(self, 0x32a8, 0x0); + + /* Alter RBL status */ + aq_hw_write_reg(self, 0x388, 0xDEAD); + + /* Global software reset*/ + hw_atl_rx_rx_reg_res_dis_set(self, 0U); + hw_atl_tx_tx_reg_res_dis_set(self, 0U); + aq_hw_write_reg_bit(self, HW_ATL_MAC_PHY_CONTROL, + BIT(HW_ATL_MAC_PHY_MPI_RESET_BIT), + HW_ATL_MAC_PHY_MPI_RESET_BIT, 0x0); + gsr = aq_hw_read_reg(self, HW_ATL_GLB_SOFT_RES_ADR); + aq_hw_write_reg(self, HW_ATL_GLB_SOFT_RES_ADR, + (gsr & 0xFFFFBFFF) | 0x8000); + + if (FORCE_FLASHLESS) + aq_hw_write_reg(self, 0x534, 0x0); + + aq_hw_write_reg(self, 0x404, 0x40e0); + + /* Wait for RBL boot */ + for (k = 0; k < 1000; k++) { + rbl_status = aq_hw_read_reg(self, 0x388) & 0xFFFF; + if (rbl_status && rbl_status != 0xDEAD) + break; + AQ_HW_SLEEP(10); + } + if (!rbl_status || rbl_status == 0xDEAD) { + aq_pr_err("RBL Restart failed"); + return -EIO; + } + + /* Restore NVR */ + if (FORCE_FLASHLESS) + aq_hw_write_reg(self, 0x534, 0xA0); + + if (rbl_status == 0xF1A7) { + aq_pr_err("No FW detected. Dynamic FW load not implemented\n"); + return -ENOTSUPP; + } + + for (k = 0; k < 1000; k++) { + u32 fw_state = aq_hw_read_reg(self, HW_ATL_MPI_FW_VERSION); + + if (fw_state) + break; + AQ_HW_SLEEP(10); + } + if (k == 1000) { + aq_pr_err("FW kickstart failed\n"); + return -EIO; + } + + return 0; +} + +int hw_atl_utils_soft_reset(struct aq_hw_s *self) +{ + int k; + u32 boot_exit_code = 0; + + for (k = 0; k < 1000; ++k) { + u32 flb_status = aq_hw_read_reg(self, + HW_ATL_MPI_DAISY_CHAIN_STATUS); + boot_exit_code = aq_hw_read_reg(self, + HW_ATL_MPI_BOOT_EXIT_CODE); + if (flb_status != 0x06000000 || boot_exit_code != 0) + break; + } + + if (k == 1000) { + aq_pr_err("Neither RBL nor FLB firmware started\n"); + return -EOPNOTSUPP; + } + + self->rbl_enabled = (boot_exit_code != 0); + + if (self->rbl_enabled) + return hw_atl_utils_soft_reset_rbl(self); + else + return hw_atl_utils_soft_reset_flb(self); +} + int hw_atl_utils_fw_downld_dwords(struct aq_hw_s *self, u32 a, u32 *p, u32 cnt) { @@ -598,7 +769,7 @@ int hw_atl_utils_hw_get_regs(struct aq_hw_s *self, for (i = 0; i < aq_hw_caps->mac_regs_count; i++) regs_buff[i] = aq_hw_read_reg(self, - hw_atl_utils_hw_mac_regs[i]); + hw_atl_utils_hw_mac_regs[i]); return 0; } From 854ab38c15061b2353f8cc04e2bb93d0980e9789 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:27 +0300 Subject: [PATCH 10/11] net: aquantia: Report correct mediatype via ethtool For devices with known capabilities of Fibre media type we now report that to ethtool. Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/aq_nic.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 3087a3044bb31..ebbaf63eaf475 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -690,7 +690,10 @@ static void aq_nic_update_ndev_stats(struct aq_nic_s *self) void aq_nic_get_link_ksettings(struct aq_nic_s *self, struct ethtool_link_ksettings *cmd) { - cmd->base.port = PORT_TP; + if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE) + cmd->base.port = PORT_FIBRE; + else + cmd->base.port = PORT_TP; /* This driver supports only 10G capable adapters, so DUPLEX_FULL */ cmd->base.duplex = DUPLEX_FULL; cmd->base.autoneg = self->aq_nic_cfg.is_autoneg; @@ -722,7 +725,11 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, Pause); ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); - ethtool_link_ksettings_add_link_mode(cmd, supported, TP); + + if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE) + ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); + else + ethtool_link_ksettings_add_link_mode(cmd, supported, TP); ethtool_link_ksettings_zero_link_mode(cmd, advertising); @@ -753,7 +760,10 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self, ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause); - ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); + if (self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_FIBRE) + ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); + else + ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); } int aq_nic_set_link_ksettings(struct aq_nic_s *self, From 6de97c0494dc5dd3a19d41328cb62a23e75db732 Mon Sep 17 00:00:00 2001 From: Igor Russkikh Date: Fri, 19 Jan 2018 17:03:28 +0300 Subject: [PATCH 11/11] net: aquantia: bump driver version to match aquantia internal numbering Signed-off-by: Igor Russkikh Signed-off-by: David S. Miller --- drivers/net/ethernet/aquantia/atlantic/ver.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/aquantia/atlantic/ver.h b/drivers/net/ethernet/aquantia/atlantic/ver.h index 9009f2651e706..5265b937677bc 100644 --- a/drivers/net/ethernet/aquantia/atlantic/ver.h +++ b/drivers/net/ethernet/aquantia/atlantic/ver.h @@ -10,9 +10,9 @@ #ifndef VER_H #define VER_H -#define NIC_MAJOR_DRIVER_VERSION 1 -#define NIC_MINOR_DRIVER_VERSION 6 -#define NIC_BUILD_DRIVER_VERSION 13 +#define NIC_MAJOR_DRIVER_VERSION 2 +#define NIC_MINOR_DRIVER_VERSION 0 +#define NIC_BUILD_DRIVER_VERSION 2 #define NIC_REVISION_DRIVER_VERSION 0 #define AQ_CFG_DRV_VERSION_SUFFIX "-kern"