| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 1 | /** | 
| Jayamohan Kallickal | 255fa9a | 2011-03-25 14:23:57 -0700 | [diff] [blame] | 2 |  * Copyright (C) 2005 - 2011 Emulex | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 3 |  * All rights reserved. | 
 | 4 |  * | 
 | 5 |  * This program is free software; you can redistribute it and/or | 
 | 6 |  * modify it under the terms of the GNU General Public License version 2 | 
 | 7 |  * as published by the Free Software Foundation.  The full GNU General | 
 | 8 |  * Public License is included in this distribution in the file called COPYING. | 
 | 9 |  * | 
 | 10 |  * Contact Information: | 
| Jayamohan Kallickal | 255fa9a | 2011-03-25 14:23:57 -0700 | [diff] [blame] | 11 |  * linux-drivers@emulex.com | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 12 |  * | 
| Jayamohan Kallickal | 255fa9a | 2011-03-25 14:23:57 -0700 | [diff] [blame] | 13 |  * Emulex | 
 | 14 |  * 3333 Susan Street | 
 | 15 |  * Costa Mesa, CA 92626 | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 16 |  */ | 
 | 17 |  | 
 | 18 | #include "be.h" | 
 | 19 | #include "be_mgmt.h" | 
 | 20 | #include "be_main.h" | 
 | 21 |  | 
| Jayamohan Kallickal | e9b9119 | 2010-07-22 04:24:53 +0530 | [diff] [blame] | 22 | int beiscsi_pci_soft_reset(struct beiscsi_hba *phba) | 
 | 23 | { | 
 | 24 | 	u32 sreset; | 
 | 25 | 	u8 *pci_reset_offset = 0; | 
 | 26 | 	u8 *pci_online0_offset = 0; | 
 | 27 | 	u8 *pci_online1_offset = 0; | 
 | 28 | 	u32 pconline0 = 0; | 
 | 29 | 	u32 pconline1 = 0; | 
 | 30 | 	u32 i; | 
 | 31 |  | 
 | 32 | 	pci_reset_offset = (u8 *)phba->pci_va + BE2_SOFT_RESET; | 
 | 33 | 	pci_online0_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE0; | 
 | 34 | 	pci_online1_offset = (u8 *)phba->pci_va + BE2_PCI_ONLINE1; | 
 | 35 | 	sreset = readl((void *)pci_reset_offset); | 
 | 36 | 	sreset |= BE2_SET_RESET; | 
 | 37 | 	writel(sreset, (void *)pci_reset_offset); | 
 | 38 |  | 
 | 39 | 	i = 0; | 
 | 40 | 	while (sreset & BE2_SET_RESET) { | 
 | 41 | 		if (i > 64) | 
 | 42 | 			break; | 
 | 43 | 		msleep(100); | 
 | 44 | 		sreset = readl((void *)pci_reset_offset); | 
 | 45 | 		i++; | 
 | 46 | 	} | 
 | 47 |  | 
 | 48 | 	if (sreset & BE2_SET_RESET) { | 
 | 49 | 		printk(KERN_ERR "Soft Reset  did not deassert\n"); | 
 | 50 | 		return -EIO; | 
 | 51 | 	} | 
 | 52 | 	pconline1 = BE2_MPU_IRAM_ONLINE; | 
 | 53 | 	writel(pconline0, (void *)pci_online0_offset); | 
 | 54 | 	writel(pconline1, (void *)pci_online1_offset); | 
 | 55 |  | 
 | 56 | 	sreset = BE2_SET_RESET; | 
 | 57 | 	writel(sreset, (void *)pci_reset_offset); | 
 | 58 |  | 
 | 59 | 	i = 0; | 
 | 60 | 	while (sreset & BE2_SET_RESET) { | 
 | 61 | 		if (i > 64) | 
 | 62 | 			break; | 
 | 63 | 		msleep(1); | 
 | 64 | 		sreset = readl((void *)pci_reset_offset); | 
 | 65 | 		i++; | 
 | 66 | 	} | 
 | 67 | 	if (sreset & BE2_SET_RESET) { | 
 | 68 | 		printk(KERN_ERR "MPU Online Soft Reset did not deassert\n"); | 
 | 69 | 		return -EIO; | 
 | 70 | 	} | 
 | 71 | 	return 0; | 
 | 72 | } | 
 | 73 |  | 
 | 74 | int be_chk_reset_complete(struct beiscsi_hba *phba) | 
 | 75 | { | 
 | 76 | 	unsigned int num_loop; | 
 | 77 | 	u8 *mpu_sem = 0; | 
 | 78 | 	u32 status; | 
 | 79 |  | 
 | 80 | 	num_loop = 1000; | 
 | 81 | 	mpu_sem = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; | 
 | 82 | 	msleep(5000); | 
 | 83 |  | 
 | 84 | 	while (num_loop) { | 
 | 85 | 		status = readl((void *)mpu_sem); | 
 | 86 |  | 
 | 87 | 		if ((status & 0x80000000) || (status & 0x0000FFFF) == 0xC000) | 
 | 88 | 			break; | 
 | 89 | 		msleep(60); | 
 | 90 | 		num_loop--; | 
 | 91 | 	} | 
 | 92 |  | 
 | 93 | 	if ((status & 0x80000000) || (!num_loop)) { | 
 | 94 | 		printk(KERN_ERR "Failed in be_chk_reset_complete" | 
 | 95 | 		"status = 0x%x\n", status); | 
 | 96 | 		return -EIO; | 
 | 97 | 	} | 
 | 98 |  | 
 | 99 | 	return 0; | 
 | 100 | } | 
 | 101 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 102 | void be_mcc_notify(struct beiscsi_hba *phba) | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 103 | { | 
 | 104 | 	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 
 | 105 | 	u32 val = 0; | 
 | 106 |  | 
 | 107 | 	val |= mccq->id & DB_MCCQ_RING_ID_MASK; | 
 | 108 | 	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT; | 
 | 109 | 	iowrite32(val, phba->db_va + DB_MCCQ_OFFSET); | 
 | 110 | } | 
 | 111 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 112 | unsigned int alloc_mcc_tag(struct beiscsi_hba *phba) | 
 | 113 | { | 
 | 114 | 	unsigned int tag = 0; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 115 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 116 | 	if (phba->ctrl.mcc_tag_available) { | 
 | 117 | 		tag = phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index]; | 
 | 118 | 		phba->ctrl.mcc_tag[phba->ctrl.mcc_alloc_index] = 0; | 
 | 119 | 		phba->ctrl.mcc_numtag[tag] = 0; | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 120 | 	} | 
 | 121 | 	if (tag) { | 
 | 122 | 		phba->ctrl.mcc_tag_available--; | 
 | 123 | 		if (phba->ctrl.mcc_alloc_index == (MAX_MCC_CMD - 1)) | 
 | 124 | 			phba->ctrl.mcc_alloc_index = 0; | 
 | 125 | 		else | 
 | 126 | 			phba->ctrl.mcc_alloc_index++; | 
 | 127 | 	} | 
 | 128 | 	return tag; | 
 | 129 | } | 
 | 130 |  | 
 | 131 | void free_mcc_tag(struct be_ctrl_info *ctrl, unsigned int tag) | 
 | 132 | { | 
 | 133 | 	spin_lock(&ctrl->mbox_lock); | 
 | 134 | 	tag = tag & 0x000000FF; | 
 | 135 | 	ctrl->mcc_tag[ctrl->mcc_free_index] = tag; | 
 | 136 | 	if (ctrl->mcc_free_index == (MAX_MCC_CMD - 1)) | 
 | 137 | 		ctrl->mcc_free_index = 0; | 
 | 138 | 	else | 
 | 139 | 		ctrl->mcc_free_index++; | 
 | 140 | 	ctrl->mcc_tag_available++; | 
 | 141 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 142 | } | 
 | 143 |  | 
 | 144 | bool is_link_state_evt(u32 trailer) | 
 | 145 | { | 
 | 146 | 	return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | 
 | 147 | 		  ASYNC_TRAILER_EVENT_CODE_MASK) == | 
 | 148 | 		  ASYNC_EVENT_CODE_LINK_STATE); | 
 | 149 | } | 
 | 150 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 151 | static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) | 
 | 152 | { | 
 | 153 | 	if (compl->flags != 0) { | 
 | 154 | 		compl->flags = le32_to_cpu(compl->flags); | 
 | 155 | 		WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); | 
 | 156 | 		return true; | 
 | 157 | 	} else | 
 | 158 | 		return false; | 
 | 159 | } | 
 | 160 |  | 
 | 161 | static inline void be_mcc_compl_use(struct be_mcc_compl *compl) | 
 | 162 | { | 
 | 163 | 	compl->flags = 0; | 
 | 164 | } | 
 | 165 |  | 
 | 166 | static int be_mcc_compl_process(struct be_ctrl_info *ctrl, | 
 | 167 | 				struct be_mcc_compl *compl) | 
 | 168 | { | 
 | 169 | 	u16 compl_status, extd_status; | 
 | 170 |  | 
 | 171 | 	be_dws_le_to_cpu(compl, 4); | 
 | 172 |  | 
 | 173 | 	compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | 
 | 174 | 					CQE_STATUS_COMPL_MASK; | 
 | 175 | 	if (compl_status != MCC_STATUS_SUCCESS) { | 
 | 176 | 		extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | 
 | 177 | 						CQE_STATUS_EXTD_MASK; | 
 | 178 | 		dev_err(&ctrl->pdev->dev, | 
 | 179 | 			"error in cmd completion: status(compl/extd)=%d/%d\n", | 
 | 180 | 			compl_status, extd_status); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 181 | 		return -EBUSY; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 182 | 	} | 
 | 183 | 	return 0; | 
 | 184 | } | 
 | 185 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 186 | int be_mcc_compl_process_isr(struct be_ctrl_info *ctrl, | 
 | 187 | 				    struct be_mcc_compl *compl) | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 188 | { | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 189 | 	u16 compl_status, extd_status; | 
 | 190 | 	unsigned short tag; | 
 | 191 |  | 
 | 192 | 	be_dws_le_to_cpu(compl, 4); | 
 | 193 |  | 
 | 194 | 	compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | 
 | 195 | 					CQE_STATUS_COMPL_MASK; | 
 | 196 | 	/* The ctrl.mcc_numtag[tag] is filled with | 
 | 197 | 	 * [31] = valid, [30:24] = Rsvd, [23:16] = wrb, [15:8] = extd_status, | 
 | 198 | 	 * [7:0] = compl_status | 
 | 199 | 	 */ | 
 | 200 | 	tag = (compl->tag0 & 0x000000FF); | 
 | 201 | 	extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | 
 | 202 | 					CQE_STATUS_EXTD_MASK; | 
 | 203 |  | 
 | 204 | 	ctrl->mcc_numtag[tag]  = 0x80000000; | 
 | 205 | 	ctrl->mcc_numtag[tag] |= (compl->tag0 & 0x00FF0000); | 
 | 206 | 	ctrl->mcc_numtag[tag] |= (extd_status & 0x000000FF) << 8; | 
 | 207 | 	ctrl->mcc_numtag[tag] |= (compl_status & 0x000000FF); | 
 | 208 | 	wake_up_interruptible(&ctrl->mcc_wait[tag]); | 
 | 209 | 	return 0; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 210 | } | 
 | 211 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 212 | static struct be_mcc_compl *be_mcc_compl_get(struct beiscsi_hba *phba) | 
 | 213 | { | 
 | 214 | 	struct be_queue_info *mcc_cq = &phba->ctrl.mcc_obj.cq; | 
 | 215 | 	struct be_mcc_compl *compl = queue_tail_node(mcc_cq); | 
 | 216 |  | 
 | 217 | 	if (be_mcc_compl_is_new(compl)) { | 
 | 218 | 		queue_tail_inc(mcc_cq); | 
 | 219 | 		return compl; | 
 | 220 | 	} | 
 | 221 | 	return NULL; | 
 | 222 | } | 
 | 223 |  | 
 | 224 | static void be2iscsi_fail_session(struct iscsi_cls_session *cls_session) | 
 | 225 | { | 
 | 226 | 	iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED); | 
 | 227 | } | 
 | 228 |  | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 229 | void beiscsi_async_link_state_process(struct beiscsi_hba *phba, | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 230 | 		struct be_async_event_link_state *evt) | 
 | 231 | { | 
 | 232 | 	switch (evt->port_link_status) { | 
 | 233 | 	case ASYNC_EVENT_LINK_DOWN: | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 234 | 		SE_DEBUG(DBG_LVL_1, "Link Down on Physical Port %d\n", | 
 | 235 | 				     evt->physical_port); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 236 | 		phba->state |= BE_ADAPTER_LINK_DOWN; | 
| Jayamohan Kallickal | da7408c | 2010-01-05 05:11:23 +0530 | [diff] [blame] | 237 | 		iscsi_host_for_each_session(phba->shost, | 
 | 238 | 					    be2iscsi_fail_session); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 239 | 		break; | 
 | 240 | 	case ASYNC_EVENT_LINK_UP: | 
 | 241 | 		phba->state = BE_ADAPTER_UP; | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 242 | 		SE_DEBUG(DBG_LVL_1, "Link UP on Physical Port %d\n", | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 243 | 						evt->physical_port); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 244 | 		break; | 
 | 245 | 	default: | 
 | 246 | 		SE_DEBUG(DBG_LVL_1, "Unexpected Async Notification %d on" | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 247 | 				    "Physical Port %d\n", | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 248 | 				     evt->port_link_status, | 
 | 249 | 				     evt->physical_port); | 
 | 250 | 	} | 
 | 251 | } | 
 | 252 |  | 
 | 253 | static void beiscsi_cq_notify(struct beiscsi_hba *phba, u16 qid, bool arm, | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 254 | 		       u16 num_popped) | 
 | 255 | { | 
 | 256 | 	u32 val = 0; | 
 | 257 | 	val |= qid & DB_CQ_RING_ID_MASK; | 
 | 258 | 	if (arm) | 
 | 259 | 		val |= 1 << DB_CQ_REARM_SHIFT; | 
 | 260 | 	val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 261 | 	iowrite32(val, phba->db_va + DB_CQ_OFFSET); | 
 | 262 | } | 
 | 263 |  | 
 | 264 |  | 
| Jayamohan Kallickal | 35e6601 | 2009-10-23 11:53:49 +0530 | [diff] [blame] | 265 | int beiscsi_process_mcc(struct beiscsi_hba *phba) | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 266 | { | 
 | 267 | 	struct be_mcc_compl *compl; | 
 | 268 | 	int num = 0, status = 0; | 
 | 269 | 	struct be_ctrl_info *ctrl = &phba->ctrl; | 
 | 270 |  | 
 | 271 | 	spin_lock_bh(&phba->ctrl.mcc_cq_lock); | 
 | 272 | 	while ((compl = be_mcc_compl_get(phba))) { | 
 | 273 | 		if (compl->flags & CQE_FLAGS_ASYNC_MASK) { | 
 | 274 | 			/* Interpret flags as an async trailer */ | 
| Jayamohan Kallickal | 78b9fb6 | 2009-11-25 01:41:37 +0530 | [diff] [blame] | 275 | 			if (is_link_state_evt(compl->flags)) | 
 | 276 | 				/* Interpret compl as a async link evt */ | 
 | 277 | 				beiscsi_async_link_state_process(phba, | 
 | 278 | 				   (struct be_async_event_link_state *) compl); | 
 | 279 | 			else | 
 | 280 | 				SE_DEBUG(DBG_LVL_1, | 
 | 281 | 					 " Unsupported Async Event, flags" | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 282 | 					 " = 0x%08x\n", compl->flags); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 283 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 284 | 		} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) { | 
 | 285 | 				status = be_mcc_compl_process(ctrl, compl); | 
 | 286 | 				atomic_dec(&phba->ctrl.mcc_obj.q.used); | 
 | 287 | 		} | 
 | 288 | 		be_mcc_compl_use(compl); | 
 | 289 | 		num++; | 
 | 290 | 	} | 
 | 291 |  | 
 | 292 | 	if (num) | 
 | 293 | 		beiscsi_cq_notify(phba, phba->ctrl.mcc_obj.cq.id, true, num); | 
 | 294 |  | 
 | 295 | 	spin_unlock_bh(&phba->ctrl.mcc_cq_lock); | 
 | 296 | 	return status; | 
 | 297 | } | 
 | 298 |  | 
 | 299 | /* Wait till no more pending mcc requests are present */ | 
 | 300 | static int be_mcc_wait_compl(struct beiscsi_hba *phba) | 
 | 301 | { | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 302 | 	int i, status; | 
 | 303 | 	for (i = 0; i < mcc_timeout; i++) { | 
| Jayamohan Kallickal | 35e6601 | 2009-10-23 11:53:49 +0530 | [diff] [blame] | 304 | 		status = beiscsi_process_mcc(phba); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 305 | 		if (status) | 
 | 306 | 			return status; | 
 | 307 |  | 
 | 308 | 		if (atomic_read(&phba->ctrl.mcc_obj.q.used) == 0) | 
 | 309 | 			break; | 
 | 310 | 		udelay(100); | 
 | 311 | 	} | 
 | 312 | 	if (i == mcc_timeout) { | 
 | 313 | 		dev_err(&phba->pcidev->dev, "mccq poll timed out\n"); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 314 | 		return -EBUSY; | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 315 | 	} | 
 | 316 | 	return 0; | 
 | 317 | } | 
 | 318 |  | 
 | 319 | /* Notify MCC requests and wait for completion */ | 
 | 320 | int be_mcc_notify_wait(struct beiscsi_hba *phba) | 
 | 321 | { | 
 | 322 | 	be_mcc_notify(phba); | 
 | 323 | 	return be_mcc_wait_compl(phba); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 324 | } | 
 | 325 |  | 
 | 326 | static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) | 
 | 327 | { | 
 | 328 | #define long_delay 2000 | 
 | 329 | 	void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | 
 | 330 | 	int cnt = 0, wait = 5;	/* in usecs */ | 
 | 331 | 	u32 ready; | 
 | 332 |  | 
 | 333 | 	do { | 
 | 334 | 		ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; | 
 | 335 | 		if (ready) | 
 | 336 | 			break; | 
 | 337 |  | 
| Jayamohan Kallickal | 91446f0 | 2010-10-06 23:45:21 +0530 | [diff] [blame] | 338 | 		if (cnt > 12000000) { | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 339 | 			dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n"); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 340 | 			return -EBUSY; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 341 | 		} | 
 | 342 |  | 
 | 343 | 		if (cnt > 50) { | 
 | 344 | 			wait = long_delay; | 
 | 345 | 			mdelay(long_delay / 1000); | 
 | 346 | 		} else | 
 | 347 | 			udelay(wait); | 
 | 348 | 		cnt += wait; | 
 | 349 | 	} while (true); | 
 | 350 | 	return 0; | 
 | 351 | } | 
 | 352 |  | 
 | 353 | int be_mbox_notify(struct be_ctrl_info *ctrl) | 
 | 354 | { | 
 | 355 | 	int status; | 
 | 356 | 	u32 val = 0; | 
 | 357 | 	void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | 
 | 358 | 	struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; | 
 | 359 | 	struct be_mcc_mailbox *mbox = mbox_mem->va; | 
 | 360 | 	struct be_mcc_compl *compl = &mbox->compl; | 
 | 361 |  | 
 | 362 | 	val &= ~MPU_MAILBOX_DB_RDY_MASK; | 
 | 363 | 	val |= MPU_MAILBOX_DB_HI_MASK; | 
 | 364 | 	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; | 
 | 365 | 	iowrite32(val, db); | 
 | 366 |  | 
 | 367 | 	status = be_mbox_db_ready_wait(ctrl); | 
 | 368 | 	if (status != 0) { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 369 | 		SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 370 | 		return status; | 
 | 371 | 	} | 
 | 372 | 	val = 0; | 
 | 373 | 	val &= ~MPU_MAILBOX_DB_RDY_MASK; | 
 | 374 | 	val &= ~MPU_MAILBOX_DB_HI_MASK; | 
 | 375 | 	val |= (u32) (mbox_mem->dma >> 4) << 2; | 
 | 376 | 	iowrite32(val, db); | 
 | 377 |  | 
 | 378 | 	status = be_mbox_db_ready_wait(ctrl); | 
 | 379 | 	if (status != 0) { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 380 | 		SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 381 | 		return status; | 
 | 382 | 	} | 
 | 383 | 	if (be_mcc_compl_is_new(compl)) { | 
 | 384 | 		status = be_mcc_compl_process(ctrl, &mbox->compl); | 
 | 385 | 		be_mcc_compl_use(compl); | 
 | 386 | 		if (status) { | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 387 | 			SE_DEBUG(DBG_LVL_1, "After be_mcc_compl_process\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 388 | 			return status; | 
 | 389 | 		} | 
 | 390 | 	} else { | 
 | 391 | 		dev_err(&ctrl->pdev->dev, "invalid mailbox completion\n"); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 392 | 		return -EBUSY; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 393 | 	} | 
 | 394 | 	return 0; | 
 | 395 | } | 
 | 396 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 397 | /* | 
 | 398 |  * Insert the mailbox address into the doorbell in two steps | 
 | 399 |  * Polls on the mbox doorbell till a command completion (or a timeout) occurs | 
 | 400 |  */ | 
 | 401 | static int be_mbox_notify_wait(struct beiscsi_hba *phba) | 
 | 402 | { | 
 | 403 | 	int status; | 
 | 404 | 	u32 val = 0; | 
 | 405 | 	void __iomem *db = phba->ctrl.db + MPU_MAILBOX_DB_OFFSET; | 
 | 406 | 	struct be_dma_mem *mbox_mem = &phba->ctrl.mbox_mem; | 
 | 407 | 	struct be_mcc_mailbox *mbox = mbox_mem->va; | 
 | 408 | 	struct be_mcc_compl *compl = &mbox->compl; | 
 | 409 | 	struct be_ctrl_info *ctrl = &phba->ctrl; | 
 | 410 |  | 
 | 411 | 	val |= MPU_MAILBOX_DB_HI_MASK; | 
 | 412 | 	/* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ | 
 | 413 | 	val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; | 
 | 414 | 	iowrite32(val, db); | 
 | 415 |  | 
 | 416 | 	/* wait for ready to be set */ | 
 | 417 | 	status = be_mbox_db_ready_wait(ctrl); | 
 | 418 | 	if (status != 0) | 
 | 419 | 		return status; | 
 | 420 |  | 
 | 421 | 	val = 0; | 
 | 422 | 	/* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ | 
 | 423 | 	val |= (u32)(mbox_mem->dma >> 4) << 2; | 
 | 424 | 	iowrite32(val, db); | 
 | 425 |  | 
 | 426 | 	status = be_mbox_db_ready_wait(ctrl); | 
 | 427 | 	if (status != 0) | 
 | 428 | 		return status; | 
 | 429 |  | 
 | 430 | 	/* A cq entry has been made now */ | 
 | 431 | 	if (be_mcc_compl_is_new(compl)) { | 
 | 432 | 		status = be_mcc_compl_process(ctrl, &mbox->compl); | 
 | 433 | 		be_mcc_compl_use(compl); | 
 | 434 | 		if (status) | 
 | 435 | 			return status; | 
 | 436 | 	} else { | 
 | 437 | 		dev_err(&phba->pcidev->dev, "invalid mailbox completion\n"); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 438 | 		return -EBUSY; | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 439 | 	} | 
 | 440 | 	return 0; | 
 | 441 | } | 
 | 442 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 443 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, | 
 | 444 | 				bool embedded, u8 sge_cnt) | 
 | 445 | { | 
 | 446 | 	if (embedded) | 
 | 447 | 		wrb->embedded |= MCC_WRB_EMBEDDED_MASK; | 
 | 448 | 	else | 
 | 449 | 		wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << | 
 | 450 | 						MCC_WRB_SGE_CNT_SHIFT; | 
 | 451 | 	wrb->payload_length = payload_len; | 
 | 452 | 	be_dws_cpu_to_le(wrb, 8); | 
 | 453 | } | 
 | 454 |  | 
 | 455 | void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, | 
 | 456 | 			u8 subsystem, u8 opcode, int cmd_len) | 
 | 457 | { | 
 | 458 | 	req_hdr->opcode = opcode; | 
 | 459 | 	req_hdr->subsystem = subsystem; | 
 | 460 | 	req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); | 
| Jayamohan Kallickal | 91eefa8 | 2011-03-25 14:23:59 -0700 | [diff] [blame] | 461 | 	req_hdr->timeout = 120; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 462 | } | 
 | 463 |  | 
 | 464 | static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, | 
 | 465 | 							struct be_dma_mem *mem) | 
 | 466 | { | 
 | 467 | 	int i, buf_pages; | 
 | 468 | 	u64 dma = (u64) mem->dma; | 
 | 469 |  | 
 | 470 | 	buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); | 
 | 471 | 	for (i = 0; i < buf_pages; i++) { | 
 | 472 | 		pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); | 
 | 473 | 		pages[i].hi = cpu_to_le32(upper_32_bits(dma)); | 
 | 474 | 		dma += PAGE_SIZE_4K; | 
 | 475 | 	} | 
 | 476 | } | 
 | 477 |  | 
 | 478 | static u32 eq_delay_to_mult(u32 usec_delay) | 
 | 479 | { | 
 | 480 | #define MAX_INTR_RATE 651042 | 
 | 481 | 	const u32 round = 10; | 
 | 482 | 	u32 multiplier; | 
 | 483 |  | 
 | 484 | 	if (usec_delay == 0) | 
 | 485 | 		multiplier = 0; | 
 | 486 | 	else { | 
 | 487 | 		u32 interrupt_rate = 1000000 / usec_delay; | 
 | 488 | 		if (interrupt_rate == 0) | 
 | 489 | 			multiplier = 1023; | 
 | 490 | 		else { | 
 | 491 | 			multiplier = (MAX_INTR_RATE - interrupt_rate) * round; | 
 | 492 | 			multiplier /= interrupt_rate; | 
 | 493 | 			multiplier = (multiplier + round / 2) / round; | 
 | 494 | 			multiplier = min(multiplier, (u32) 1023); | 
 | 495 | 		} | 
 | 496 | 	} | 
 | 497 | 	return multiplier; | 
 | 498 | } | 
 | 499 |  | 
 | 500 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) | 
 | 501 | { | 
 | 502 | 	return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; | 
 | 503 | } | 
 | 504 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 505 | struct be_mcc_wrb *wrb_from_mccq(struct beiscsi_hba *phba) | 
 | 506 | { | 
 | 507 | 	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 
 | 508 | 	struct be_mcc_wrb *wrb; | 
 | 509 |  | 
 | 510 | 	BUG_ON(atomic_read(&mccq->used) >= mccq->len); | 
 | 511 | 	wrb = queue_head_node(mccq); | 
| Jayamohan Kallickal | 756d29c | 2010-01-05 05:10:46 +0530 | [diff] [blame] | 512 | 	memset(wrb, 0, sizeof(*wrb)); | 
 | 513 | 	wrb->tag0 = (mccq->head & 0x000000FF) << 16; | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 514 | 	queue_head_inc(mccq); | 
 | 515 | 	atomic_inc(&mccq->used); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 516 | 	return wrb; | 
 | 517 | } | 
 | 518 |  | 
 | 519 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 520 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, | 
 | 521 | 			  struct be_queue_info *eq, int eq_delay) | 
 | 522 | { | 
 | 523 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 524 | 	struct be_cmd_req_eq_create *req = embedded_payload(wrb); | 
 | 525 | 	struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); | 
 | 526 | 	struct be_dma_mem *q_mem = &eq->dma_mem; | 
 | 527 | 	int status; | 
 | 528 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 529 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_eq_create\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 530 | 	spin_lock(&ctrl->mbox_lock); | 
 | 531 | 	memset(wrb, 0, sizeof(*wrb)); | 
 | 532 |  | 
 | 533 | 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 534 |  | 
 | 535 | 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 
 | 536 | 			OPCODE_COMMON_EQ_CREATE, sizeof(*req)); | 
 | 537 |  | 
 | 538 | 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); | 
 | 539 |  | 
 | 540 | 	AMAP_SET_BITS(struct amap_eq_context, func, req->context, | 
 | 541 | 						PCI_FUNC(ctrl->pdev->devfn)); | 
 | 542 | 	AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); | 
 | 543 | 	AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); | 
 | 544 | 	AMAP_SET_BITS(struct amap_eq_context, count, req->context, | 
 | 545 | 					__ilog2_u32(eq->len / 256)); | 
 | 546 | 	AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, | 
 | 547 | 					eq_delay_to_mult(eq_delay)); | 
 | 548 | 	be_dws_cpu_to_le(req->context, sizeof(req->context)); | 
 | 549 |  | 
 | 550 | 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 
 | 551 |  | 
 | 552 | 	status = be_mbox_notify(ctrl); | 
 | 553 | 	if (!status) { | 
 | 554 | 		eq->id = le16_to_cpu(resp->eq_id); | 
 | 555 | 		eq->created = true; | 
 | 556 | 	} | 
 | 557 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 558 | 	return status; | 
 | 559 | } | 
 | 560 |  | 
 | 561 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) | 
 | 562 | { | 
 | 563 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 564 | 	int status; | 
 | 565 | 	u8 *endian_check; | 
 | 566 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 567 | 	SE_DEBUG(DBG_LVL_8, "In be_cmd_fw_initialize\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 568 | 	spin_lock(&ctrl->mbox_lock); | 
 | 569 | 	memset(wrb, 0, sizeof(*wrb)); | 
 | 570 |  | 
 | 571 | 	endian_check = (u8 *) wrb; | 
 | 572 | 	*endian_check++ = 0xFF; | 
 | 573 | 	*endian_check++ = 0x12; | 
 | 574 | 	*endian_check++ = 0x34; | 
 | 575 | 	*endian_check++ = 0xFF; | 
 | 576 | 	*endian_check++ = 0xFF; | 
 | 577 | 	*endian_check++ = 0x56; | 
 | 578 | 	*endian_check++ = 0x78; | 
 | 579 | 	*endian_check++ = 0xFF; | 
 | 580 | 	be_dws_cpu_to_le(wrb, sizeof(*wrb)); | 
 | 581 |  | 
 | 582 | 	status = be_mbox_notify(ctrl); | 
 | 583 | 	if (status) | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 584 | 		SE_DEBUG(DBG_LVL_1, "be_cmd_fw_initialize Failed\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 585 |  | 
 | 586 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 587 | 	return status; | 
 | 588 | } | 
 | 589 |  | 
 | 590 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | 
 | 591 | 			  struct be_queue_info *cq, struct be_queue_info *eq, | 
 | 592 | 			  bool sol_evts, bool no_delay, int coalesce_wm) | 
 | 593 | { | 
 | 594 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 595 | 	struct be_cmd_req_cq_create *req = embedded_payload(wrb); | 
 | 596 | 	struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); | 
 | 597 | 	struct be_dma_mem *q_mem = &cq->dma_mem; | 
 | 598 | 	void *ctxt = &req->context; | 
 | 599 | 	int status; | 
 | 600 |  | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 601 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_cq_create\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 602 | 	spin_lock(&ctrl->mbox_lock); | 
 | 603 | 	memset(wrb, 0, sizeof(*wrb)); | 
 | 604 |  | 
 | 605 | 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 606 |  | 
 | 607 | 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 
 | 608 | 			OPCODE_COMMON_CQ_CREATE, sizeof(*req)); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 609 | 	if (!q_mem->va) | 
 | 610 | 		SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n"); | 
 | 611 |  | 
 | 612 | 	req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); | 
 | 613 |  | 
 | 614 | 	AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm); | 
 | 615 | 	AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); | 
 | 616 | 	AMAP_SET_BITS(struct amap_cq_context, count, ctxt, | 
 | 617 | 		      __ilog2_u32(cq->len / 256)); | 
 | 618 | 	AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); | 
 | 619 | 	AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); | 
 | 620 | 	AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); | 
 | 621 | 	AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); | 
 | 622 | 	AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); | 
 | 623 | 	AMAP_SET_BITS(struct amap_cq_context, func, ctxt, | 
 | 624 | 		      PCI_FUNC(ctrl->pdev->devfn)); | 
 | 625 | 	be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 
 | 626 |  | 
 | 627 | 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 
 | 628 |  | 
 | 629 | 	status = be_mbox_notify(ctrl); | 
 | 630 | 	if (!status) { | 
 | 631 | 		cq->id = le16_to_cpu(resp->cq_id); | 
 | 632 | 		cq->created = true; | 
 | 633 | 	} else | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 634 | 		SE_DEBUG(DBG_LVL_1, "In be_cmd_cq_create, status=ox%08x\n", | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 635 | 			status); | 
 | 636 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 637 |  | 
 | 638 | 	return status; | 
 | 639 | } | 
 | 640 |  | 
 | 641 | static u32 be_encoded_q_len(int q_len) | 
 | 642 | { | 
 | 643 | 	u32 len_encoded = fls(q_len);	/* log2(len) + 1 */ | 
 | 644 | 	if (len_encoded == 16) | 
 | 645 | 		len_encoded = 0; | 
 | 646 | 	return len_encoded; | 
 | 647 | } | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 648 |  | 
| Jayamohan Kallickal | 35e6601 | 2009-10-23 11:53:49 +0530 | [diff] [blame] | 649 | int beiscsi_cmd_mccq_create(struct beiscsi_hba *phba, | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 650 | 			struct be_queue_info *mccq, | 
 | 651 | 			struct be_queue_info *cq) | 
 | 652 | { | 
 | 653 | 	struct be_mcc_wrb *wrb; | 
 | 654 | 	struct be_cmd_req_mcc_create *req; | 
 | 655 | 	struct be_dma_mem *q_mem = &mccq->dma_mem; | 
 | 656 | 	struct be_ctrl_info *ctrl; | 
 | 657 | 	void *ctxt; | 
 | 658 | 	int status; | 
 | 659 |  | 
 | 660 | 	spin_lock(&phba->ctrl.mbox_lock); | 
 | 661 | 	ctrl = &phba->ctrl; | 
 | 662 | 	wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
| Jayamohan Kallickal | 3760976 | 2011-10-07 19:31:11 -0500 | [diff] [blame] | 663 | 	memset(wrb, 0, sizeof(*wrb)); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 664 | 	req = embedded_payload(wrb); | 
 | 665 | 	ctxt = &req->context; | 
 | 666 |  | 
 | 667 | 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 668 |  | 
 | 669 | 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 
 | 670 | 			OPCODE_COMMON_MCC_CREATE, sizeof(*req)); | 
 | 671 |  | 
 | 672 | 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | 
 | 673 |  | 
 | 674 | 	AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, | 
 | 675 | 		      PCI_FUNC(phba->pcidev->devfn)); | 
 | 676 | 	AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); | 
 | 677 | 	AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, | 
 | 678 | 		be_encoded_q_len(mccq->len)); | 
 | 679 | 	AMAP_SET_BITS(struct amap_mcc_context, cq_id, ctxt, cq->id); | 
 | 680 |  | 
 | 681 | 	be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 
 | 682 |  | 
 | 683 | 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 
 | 684 |  | 
 | 685 | 	status = be_mbox_notify_wait(phba); | 
 | 686 | 	if (!status) { | 
 | 687 | 		struct be_cmd_resp_mcc_create *resp = embedded_payload(wrb); | 
 | 688 | 		mccq->id = le16_to_cpu(resp->id); | 
 | 689 | 		mccq->created = true; | 
 | 690 | 	} | 
 | 691 | 	spin_unlock(&phba->ctrl.mbox_lock); | 
 | 692 |  | 
 | 693 | 	return status; | 
 | 694 | } | 
 | 695 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 696 | int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | 
 | 697 | 			  int queue_type) | 
 | 698 | { | 
 | 699 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 700 | 	struct be_cmd_req_q_destroy *req = embedded_payload(wrb); | 
 | 701 | 	u8 subsys = 0, opcode = 0; | 
 | 702 | 	int status; | 
 | 703 |  | 
| Jayamohan Kallickal | 457ff3b | 2010-07-22 04:16:00 +0530 | [diff] [blame] | 704 | 	SE_DEBUG(DBG_LVL_8, "In beiscsi_cmd_q_destroy\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 705 | 	spin_lock(&ctrl->mbox_lock); | 
 | 706 | 	memset(wrb, 0, sizeof(*wrb)); | 
 | 707 | 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 708 |  | 
 | 709 | 	switch (queue_type) { | 
 | 710 | 	case QTYPE_EQ: | 
 | 711 | 		subsys = CMD_SUBSYSTEM_COMMON; | 
 | 712 | 		opcode = OPCODE_COMMON_EQ_DESTROY; | 
 | 713 | 		break; | 
 | 714 | 	case QTYPE_CQ: | 
 | 715 | 		subsys = CMD_SUBSYSTEM_COMMON; | 
 | 716 | 		opcode = OPCODE_COMMON_CQ_DESTROY; | 
 | 717 | 		break; | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 718 | 	case QTYPE_MCCQ: | 
 | 719 | 		subsys = CMD_SUBSYSTEM_COMMON; | 
 | 720 | 		opcode = OPCODE_COMMON_MCC_DESTROY; | 
 | 721 | 		break; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 722 | 	case QTYPE_WRBQ: | 
 | 723 | 		subsys = CMD_SUBSYSTEM_ISCSI; | 
 | 724 | 		opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY; | 
 | 725 | 		break; | 
 | 726 | 	case QTYPE_DPDUQ: | 
 | 727 | 		subsys = CMD_SUBSYSTEM_ISCSI; | 
 | 728 | 		opcode = OPCODE_COMMON_ISCSI_DEFQ_DESTROY; | 
 | 729 | 		break; | 
 | 730 | 	case QTYPE_SGL: | 
 | 731 | 		subsys = CMD_SUBSYSTEM_ISCSI; | 
 | 732 | 		opcode = OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES; | 
 | 733 | 		break; | 
 | 734 | 	default: | 
 | 735 | 		spin_unlock(&ctrl->mbox_lock); | 
 | 736 | 		BUG(); | 
| Jayamohan Kallickal | d3ad2bb | 2010-07-22 04:16:38 +0530 | [diff] [blame] | 737 | 		return -ENXIO; | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 738 | 	} | 
 | 739 | 	be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); | 
 | 740 | 	if (queue_type != QTYPE_SGL) | 
 | 741 | 		req->id = cpu_to_le16(q->id); | 
 | 742 |  | 
 | 743 | 	status = be_mbox_notify(ctrl); | 
 | 744 |  | 
 | 745 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 746 | 	return status; | 
 | 747 | } | 
 | 748 |  | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 749 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | 
 | 750 | 				    struct be_queue_info *cq, | 
 | 751 | 				    struct be_queue_info *dq, int length, | 
 | 752 | 				    int entry_size) | 
 | 753 | { | 
 | 754 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 755 | 	struct be_defq_create_req *req = embedded_payload(wrb); | 
 | 756 | 	struct be_dma_mem *q_mem = &dq->dma_mem; | 
 | 757 | 	void *ctxt = &req->context; | 
 | 758 | 	int status; | 
 | 759 |  | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 760 | 	SE_DEBUG(DBG_LVL_8, "In be_cmd_create_default_pdu_queue\n"); | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 761 | 	spin_lock(&ctrl->mbox_lock); | 
 | 762 | 	memset(wrb, 0, sizeof(*wrb)); | 
 | 763 |  | 
 | 764 | 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 765 |  | 
 | 766 | 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 
 | 767 | 			   OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); | 
 | 768 |  | 
 | 769 | 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | 
 | 770 | 	AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0); | 
 | 771 | 	AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt, | 
 | 772 | 		      1); | 
 | 773 | 	AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt, | 
 | 774 | 		      PCI_FUNC(ctrl->pdev->devfn)); | 
 | 775 | 	AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt, | 
 | 776 | 		      be_encoded_q_len(length / sizeof(struct phys_addr))); | 
 | 777 | 	AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size, | 
 | 778 | 		      ctxt, entry_size); | 
 | 779 | 	AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt, | 
 | 780 | 		      cq->id); | 
 | 781 |  | 
 | 782 | 	be_dws_cpu_to_le(ctxt, sizeof(req->context)); | 
 | 783 |  | 
 | 784 | 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 
 | 785 |  | 
 | 786 | 	status = be_mbox_notify(ctrl); | 
 | 787 | 	if (!status) { | 
 | 788 | 		struct be_defq_create_resp *resp = embedded_payload(wrb); | 
 | 789 |  | 
 | 790 | 		dq->id = le16_to_cpu(resp->id); | 
 | 791 | 		dq->created = true; | 
 | 792 | 	} | 
 | 793 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 794 |  | 
 | 795 | 	return status; | 
 | 796 | } | 
 | 797 |  | 
 | 798 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | 
 | 799 | 		       struct be_queue_info *wrbq) | 
 | 800 | { | 
 | 801 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 802 | 	struct be_wrbq_create_req *req = embedded_payload(wrb); | 
 | 803 | 	struct be_wrbq_create_resp *resp = embedded_payload(wrb); | 
 | 804 | 	int status; | 
 | 805 |  | 
 | 806 | 	spin_lock(&ctrl->mbox_lock); | 
 | 807 | 	memset(wrb, 0, sizeof(*wrb)); | 
 | 808 |  | 
 | 809 | 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 810 |  | 
 | 811 | 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 
 | 812 | 		OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req)); | 
 | 813 | 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | 
 | 814 | 	be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | 
 | 815 |  | 
 | 816 | 	status = be_mbox_notify(ctrl); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 817 | 	if (!status) { | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 818 | 		wrbq->id = le16_to_cpu(resp->cid); | 
| Jayamohan Kallickal | bfead3b | 2009-10-23 11:52:33 +0530 | [diff] [blame] | 819 | 		wrbq->created = true; | 
 | 820 | 	} | 
| Jayamohan Kallickal | 6733b39 | 2009-09-05 07:36:35 +0530 | [diff] [blame] | 821 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 822 | 	return status; | 
 | 823 | } | 
 | 824 |  | 
 | 825 | int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, | 
 | 826 | 				struct be_dma_mem *q_mem, | 
 | 827 | 				u32 page_offset, u32 num_pages) | 
 | 828 | { | 
 | 829 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 830 | 	struct be_post_sgl_pages_req *req = embedded_payload(wrb); | 
 | 831 | 	int status; | 
 | 832 | 	unsigned int curr_pages; | 
 | 833 | 	u32 internal_page_offset = 0; | 
 | 834 | 	u32 temp_num_pages = num_pages; | 
 | 835 |  | 
 | 836 | 	if (num_pages == 0xff) | 
 | 837 | 		num_pages = 1; | 
 | 838 |  | 
 | 839 | 	spin_lock(&ctrl->mbox_lock); | 
 | 840 | 	do { | 
 | 841 | 		memset(wrb, 0, sizeof(*wrb)); | 
 | 842 | 		be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 843 | 		be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | 
 | 844 | 				   OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES, | 
 | 845 | 				   sizeof(*req)); | 
 | 846 | 		curr_pages = BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req, | 
 | 847 | 						pages); | 
 | 848 | 		req->num_pages = min(num_pages, curr_pages); | 
 | 849 | 		req->page_offset = page_offset; | 
 | 850 | 		be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem); | 
 | 851 | 		q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE); | 
 | 852 | 		internal_page_offset += req->num_pages; | 
 | 853 | 		page_offset += req->num_pages; | 
 | 854 | 		num_pages -= req->num_pages; | 
 | 855 |  | 
 | 856 | 		if (temp_num_pages == 0xff) | 
 | 857 | 			req->num_pages = temp_num_pages; | 
 | 858 |  | 
 | 859 | 		status = be_mbox_notify(ctrl); | 
 | 860 | 		if (status) { | 
 | 861 | 			SE_DEBUG(DBG_LVL_1, | 
 | 862 | 				 "FW CMD to map iscsi frags failed.\n"); | 
 | 863 | 			goto error; | 
 | 864 | 		} | 
 | 865 | 	} while (num_pages > 0); | 
 | 866 | error: | 
 | 867 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 868 | 	if (status != 0) | 
 | 869 | 		beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); | 
 | 870 | 	return status; | 
 | 871 | } | 
| Jayamohan Kallickal | e528586 | 2011-10-07 19:31:08 -0500 | [diff] [blame] | 872 |  | 
 | 873 | int beiscsi_cmd_reset_function(struct beiscsi_hba  *phba) | 
 | 874 | { | 
 | 875 | 	struct be_ctrl_info *ctrl = &phba->ctrl; | 
 | 876 | 	struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | 
 | 877 | 	struct be_post_sgl_pages_req *req = embedded_payload(wrb); | 
 | 878 | 	int status; | 
 | 879 |  | 
 | 880 | 	spin_lock(&ctrl->mbox_lock); | 
 | 881 |  | 
 | 882 | 	req = embedded_payload(wrb); | 
 | 883 | 	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | 
 | 884 | 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 
 | 885 | 			   OPCODE_COMMON_FUNCTION_RESET, sizeof(*req)); | 
 | 886 | 	status = be_mbox_notify_wait(phba); | 
 | 887 |  | 
 | 888 | 	spin_unlock(&ctrl->mbox_lock); | 
 | 889 | 	return status; | 
 | 890 | } |