* [PATCH NEXT 1/5] qlcnic: fix pause params setting
2010-07-13 9:46 [PATCH NEXT 0/5]qlcnic: aer support amit.salecha
@ 2010-07-13 9:46 ` amit.salecha
2010-07-13 9:46 ` [PATCH NEXT 2/5] qlcnic: disable tx timeout recovery amit.salecha
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: amit.salecha @ 2010-07-13 9:46 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Rajesh Borundia, Amit Kumar Salecha
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
Turning off rx pause param and autoneg param is not supported so
return error in that case.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_ethtool.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index baf5a52..8599993 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -578,8 +578,13 @@ qlcnic_set_pauseparam(struct net_device *netdev,
}
QLCWR32(adapter, QLCNIC_NIU_GB_PAUSE_CTL, val);
} else if (adapter->ahw.port_type == QLCNIC_XGBE) {
+
+ if (!pause->rx_pause || pause->autoneg)
+ return -EOPNOTSUPP;
+
if ((port < 0) || (port > QLCNIC_NIU_MAX_XG_PORTS))
return -EIO;
+
val = QLCRD32(adapter, QLCNIC_NIU_XG_PAUSE_CTL);
if (port == 0) {
if (pause->tx_pause)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH NEXT 2/5] qlcnic: disable tx timeout recovery
2010-07-13 9:46 [PATCH NEXT 0/5]qlcnic: aer support amit.salecha
2010-07-13 9:46 ` [PATCH NEXT 1/5] qlcnic: fix pause params setting amit.salecha
@ 2010-07-13 9:46 ` amit.salecha
2010-07-13 9:46 ` [PATCH NEXT 3/5] qlcnic: fix netdev notifier in error path amit.salecha
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: amit.salecha @ 2010-07-13 9:46 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Amit Kumar Salecha
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
Disable tx timeout recovery, if auto_fw_reset is disable
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 4d18313..d511fd1 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -2581,7 +2581,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
if (adapter->need_fw_reset)
goto detach;
- if (adapter->reset_context) {
+ if (adapter->reset_context &&
+ auto_fw_reset == AUTO_FW_RESET_ENABLED) {
qlcnic_reset_hw_context(adapter);
adapter->netdev->trans_start = jiffies;
}
@@ -2594,7 +2595,8 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
qlcnic_dev_request_reset(adapter);
- clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
+ if ((auto_fw_reset == AUTO_FW_RESET_ENABLED))
+ clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
dev_info(&netdev->dev, "firmware hang detected\n");
--
1.6.0.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH NEXT 3/5] qlcnic: fix netdev notifier in error path
2010-07-13 9:46 [PATCH NEXT 0/5]qlcnic: aer support amit.salecha
2010-07-13 9:46 ` [PATCH NEXT 1/5] qlcnic: fix pause params setting amit.salecha
2010-07-13 9:46 ` [PATCH NEXT 2/5] qlcnic: disable tx timeout recovery amit.salecha
@ 2010-07-13 9:46 ` amit.salecha
2010-07-13 9:46 ` [PATCH NEXT 4/5] qlcnic: aer support amit.salecha
2010-07-13 9:47 ` [PATCH NEXT 5/5] qlcnic: restore NPAR config data after recovery amit.salecha
4 siblings, 0 replies; 6+ messages in thread
From: amit.salecha @ 2010-07-13 9:46 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Amit Kumar Salecha
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
netdev notifier are not unregistered if pci_register_driver fails.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index d511fd1..c8275f0 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -3451,6 +3451,7 @@ static struct pci_driver qlcnic_driver = {
static int __init qlcnic_init_module(void)
{
+ int ret;
printk(KERN_INFO "%s\n", qlcnic_driver_string);
@@ -3459,8 +3460,15 @@ static int __init qlcnic_init_module(void)
register_inetaddr_notifier(&qlcnic_inetaddr_cb);
#endif
+ ret = pci_register_driver(&qlcnic_driver);
+ if (ret) {
+#ifdef CONFIG_INET
+ unregister_inetaddr_notifier(&qlcnic_inetaddr_cb);
+ unregister_netdevice_notifier(&qlcnic_netdev_cb);
+#endif
+ }
- return pci_register_driver(&qlcnic_driver);
+ return ret;
}
module_init(qlcnic_init_module);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH NEXT 4/5] qlcnic: aer support
2010-07-13 9:46 [PATCH NEXT 0/5]qlcnic: aer support amit.salecha
` (2 preceding siblings ...)
2010-07-13 9:46 ` [PATCH NEXT 3/5] qlcnic: fix netdev notifier in error path amit.salecha
@ 2010-07-13 9:46 ` amit.salecha
2010-07-13 9:47 ` [PATCH NEXT 5/5] qlcnic: restore NPAR config data after recovery amit.salecha
4 siblings, 0 replies; 6+ messages in thread
From: amit.salecha @ 2010-07-13 9:46 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, Sucheta Chakraborty, Amit Kumar Salecha
From: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Pci error recovery support added.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 1 +
drivers/net/qlcnic/qlcnic_main.c | 137 +++++++++++++++++++++++++++++++++++++-
2 files changed, 137 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 02a50e6..0644642 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -911,6 +911,7 @@ struct qlcnic_mac_req {
#define __QLCNIC_DEV_UP 1
#define __QLCNIC_RESETTING 2
#define __QLCNIC_START_FW 4
+#define __QLCNIC_AER 5
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index c8275f0..462cb6b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -34,6 +34,7 @@
#include <linux/ipv6.h>
#include <linux/inetdevice.h>
#include <linux/sysfs.h>
+#include <linux/aer.h>
MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver");
MODULE_LICENSE("GPL");
@@ -1306,6 +1307,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_disable_pdev;
pci_set_master(pdev);
+ pci_enable_pcie_error_reporting(pdev);
netdev = alloc_etherdev(sizeof(struct qlcnic_adapter));
if (!netdev) {
@@ -1437,6 +1439,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
qlcnic_release_firmware(adapter);
+ pci_disable_pcie_error_reporting(pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
@@ -2521,6 +2524,9 @@ static void
qlcnic_schedule_work(struct qlcnic_adapter *adapter,
work_func_t func, int delay)
{
+ if (test_bit(__QLCNIC_AER, &adapter->state))
+ return;
+
INIT_DELAYED_WORK(&adapter->fw_work, func);
schedule_delayed_work(&adapter->fw_work, round_jiffies_relative(delay));
}
@@ -2631,6 +2637,128 @@ reschedule:
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}
+static int qlcnic_is_first_func(struct pci_dev *pdev)
+{
+ struct pci_dev *oth_pdev;
+ int val = pdev->devfn;
+
+ while (val-- > 0) {
+ oth_pdev = pci_get_domain_bus_and_slot(pci_domain_nr
+ (pdev->bus), pdev->bus->number,
+ PCI_DEVFN(PCI_SLOT(pdev->devfn), val));
+
+ if (oth_pdev && (oth_pdev->current_state != PCI_D3cold))
+ return 0;
+ }
+ return 1;
+}
+
+static int qlcnic_attach_func(struct pci_dev *pdev)
+{
+ int err, first_func;
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+
+ pdev->error_state = pci_channel_io_normal;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
+
+ first_func = qlcnic_is_first_func(pdev);
+
+ if (qlcnic_api_lock(adapter))
+ return -EINVAL;
+
+ if (first_func) {
+ adapter->need_fw_reset = 1;
+ set_bit(__QLCNIC_START_FW, &adapter->state);
+ QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING);
+ QLCDB(adapter, DRV, "Restarting fw\n");
+ }
+ qlcnic_api_unlock(adapter);
+
+ err = adapter->nic_ops->start_firmware(adapter);
+ if (err)
+ return err;
+
+ qlcnic_clr_drv_state(adapter);
+ qlcnic_setup_intr(adapter);
+
+ if (netif_running(netdev)) {
+ err = qlcnic_attach(adapter);
+ if (err) {
+ qlcnic_clr_all_drv_state(adapter);
+ clear_bit(__QLCNIC_AER, &adapter->state);
+ netif_device_attach(netdev);
+ return err;
+ }
+
+ err = qlcnic_up(adapter, netdev);
+ if (err)
+ goto done;
+
+ qlcnic_config_indev_addr(netdev, NETDEV_UP);
+ }
+ done:
+ netif_device_attach(netdev);
+ return err;
+}
+
+static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+ struct net_device *netdev = adapter->netdev;
+
+ if (state == pci_channel_io_perm_failure)
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ if (state == pci_channel_io_normal)
+ return PCI_ERS_RESULT_RECOVERED;
+
+ set_bit(__QLCNIC_AER, &adapter->state);
+ netif_device_detach(netdev);
+
+ cancel_delayed_work_sync(&adapter->fw_work);
+
+ if (netif_running(netdev))
+ qlcnic_down(adapter, netdev);
+
+ qlcnic_detach(adapter);
+ qlcnic_teardown_intr(adapter);
+
+ clear_bit(__QLCNIC_RESETTING, &adapter->state);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev)
+{
+ return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT :
+ PCI_ERS_RESULT_RECOVERED;
+}
+
+static void qlcnic_io_resume(struct pci_dev *pdev)
+{
+ struct qlcnic_adapter *adapter = pci_get_drvdata(pdev);
+
+ pci_cleanup_aer_uncorrect_error_status(pdev);
+
+ if ((QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) == QLCNIC_DEV_READY) &&
+ (test_and_clear_bit(__QLCNIC_AER, &adapter->state)))
+ qlcnic_schedule_work(adapter, qlcnic_fw_poll_work,
+ FW_POLL_DELAY);
+}
+
+
static int
qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
{
@@ -3436,6 +3564,11 @@ static void
qlcnic_config_indev_addr(struct net_device *dev, unsigned long event)
{ }
#endif
+static struct pci_error_handlers qlcnic_err_handler = {
+ .error_detected = qlcnic_io_error_detected,
+ .slot_reset = qlcnic_io_slot_reset,
+ .resume = qlcnic_io_resume,
+};
static struct pci_driver qlcnic_driver = {
.name = qlcnic_driver_name,
@@ -3446,7 +3579,9 @@ static struct pci_driver qlcnic_driver = {
.suspend = qlcnic_suspend,
.resume = qlcnic_resume,
#endif
- .shutdown = qlcnic_shutdown
+ .shutdown = qlcnic_shutdown,
+ .err_handler = &qlcnic_err_handler
+
};
static int __init qlcnic_init_module(void)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH NEXT 5/5] qlcnic: restore NPAR config data after recovery
2010-07-13 9:46 [PATCH NEXT 0/5]qlcnic: aer support amit.salecha
` (3 preceding siblings ...)
2010-07-13 9:46 ` [PATCH NEXT 4/5] qlcnic: aer support amit.salecha
@ 2010-07-13 9:47 ` amit.salecha
4 siblings, 0 replies; 6+ messages in thread
From: amit.salecha @ 2010-07-13 9:47 UTC (permalink / raw)
To: davem
Cc: netdev, ameen.rahman, Anirban Chakraborty, Rajesh Borundia,
Amit Kumar Salecha
From: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
NPAR configuration which is programmed in fw, need to
restore after fw recovery.
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 3 +-
drivers/net/qlcnic/qlcnic_ctx.c | 2 +
drivers/net/qlcnic/qlcnic_main.c | 80 ++++++++++++++++++++++++++++++--------
3 files changed, 67 insertions(+), 18 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 0644642..9f96298 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -949,7 +949,6 @@ struct qlcnic_adapter {
u8 has_link_events;
u8 fw_type;
u16 tx_context_id;
- u16 mtu;
u16 is_up;
u16 link_speed;
@@ -1044,6 +1043,8 @@ struct qlcnic_pci_info {
struct qlcnic_npar_info {
u16 vlan_id;
+ u16 min_bw;
+ u16 max_bw;
u8 phy_port;
u8 type;
u8 active;
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index cdd44b4..cc5d861 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -636,6 +636,8 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter,
QLCNIC_CDRP_CMD_GET_NIC_INFO);
if (err == QLCNIC_RCODE_SUCCESS) {
+ npar_info->pci_func = le16_to_cpu(nic_info->pci_func);
+ npar_info->op_mode = le16_to_cpu(nic_info->op_mode);
npar_info->phys_port = le16_to_cpu(nic_info->phys_port);
npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode);
npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques);
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 462cb6b..38c8d9c 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -507,6 +507,8 @@ qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
adapter->npars[pfn].type = pci_info[i].type;
adapter->npars[pfn].phy_port = pci_info[i].default_port;
adapter->npars[pfn].mac_learning = DEFAULT_MAC_LEARN;
+ adapter->npars[pfn].min_bw = pci_info[i].tx_min_bw;
+ adapter->npars[pfn].max_bw = pci_info[i].tx_max_bw;
}
for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++)
@@ -771,6 +773,50 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
}
static int
+qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
+{
+ int i, err = 0;
+ struct qlcnic_npar_info *npar;
+ struct qlcnic_info nic_info;
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)
+ || !adapter->need_fw_reset)
+ return 0;
+
+ if (adapter->op_mode == QLCNIC_MGMT_FUNC) {
+ /* Set the NPAR config data after FW reset */
+ for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
+ npar = &adapter->npars[i];
+ if (npar->type != QLCNIC_TYPE_NIC)
+ continue;
+ err = qlcnic_get_nic_info(adapter, &nic_info, i);
+ if (err)
+ goto err_out;
+ nic_info.min_tx_bw = npar->min_bw;
+ nic_info.max_tx_bw = npar->max_bw;
+ err = qlcnic_set_nic_info(adapter, &nic_info);
+ if (err)
+ goto err_out;
+
+ if (npar->enable_pm) {
+ err = qlcnic_config_port_mirroring(adapter,
+ npar->dest_npar, 1, i);
+ if (err)
+ goto err_out;
+
+ }
+ npar->mac_learning = DEFAULT_MAC_LEARN;
+ npar->host_vlan_tag = 0;
+ npar->promisc_mode = 0;
+ npar->discard_tagged = 0;
+ npar->vlan_id = 0;
+ }
+ }
+err_out:
+ return err;
+}
+
+static int
qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
int val, err, first_boot;
@@ -834,10 +880,9 @@ wait_init:
qlcnic_idc_debug_info(adapter, 1);
qlcnic_check_options(adapter);
-
- if (adapter->flags & QLCNIC_ESWITCH_ENABLED &&
- adapter->op_mode != QLCNIC_NON_PRIV_FUNC)
- qlcnic_dev_set_npar_ready(adapter);
+ if (qlcnic_reset_npar_config(adapter))
+ goto err_out;
+ qlcnic_dev_set_npar_ready(adapter);
adapter->need_fw_reset = 0;
@@ -2486,6 +2531,7 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
{
u32 state;
+ adapter->need_fw_reset = 1;
if (qlcnic_api_lock(adapter))
return;
@@ -2506,6 +2552,9 @@ qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
u32 state;
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+ adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
+ return;
if (qlcnic_api_lock(adapter))
return;
@@ -3154,9 +3203,8 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
struct device *dev = container_of(kobj, struct device, kobj);
struct qlcnic_adapter *adapter = dev_get_drvdata(dev);
struct qlcnic_esw_func_cfg *esw_cfg;
- u8 id, discard_tagged, promsc_mode, mac_learn;
- u8 vlan_tagging, pci_func, vlan_id;
int count, rem, i, ret;
+ u8 id, pci_func;
count = size / sizeof(struct qlcnic_esw_func_cfg);
rem = size % sizeof(struct qlcnic_esw_func_cfg);
@@ -3171,17 +3219,13 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
id = adapter->npars[pci_func].phy_port;
- vlan_tagging = esw_cfg[i].host_vlan_tag;
- promsc_mode = esw_cfg[i].promisc_mode;
- mac_learn = esw_cfg[i].mac_learning;
- vlan_id = esw_cfg[i].vlan_id;
- discard_tagged = esw_cfg[i].discard_tagged;
- ret = qlcnic_config_switch_port(adapter, id, vlan_tagging,
- discard_tagged,
- promsc_mode,
- mac_learn,
- pci_func,
- vlan_id);
+ ret = qlcnic_config_switch_port(adapter, id,
+ esw_cfg[i].host_vlan_tag,
+ esw_cfg[i].discard_tagged,
+ esw_cfg[i].promisc_mode,
+ esw_cfg[i].mac_learning,
+ esw_cfg[i].pci_func,
+ esw_cfg[i].vlan_id);
if (ret)
return ret;
}
@@ -3282,6 +3326,8 @@ qlcnic_sysfs_write_npar_config(struct file *file, struct kobject *kobj,
ret = qlcnic_set_nic_info(adapter, &nic_info);
if (ret)
return ret;
+ adapter->npars[i].min_bw = nic_info.min_tx_bw;
+ adapter->npars[i].max_bw = nic_info.max_tx_bw;
}
return size;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 6+ messages in thread