diff options
Diffstat (limited to 'drivers/net/benet')
-rw-r--r-- | drivers/net/benet/be.h | 1 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.c | 192 | ||||
-rw-r--r-- | drivers/net/benet/be_cmds.h | 11 | ||||
-rw-r--r-- | drivers/net/benet/be_hw.h | 5 | ||||
-rw-r--r-- | drivers/net/benet/be_main.c | 141 |
5 files changed, 308 insertions, 42 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 67e165cf3f4..dc7c19e4911 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -254,6 +254,7 @@ struct be_adapter { struct vlan_group *vlan_grp; u16 num_vlans; u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; + struct be_dma_mem mc_cmd_mem; struct be_stats_obj stats; /* Work queue used to perform periodic tasks like getting statistics */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index cc75dd0df0d..8bd53156004 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -349,7 +349,11 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) struct be_queue_info *mccq = &adapter->mcc_obj.q; struct be_mcc_wrb *wrb; - BUG_ON(atomic_read(&mccq->used) >= mccq->len); + if (atomic_read(&mccq->used) >= mccq->len) { + dev_err(&adapter->pdev->dev, "Out of MCCQ wrbs\n"); + return NULL; + } + wrb = queue_head_node(mccq); queue_head_inc(mccq); atomic_inc(&mccq->used); @@ -357,6 +361,57 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter) return wrb; } +/* Tell fw we're about to start firing cmds by writing a + * special pattern across the wrb hdr; uses mbox + */ +int be_cmd_fw_init(struct be_adapter *adapter) +{ + u8 *wrb; + int status; + + spin_lock(&adapter->mbox_lock); + + wrb = (u8 *)wrb_from_mbox(adapter); + *wrb++ = 0xFF; + *wrb++ = 0x12; + *wrb++ = 0x34; + *wrb++ = 0xFF; + *wrb++ = 0xFF; + *wrb++ = 0x56; + *wrb++ = 0x78; + *wrb = 0xFF; + + status = be_mbox_notify_wait(adapter); + + spin_unlock(&adapter->mbox_lock); + return status; +} + +/* Tell fw we're done with firing cmds by writing a + * special pattern across the wrb hdr; uses mbox + */ +int be_cmd_fw_clean(struct be_adapter *adapter) +{ + u8 *wrb; + int status; + + spin_lock(&adapter->mbox_lock); + + wrb = (u8 *)wrb_from_mbox(adapter); + *wrb++ = 0xFF; + *wrb++ = 0xAA; + *wrb++ = 0xBB; + *wrb++ = 0xFF; + *wrb++ = 0xFF; + *wrb++ = 0xCC; + *wrb++ = 0xDD; + *wrb = 0xFF; + + status = be_mbox_notify_wait(adapter); + + spin_unlock(&adapter->mbox_lock); + return status; +} int be_cmd_eq_create(struct be_adapter *adapter, struct be_queue_info *eq, int eq_delay) { @@ -448,6 +503,10 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -464,6 +523,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, *pmac_id = le32_to_cpu(resp->pmac_id); } +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -478,6 +538,10 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id) spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -490,8 +554,8 @@ int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id) status = be_mcc_notify_wait(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); - return status; } @@ -810,10 +874,15 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) struct be_mcc_wrb *wrb; struct be_cmd_req_get_stats *req; struct be_sge *sge; + int status = 0; spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = nonemb_cmd->va; sge = nonembedded_sgl(wrb); @@ -828,8 +897,9 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd) be_mcc_notify(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); - return 0; + return status; } /* Uses synchronous mcc */ @@ -843,6 +913,10 @@ int be_cmd_link_status_query(struct be_adapter *adapter, spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); *link_up = false; @@ -862,6 +936,7 @@ int be_cmd_link_status_query(struct be_adapter *adapter, } } +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -900,10 +975,15 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) { struct be_mcc_wrb *wrb; struct be_cmd_req_modify_eq_delay *req; + int status = 0; spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -918,8 +998,9 @@ int be_cmd_modify_eqd(struct be_adapter *adapter, u32 eq_id, u32 eqd) be_mcc_notify(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); - return 0; + return status; } /* Uses sycnhronous mcc */ @@ -933,6 +1014,10 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -951,6 +1036,7 @@ int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, u16 *vtag_array, status = be_mcc_notify_wait(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -967,6 +1053,10 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -981,6 +1071,7 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) status = be_mcc_notify_wait(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -990,24 +1081,34 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) * (mc == NULL) => multicast promiscous */ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, - struct dev_mc_list *mc_list, u32 mc_count) + struct dev_mc_list *mc_list, u32 mc_count, + struct be_dma_mem *mem) { -#define BE_MAX_MC 32 /* set mcast promisc if > 32 */ struct be_mcc_wrb *wrb; - struct be_cmd_req_mcast_mac_config *req; + struct be_cmd_req_mcast_mac_config *req = mem->va; + struct be_sge *sge; + int status; spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); - req = embedded_payload(wrb); + if (!wrb) { + status = -EBUSY; + goto err; + } + sge = nonembedded_sgl(wrb); + memset(req, 0, sizeof(*req)); - be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + sge->pa_hi = cpu_to_le32(upper_32_bits(mem->dma)); + sge->pa_lo = cpu_to_le32(mem->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(mem->size); be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); req->interface_id = if_id; - if (mc_list && mc_count <= BE_MAX_MC) { + if (mc_list) { int i; struct dev_mc_list *mc; @@ -1019,11 +1120,11 @@ int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, req->promiscuous = 1; } - be_mcc_notify_wait(adapter); + status = be_mcc_notify_wait(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); - - return 0; + return status; } /* Uses synchrounous mcc */ @@ -1036,6 +1137,10 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -1048,6 +1153,7 @@ int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc) status = be_mcc_notify_wait(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1062,6 +1168,10 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -1077,6 +1187,7 @@ int be_cmd_get_flow_control(struct be_adapter *adapter, u32 *tx_fc, u32 *rx_fc) *rx_fc = le16_to_cpu(resp->rx_flow_control); } +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1143,6 +1254,10 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -1157,6 +1272,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, status = be_mcc_notify_wait(adapter); +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1171,6 +1287,10 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); @@ -1187,6 +1307,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state) *state = resp->beacon_state; } +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1202,6 +1323,10 @@ int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(struct be_cmd_resp_port_type), true, 0); @@ -1217,6 +1342,7 @@ int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, *connector = resp->data.connector; } +err: spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1232,6 +1358,11 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + req = cmd->va; sge = nonembedded_sgl(wrb); be_wrb_hdr_prepare(wrb, cmd->size, false, 1); @@ -1248,6 +1379,41 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, status = be_mcc_notify_wait(adapter); +err: + spin_unlock_bh(&adapter->mcc_lock); + return status; +} + +int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_write_flashrom *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req)+4, true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_READ_FLASHROM, sizeof(*req)+4); + + req->params.op_type = cpu_to_le32(FLASHROM_TYPE_REDBOOT); + req->params.op_code = cpu_to_le32(FLASHROM_OPER_REPORT); + req->params.offset = 0x3FFFC; + req->params.data_buf_size = 0x4; + + status = be_mcc_notify_wait(adapter); + if (!status) + memcpy(flashed_crc, req->params.data_buf, 4); + +err: spin_unlock_bh(&adapter->mcc_lock); return status; } diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index 69dc017c814..8ec6528cb05 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -118,6 +118,7 @@ struct be_mcc_mailbox { #define OPCODE_COMMON_NTWK_MULTICAST_SET 3 #define OPCODE_COMMON_NTWK_VLAN_CONFIG 4 #define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5 +#define OPCODE_COMMON_READ_FLASHROM 6 #define OPCODE_COMMON_WRITE_FLASHROM 7 #define OPCODE_COMMON_CQ_CREATE 12 #define OPCODE_COMMON_EQ_CREATE 13 @@ -590,6 +591,8 @@ struct be_cmd_req_promiscuous_config { u16 rsvd0; } __packed; +/******************** Multicast MAC Config *******************/ +#define BE_MAX_MC 64 /* set mcast promisc if > 64 */ struct macaddr { u8 byte[ETH_ALEN]; }; @@ -599,7 +602,7 @@ struct be_cmd_req_mcast_mac_config { u16 num_mac; u8 promiscuous; u8 interface_id; - struct macaddr mac[32]; + struct macaddr mac[BE_MAX_MC]; } __packed; static inline struct be_hw_stats * @@ -828,7 +831,8 @@ extern int be_cmd_vlan_config(struct be_adapter *adapter, u32 if_id, extern int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en); extern int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id, - struct dev_mc_list *mc_list, u32 mc_count); + struct dev_mc_list *mc_list, u32 mc_count, + struct be_dma_mem *mem); extern int be_cmd_set_flow_control(struct be_adapter *adapter, u32 tx_fc, u32 rx_fc); extern int be_cmd_get_flow_control(struct be_adapter *adapter, @@ -846,3 +850,6 @@ extern int be_cmd_read_port_type(struct be_adapter *adapter, u32 port, extern int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, u32 flash_oper, u32 flash_opcode, u32 buf_size); +extern int be_cmd_get_flash_crc(struct be_adapter *adapter, u8 *flashed_crc); +extern int be_cmd_fw_init(struct be_adapter *adapter); +extern int be_cmd_fw_clean(struct be_adapter *adapter); diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index a3394b4aa14..f53d5ca2da9 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -225,6 +225,7 @@ struct be_eth_rx_compl { #define NUM_FLASHDIR_ENTRIES 32 #define FLASHROM_TYPE_ISCSI_ACTIVE 0 +#define FLASHROM_TYPE_REDBOOT 1 #define FLASHROM_TYPE_BIOS 2 #define FLASHROM_TYPE_PXE_BIOS 3 #define FLASHROM_TYPE_FCOE_BIOS 8 @@ -234,9 +235,11 @@ struct be_eth_rx_compl { #define FLASHROM_OPER_FLASH 1 #define FLASHROM_OPER_SAVE 2 +#define FLASHROM_OPER_REPORT 4 #define FLASH_IMAGE_MAX_SIZE (1310720) /* Max firmware image size */ #define FLASH_BIOS_IMAGE_MAX_SIZE (262144) /* Max OPTION ROM image sz */ +#define FLASH_REDBOOT_IMAGE_MAX_SIZE (262144) /* Max redboot image sz */ /* Offsets for components on Flash. */ #define FLASH_iSCSI_PRIMARY_IMAGE_START (1048576) @@ -246,6 +249,8 @@ struct be_eth_rx_compl { #define FLASH_iSCSI_BIOS_START (7340032) #define FLASH_PXE_BIOS_START (7864320) #define FLASH_FCoE_BIOS_START (524288) +#define FLASH_REDBOOT_START (32768) +#define FLASH_REDBOOT_ISM_START (0) struct controller_id { u32 vendor; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index c0bd20356ea..79593643949 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -170,7 +170,8 @@ void netdev_stats_update(struct be_adapter *adapter) port_stats->rx_udp_checksum_errs; /* no space in linux buffers: best possible approximation */ - dev_stats->rx_dropped = erx_stats->rx_drops_no_fragments[0]; + dev_stats->rx_dropped = + erx_stats->rx_drops_no_fragments[adapter->rx_obj.q.id]; /* detailed rx errors */ dev_stats->rx_length_errors = port_stats->rx_in_range_errors + @@ -562,13 +563,15 @@ static void be_set_multicast_list(struct net_device *netdev) be_cmd_promiscuous_config(adapter, adapter->port_num, 0); } - if (netdev->flags & IFF_ALLMULTI) { - be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0); + /* Enable multicast promisc if num configured exceeds what we support */ + if (netdev->flags & IFF_ALLMULTI || netdev->mc_count > BE_MAX_MC) { + be_cmd_multicast_set(adapter, adapter->if_handle, NULL, 0, + &adapter->mc_cmd_mem); goto done; } be_cmd_multicast_set(adapter, adapter->if_handle, netdev->mc_list, - netdev->mc_count); + netdev->mc_count, &adapter->mc_cmd_mem); done: return; } @@ -1473,6 +1476,14 @@ static void be_worker(struct work_struct *work) schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); } +static void be_msix_disable(struct be_adapter *adapter) +{ + if (adapter->msix_enabled) { + pci_disable_msix(adapter->pdev); + adapter->msix_enabled = false; + } +} + static void be_msix_enable(struct be_adapter *adapter) { int i, status; @@ -1679,6 +1690,8 @@ static int be_clear(struct be_adapter *adapter) be_cmd_if_destroy(adapter, adapter->if_handle); + /* tell fw we're done with firing cmds */ + be_cmd_fw_clean(adapter); return 0; } @@ -1721,6 +1734,31 @@ static int be_close(struct net_device *netdev) #define FW_FILE_HDR_SIGN "ServerEngines Corp. " char flash_cookie[2][16] = {"*** SE FLAS", "H DIRECTORY *** "}; + +static bool be_flash_redboot(struct be_adapter *adapter, + const u8 *p) +{ + u32 crc_offset; + u8 flashed_crc[4]; + int status; + crc_offset = FLASH_REDBOOT_START + FLASH_REDBOOT_IMAGE_MAX_SIZE - 4 + + sizeof(struct flash_file_hdr) - 32*1024; + p += crc_offset; + status = be_cmd_get_flash_crc(adapter, flashed_crc); + if (status) { + dev_err(&adapter->pdev->dev, + "could not get crc from flash, not flashing redboot\n"); + return false; + } + + /*update redboot only if crc does not match*/ + if (!memcmp(flashed_crc, p, 4)) + return false; + else + return true; + +} + static int be_flash_image(struct be_adapter *adapter, const struct firmware *fw, struct be_dma_mem *flash_cmd, u32 flash_type) @@ -1760,6 +1798,12 @@ static int be_flash_image(struct be_adapter *adapter, image_offset = FLASH_PXE_BIOS_START; image_size = FLASH_BIOS_IMAGE_MAX_SIZE; break; + case FLASHROM_TYPE_REDBOOT: + if (!be_flash_redboot(adapter, fw->data)) + return 0; + image_offset = FLASH_REDBOOT_ISM_START; + image_size = FLASH_REDBOOT_IMAGE_MAX_SIZE; + break; default: return 0; } @@ -1978,34 +2022,61 @@ static void be_ctrl_cleanup(struct be_adapter *adapter) if (mem->va) pci_free_consistent(adapter->pdev, mem->size, mem->va, mem->dma); + + mem = &adapter->mc_cmd_mem; + if (mem->va) + pci_free_consistent(adapter->pdev, mem->size, + mem->va, mem->dma); } static int be_ctrl_init(struct be_adapter *adapter) { struct be_dma_mem *mbox_mem_alloc = &adapter->mbox_mem_alloced; struct be_dma_mem *mbox_mem_align = &adapter->mbox_mem; + struct be_dma_mem *mc_cmd_mem = &adapter->mc_cmd_mem; int status; status = be_map_pci_bars(adapter); if (status) - return status; + goto done; mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev, mbox_mem_alloc->size, &mbox_mem_alloc->dma); if (!mbox_mem_alloc->va) { - be_unmap_pci_bars(adapter); - return -1; + status = -ENOMEM; + goto unmap_pci_bars; } + mbox_mem_align->size = sizeof(struct be_mcc_mailbox); mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); + + mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config); + mc_cmd_mem->va = pci_alloc_consistent(adapter->pdev, mc_cmd_mem->size, + &mc_cmd_mem->dma); + if (mc_cmd_mem->va == NULL) { + status = -ENOMEM; + goto free_mbox; + } + memset(mc_cmd_mem->va, 0, mc_cmd_mem->size); + spin_lock_init(&adapter->mbox_lock); spin_lock_init(&adapter->mcc_lock); spin_lock_init(&adapter->mcc_cq_lock); return 0; + +free_mbox: + pci_free_consistent(adapter->pdev, mbox_mem_alloc->size, + mbox_mem_alloc->va, mbox_mem_alloc->dma); + +unmap_pci_bars: + be_unmap_pci_bars(adapter); + +done: + return status; } static void be_stats_cleanup(struct be_adapter *adapter) @@ -2033,6 +2104,7 @@ static int be_stats_init(struct be_adapter *adapter) static void __devexit be_remove(struct pci_dev *pdev) { struct be_adapter *adapter = pci_get_drvdata(pdev); + if (!adapter) return; @@ -2044,10 +2116,7 @@ static void __devexit be_remove(struct pci_dev *pdev) be_ctrl_cleanup(adapter); - if (adapter->msix_enabled) { - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = false; - } + be_msix_disable(adapter); pci_set_drvdata(pdev, NULL); pci_release_regions(pdev); @@ -2056,25 +2125,28 @@ static void __devexit be_remove(struct pci_dev *pdev) free_netdev(adapter->netdev); } -static int be_hw_up(struct be_adapter *adapter) +static int be_get_config(struct be_adapter *adapter) { int status; + u8 mac[ETH_ALEN]; - status = be_cmd_POST(adapter); + status = be_cmd_get_fw_ver(adapter, adapter->fw_ver); if (status) return status; - status = be_cmd_reset_function(adapter); + status = be_cmd_query_fw_cfg(adapter, + &adapter->port_num, &adapter->cap); if (status) return status; - status = be_cmd_get_fw_ver(adapter, adapter->fw_ver); + memset(mac, 0, ETH_ALEN); + status = be_cmd_mac_addr_query(adapter, mac, + MAC_ADDRESS_TYPE_NETWORK, true /*permanent */, 0); if (status) return status; + memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN); - status = be_cmd_query_fw_cfg(adapter, - &adapter->port_num, &adapter->cap); - return status; + return 0; } static int __devinit be_probe(struct pci_dev *pdev, @@ -2083,7 +2155,6 @@ static int __devinit be_probe(struct pci_dev *pdev, int status = 0; struct be_adapter *adapter; struct net_device *netdev; - u8 mac[ETH_ALEN]; status = pci_enable_device(pdev); if (status) @@ -2103,6 +2174,8 @@ static int __devinit be_probe(struct pci_dev *pdev, adapter->pdev = pdev; pci_set_drvdata(pdev, adapter); adapter->netdev = netdev; + be_netdev_init(netdev); + SET_NETDEV_DEV(netdev, &pdev->dev); be_msix_enable(adapter); @@ -2121,27 +2194,34 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status) goto free_netdev; - status = be_stats_init(adapter); + /* sync up with fw's ready state */ + status = be_cmd_POST(adapter); if (status) goto ctrl_clean; - status = be_hw_up(adapter); + /* tell fw we're ready to fire cmds */ + status = be_cmd_fw_init(adapter); if (status) - goto stats_clean; + goto ctrl_clean; + + status = be_cmd_reset_function(adapter); + if (status) + goto ctrl_clean; + + status = be_stats_init(adapter); + if (status) + goto ctrl_clean; - status = be_cmd_mac_addr_query(adapter, mac, MAC_ADDRESS_TYPE_NETWORK, - true /* permanent */, 0); + status = be_get_config(adapter); if (status) goto stats_clean; - memcpy(netdev->dev_addr, mac, ETH_ALEN); INIT_DELAYED_WORK(&adapter->work, be_worker); - be_netdev_init(netdev); - SET_NETDEV_DEV(netdev, &adapter->pdev->dev); status = be_setup(adapter); if (status) goto stats_clean; + status = register_netdev(netdev); if (status != 0) goto unsetup; @@ -2156,7 +2236,9 @@ stats_clean: ctrl_clean: be_ctrl_cleanup(adapter); free_netdev: + be_msix_disable(adapter); free_netdev(adapter->netdev); + pci_set_drvdata(pdev, NULL); rel_reg: pci_release_regions(pdev); disable_dev: @@ -2201,6 +2283,11 @@ static int be_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_restore_state(pdev); + /* tell fw we're ready to fire cmds */ + status = be_cmd_fw_init(adapter); + if (status) + return status; + be_setup(adapter); if (netif_running(netdev)) { rtnl_lock(); |