diff options
Diffstat (limited to 'drivers/net/benet/be_cmds.c')
| -rw-r--r-- | drivers/net/benet/be_cmds.c | 341 | 
1 files changed, 305 insertions, 36 deletions
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 1e2d825bb94..2463b1c9792 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -71,18 +71,38 @@ static int be_mcc_compl_process(struct be_adapter *adapter,  	compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &  				CQE_STATUS_COMPL_MASK; -	if ((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) && +	if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) || +		(compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) &&  		(compl->tag1 == CMD_SUBSYSTEM_COMMON)) {  		adapter->flash_status = compl_status;  		complete(&adapter->flash_compl);  	}  	if (compl_status == MCC_STATUS_SUCCESS) { -		if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) { -			struct be_cmd_resp_get_stats *resp = -						adapter->stats_cmd.va; -			be_dws_le_to_cpu(&resp->hw_stats, -						sizeof(resp->hw_stats)); +		if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) || +			 (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) && +			(compl->tag1 == CMD_SUBSYSTEM_ETH)) { +			if (adapter->generation == BE_GEN3) { +				if (lancer_chip(adapter)) { +					struct lancer_cmd_resp_pport_stats +						*resp = adapter->stats_cmd.va; +					be_dws_le_to_cpu(&resp->pport_stats, +						sizeof(resp->pport_stats)); +				} else { +					struct be_cmd_resp_get_stats_v1 *resp = +							adapter->stats_cmd.va; + +				be_dws_le_to_cpu(&resp->hw_stats, +							sizeof(resp->hw_stats)); +				} +			} else { +				struct be_cmd_resp_get_stats_v0 *resp = +							adapter->stats_cmd.va; + +				be_dws_le_to_cpu(&resp->hw_stats, +							sizeof(resp->hw_stats)); +			} +			be_parse_stats(adapter);  			netdev_stats_update(adapter);  			adapter->stats_cmd_sent = false;  		} @@ -132,7 +152,7 @@ static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,  		struct be_async_event_grp5_pvid_state *evt)  {  	if (evt->enabled) -		adapter->pvid = evt->tag; +		adapter->pvid = le16_to_cpu(evt->tag);  	else  		adapter->pvid = 0;  } @@ -292,12 +312,12 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)  		if (msecs > 4000) {  			dev_err(&adapter->pdev->dev, "mbox poll timed out\n"); -			be_detect_dump_ue(adapter); +			if (!lancer_chip(adapter)) +				be_detect_dump_ue(adapter);  			return -1;  		} -		set_current_state(TASK_INTERRUPTIBLE); -		schedule_timeout(msecs_to_jiffies(1)); +		msleep(1);  		msecs++;  	} while (true); @@ -374,23 +394,25 @@ int be_cmd_POST(struct be_adapter *adapter)  {  	u16 stage;  	int status, timeout = 0; +	struct device *dev = &adapter->pdev->dev;  	do {  		status = be_POST_stage_get(adapter, &stage);  		if (status) { -			dev_err(&adapter->pdev->dev, "POST error; stage=0x%x\n", -				stage); +			dev_err(dev, "POST error; stage=0x%x\n", stage);  			return -1;  		} else if (stage != POST_STAGE_ARMFW_RDY) { -			set_current_state(TASK_INTERRUPTIBLE); -			schedule_timeout(2 * HZ); +			if (msleep_interruptible(2000)) { +				dev_err(dev, "Waiting for POST aborted\n"); +				return -EINTR; +			}  			timeout += 2;  		} else {  			return 0;  		}  	} while (timeout < 40); -	dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage); +	dev_err(dev, "POST timeout; stage=0x%x\n", stage);  	return -1;  } @@ -728,8 +750,6 @@ int be_cmd_cq_create(struct be_adapter *adapter,  	if (lancer_chip(adapter)) {  		req->hdr.version = 2;  		req->page_size = 1; /* 1 for 4K */ -		AMAP_SET_BITS(struct amap_cq_context_lancer, coalescwm, ctxt, -								coalesce_wm);  		AMAP_SET_BITS(struct amap_cq_context_lancer, nodelay, ctxt,  								no_delay);  		AMAP_SET_BITS(struct amap_cq_context_lancer, count, ctxt, @@ -1074,7 +1094,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)  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_cmd_req_hdr *hdr;  	struct be_sge *sge;  	int status = 0; @@ -1088,14 +1108,62 @@ int be_cmd_get_stats(struct be_adapter *adapter, struct be_dma_mem *nonemb_cmd)  		status = -EBUSY;  		goto err;  	} -	req = nonemb_cmd->va; +	hdr = nonemb_cmd->va;  	sge = nonembedded_sgl(wrb); -	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, +	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1,  			OPCODE_ETH_GET_STATISTICS); +	be_cmd_hdr_prepare(hdr, CMD_SUBSYSTEM_ETH, +		OPCODE_ETH_GET_STATISTICS, nonemb_cmd->size); + +	if (adapter->generation == BE_GEN3) +		hdr->version = 1; + +	wrb->tag1 = CMD_SUBSYSTEM_ETH; +	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); +	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); +	sge->len = cpu_to_le32(nonemb_cmd->size); + +	be_mcc_notify(adapter); +	adapter->stats_cmd_sent = true; + +err: +	spin_unlock_bh(&adapter->mcc_lock); +	return status; +} + +/* Lancer Stats */ +int lancer_cmd_get_pport_stats(struct be_adapter *adapter, +				struct be_dma_mem *nonemb_cmd) +{ + +	struct be_mcc_wrb *wrb; +	struct lancer_cmd_req_pport_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); + +	be_wrb_hdr_prepare(wrb, nonemb_cmd->size, false, 1, +			OPCODE_ETH_GET_PPORT_STATS); +  	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, -		OPCODE_ETH_GET_STATISTICS, sizeof(*req)); +			OPCODE_ETH_GET_PPORT_STATS, nonemb_cmd->size); + + +	req->cmd_params.params.pport_num = cpu_to_le16(adapter->port_num); +	req->cmd_params.params.reset_stats = 0; + +	wrb->tag1 = CMD_SUBSYSTEM_ETH;  	sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma));  	sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF);  	sge->len = cpu_to_le32(nonemb_cmd->size); @@ -1110,7 +1178,7 @@ err:  /* Uses synchronous mcc */  int be_cmd_link_status_query(struct be_adapter *adapter, -			bool *link_up, u8 *mac_speed, u16 *link_speed) +			bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom)  {  	struct be_mcc_wrb *wrb;  	struct be_cmd_req_link_status *req; @@ -1186,6 +1254,116 @@ err:  	return status;  } +/* Uses synchronous mcc */ +int be_cmd_get_reg_len(struct be_adapter *adapter, u32 *log_size) +{ +	struct be_mcc_wrb *wrb; +	struct be_cmd_req_get_fat *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), true, 0, +			OPCODE_COMMON_MANAGE_FAT); + +	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, +		OPCODE_COMMON_MANAGE_FAT, sizeof(*req)); +	req->fat_operation = cpu_to_le32(QUERY_FAT); +	status = be_mcc_notify_wait(adapter); +	if (!status) { +		struct be_cmd_resp_get_fat *resp = embedded_payload(wrb); +		if (log_size && resp->log_size) +			*log_size = le32_to_cpu(resp->log_size) - +					sizeof(u32); +	} +err: +	spin_unlock_bh(&adapter->mcc_lock); +	return status; +} + +void be_cmd_get_regs(struct be_adapter *adapter, u32 buf_len, void *buf) +{ +	struct be_dma_mem get_fat_cmd; +	struct be_mcc_wrb *wrb; +	struct be_cmd_req_get_fat *req; +	struct be_sge *sge; +	u32 offset = 0, total_size, buf_size, +				log_offset = sizeof(u32), payload_len; +	int status; + +	if (buf_len == 0) +		return; + +	total_size = buf_len; + +	get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024; +	get_fat_cmd.va = pci_alloc_consistent(adapter->pdev, +			get_fat_cmd.size, +			&get_fat_cmd.dma); +	if (!get_fat_cmd.va) { +		status = -ENOMEM; +		dev_err(&adapter->pdev->dev, +		"Memory allocation failure while retrieving FAT data\n"); +		return; +	} + +	spin_lock_bh(&adapter->mcc_lock); + +	while (total_size) { +		buf_size = min(total_size, (u32)60*1024); +		total_size -= buf_size; + +		wrb = wrb_from_mccq(adapter); +		if (!wrb) { +			status = -EBUSY; +			goto err; +		} +		req = get_fat_cmd.va; +		sge = nonembedded_sgl(wrb); + +		payload_len = sizeof(struct be_cmd_req_get_fat) + buf_size; +		be_wrb_hdr_prepare(wrb, payload_len, false, 1, +				OPCODE_COMMON_MANAGE_FAT); + +		be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, +				OPCODE_COMMON_MANAGE_FAT, payload_len); + +		sge->pa_hi = cpu_to_le32(upper_32_bits(get_fat_cmd.dma)); +		sge->pa_lo = cpu_to_le32(get_fat_cmd.dma & 0xFFFFFFFF); +		sge->len = cpu_to_le32(get_fat_cmd.size); + +		req->fat_operation = cpu_to_le32(RETRIEVE_FAT); +		req->read_log_offset = cpu_to_le32(log_offset); +		req->read_log_length = cpu_to_le32(buf_size); +		req->data_buffer_size = cpu_to_le32(buf_size); + +		status = be_mcc_notify_wait(adapter); +		if (!status) { +			struct be_cmd_resp_get_fat *resp = get_fat_cmd.va; +			memcpy(buf + offset, +				resp->data_buffer, +				resp->read_log_length); +		} else { +			dev_err(&adapter->pdev->dev, "FAT Table Retrieve error\n"); +			goto err; +		} +		offset += buf_size; +		log_offset += buf_size; +	} +err: +	pci_free_consistent(adapter->pdev, get_fat_cmd.size, +			get_fat_cmd.va, +			get_fat_cmd.dma); +	spin_unlock_bh(&adapter->mcc_lock); +} +  /* Uses Mbox */  int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)  { @@ -1293,12 +1471,24 @@ err:  /* Uses MCC for this command as it may be called in BH context   * Uses synchronous mcc   */ -int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en) +int be_cmd_promiscuous_config(struct be_adapter *adapter, bool en)  {  	struct be_mcc_wrb *wrb; -	struct be_cmd_req_promiscuous_config *req; +	struct be_cmd_req_rx_filter *req; +	struct be_dma_mem promiscous_cmd; +	struct be_sge *sge;  	int status; +	memset(&promiscous_cmd, 0, sizeof(struct be_dma_mem)); +	promiscous_cmd.size = sizeof(struct be_cmd_req_rx_filter); +	promiscous_cmd.va = pci_alloc_consistent(adapter->pdev, +				promiscous_cmd.size, &promiscous_cmd.dma); +	if (!promiscous_cmd.va) { +		dev_err(&adapter->pdev->dev, +				"Memory allocation failure\n"); +		return -ENOMEM; +	} +  	spin_lock_bh(&adapter->mcc_lock);  	wrb = wrb_from_mccq(adapter); @@ -1306,26 +1496,30 @@ int be_cmd_promiscuous_config(struct be_adapter *adapter, u8 port_num, bool en)  		status = -EBUSY;  		goto err;  	} -	req = embedded_payload(wrb); -	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_PROMISCUOUS); +	req = promiscous_cmd.va; +	sge = nonembedded_sgl(wrb); -	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, -		OPCODE_ETH_PROMISCUOUS, sizeof(*req)); +	be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1, +					OPCODE_COMMON_NTWK_RX_FILTER); +	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, +			OPCODE_COMMON_NTWK_RX_FILTER, sizeof(*req)); -	/* In FW versions X.102.149/X.101.487 and later, -	 * the port setting associated only with the -	 * issuing pci function will take effect -	 */ -	if (port_num) -		req->port1_promiscuous = en; -	else -		req->port0_promiscuous = en; +	req->if_id = cpu_to_le32(adapter->if_handle); +	req->if_flags_mask = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); +	if (en) +		req->if_flags = cpu_to_le32(BE_IF_FLAGS_PROMISCUOUS); + +	sge->pa_hi = cpu_to_le32(upper_32_bits(promiscous_cmd.dma)); +	sge->pa_lo = cpu_to_le32(promiscous_cmd.dma & 0xFFFFFFFF); +	sge->len = cpu_to_le32(promiscous_cmd.size);  	status = be_mcc_notify_wait(adapter);  err:  	spin_unlock_bh(&adapter->mcc_lock); +	pci_free_consistent(adapter->pdev, promiscous_cmd.size, +			promiscous_cmd.va, promiscous_cmd.dma);  	return status;  } @@ -1608,6 +1802,81 @@ err:  	return status;  } +int lancer_cmd_write_object(struct be_adapter *adapter, struct be_dma_mem *cmd, +			u32 data_size, u32 data_offset, const char *obj_name, +			u32 *data_written, u8 *addn_status) +{ +	struct be_mcc_wrb *wrb; +	struct lancer_cmd_req_write_object *req; +	struct lancer_cmd_resp_write_object *resp; +	void *ctxt = NULL; +	int status; + +	spin_lock_bh(&adapter->mcc_lock); +	adapter->flash_status = 0; + +	wrb = wrb_from_mccq(adapter); +	if (!wrb) { +		status = -EBUSY; +		goto err_unlock; +	} + +	req = embedded_payload(wrb); + +	be_wrb_hdr_prepare(wrb, sizeof(struct lancer_cmd_req_write_object), +			true, 1, OPCODE_COMMON_WRITE_OBJECT); +	wrb->tag1 = CMD_SUBSYSTEM_COMMON; + +	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, +				OPCODE_COMMON_WRITE_OBJECT, +				sizeof(struct lancer_cmd_req_write_object)); + +	ctxt = &req->context; +	AMAP_SET_BITS(struct amap_lancer_write_obj_context, +			write_length, ctxt, data_size); + +	if (data_size == 0) +		AMAP_SET_BITS(struct amap_lancer_write_obj_context, +				eof, ctxt, 1); +	else +		AMAP_SET_BITS(struct amap_lancer_write_obj_context, +				eof, ctxt, 0); + +	be_dws_cpu_to_le(ctxt, sizeof(req->context)); +	req->write_offset = cpu_to_le32(data_offset); +	strcpy(req->object_name, obj_name); +	req->descriptor_count = cpu_to_le32(1); +	req->buf_len = cpu_to_le32(data_size); +	req->addr_low = cpu_to_le32((cmd->dma + +				sizeof(struct lancer_cmd_req_write_object)) +				& 0xFFFFFFFF); +	req->addr_high = cpu_to_le32(upper_32_bits(cmd->dma + +				sizeof(struct lancer_cmd_req_write_object))); + +	be_mcc_notify(adapter); +	spin_unlock_bh(&adapter->mcc_lock); + +	if (!wait_for_completion_timeout(&adapter->flash_compl, +			msecs_to_jiffies(12000))) +		status = -1; +	else +		status = adapter->flash_status; + +	resp = embedded_payload(wrb); +	if (!status) { +		*data_written = le32_to_cpu(resp->actual_write_len); +	} else { +		*addn_status = resp->additional_status; +		status = resp->status; +	} + +	return status; + +err_unlock: +	spin_unlock_bh(&adapter->mcc_lock); +	return status; +} +  int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd,  			u32 flash_type, u32 flash_opcode, u32 buf_size)  {  |