* [PATCHv2 NEXT 01/10] qlcnic: backout firmware initialization update
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 02/10] qlcnic: add api version in reg dump Amit Kumar Salecha
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Sony Chacko
From: Sony Chacko <sony.chacko@qlogic.com>
o Backing out "firmware initialization update" changes, commit-id
"d4066833bb1b35fefb1dd45eb2b10659d46bf151".
o fix heartbit spelling, it should be heartbeat
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 2 +-
drivers/net/qlcnic/qlcnic_hdr.h | 6 ++-
drivers/net/qlcnic/qlcnic_init.c | 109 +++++++++++++++++++++++++++++++-------
drivers/net/qlcnic/qlcnic_main.c | 11 ++--
4 files changed, 100 insertions(+), 28 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 1f5c10b..74eff18 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -978,7 +978,7 @@ struct qlcnic_adapter {
u32 temp;
u32 int_vec_bit;
- u32 heartbit;
+ u32 heartbeat;
u8 max_mac_filters;
u8 dev_state;
diff --git a/drivers/net/qlcnic/qlcnic_hdr.h b/drivers/net/qlcnic/qlcnic_hdr.h
index bce1b1d..716203e 100644
--- a/drivers/net/qlcnic/qlcnic_hdr.h
+++ b/drivers/net/qlcnic/qlcnic_hdr.h
@@ -747,8 +747,12 @@ enum {
#define QLCNIC_RESET_TIMEOUT_SECS 10
#define QLCNIC_INIT_TIMEOUT_SECS 30
+#define QLCNIC_RCVPEG_CHECK_RETRY_COUNT 2000
+#define QLCNIC_RCVPEG_CHECK_DELAY 10
+#define QLCNIC_CMDPEG_CHECK_RETRY_COUNT 60
+#define QLCNIC_CMDPEG_CHECK_DELAY 500
#define QLCNIC_HEARTBEAT_PERIOD_MSECS 200
-#define QLCNIC_HEARTBEAT_RETRY_COUNT 45
+#define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45
#define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC)))
#define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200)
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index eb8256b..8e0e7a3 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -46,6 +46,9 @@ static void
qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter,
struct qlcnic_host_rds_ring *rds_ring);
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter);
+
static void crb_addr_transform_setup(void)
{
crb_addr_transform(XDMA);
@@ -544,31 +547,77 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter)
return 0;
}
-int
-qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
+static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter)
{
- u32 heartbit, cmdpeg_state, ret = -EIO;
- int retries = QLCNIC_HEARTBEAT_RETRY_COUNT;
+ u32 val;
+ int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT;
- adapter->heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
do {
- msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
- heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
- if (heartbit != adapter->heartbit) {
- cmdpeg_state = QLCRD32(adapter, CRB_CMDPEG_STATE);
- /* Ensure peg states are initialized */
- if (cmdpeg_state == PHAN_INITIALIZE_COMPLETE ||
- cmdpeg_state == PHAN_INITIALIZE_ACK) {
- /* Complete firmware handshake */
- QLCWR32(adapter, CRB_CMDPEG_STATE,
- PHAN_INITIALIZE_ACK);
- ret = QLCNIC_RCODE_SUCCESS;
- break;
- }
+ val = QLCRD32(adapter, CRB_CMDPEG_STATE);
+
+ switch (val) {
+ case PHAN_INITIALIZE_COMPLETE:
+ case PHAN_INITIALIZE_ACK:
+ return 0;
+ case PHAN_INITIALIZE_FAILED:
+ goto out_err;
+ default:
+ break;
}
+
+ msleep(QLCNIC_CMDPEG_CHECK_DELAY);
+
} while (--retries);
- return ret;
+ QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED);
+
+out_err:
+ dev_err(&adapter->pdev->dev, "Command Peg initialization not "
+ "complete, state: 0x%x.\n", val);
+ return -EIO;
+}
+
+static int
+qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter)
+{
+ u32 val;
+ int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT;
+
+ do {
+ val = QLCRD32(adapter, CRB_RCVPEG_STATE);
+
+ if (val == PHAN_PEG_RCV_INITIALIZED)
+ return 0;
+
+ msleep(QLCNIC_RCVPEG_CHECK_DELAY);
+
+ } while (--retries);
+
+ if (!retries) {
+ dev_err(&adapter->pdev->dev, "Receive Peg initialization not "
+ "complete, state: 0x%x.\n", val);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+int
+qlcnic_check_fw_status(struct qlcnic_adapter *adapter)
+{
+ int err;
+
+ err = qlcnic_cmd_peg_ready(adapter);
+ if (err)
+ return err;
+
+ err = qlcnic_receive_peg_ready(adapter);
+ if (err)
+ return err;
+
+ QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK);
+
+ return err;
}
int
@@ -943,12 +992,32 @@ static void qlcnic_rom_lock_recovery(struct qlcnic_adapter *adapter)
qlcnic_pcie_sem_unlock(adapter, 2);
}
+static int
+qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter)
+{
+ u32 heartbeat, ret = -EIO;
+ int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT;
+
+ adapter->heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+
+ do {
+ msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS);
+ heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ if (heartbeat != adapter->heartbeat) {
+ ret = QLCNIC_RCODE_SUCCESS;
+ break;
+ }
+ } while (--retries);
+
+ return ret;
+}
+
int
qlcnic_need_fw_reset(struct qlcnic_adapter *adapter)
{
u32 val, version, major, minor, build;
- if (qlcnic_check_fw_status(adapter)) {
+ if (qlcnic_check_fw_hearbeat(adapter)) {
qlcnic_rom_lock_recovery(adapter);
return 1;
}
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 6999d5a..771a160 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -983,7 +983,7 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter)
err = qlcnic_need_fw_reset(adapter);
if (err == 0)
- goto set_dev_ready;
+ goto check_fw_status;
err = qlcnic_pinit_from_rom(adapter);
if (err)
@@ -1002,7 +1002,6 @@ check_fw_status:
if (err)
goto err_out;
-set_dev_ready:
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
qlcnic_idc_debug_info(adapter, 1);
@@ -2795,7 +2794,7 @@ done:
static int
qlcnic_check_health(struct qlcnic_adapter *adapter)
{
- u32 state = 0, heartbit;
+ u32 state = 0, heartbeat;
struct net_device *netdev = adapter->netdev;
if (qlcnic_check_temp(adapter))
@@ -2811,9 +2810,9 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
adapter->need_fw_reset = 1;
}
- heartbit = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
- if (heartbit != adapter->heartbit) {
- adapter->heartbit = heartbit;
+ heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER);
+ if (heartbeat != adapter->heartbeat) {
+ adapter->heartbeat = heartbeat;
adapter->fw_fail_cnt = 0;
if (adapter->need_fw_reset)
goto detach;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 02/10] qlcnic: add api version in reg dump
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 01/10] qlcnic: backout firmware initialization update Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 03/10] qlcnic: fix mac addr read Amit Kumar Salecha
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Rajesh Borundia
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
o ethtool reg version bumped to 2
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 | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
index e294b82..cb9463b 100644
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
@@ -115,9 +115,13 @@ static const u32 diag_registers[] = {
-1
};
+#define QLCNIC_MGMT_API_VERSION 2
+#define QLCNIC_DEV_INFO_SIZE 1
+#define QLCNIC_ETHTOOL_REGS_VER 2
static int qlcnic_get_regs_len(struct net_device *dev)
{
- return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN;
+ return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN +
+ QLCNIC_DEV_INFO_SIZE + 1;
}
static int qlcnic_get_eeprom_len(struct net_device *dev)
@@ -342,10 +346,13 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
int ring, i = 0;
memset(p, 0, qlcnic_get_regs_len(dev));
- regs->version = (1 << 24) | (adapter->ahw.revision_id << 16) |
- (adapter->pdev)->device;
+ regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) |
+ (adapter->ahw.revision_id << 16) | (adapter->pdev)->device;
- for (i = 0; diag_registers[i] != -1; i++)
+ regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff));
+ regs_buff[1] = QLCNIC_MGMT_API_VERSION;
+
+ for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[i] != -1; i++)
regs_buff[i] = QLCRD32(adapter, diag_registers[i]);
if (!test_bit(__QLCNIC_DEV_UP, &adapter->state))
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 03/10] qlcnic: fix mac addr read
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 01/10] qlcnic: backout firmware initialization update Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 02/10] qlcnic: add api version in reg dump Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 04/10] qlcnic: fix for setting default eswitch config Amit Kumar Salecha
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Rajesh Borundia
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
o Mac addr was read from flash for every fw reset
for Non-priviledge function.It should be read only once.
o Remove unnecessary get_mac_addr callback
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 2 --
drivers/net/qlcnic/qlcnic_hw.c | 13 -------------
drivers/net/qlcnic/qlcnic_main.c | 28 +++++++++++++---------------
3 files changed, 13 insertions(+), 30 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 74eff18..220370f 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -1259,7 +1259,6 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable);
int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter);
void qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter,
struct qlcnic_host_tx_ring *tx_ring);
-int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac);
void qlcnic_clear_ilb_mode(struct qlcnic_adapter *adapter);
int qlcnic_set_ilb_mode(struct qlcnic_adapter *adapter);
void qlcnic_fetch_mac(struct qlcnic_adapter *, u32, u32, u8, u8 *);
@@ -1346,7 +1345,6 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring)
extern const struct ethtool_ops qlcnic_ethtool_ops;
struct qlcnic_nic_template {
- int (*get_mac_addr) (struct qlcnic_adapter *, u8*);
int (*config_bridged_mode) (struct qlcnic_adapter *, u32);
int (*config_led) (struct qlcnic_adapter *, u32, u32);
int (*start_firmware) (struct qlcnic_adapter *);
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 5e6f486..670a54a 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -715,19 +715,6 @@ int qlcnic_change_mtu(struct net_device *netdev, int mtu)
return rc;
}
-int qlcnic_get_mac_addr(struct qlcnic_adapter *adapter, u8 *mac)
-{
- u32 crbaddr;
- int pci_func = adapter->ahw.pci_func;
-
- crbaddr = CRB_MAC_BLOCK_START +
- (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1));
-
- qlcnic_fetch_mac(adapter, crbaddr, crbaddr+4, pci_func & 1, mac);
-
- return 0;
-}
-
/*
* Changes the CRB window to the specified window.
*/
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 771a160..3f2f93b 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -322,7 +322,7 @@ qlcnic_read_mac_addr(struct qlcnic_adapter *adapter)
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- if (adapter->nic_ops->get_mac_addr(adapter, mac_addr) != 0)
+ if (qlcnic_get_mac_address(adapter, mac_addr) != 0)
return -EIO;
memcpy(netdev->dev_addr, mac_addr, ETH_ALEN);
@@ -378,14 +378,12 @@ static const struct net_device_ops qlcnic_netdev_ops = {
};
static struct qlcnic_nic_template qlcnic_ops = {
- .get_mac_addr = qlcnic_get_mac_address,
.config_bridged_mode = qlcnic_config_bridged_mode,
.config_led = qlcnic_config_led,
.start_firmware = qlcnic_start_firmware
};
static struct qlcnic_nic_template qlcnic_vf_ops = {
- .get_mac_addr = qlcnic_get_mac_address,
.config_bridged_mode = qlcnicvf_config_bridged_mode,
.config_led = qlcnicvf_config_led,
.start_firmware = qlcnicvf_start_firmware
@@ -668,7 +666,6 @@ static void
qlcnic_check_options(struct qlcnic_adapter *adapter)
{
u32 fw_major, fw_minor, fw_build;
- char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
struct pci_dev *pdev = adapter->pdev;
struct qlcnic_info nic_info;
@@ -678,17 +675,6 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build);
- if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED))
- if (qlcnic_read_mac_addr(adapter))
- dev_warn(&pdev->dev, "failed to read mac addr\n");
- if (adapter->portnum == 0) {
- get_brd_name(adapter, brd_name);
-
- pr_info("%s: %s Board Chip rev 0x%x\n",
- module_name(THIS_MODULE),
- brd_name, adapter->ahw.revision_id);
- }
-
dev_info(&pdev->dev, "firmware v%d.%d.%d\n",
fw_major, fw_minor, fw_build);
@@ -1468,6 +1454,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int err;
uint8_t revision_id;
uint8_t pci_using_dac;
+ char brd_name[QLCNIC_MAX_BOARD_NAME_LEN];
err = pci_enable_device(pdev);
if (err)
@@ -1535,6 +1522,17 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_decr_ref;
}
+ if (qlcnic_read_mac_addr(adapter))
+ dev_warn(&pdev->dev, "failed to read mac addr\n");
+
+ if (adapter->portnum == 0) {
+ get_brd_name(adapter, brd_name);
+
+ pr_info("%s: %s Board Chip rev 0x%x\n",
+ module_name(THIS_MODULE),
+ brd_name, adapter->ahw.revision_id);
+ }
+
qlcnic_clear_stats(adapter);
qlcnic_setup_intr(adapter);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 04/10] qlcnic: fix for setting default eswitch config
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (2 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 03/10] qlcnic: fix mac addr read Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 05/10] qlcnic: fix mac anti spoof policy Amit Kumar Salecha
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Rajesh Borundia
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
o Default eswitch config was set, even before eswitch capabilty get detected.
As a result setting default config was getting fail.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 96 +++++++++++++++++++++++++------------
1 files changed, 65 insertions(+), 31 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 3f2f93b..e0c6811 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -667,7 +667,6 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
{
u32 fw_major, fw_minor, fw_build;
struct pci_dev *pdev = adapter->pdev;
- struct qlcnic_info nic_info;
fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR);
fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR);
@@ -688,16 +687,6 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
}
- if (!qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func)) {
- adapter->physical_port = nic_info.phys_port;
- adapter->switch_mode = nic_info.switch_mode;
- adapter->max_tx_ques = nic_info.max_tx_ques;
- adapter->max_rx_ques = nic_info.max_rx_ques;
- adapter->capabilities = nic_info.capabilities;
- adapter->max_mac_filters = nic_info.max_mac_filters;
- adapter->max_mtu = nic_info.max_mtu;
- }
-
adapter->msix_supported = !!use_msi_x;
adapter->rss_supported = !!use_msi_x;
@@ -706,6 +695,32 @@ qlcnic_check_options(struct qlcnic_adapter *adapter)
adapter->max_rds_rings = MAX_RDS_RINGS;
}
+static int
+qlcnic_initialize_nic(struct qlcnic_adapter *adapter)
+{
+ int err;
+ struct qlcnic_info nic_info;
+
+ err = qlcnic_get_nic_info(adapter, &nic_info, adapter->ahw.pci_func);
+ if (err)
+ return err;
+
+ adapter->physical_port = nic_info.phys_port;
+ adapter->switch_mode = nic_info.switch_mode;
+ adapter->max_tx_ques = nic_info.max_tx_ques;
+ adapter->max_rx_ques = nic_info.max_rx_ques;
+ adapter->capabilities = nic_info.capabilities;
+ adapter->max_mac_filters = nic_info.max_mac_filters;
+ adapter->max_mtu = nic_info.max_mtu;
+
+ if (adapter->capabilities & BIT_6)
+ adapter->flags |= QLCNIC_ESWITCH_ENABLED;
+ else
+ adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
+
+ return err;
+}
+
static void
qlcnic_set_vlan_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
@@ -791,6 +806,10 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
u32 op_mode, priv_level;
int err = 0;
+ err = qlcnic_initialize_nic(adapter);
+ if (err)
+ return err;
+
if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED)
return 0;
@@ -803,8 +822,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
else
priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw.pci_func);
- if (adapter->capabilities & BIT_6) {
- adapter->flags |= QLCNIC_ESWITCH_ENABLED;
+ if (adapter->flags & QLCNIC_ESWITCH_ENABLED) {
if (priv_level == QLCNIC_MGMT_FUNC) {
adapter->op_mode = QLCNIC_MGMT_FUNC;
err = qlcnic_init_pci_info(adapter);
@@ -821,8 +839,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter)
"HAL Version: %d, Privileged function\n",
adapter->fw_hal_version);
}
- } else
- adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
+ }
adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
@@ -836,9 +853,7 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
struct qlcnic_npar_info *npar;
u8 i;
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->need_fw_reset ||
- adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (adapter->need_fw_reset)
return 0;
for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) {
@@ -894,8 +909,7 @@ qlcnic_reset_npar_config(struct qlcnic_adapter *adapter)
struct qlcnic_npar_info *npar;
struct qlcnic_info nic_info;
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- !adapter->need_fw_reset || adapter->op_mode != QLCNIC_MGMT_FUNC)
+ if (!adapter->need_fw_reset)
return 0;
/* Set the NPAR config data after FW reset */
@@ -947,6 +961,28 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter)
}
static int
+qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter)
+{
+ int err;
+
+ if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
+ adapter->op_mode != QLCNIC_MGMT_FUNC)
+ return 0;
+
+ err = qlcnic_set_default_offload_settings(adapter);
+ if (err)
+ return err;
+
+ err = qlcnic_reset_npar_config(adapter);
+ if (err)
+ return err;
+
+ qlcnic_dev_set_npar_ready(adapter);
+
+ return err;
+}
+
+static int
qlcnic_start_firmware(struct qlcnic_adapter *adapter)
{
int err;
@@ -991,20 +1027,17 @@ check_fw_status:
QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY);
qlcnic_idc_debug_info(adapter, 1);
- err = qlcnic_set_default_offload_settings(adapter);
- if (err)
- goto err_out;
- err = qlcnic_reset_npar_config(adapter);
- if (err)
- goto err_out;
- qlcnic_check_options(adapter);
err = qlcnic_check_eswitch_mode(adapter);
if (err) {
dev_err(&adapter->pdev->dev,
"Memory allocation failed for eswitch\n");
goto err_out;
}
- qlcnic_dev_set_npar_ready(adapter);
+ err = qlcnic_set_mgmt_operations(adapter);
+ if (err)
+ goto err_out;
+
+ qlcnic_check_options(adapter);
adapter->need_fw_reset = 0;
qlcnic_release_firmware(adapter);
@@ -2719,9 +2752,6 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter)
static void
qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter)
{
- if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED) ||
- adapter->op_mode != QLCNIC_MGMT_FUNC)
- return;
if (qlcnic_api_lock(adapter))
return;
@@ -3004,6 +3034,10 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
if (err)
return err;
+ err = qlcnic_initialize_nic(adapter);
+ if (err)
+ return err;
+
qlcnic_check_options(adapter);
adapter->need_fw_reset = 0;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 05/10] qlcnic: fix mac anti spoof policy
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (3 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 04/10] qlcnic: fix for setting default eswitch config Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 06/10] qlcnic: fix panic while using eth_hdr Amit Kumar Salecha
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Rajesh Borundia
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
o Allow enabling/disabling mac anti spoof policy only for
Non privilege functions.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index e0c6811..9a3ebb8 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -741,9 +741,9 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
adapter->flags &= ~QLCNIC_MACSPOOF;
- if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC)
- if (esw_cfg->mac_anti_spoof)
- adapter->flags |= QLCNIC_MACSPOOF;
+
+ if (esw_cfg->mac_anti_spoof)
+ adapter->flags |= QLCNIC_MACSPOOF;
qlcnic_set_netdev_features(adapter, esw_cfg);
}
@@ -3377,8 +3377,12 @@ static int
validate_esw_config(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg, int count)
{
+ u32 op_mode;
u8 pci_func;
int i;
+
+ op_mode = readl(adapter->ahw.pci_base0 + QLCNIC_DRV_OP_MODE);
+
for (i = 0; i < count; i++) {
pci_func = esw_cfg[i].pci_func;
if (pci_func >= QLCNIC_MAX_PCI_FUNC)
@@ -3390,6 +3394,9 @@ validate_esw_config(struct qlcnic_adapter *adapter,
switch (esw_cfg[i].op_mode) {
case QLCNIC_PORT_DEFAULTS:
+ if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
+ QLCNIC_NON_PRIV_FUNC)
+ esw_cfg[i].mac_anti_spoof = 0;
break;
case QLCNIC_ADD_VLAN:
if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 06/10] qlcnic: fix panic while using eth_hdr
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (4 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 05/10] qlcnic: fix mac anti spoof policy Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 07/10] qlcnic: fix mac override capability Amit Kumar Salecha
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Rajesh Borundia
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
o skb->mac_header is not set, so machine panics while using function eth_hdr.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic_main.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 9a3ebb8..789fe81 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1991,6 +1991,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
struct qlcnic_skb_frag *buffrag;
struct cmd_desc_type0 *hwdesc, *first_desc;
struct pci_dev *pdev;
+ struct ethhdr *phdr;
int i, k;
u32 producer;
@@ -2003,7 +2004,8 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
if (adapter->flags & QLCNIC_MACSPOOF) {
- if (compare_ether_addr(eth_hdr(skb)->h_source,
+ phdr = (struct ethhdr *)skb->data;
+ if (compare_ether_addr(phdr->h_source,
adapter->mac_addr))
goto drop_packet;
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 07/10] qlcnic: fix mac override capability
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (5 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 06/10] qlcnic: fix panic while using eth_hdr Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 08/10] qlcnic: support mac learning Amit Kumar Salecha
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty, Rajesh Borundia
From: Rajesh Borundia <rajesh.borundia@qlogic.com>
o Rename mac_learning to mac_override
o Added check in set_mac to return error if mac override is disabled.
o Disabling mac_override only supported for Non priviledged functions.
Signed-off-by: Rajesh Borundia <rajesh.borundia@qlogic.com>
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 5 +++--
drivers/net/qlcnic/qlcnic_ctx.c | 13 +++++++------
drivers/net/qlcnic/qlcnic_main.c | 23 ++++++++++++++++++-----
3 files changed, 28 insertions(+), 13 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 220370f..cd1a2e6 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -905,6 +905,7 @@ struct qlcnic_mac_req {
#define QLCNIC_ADAPTER_INITIALIZED 0x80
#define QLCNIC_TAGGING_ENABLED 0x100
#define QLCNIC_MACSPOOF 0x200
+#define QLCNIC_MAC_OVERRIDE_DISABLED 0x400
#define QLCNIC_IS_MSI_FAMILY(adapter) \
((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED))
@@ -1060,7 +1061,7 @@ struct qlcnic_npar_info {
u8 enable_pm;
u8 dest_npar;
u8 discard_tagged;
- u8 mac_learning;
+ u8 mac_override;
u8 mac_anti_spoof;
u8 promisc_mode;
u8 offload_flags;
@@ -1134,7 +1135,7 @@ struct qlcnic_esw_func_cfg {
u8 host_vlan_tag;
u8 promisc_mode;
u8 discard_tagged;
- u8 mac_learning;
+ u8 mac_override;
u8 mac_anti_spoof;
u8 offload_flags;
u8 reserved[5];
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c
index bd4b06b..95a821e 100644
--- a/drivers/net/qlcnic/qlcnic_ctx.c
+++ b/drivers/net/qlcnic/qlcnic_ctx.c
@@ -1100,10 +1100,11 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
*arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET);
*arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET);
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 {
dev_err(&adapter->pdev->dev,
- "Failed to get eswitch port config%d\n", pci_func);
+ "Failed to get eswitch port config for pci func %d\n",
+ pci_func);
}
return err;
}
@@ -1142,7 +1143,7 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
arg1 &= ~BIT_4;
if (!(esw_cfg->promisc_mode))
arg1 &= ~BIT_6;
- if (!(esw_cfg->mac_learning))
+ if (!(esw_cfg->mac_override))
arg1 &= ~BIT_7;
if (!(esw_cfg->mac_anti_spoof))
arg2 &= ~BIT_0;
@@ -1175,10 +1176,10 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter,
if (err != QLCNIC_RCODE_SUCCESS) {
dev_err(&adapter->pdev->dev,
- "Failed to configure eswitch port%d\n", pci_func);
+ "Failed to configure eswitch pci func %d\n", pci_func);
} else {
dev_info(&adapter->pdev->dev,
- "Configured eSwitch for port %d\n", pci_func);
+ "Configured eSwitch for pci func %d\n", pci_func);
}
return err;
@@ -1202,7 +1203,7 @@ qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter,
esw_cfg->discard_tagged = !!(arg1 & BIT_4);
esw_cfg->host_vlan_tag = !!(arg1 & BIT_5);
esw_cfg->promisc_mode = !!(arg1 & BIT_6);
- esw_cfg->mac_learning = !!(arg1 & BIT_7);
+ esw_cfg->mac_override = !!(arg1 & BIT_7);
esw_cfg->vlan_id = LSW(arg1 >> 16);
esw_cfg->mac_anti_spoof = (arg2 & 0x1);
esw_cfg->offload_flags = ((arg2 >> 1) & 0x7);
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 789fe81..130f4db 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -343,6 +343,9 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
struct qlcnic_adapter *adapter = netdev_priv(netdev);
struct sockaddr *addr = p;
+ if ((adapter->flags & QLCNIC_MAC_OVERRIDE_DISABLED))
+ return -EOPNOTSUPP;
+
if (!is_valid_ether_addr(addr->sa_data))
return -EINVAL;
@@ -741,10 +744,14 @@ qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter,
struct qlcnic_esw_func_cfg *esw_cfg)
{
adapter->flags &= ~QLCNIC_MACSPOOF;
+ adapter->flags &= ~QLCNIC_MAC_OVERRIDE_DISABLED;
if (esw_cfg->mac_anti_spoof)
adapter->flags |= QLCNIC_MACSPOOF;
+ if (!esw_cfg->mac_override)
+ adapter->flags |= QLCNIC_MAC_OVERRIDE_DISABLED;
+
qlcnic_set_netdev_features(adapter, esw_cfg);
}
@@ -862,14 +869,14 @@ qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter)
memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg));
esw_cfg.pci_func = i;
esw_cfg.offload_flags = BIT_0;
- esw_cfg.mac_learning = BIT_0;
+ esw_cfg.mac_override = BIT_0;
if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO)
esw_cfg.offload_flags |= (BIT_1 | BIT_2);
if (qlcnic_config_switch_port(adapter, &esw_cfg))
return -EIO;
npar = &adapter->npars[i];
npar->pvid = esw_cfg.vlan_id;
- npar->mac_learning = esw_cfg.offload_flags;
+ npar->mac_override = esw_cfg.mac_override;
npar->mac_anti_spoof = esw_cfg.mac_anti_spoof;
npar->discard_tagged = esw_cfg.discard_tagged;
npar->promisc_mode = esw_cfg.promisc_mode;
@@ -887,7 +894,7 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter,
esw_cfg.op_mode = QLCNIC_PORT_DEFAULTS;
esw_cfg.pci_func = pci_func;
esw_cfg.vlan_id = npar->pvid;
- esw_cfg.mac_learning = npar->mac_learning;
+ esw_cfg.mac_override = npar->mac_override;
esw_cfg.discard_tagged = npar->discard_tagged;
esw_cfg.mac_anti_spoof = npar->mac_anti_spoof;
esw_cfg.offload_flags = npar->offload_flags;
@@ -3042,6 +3049,10 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter)
qlcnic_check_options(adapter);
+ err = qlcnic_set_eswitch_port_config(adapter);
+ if (err)
+ return err;
+
adapter->need_fw_reset = 0;
return err;
@@ -3397,8 +3408,10 @@ validate_esw_config(struct qlcnic_adapter *adapter,
switch (esw_cfg[i].op_mode) {
case QLCNIC_PORT_DEFAULTS:
if (QLC_DEV_GET_DRV(op_mode, pci_func) !=
- QLCNIC_NON_PRIV_FUNC)
+ QLCNIC_NON_PRIV_FUNC) {
esw_cfg[i].mac_anti_spoof = 0;
+ esw_cfg[i].mac_override = 1;
+ }
break;
case QLCNIC_ADD_VLAN:
if (!IS_VALID_VLAN(esw_cfg[i].vlan_id))
@@ -3474,7 +3487,7 @@ qlcnic_sysfs_write_esw_config(struct file *file, struct kobject *kobj,
switch (esw_cfg[i].op_mode) {
case QLCNIC_PORT_DEFAULTS:
npar->promisc_mode = esw_cfg[i].promisc_mode;
- npar->mac_learning = esw_cfg[i].mac_learning;
+ npar->mac_override = esw_cfg[i].mac_override;
npar->offload_flags = esw_cfg[i].offload_flags;
npar->mac_anti_spoof = esw_cfg[i].mac_anti_spoof;
npar->discard_tagged = esw_cfg[i].discard_tagged;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 08/10] qlcnic: support mac learning
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (6 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 07/10] qlcnic: fix mac override capability Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 09/10] qlcnic: mac vlan learning support Amit Kumar Salecha
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
Device eswitch need to configure with VM's mac address.
Hypervisor doesn't provide any utility/callbacks to get VM's mac address.
Unicast mac address filter improves performance and also provide
packet loopback capability i.e communication between VM.
Above features is by default off, can be turned on with module parameter
'mac_learn'.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 20 ++++++
drivers/net/qlcnic/qlcnic_hw.c | 48 +++++++++++++++
drivers/net/qlcnic/qlcnic_main.c | 123 ++++++++++++++++++++++++++++++++++++++
3 files changed, 191 insertions(+), 0 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index cd1a2e6..4727204 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -926,6 +926,21 @@ struct qlcnic_mac_req {
#define QLCNIC_INTERRUPT_TEST 1
#define QLCNIC_LOOPBACK_TEST 2
+#define QLCNIC_FILTER_AGE 80
+#define QLCNIC_LB_MAX_FILTERS 64
+
+struct qlcnic_filter {
+ struct hlist_node fnode;
+ u8 faddr[ETH_ALEN];
+ unsigned long ftime;
+};
+
+struct qlcnic_filter_hash {
+ struct hlist_head *fhead;
+ u8 fnum;
+ u8 fmax;
+};
+
struct qlcnic_adapter {
struct qlcnic_hardware_context ahw;
@@ -934,6 +949,7 @@ struct qlcnic_adapter {
struct list_head mac_list;
spinlock_t tx_clean_lock;
+ spinlock_t mac_learn_lock;
u16 num_txd;
u16 num_rxd;
@@ -1013,6 +1029,8 @@ struct qlcnic_adapter {
struct qlcnic_nic_intr_coalesce coal;
+ struct qlcnic_filter_hash fhash;
+
unsigned long state;
__le32 file_prd_off; /*File fw product offset*/
u32 fw_version;
@@ -1211,6 +1229,8 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int);
int qlcnic_get_board_info(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_delete_lb_filters(struct qlcnic_adapter *adapter);
/* Functions from qlcnic_init.c */
int qlcnic_load_firmware(struct qlcnic_adapter *adapter);
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 670a54a..5b2bce5 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -491,6 +491,54 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
}
}
+void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_filter *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ int i;
+
+ for (i = 0; i < adapter->fhash.fmax; i++) {
+ head = &(adapter->fhash.fhead[i]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode)
+ {
+ if (jiffies >
+ (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
+ qlcnic_sre_macaddr_change(adapter,
+ tmp_fil->faddr, QLCNIC_MAC_DEL);
+ spin_lock_bh(&adapter->mac_learn_lock);
+ adapter->fhash.fnum--;
+ hlist_del(&tmp_fil->fnode);
+ spin_unlock_bh(&adapter->mac_learn_lock);
+ kfree(tmp_fil);
+ }
+ }
+ }
+}
+
+void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
+{
+ struct qlcnic_filter *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ int i;
+
+ for (i = 0; i < adapter->fhash.fmax; i++) {
+ head = &(adapter->fhash.fhead[i]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+ qlcnic_sre_macaddr_change(adapter,
+ tmp_fil->faddr, QLCNIC_MAC_DEL);
+ spin_lock_bh(&adapter->mac_learn_lock);
+ adapter->fhash.fnum--;
+ hlist_del(&tmp_fil->fnode);
+ spin_unlock_bh(&adapter->mac_learn_lock);
+ kfree(tmp_fil);
+ }
+ }
+}
+
#define QLCNIC_CONFIG_INTR_COALESCE 3
/*
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 130f4db..0fbfb53 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -50,6 +50,10 @@ static int port_mode = QLCNIC_PORT_MODE_AUTO_NEG;
/* Default to restricted 1G auto-neg mode */
static int wol_port_mode = 5;
+static int qlcnic_mac_learn;
+module_param(qlcnic_mac_learn, int, 0644);
+MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)");
+
static int use_msi = 1;
module_param(use_msi, int, 0644);
MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled");
@@ -106,6 +110,8 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev);
static void qlcnic_config_indev_addr(struct net_device *dev, unsigned long);
static int qlcnic_start_firmware(struct qlcnic_adapter *);
+static void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter);
+static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter);
static void qlcnic_dev_set_npar_ready(struct qlcnic_adapter *);
static int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32);
static int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32);
@@ -1201,6 +1207,9 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev)
qlcnic_free_mac_list(adapter);
+ if (adapter->fhash.fnum)
+ qlcnic_delete_lb_filters(adapter);
+
qlcnic_nic_set_promisc(adapter, QLCNIC_NIU_NON_PROMISC_MODE);
qlcnic_napi_disable(adapter);
@@ -1596,6 +1605,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
break;
}
+ qlcnic_alloc_lb_filters_mem(adapter);
qlcnic_create_diag_entries(adapter);
return 0;
@@ -1647,6 +1657,8 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
clear_bit(__QLCNIC_RESETTING, &adapter->state);
+ qlcnic_free_lb_filters_mem(adapter);
+
qlcnic_teardown_intr(adapter);
qlcnic_remove_diag_entries(adapter);
@@ -1782,6 +1794,111 @@ static int qlcnic_close(struct net_device *netdev)
}
static void
+qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter)
+{
+ void *head;
+ int i;
+
+ if (!qlcnic_mac_learn)
+ return;
+
+ spin_lock_init(&adapter->mac_learn_lock);
+
+ head = kcalloc(QLCNIC_LB_MAX_FILTERS, sizeof(struct hlist_head),
+ GFP_KERNEL);
+ if (!head)
+ return;
+
+ adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS;
+ adapter->fhash.fhead = (struct hlist_head *)head;
+
+ for (i = 0; i < adapter->fhash.fmax; i++)
+ INIT_HLIST_HEAD(&adapter->fhash.fhead[i]);
+}
+
+static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
+{
+ if (adapter->fhash.fmax && adapter->fhash.fhead)
+ kfree(adapter->fhash.fhead);
+
+ adapter->fhash.fhead = NULL;
+ adapter->fhash.fmax = 0;
+}
+
+static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
+ u64 uaddr, struct qlcnic_host_tx_ring *tx_ring)
+{
+ struct cmd_desc_type0 *hwdesc;
+ struct qlcnic_nic_req *req;
+ struct qlcnic_mac_req *mac_req;
+ u32 producer;
+ u64 word;
+
+ producer = tx_ring->producer;
+ hwdesc = &tx_ring->desc_head[tx_ring->producer];
+
+ req = (struct qlcnic_nic_req *)hwdesc;
+ memset(req, 0, sizeof(struct qlcnic_nic_req));
+ req->qhdr = cpu_to_le64(QLCNIC_REQUEST << 23);
+
+ word = QLCNIC_MAC_EVENT | ((u64)(adapter->portnum) << 16);
+ req->req_hdr = cpu_to_le64(word);
+
+ mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
+ mac_req->op = QLCNIC_MAC_ADD;
+ memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+
+ tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
+}
+
+#define QLCNIC_MAC_HASH(MAC)\
+ ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25))
+
+static void
+qlcnic_send_filter(struct qlcnic_adapter *adapter,
+ struct qlcnic_host_tx_ring *tx_ring,
+ struct cmd_desc_type0 *first_desc,
+ struct sk_buff *skb)
+{
+ struct ethhdr *phdr = (struct ethhdr *)(skb->data);
+ struct qlcnic_filter *fil, *tmp_fil;
+ struct hlist_node *tmp_hnode, *n;
+ struct hlist_head *head;
+ u64 src_addr = 0;
+ u8 hindex;
+
+ if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
+ return;
+
+ if (adapter->fhash.fnum >= adapter->fhash.fmax)
+ return;
+
+ memcpy(&src_addr, phdr->h_source, ETH_ALEN);
+ hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
+ head = &(adapter->fhash.fhead[hindex]);
+
+ hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
+ if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN)) {
+ tmp_fil->ftime = jiffies;
+ return;
+ }
+ }
+
+ fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC);
+ if (!fil)
+ return;
+
+ qlcnic_change_filter(adapter, src_addr, tx_ring);
+
+ fil->ftime = jiffies;
+ memcpy(fil->faddr, &src_addr, ETH_ALEN);
+ spin_lock(&adapter->mac_learn_lock);
+ hlist_add_head(&(fil->fnode), head);
+ adapter->fhash.fnum++;
+ spin_unlock(&adapter->mac_learn_lock);
+}
+
+static void
qlcnic_tso_check(struct net_device *netdev,
struct qlcnic_host_tx_ring *tx_ring,
struct cmd_desc_type0 *first_desc,
@@ -2090,6 +2207,9 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
qlcnic_tso_check(netdev, tx_ring, first_desc, skb);
+ if (qlcnic_mac_learn)
+ qlcnic_send_filter(adapter, tx_ring, first_desc, skb);
+
qlcnic_update_cmd_producer(adapter, tx_ring);
adapter->stats.txbytes += skb->len;
@@ -2900,6 +3020,9 @@ qlcnic_fw_poll_work(struct work_struct *work)
if (qlcnic_check_health(adapter))
return;
+ if (adapter->fhash.fnum)
+ qlcnic_prune_lb_filters(adapter);
+
reschedule:
qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, FW_POLL_DELAY);
}
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 09/10] qlcnic: mac vlan learning support
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (7 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 08/10] qlcnic: support mac learning Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 3:17 ` [PATCHv2 NEXT 10/10] qlcnic: add cksum flag Amit Kumar Salecha
2010-09-01 17:42 ` [PATCHv2 0/10]qlcnic: Fixes and enhancement David Miller
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
Hypervisor allows, two VM's interfaces to have same mac address.
These VM's interfaces get differentiate with Vlan tag.
This patch add support to learn and configure mac+vlan filter on device.
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 3 +++
drivers/net/qlcnic/qlcnic_hw.c | 17 +++++++++++------
drivers/net/qlcnic/qlcnic_main.c | 16 ++++++++++++----
3 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 4727204..9d21152 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -722,6 +722,8 @@ struct qlcnic_cardrsp_tx_ctx {
#define QLCNIC_MAC_NOOP 0
#define QLCNIC_MAC_ADD 1
#define QLCNIC_MAC_DEL 2
+#define QLCNIC_MAC_VLAN_ADD 3
+#define QLCNIC_MAC_VLAN_DEL 4
struct qlcnic_mac_list_s {
struct list_head list;
@@ -932,6 +934,7 @@ struct qlcnic_mac_req {
struct qlcnic_filter {
struct hlist_node fnode;
u8 faddr[ETH_ALEN];
+ u16 vlan_id;
unsigned long ftime;
};
diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c
index 5b2bce5..c198df9 100644
--- a/drivers/net/qlcnic/qlcnic_hw.c
+++ b/drivers/net/qlcnic/qlcnic_hw.c
@@ -375,7 +375,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter,
static int
qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
- unsigned op)
+ u16 vlan_id, unsigned op)
{
struct qlcnic_nic_req req;
struct qlcnic_mac_req *mac_req;
@@ -391,6 +391,8 @@ qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr,
mac_req->op = op;
memcpy(mac_req->mac_addr, addr, 6);
+ req.words[1] = cpu_to_le64(vlan_id);
+
return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1);
}
@@ -415,7 +417,7 @@ static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr)
memcpy(cur->mac_addr, addr, ETH_ALEN);
if (qlcnic_sre_macaddr_change(adapter,
- cur->mac_addr, QLCNIC_MAC_ADD)) {
+ cur->mac_addr, 0, QLCNIC_MAC_ADD)) {
kfree(cur);
return -EIO;
}
@@ -485,7 +487,7 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter)
while (!list_empty(head)) {
cur = list_entry(head->next, struct qlcnic_mac_list_s, list);
qlcnic_sre_macaddr_change(adapter,
- cur->mac_addr, QLCNIC_MAC_DEL);
+ cur->mac_addr, 0, QLCNIC_MAC_DEL);
list_del(&cur->list);
kfree(cur);
}
@@ -506,7 +508,9 @@ void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter)
if (jiffies >
(QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) {
qlcnic_sre_macaddr_change(adapter,
- tmp_fil->faddr, QLCNIC_MAC_DEL);
+ tmp_fil->faddr, tmp_fil->vlan_id,
+ tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL :
+ QLCNIC_MAC_DEL);
spin_lock_bh(&adapter->mac_learn_lock);
adapter->fhash.fnum--;
hlist_del(&tmp_fil->fnode);
@@ -528,8 +532,9 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter)
head = &(adapter->fhash.fhead[i]);
hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) {
- qlcnic_sre_macaddr_change(adapter,
- tmp_fil->faddr, QLCNIC_MAC_DEL);
+ qlcnic_sre_macaddr_change(adapter, tmp_fil->faddr,
+ tmp_fil->vlan_id, tmp_fil->vlan_id ?
+ QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL);
spin_lock_bh(&adapter->mac_learn_lock);
adapter->fhash.fnum--;
hlist_del(&tmp_fil->fnode);
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index 0fbfb53..5a6445a 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -1826,7 +1826,7 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter)
}
static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
- u64 uaddr, struct qlcnic_host_tx_ring *tx_ring)
+ u64 uaddr, u16 vlan_id, struct qlcnic_host_tx_ring *tx_ring)
{
struct cmd_desc_type0 *hwdesc;
struct qlcnic_nic_req *req;
@@ -1845,9 +1845,11 @@ static void qlcnic_change_filter(struct qlcnic_adapter *adapter,
req->req_hdr = cpu_to_le64(word);
mac_req = (struct qlcnic_mac_req *)&(req->words[0]);
- mac_req->op = QLCNIC_MAC_ADD;
+ mac_req->op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD;
memcpy(mac_req->mac_addr, &uaddr, ETH_ALEN);
+ req->words[1] = cpu_to_le64(vlan_id);
+
tx_ring->producer = get_next_index(producer, tx_ring->num_desc);
}
@@ -1865,6 +1867,7 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
struct hlist_node *tmp_hnode, *n;
struct hlist_head *head;
u64 src_addr = 0;
+ u16 vlan_id = 0;
u8 hindex;
if (!compare_ether_addr(phdr->h_source, adapter->mac_addr))
@@ -1873,12 +1876,16 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
if (adapter->fhash.fnum >= adapter->fhash.fmax)
return;
+ /* Only NPAR capable devices support vlan based learning*/
+ if (adapter->flags & QLCNIC_ESWITCH_ENABLED)
+ vlan_id = first_desc->vlan_TCI;
memcpy(&src_addr, phdr->h_source, ETH_ALEN);
hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1);
head = &(adapter->fhash.fhead[hindex]);
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->ftime = jiffies;
return;
}
@@ -1888,9 +1895,10 @@ qlcnic_send_filter(struct qlcnic_adapter *adapter,
if (!fil)
return;
- qlcnic_change_filter(adapter, src_addr, tx_ring);
+ qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring);
fil->ftime = jiffies;
+ fil->vlan_id = vlan_id;
memcpy(fil->faddr, &src_addr, ETH_ALEN);
spin_lock(&adapter->mac_learn_lock);
hlist_add_head(&(fil->fnode), head);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCHv2 NEXT 10/10] qlcnic: add cksum flag
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (8 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 09/10] qlcnic: mac vlan learning support Amit Kumar Salecha
@ 2010-09-01 3:17 ` Amit Kumar Salecha
2010-09-01 17:42 ` [PATCHv2 0/10]qlcnic: Fixes and enhancement David Miller
10 siblings, 0 replies; 12+ messages in thread
From: Amit Kumar Salecha @ 2010-09-01 3:17 UTC (permalink / raw)
To: davem; +Cc: netdev, ameen.rahman, anirban.chakraborty
o New CKSUM flag added by fw to notify cksum is verified.
o Update version to 5.0.9
Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com>
---
drivers/net/qlcnic/qlcnic.h | 7 ++++---
drivers/net/qlcnic/qlcnic_init.c | 3 ++-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 9d21152..cc8385a 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -51,8 +51,8 @@
#define _QLCNIC_LINUX_MAJOR 5
#define _QLCNIC_LINUX_MINOR 0
-#define _QLCNIC_LINUX_SUBVERSION 8
-#define QLCNIC_LINUX_VERSIONID "5.0.8"
+#define _QLCNIC_LINUX_SUBVERSION 9
+#define QLCNIC_LINUX_VERSIONID "5.0.9"
#define QLCNIC_DRV_IDC_VER 0x01
#define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\
(_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
@@ -224,7 +224,8 @@ struct rcv_desc {
#define QLCNIC_LRO_DESC 0x12
/* for status field in status_desc */
-#define STATUS_CKSUM_OK (2)
+#define STATUS_CKSUM_LOOP 0
+#define STATUS_CKSUM_OK 2
/* owner bits of status_desc */
#define STATUS_OWNER_HOST (0x1ULL << 56)
diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c
index 8e0e7a3..8e47d7a 100644
--- a/drivers/net/qlcnic/qlcnic_init.c
+++ b/drivers/net/qlcnic/qlcnic_init.c
@@ -1364,7 +1364,8 @@ static struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter,
skb = buffer->skb;
- if (likely(adapter->rx_csum && cksum == STATUS_CKSUM_OK)) {
+ if (likely(adapter->rx_csum && (cksum == STATUS_CKSUM_OK ||
+ cksum == STATUS_CKSUM_LOOP))) {
adapter->stats.csummed++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else {
--
1.6.0.2
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCHv2 0/10]qlcnic: Fixes and enhancement
2010-09-01 3:17 [PATCHv2 0/10]qlcnic: Fixes and enhancement Amit Kumar Salecha
` (9 preceding siblings ...)
2010-09-01 3:17 ` [PATCHv2 NEXT 10/10] qlcnic: add cksum flag Amit Kumar Salecha
@ 2010-09-01 17:42 ` David Miller
10 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2010-09-01 17:42 UTC (permalink / raw)
To: amit.salecha; +Cc: netdev, ameen.rahman, anirban.chakraborty
From: Amit Kumar Salecha <amit.salecha@qlogic.com>
Date: Tue, 31 Aug 2010 20:17:43 -0700
> Hi
> Series v2 of 10 patches, updating ethtool regs version.
> Please apply them on net-next.
All applied, thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread