diff options
author | James Smart <James.Smart@Emulex.Com> | 2009-05-22 14:52:59 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@HansenPartnership.com> | 2009-06-08 12:25:24 -0400 |
commit | 6fb120a7ed882aae9636545142a51cf3182a3ace (patch) | |
tree | 7e830b09907286288f20f60c0f104d5fbec9998d /drivers/scsi/lpfc/lpfc_sli.c | |
parent | 04c684968487eb4f98728363a97b8da48f3bb958 (diff) |
[SCSI] lpfc 8.3.2 : Addition of SLI4 Interface - FCOE Discovery support
SLI4 supports both FC and FCOE, with some extended topology objects.
This patch adss support for the objects, and updates the disovery
engines for their use.
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_sli.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 517 |
1 files changed, 517 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index b53af9936282..9645d32e6f87 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -10929,3 +10929,520 @@ lpfc_sli4_handle_received_buffer(struct lpfc_hba *phba) | |||
10929 | }; | 10929 | }; |
10930 | return 0; | 10930 | return 0; |
10931 | } | 10931 | } |
10932 | |||
10933 | /** | ||
10934 | * lpfc_sli4_post_all_rpi_hdrs - Post the rpi header memory region to the port | ||
10935 | * @phba: pointer to lpfc hba data structure. | ||
10936 | * | ||
10937 | * This routine is invoked to post rpi header templates to the | ||
10938 | * HBA consistent with the SLI-4 interface spec. This routine | ||
10939 | * posts a PAGE_SIZE memory region to the port to hold up to | ||
10940 | * PAGE_SIZE modulo 64 rpi context headers. | ||
10941 | * | ||
10942 | * This routine does not require any locks. It's usage is expected | ||
10943 | * to be driver load or reset recovery when the driver is | ||
10944 | * sequential. | ||
10945 | * | ||
10946 | * Return codes | ||
10947 | * 0 - sucessful | ||
10948 | * EIO - The mailbox failed to complete successfully. | ||
10949 | * When this error occurs, the driver is not guaranteed | ||
10950 | * to have any rpi regions posted to the device and | ||
10951 | * must either attempt to repost the regions or take a | ||
10952 | * fatal error. | ||
10953 | **/ | ||
10954 | int | ||
10955 | lpfc_sli4_post_all_rpi_hdrs(struct lpfc_hba *phba) | ||
10956 | { | ||
10957 | struct lpfc_rpi_hdr *rpi_page; | ||
10958 | uint32_t rc = 0; | ||
10959 | |||
10960 | /* Post all rpi memory regions to the port. */ | ||
10961 | list_for_each_entry(rpi_page, &phba->sli4_hba.lpfc_rpi_hdr_list, list) { | ||
10962 | rc = lpfc_sli4_post_rpi_hdr(phba, rpi_page); | ||
10963 | if (rc != MBX_SUCCESS) { | ||
10964 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
10965 | "2008 Error %d posting all rpi " | ||
10966 | "headers\n", rc); | ||
10967 | rc = -EIO; | ||
10968 | break; | ||
10969 | } | ||
10970 | } | ||
10971 | |||
10972 | return rc; | ||
10973 | } | ||
10974 | |||
10975 | /** | ||
10976 | * lpfc_sli4_post_rpi_hdr - Post an rpi header memory region to the port | ||
10977 | * @phba: pointer to lpfc hba data structure. | ||
10978 | * @rpi_page: pointer to the rpi memory region. | ||
10979 | * | ||
10980 | * This routine is invoked to post a single rpi header to the | ||
10981 | * HBA consistent with the SLI-4 interface spec. This memory region | ||
10982 | * maps up to 64 rpi context regions. | ||
10983 | * | ||
10984 | * Return codes | ||
10985 | * 0 - sucessful | ||
10986 | * ENOMEM - No available memory | ||
10987 | * EIO - The mailbox failed to complete successfully. | ||
10988 | **/ | ||
10989 | int | ||
10990 | lpfc_sli4_post_rpi_hdr(struct lpfc_hba *phba, struct lpfc_rpi_hdr *rpi_page) | ||
10991 | { | ||
10992 | LPFC_MBOXQ_t *mboxq; | ||
10993 | struct lpfc_mbx_post_hdr_tmpl *hdr_tmpl; | ||
10994 | uint32_t rc = 0; | ||
10995 | uint32_t mbox_tmo; | ||
10996 | uint32_t shdr_status, shdr_add_status; | ||
10997 | union lpfc_sli4_cfg_shdr *shdr; | ||
10998 | |||
10999 | /* The port is notified of the header region via a mailbox command. */ | ||
11000 | mboxq = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
11001 | if (!mboxq) { | ||
11002 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
11003 | "2001 Unable to allocate memory for issuing " | ||
11004 | "SLI_CONFIG_SPECIAL mailbox command\n"); | ||
11005 | return -ENOMEM; | ||
11006 | } | ||
11007 | |||
11008 | /* Post all rpi memory regions to the port. */ | ||
11009 | hdr_tmpl = &mboxq->u.mqe.un.hdr_tmpl; | ||
11010 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG); | ||
11011 | lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
11012 | LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE, | ||
11013 | sizeof(struct lpfc_mbx_post_hdr_tmpl) - | ||
11014 | sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED); | ||
11015 | bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt, | ||
11016 | hdr_tmpl, rpi_page->page_count); | ||
11017 | bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl, | ||
11018 | rpi_page->start_rpi); | ||
11019 | hdr_tmpl->rpi_paddr_lo = putPaddrLow(rpi_page->dmabuf->phys); | ||
11020 | hdr_tmpl->rpi_paddr_hi = putPaddrHigh(rpi_page->dmabuf->phys); | ||
11021 | if (!phba->sli4_hba.intr_enable) | ||
11022 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL); | ||
11023 | else | ||
11024 | rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); | ||
11025 | shdr = (union lpfc_sli4_cfg_shdr *) &hdr_tmpl->header.cfg_shdr; | ||
11026 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
11027 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
11028 | if (rc != MBX_TIMEOUT) | ||
11029 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
11030 | if (shdr_status || shdr_add_status || rc) { | ||
11031 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11032 | "2514 POST_RPI_HDR mailbox failed with " | ||
11033 | "status x%x add_status x%x, mbx status x%x\n", | ||
11034 | shdr_status, shdr_add_status, rc); | ||
11035 | rc = -ENXIO; | ||
11036 | } | ||
11037 | return rc; | ||
11038 | } | ||
11039 | |||
11040 | /** | ||
11041 | * lpfc_sli4_alloc_rpi - Get an available rpi in the device's range | ||
11042 | * @phba: pointer to lpfc hba data structure. | ||
11043 | * | ||
11044 | * This routine is invoked to post rpi header templates to the | ||
11045 | * HBA consistent with the SLI-4 interface spec. This routine | ||
11046 | * posts a PAGE_SIZE memory region to the port to hold up to | ||
11047 | * PAGE_SIZE modulo 64 rpi context headers. | ||
11048 | * | ||
11049 | * Returns | ||
11050 | * A nonzero rpi defined as rpi_base <= rpi < max_rpi if sucessful | ||
11051 | * LPFC_RPI_ALLOC_ERROR if no rpis are available. | ||
11052 | **/ | ||
11053 | int | ||
11054 | lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | ||
11055 | { | ||
11056 | int rpi; | ||
11057 | uint16_t max_rpi, rpi_base, rpi_limit; | ||
11058 | uint16_t rpi_remaining; | ||
11059 | struct lpfc_rpi_hdr *rpi_hdr; | ||
11060 | |||
11061 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; | ||
11062 | rpi_base = phba->sli4_hba.max_cfg_param.rpi_base; | ||
11063 | rpi_limit = phba->sli4_hba.next_rpi; | ||
11064 | |||
11065 | /* | ||
11066 | * The valid rpi range is not guaranteed to be zero-based. Start | ||
11067 | * the search at the rpi_base as reported by the port. | ||
11068 | */ | ||
11069 | spin_lock_irq(&phba->hbalock); | ||
11070 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, rpi_base); | ||
11071 | if (rpi >= rpi_limit || rpi < rpi_base) | ||
11072 | rpi = LPFC_RPI_ALLOC_ERROR; | ||
11073 | else { | ||
11074 | set_bit(rpi, phba->sli4_hba.rpi_bmask); | ||
11075 | phba->sli4_hba.max_cfg_param.rpi_used++; | ||
11076 | phba->sli4_hba.rpi_count++; | ||
11077 | } | ||
11078 | |||
11079 | /* | ||
11080 | * Don't try to allocate more rpi header regions if the device limit | ||
11081 | * on available rpis max has been exhausted. | ||
11082 | */ | ||
11083 | if ((rpi == LPFC_RPI_ALLOC_ERROR) && | ||
11084 | (phba->sli4_hba.rpi_count >= max_rpi)) { | ||
11085 | spin_unlock_irq(&phba->hbalock); | ||
11086 | return rpi; | ||
11087 | } | ||
11088 | |||
11089 | /* | ||
11090 | * If the driver is running low on rpi resources, allocate another | ||
11091 | * page now. Note that the next_rpi value is used because | ||
11092 | * it represents how many are actually in use whereas max_rpi notes | ||
11093 | * how many are supported max by the device. | ||
11094 | */ | ||
11095 | rpi_remaining = phba->sli4_hba.next_rpi - rpi_base - | ||
11096 | phba->sli4_hba.rpi_count; | ||
11097 | spin_unlock_irq(&phba->hbalock); | ||
11098 | if (rpi_remaining < LPFC_RPI_LOW_WATER_MARK) { | ||
11099 | rpi_hdr = lpfc_sli4_create_rpi_hdr(phba); | ||
11100 | if (!rpi_hdr) { | ||
11101 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
11102 | "2002 Error Could not grow rpi " | ||
11103 | "count\n"); | ||
11104 | } else { | ||
11105 | lpfc_sli4_post_rpi_hdr(phba, rpi_hdr); | ||
11106 | } | ||
11107 | } | ||
11108 | |||
11109 | return rpi; | ||
11110 | } | ||
11111 | |||
11112 | /** | ||
11113 | * lpfc_sli4_free_rpi - Release an rpi for reuse. | ||
11114 | * @phba: pointer to lpfc hba data structure. | ||
11115 | * | ||
11116 | * This routine is invoked to release an rpi to the pool of | ||
11117 | * available rpis maintained by the driver. | ||
11118 | **/ | ||
11119 | void | ||
11120 | lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) | ||
11121 | { | ||
11122 | spin_lock_irq(&phba->hbalock); | ||
11123 | clear_bit(rpi, phba->sli4_hba.rpi_bmask); | ||
11124 | phba->sli4_hba.rpi_count--; | ||
11125 | phba->sli4_hba.max_cfg_param.rpi_used--; | ||
11126 | spin_unlock_irq(&phba->hbalock); | ||
11127 | } | ||
11128 | |||
11129 | /** | ||
11130 | * lpfc_sli4_remove_rpis - Remove the rpi bitmask region | ||
11131 | * @phba: pointer to lpfc hba data structure. | ||
11132 | * | ||
11133 | * This routine is invoked to remove the memory region that | ||
11134 | * provided rpi via a bitmask. | ||
11135 | **/ | ||
11136 | void | ||
11137 | lpfc_sli4_remove_rpis(struct lpfc_hba *phba) | ||
11138 | { | ||
11139 | kfree(phba->sli4_hba.rpi_bmask); | ||
11140 | } | ||
11141 | |||
11142 | /** | ||
11143 | * lpfc_sli4_resume_rpi - Remove the rpi bitmask region | ||
11144 | * @phba: pointer to lpfc hba data structure. | ||
11145 | * | ||
11146 | * This routine is invoked to remove the memory region that | ||
11147 | * provided rpi via a bitmask. | ||
11148 | **/ | ||
11149 | int | ||
11150 | lpfc_sli4_resume_rpi(struct lpfc_nodelist *ndlp) | ||
11151 | { | ||
11152 | LPFC_MBOXQ_t *mboxq; | ||
11153 | struct lpfc_hba *phba = ndlp->phba; | ||
11154 | int rc; | ||
11155 | |||
11156 | /* The port is notified of the header region via a mailbox command. */ | ||
11157 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
11158 | if (!mboxq) | ||
11159 | return -ENOMEM; | ||
11160 | |||
11161 | /* Post all rpi memory regions to the port. */ | ||
11162 | lpfc_resume_rpi(mboxq, ndlp); | ||
11163 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | ||
11164 | if (rc == MBX_NOT_FINISHED) { | ||
11165 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
11166 | "2010 Resume RPI Mailbox failed " | ||
11167 | "status %d, mbxStatus x%x\n", rc, | ||
11168 | bf_get(lpfc_mqe_status, &mboxq->u.mqe)); | ||
11169 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
11170 | return -EIO; | ||
11171 | } | ||
11172 | return 0; | ||
11173 | } | ||
11174 | |||
11175 | /** | ||
11176 | * lpfc_sli4_init_vpi - Initialize a vpi with the port | ||
11177 | * @phba: pointer to lpfc hba data structure. | ||
11178 | * @vpi: vpi value to activate with the port. | ||
11179 | * | ||
11180 | * This routine is invoked to activate a vpi with the | ||
11181 | * port when the host intends to use vports with a | ||
11182 | * nonzero vpi. | ||
11183 | * | ||
11184 | * Returns: | ||
11185 | * 0 success | ||
11186 | * -Evalue otherwise | ||
11187 | **/ | ||
11188 | int | ||
11189 | lpfc_sli4_init_vpi(struct lpfc_hba *phba, uint16_t vpi) | ||
11190 | { | ||
11191 | LPFC_MBOXQ_t *mboxq; | ||
11192 | int rc = 0; | ||
11193 | uint32_t mbox_tmo; | ||
11194 | |||
11195 | if (vpi == 0) | ||
11196 | return -EINVAL; | ||
11197 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
11198 | if (!mboxq) | ||
11199 | return -ENOMEM; | ||
11200 | lpfc_init_vpi(mboxq, vpi); | ||
11201 | mbox_tmo = lpfc_mbox_tmo_val(phba, MBX_INIT_VPI); | ||
11202 | rc = lpfc_sli_issue_mbox_wait(phba, mboxq, mbox_tmo); | ||
11203 | if (rc != MBX_TIMEOUT) | ||
11204 | mempool_free(mboxq, phba->mbox_mem_pool); | ||
11205 | if (rc != MBX_SUCCESS) { | ||
11206 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
11207 | "2022 INIT VPI Mailbox failed " | ||
11208 | "status %d, mbxStatus x%x\n", rc, | ||
11209 | bf_get(lpfc_mqe_status, &mboxq->u.mqe)); | ||
11210 | rc = -EIO; | ||
11211 | } | ||
11212 | return rc; | ||
11213 | } | ||
11214 | |||
11215 | /** | ||
11216 | * lpfc_mbx_cmpl_add_fcf_record - add fcf mbox completion handler. | ||
11217 | * @phba: pointer to lpfc hba data structure. | ||
11218 | * @mboxq: Pointer to mailbox object. | ||
11219 | * | ||
11220 | * This routine is invoked to manually add a single FCF record. The caller | ||
11221 | * must pass a completely initialized FCF_Record. This routine takes | ||
11222 | * care of the nonembedded mailbox operations. | ||
11223 | **/ | ||
11224 | static void | ||
11225 | lpfc_mbx_cmpl_add_fcf_record(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq) | ||
11226 | { | ||
11227 | void *virt_addr; | ||
11228 | union lpfc_sli4_cfg_shdr *shdr; | ||
11229 | uint32_t shdr_status, shdr_add_status; | ||
11230 | |||
11231 | virt_addr = mboxq->sge_array->addr[0]; | ||
11232 | /* The IOCTL status is embedded in the mailbox subheader. */ | ||
11233 | shdr = (union lpfc_sli4_cfg_shdr *) virt_addr; | ||
11234 | shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response); | ||
11235 | shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response); | ||
11236 | |||
11237 | if ((shdr_status || shdr_add_status) && | ||
11238 | (shdr_status != STATUS_FCF_IN_USE)) | ||
11239 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11240 | "2558 ADD_FCF_RECORD mailbox failed with " | ||
11241 | "status x%x add_status x%x\n", | ||
11242 | shdr_status, shdr_add_status); | ||
11243 | |||
11244 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
11245 | } | ||
11246 | |||
11247 | /** | ||
11248 | * lpfc_sli4_add_fcf_record - Manually add an FCF Record. | ||
11249 | * @phba: pointer to lpfc hba data structure. | ||
11250 | * @fcf_record: pointer to the initialized fcf record to add. | ||
11251 | * | ||
11252 | * This routine is invoked to manually add a single FCF record. The caller | ||
11253 | * must pass a completely initialized FCF_Record. This routine takes | ||
11254 | * care of the nonembedded mailbox operations. | ||
11255 | **/ | ||
11256 | int | ||
11257 | lpfc_sli4_add_fcf_record(struct lpfc_hba *phba, struct fcf_record *fcf_record) | ||
11258 | { | ||
11259 | int rc = 0; | ||
11260 | LPFC_MBOXQ_t *mboxq; | ||
11261 | uint8_t *bytep; | ||
11262 | void *virt_addr; | ||
11263 | dma_addr_t phys_addr; | ||
11264 | struct lpfc_mbx_sge sge; | ||
11265 | uint32_t alloc_len, req_len; | ||
11266 | uint32_t fcfindex; | ||
11267 | |||
11268 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
11269 | if (!mboxq) { | ||
11270 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11271 | "2009 Failed to allocate mbox for ADD_FCF cmd\n"); | ||
11272 | return -ENOMEM; | ||
11273 | } | ||
11274 | |||
11275 | req_len = sizeof(struct fcf_record) + sizeof(union lpfc_sli4_cfg_shdr) + | ||
11276 | sizeof(uint32_t); | ||
11277 | |||
11278 | /* Allocate DMA memory and set up the non-embedded mailbox command */ | ||
11279 | alloc_len = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
11280 | LPFC_MBOX_OPCODE_FCOE_ADD_FCF, | ||
11281 | req_len, LPFC_SLI4_MBX_NEMBED); | ||
11282 | if (alloc_len < req_len) { | ||
11283 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11284 | "2523 Allocated DMA memory size (x%x) is " | ||
11285 | "less than the requested DMA memory " | ||
11286 | "size (x%x)\n", alloc_len, req_len); | ||
11287 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
11288 | return -ENOMEM; | ||
11289 | } | ||
11290 | |||
11291 | /* | ||
11292 | * Get the first SGE entry from the non-embedded DMA memory. This | ||
11293 | * routine only uses a single SGE. | ||
11294 | */ | ||
11295 | lpfc_sli4_mbx_sge_get(mboxq, 0, &sge); | ||
11296 | phys_addr = getPaddr(sge.pa_hi, sge.pa_lo); | ||
11297 | if (unlikely(!mboxq->sge_array)) { | ||
11298 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, | ||
11299 | "2526 Failed to get the non-embedded SGE " | ||
11300 | "virtual address\n"); | ||
11301 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
11302 | return -ENOMEM; | ||
11303 | } | ||
11304 | virt_addr = mboxq->sge_array->addr[0]; | ||
11305 | /* | ||
11306 | * Configure the FCF record for FCFI 0. This is the driver's | ||
11307 | * hardcoded default and gets used in nonFIP mode. | ||
11308 | */ | ||
11309 | fcfindex = bf_get(lpfc_fcf_record_fcf_index, fcf_record); | ||
11310 | bytep = virt_addr + sizeof(union lpfc_sli4_cfg_shdr); | ||
11311 | lpfc_sli_pcimem_bcopy(&fcfindex, bytep, sizeof(uint32_t)); | ||
11312 | |||
11313 | /* | ||
11314 | * Copy the fcf_index and the FCF Record Data. The data starts after | ||
11315 | * the FCoE header plus word10. The data copy needs to be endian | ||
11316 | * correct. | ||
11317 | */ | ||
11318 | bytep += sizeof(uint32_t); | ||
11319 | lpfc_sli_pcimem_bcopy(fcf_record, bytep, sizeof(struct fcf_record)); | ||
11320 | mboxq->vport = phba->pport; | ||
11321 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_add_fcf_record; | ||
11322 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | ||
11323 | if (rc == MBX_NOT_FINISHED) { | ||
11324 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11325 | "2515 ADD_FCF_RECORD mailbox failed with " | ||
11326 | "status 0x%x\n", rc); | ||
11327 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
11328 | rc = -EIO; | ||
11329 | } else | ||
11330 | rc = 0; | ||
11331 | |||
11332 | return rc; | ||
11333 | } | ||
11334 | |||
11335 | /** | ||
11336 | * lpfc_sli4_build_dflt_fcf_record - Build the driver's default FCF Record. | ||
11337 | * @phba: pointer to lpfc hba data structure. | ||
11338 | * @fcf_record: pointer to the fcf record to write the default data. | ||
11339 | * @fcf_index: FCF table entry index. | ||
11340 | * | ||
11341 | * This routine is invoked to build the driver's default FCF record. The | ||
11342 | * values used are hardcoded. This routine handles memory initialization. | ||
11343 | * | ||
11344 | **/ | ||
11345 | void | ||
11346 | lpfc_sli4_build_dflt_fcf_record(struct lpfc_hba *phba, | ||
11347 | struct fcf_record *fcf_record, | ||
11348 | uint16_t fcf_index) | ||
11349 | { | ||
11350 | memset(fcf_record, 0, sizeof(struct fcf_record)); | ||
11351 | fcf_record->max_rcv_size = LPFC_FCOE_MAX_RCV_SIZE; | ||
11352 | fcf_record->fka_adv_period = LPFC_FCOE_FKA_ADV_PER; | ||
11353 | fcf_record->fip_priority = LPFC_FCOE_FIP_PRIORITY; | ||
11354 | bf_set(lpfc_fcf_record_mac_0, fcf_record, phba->fc_map[0]); | ||
11355 | bf_set(lpfc_fcf_record_mac_1, fcf_record, phba->fc_map[1]); | ||
11356 | bf_set(lpfc_fcf_record_mac_2, fcf_record, phba->fc_map[2]); | ||
11357 | bf_set(lpfc_fcf_record_mac_3, fcf_record, LPFC_FCOE_FCF_MAC3); | ||
11358 | bf_set(lpfc_fcf_record_mac_4, fcf_record, LPFC_FCOE_FCF_MAC4); | ||
11359 | bf_set(lpfc_fcf_record_mac_5, fcf_record, LPFC_FCOE_FCF_MAC5); | ||
11360 | bf_set(lpfc_fcf_record_fc_map_0, fcf_record, phba->fc_map[0]); | ||
11361 | bf_set(lpfc_fcf_record_fc_map_1, fcf_record, phba->fc_map[1]); | ||
11362 | bf_set(lpfc_fcf_record_fc_map_2, fcf_record, phba->fc_map[2]); | ||
11363 | bf_set(lpfc_fcf_record_fcf_valid, fcf_record, 1); | ||
11364 | bf_set(lpfc_fcf_record_fcf_index, fcf_record, fcf_index); | ||
11365 | bf_set(lpfc_fcf_record_mac_addr_prov, fcf_record, | ||
11366 | LPFC_FCF_FPMA | LPFC_FCF_SPMA); | ||
11367 | /* Set the VLAN bit map */ | ||
11368 | if (phba->valid_vlan) { | ||
11369 | fcf_record->vlan_bitmap[phba->vlan_id / 8] | ||
11370 | = 1 << (phba->vlan_id % 8); | ||
11371 | } | ||
11372 | } | ||
11373 | |||
11374 | /** | ||
11375 | * lpfc_sli4_read_fcf_record - Read the driver's default FCF Record. | ||
11376 | * @phba: pointer to lpfc hba data structure. | ||
11377 | * @fcf_index: FCF table entry offset. | ||
11378 | * | ||
11379 | * This routine is invoked to read up to @fcf_num of FCF record from the | ||
11380 | * device starting with the given @fcf_index. | ||
11381 | **/ | ||
11382 | int | ||
11383 | lpfc_sli4_read_fcf_record(struct lpfc_hba *phba, uint16_t fcf_index) | ||
11384 | { | ||
11385 | int rc = 0, error; | ||
11386 | LPFC_MBOXQ_t *mboxq; | ||
11387 | void *virt_addr; | ||
11388 | dma_addr_t phys_addr; | ||
11389 | uint8_t *bytep; | ||
11390 | struct lpfc_mbx_sge sge; | ||
11391 | uint32_t alloc_len, req_len; | ||
11392 | struct lpfc_mbx_read_fcf_tbl *read_fcf; | ||
11393 | |||
11394 | mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
11395 | if (!mboxq) { | ||
11396 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11397 | "2000 Failed to allocate mbox for " | ||
11398 | "READ_FCF cmd\n"); | ||
11399 | return -ENOMEM; | ||
11400 | } | ||
11401 | |||
11402 | req_len = sizeof(struct fcf_record) + | ||
11403 | sizeof(union lpfc_sli4_cfg_shdr) + 2 * sizeof(uint32_t); | ||
11404 | |||
11405 | /* Set up READ_FCF SLI4_CONFIG mailbox-ioctl command */ | ||
11406 | alloc_len = lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE, | ||
11407 | LPFC_MBOX_OPCODE_FCOE_READ_FCF_TABLE, req_len, | ||
11408 | LPFC_SLI4_MBX_NEMBED); | ||
11409 | |||
11410 | if (alloc_len < req_len) { | ||
11411 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
11412 | "0291 Allocated DMA memory size (x%x) is " | ||
11413 | "less than the requested DMA memory " | ||
11414 | "size (x%x)\n", alloc_len, req_len); | ||
11415 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
11416 | return -ENOMEM; | ||
11417 | } | ||
11418 | |||
11419 | /* Get the first SGE entry from the non-embedded DMA memory. This | ||
11420 | * routine only uses a single SGE. | ||
11421 | */ | ||
11422 | lpfc_sli4_mbx_sge_get(mboxq, 0, &sge); | ||
11423 | phys_addr = getPaddr(sge.pa_hi, sge.pa_lo); | ||
11424 | if (unlikely(!mboxq->sge_array)) { | ||
11425 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, | ||
11426 | "2527 Failed to get the non-embedded SGE " | ||
11427 | "virtual address\n"); | ||
11428 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
11429 | return -ENOMEM; | ||
11430 | } | ||
11431 | virt_addr = mboxq->sge_array->addr[0]; | ||
11432 | read_fcf = (struct lpfc_mbx_read_fcf_tbl *)virt_addr; | ||
11433 | |||
11434 | /* Set up command fields */ | ||
11435 | bf_set(lpfc_mbx_read_fcf_tbl_indx, &read_fcf->u.request, fcf_index); | ||
11436 | /* Perform necessary endian conversion */ | ||
11437 | bytep = virt_addr + sizeof(union lpfc_sli4_cfg_shdr); | ||
11438 | lpfc_sli_pcimem_bcopy(bytep, bytep, sizeof(uint32_t)); | ||
11439 | mboxq->vport = phba->pport; | ||
11440 | mboxq->mbox_cmpl = lpfc_mbx_cmpl_read_fcf_record; | ||
11441 | rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_NOWAIT); | ||
11442 | if (rc == MBX_NOT_FINISHED) { | ||
11443 | lpfc_sli4_mbox_cmd_free(phba, mboxq); | ||
11444 | error = -EIO; | ||
11445 | } else | ||
11446 | error = 0; | ||
11447 | return error; | ||
11448 | } | ||