From 41de8d4cff21a2e81e3d9ff66f5f7c903f9c3ab1 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sun, 29 Jan 2012 13:47:52 +0000 Subject: drivers/net: Remove alloc_etherdev error messages alloc_etherdev has a generic OOM/unable to alloc message. Remove the duplicative messages after alloc_etherdev calls. Signed-off-by: Joe Perches Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c') diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 7dd9a4b107e6..64aa44d5dabb 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1403,7 +1403,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev = alloc_etherdev(sizeof(struct netxen_adapter)); if(!netdev) { - dev_err(&pdev->dev, "failed to allocate net_device\n"); err = -ENOMEM; goto err_out_free_res; } -- cgit v1.2.3 From 83f18a557c6d6cdc03c7821e0b596c8f8b7bdb9f Mon Sep 17 00:00:00 2001 From: Manish chopra Date: Fri, 3 Feb 2012 11:35:11 +0000 Subject: netxen_nic: fw dump support Signed-off-by: Manish Chopra Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 421 +++++++++++++- .../net/ethernet/qlogic/netxen/netxen_nic_ctx.c | 143 +++++ .../ethernet/qlogic/netxen/netxen_nic_ethtool.c | 104 ++++ drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | 629 ++++++++++++++++++++- .../net/ethernet/qlogic/netxen/netxen_nic_init.c | 3 +- .../net/ethernet/qlogic/netxen/netxen_nic_main.c | 102 +++- 6 files changed, 1380 insertions(+), 22 deletions(-) (limited to 'drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c') diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index 1b09ba172310..8a35430b2f8b 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -1154,6 +1154,7 @@ typedef struct { #define NETXEN_NIC_LRO_DISABLED 0x00 #define NETXEN_NIC_BRIDGE_ENABLED 0X10 #define NETXEN_NIC_DIAG_ENABLED 0x20 +#define NETXEN_FW_RESET_OWNER 0x40 #define NETXEN_IS_MSI_FAMILY(adapter) \ ((adapter)->flags & (NETXEN_NIC_MSI_ENABLED | NETXEN_NIC_MSIX_ENABLED)) @@ -1171,6 +1172,419 @@ typedef struct { #define __NX_DEV_UP 1 #define __NX_RESETTING 2 +/* Mini Coredump FW supported version */ +#define NX_MD_SUPPORT_MAJOR 4 +#define NX_MD_SUPPORT_MINOR 0 +#define NX_MD_SUPPORT_SUBVERSION 579 + +#define LSW(x) ((uint16_t)(x)) +#define LSD(x) ((uint32_t)((uint64_t)(x))) +#define MSD(x) ((uint32_t)((((uint64_t)(x)) >> 16) >> 16)) + +/* Mini Coredump mask level */ +#define NX_DUMP_MASK_MIN 0x03 +#define NX_DUMP_MASK_DEF 0x1f +#define NX_DUMP_MASK_MAX 0xff + +/* Mini Coredump CDRP commands */ +#define NX_CDRP_CMD_TEMP_SIZE 0x0000002f +#define NX_CDRP_CMD_GET_TEMP_HDR 0x00000030 + + +#define NX_DUMP_STATE_ARRAY_LEN 16 +#define NX_DUMP_CAP_SIZE_ARRAY_LEN 8 + +/* Mini Coredump sysfs entries flags*/ +#define NX_FORCE_FW_DUMP_KEY 0xdeadfeed +#define NX_ENABLE_FW_DUMP 0xaddfeed +#define NX_DISABLE_FW_DUMP 0xbadfeed +#define NX_FORCE_FW_RESET 0xdeaddead + + +/* Flash read/write address */ +#define NX_FW_DUMP_REG1 0x00130060 +#define NX_FW_DUMP_REG2 0x001e0000 +#define NX_FLASH_SEM2_LK 0x0013C010 +#define NX_FLASH_SEM2_ULK 0x0013C014 +#define NX_FLASH_LOCK_ID 0x001B2100 +#define FLASH_ROM_WINDOW 0x42110030 +#define FLASH_ROM_DATA 0x42150000 + +/* Mini Coredump register read/write routine */ +#define NX_RD_DUMP_REG(addr, bar0, data) do { \ + writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \ + NX_FW_DUMP_REG1)); \ + readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \ + *data = readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + \ + LSW(addr))); \ +} while (0) + +#define NX_WR_DUMP_REG(addr, bar0, data) do { \ + writel((addr & 0xFFFF0000), (void __iomem *) (bar0 + \ + NX_FW_DUMP_REG1)); \ + readl((void __iomem *) (bar0 + NX_FW_DUMP_REG1)); \ + writel(data, (void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr)));\ + readl((void __iomem *) (bar0 + NX_FW_DUMP_REG2 + LSW(addr))); \ +} while (0) + + +/* +Entry Type Defines +*/ + +#define RDNOP 0 +#define RDCRB 1 +#define RDMUX 2 +#define QUEUE 3 +#define BOARD 4 +#define RDSRE 5 +#define RDOCM 6 +#define PREGS 7 +#define L1DTG 8 +#define L1ITG 9 +#define CACHE 10 + +#define L1DAT 11 +#define L1INS 12 +#define RDSTK 13 +#define RDCON 14 + +#define L2DTG 21 +#define L2ITG 22 +#define L2DAT 23 +#define L2INS 24 +#define RDOC3 25 + +#define MEMBK 32 + +#define RDROM 71 +#define RDMEM 72 +#define RDMN 73 + +#define INFOR 81 +#define CNTRL 98 + +#define TLHDR 99 +#define RDEND 255 + +#define PRIMQ 103 +#define SQG2Q 104 +#define SQG3Q 105 + +/* +* Opcodes for Control Entries. +* These Flags are bit fields. +*/ +#define NX_DUMP_WCRB 0x01 +#define NX_DUMP_RWCRB 0x02 +#define NX_DUMP_ANDCRB 0x04 +#define NX_DUMP_ORCRB 0x08 +#define NX_DUMP_POLLCRB 0x10 +#define NX_DUMP_RD_SAVE 0x20 +#define NX_DUMP_WRT_SAVED 0x40 +#define NX_DUMP_MOD_SAVE_ST 0x80 + +/* Driver Flags */ +#define NX_DUMP_SKIP 0x80 /* driver skipped this entry */ +#define NX_DUMP_SIZE_ERR 0x40 /*entry size vs capture size mismatch*/ + +#define NX_PCI_READ_32(ADDR) readl((ADDR)) +#define NX_PCI_WRITE_32(DATA, ADDR) writel(DATA, (ADDR)) + + + +struct netxen_minidump { + u32 pos; /* position in the dump buffer */ + u8 fw_supports_md; /* FW supports Mini cordump */ + u8 has_valid_dump; /* indicates valid dump */ + u8 md_capture_mask; /* driver capture mask */ + u8 md_enabled; /* Turn Mini Coredump on/off */ + u32 md_dump_size; /* Total FW Mini Coredump size */ + u32 md_capture_size; /* FW dump capture size */ + u32 md_template_size; /* FW template size */ + u32 md_template_ver; /* FW template version */ + u64 md_timestamp; /* FW Mini dump timestamp */ + void *md_template; /* FW template will be stored */ + void *md_capture_buff; /* FW dump will be stored */ +}; + + + +struct netxen_minidump_template_hdr { + u32 entry_type; + u32 first_entry_offset; + u32 size_of_template; + u32 capture_mask; + u32 num_of_entries; + u32 version; + u32 driver_timestamp; + u32 checksum; + u32 driver_capture_mask; + u32 driver_info_word2; + u32 driver_info_word3; + u32 driver_info_word4; + u32 saved_state_array[NX_DUMP_STATE_ARRAY_LEN]; + u32 capture_size_array[NX_DUMP_CAP_SIZE_ARRAY_LEN]; + u32 rsvd[0]; +}; + +/* Common Entry Header: Common to All Entry Types */ +/* + * Driver Code is for driver to write some info about the entry. + * Currently not used. + */ + +struct netxen_common_entry_hdr { + u32 entry_type; + u32 entry_size; + u32 entry_capture_size; + union { + struct { + u8 entry_capture_mask; + u8 entry_code; + u8 driver_code; + u8 driver_flags; + }; + u32 entry_ctrl_word; + }; +}; + + +/* Generic Entry Including Header */ +struct netxen_minidump_entry { + struct netxen_common_entry_hdr hdr; + u32 entry_data00; + u32 entry_data01; + u32 entry_data02; + u32 entry_data03; + u32 entry_data04; + u32 entry_data05; + u32 entry_data06; + u32 entry_data07; +}; + +/* Read ROM Header */ +struct netxen_minidump_entry_rdrom { + struct netxen_common_entry_hdr h; + union { + struct { + u32 select_addr_reg; + }; + u32 rsvd_0; + }; + union { + struct { + u8 addr_stride; + u8 addr_cnt; + u16 data_size; + }; + u32 rsvd_1; + }; + union { + struct { + u32 op_count; + }; + u32 rsvd_2; + }; + union { + struct { + u32 read_addr_reg; + }; + u32 rsvd_3; + }; + union { + struct { + u32 write_mask; + }; + u32 rsvd_4; + }; + union { + struct { + u32 read_mask; + }; + u32 rsvd_5; + }; + u32 read_addr; + u32 read_data_size; +}; + + +/* Read CRB and Control Entry Header */ +struct netxen_minidump_entry_crb { + struct netxen_common_entry_hdr h; + u32 addr; + union { + struct { + u8 addr_stride; + u8 state_index_a; + u16 poll_timeout; + }; + u32 addr_cntrl; + }; + u32 data_size; + u32 op_count; + union { + struct { + u8 opcode; + u8 state_index_v; + u8 shl; + u8 shr; + }; + u32 control_value; + }; + u32 value_1; + u32 value_2; + u32 value_3; +}; + +/* Read Memory and MN Header */ +struct netxen_minidump_entry_rdmem { + struct netxen_common_entry_hdr h; + union { + struct { + u32 select_addr_reg; + }; + u32 rsvd_0; + }; + union { + struct { + u8 addr_stride; + u8 addr_cnt; + u16 data_size; + }; + u32 rsvd_1; + }; + union { + struct { + u32 op_count; + }; + u32 rsvd_2; + }; + union { + struct { + u32 read_addr_reg; + }; + u32 rsvd_3; + }; + union { + struct { + u32 cntrl_addr_reg; + }; + u32 rsvd_4; + }; + union { + struct { + u8 wr_byte0; + u8 wr_byte1; + u8 poll_mask; + u8 poll_cnt; + }; + u32 rsvd_5; + }; + u32 read_addr; + u32 read_data_size; +}; + +/* Read Cache L1 and L2 Header */ +struct netxen_minidump_entry_cache { + struct netxen_common_entry_hdr h; + u32 tag_reg_addr; + union { + struct { + u16 tag_value_stride; + u16 init_tag_value; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 control_addr; + union { + struct { + u16 write_value; + u8 poll_mask; + u8 poll_wait; + }; + u32 control_value; + }; + u32 read_addr; + union { + struct { + u8 read_addr_stride; + u8 read_addr_cnt; + u16 rsvd_1; + }; + u32 read_addr_cntrl; + }; +}; + +/* Read OCM Header */ +struct netxen_minidump_entry_rdocm { + struct netxen_common_entry_hdr h; + u32 rsvd_0; + union { + struct { + u32 rsvd_1; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 rsvd_2; + u32 rsvd_3; + u32 read_addr; + union { + struct { + u32 read_addr_stride; + }; + u32 read_addr_cntrl; + }; +}; + +/* Read MUX Header */ +struct netxen_minidump_entry_mux { + struct netxen_common_entry_hdr h; + u32 select_addr; + union { + struct { + u32 rsvd_0; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 select_value; + u32 select_value_stride; + u32 read_addr; + u32 rsvd_1; +}; + +/* Read Queue Header */ +struct netxen_minidump_entry_queue { + struct netxen_common_entry_hdr h; + u32 select_addr; + union { + struct { + u16 queue_id_stride; + u16 rsvd_0; + }; + u32 select_addr_cntrl; + }; + u32 data_size; + u32 op_count; + u32 rsvd_1; + u32 rsvd_2; + u32 read_addr; + union { + struct { + u8 read_addr_stride; + u8 read_addr_cnt; + u16 rsvd_3; + }; + u32 read_addr_cntrl; + }; +}; + struct netxen_dummy_dma { void *addr; dma_addr_t phys_addr; @@ -1275,6 +1689,8 @@ struct netxen_adapter { __le32 file_prd_off; /*File fw product offset*/ u32 fw_version; const struct firmware *fw; + struct netxen_minidump mdump; /* mdump ptr */ + int fw_mdump_rdy; /* for mdump ready */ }; int nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val); @@ -1377,13 +1793,16 @@ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu); int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable); int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable); int netxen_send_lro_cleanup(struct netxen_adapter *adapter); - +int netxen_setup_minidump(struct netxen_adapter *adapter); +void netxen_dump_fw(struct netxen_adapter *adapter); void netxen_nic_update_cmd_producer(struct netxen_adapter *adapter, struct nx_host_tx_ring *tx_ring); /* Functions from netxen_nic_main.c */ int netxen_nic_reset_context(struct netxen_adapter *); +int nx_dev_request_reset(struct netxen_adapter *adapter); + /* * NetXen Board information */ diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index d46e8cb394eb..8f89c05e0c70 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c @@ -83,6 +83,7 @@ netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) printk(KERN_ERR "%s: failed card response code:0x%x\n", netxen_nic_driver_name, rcode); } else if (rsp == NX_CDRP_RSP_OK) { + cmd->rsp.cmd = NX_RCODE_SUCCESS; if (cmd->rsp.arg2) cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET); if (cmd->rsp.arg3) @@ -97,6 +98,148 @@ netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) return rcode; } +static int +netxen_get_minidump_template_size(struct netxen_adapter *adapter) +{ + struct netxen_cmd_args cmd; + memset(&cmd, 0, sizeof(cmd)); + cmd.req.cmd = NX_CDRP_CMD_TEMP_SIZE; + memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); + netxen_issue_cmd(adapter, &cmd); + if (cmd.rsp.cmd != NX_RCODE_SUCCESS) { + dev_info(&adapter->pdev->dev, + "Can't get template size %d\n", cmd.rsp.cmd); + return -EIO; + } + adapter->mdump.md_template_size = cmd.rsp.arg2; + adapter->mdump.md_template_ver = cmd.rsp.arg3; + return 0; +} + +static int +netxen_get_minidump_template(struct netxen_adapter *adapter) +{ + dma_addr_t md_template_addr; + void *addr; + u32 size; + struct netxen_cmd_args cmd; + size = adapter->mdump.md_template_size; + + if (size == 0) { + dev_err(&adapter->pdev->dev, "Can not capture Minidump " + "template. Invalid template size.\n"); + return NX_RCODE_INVALID_ARGS; + } + + addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr); + + if (!addr) { + dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n"); + return -ENOMEM; + } + + memset(addr, 0, size); + memset(&cmd, 0, sizeof(cmd)); + memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); + cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR; + cmd.req.arg1 = LSD(md_template_addr); + cmd.req.arg2 = MSD(md_template_addr); + cmd.req.arg3 |= size; + netxen_issue_cmd(adapter, &cmd); + + if ((cmd.rsp.cmd == NX_RCODE_SUCCESS) && (size == cmd.rsp.arg2)) { + memcpy(adapter->mdump.md_template, addr, size); + } else { + dev_err(&adapter->pdev->dev, "Failed to get minidump template, " + "err_code : %d, requested_size : %d, actual_size : %d\n ", + cmd.rsp.cmd, size, cmd.rsp.arg2); + } + pci_free_consistent(adapter->pdev, size, addr, md_template_addr); + return 0; +} + +static u32 +netxen_check_template_checksum(struct netxen_adapter *adapter) +{ + u64 sum = 0 ; + u32 *buff = adapter->mdump.md_template; + int count = adapter->mdump.md_template_size/sizeof(uint32_t) ; + + while (count-- > 0) + sum += *buff++ ; + while (sum >> 32) + sum = (sum & 0xFFFFFFFF) + (sum >> 32) ; + + return ~sum; +} + +int +netxen_setup_minidump(struct netxen_adapter *adapter) +{ + int err = 0, i; + u32 *template, *tmp_buf; + struct netxen_minidump_template_hdr *hdr; + err = netxen_get_minidump_template_size(adapter); + if (err) { + adapter->mdump.fw_supports_md = 0; + if ((err == NX_RCODE_CMD_INVALID) || + (err == NX_RCODE_CMD_NOT_IMPL)) { + dev_info(&adapter->pdev->dev, + "Flashed firmware version does not support minidump, " + "minimum version required is [ %u.%u.%u ].\n ", + NX_MD_SUPPORT_MAJOR, NX_MD_SUPPORT_MINOR, + NX_MD_SUPPORT_SUBVERSION); + } + return err; + } + + if (!adapter->mdump.md_template_size) { + dev_err(&adapter->pdev->dev, "Error : Invalid template size " + ",should be non-zero.\n"); + return -EIO; + } + adapter->mdump.md_template = + kmalloc(adapter->mdump.md_template_size, GFP_KERNEL); + + if (!adapter->mdump.md_template) { + dev_err(&adapter->pdev->dev, "Unable to allocate memory " + "for minidump template.\n"); + return -ENOMEM; + } + + err = netxen_get_minidump_template(adapter); + if (err) { + if (err == NX_RCODE_CMD_NOT_IMPL) + adapter->mdump.fw_supports_md = 0; + goto free_template; + } + + if (netxen_check_template_checksum(adapter)) { + dev_err(&adapter->pdev->dev, "Minidump template checksum Error\n"); + err = -EIO; + goto free_template; + } + + adapter->mdump.md_capture_mask = NX_DUMP_MASK_DEF; + tmp_buf = (u32 *) adapter->mdump.md_template; + template = (u32 *) adapter->mdump.md_template; + for (i = 0; i < adapter->mdump.md_template_size/sizeof(u32); i++) + *template++ = __le32_to_cpu(*tmp_buf++); + hdr = (struct netxen_minidump_template_hdr *) + adapter->mdump.md_template; + adapter->mdump.md_capture_buff = NULL; + adapter->mdump.fw_supports_md = 1; + adapter->mdump.md_enabled = 1; + + return err; + +free_template: + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + return err; +} + + int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) { diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c index 8a371985319f..3e73d35cceaa 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c @@ -812,6 +812,107 @@ static int netxen_get_intr_coalesce(struct net_device *netdev, return 0; } +static int +netxen_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) +{ + struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_minidump *mdump = &adapter->mdump; + if (adapter->fw_mdump_rdy) + dump->len = mdump->md_dump_size; + else + dump->len = 0; + dump->flag = mdump->md_capture_mask; + dump->version = adapter->fw_version; + return 0; +} + +static int +netxen_set_dump(struct net_device *netdev, struct ethtool_dump *val) +{ + int ret = 0; + struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_minidump *mdump = &adapter->mdump; + + switch (val->flag) { + case NX_FORCE_FW_DUMP_KEY: + if (!mdump->md_enabled) + mdump->md_enabled = 1; + if (adapter->fw_mdump_rdy) { + netdev_info(netdev, "Previous dump not cleared, not forcing dump\n"); + return ret; + } + netdev_info(netdev, "Forcing a fw dump\n"); + nx_dev_request_reset(adapter); + break; + case NX_DISABLE_FW_DUMP: + if (mdump->md_enabled) { + netdev_info(netdev, "Disabling FW Dump\n"); + mdump->md_enabled = 0; + } + break; + case NX_ENABLE_FW_DUMP: + if (!mdump->md_enabled) { + netdev_info(netdev, "Enabling FW dump\n"); + mdump->md_enabled = 1; + } + break; + case NX_FORCE_FW_RESET: + netdev_info(netdev, "Forcing FW reset\n"); + nx_dev_request_reset(adapter); + adapter->flags &= ~NETXEN_FW_RESET_OWNER; + break; + default: + if (val->flag <= NX_DUMP_MASK_MAX && + val->flag >= NX_DUMP_MASK_MIN) { + mdump->md_capture_mask = val->flag & 0xff; + netdev_info(netdev, "Driver mask changed to: 0x%x\n", + mdump->md_capture_mask); + break; + } + netdev_info(netdev, + "Invalid dump level: 0x%x\n", val->flag); + return -EINVAL; + } + + return ret; +} + +static int +netxen_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, + void *buffer) +{ + int i, copy_sz; + u32 *hdr_ptr, *data; + struct netxen_adapter *adapter = netdev_priv(netdev); + struct netxen_minidump *mdump = &adapter->mdump; + + + if (!adapter->fw_mdump_rdy) { + netdev_info(netdev, "Dump not available\n"); + return -EINVAL; + } + /* Copy template header first */ + copy_sz = mdump->md_template_size; + hdr_ptr = (u32 *) mdump->md_template; + data = buffer; + for (i = 0; i < copy_sz/sizeof(u32); i++) + *data++ = cpu_to_le32(*hdr_ptr++); + + /* Copy captured dump data */ + memcpy(buffer + copy_sz, + mdump->md_capture_buff + mdump->md_template_size, + mdump->md_capture_size); + dump->len = copy_sz + mdump->md_capture_size; + dump->flag = mdump->md_capture_mask; + + /* Free dump area once data has been captured */ + vfree(mdump->md_capture_buff); + mdump->md_capture_buff = NULL; + adapter->fw_mdump_rdy = 0; + netdev_info(netdev, "extracted the fw dump Successfully\n"); + return 0; +} + const struct ethtool_ops netxen_nic_ethtool_ops = { .get_settings = netxen_nic_get_settings, .set_settings = netxen_nic_set_settings, @@ -833,4 +934,7 @@ const struct ethtool_ops netxen_nic_ethtool_ops = { .get_sset_count = netxen_get_sset_count, .get_coalesce = netxen_get_intr_coalesce, .set_coalesce = netxen_set_intr_coalesce, + .get_dump_flag = netxen_get_dump_flag, + .get_dump_data = netxen_get_dump_data, + .set_dump = netxen_set_dump, }; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 3f89e57cae50..0a8122851025 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c @@ -46,7 +46,6 @@ static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, void __iomem *addr, u32 data); static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, void __iomem *addr); - #ifndef readq static inline u64 readq(void __iomem *addr) { @@ -1974,3 +1973,631 @@ netxen_nic_wol_supported(struct netxen_adapter *adapter) return 0; } + +static u32 netxen_md_cntrl(struct netxen_adapter *adapter, + struct netxen_minidump_template_hdr *template_hdr, + struct netxen_minidump_entry_crb *crtEntry) +{ + int loop_cnt, i, rv = 0, timeout_flag; + u32 op_count, stride; + u32 opcode, read_value, addr; + unsigned long timeout, timeout_jiffies; + addr = crtEntry->addr; + op_count = crtEntry->op_count; + stride = crtEntry->addr_stride; + + for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { + for (i = 0; i < sizeof(crtEntry->opcode) * 8; i++) { + opcode = (crtEntry->opcode & (0x1 << i)); + if (opcode) { + switch (opcode) { + case NX_DUMP_WCRB: + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + crtEntry->value_1); + break; + case NX_DUMP_RWCRB: + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_ANDCRB: + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + read_value &= crtEntry->value_2; + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_ORCRB: + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + read_value |= crtEntry->value_3; + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_POLLCRB: + timeout = crtEntry->poll_timeout; + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + timeout_jiffies = + msecs_to_jiffies(timeout) + jiffies; + for (timeout_flag = 0; + !timeout_flag + && ((read_value & crtEntry->value_2) + != crtEntry->value_1);) { + if (time_after(jiffies, + timeout_jiffies)) + timeout_flag = 1; + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + } + + if (timeout_flag) { + dev_err(&adapter->pdev->dev, "%s : " + "Timeout in poll_crb control operation.\n" + , __func__); + return -1; + } + break; + case NX_DUMP_RD_SAVE: + /* Decide which address to use */ + if (crtEntry->state_index_a) + addr = + template_hdr->saved_state_array + [crtEntry->state_index_a]; + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + template_hdr->saved_state_array + [crtEntry->state_index_v] + = read_value; + break; + case NX_DUMP_WRT_SAVED: + /* Decide which value to use */ + if (crtEntry->state_index_v) + read_value = + template_hdr->saved_state_array + [crtEntry->state_index_v]; + else + read_value = crtEntry->value_1; + + /* Decide which address to use */ + if (crtEntry->state_index_a) + addr = + template_hdr->saved_state_array + [crtEntry->state_index_a]; + + NX_WR_DUMP_REG(addr, + adapter->ahw.pci_base0, + read_value); + break; + case NX_DUMP_MOD_SAVE_ST: + read_value = + template_hdr->saved_state_array + [crtEntry->state_index_v]; + read_value <<= crtEntry->shl; + read_value >>= crtEntry->shr; + if (crtEntry->value_2) + read_value &= + crtEntry->value_2; + read_value |= crtEntry->value_3; + read_value += crtEntry->value_1; + /* Write value back to state area.*/ + template_hdr->saved_state_array + [crtEntry->state_index_v] + = read_value; + break; + default: + rv = 1; + break; + } + } + } + addr = addr + stride; + } + return rv; +} + +/* Read memory or MN */ +static u32 +netxen_md_rdmem(struct netxen_adapter *adapter, + struct netxen_minidump_entry_rdmem + *memEntry, u64 *data_buff) +{ + u64 addr, value = 0; + int i = 0, loop_cnt; + + addr = (u64)memEntry->read_addr; + loop_cnt = memEntry->read_data_size; /* This is size in bytes */ + loop_cnt /= sizeof(value); + + for (i = 0; i < loop_cnt; i++) { + if (netxen_nic_pci_mem_read_2M(adapter, addr, &value)) + goto out; + *data_buff++ = value; + addr += sizeof(value); + } +out: + return i * sizeof(value); +} + +/* Read CRB operation */ +static u32 netxen_md_rd_crb(struct netxen_adapter *adapter, + struct netxen_minidump_entry_crb + *crbEntry, u32 *data_buff) +{ + int loop_cnt; + u32 op_count, addr, stride, value; + + addr = crbEntry->addr; + op_count = crbEntry->op_count; + stride = crbEntry->addr_stride; + + for (loop_cnt = 0; loop_cnt < op_count; loop_cnt++) { + NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, &value); + *data_buff++ = addr; + *data_buff++ = value; + addr = addr + stride; + } + return loop_cnt * (2 * sizeof(u32)); +} + +/* Read ROM */ +static u32 +netxen_md_rdrom(struct netxen_adapter *adapter, + struct netxen_minidump_entry_rdrom + *romEntry, u32 *data_buff) +{ + int i, count = 0; + u32 size, lck_val; + u32 val; + u32 fl_addr, waddr, raddr; + fl_addr = romEntry->read_addr; + size = romEntry->read_data_size/4; +lock_try: + lck_val = readl((void __iomem *)(adapter->ahw.pci_base0 + + NX_FLASH_SEM2_LK)); + if (!lck_val && count < MAX_CTL_CHECK) { + msleep(20); + count++; + goto lock_try; + } + writel(adapter->ahw.pci_func, (void __iomem *)(adapter->ahw.pci_base0 + + NX_FLASH_LOCK_ID)); + for (i = 0; i < size; i++) { + waddr = fl_addr & 0xFFFF0000; + NX_WR_DUMP_REG(FLASH_ROM_WINDOW, adapter->ahw.pci_base0, waddr); + raddr = FLASH_ROM_DATA + (fl_addr & 0x0000FFFF); + NX_RD_DUMP_REG(raddr, adapter->ahw.pci_base0, &val); + *data_buff++ = cpu_to_le32(val); + fl_addr += sizeof(val); + } + readl((void __iomem *)(adapter->ahw.pci_base0 + NX_FLASH_SEM2_ULK)); + return romEntry->read_data_size; +} + +/* Handle L2 Cache */ +static u32 +netxen_md_L2Cache(struct netxen_adapter *adapter, + struct netxen_minidump_entry_cache + *cacheEntry, u32 *data_buff) +{ + int loop_cnt, i, k, timeout_flag = 0; + u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr; + u32 tag_value, read_cnt; + u8 cntl_value_w, cntl_value_r; + unsigned long timeout, timeout_jiffies; + + loop_cnt = cacheEntry->op_count; + read_addr = cacheEntry->read_addr; + cntrl_addr = cacheEntry->control_addr; + cntl_value_w = (u32) cacheEntry->write_value; + tag_reg_addr = cacheEntry->tag_reg_addr; + tag_value = cacheEntry->init_tag_value; + read_cnt = cacheEntry->read_addr_cnt; + + for (i = 0; i < loop_cnt; i++) { + NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value); + if (cntl_value_w) + NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, + (u32)cntl_value_w); + if (cacheEntry->poll_mask) { + timeout = cacheEntry->poll_wait; + NX_RD_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, + &cntl_value_r); + timeout_jiffies = msecs_to_jiffies(timeout) + jiffies; + for (timeout_flag = 0; !timeout_flag && + ((cntl_value_r & cacheEntry->poll_mask) != 0);) { + if (time_after(jiffies, timeout_jiffies)) + timeout_flag = 1; + NX_RD_DUMP_REG(cntrl_addr, + adapter->ahw.pci_base0, + &cntl_value_r); + } + if (timeout_flag) { + dev_err(&adapter->pdev->dev, + "Timeout in processing L2 Tag poll.\n"); + return -1; + } + } + addr = read_addr; + for (k = 0; k < read_cnt; k++) { + NX_RD_DUMP_REG(addr, adapter->ahw.pci_base0, + &read_value); + *data_buff++ = read_value; + addr += cacheEntry->read_addr_stride; + } + tag_value += cacheEntry->tag_value_stride; + } + return read_cnt * loop_cnt * sizeof(read_value); +} + + +/* Handle L1 Cache */ +static u32 netxen_md_L1Cache(struct netxen_adapter *adapter, + struct netxen_minidump_entry_cache + *cacheEntry, u32 *data_buff) +{ + int i, k, loop_cnt; + u32 addr, read_addr, read_value, cntrl_addr, tag_reg_addr; + u32 tag_value, read_cnt; + u8 cntl_value_w; + + loop_cnt = cacheEntry->op_count; + read_addr = cacheEntry->read_addr; + cntrl_addr = cacheEntry->control_addr; + cntl_value_w = (u32) cacheEntry->write_value; + tag_reg_addr = cacheEntry->tag_reg_addr; + tag_value = cacheEntry->init_tag_value; + read_cnt = cacheEntry->read_addr_cnt; + + for (i = 0; i < loop_cnt; i++) { + NX_WR_DUMP_REG(tag_reg_addr, adapter->ahw.pci_base0, tag_value); + NX_WR_DUMP_REG(cntrl_addr, adapter->ahw.pci_base0, + (u32) cntl_value_w); + addr = read_addr; + for (k = 0; k < read_cnt; k++) { + NX_RD_DUMP_REG(addr, + adapter->ahw.pci_base0, + &read_value); + *data_buff++ = read_value; + addr += cacheEntry->read_addr_stride; + } + tag_value += cacheEntry->tag_value_stride; + } + return read_cnt * loop_cnt * sizeof(read_value); +} + +/* Reading OCM memory */ +static u32 +netxen_md_rdocm(struct netxen_adapter *adapter, + struct netxen_minidump_entry_rdocm + *ocmEntry, u32 *data_buff) +{ + int i, loop_cnt; + u32 value; + void __iomem *addr; + addr = (ocmEntry->read_addr + adapter->ahw.pci_base0); + loop_cnt = ocmEntry->op_count; + + for (i = 0; i < loop_cnt; i++) { + value = readl(addr); + *data_buff++ = value; + addr += ocmEntry->read_addr_stride; + } + return i * sizeof(u32); +} + +/* Read MUX data */ +static u32 +netxen_md_rdmux(struct netxen_adapter *adapter, struct netxen_minidump_entry_mux + *muxEntry, u32 *data_buff) +{ + int loop_cnt = 0; + u32 read_addr, read_value, select_addr, sel_value; + + read_addr = muxEntry->read_addr; + sel_value = muxEntry->select_value; + select_addr = muxEntry->select_addr; + + for (loop_cnt = 0; loop_cnt < muxEntry->op_count; loop_cnt++) { + NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, sel_value); + NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, &read_value); + *data_buff++ = sel_value; + *data_buff++ = read_value; + sel_value += muxEntry->select_value_stride; + } + return loop_cnt * (2 * sizeof(u32)); +} + +/* Handling Queue State Reads */ +static u32 +netxen_md_rdqueue(struct netxen_adapter *adapter, + struct netxen_minidump_entry_queue + *queueEntry, u32 *data_buff) +{ + int loop_cnt, k; + u32 queue_id, read_addr, read_value, read_stride, select_addr, read_cnt; + + read_cnt = queueEntry->read_addr_cnt; + read_stride = queueEntry->read_addr_stride; + select_addr = queueEntry->select_addr; + + for (loop_cnt = 0, queue_id = 0; loop_cnt < queueEntry->op_count; + loop_cnt++) { + NX_WR_DUMP_REG(select_addr, adapter->ahw.pci_base0, queue_id); + read_addr = queueEntry->read_addr; + for (k = 0; k < read_cnt; k--) { + NX_RD_DUMP_REG(read_addr, adapter->ahw.pci_base0, + &read_value); + *data_buff++ = read_value; + read_addr += read_stride; + } + queue_id += queueEntry->queue_id_stride; + } + return loop_cnt * (read_cnt * sizeof(read_value)); +} + + +/* +* We catch an error where driver does not read +* as much data as we expect from the entry. +*/ + +static int netxen_md_entry_err_chk(struct netxen_adapter *adapter, + struct netxen_minidump_entry *entry, u32 esize) +{ + if (esize < 0) { + entry->hdr.driver_flags |= NX_DUMP_SKIP; + return esize; + } + if (esize != entry->hdr.entry_capture_size) { + entry->hdr.entry_capture_size = esize; + entry->hdr.driver_flags |= NX_DUMP_SIZE_ERR; + dev_info(&adapter->pdev->dev, + "Invalidate dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", + entry->hdr.entry_type, entry->hdr.entry_capture_mask, + esize, entry->hdr.entry_capture_size); + dev_info(&adapter->pdev->dev, "Aborting further dump capture\n"); + } + return 0; +} + +static int netxen_parse_md_template(struct netxen_adapter *adapter) +{ + int num_of_entries, buff_level, e_cnt, esize; + int end_cnt = 0, rv = 0, sane_start = 0, sane_end = 0; + char *dbuff; + void *template_buff = adapter->mdump.md_template; + char *dump_buff = adapter->mdump.md_capture_buff; + int capture_mask = adapter->mdump.md_capture_mask; + struct netxen_minidump_template_hdr *template_hdr; + struct netxen_minidump_entry *entry; + + if ((capture_mask & 0x3) != 0x3) { + dev_err(&adapter->pdev->dev, "Capture mask %02x below minimum needed " + "for valid firmware dump\n", capture_mask); + return -EINVAL; + } + template_hdr = (struct netxen_minidump_template_hdr *) template_buff; + num_of_entries = template_hdr->num_of_entries; + entry = (struct netxen_minidump_entry *) ((char *) template_buff + + template_hdr->first_entry_offset); + memcpy(dump_buff, template_buff, adapter->mdump.md_template_size); + dump_buff = dump_buff + adapter->mdump.md_template_size; + + if (template_hdr->entry_type == TLHDR) + sane_start = 1; + + for (e_cnt = 0, buff_level = 0; e_cnt < num_of_entries; e_cnt++) { + if (!(entry->hdr.entry_capture_mask & capture_mask)) { + entry->hdr.driver_flags |= NX_DUMP_SKIP; + entry = (struct netxen_minidump_entry *) + ((char *) entry + entry->hdr.entry_size); + continue; + } + switch (entry->hdr.entry_type) { + case RDNOP: + entry->hdr.driver_flags |= NX_DUMP_SKIP; + break; + case RDEND: + entry->hdr.driver_flags |= NX_DUMP_SKIP; + if (!sane_end) + end_cnt = e_cnt; + sane_end += 1; + break; + case CNTRL: + rv = netxen_md_cntrl(adapter, + template_hdr, (void *)entry); + if (rv) + entry->hdr.driver_flags |= NX_DUMP_SKIP; + break; + case RDCRB: + dbuff = dump_buff + buff_level; + esize = netxen_md_rd_crb(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case RDMN: + case RDMEM: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdmem(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case BOARD: + case RDROM: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdrom(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case L2ITG: + case L2DTG: + case L2DAT: + case L2INS: + dbuff = dump_buff + buff_level; + esize = netxen_md_L2Cache(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case L1DAT: + case L1INS: + dbuff = dump_buff + buff_level; + esize = netxen_md_L1Cache(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case RDOCM: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdocm(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case RDMUX: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdmux(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + case QUEUE: + dbuff = dump_buff + buff_level; + esize = netxen_md_rdqueue(adapter, + (void *) entry, (void *) dbuff); + rv = netxen_md_entry_err_chk + (adapter, entry, esize); + if (rv < 0) + break; + buff_level += esize; + break; + default: + entry->hdr.driver_flags |= NX_DUMP_SKIP; + break; + } + /* Next entry in the template */ + entry = (struct netxen_minidump_entry *) + ((char *) entry + entry->hdr.entry_size); + } + if (!sane_start || sane_end > 1) { + dev_err(&adapter->pdev->dev, + "Firmware minidump template configuration error.\n"); + } + return 0; +} + +static int +netxen_collect_minidump(struct netxen_adapter *adapter) +{ + int ret = 0; + struct netxen_minidump_template_hdr *hdr; + struct timespec val; + hdr = (struct netxen_minidump_template_hdr *) + adapter->mdump.md_template; + hdr->driver_capture_mask = adapter->mdump.md_capture_mask; + jiffies_to_timespec(jiffies, &val); + hdr->driver_timestamp = (u32) val.tv_sec; + hdr->driver_info_word2 = adapter->fw_version; + hdr->driver_info_word3 = NXRD32(adapter, CRB_DRIVER_VERSION); + ret = netxen_parse_md_template(adapter); + if (ret) + return ret; + + return ret; +} + + +void +netxen_dump_fw(struct netxen_adapter *adapter) +{ + struct netxen_minidump_template_hdr *hdr; + int i, k, data_size = 0; + u32 capture_mask; + hdr = (struct netxen_minidump_template_hdr *) + adapter->mdump.md_template; + capture_mask = adapter->mdump.md_capture_mask; + + for (i = 0x2, k = 1; (i & NX_DUMP_MASK_MAX); i <<= 1, k++) { + if (i & capture_mask) + data_size += hdr->capture_size_array[k]; + } + if (!data_size) { + dev_err(&adapter->pdev->dev, + "Invalid cap sizes for capture_mask=0x%x\n", + adapter->mdump.md_capture_mask); + return; + } + adapter->mdump.md_capture_size = data_size; + adapter->mdump.md_dump_size = adapter->mdump.md_template_size + + adapter->mdump.md_capture_size; + if (!adapter->mdump.md_capture_buff) { + adapter->mdump.md_capture_buff = + vmalloc(adapter->mdump.md_dump_size); + if (!adapter->mdump.md_capture_buff) { + dev_info(&adapter->pdev->dev, + "Unable to allocate memory for minidump " + "capture_buffer(%d bytes).\n", + adapter->mdump.md_dump_size); + return; + } + memset(adapter->mdump.md_capture_buff, 0, + adapter->mdump.md_dump_size); + if (netxen_collect_minidump(adapter)) { + adapter->mdump.has_valid_dump = 0; + adapter->mdump.md_dump_size = 0; + vfree(adapter->mdump.md_capture_buff); + adapter->mdump.md_capture_buff = NULL; + dev_err(&adapter->pdev->dev, + "Error in collecting firmware minidump.\n"); + } else { + adapter->mdump.md_timestamp = jiffies; + adapter->mdump.has_valid_dump = 1; + adapter->fw_mdump_rdy = 1; + dev_info(&adapter->pdev->dev, "%s Successfully " + "collected fw dump.\n", adapter->netdev->name); + } + + } else { + dev_info(&adapter->pdev->dev, + "Cannot overwrite previously collected " + "firmware minidump.\n"); + adapter->fw_mdump_rdy = 1; + return; + } +} diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 094d26c51816..f69ac442c6a1 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -446,7 +446,7 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter) /* resetall */ netxen_rom_lock(adapter); - NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); + NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xfeffffff); netxen_rom_unlock(adapter); if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { @@ -1347,7 +1347,6 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) do { val = NXRD32(adapter, CRB_CMDPEG_STATE); - switch (val) { case PHAN_INITIALIZE_COMPLETE: case PHAN_INITIALIZE_ACK: diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 64aa44d5dabb..f67655f3462c 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -82,7 +82,6 @@ static void netxen_create_sysfs_entries(struct netxen_adapter *adapter); static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); static void netxen_create_diag_entries(struct netxen_adapter *adapter); static void netxen_remove_diag_entries(struct netxen_adapter *adapter); - static int nx_dev_request_aer(struct netxen_adapter *adapter); static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); static int netxen_can_start_firmware(struct netxen_adapter *adapter); @@ -802,10 +801,10 @@ err_out: static void netxen_check_options(struct netxen_adapter *adapter) { - u32 fw_major, fw_minor, fw_build; + u32 fw_major, fw_minor, fw_build, prev_fw_version; char brd_name[NETXEN_MAX_SHORT_NAME]; char serial_num[32]; - int i, offset, val; + int i, offset, val, err; int *ptr32; struct pci_dev *pdev = adapter->pdev; @@ -826,9 +825,22 @@ netxen_check_options(struct netxen_adapter *adapter) fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); - + prev_fw_version = adapter->fw_version; adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); + /* Get FW Mini Coredump template and store it */ + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (adapter->mdump.md_template == NULL || + adapter->fw_version > prev_fw_version) { + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + err = netxen_setup_minidump(adapter); + if (err) + dev_err(&adapter->pdev->dev, + "Failed to setup minidump rcode = %d\n", err); + } + } + if (adapter->portnum == 0) { get_brd_name_by_type(adapter->ahw.board_type, brd_name); @@ -909,7 +921,12 @@ netxen_start_firmware(struct netxen_adapter *adapter) if (err) return err; - if (!netxen_can_start_firmware(adapter)) + err = netxen_can_start_firmware(adapter); + + if (err < 0) + return err; + + if (!err) goto wait_init; first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); @@ -1528,6 +1545,18 @@ err_out_disable_pdev: return err; } +static +void netxen_cleanup_minidump(struct netxen_adapter *adapter) +{ + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + + if (adapter->mdump.md_capture_buff) { + vfree(adapter->mdump.md_capture_buff); + adapter->mdump.md_capture_buff = NULL; + } +} + static void __devexit netxen_nic_remove(struct pci_dev *pdev) { struct netxen_adapter *adapter; @@ -1563,8 +1592,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_release_firmware(adapter); - if (NX_IS_REVISION_P3(pdev->revision)) + if (NX_IS_REVISION_P3(pdev->revision)) { + netxen_cleanup_minidump(adapter); pci_disable_pcie_error_reporting(pdev); + } pci_release_regions(pdev); pci_disable_device(pdev); @@ -2316,7 +2347,7 @@ nx_incr_dev_ref_cnt(struct netxen_adapter *adapter) static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) { - int count; + int count, state; if (netxen_api_lock(adapter)) return -EIO; @@ -2324,8 +2355,9 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) WARN_ON(count == 0); NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); + state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (count == 0) + if (count == 0 && state != NX_DEV_FAILED) NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); netxen_api_unlock(adapter); @@ -2354,7 +2386,7 @@ nx_dev_request_aer(struct netxen_adapter *adapter) return ret; } -static int +int nx_dev_request_reset(struct netxen_adapter *adapter) { u32 state; @@ -2365,10 +2397,11 @@ nx_dev_request_reset(struct netxen_adapter *adapter) state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (state == NX_DEV_NEED_RESET) + if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) ret = 0; else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) { NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); + adapter->flags |= NETXEN_FW_RESET_OWNER; ret = 0; } @@ -2383,8 +2416,10 @@ netxen_can_start_firmware(struct netxen_adapter *adapter) int count; int can_start = 0; - if (netxen_api_lock(adapter)) - return 0; + if (netxen_api_lock(adapter)) { + nx_incr_dev_ref_cnt(adapter); + return -1; + } count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); @@ -2456,8 +2491,31 @@ netxen_fwinit_work(struct work_struct *work) struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, fw_work.work); int dev_state; - + int count; dev_state = NXRD32(adapter, NX_CRB_DEV_STATE); + if (adapter->flags & NETXEN_FW_RESET_OWNER) { + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + WARN_ON(count == 0); + if (count == 1) { + if (adapter->mdump.md_enabled) { + rtnl_lock(); + netxen_dump_fw(adapter); + rtnl_unlock(); + } + adapter->flags &= ~NETXEN_FW_RESET_OWNER; + if (netxen_api_lock(adapter)) { + clear_bit(__NX_RESETTING, &adapter->state); + NXWR32(adapter, NX_CRB_DEV_STATE, + NX_DEV_FAILED); + return; + } + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); + dev_state = NX_DEV_COLD; + netxen_api_unlock(adapter); + } + } switch (dev_state) { case NX_DEV_COLD: @@ -2470,11 +2528,9 @@ netxen_fwinit_work(struct work_struct *work) case NX_DEV_NEED_RESET: case NX_DEV_INITALIZING: - if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { netxen_schedule_work(adapter, netxen_fwinit_work, 2 * FW_POLL_DELAY); return; - } case NX_DEV_FAILED: default: @@ -2482,6 +2538,15 @@ netxen_fwinit_work(struct work_struct *work) break; } + if (netxen_api_lock(adapter)) { + clear_bit(__NX_RESETTING, &adapter->state); + return; + } + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_FAILED); + netxen_api_unlock(adapter); + dev_err(&adapter->pdev->dev, "%s: Device initialization Failed\n", + adapter->netdev->name); + clear_bit(__NX_RESETTING, &adapter->state); } @@ -2491,7 +2556,7 @@ netxen_detach_work(struct work_struct *work) struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, fw_work.work); struct net_device *netdev = adapter->netdev; - int ref_cnt, delay; + int ref_cnt = 0, delay; u32 status; netif_device_detach(netdev); @@ -2510,7 +2575,8 @@ netxen_detach_work(struct work_struct *work) if (adapter->temp == NX_TEMP_PANIC) goto err_ret; - ref_cnt = nx_decr_dev_ref_cnt(adapter); + if (!(adapter->flags & NETXEN_FW_RESET_OWNER)) + ref_cnt = nx_decr_dev_ref_cnt(adapter); if (ref_cnt == -EIO) goto err_ret; @@ -2550,7 +2616,7 @@ netxen_check_health(struct netxen_adapter *adapter) * Send request to destroy context in case of tx timeout only * and doesn't required in case of Fw hang */ - if (state == NX_DEV_NEED_RESET) { + if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) { adapter->need_fw_reset = 1; if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) goto detach; -- cgit v1.2.3 From 5471aed0259298e4e258b8a9e403ebdf88ebcd56 Mon Sep 17 00:00:00 2001 From: Sritej Velaga Date: Fri, 3 Feb 2012 11:35:13 +0000 Subject: netxen_nic: Error logging on firmware hang Log states of essential registers on firmware hang detection. Signed-off-by: Sritej Velaga Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h | 1 + .../net/ethernet/qlogic/netxen/netxen_nic_main.c | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c') diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h index dc1967c1f312..b1a897cd9a8d 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hdr.h @@ -969,6 +969,7 @@ enum { #define NX_RCODE_FATAL_ERROR 0x80000000 #define NX_FWERROR_PEGNUM(code) ((code) & 0xff) #define NX_FWERROR_CODE(code) ((code >> 8) & 0xfffff) +#define NX_FWERROR_PEGSTAT1(code) ((code >> 8) & 0x1fffff) #define FW_POLL_DELAY (2 * HZ) #define FW_FAIL_THRESH 3 diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index f67655f3462c..f517c16bfa3f 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -2596,6 +2596,7 @@ static int netxen_check_health(struct netxen_adapter *adapter) { u32 state, heartbit; + u32 peg_status; struct net_device *netdev = adapter->netdev; state = NXRD32(adapter, NX_CRB_DEV_STATE); @@ -2642,8 +2643,24 @@ netxen_check_health(struct netxen_adapter *adapter) clear_bit(__NX_FW_ATTACHED, &adapter->state); - dev_info(&netdev->dev, "firmware hang detected\n"); - + dev_err(&netdev->dev, "firmware hang detected\n"); + peg_status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1); + dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n" + "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n" + "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n" + "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n" + "PEG_NET_4_PC: 0x%x\n", + peg_status, + NXRD32(adapter, NETXEN_PEG_HALT_STATUS2), + NXRD32(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_4 + 0x3c)); + if (NX_FWERROR_PEGSTAT1(peg_status) == 0x67) + dev_err(&adapter->pdev->dev, + "Firmware aborted with error code 0x00006700. " + "Device is being reset.\n"); detach: if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) && !test_and_set_bit(__NX_RESETTING, &adapter->state)) -- cgit v1.2.3 From b8c30812b479a53b717ad665728df55d30f784d5 Mon Sep 17 00:00:00 2001 From: Rajesh Borundia Date: Fri, 3 Feb 2012 11:35:14 +0000 Subject: netxen: Fix a panic during driver unload in device_remove_file o Pass adapter->pdev->dev instead of netdev->dev Signed-off-by: Rajesh Borundia Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c') diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index f517c16bfa3f..8dc4a134dece 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -2930,13 +2930,12 @@ static struct bin_attribute bin_attr_mem = { static void netxen_create_sysfs_entries(struct netxen_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - struct device *dev = &netdev->dev; + struct device *dev = &adapter->pdev->dev; if (adapter->capabilities & NX_FW_CAPABILITY_BDG) { /* bridged_mode control */ if (device_create_file(dev, &dev_attr_bridged_mode)) { - dev_warn(&netdev->dev, + dev_warn(dev, "failed to create bridged_mode sysfs entry\n"); } } @@ -2945,8 +2944,7 @@ netxen_create_sysfs_entries(struct netxen_adapter *adapter) static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - struct device *dev = &netdev->dev; + struct device *dev = &adapter->pdev->dev; if (adapter->capabilities & NX_FW_CAPABILITY_BDG) device_remove_file(dev, &dev_attr_bridged_mode); -- cgit v1.2.3 From 504f9b5a6bb5336ad434438d0cdd61a16db80129 Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Tue, 21 Feb 2012 02:07:49 +0000 Subject: ethernet: unify return value of .ndo_set_mac_address if address is invalid Unify return value of .ndo_set_mac_address if the given address isn't valid. Return -EADDRNOTAVAIL as eth_mac_addr() already does if is_valid_ether_addr() fails. Signed-off-by: Danny Kukawka Signed-off-by: David S. Miller --- drivers/net/ethernet/aeroflex/greth.c | 2 +- drivers/net/ethernet/broadcom/bnx2.c | 2 +- drivers/net/ethernet/broadcom/tg3.c | 2 +- drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c | 2 +- drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 2 +- drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c | 2 +- drivers/net/ethernet/dlink/sundance.c | 2 +- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- drivers/net/ethernet/marvell/pxa168_eth.c | 2 +- drivers/net/ethernet/neterion/s2io.c | 2 +- drivers/net/ethernet/pasemi/pasemi_mac.c | 2 +- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 2 +- drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 +- drivers/net/ethernet/sfc/efx.c | 2 +- drivers/net/ethernet/sun/niu.c | 2 +- drivers/net/ethernet/ti/davinci_emac.c | 2 +- drivers/net/ethernet/tile/tilepro.c | 2 +- drivers/net/ethernet/tundra/tsi108_eth.c | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) (limited to 'drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c') diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index cfa13481e5f2..348501178089 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -1017,7 +1017,7 @@ static int greth_set_mac_add(struct net_device *dev, void *p) regs = (struct greth_regs *) greth->regs; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); GRETH_REGSAVE(regs->esa_msb, dev->dev_addr[0] << 8 | dev->dev_addr[1]); diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 7105989ba658..8297e2868736 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -7773,7 +7773,7 @@ bnx2_change_mac_addr(struct net_device *dev, void *p) struct bnx2 *bp = netdev_priv(dev); if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); if (netif_running(dev)) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index ec5bc3d04333..97dcccdb9eb2 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -8045,7 +8045,7 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) int err = 0, skip_mac_1 = 0; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c index 857cc254cab8..63bfdd10bd6d 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c +++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c @@ -2499,7 +2499,7 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p) struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); t3_mac_set_address(&pi->mac, LAN_MAC_IDX, dev->dev_addr); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index e83d12c7bf20..1d889427073f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -2809,7 +2809,7 @@ static int cxgb_set_mac_addr(struct net_device *dev, void *p) struct port_info *pi = netdev_priv(dev); if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; ret = t4_change_mac(pi->adapter, pi->adapter->fn, pi->viid, pi->xact_addr_filt, addr->sa_data, true, true); diff --git a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c index 9045a451d4a9..3f580c0c28a6 100644 --- a/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c @@ -1130,7 +1130,7 @@ static int cxgb4vf_set_mac_addr(struct net_device *dev, void *_addr) struct port_info *pi = netdev_priv(dev); if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; ret = t4vf_change_mac(pi->adapter, pi->viid, pi->xact_addr_filt, addr->sa_data, true); diff --git a/drivers/net/ethernet/dlink/sundance.c b/drivers/net/ethernet/dlink/sundance.c index 7227f29ee2ee..d783f4f96ec0 100644 --- a/drivers/net/ethernet/dlink/sundance.c +++ b/drivers/net/ethernet/dlink/sundance.c @@ -1601,7 +1601,7 @@ static int sundance_set_mac_addr(struct net_device *dev, void *data) const struct sockaddr *addr = data; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); __set_mac_addr(dev); diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index f702d0dc18c7..75af1afe46c8 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1832,7 +1832,7 @@ static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr) struct sockaddr *sa = addr; if (!is_valid_ether_addr(sa->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); diff --git a/drivers/net/ethernet/marvell/pxa168_eth.c b/drivers/net/ethernet/marvell/pxa168_eth.c index 83e37ad113e0..3a7df0593c68 100644 --- a/drivers/net/ethernet/marvell/pxa168_eth.c +++ b/drivers/net/ethernet/marvell/pxa168_eth.c @@ -627,7 +627,7 @@ static int pxa168_eth_set_mac_address(struct net_device *dev, void *addr) unsigned char oldMac[ETH_ALEN]; if (!is_valid_ether_addr(sa->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(oldMac, dev->dev_addr, ETH_ALEN); dev->addr_assign_type &= ~NET_ADDR_RANDOM; memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN); diff --git a/drivers/net/ethernet/neterion/s2io.c b/drivers/net/ethernet/neterion/s2io.c index 44a6065794c3..22a8de00bf02 100644 --- a/drivers/net/ethernet/neterion/s2io.c +++ b/drivers/net/ethernet/neterion/s2io.c @@ -5248,7 +5248,7 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p) struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c index 667498ea4603..ddc95b0ac78d 100644 --- a/drivers/net/ethernet/pasemi/pasemi_mac.c +++ b/drivers/net/ethernet/pasemi/pasemi_mac.c @@ -238,7 +238,7 @@ static int pasemi_mac_set_mac_addr(struct net_device *dev, void *p) unsigned int adr0, adr1; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 8dc4a134dece..7648995ea720 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -518,7 +518,7 @@ static int netxen_nic_set_mac(struct net_device *netdev, void *p) struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; if (netif_running(netdev)) { netif_device_detach(netdev); diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index dba95311a462..81bb1a69e69f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -301,7 +301,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) return -EOPNOTSUPP; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { netif_device_detach(netdev); diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index c7004dcb5838..1908ba7ca7e6 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1935,7 +1935,7 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data) netif_err(efx, drv, efx->net_dev, "invalid ethernet MAC address requested: %pM\n", new_addr); - return -EINVAL; + return -EADDRNOTAVAIL; } memcpy(net_dev->dev_addr, new_addr, net_dev->addr_len); diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index d83c50816714..c99b3b0e2eae 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -6412,7 +6412,7 @@ static int niu_set_mac_addr(struct net_device *dev, void *p) unsigned long flags; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index f053aebbaa06..6d74cb7aaae8 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1254,7 +1254,7 @@ static int emac_dev_setmac_addr(struct net_device *ndev, void *addr) struct sockaddr *sa = addr; if (!is_valid_ether_addr(sa->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; /* Store mac addr in priv and rx channel and set it in EMAC hw */ memcpy(priv->mac_addr, sa->sa_data, ndev->addr_len); diff --git a/drivers/net/ethernet/tile/tilepro.c b/drivers/net/ethernet/tile/tilepro.c index 948c4f2a2d67..261356c2dc99 100644 --- a/drivers/net/ethernet/tile/tilepro.c +++ b/drivers/net/ethernet/tile/tilepro.c @@ -2186,7 +2186,7 @@ static int tile_net_set_mac_address(struct net_device *dev, void *p) struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; /* ISSUE: Note that "dev_addr" is now a pointer. */ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); diff --git a/drivers/net/ethernet/tundra/tsi108_eth.c b/drivers/net/ethernet/tundra/tsi108_eth.c index fc5521c9c089..840e0e9031f5 100644 --- a/drivers/net/ethernet/tundra/tsi108_eth.c +++ b/drivers/net/ethernet/tundra/tsi108_eth.c @@ -1148,7 +1148,7 @@ static int tsi108_set_mac(struct net_device *dev, void *addr) int i; if (!is_valid_ether_addr(addr)) - return -EINVAL; + return -EADDRNOTAVAIL; for (i = 0; i < 6; i++) /* +2 is for the offset of the HW addr type */ -- cgit v1.2.3 From 06d6c1087605b38342eb20e74b0cacb8b71f5086 Mon Sep 17 00:00:00 2001 From: Santosh Nayak Date: Mon, 12 Mar 2012 22:58:24 +0000 Subject: netxen: qlogic ethernet : Fix endian bug. Change the datatype of "ip_addr" to __be32 as 'ip' should be in big endian format. Adapter needs "ip address" in big endian format stored at lower 32bit of req.word[1]. netxen_config_ipaddr() now receives 'ip' in big endian format. To satisfy adapter's need, use memcpy() to copy byte by byte of 'ip' into lower 32bit of req.word[1]. Mac address and serial number of adapter need to be in little endian format. Change the data type of the related variables to __le32 / __le64 or cast it explicitly to __le32 / __le64 depending upon the requirement. Signed-off-by: Santosh Nayak Signed-off-by: David S. Miller --- drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 4 ++-- drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | 10 +++++----- drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c') diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index 2eeac32f7fdd..b5de8a7b90f1 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h @@ -954,7 +954,7 @@ typedef struct nx_mac_list_s { struct nx_vlan_ip_list { struct list_head list; - u32 ip_addr; + __be32 ip_addr; }; /* @@ -1780,7 +1780,7 @@ int netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max); void netxen_p3_free_mac_list(struct netxen_adapter *adapter); int netxen_config_intr_coalesce(struct netxen_adapter *adapter); int netxen_config_rss(struct netxen_adapter *adapter, int enable); -int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd); +int netxen_config_ipaddr(struct netxen_adapter *adapter, __be32 ip, int cmd); int netxen_linkevent_request(struct netxen_adapter *adapter, int enable); void netxen_advert_link_change(struct netxen_adapter *adapter, int linkup); void netxen_pci_camqm_read_2M(struct netxen_adapter *, u64, u64 *); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 6f37470750f3..de96a948bb7f 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c @@ -909,7 +909,7 @@ int netxen_config_rss(struct netxen_adapter *adapter, int enable) return rv; } -int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd) +int netxen_config_ipaddr(struct netxen_adapter *adapter, __be32 ip, int cmd) { nx_nic_req_t req; u64 word; @@ -922,7 +922,7 @@ int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd) req.req_hdr = cpu_to_le64(word); req.words[0] = cpu_to_le64(cmd); - req.words[1] = cpu_to_le64(ip); + memcpy(&req.words[1], &ip, sizeof(u32)); rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); if (rv != 0) { @@ -1050,7 +1050,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac) if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1) return -1; - if (*mac == cpu_to_le64(~0ULL)) { + if (*mac == ~0ULL) { offset = NX_OLD_MAC_ADDR_OFFSET + (adapter->portnum * sizeof(u64)); @@ -1059,7 +1059,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac) offset, sizeof(u64), pmac) == -1) return -1; - if (*mac == cpu_to_le64(~0ULL)) + if (*mac == ~0ULL) return -1; } return 0; @@ -2155,7 +2155,7 @@ static u32 netxen_md_rd_crb(struct netxen_adapter *adapter, static u32 netxen_md_rdrom(struct netxen_adapter *adapter, struct netxen_minidump_entry_rdrom - *romEntry, u32 *data_buff) + *romEntry, __le32 *data_buff) { int i, count = 0; u32 size, lck_val; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 7648995ea720..65a718f9ccd3 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -805,12 +805,12 @@ netxen_check_options(struct netxen_adapter *adapter) char brd_name[NETXEN_MAX_SHORT_NAME]; char serial_num[32]; int i, offset, val, err; - int *ptr32; + __le32 *ptr32; struct pci_dev *pdev = adapter->pdev; adapter->driver_mismatch = 0; - ptr32 = (int *)&serial_num; + ptr32 = (__le32 *)&serial_num; offset = NX_FW_SERIAL_NUM_OFFSET; for (i = 0; i < 8; i++) { if (netxen_rom_fast_read(adapter, offset, &val) == -1) { -- cgit v1.2.3