Skip to content

Commit

Permalink
net: aquantia: Introduce firmware ops callbacks
Browse files Browse the repository at this point in the history
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 <igor.russkikh@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Igor Russkikh authored and David S. Miller committed Jan 21, 2018
1 parent 76c19c6 commit 0c58c35
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 81 deletions.
27 changes: 17 additions & 10 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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 */
3 changes: 3 additions & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_hw_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
14 changes: 9 additions & 5 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/aquantia/atlantic/aq_nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
23 changes: 4 additions & 19 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
23 changes: 4 additions & 19 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
81 changes: 56 additions & 25 deletions drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <linux/random.h>

#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)
{
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
};
Loading

0 comments on commit 0c58c35

Please sign in to comment.