Commit 7e2cf4fe authored by Sony Chacko's avatar Sony Chacko Committed by David S. Miller

qlcnic: change driver hardware interface mechanism

Refactor 82xx driver to support new adapter - Qlogic 83XX CNA

Create adapter abstraction layer and seperate 82xx hardware access routines.
Create mailbox based HW interface mechanism
Signed-off-by: default avatarAnirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: default avatarSony Chacko <sony.chacko@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8395be5e
...@@ -402,6 +402,7 @@ struct qlcnic_hardware_context { ...@@ -402,6 +402,7 @@ struct qlcnic_hardware_context {
struct qlcnic_hardware_ops *hw_ops; struct qlcnic_hardware_ops *hw_ops;
struct qlcnic_nic_intr_coalesce coal; struct qlcnic_nic_intr_coalesce coal;
struct qlcnic_fw_dump fw_dump; struct qlcnic_fw_dump fw_dump;
u32 *reg_tbl;
}; };
struct qlcnic_adapter_stats { struct qlcnic_adapter_stats {
...@@ -492,8 +493,6 @@ struct qlcnic_recv_context { ...@@ -492,8 +493,6 @@ struct qlcnic_recv_context {
/* HW context creation */ /* HW context creation */
#define QLCNIC_OS_CRB_RETRY_COUNT 4000 #define QLCNIC_OS_CRB_RETRY_COUNT 4000
#define QLCNIC_CDRP_SIGNATURE_MAKE(pcifn, version) \
(((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16))
#define QLCNIC_CDRP_CMD_BIT 0x80000000 #define QLCNIC_CDRP_CMD_BIT 0x80000000
...@@ -1266,10 +1265,8 @@ struct qlcnic_esw_statistics { ...@@ -1266,10 +1265,8 @@ struct qlcnic_esw_statistics {
#define QLCNIC_RESET_QUIESCENT 0xadd00020 #define QLCNIC_RESET_QUIESCENT 0xadd00020
struct _cdrp_cmd { struct _cdrp_cmd {
u32 cmd; u32 num;
u32 arg1; u32 *arg;
u32 arg2;
u32 arg3;
}; };
struct qlcnic_cmd_args { struct qlcnic_cmd_args {
...@@ -1279,9 +1276,6 @@ struct qlcnic_cmd_args { ...@@ -1279,9 +1276,6 @@ struct qlcnic_cmd_args {
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter);
int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config); int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config);
int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off);
int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data);
int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data); int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data);
int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data); int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data);
void qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *, u64, u64 *); void qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *, u64, u64 *);
...@@ -1291,9 +1285,10 @@ void qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *, u64, u64); ...@@ -1291,9 +1285,10 @@ void qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *, u64, u64);
(((addr) < (high)) && ((addr) >= (low))) (((addr) < (high)) && ((addr) >= (low)))
#define QLCRD32(adapter, off) \ #define QLCRD32(adapter, off) \
(qlcnic_hw_read_wx_2M(adapter, off)) (adapter->ahw->hw_ops->read_reg)(adapter, off)
#define QLCWR32(adapter, off, val) \ #define QLCWR32(adapter, off, val) \
(qlcnic_hw_write_wx_2M(adapter, off, val)) adapter->ahw->hw_ops->write_reg(adapter, off, val)
int qlcnic_pcie_sem_lock(struct qlcnic_adapter *, int, u32); int qlcnic_pcie_sem_lock(struct qlcnic_adapter *, int, u32);
void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
...@@ -1306,10 +1301,6 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); ...@@ -1306,10 +1301,6 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
qlcnic_pcie_sem_lock((a), 3, QLCNIC_PHY_LOCK_ID) qlcnic_pcie_sem_lock((a), 3, QLCNIC_PHY_LOCK_ID)
#define qlcnic_phy_unlock(a) \ #define qlcnic_phy_unlock(a) \
qlcnic_pcie_sem_unlock((a), 3) qlcnic_pcie_sem_unlock((a), 3)
#define qlcnic_api_lock(a) \
qlcnic_pcie_sem_lock((a), 5, 0)
#define qlcnic_api_unlock(a) \
qlcnic_pcie_sem_unlock((a), 5)
#define qlcnic_sw_lock(a) \ #define qlcnic_sw_lock(a) \
qlcnic_pcie_sem_lock((a), 6, 0) qlcnic_pcie_sem_lock((a), 6, 0)
#define qlcnic_sw_unlock(a) \ #define qlcnic_sw_unlock(a) \
...@@ -1324,9 +1315,7 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); ...@@ -1324,9 +1315,7 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
#define MAX_CTL_CHECK 1000 #define MAX_CTL_CHECK 1000
int qlcnic_get_board_info(struct qlcnic_adapter *adapter);
int qlcnic_wol_supported(struct qlcnic_adapter *adapter); int qlcnic_wol_supported(struct qlcnic_adapter *adapter);
int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate);
void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter);
void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter);
int qlcnic_dump_fw(struct qlcnic_adapter *); int qlcnic_dump_fw(struct qlcnic_adapter *);
...@@ -1365,47 +1354,28 @@ void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, ...@@ -1365,47 +1354,28 @@ void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter,
int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max); int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max);
void qlcnic_set_multi(struct net_device *netdev); void qlcnic_set_multi(struct net_device *netdev);
void qlcnic_free_mac_list(struct qlcnic_adapter *adapter); void qlcnic_free_mac_list(struct qlcnic_adapter *adapter);
int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter);
int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable);
int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd);
int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable);
void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup);
int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu);
int qlcnic_change_mtu(struct net_device *netdev, int new_mtu); int qlcnic_change_mtu(struct net_device *netdev, int new_mtu);
netdev_features_t qlcnic_fix_features(struct net_device *netdev, netdev_features_t qlcnic_fix_features(struct net_device *netdev,
netdev_features_t features); netdev_features_t features);
int qlcnic_set_features(struct net_device *netdev, netdev_features_t features); int qlcnic_set_features(struct net_device *netdev, netdev_features_t features);
int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable);
int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable); int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *);
void qlcnic_fetch_mac(u32, u32, u8, u8 *);
void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter);
int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode);
/* Functions from qlcnic_ethtool.c */ /* Functions from qlcnic_ethtool.c */
int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]); int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]);
/* Functions from qlcnic_main.c */ /* Functions from qlcnic_main.c */
int qlcnic_reset_context(struct qlcnic_adapter *); int qlcnic_reset_context(struct qlcnic_adapter *);
void qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *);
void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings);
int qlcnic_diag_alloc_res(struct net_device *netdev, int test); int qlcnic_diag_alloc_res(struct net_device *netdev, int test);
netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val);
int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data); int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data);
void qlcnic_dev_request_reset(struct qlcnic_adapter *); int qlcnic_validate_max_rss(struct net_device *netdev, u8, u8);
void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
/* Management functions */
int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*);
int qlcnic_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
int qlcnic_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
int qlcnic_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*);
/* eSwitch management functions */ /* eSwitch management functions */
int qlcnic_config_switch_port(struct qlcnic_adapter *, int qlcnic_config_switch_port(struct qlcnic_adapter *,
struct qlcnic_esw_func_cfg *); struct qlcnic_esw_func_cfg *);
...@@ -1418,12 +1388,10 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8, ...@@ -1418,12 +1388,10 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8,
struct __qlcnic_esw_statistics *); struct __qlcnic_esw_statistics *);
int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8); int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8);
int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *); int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *);
extern int qlcnic_config_tso;
int qlcnic_napi_add(struct qlcnic_adapter *, struct net_device *); void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd);
void qlcnic_napi_del(struct qlcnic_adapter *adapter); void qlcnic_napi_del(struct qlcnic_adapter *);
void qlcnic_napi_enable(struct qlcnic_adapter *adapter);
void qlcnic_napi_disable(struct qlcnic_adapter *adapter);
int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int);
void qlcnic_free_sds_rings(struct qlcnic_recv_context *); void qlcnic_free_sds_rings(struct qlcnic_recv_context *);
void qlcnic_free_tx_rings(struct qlcnic_adapter *); void qlcnic_free_tx_rings(struct qlcnic_adapter *);
...@@ -1433,6 +1401,9 @@ void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); ...@@ -1433,6 +1401,9 @@ void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter);
void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter);
void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter);
void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter);
void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter);
void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter);
int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
void qlcnic_set_vlan_config(struct qlcnic_adapter *, void qlcnic_set_vlan_config(struct qlcnic_adapter *,
...@@ -1462,6 +1433,271 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) ...@@ -1462,6 +1433,271 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
tx_ring->producer; tx_ring->producer;
} }
struct qlcnic_nic_template {
int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
int (*config_led) (struct qlcnic_adapter *, u32, u32);
int (*start_firmware) (struct qlcnic_adapter *);
int (*init_driver) (struct qlcnic_adapter *);
void (*request_reset) (struct qlcnic_adapter *, u32);
void (*cancel_idc_work) (struct qlcnic_adapter *);
int (*napi_add)(struct qlcnic_adapter *, struct net_device *);
void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int);
irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *);
};
/* Adapter hardware abstraction */
struct qlcnic_hardware_ops {
void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
void (*write_crb) (struct qlcnic_adapter *, char *, loff_t, size_t);
int (*read_reg) (struct qlcnic_adapter *, ulong);
int (*write_reg) (struct qlcnic_adapter *, ulong, u32);
void (*get_ocm_win) (struct qlcnic_hardware_context *);
int (*get_mac_address) (struct qlcnic_adapter *, u8 *);
int (*setup_intr) (struct qlcnic_adapter *, u8);
int (*alloc_mbx_args)(struct qlcnic_cmd_args *,
struct qlcnic_adapter *, u32);
int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *);
void (*get_func_no) (struct qlcnic_adapter *);
int (*api_lock) (struct qlcnic_adapter *);
void (*api_unlock) (struct qlcnic_adapter *);
void (*add_sysfs) (struct qlcnic_adapter *);
void (*remove_sysfs) (struct qlcnic_adapter *);
void (*process_lb_rcv_ring_diag) (struct qlcnic_host_sds_ring *);
int (*create_rx_ctx) (struct qlcnic_adapter *);
int (*create_tx_ctx) (struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *, int);
int (*setup_link_event) (struct qlcnic_adapter *, int);
int (*get_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *, u8);
int (*get_pci_info) (struct qlcnic_adapter *, struct qlcnic_pci_info *);
int (*set_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *);
int (*change_macvlan) (struct qlcnic_adapter *, u8*, __le16, u8);
void (*napi_enable) (struct qlcnic_adapter *);
void (*napi_disable) (struct qlcnic_adapter *);
void (*config_intr_coal) (struct qlcnic_adapter *);
int (*config_rss) (struct qlcnic_adapter *, int);
int (*config_hw_lro) (struct qlcnic_adapter *, int);
int (*config_loopback) (struct qlcnic_adapter *, u8);
int (*clear_loopback) (struct qlcnic_adapter *, u8);
int (*config_promisc_mode) (struct qlcnic_adapter *, u32);
void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, __le16);
int (*get_board_info) (struct qlcnic_adapter *);
};
extern struct qlcnic_nic_template qlcnic_vf_ops;
static inline int qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
return adapter->nic_ops->start_firmware(adapter);
}
static inline void qlcnic_read_crb(struct qlcnic_adapter *adapter, char *buf,
loff_t offset, size_t size)
{
adapter->ahw->hw_ops->read_crb(adapter, buf, offset, size);
}
static inline void qlcnic_write_crb(struct qlcnic_adapter *adapter, char *buf,
loff_t offset, size_t size)
{
adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size);
}
static inline u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter,
ulong off)
{
return adapter->ahw->hw_ops->read_reg(adapter, off);
}
static inline int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter,
ulong off, u32 data)
{
return adapter->ahw->hw_ops->write_reg(adapter, off, data);
}
static inline int qlcnic_get_mac_address(struct qlcnic_adapter *adapter,
u8 *mac)
{
return adapter->ahw->hw_ops->get_mac_address(adapter, mac);
}
static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
{
return adapter->ahw->hw_ops->setup_intr(adapter, num_intr);
}
static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
struct qlcnic_adapter *adapter, u32 arg)
{
return adapter->ahw->hw_ops->alloc_mbx_args(mbx, adapter, arg);
}
static inline int qlcnic_issue_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *cmd)
{
return adapter->ahw->hw_ops->mbx_cmd(adapter, cmd);
}
static inline void qlcnic_get_func_no(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->get_func_no(adapter);
}
static inline int qlcnic_api_lock(struct qlcnic_adapter *adapter)
{
return adapter->ahw->hw_ops->api_lock(adapter);
}
static inline void qlcnic_api_unlock(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->api_unlock(adapter);
}
static inline void qlcnic_add_sysfs(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->add_sysfs(adapter);
}
static inline void qlcnic_remove_sysfs(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->remove_sysfs(adapter);
}
static inline void
qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
{
sds_ring->adapter->ahw->hw_ops->process_lb_rcv_ring_diag(sds_ring);
}
static inline int qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
{
return adapter->ahw->hw_ops->create_rx_ctx(adapter);
}
static inline int qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *ptr,
int ring)
{
return adapter->ahw->hw_ops->create_tx_ctx(adapter, ptr, ring);
}
static inline int qlcnic_linkevent_request(struct qlcnic_adapter *adapter,
int enable)
{
return adapter->ahw->hw_ops->setup_link_event(adapter, enable);
}
static inline int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
struct qlcnic_info *info, u8 id)
{
return adapter->ahw->hw_ops->get_nic_info(adapter, info, id);
}
static inline int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
struct qlcnic_pci_info *info)
{
return adapter->ahw->hw_ops->get_pci_info(adapter, info);
}
static inline int qlcnic_set_nic_info(struct qlcnic_adapter *adapter,
struct qlcnic_info *info)
{
return adapter->ahw->hw_ops->set_nic_info(adapter, info);
}
static inline int qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter,
u8 *addr, __le16 id, u8 cmd)
{
return adapter->ahw->hw_ops->change_macvlan(adapter, addr, id, cmd);
}
static inline int qlcnic_napi_add(struct qlcnic_adapter *adapter,
struct net_device *netdev)
{
return adapter->nic_ops->napi_add(adapter, netdev);
}
static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->napi_enable(adapter);
}
static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->napi_disable(adapter);
}
static inline void qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
{
adapter->ahw->hw_ops->config_intr_coal(adapter);
}
static inline int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
{
return adapter->ahw->hw_ops->config_rss(adapter, enable);
}
static inline int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter,
int enable)
{
return adapter->ahw->hw_ops->config_hw_lro(adapter, enable);
}
static inline int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
{
return adapter->ahw->hw_ops->config_loopback(adapter, mode);
}
static inline int qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
{
return adapter->ahw->hw_ops->config_loopback(adapter, mode);
}
static inline int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter,
u32 mode)
{
return adapter->ahw->hw_ops->config_promisc_mode(adapter, mode);
}
static inline void qlcnic_change_filter(struct qlcnic_adapter *adapter,
u64 *addr, __le16 id)
{
adapter->ahw->hw_ops->change_l2_filter(adapter, addr, id);
}
static inline int qlcnic_get_board_info(struct qlcnic_adapter *adapter)
{
return adapter->ahw->hw_ops->get_board_info(adapter);
}
static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter,
u32 key)
{
adapter->nic_ops->request_reset(adapter, key);
}
static inline void qlcnic_cancel_idc_work(struct qlcnic_adapter *adapter)
{
adapter->nic_ops->cancel_idc_work(adapter);
}
static inline irqreturn_t
qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter)
{
return adapter->nic_ops->clear_legacy_intr(adapter);
}
static inline int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state,
u32 rate)
{
return adapter->nic_ops->config_led(adapter, state, rate);
}
static inline void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter,
__be32 ip, int cmd)
{
adapter->nic_ops->config_ipaddr(adapter, ip, cmd);
}
static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring)
{ {
writel(0, sds_ring->crb_intr_mask); writel(0, sds_ring->crb_intr_mask);
...@@ -1480,12 +1716,6 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) ...@@ -1480,12 +1716,6 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring)
extern const struct ethtool_ops qlcnic_ethtool_ops; extern const struct ethtool_ops qlcnic_ethtool_ops;
extern const struct ethtool_ops qlcnic_ethtool_failed_ops; extern const struct ethtool_ops qlcnic_ethtool_failed_ops;
struct qlcnic_nic_template {
int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
int (*config_led) (struct qlcnic_adapter *, u32, u32);
int (*start_firmware) (struct qlcnic_adapter *);
};
#define QLCDB(adapter, lvl, _fmt, _args...) do { \ #define QLCDB(adapter, lvl, _fmt, _args...) do { \
if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \ if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \
printk(KERN_INFO "%s: %s: " _fmt, \ printk(KERN_INFO "%s: %s: " _fmt, \
......
...@@ -7,6 +7,86 @@ ...@@ -7,6 +7,86 @@
#include "qlcnic.h" #include "qlcnic.h"
static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = {
{QLCNIC_CMD_CREATE_RX_CTX, 4, 1},
{QLCNIC_CMD_DESTROY_RX_CTX, 2, 1},
{QLCNIC_CMD_CREATE_TX_CTX, 4, 1},
{QLCNIC_CMD_DESTROY_TX_CTX, 2, 1},
{QLCNIC_CMD_INTRPT_TEST, 4, 1},
{QLCNIC_CMD_SET_MTU, 4, 1},
{QLCNIC_CMD_READ_PHY, 4, 2},
{QLCNIC_CMD_WRITE_PHY, 5, 1},
{QLCNIC_CMD_READ_HW_REG, 4, 1},
{QLCNIC_CMD_GET_FLOW_CTL, 4, 2},
{QLCNIC_CMD_SET_FLOW_CTL, 4, 1},
{QLCNIC_CMD_READ_MAX_MTU, 4, 2},
{QLCNIC_CMD_READ_MAX_LRO, 4, 2},
{QLCNIC_CMD_MAC_ADDRESS, 4, 3},
{QLCNIC_CMD_GET_PCI_INFO, 4, 1},
{QLCNIC_CMD_GET_NIC_INFO, 4, 1},
{QLCNIC_CMD_SET_NIC_INFO, 4, 1},
{QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3},
{QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1},
{QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3},
{QLCNIC_CMD_SET_PORTMIRRORING, 4, 1},
{QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1},
{QLCNIC_CMD_GET_MAC_STATS, 4, 1},
{QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3},
{QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1},
{QLCNIC_CMD_CONFIG_PORT, 4, 1},
{QLCNIC_CMD_TEMP_SIZE, 4, 4},
{QLCNIC_CMD_GET_TEMP_HDR, 4, 1},
{QLCNIC_CMD_SET_DRV_VER, 4, 1},
};
static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw)
{
return (ahw->pci_func & 0xff) | ((ahw->fw_hal_version & 0xff) << 8) |
(0xcafe << 16);
}
/* Allocate mailbox registers */
int qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx,
struct qlcnic_adapter *adapter, u32 type)
{
int i, size;
const struct qlcnic_mailbox_metadata *mbx_tbl;
mbx_tbl = qlcnic_mbx_tbl;
size = ARRAY_SIZE(qlcnic_mbx_tbl);
for (i = 0; i < size; i++) {
if (type == mbx_tbl[i].cmd) {
mbx->req.num = mbx_tbl[i].in_args;
mbx->rsp.num = mbx_tbl[i].out_args;
mbx->req.arg = kcalloc(mbx->req.num,
sizeof(u32), GFP_ATOMIC);
if (!mbx->req.arg)
return -ENOMEM;
mbx->rsp.arg = kcalloc(mbx->rsp.num,
sizeof(u32), GFP_ATOMIC);
if (!mbx->rsp.arg) {
kfree(mbx->req.arg);
mbx->req.arg = NULL;
return -ENOMEM;
}
memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num);
memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num);
mbx->req.arg[0] = type;
break;
}
}
return 0;
}
/* Free up mailbox registers */
void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd)
{
kfree(cmd->req.arg);
cmd->req.arg = NULL;
kfree(cmd->rsp.arg);
cmd->rsp.arg = NULL;
}
static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func)
{ {
int i; int i;
...@@ -38,194 +118,105 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter) ...@@ -38,194 +118,105 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
return rsp; return rsp;
} }
void int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) struct qlcnic_cmd_args *cmd)
{ {
int i;
u32 rsp; u32 rsp;
u32 signature; u32 signature;
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
struct qlcnic_hardware_context *ahw = adapter->ahw; struct qlcnic_hardware_context *ahw = adapter->ahw;
signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func, signature = qlcnic_get_cmd_signature(ahw);
adapter->ahw->fw_hal_version);
/* Acquire semaphore before accessing CRB */ /* Acquire semaphore before accessing CRB */
if (qlcnic_api_lock(adapter)) { if (qlcnic_api_lock(adapter)) {
cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT; cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
return; return cmd->rsp.arg[0];
} }
QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature); QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature);
QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, cmd->req.arg1); for (i = 1; i < QLCNIC_CDRP_MAX_ARGS; i++)
QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, cmd->req.arg2); QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]);
QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, cmd->req.arg3);
QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET, QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET,
QLCNIC_CDRP_FORM_CMD(cmd->req.cmd)); QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0]));
rsp = qlcnic_poll_rsp(adapter); rsp = qlcnic_poll_rsp(adapter);
if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) { if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) {
dev_err(&pdev->dev, "CDRP response timeout.\n"); dev_err(&pdev->dev, "card response timeout.\n");
cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT; cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT;
} else if (rsp == QLCNIC_CDRP_RSP_FAIL) { } else if (rsp == QLCNIC_CDRP_RSP_FAIL) {
cmd->rsp.cmd = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1));
switch (cmd->rsp.cmd) { dev_err(&pdev->dev, "failed card response code:0x%x\n",
case QLCNIC_RCODE_INVALID_ARGS: cmd->rsp.arg[0]);
dev_err(&pdev->dev, "CDRP invalid args: 0x%x.\n", } else if (rsp == QLCNIC_CDRP_RSP_OK)
cmd->rsp.cmd); cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS;
break;
case QLCNIC_RCODE_NOT_SUPPORTED: for (i = 1; i < cmd->rsp.num; i++)
case QLCNIC_RCODE_NOT_IMPL: cmd->rsp.arg[i] = QLCRD32(adapter, QLCNIC_CDRP_ARG(i));
dev_err(&pdev->dev,
"CDRP command not supported: 0x%x.\n",
cmd->rsp.cmd);
break;
case QLCNIC_RCODE_NOT_PERMITTED:
dev_err(&pdev->dev,
"CDRP requested action not permitted: 0x%x.\n",
cmd->rsp.cmd);
break;
case QLCNIC_RCODE_INVALID:
dev_err(&pdev->dev,
"CDRP invalid or unknown cmd received: 0x%x.\n",
cmd->rsp.cmd);
break;
case QLCNIC_RCODE_TIMEOUT:
dev_err(&pdev->dev, "CDRP command timeout: 0x%x.\n",
cmd->rsp.cmd);
break;
default:
dev_err(&pdev->dev, "CDRP command failed: 0x%x.\n",
cmd->rsp.cmd);
}
} else if (rsp == QLCNIC_CDRP_RSP_OK) {
cmd->rsp.cmd = QLCNIC_RCODE_SUCCESS;
if (cmd->rsp.arg2)
cmd->rsp.arg2 = QLCRD32(adapter,
QLCNIC_ARG2_CRB_OFFSET);
if (cmd->rsp.arg3)
cmd->rsp.arg3 = QLCRD32(adapter,
QLCNIC_ARG3_CRB_OFFSET);
}
if (cmd->rsp.arg1)
cmd->rsp.arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
/* Release semaphore */ /* Release semaphore */
qlcnic_api_unlock(adapter); qlcnic_api_unlock(adapter);
return cmd->rsp.arg[0];
}
static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size)
{
uint64_t sum = 0;
int count = temp_size / sizeof(uint32_t);
while (count-- > 0)
sum += *temp_buffer++;
while (sum >> 32)
sum = (sum & 0xFFFFFFFF) + (sum >> 32);
return ~sum;
} }
int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter)
{ {
int err, i; int err = 0;
void *tmp_addr; void *tmp_addr;
u32 temp_size, version, csum, *template;
__le32 *tmp_buf;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
struct qlcnic_hardware_context *ahw;
struct qlcnic_dump_template_hdr *tmpl_hdr;
dma_addr_t tmp_addr_t = 0; dma_addr_t tmp_addr_t = 0;
ahw = adapter->ahw; tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, 0x1000,
memset(&cmd, 0, sizeof(cmd)); &tmp_addr_t, GFP_KERNEL);
cmd.req.cmd = QLCNIC_CDRP_CMD_TEMP_SIZE;
memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd));
qlcnic_issue_cmd(adapter, &cmd);
if (cmd.rsp.cmd != QLCNIC_RCODE_SUCCESS) {
dev_info(&adapter->pdev->dev,
"Can't get template size %d\n", cmd.rsp.cmd);
err = -EIO;
return err;
}
temp_size = cmd.rsp.arg2;
version = cmd.rsp.arg3;
dev_info(&adapter->pdev->dev,
"minidump template version = 0x%x", version);
if (!temp_size)
return -EIO;
tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size,
&tmp_addr_t, GFP_KERNEL);
if (!tmp_addr) { if (!tmp_addr) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Can't get memory for FW dump template\n"); "Can't get memory for FW dump template\n");
return -ENOMEM; return -ENOMEM;
} }
memset(&cmd.rsp, 0, sizeof(struct _cdrp_cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_TEMP_HDR;
cmd.req.arg1 = LSD(tmp_addr_t);
cmd.req.arg2 = MSD(tmp_addr_t);
cmd.req.arg3 = temp_size;
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
"Failed to get mini dump template header %d\n", err);
err = -EIO;
goto error;
}
ahw->fw_dump.tmpl_hdr = vzalloc(temp_size);
if (!ahw->fw_dump.tmpl_hdr) {
err = -EIO;
goto error;
}
tmp_buf = tmp_addr;
template = (u32 *) ahw->fw_dump.tmpl_hdr;
for (i = 0; i < temp_size/sizeof(u32); i++)
*template++ = __le32_to_cpu(*tmp_buf++);
csum = qlcnic_temp_checksum((u32 *)ahw->fw_dump.tmpl_hdr, temp_size); if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_TEMP_HDR)) {
if (csum) { err = -ENOMEM;
dev_err(&adapter->pdev->dev, goto free_mem;
"Template header checksum validation failed\n");
err = -EIO;
goto error;
} }
tmpl_hdr = ahw->fw_dump.tmpl_hdr; cmd.req.arg[1] = LSD(tmp_addr_t);
tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; cmd.req.arg[2] = MSD(tmp_addr_t);
ahw->fw_dump.enable = 1; cmd.req.arg[3] = 0x1000;
error: err = qlcnic_issue_cmd(adapter, &cmd);
dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t);
qlcnic_free_mbx_args(&cmd);
free_mem:
dma_free_coherent(&adapter->pdev->dev, 0x1000, tmp_addr, tmp_addr_t);
return err; return err;
} }
int int
qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu)
{ {
int err = 0;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
memset(&cmd, 0, sizeof(cmd)); if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE)
cmd.req.cmd = QLCNIC_CDRP_CMD_SET_MTU; return err;
cmd.req.arg1 = recv_ctx->context_id; qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU);
cmd.req.arg2 = mtu; cmd.req.arg[1] = recv_ctx->context_id;
cmd.req.arg3 = 0; cmd.req.arg[2] = mtu;
if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) {
qlcnic_issue_cmd(adapter, &cmd);
if (cmd.rsp.cmd) {
dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
return -EIO;
}
}
return 0; err = qlcnic_issue_cmd(adapter, &cmd);
if (err) {
dev_err(&adapter->pdev->dev, "Failed to set mtu\n");
err = -EIO;
}
qlcnic_free_mbx_args(&cmd);
return err;
} }
static int int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
{ {
void *addr; void *addr;
struct qlcnic_hostrq_rx_ctx *prq; struct qlcnic_hostrq_rx_ctx *prq;
...@@ -242,10 +233,10 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) ...@@ -242,10 +233,10 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
u64 phys_addr; u64 phys_addr;
u8 i, nrds_rings, nsds_rings; u8 i, nrds_rings, nsds_rings;
u16 temp_u16;
size_t rq_size, rsp_size; size_t rq_size, rsp_size;
u32 cap, reg, val, reg2; u32 cap, reg, val, reg2;
int err; int err;
u16 temp;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
...@@ -279,11 +270,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) ...@@ -279,11 +270,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
| QLCNIC_CAP0_VALIDOFF); | QLCNIC_CAP0_VALIDOFF);
cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS);
if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) temp_u16 = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler);
cap |= QLCNIC_CAP0_LRO_MSS; prq->valid_field_offset = cpu_to_le16(temp_u16);
temp = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler);
prq->valid_field_offset = cpu_to_le16(temp);
prq->txrx_sds_binding = nsds_rings - 1; prq->txrx_sds_binding = nsds_rings - 1;
prq->capabilities[0] = cpu_to_le32(cap); prq->capabilities[0] = cpu_to_le32(cap);
...@@ -329,20 +317,17 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) ...@@ -329,20 +317,17 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
} }
phys_addr = hostrq_phys_addr; phys_addr = hostrq_phys_addr;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX);
cmd.req.arg1 = (u32) (phys_addr >> 32); cmd.req.arg[1] = MSD(phys_addr);
cmd.req.arg2 = (u32) (phys_addr & 0xffffffff); cmd.req.arg[2] = LSD(phys_addr);
cmd.req.arg3 = rq_size; cmd.req.arg[3] = rq_size;
cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_RX_CTX; err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err) { if (err) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to create rx ctx in firmware%d\n", err); "Failed to create rx ctx in firmware%d\n", err);
goto out_free_rsp; goto out_free_rsp;
} }
prsp_rds = ((struct qlcnic_cardrsp_rds_ring *) prsp_rds = ((struct qlcnic_cardrsp_rds_ring *)
&prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]);
...@@ -373,6 +358,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) ...@@ -373,6 +358,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
out_free_rsp: out_free_rsp:
dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp,
cardrsp_phys_addr); cardrsp_phys_addr);
qlcnic_free_mbx_args(&cmd);
out_free_rq: out_free_rq:
dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr);
return err; return err;
...@@ -381,24 +367,24 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) ...@@ -381,24 +367,24 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter)
static void static void
qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter)
{ {
int err;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX);
cmd.req.arg1 = recv_ctx->context_id; cmd.req.arg[1] = recv_ctx->context_id;
cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET; err = qlcnic_issue_cmd(adapter, &cmd);
cmd.req.arg3 = 0; if (err)
cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_RX_CTX;
qlcnic_issue_cmd(adapter, &cmd);
if (cmd.rsp.cmd)
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to destroy rx ctx in firmware\n"); "Failed to destroy rx ctx in firmware\n");
recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED; recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED;
qlcnic_free_mbx_args(&cmd);
} }
static int int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) struct qlcnic_host_tx_ring *tx_ring,
int ring)
{ {
struct qlcnic_hostrq_tx_ctx *prq; struct qlcnic_hostrq_tx_ctx *prq;
struct qlcnic_hostrq_cds_ring *prq_cds; struct qlcnic_hostrq_cds_ring *prq_cds;
...@@ -410,7 +396,6 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) ...@@ -410,7 +396,6 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
int err; int err;
u64 phys_addr; u64 phys_addr;
dma_addr_t rq_phys_addr, rsp_phys_addr; dma_addr_t rq_phys_addr, rsp_phys_addr;
struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
/* reset host resources */ /* reset host resources */
tx_ring->producer = 0; tx_ring->producer = 0;
...@@ -445,9 +430,9 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) ...@@ -445,9 +430,9 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
prq->host_int_crb_mode = prq->host_int_crb_mode =
cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED);
prq->msi_index = 0;
prq->interrupt_ctl = 0; prq->interrupt_ctl = 0;
prq->msi_index = 0;
prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr); prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr);
prq_cds = &prq->cds_ring; prq_cds = &prq->cds_ring;
...@@ -456,19 +441,17 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) ...@@ -456,19 +441,17 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc);
phys_addr = rq_phys_addr; phys_addr = rq_phys_addr;
memset(&cmd, 0, sizeof(cmd));
cmd.req.arg1 = (u32)(phys_addr >> 32); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX);
cmd.req.arg2 = ((u32)phys_addr & 0xffffffff); cmd.req.arg[1] = MSD(phys_addr);
cmd.req.arg3 = rq_size; cmd.req.arg[2] = LSD(phys_addr);
cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_TX_CTX; cmd.req.arg[3] = rq_size;
qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) { if (err == QLCNIC_RCODE_SUCCESS) {
temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); temp = le32_to_cpu(prsp->cds_ring.host_producer_crb);
tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp;
tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
adapter->tx_ring->ctx_id = le16_to_cpu(prsp->context_id);
} else { } else {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to create tx ctx in firmware%d\n", err); "Failed to create tx ctx in firmware%d\n", err);
...@@ -476,41 +459,40 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) ...@@ -476,41 +459,40 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter)
} }
dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr, dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr,
rsp_phys_addr); rsp_phys_addr);
out_free_rq: out_free_rq:
dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr); dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr);
qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
static void static void
qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring)
{ {
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX);
cmd.req.arg1 = adapter->tx_ring->ctx_id; cmd.req.arg[1] = tx_ring->ctx_id;
cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET; if (qlcnic_issue_cmd(adapter, &cmd))
cmd.req.arg3 = 0;
cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX;
qlcnic_issue_cmd(adapter, &cmd);
if (cmd.rsp.cmd)
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to destroy tx ctx in firmware\n"); "Failed to destroy tx ctx in firmware\n");
qlcnic_free_mbx_args(&cmd);
} }
int int
qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config) qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config)
{ {
int err;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT);
cmd.req.arg1 = config; cmd.req.arg[1] = config;
cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIG_PORT; err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd); qlcnic_free_mbx_args(&cmd);
return err;
return cmd.rsp.cmd;
} }
int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
...@@ -584,36 +566,49 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) ...@@ -584,36 +566,49 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter)
return err; return err;
} }
int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev)
int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter)
{ {
int err; int i, err, ring;
if (adapter->flags & QLCNIC_NEED_FLR) { if (dev->flags & QLCNIC_NEED_FLR) {
pci_reset_function(adapter->pdev); pci_reset_function(dev->pdev);
adapter->flags &= ~QLCNIC_NEED_FLR; dev->flags &= ~QLCNIC_NEED_FLR;
} }
err = qlcnic_fw_cmd_create_rx_ctx(adapter); err = qlcnic_fw_cmd_create_rx_ctx(dev);
if (err) if (err)
return err; return err;
err = qlcnic_fw_cmd_create_tx_ctx(adapter); for (ring = 0; ring < dev->max_drv_tx_rings; ring++) {
if (err) { err = qlcnic_fw_cmd_create_tx_ctx(dev,
qlcnic_fw_cmd_destroy_rx_ctx(adapter); &dev->tx_ring[ring],
return err; ring);
if (err) {
qlcnic_fw_cmd_destroy_rx_ctx(dev);
if (ring == 0)
return err;
for (i = 0; i < ring; i++)
qlcnic_fw_cmd_destroy_tx_ctx(dev,
&dev->tx_ring[i]);
return err;
}
} }
set_bit(__QLCNIC_FW_ATTACHED, &adapter->state); set_bit(__QLCNIC_FW_ATTACHED, &dev->state);
return 0; return 0;
} }
void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
{ {
int ring;
if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) { if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) {
qlcnic_fw_cmd_destroy_rx_ctx(adapter); qlcnic_fw_cmd_destroy_rx_ctx(adapter);
qlcnic_fw_cmd_destroy_tx_ctx(adapter); for (ring = 0; ring < adapter->max_drv_tx_rings; ring++)
qlcnic_fw_cmd_destroy_tx_ctx(adapter,
&adapter->tx_ring[ring]);
/* Allow dma queues to drain after context reset */ /* Allow dma queues to drain after context reset */
mdelay(20); mdelay(20);
} }
...@@ -671,40 +666,43 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) ...@@ -671,40 +666,43 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter)
} }
/* Get MAC address of a NIC partition */ int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac)
{ {
int err; int err, i;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
u32 mac_low, mac_high;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS);
cmd.req.arg1 = adapter->ahw->pci_func | BIT_8; cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8;
cmd.req.cmd = QLCNIC_CDRP_CMD_MAC_ADDRESS; err = qlcnic_issue_cmd(adapter, &cmd);
cmd.rsp.arg1 = cmd.rsp.arg2 = 1;
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) if (err == QLCNIC_RCODE_SUCCESS) {
qlcnic_fetch_mac(cmd.rsp.arg1, cmd.rsp.arg2, 0, mac); mac_low = cmd.rsp.arg[1];
else { mac_high = cmd.rsp.arg[2];
for (i = 0; i < 2; i++)
mac[i] = (u8) (mac_high >> ((1 - i) * 8));
for (i = 2; i < 6; i++)
mac[i] = (u8) (mac_low >> ((5 - i) * 8));
} else {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to get mac address%d\n", err); "Failed to get mac address%d\n", err);
err = -EIO; err = -EIO;
} }
qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
/* Get info of a NIC partition */ /* Get info of a NIC partition */
int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
struct qlcnic_info *npar_info, u8 func_id) struct qlcnic_info *npar_info, u8 func_id)
{ {
int err; int err;
dma_addr_t nic_dma_t; dma_addr_t nic_dma_t;
struct qlcnic_info_le *nic_info; const struct qlcnic_info_le *nic_info;
void *nic_info_addr; void *nic_info_addr;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
size_t nic_size = sizeof(struct qlcnic_info_le); size_t nic_size = sizeof(struct qlcnic_info_le);
nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
&nic_dma_t, GFP_KERNEL); &nic_dma_t, GFP_KERNEL);
...@@ -713,47 +711,39 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, ...@@ -713,47 +711,39 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
memset(nic_info_addr, 0, nic_size); memset(nic_info_addr, 0, nic_size);
nic_info = nic_info_addr; nic_info = nic_info_addr;
memset(&cmd, 0, sizeof(cmd));
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_NIC_INFO;
cmd.req.arg1 = MSD(nic_dma_t);
cmd.req.arg2 = LSD(nic_dma_t);
cmd.req.arg3 = (func_id << 16 | nic_size);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err == QLCNIC_RCODE_SUCCESS) { qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO);
cmd.req.arg[1] = MSD(nic_dma_t);
cmd.req.arg[2] = LSD(nic_dma_t);
cmd.req.arg[3] = (func_id << 16 | nic_size);
err = qlcnic_issue_cmd(adapter, &cmd);
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
"Failed to get nic info%d\n", err);
err = -EIO;
} else {
npar_info->pci_func = le16_to_cpu(nic_info->pci_func); npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
npar_info->op_mode = le16_to_cpu(nic_info->op_mode); npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw);
npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw);
npar_info->phys_port = le16_to_cpu(nic_info->phys_port); npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode); npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques); npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques); npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques);
npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw);
npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw);
npar_info->capabilities = le32_to_cpu(nic_info->capabilities); npar_info->capabilities = le32_to_cpu(nic_info->capabilities);
npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu); npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu);
dev_info(&adapter->pdev->dev,
"phy port: %d switch_mode: %d,\n"
"\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n"
"\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n",
npar_info->phys_port, npar_info->switch_mode,
npar_info->max_tx_ques, npar_info->max_rx_ques,
npar_info->min_tx_bw, npar_info->max_tx_bw,
npar_info->max_mtu, npar_info->capabilities);
} else {
dev_err(&adapter->pdev->dev,
"Failed to get nic info%d\n", err);
err = -EIO;
} }
dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
nic_dma_t); nic_dma_t);
qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
/* Configure a NIC partition */ /* Configure a NIC partition */
int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
struct qlcnic_info *nic)
{ {
int err = -EIO; int err = -EIO;
dma_addr_t nic_dma_t; dma_addr_t nic_dma_t;
...@@ -784,13 +774,11 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) ...@@ -784,13 +774,11 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw); nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw);
nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw);
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO);
cmd.req.cmd = QLCNIC_CDRP_CMD_SET_NIC_INFO; cmd.req.arg[1] = MSD(nic_dma_t);
cmd.req.arg1 = MSD(nic_dma_t); cmd.req.arg[2] = LSD(nic_dma_t);
cmd.req.arg2 = LSD(nic_dma_t); cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size);
cmd.req.arg3 = ((nic->pci_func << 16) | nic_size); err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) { if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
...@@ -800,12 +788,14 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) ...@@ -800,12 +788,14 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic)
dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr,
nic_dma_t); nic_dma_t);
qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
/* Get PCI Info of a partition */ /* Get PCI Info of a partition */
int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
struct qlcnic_pci_info *pci_info) struct qlcnic_pci_info *pci_info)
{ {
int err = 0, i; int err = 0, i;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
...@@ -822,13 +812,11 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, ...@@ -822,13 +812,11 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
memset(pci_info_addr, 0, pci_size); memset(pci_info_addr, 0, pci_size);
npar = pci_info_addr; npar = pci_info_addr;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO);
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_PCI_INFO; cmd.req.arg[1] = MSD(pci_info_dma_t);
cmd.req.arg1 = MSD(pci_info_dma_t); cmd.req.arg[2] = LSD(pci_info_dma_t);
cmd.req.arg2 = LSD(pci_info_dma_t); cmd.req.arg[3] = pci_size;
cmd.req.arg3 = pci_size; err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
adapter->ahw->act_pci_func = 0; adapter->ahw->act_pci_func = 0;
if (err == QLCNIC_RCODE_SUCCESS) { if (err == QLCNIC_RCODE_SUCCESS) {
...@@ -854,6 +842,8 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, ...@@ -854,6 +842,8 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter,
dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr, dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr,
pci_info_dma_t); pci_info_dma_t);
qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
...@@ -872,21 +862,19 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, ...@@ -872,21 +862,19 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id,
arg1 = id | (enable_mirroring ? BIT_4 : 0); arg1 = id | (enable_mirroring ? BIT_4 : 0);
arg1 |= pci_func << 8; arg1 |= pci_func << 8;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORTMIRRORING);
cmd.req.cmd = QLCNIC_CDRP_CMD_SET_PORTMIRRORING; cmd.req.arg[1] = arg1;
cmd.req.arg1 = arg1; err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (err != QLCNIC_RCODE_SUCCESS) { if (err != QLCNIC_RCODE_SUCCESS)
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to configure port mirroring%d on eswitch:%d\n", "Failed to configure port mirroring%d on eswitch:%d\n",
pci_func, id); pci_func, id);
} else { else
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"Configured eSwitch %d for port mirroring:%d\n", "Configured eSwitch %d for port mirroring:%d\n",
id, pci_func); id, pci_func);
} qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
...@@ -923,13 +911,11 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, ...@@ -923,13 +911,11 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12; arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12;
arg1 |= rx_tx << 15 | stats_size << 16; arg1 |= rx_tx << 15 | stats_size << 16;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS);
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS; cmd.req.arg[1] = arg1;
cmd.req.arg1 = arg1; cmd.req.arg[2] = MSD(stats_dma_t);
cmd.req.arg2 = MSD(stats_dma_t); cmd.req.arg[3] = LSD(stats_dma_t);
cmd.req.arg3 = LSD(stats_dma_t); err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (!err) { if (!err) {
stats = stats_addr; stats = stats_addr;
...@@ -949,6 +935,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, ...@@ -949,6 +935,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
stats_dma_t); stats_dma_t);
qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
...@@ -963,6 +951,9 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, ...@@ -963,6 +951,9 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
void *stats_addr; void *stats_addr;
int err; int err;
if (mac_stats == NULL)
return -ENOMEM;
stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
&stats_dma_t, GFP_KERNEL); &stats_dma_t, GFP_KERNEL);
if (!stats_addr) { if (!stats_addr) {
...@@ -971,15 +962,11 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, ...@@ -971,15 +962,11 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
return -ENOMEM; return -ENOMEM;
} }
memset(stats_addr, 0, stats_size); memset(stats_addr, 0, stats_size);
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS);
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_MAC_STATS; cmd.req.arg[1] = stats_size << 16;
cmd.req.arg1 = stats_size << 16; cmd.req.arg[2] = MSD(stats_dma_t);
cmd.req.arg2 = MSD(stats_dma_t); cmd.req.arg[3] = LSD(stats_dma_t);
cmd.req.arg3 = LSD(stats_dma_t); err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd);
err = cmd.rsp.cmd;
if (!err) { if (!err) {
stats = stats_addr; stats = stats_addr;
mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames); mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames);
...@@ -1001,10 +988,16 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, ...@@ -1001,10 +988,16 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber); mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber);
mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped); mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped);
mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error); mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error);
} else {
dev_err(&adapter->pdev->dev,
"%s: Get mac stats failed, err=%d.\n", __func__, err);
} }
dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr,
stats_dma_t); stats_dma_t);
qlcnic_free_mbx_args(&cmd);
return err; return err;
} }
...@@ -1065,7 +1058,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, ...@@ -1065,7 +1058,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch,
int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
const u8 port, const u8 rx_tx) const u8 port, const u8 rx_tx)
{ {
int err;
u32 arg1; u32 arg1;
struct qlcnic_cmd_args cmd; struct qlcnic_cmd_args cmd;
...@@ -1088,15 +1081,16 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, ...@@ -1088,15 +1081,16 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw,
arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12; arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12;
arg1 |= BIT_14 | rx_tx << 15; arg1 |= BIT_14 | rx_tx << 15;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS);
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS; cmd.req.arg[1] = arg1;
cmd.req.arg1 = arg1; err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd); qlcnic_free_mbx_args(&cmd);
return cmd.rsp.cmd; return err;
err_ret: err_ret:
dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d" dev_err(&adapter->pdev->dev,
"rx_ctx=%d\n", func_esw, port, rx_tx); "Invalid args func_esw %d port %d rx_ctx %d\n",
func_esw, port, rx_tx);
return -EIO; return -EIO;
} }
...@@ -1109,22 +1103,21 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, ...@@ -1109,22 +1103,21 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
u8 pci_func; u8 pci_func;
pci_func = (*arg1 >> 8); pci_func = (*arg1 >> 8);
cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG; qlcnic_alloc_mbx_args(&cmd, adapter,
cmd.req.arg1 = *arg1; QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG);
cmd.rsp.arg1 = cmd.rsp.arg2 = 1; cmd.req.arg[1] = *arg1;
qlcnic_issue_cmd(adapter, &cmd); err = qlcnic_issue_cmd(adapter, &cmd);
*arg1 = cmd.rsp.arg1; *arg1 = cmd.rsp.arg[1];
*arg2 = cmd.rsp.arg2; *arg2 = cmd.rsp.arg[2];
err = cmd.rsp.cmd; qlcnic_free_mbx_args(&cmd);
if (err == QLCNIC_RCODE_SUCCESS) { if (err == QLCNIC_RCODE_SUCCESS)
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"eSwitch port config for pci func %d\n", pci_func); "eSwitch port config for pci func %d\n", pci_func);
} else { else
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to get eswitch port config for pci func %d\n", "Failed to get eswitch port config for pci func %d\n",
pci_func); pci_func);
}
return err; return err;
} }
/* Configure eSwitch port /* Configure eSwitch port
...@@ -1189,20 +1182,18 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, ...@@ -1189,20 +1182,18 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
return err; return err;
} }
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_ESWITCH);
cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH; cmd.req.arg[1] = arg1;
cmd.req.arg1 = arg1; cmd.req.arg[2] = arg2;
cmd.req.arg2 = arg2; err = qlcnic_issue_cmd(adapter, &cmd);
qlcnic_issue_cmd(adapter, &cmd); qlcnic_free_mbx_args(&cmd);
err = cmd.rsp.cmd; if (err != QLCNIC_RCODE_SUCCESS)
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Failed to configure eswitch pci func %d\n", pci_func); "Failed to configure eswitch pci func %d\n", pci_func);
} else { else
dev_info(&adapter->pdev->dev, dev_info(&adapter->pdev->dev,
"Configured eSwitch for pci func %d\n", pci_func); "Configured eSwitch for pci func %d\n", pci_func);
}
return err; return err;
} }
......
...@@ -705,20 +705,19 @@ static int qlcnic_irq_test(struct net_device *netdev) ...@@ -705,20 +705,19 @@ static int qlcnic_irq_test(struct net_device *netdev)
goto clear_it; goto clear_it;
adapter->ahw->diag_cnt = 0; adapter->ahw->diag_cnt = 0;
memset(&cmd, 0, sizeof(cmd)); qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST);
cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST;
cmd.req.arg1 = adapter->ahw->pci_func; cmd.req.arg[1] = adapter->ahw->pci_func;
qlcnic_issue_cmd(adapter, &cmd); ret = qlcnic_issue_cmd(adapter, &cmd);
ret = cmd.rsp.cmd;
if (ret) if (ret)
goto done; goto done;
msleep(10); usleep_range(1000, 12000);
ret = !adapter->ahw->diag_cnt; ret = !adapter->ahw->diag_cnt;
done: done:
qlcnic_free_mbx_args(&cmd);
qlcnic_diag_free_res(netdev, max_sds_rings); qlcnic_diag_free_res(netdev, max_sds_rings);
clear_it: clear_it:
...@@ -845,7 +844,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) ...@@ -845,7 +844,7 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode)
ret = qlcnic_do_lb_test(adapter, mode); ret = qlcnic_do_lb_test(adapter, mode);
qlcnic_clear_lb_mode(adapter); qlcnic_clear_lb_mode(adapter, mode);
free_res: free_res:
qlcnic_diag_free_res(netdev, max_sds_rings); qlcnic_diag_free_res(netdev, max_sds_rings);
...@@ -1307,7 +1306,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) ...@@ -1307,7 +1306,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
return 0; return 0;
} }
netdev_info(netdev, "Forcing a FW dump\n"); netdev_info(netdev, "Forcing a FW dump\n");
qlcnic_dev_request_reset(adapter); qlcnic_dev_request_reset(adapter, 0);
break; break;
case QLCNIC_DISABLE_FW_DUMP: case QLCNIC_DISABLE_FW_DUMP:
if (fw_dump->enable && fw_dump->tmpl_hdr) { if (fw_dump->enable && fw_dump->tmpl_hdr) {
...@@ -1327,7 +1326,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) ...@@ -1327,7 +1326,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
return 0; return 0;
case QLCNIC_FORCE_FW_RESET: case QLCNIC_FORCE_FW_RESET:
netdev_info(netdev, "Forcing a FW reset\n"); netdev_info(netdev, "Forcing a FW reset\n");
qlcnic_dev_request_reset(adapter); qlcnic_dev_request_reset(adapter, 0);
adapter->flags &= ~QLCNIC_FW_RESET_OWNER; adapter->flags &= ~QLCNIC_FW_RESET_OWNER;
return 0; return 0;
case QLCNIC_SET_QUIESCENT: case QLCNIC_SET_QUIESCENT:
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
#include "qlcnic_hw.h"
/* /*
* The basic unit of access when reading/writing control registers. * The basic unit of access when reading/writing control registers.
*/ */
...@@ -568,6 +570,9 @@ enum { ...@@ -568,6 +570,9 @@ enum {
#define QLCNIC_REG(X) (NIC_CRB_BASE+(X)) #define QLCNIC_REG(X) (NIC_CRB_BASE+(X))
#define QLCNIC_REG_2(X) (NIC_CRB_BASE_2+(X)) #define QLCNIC_REG_2(X) (NIC_CRB_BASE_2+(X))
#define QLCNIC_CDRP_MAX_ARGS 4
#define QLCNIC_CDRP_ARG(i) (QLCNIC_REG(0x18 + ((i) * 4)))
#define QLCNIC_CDRP_CRB_OFFSET (QLCNIC_REG(0x18)) #define QLCNIC_CDRP_CRB_OFFSET (QLCNIC_REG(0x18))
#define QLCNIC_ARG1_CRB_OFFSET (QLCNIC_REG(0x1c)) #define QLCNIC_ARG1_CRB_OFFSET (QLCNIC_REG(0x1c))
#define QLCNIC_ARG2_CRB_OFFSET (QLCNIC_REG(0x20)) #define QLCNIC_ARG2_CRB_OFFSET (QLCNIC_REG(0x20))
......
...@@ -417,9 +417,8 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, ...@@ -417,9 +417,8 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
return 0; return 0;
} }
static int int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, __le16 vlan_id, u8 op)
__le16 vlan_id, unsigned op)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
struct qlcnic_mac_req *mac_req; struct qlcnic_mac_req *mac_req;
...@@ -516,7 +515,7 @@ void qlcnic_set_multi(struct net_device *netdev) ...@@ -516,7 +515,7 @@ void qlcnic_set_multi(struct net_device *netdev)
qlcnic_nic_set_promisc(adapter, mode); qlcnic_nic_set_promisc(adapter, mode);
} }
int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
u64 word; u64 word;
...@@ -620,12 +619,13 @@ static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag) ...@@ -620,12 +619,13 @@ static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag)
return rv; return rv;
} }
int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) int qlcnic_82xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
{ {
if (qlcnic_set_fw_loopback(adapter, mode)) if (qlcnic_set_fw_loopback(adapter, mode))
return -EIO; return -EIO;
if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) { if (qlcnic_nic_set_promisc(adapter,
VPORT_MISS_MODE_ACCEPT_ALL)) {
qlcnic_set_fw_loopback(adapter, 0); qlcnic_set_fw_loopback(adapter, 0);
return -EIO; return -EIO;
} }
...@@ -634,11 +634,11 @@ int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) ...@@ -634,11 +634,11 @@ int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
return 0; return 0;
} }
void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter) int qlcnic_82xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode)
{ {
int mode = VPORT_MISS_MODE_DROP;
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
mode = VPORT_MISS_MODE_DROP;
qlcnic_set_fw_loopback(adapter, 0); qlcnic_set_fw_loopback(adapter, 0);
if (netdev->flags & IFF_PROMISC) if (netdev->flags & IFF_PROMISC)
...@@ -648,12 +648,13 @@ void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter) ...@@ -648,12 +648,13 @@ void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter)
qlcnic_nic_set_promisc(adapter, mode); qlcnic_nic_set_promisc(adapter, mode);
msleep(1000); msleep(1000);
return 0;
} }
/* /*
* Send the interrupt coalescing parameter set by ethtool to the card. * Send the interrupt coalescing parameter set by ethtool to the card.
*/ */
int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter) void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
int rv; int rv;
...@@ -675,10 +676,9 @@ int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter) ...@@ -675,10 +676,9 @@ int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter)
if (rv != 0) if (rv != 0)
dev_err(&adapter->netdev->dev, dev_err(&adapter->netdev->dev,
"Could not send interrupt coalescing parameters\n"); "Could not send interrupt coalescing parameters\n");
return rv;
} }
int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable) int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
u64 word; u64 word;
...@@ -736,7 +736,7 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) ...@@ -736,7 +736,7 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable)
#define RSS_HASHTYPE_IP_TCP 0x3 #define RSS_HASHTYPE_IP_TCP 0x3
int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable) int qlcnic_82xx_config_rss(struct qlcnic_adapter *adapter, int enable)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
u64 word; u64 word;
...@@ -779,7 +779,8 @@ int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable) ...@@ -779,7 +779,8 @@ int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable)
return rv; return rv;
} }
int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd) void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter,
__be32 ip, int cmd)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
struct qlcnic_ipaddr *ipa; struct qlcnic_ipaddr *ipa;
...@@ -801,23 +802,19 @@ int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd) ...@@ -801,23 +802,19 @@ int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd)
dev_err(&adapter->netdev->dev, dev_err(&adapter->netdev->dev,
"could not notify %s IP 0x%x reuqest\n", "could not notify %s IP 0x%x reuqest\n",
(cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip); (cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip);
return rv;
} }
int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable) int qlcnic_82xx_linkevent_request(struct qlcnic_adapter *adapter, int enable)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
u64 word; u64 word;
int rv; int rv;
memset(&req, 0, sizeof(struct qlcnic_nic_req)); memset(&req, 0, sizeof(struct qlcnic_nic_req));
req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23);
word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16);
req.req_hdr = cpu_to_le64(word); req.req_hdr = cpu_to_le64(word);
req.words[0] = cpu_to_le64(enable | (enable << 8)); req.words[0] = cpu_to_le64(enable | (enable << 8));
rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
if (rv != 0) if (rv != 0)
dev_err(&adapter->netdev->dev, dev_err(&adapter->netdev->dev,
...@@ -981,8 +978,8 @@ qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off) ...@@ -981,8 +978,8 @@ qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off)
return 0; return 0;
} }
int int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off,
qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) u32 data)
{ {
unsigned long flags; unsigned long flags;
int rv; int rv;
...@@ -1013,7 +1010,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) ...@@ -1013,7 +1010,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data)
return -EIO; return -EIO;
} }
int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
{ {
unsigned long flags; unsigned long flags;
int rv; int rv;
...@@ -1042,7 +1039,6 @@ int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) ...@@ -1042,7 +1039,6 @@ int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off)
return -1; return -1;
} }
void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw,
u32 offset) u32 offset)
{ {
...@@ -1268,7 +1264,7 @@ int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data) ...@@ -1268,7 +1264,7 @@ int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data)
return ret; return ret;
} }
int qlcnic_get_board_info(struct qlcnic_adapter *adapter) int qlcnic_82xx_get_board_info(struct qlcnic_adapter *adapter)
{ {
int offset, board_type, magic; int offset, board_type, magic;
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
...@@ -1341,7 +1337,7 @@ qlcnic_wol_supported(struct qlcnic_adapter *adapter) ...@@ -1341,7 +1337,7 @@ qlcnic_wol_supported(struct qlcnic_adapter *adapter)
return 0; return 0;
} }
int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
{ {
struct qlcnic_nic_req req; struct qlcnic_nic_req req;
int rv; int rv;
...@@ -1362,3 +1358,56 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) ...@@ -1362,3 +1358,56 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate)
return rv; return rv;
} }
void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter)
{
void __iomem *msix_base_addr;
u32 func;
u32 msix_base;
pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func);
msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE;
msix_base = readl(msix_base_addr);
func = (func - msix_base) / QLCNIC_MSIX_TBL_PGSIZE;
adapter->ahw->pci_func = func;
}
void qlcnic_82xx_read_crb(struct qlcnic_adapter *adapter, char *buf,
loff_t offset, size_t size)
{
u32 data;
u64 qmdata;
if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata);
memcpy(buf, &qmdata, size);
} else {
data = QLCRD32(adapter, offset);
memcpy(buf, &data, size);
}
}
void qlcnic_82xx_write_crb(struct qlcnic_adapter *adapter, char *buf,
loff_t offset, size_t size)
{
u32 data;
u64 qmdata;
if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) {
memcpy(&qmdata, buf, size);
qlcnic_pci_camqm_write_2M(adapter, offset, qmdata);
} else {
memcpy(&data, buf, size);
QLCWR32(adapter, offset, data);
}
}
int qlcnic_82xx_api_lock(struct qlcnic_adapter *adapter)
{
return qlcnic_pcie_sem_lock(adapter, 5, 0);
}
void qlcnic_82xx_api_unlock(struct qlcnic_adapter *adapter)
{
qlcnic_pcie_sem_unlock(adapter, 5);
}
#ifndef __QLCNIC_HW_H
#define __QLCNIC_HW_H
/* Common registers in 83xx and 82xx */
enum qlcnic_regs {
QLCNIC_PEG_HALT_STATUS1 = 0,
QLCNIC_PEG_HALT_STATUS2,
QLCNIC_PEG_ALIVE_COUNTER,
QLCNIC_FLASH_LOCK_OWNER,
QLCNIC_FW_CAPABILITIES,
QLCNIC_CRB_DRV_ACTIVE,
QLCNIC_CRB_DEV_STATE,
QLCNIC_CRB_DRV_STATE,
QLCNIC_CRB_DRV_SCRATCH,
QLCNIC_CRB_DEV_PARTITION_INFO,
QLCNIC_CRB_DRV_IDC_VER,
QLCNIC_FW_VERSION_MAJOR,
QLCNIC_FW_VERSION_MINOR,
QLCNIC_FW_VERSION_SUB,
QLCNIC_CRB_DEV_NPAR_STATE,
QLCNIC_FW_IMG_VALID,
QLCNIC_CMDPEG_STATE,
QLCNIC_RCVPEG_STATE,
QLCNIC_ASIC_TEMP,
QLCNIC_FW_API,
QLCNIC_DRV_OP_MODE,
QLCNIC_FLASH_LOCK,
QLCNIC_FLASH_UNLOCK,
};
#define QLCNIC_CMD_CONFIGURE_IP_ADDR 0x1
#define QLCNIC_CMD_CONFIG_INTRPT 0x2
#define QLCNIC_CMD_CREATE_RX_CTX 0x7
#define QLCNIC_CMD_DESTROY_RX_CTX 0x8
#define QLCNIC_CMD_CREATE_TX_CTX 0x9
#define QLCNIC_CMD_DESTROY_TX_CTX 0xa
#define QLCNIC_CMD_CONFIGURE_LRO 0xC
#define QLCNIC_CMD_CONFIGURE_MAC_LEARNING 0xD
#define QLCNIC_CMD_GET_STATISTICS 0xF
#define QLCNIC_CMD_INTRPT_TEST 0x11
#define QLCNIC_CMD_SET_MTU 0x12
#define QLCNIC_CMD_READ_PHY 0x13
#define QLCNIC_CMD_WRITE_PHY 0x14
#define QLCNIC_CMD_READ_HW_REG 0x15
#define QLCNIC_CMD_GET_FLOW_CTL 0x16
#define QLCNIC_CMD_SET_FLOW_CTL 0x17
#define QLCNIC_CMD_READ_MAX_MTU 0x18
#define QLCNIC_CMD_READ_MAX_LRO 0x19
#define QLCNIC_CMD_MAC_ADDRESS 0x1f
#define QLCNIC_CMD_GET_PCI_INFO 0x20
#define QLCNIC_CMD_GET_NIC_INFO 0x21
#define QLCNIC_CMD_SET_NIC_INFO 0x22
#define QLCNIC_CMD_GET_ESWITCH_CAPABILITY 0x24
#define QLCNIC_CMD_TOGGLE_ESWITCH 0x25
#define QLCNIC_CMD_GET_ESWITCH_STATUS 0x26
#define QLCNIC_CMD_SET_PORTMIRRORING 0x27
#define QLCNIC_CMD_CONFIGURE_ESWITCH 0x28
#define QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG 0x29
#define QLCNIC_CMD_GET_ESWITCH_STATS 0x2a
#define QLCNIC_CMD_CONFIG_PORT 0x2e
#define QLCNIC_CMD_TEMP_SIZE 0x2f
#define QLCNIC_CMD_GET_TEMP_HDR 0x30
#define QLCNIC_CMD_GET_MAC_STATS 0x37
#define QLCNIC_CMD_SET_DRV_VER 0x38
#define QLCNIC_CMD_CONFIGURE_RSS 0x41
#define QLCNIC_CMD_CONFIG_INTR_COAL 0x43
#define QLCNIC_CMD_CONFIGURE_LED 0x44
#define QLCNIC_CMD_CONFIG_MAC_VLAN 0x45
#define QLCNIC_CMD_GET_LINK_EVENT 0x48
#define QLCNIC_CMD_CONFIGURE_MAC_RX_MODE 0x49
#define QLCNIC_CMD_CONFIGURE_HW_LRO 0x4A
#define QLCNIC_CMD_INIT_NIC_FUNC 0x60
#define QLCNIC_CMD_STOP_NIC_FUNC 0x61
#define QLCNIC_CMD_IDC_ACK 0x63
#define QLCNIC_CMD_SET_PORT_CONFIG 0x66
#define QLCNIC_CMD_GET_PORT_CONFIG 0x67
#define QLCNIC_CMD_GET_LINK_STATUS 0x68
#define QLCNIC_CMD_SET_LED_CONFIG 0x69
#define QLCNIC_CMD_GET_LED_CONFIG 0x6A
#define QLCNIC_INTRPT_INTX 1
#define QLCNIC_INTRPT_MSIX 3
#define QLCNIC_INTRPT_ADD 1
#define QLCNIC_INTRPT_DEL 2
#define QLCNIC_GET_CURRENT_MAC 1
#define QLCNIC_SET_STATION_MAC 2
#define QLCNIC_GET_DEFAULT_MAC 3
#define QLCNIC_GET_FAC_DEF_MAC 4
#define QLCNIC_SET_FAC_DEF_MAC 5
#define QLCNIC_MBX_LINK_EVENT 0x8001
#define QLCNIC_MBX_COMP_EVENT 0x8100
#define QLCNIC_MBX_REQUEST_EVENT 0x8101
#define QLCNIC_MBX_TIME_EXTEND_EVENT 0x8102
#define QLCNIC_MBX_SFP_INSERT_EVENT 0x8130
#define QLCNIC_MBX_SFP_REMOVE_EVENT 0x8131
struct qlcnic_mailbox_metadata {
u32 cmd;
u32 in_args;
u32 out_args;
};
#define QLCNIC_MBX_RSP_OK 1
#define QLCNIC_MBX_PORT_RSP_OK 0x1a
struct qlcnic_pci_info;
struct qlcnic_info;
struct qlcnic_cmd_args;
struct ethtool_stats;
struct pci_device_id;
struct qlcnic_host_sds_ring;
struct qlcnic_host_tx_ring;
struct qlcnic_host_tx_ring;
struct qlcnic_hardware_context;
struct qlcnic_adapter;
int qlcnic_82xx_start_firmware(struct qlcnic_adapter *);
int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong);
int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32);
int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int);
int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32);
int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
struct net_device *netdev);
void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter,
u64 *uaddr, __le16 vlan_id);
void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter);
int qlcnic_82xx_config_rss(struct qlcnic_adapter *adapter, int);
void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter,
__be32, int);
int qlcnic_82xx_linkevent_request(struct qlcnic_adapter *adapter, int);
void qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring);
int qlcnic_82xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8);
int qlcnic_82xx_set_lb_mode(struct qlcnic_adapter *, u8);
void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t);
void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32);
int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8);
irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *);
int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter,
struct qlcnic_cmd_args *);
int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *);
int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *,
struct qlcnic_host_tx_ring *tx_ring, int);
int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8);
int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*);
int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8);
int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *);
int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*);
int qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args *,
struct qlcnic_adapter *, u32);
int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32);
int qlcnic_82xx_get_board_info(struct qlcnic_adapter *);
int qlcnic_82xx_config_led(struct qlcnic_adapter *, u32, u32);
void qlcnic_82xx_get_func_no(struct qlcnic_adapter *);
int qlcnic_82xx_api_lock(struct qlcnic_adapter *);
void qlcnic_82xx_api_unlock(struct qlcnic_adapter *);
void qlcnic_82xx_napi_enable(struct qlcnic_adapter *);
void qlcnic_82xx_napi_disable(struct qlcnic_adapter *);
#endif /* __QLCNIC_HW_H_ */
...@@ -95,14 +95,14 @@ ...@@ -95,14 +95,14 @@
#define STATUS_CKSUM_LOOP 0 #define STATUS_CKSUM_LOOP 0
#define STATUS_CKSUM_OK 2 #define STATUS_CKSUM_OK 2
static void qlcnic_change_filter(struct qlcnic_adapter *adapter, void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr,
u64 uaddr, __le16 vlan_id, __le16 vlan_id)
struct qlcnic_host_tx_ring *tx_ring)
{ {
struct cmd_desc_type0 *hwdesc; struct cmd_desc_type0 *hwdesc;
struct qlcnic_nic_req *req; struct qlcnic_nic_req *req;
struct qlcnic_mac_req *mac_req; struct qlcnic_mac_req *mac_req;
struct qlcnic_vlan_req *vlan_req; struct qlcnic_vlan_req *vlan_req;
struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring;
u32 producer; u32 producer;
u64 word; u64 word;
...@@ -132,21 +132,21 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, ...@@ -132,21 +132,21 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
struct cmd_desc_type0 *first_desc, struct cmd_desc_type0 *first_desc,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ethhdr *phdr = (struct ethhdr *)(skb->data);
struct qlcnic_filter *fil, *tmp_fil; struct qlcnic_filter *fil, *tmp_fil;
struct hlist_node *tmp_hnode, *n; struct hlist_node *tmp_hnode, *n;
struct hlist_head *head; struct hlist_head *head;
struct ethhdr *phdr = (struct ethhdr *)(skb->data);
u64 src_addr = 0; u64 src_addr = 0;
__le16 vlan_id = 0; __le16 vlan_id = 0;
u8 hindex; u8 hindex;
if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
return; return;
if (adapter->fhash.fnum >= adapter->fhash.fmax) if (adapter->fhash.fnum >= adapter->fhash.fmax)
return; return;
/* Only NPAR capable devices support vlan based learning*/ /* Only NPAR capable devices support vlan based learning */
if (adapter->flags & QLCNIC_ESWITCH_ENABLED) if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
vlan_id = first_desc->vlan_TCI; vlan_id = first_desc->vlan_TCI;
memcpy(&src_addr, phdr->h_source, ETH_ALEN); memcpy(&src_addr, phdr->h_source, ETH_ALEN);
...@@ -155,11 +155,10 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, ...@@ -155,11 +155,10 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) &&
tmp_fil->vlan_id == vlan_id) { tmp_fil->vlan_id == vlan_id) {
if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime)) if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime))
qlcnic_change_filter(adapter, src_addr, vlan_id, qlcnic_change_filter(adapter, &src_addr,
tx_ring); vlan_id);
tmp_fil->ftime = jiffies; tmp_fil->ftime = jiffies;
return; return;
} }
...@@ -169,17 +168,13 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, ...@@ -169,17 +168,13 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter,
if (!fil) if (!fil)
return; return;
qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring); qlcnic_change_filter(adapter, &src_addr, vlan_id);
fil->ftime = jiffies; fil->ftime = jiffies;
fil->vlan_id = vlan_id; fil->vlan_id = vlan_id;
memcpy(fil->faddr, &src_addr, ETH_ALEN); memcpy(fil->faddr, &src_addr, ETH_ALEN);
spin_lock(&adapter->mac_learn_lock); spin_lock(&adapter->mac_learn_lock);
hlist_add_head(&(fil->fnode), head); hlist_add_head(&(fil->fnode), head);
adapter->fhash.fnum++; adapter->fhash.fnum++;
spin_unlock(&adapter->mac_learn_lock); spin_unlock(&adapter->mac_learn_lock);
} }
...@@ -492,7 +487,8 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ...@@ -492,7 +487,8 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) static void qlcnic_advert_link_change(struct qlcnic_adapter *adapter,
int linkup)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
...@@ -1180,7 +1176,7 @@ static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring, ...@@ -1180,7 +1176,7 @@ static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring,
return; return;
} }
void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) void qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
{ {
struct qlcnic_adapter *adapter = sds_ring->adapter; struct qlcnic_adapter *adapter = sds_ring->adapter;
struct status_desc *desc; struct status_desc *desc;
...@@ -1217,26 +1213,8 @@ void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) ...@@ -1217,26 +1213,8 @@ void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring)
writel(consumer, sds_ring->crb_sts_consumer); writel(consumer, sds_ring->crb_sts_consumer);
} }
void qlcnic_fetch_mac(u32 off1, u32 off2, u8 alt_mac, u8 *mac) int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter,
{ struct net_device *netdev)
u32 mac_low, mac_high;
int i;
mac_low = off1;
mac_high = off2;
if (alt_mac) {
mac_low |= (mac_low >> 16) | (mac_high << 16);
mac_high >>= 16;
}
for (i = 0; i < 2; i++)
mac[i] = (u8)(mac_high >> ((1 - i) * 8));
for (i = 2; i < 6; i++)
mac[i] = (u8)(mac_low >> ((5 - i) * 8));
}
int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev)
{ {
int ring, max_sds_rings; int ring, max_sds_rings;
struct qlcnic_host_sds_ring *sds_ring; struct qlcnic_host_sds_ring *sds_ring;
...@@ -1275,7 +1253,7 @@ void qlcnic_napi_del(struct qlcnic_adapter *adapter) ...@@ -1275,7 +1253,7 @@ void qlcnic_napi_del(struct qlcnic_adapter *adapter)
qlcnic_free_sds_rings(adapter->recv_ctx); qlcnic_free_sds_rings(adapter->recv_ctx);
} }
void qlcnic_napi_enable(struct qlcnic_adapter *adapter) void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter)
{ {
int ring; int ring;
struct qlcnic_host_sds_ring *sds_ring; struct qlcnic_host_sds_ring *sds_ring;
...@@ -1291,7 +1269,7 @@ void qlcnic_napi_enable(struct qlcnic_adapter *adapter) ...@@ -1291,7 +1269,7 @@ void qlcnic_napi_enable(struct qlcnic_adapter *adapter)
} }
} }
void qlcnic_napi_disable(struct qlcnic_adapter *adapter) void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter)
{ {
int ring; int ring;
struct qlcnic_host_sds_ring *sds_ring; struct qlcnic_host_sds_ring *sds_ring;
......
...@@ -120,6 +120,32 @@ static const u32 msi_tgt_status[8] = { ...@@ -120,6 +120,32 @@ static const u32 msi_tgt_status[8] = {
ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7 ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7
}; };
static const u32 qlcnic_reg_tbl[] = {
0x1B20A8, /* PEG_HALT_STAT1 */
0x1B20AC, /* PEG_HALT_STAT2 */
0x1B20B0, /* FW_HEARTBEAT */
0x1B2100, /* LOCK ID */
0x1B2128, /* FW_CAPABILITIES */
0x1B2138, /* drv active */
0x1B2140, /* dev state */
0x1B2144, /* drv state */
0x1B2148, /* drv scratch */
0x1B214C, /* dev partition info */
0x1B2174, /* drv idc ver */
0x1B2150, /* fw version major */
0x1B2154, /* fw version minor */
0x1B2158, /* fw version sub */
0x1B219C, /* npar state */
0x1B21FC, /* FW_IMG_VALID */
0x1B2250, /* CMD_PEG_STATE */
0x1B233C, /* RCV_PEG_STATE */
0x1B23B4, /* ASIC TEMP */
0x1B216C, /* FW api */
0x1B2170, /* drv op mode */
0x13C010, /* flash lock */
0x13C014, /* flash unlock */
};
static const struct qlcnic_board_info qlcnic_boards[] = { static const struct qlcnic_board_info qlcnic_boards[] = {
{0x1077, 0x8020, 0x1077, 0x203, {0x1077, 0x8020, 0x1077, 0x203,
"8200 Series Single Port 10GbE Converged Network Adapter" "8200 Series Single Port 10GbE Converged Network Adapter"
...@@ -164,11 +190,6 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx) ...@@ -164,11 +190,6 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx)
recv_ctx->sds_rings = NULL; recv_ctx->sds_rings = NULL;
} }
static void qlcnic_clear_stats(struct qlcnic_adapter *adapter)
{
memset(&adapter->stats, 0, sizeof(adapter->stats));
}
static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable) static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable)
{ {
u32 control; u32 control;
...@@ -243,6 +264,14 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) ...@@ -243,6 +264,14 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
return 0; return 0;
} }
static void qlcnic_82xx_cancel_idc_work(struct qlcnic_adapter *adapter)
{
while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
usleep_range(10000, 11000);
cancel_delayed_work_sync(&adapter->fw_work);
}
static const struct net_device_ops qlcnic_netdev_ops = { static const struct net_device_ops qlcnic_netdev_ops = {
.ndo_open = qlcnic_open, .ndo_open = qlcnic_open,
.ndo_stop = qlcnic_close, .ndo_stop = qlcnic_close,
...@@ -267,15 +296,54 @@ static const struct net_device_ops qlcnic_netdev_failed_ops = { ...@@ -267,15 +296,54 @@ static const struct net_device_ops qlcnic_netdev_failed_ops = {
}; };
static struct qlcnic_nic_template qlcnic_ops = { static struct qlcnic_nic_template qlcnic_ops = {
.config_bridged_mode = qlcnic_config_bridged_mode, .config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led, .config_led = qlcnic_82xx_config_led,
.start_firmware = qlcnic_start_firmware .start_firmware = qlcnic_82xx_start_firmware,
.request_reset = qlcnic_82xx_dev_request_reset,
.cancel_idc_work = qlcnic_82xx_cancel_idc_work,
.napi_add = qlcnic_82xx_napi_add,
.config_ipaddr = qlcnic_82xx_config_ipaddr,
.clear_legacy_intr = qlcnic_82xx_clear_legacy_intr,
};
struct qlcnic_nic_template qlcnic_vf_ops = {
.config_bridged_mode = qlcnicvf_config_bridged_mode,
.config_led = qlcnicvf_config_led,
.start_firmware = qlcnicvf_start_firmware
}; };
static struct qlcnic_nic_template qlcnic_vf_ops = { static struct qlcnic_hardware_ops qlcnic_hw_ops = {
.config_bridged_mode = qlcnicvf_config_bridged_mode, .read_crb = qlcnic_82xx_read_crb,
.config_led = qlcnicvf_config_led, .write_crb = qlcnic_82xx_write_crb,
.start_firmware = qlcnicvf_start_firmware .read_reg = qlcnic_82xx_hw_read_wx_2M,
.write_reg = qlcnic_82xx_hw_write_wx_2M,
.get_mac_address = qlcnic_82xx_get_mac_address,
.setup_intr = qlcnic_82xx_setup_intr,
.alloc_mbx_args = qlcnic_82xx_alloc_mbx_args,
.mbx_cmd = qlcnic_82xx_issue_cmd,
.get_func_no = qlcnic_82xx_get_func_no,
.api_lock = qlcnic_82xx_api_lock,
.api_unlock = qlcnic_82xx_api_unlock,
.add_sysfs = qlcnic_82xx_add_sysfs,
.remove_sysfs = qlcnic_82xx_remove_sysfs,
.process_lb_rcv_ring_diag = qlcnic_82xx_process_rcv_ring_diag,
.create_rx_ctx = qlcnic_82xx_fw_cmd_create_rx_ctx,
.create_tx_ctx = qlcnic_82xx_fw_cmd_create_tx_ctx,
.setup_link_event = qlcnic_82xx_linkevent_request,
.get_nic_info = qlcnic_82xx_get_nic_info,
.get_pci_info = qlcnic_82xx_get_pci_info,
.set_nic_info = qlcnic_82xx_set_nic_info,
.change_macvlan = qlcnic_82xx_sre_macaddr_change,
.napi_enable = qlcnic_82xx_napi_enable,
.napi_disable = qlcnic_82xx_napi_disable,
.config_intr_coal = qlcnic_82xx_config_intr_coalesce,
.config_rss = qlcnic_82xx_config_rss,
.config_hw_lro = qlcnic_82xx_config_hw_lro,
.config_loopback = qlcnic_82xx_set_lb_mode,
.clear_loopback = qlcnic_82xx_clear_lb_mode,
.config_promisc_mode = qlcnic_82xx_nic_set_promisc,
.change_l2_filter = qlcnic_82xx_change_filter,
.get_board_info = qlcnic_82xx_get_board_info,
}; };
static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix)
...@@ -338,21 +406,25 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) ...@@ -338,21 +406,25 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter)
adapter->msix_entries[0].vector = pdev->irq; adapter->msix_entries[0].vector = pdev->irq;
} }
static void int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr)
qlcnic_setup_intr(struct qlcnic_adapter *adapter)
{ {
int num_msix; int num_msix, err;
if (adapter->ahw->msix_supported) { if (!num_intr)
num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS;
if (adapter->ahw->msix_supported)
num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(),
QLCNIC_DEF_NUM_STS_DESC_RINGS)); num_intr));
} else else
num_msix = 1; num_msix = 1;
if (!qlcnic_enable_msix(adapter, num_msix)) err = qlcnic_enable_msix(adapter, num_msix);
return; if (err == -ENOMEM || !err)
return err;
qlcnic_enable_msi_legacy(adapter); qlcnic_enable_msi_legacy(adapter);
return 0;
} }
static void static void
...@@ -371,6 +443,34 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) ...@@ -371,6 +443,34 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter)
iounmap(adapter->ahw->pci_base0); iounmap(adapter->ahw->pci_base0);
} }
static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter)
{
struct qlcnic_pci_info *pci_info;
int ret;
if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) {
switch (adapter->ahw->port_type) {
case QLCNIC_GBE:
adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_GBE_PORTS;
break;
case QLCNIC_XGBE:
adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_XG_PORTS;
break;
}
return 0;
}
if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC)
return 0;
pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL);
if (!pci_info)
return -ENOMEM;
ret = qlcnic_get_pci_info(adapter, pci_info);
kfree(pci_info);
return ret;
}
static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
{ {
struct qlcnic_pci_info *pci_info; struct qlcnic_pci_info *pci_info;
...@@ -547,6 +647,7 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, ...@@ -547,6 +647,7 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev,
} }
dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20));
ahw->pci_base0 = mem_ptr0; ahw->pci_base0 = mem_ptr0;
ahw->pci_len0 = pci_len0; ahw->pci_len0 = pci_len0;
offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func)); offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func));
...@@ -944,8 +1045,7 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter) ...@@ -944,8 +1045,7 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
return err; return err;
} }
static int int qlcnic_82xx_start_firmware(struct qlcnic_adapter *adapter)
qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{ {
int err; int err;
...@@ -1493,13 +1593,13 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count) ...@@ -1493,13 +1593,13 @@ qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count)
return -ENOMEM; return -ENOMEM;
} }
static int static int __devinit
qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
struct net_device *netdev = NULL; struct net_device *netdev = NULL;
struct qlcnic_adapter *adapter = NULL; struct qlcnic_adapter *adapter = NULL;
struct qlcnic_hardware_context *ahw;
int err, pci_using_dac = -1; int err, pci_using_dac = -1;
uint8_t revision_id;
char board_name[QLCNIC_MAX_BOARD_NAME_LEN]; char board_name[QLCNIC_MAX_BOARD_NAME_LEN];
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
...@@ -1522,10 +1622,23 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1522,10 +1622,23 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev); pci_set_master(pdev);
pci_enable_pcie_error_reporting(pdev); pci_enable_pcie_error_reporting(pdev);
ahw = kzalloc(sizeof(struct qlcnic_hardware_context), GFP_KERNEL);
if (!ahw)
goto err_out_free_res;
if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X) {
ahw->hw_ops = &qlcnic_hw_ops;
ahw->reg_tbl = (u32 *)qlcnic_reg_tbl;
}
err = qlcnic_setup_pci_map(pdev, ahw);
if (err)
goto err_out_free_hw_res;
netdev = alloc_etherdev(sizeof(struct qlcnic_adapter)); netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
if (!netdev) { if (!netdev) {
err = -ENOMEM; err = -ENOMEM;
goto err_out_free_res; goto err_out_iounmap;
} }
SET_NETDEV_DEV(netdev, &pdev->dev); SET_NETDEV_DEV(netdev, &pdev->dev);
...@@ -1539,9 +1652,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1539,9 +1652,9 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_netdev; goto err_out_free_netdev;
adapter->dev_rst_time = jiffies; adapter->dev_rst_time = jiffies;
revision_id = pdev->revision; adapter->ahw->revision_id = pdev->revision;
adapter->ahw->revision_id = revision_id;
adapter->mac_learn = qlcnic_mac_learn; adapter->mac_learn = qlcnic_mac_learn;
adapter->max_drv_tx_rings = 1;
rwlock_init(&adapter->ahw->crb_lock); rwlock_init(&adapter->ahw->crb_lock);
mutex_init(&adapter->ahw->mem_lock); mutex_init(&adapter->ahw->mem_lock);
...@@ -1549,31 +1662,20 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1549,31 +1662,20 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
spin_lock_init(&adapter->tx_clean_lock); spin_lock_init(&adapter->tx_clean_lock);
INIT_LIST_HEAD(&adapter->mac_list); INIT_LIST_HEAD(&adapter->mac_list);
err = qlcnic_setup_pci_map(pdev, adapter->ahw); if (qlcnic_82xx_check(adapter)) {
if (err) qlcnic_check_vf(adapter);
goto err_out_free_hw; adapter->portnum = adapter->ahw->pci_func;
qlcnic_check_vf(adapter); err = qlcnic_start_firmware(adapter);
if (err) {
/* This will be reset for mezz cards */ dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n");
adapter->portnum = adapter->ahw->pci_func; goto err_out_free_hw;
}
err = qlcnic_get_board_info(adapter);
if (err) {
dev_err(&pdev->dev, "Error getting board config info.\n");
goto err_out_iounmap;
}
err = qlcnic_setup_idc_param(adapter);
if (err)
goto err_out_iounmap;
adapter->flags |= QLCNIC_NEED_FLR; err = qlcnic_setup_idc_param(adapter);
if (err)
goto err_out_free_hw;
err = adapter->nic_ops->start_firmware(adapter); adapter->flags |= QLCNIC_NEED_FLR;
if (err) {
dev_err(&pdev->dev, "Loading fw failed. Please Reboot\n"
"\t\tIf reboot doesn't help, try flashing the card\n");
goto err_out_maintenance_mode;
} }
if (qlcnic_read_mac_addr(adapter)) if (qlcnic_read_mac_addr(adapter))
...@@ -1585,18 +1687,18 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1585,18 +1687,18 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
module_name(THIS_MODULE), module_name(THIS_MODULE),
board_name, adapter->ahw->revision_id); board_name, adapter->ahw->revision_id);
} }
qlcnic_clear_stats(adapter);
err = qlcnic_alloc_msix_entries(adapter, adapter->ahw->max_rx_ques); err = qlcnic_alloc_msix_entries(adapter, adapter->ahw->max_rx_ques);
if (err) if (err)
goto err_out_decr_ref; goto err_out_disable_msi;
err = qlcnic_setup_intr(adapter, 0);
if (err)
goto err_out_disable_msi;
qlcnic_setup_intr(adapter);
err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac); err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac);
if (err) if (err)
goto err_out_disable_msi; goto err_out_disable_mbx_intr;
pci_set_drvdata(pdev, adapter); pci_set_drvdata(pdev, adapter);
...@@ -1615,29 +1717,35 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1615,29 +1717,35 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break; break;
} }
if (qlcnic_get_act_pci_func(adapter))
goto err_out_disable_mbx_intr;
if (adapter->mac_learn) if (adapter->mac_learn)
qlcnic_alloc_lb_filters_mem(adapter); qlcnic_alloc_lb_filters_mem(adapter);
qlcnic_create_diag_entries(adapter); qlcnic_add_sysfs(adapter);
return 0; return 0;
err_out_disable_mbx_intr:
err_out_disable_msi: err_out_disable_msi:
qlcnic_teardown_intr(adapter); qlcnic_teardown_intr(adapter);
kfree(adapter->msix_entries); qlcnic_cancel_idc_work(adapter);
err_out_decr_ref:
qlcnic_clr_all_drv_state(adapter, 0); qlcnic_clr_all_drv_state(adapter, 0);
err_out_iounmap:
qlcnic_cleanup_pci_map(adapter);
err_out_free_hw: err_out_free_hw:
qlcnic_free_adapter_resources(adapter); qlcnic_free_adapter_resources(adapter);
err_out_free_netdev: err_out_free_netdev:
free_netdev(netdev); free_netdev(netdev);
err_out_iounmap:
qlcnic_cleanup_pci_map(adapter);
err_out_free_hw_res:
kfree(ahw);
err_out_free_res: err_out_free_res:
pci_release_regions(pdev); pci_release_regions(pdev);
...@@ -1645,18 +1753,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1645,18 +1753,6 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
pci_disable_device(pdev); pci_disable_device(pdev);
return err; return err;
err_out_maintenance_mode:
netdev->netdev_ops = &qlcnic_netdev_failed_ops;
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
err = register_netdev(netdev);
if (err) {
dev_err(&pdev->dev, "failed to register net device\n");
goto err_out_decr_ref;
}
pci_set_drvdata(pdev, adapter);
qlcnic_create_diag_entries(adapter);
return 0;
} }
static void qlcnic_remove(struct pci_dev *pdev) static void qlcnic_remove(struct pci_dev *pdev)
...@@ -1933,7 +2029,7 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) ...@@ -1933,7 +2029,7 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
return stats; return stats;
} }
static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter) irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *adapter)
{ {
u32 status; u32 status;
...@@ -2313,7 +2409,7 @@ qlcnic_fwinit_work(struct work_struct *work) ...@@ -2313,7 +2409,7 @@ qlcnic_fwinit_work(struct work_struct *work)
switch (dev_state) { switch (dev_state) {
case QLCNIC_DEV_READY: case QLCNIC_DEV_READY:
if (!adapter->nic_ops->start_firmware(adapter)) { if (!qlcnic_start_firmware(adapter)) {
qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); qlcnic_schedule_work(adapter, qlcnic_attach_work, 0);
adapter->fw_wait_cnt = 0; adapter->fw_wait_cnt = 0;
return; return;
...@@ -2411,9 +2507,7 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter) ...@@ -2411,9 +2507,7 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter)
qlcnic_api_unlock(adapter); qlcnic_api_unlock(adapter);
} }
/*Transit to RESET state from READY state only */ void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
void
qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
{ {
u32 state, xg_val = 0, gb_val = 0; u32 state, xg_val = 0, gb_val = 0;
...@@ -2536,7 +2630,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) ...@@ -2536,7 +2630,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
goto detach; goto detach;
if (adapter->need_fw_reset) if (adapter->need_fw_reset)
qlcnic_dev_request_reset(adapter); qlcnic_dev_request_reset(adapter, 0);
state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE);
if (state == QLCNIC_DEV_NEED_RESET) { if (state == QLCNIC_DEV_NEED_RESET) {
...@@ -2565,7 +2659,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) ...@@ -2565,7 +2659,7 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
adapter->flags |= QLCNIC_FW_HANG; adapter->flags |= QLCNIC_FW_HANG;
qlcnic_dev_request_reset(adapter); qlcnic_dev_request_reset(adapter, 0);
if (qlcnic_auto_fw_reset) if (qlcnic_auto_fw_reset)
clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state); clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
...@@ -2677,7 +2771,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev) ...@@ -2677,7 +2771,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev)
return err; return err;
qlcnic_clr_drv_state(adapter); qlcnic_clr_drv_state(adapter);
qlcnic_setup_intr(adapter); qlcnic_setup_intr(adapter, 0);
if (netif_running(netdev)) { if (netif_running(netdev)) {
err = qlcnic_attach(adapter); err = qlcnic_attach(adapter);
......
...@@ -958,3 +958,13 @@ void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) ...@@ -958,3 +958,13 @@ void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
device_remove_bin_file(dev, &bin_attr_pm_config); device_remove_bin_file(dev, &bin_attr_pm_config);
device_remove_bin_file(dev, &bin_attr_esw_stats); device_remove_bin_file(dev, &bin_attr_esw_stats);
} }
void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter)
{
qlcnic_create_diag_entries(adapter);
}
void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter)
{
qlcnic_remove_diag_entries(adapter);
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment