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

Commit 4948293f authored by Igor Russkikh's avatar Igor Russkikh Committed by David S. Miller
Browse files

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: default avatarIgor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent efe779b7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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)
+4 −5
Original line number Diff line number Diff line
@@ -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);

+3 −6
Original line number Diff line number Diff line
@@ -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:
+2 −1
Original line number Diff line number Diff line
@@ -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,
+60 −14
Original line number Diff line number Diff line
@@ -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;
Loading