Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

scsi: lpfc: Commonize VMID code location

Remove VMID code from its SCSI-specific location and move to a new file
solely for VMID code.

Link: https://lore.kernel.org/r/20220519123110.17361-3-jsmart2021@gmail.com
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
Co-developed-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

James Smart and committed by
Martin K. Petersen
ed913cf4 827fc630

+291 -257
+1 -1
drivers/scsi/lpfc/Makefile
··· 33 33 lpfc-objs := lpfc_mem.o lpfc_sli.o lpfc_ct.o lpfc_els.o \ 34 34 lpfc_hbadisc.o lpfc_init.o lpfc_mbox.o lpfc_nportdisc.o \ 35 35 lpfc_scsi.o lpfc_attr.o lpfc_vport.o lpfc_debugfs.o lpfc_bsg.o \ 36 - lpfc_nvme.o lpfc_nvmet.o 36 + lpfc_nvme.o lpfc_nvmet.o lpfc_vmid.o
+2
drivers/scsi/lpfc/lpfc_crtn.h
··· 671 671 int lpfc_vmid_hash_fn(const char *vmid, int len); 672 672 struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport, 673 673 uint32_t hash, uint8_t *buf); 674 + int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct 675 + scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag); 674 676 void lpfc_vmid_vport_cleanup(struct lpfc_vport *vport); 675 677 int lpfc_issue_els_qfpa(struct lpfc_vport *vport); 676 678
-256
drivers/scsi/lpfc/lpfc_scsi.c
··· 87 87 lpfc_release_scsi_buf_s3(struct lpfc_hba *phba, struct lpfc_io_buf *psb); 88 88 static int 89 89 lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc); 90 - static void 91 - lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash, 92 - struct lpfc_vmid *vmp); 93 - static void lpfc_vmid_update_entry(struct lpfc_vport *vport, struct scsi_cmnd 94 - *cmd, struct lpfc_vmid *vmp, 95 - union lpfc_vmid_io_tag *tag); 96 - static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport, 97 - struct lpfc_vmid *vmid); 98 90 99 91 /** 100 92 * lpfc_sli4_set_rsp_sgl_last - Set the last bit in the response sge. ··· 5260 5268 if (phba->cfg_poll & DISABLE_FCP_RING_INT) 5261 5269 lpfc_poll_rearm_timer(phba); 5262 5270 } 5263 - } 5264 - 5265 - /* 5266 - * lpfc_get_vmid_from_hashtable - search the UUID in the hash table 5267 - * @vport: The virtual port for which this call is being executed. 5268 - * @hash: calculated hash value 5269 - * @buf: uuid associated with the VE 5270 - * Return the VMID entry associated with the UUID 5271 - * Make sure to acquire the appropriate lock before invoking this routine. 5272 - */ 5273 - struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport, 5274 - u32 hash, u8 *buf) 5275 - { 5276 - struct lpfc_vmid *vmp; 5277 - 5278 - hash_for_each_possible(vport->hash_table, vmp, hnode, hash) { 5279 - if (memcmp(&vmp->host_vmid[0], buf, 16) == 0) 5280 - return vmp; 5281 - } 5282 - return NULL; 5283 - } 5284 - 5285 - /* 5286 - * lpfc_put_vmid_in_hashtable - put the VMID in the hash table 5287 - * @vport: The virtual port for which this call is being executed. 5288 - * @hash - calculated hash value 5289 - * @vmp: Pointer to a VMID entry representing a VM sending I/O 5290 - * 5291 - * This routine will insert the newly acquired VMID entity in the hash table. 5292 - * Make sure to acquire the appropriate lock before invoking this routine. 5293 - */ 5294 - static void 5295 - lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash, 5296 - struct lpfc_vmid *vmp) 5297 - { 5298 - hash_add(vport->hash_table, &vmp->hnode, hash); 5299 - } 5300 - 5301 - /* 5302 - * lpfc_vmid_hash_fn - create a hash value of the UUID 5303 - * @vmid: uuid associated with the VE 5304 - * @len: length of the VMID string 5305 - * Returns the calculated hash value 5306 - */ 5307 - int lpfc_vmid_hash_fn(const char *vmid, int len) 5308 - { 5309 - int c; 5310 - int hash = 0; 5311 - 5312 - if (len == 0) 5313 - return 0; 5314 - while (len--) { 5315 - c = *vmid++; 5316 - if (c >= 'A' && c <= 'Z') 5317 - c += 'a' - 'A'; 5318 - 5319 - hash = (hash + (c << LPFC_VMID_HASH_SHIFT) + 5320 - (c >> LPFC_VMID_HASH_SHIFT)) * 19; 5321 - } 5322 - 5323 - return hash & LPFC_VMID_HASH_MASK; 5324 - } 5325 - 5326 - /* 5327 - * lpfc_vmid_update_entry - update the vmid entry in the hash table 5328 - * @vport: The virtual port for which this call is being executed. 5329 - * @cmd: address of scsi cmd descriptor 5330 - * @vmp: Pointer to a VMID entry representing a VM sending I/O 5331 - * @tag: VMID tag 5332 - */ 5333 - static void lpfc_vmid_update_entry(struct lpfc_vport *vport, struct scsi_cmnd 5334 - *cmd, struct lpfc_vmid *vmp, 5335 - union lpfc_vmid_io_tag *tag) 5336 - { 5337 - u64 *lta; 5338 - 5339 - if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) 5340 - tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid; 5341 - else if (vport->phba->cfg_vmid_app_header) 5342 - tag->app_id = vmp->un.app_id; 5343 - 5344 - if (cmd->sc_data_direction == DMA_TO_DEVICE) 5345 - vmp->io_wr_cnt++; 5346 - else 5347 - vmp->io_rd_cnt++; 5348 - 5349 - /* update the last access timestamp in the table */ 5350 - lta = per_cpu_ptr(vmp->last_io_time, raw_smp_processor_id()); 5351 - *lta = jiffies; 5352 - } 5353 - 5354 - static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport, 5355 - struct lpfc_vmid *vmid) 5356 - { 5357 - u32 hash; 5358 - struct lpfc_vmid *pvmid; 5359 - 5360 - if (vport->port_type == LPFC_PHYSICAL_PORT) { 5361 - vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport); 5362 - } else { 5363 - hash = lpfc_vmid_hash_fn(vmid->host_vmid, vmid->vmid_len); 5364 - pvmid = 5365 - lpfc_get_vmid_from_hashtable(vport->phba->pport, hash, 5366 - vmid->host_vmid); 5367 - if (pvmid) 5368 - vmid->un.cs_ctl_vmid = pvmid->un.cs_ctl_vmid; 5369 - else 5370 - vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport); 5371 - } 5372 - } 5373 - 5374 - /* 5375 - * lpfc_vmid_get_appid - get the VMID associated with the UUID 5376 - * @vport: The virtual port for which this call is being executed. 5377 - * @uuid: UUID associated with the VE 5378 - * @cmd: address of scsi_cmd descriptor 5379 - * @tag: VMID tag 5380 - * Returns status of the function 5381 - */ 5382 - static int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, struct 5383 - scsi_cmnd * cmd, union lpfc_vmid_io_tag *tag) 5384 - { 5385 - struct lpfc_vmid *vmp = NULL; 5386 - int hash, len, rc = -EPERM, i; 5387 - 5388 - /* check if QFPA is complete */ 5389 - if (lpfc_vmid_is_type_priority_tag(vport) && 5390 - !(vport->vmid_flag & LPFC_VMID_QFPA_CMPL) && 5391 - (vport->vmid_flag & LPFC_VMID_ISSUE_QFPA)) { 5392 - vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA; 5393 - return -EAGAIN; 5394 - } 5395 - 5396 - /* search if the UUID has already been mapped to the VMID */ 5397 - len = strlen(uuid); 5398 - hash = lpfc_vmid_hash_fn(uuid, len); 5399 - 5400 - /* search for the VMID in the table */ 5401 - read_lock(&vport->vmid_lock); 5402 - vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid); 5403 - 5404 - /* if found, check if its already registered */ 5405 - if (vmp && vmp->flag & LPFC_VMID_REGISTERED) { 5406 - read_unlock(&vport->vmid_lock); 5407 - lpfc_vmid_update_entry(vport, cmd, vmp, tag); 5408 - rc = 0; 5409 - } else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER || 5410 - vmp->flag & LPFC_VMID_DE_REGISTER)) { 5411 - /* else if register or dereg request has already been sent */ 5412 - /* Hence VMID tag will not be added for this I/O */ 5413 - read_unlock(&vport->vmid_lock); 5414 - rc = -EBUSY; 5415 - } else { 5416 - /* The VMID was not found in the hashtable. At this point, */ 5417 - /* drop the read lock first before proceeding further */ 5418 - read_unlock(&vport->vmid_lock); 5419 - /* start the process to obtain one as per the */ 5420 - /* type of the VMID indicated */ 5421 - write_lock(&vport->vmid_lock); 5422 - vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid); 5423 - 5424 - /* while the read lock was released, in case the entry was */ 5425 - /* added by other context or is in process of being added */ 5426 - if (vmp && vmp->flag & LPFC_VMID_REGISTERED) { 5427 - lpfc_vmid_update_entry(vport, cmd, vmp, tag); 5428 - write_unlock(&vport->vmid_lock); 5429 - return 0; 5430 - } else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) { 5431 - write_unlock(&vport->vmid_lock); 5432 - return -EBUSY; 5433 - } 5434 - 5435 - /* else search and allocate a free slot in the hash table */ 5436 - if (vport->cur_vmid_cnt < vport->max_vmid) { 5437 - for (i = 0; i < vport->max_vmid; i++) { 5438 - vmp = vport->vmid + i; 5439 - if (vmp->flag == LPFC_VMID_SLOT_FREE) 5440 - break; 5441 - } 5442 - if (i == vport->max_vmid) 5443 - vmp = NULL; 5444 - } else { 5445 - vmp = NULL; 5446 - } 5447 - 5448 - if (!vmp) { 5449 - write_unlock(&vport->vmid_lock); 5450 - return -ENOMEM; 5451 - } 5452 - 5453 - /* Add the vmid and register */ 5454 - lpfc_put_vmid_in_hashtable(vport, hash, vmp); 5455 - vmp->vmid_len = len; 5456 - memcpy(vmp->host_vmid, uuid, vmp->vmid_len); 5457 - vmp->io_rd_cnt = 0; 5458 - vmp->io_wr_cnt = 0; 5459 - vmp->flag = LPFC_VMID_SLOT_USED; 5460 - 5461 - vmp->delete_inactive = 5462 - vport->vmid_inactivity_timeout ? 1 : 0; 5463 - 5464 - /* if type priority tag, get next available VMID */ 5465 - if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) 5466 - lpfc_vmid_assign_cs_ctl(vport, vmp); 5467 - 5468 - /* allocate the per cpu variable for holding */ 5469 - /* the last access time stamp only if VMID is enabled */ 5470 - if (!vmp->last_io_time) 5471 - vmp->last_io_time = __alloc_percpu(sizeof(u64), 5472 - __alignof__(struct 5473 - lpfc_vmid)); 5474 - if (!vmp->last_io_time) { 5475 - hash_del(&vmp->hnode); 5476 - vmp->flag = LPFC_VMID_SLOT_FREE; 5477 - write_unlock(&vport->vmid_lock); 5478 - return -EIO; 5479 - } 5480 - 5481 - write_unlock(&vport->vmid_lock); 5482 - 5483 - /* complete transaction with switch */ 5484 - if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) 5485 - rc = lpfc_vmid_uvem(vport, vmp, true); 5486 - else if (vport->phba->cfg_vmid_app_header) 5487 - rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp); 5488 - if (!rc) { 5489 - write_lock(&vport->vmid_lock); 5490 - vport->cur_vmid_cnt++; 5491 - vmp->flag |= LPFC_VMID_REQ_REGISTER; 5492 - write_unlock(&vport->vmid_lock); 5493 - } else { 5494 - write_lock(&vport->vmid_lock); 5495 - hash_del(&vmp->hnode); 5496 - vmp->flag = LPFC_VMID_SLOT_FREE; 5497 - free_percpu(vmp->last_io_time); 5498 - write_unlock(&vport->vmid_lock); 5499 - return -EIO; 5500 - } 5501 - 5502 - /* finally, enable the idle timer once */ 5503 - if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) { 5504 - mod_timer(&vport->phba->inactive_vmid_poll, 5505 - jiffies + 5506 - msecs_to_jiffies(1000 * LPFC_VMID_TIMER)); 5507 - vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD; 5508 - } 5509 - } 5510 - return rc; 5511 5271 } 5512 5272 5513 5273 /*
+288
drivers/scsi/lpfc/lpfc_vmid.c
··· 1 + /******************************************************************* 2 + * This file is part of the Emulex Linux Device Driver for * 3 + * Fibre Channel Host Bus Adapters. * 4 + * Copyright (C) 2017-2022 Broadcom. All Rights Reserved. The term * 5 + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * 6 + * Copyright (C) 2004-2016 Emulex. All rights reserved. * 7 + * EMULEX and SLI are trademarks of Emulex. * 8 + * www.broadcom.com * 9 + * Portions Copyright (C) 2004-2005 Christoph Hellwig * 10 + * * 11 + * This program is free software; you can redistribute it and/or * 12 + * modify it under the terms of version 2 of the GNU General * 13 + * Public License as published by the Free Software Foundation. * 14 + * This program is distributed in the hope that it will be useful. * 15 + * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND * 16 + * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, * 17 + * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE * 18 + * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD * 19 + * TO BE LEGALLY INVALID. See the GNU General Public License for * 20 + * more details, a copy of which can be found in the file COPYING * 21 + * included with this package. * 22 + *******************************************************************/ 23 + 24 + #include <linux/interrupt.h> 25 + #include <linux/dma-direction.h> 26 + 27 + #include <scsi/scsi_transport_fc.h> 28 + 29 + #include "lpfc_hw4.h" 30 + #include "lpfc_hw.h" 31 + #include "lpfc_sli.h" 32 + #include "lpfc_sli4.h" 33 + #include "lpfc_nl.h" 34 + #include "lpfc_disc.h" 35 + #include "lpfc.h" 36 + #include "lpfc_crtn.h" 37 + 38 + 39 + /* 40 + * lpfc_get_vmid_from_hashtable - search the UUID in the hash table 41 + * @vport: The virtual port for which this call is being executed. 42 + * @hash: calculated hash value 43 + * @buf: uuid associated with the VE 44 + * Return the VMID entry associated with the UUID 45 + * Make sure to acquire the appropriate lock before invoking this routine. 46 + */ 47 + struct lpfc_vmid *lpfc_get_vmid_from_hashtable(struct lpfc_vport *vport, 48 + u32 hash, u8 *buf) 49 + { 50 + struct lpfc_vmid *vmp; 51 + 52 + hash_for_each_possible(vport->hash_table, vmp, hnode, hash) { 53 + if (memcmp(&vmp->host_vmid[0], buf, 16) == 0) 54 + return vmp; 55 + } 56 + return NULL; 57 + } 58 + 59 + /* 60 + * lpfc_put_vmid_in_hashtable - put the VMID in the hash table 61 + * @vport: The virtual port for which this call is being executed. 62 + * @hash - calculated hash value 63 + * @vmp: Pointer to a VMID entry representing a VM sending I/O 64 + * 65 + * This routine will insert the newly acquired VMID entity in the hash table. 66 + * Make sure to acquire the appropriate lock before invoking this routine. 67 + */ 68 + static void 69 + lpfc_put_vmid_in_hashtable(struct lpfc_vport *vport, u32 hash, 70 + struct lpfc_vmid *vmp) 71 + { 72 + hash_add(vport->hash_table, &vmp->hnode, hash); 73 + } 74 + 75 + /* 76 + * lpfc_vmid_hash_fn - create a hash value of the UUID 77 + * @vmid: uuid associated with the VE 78 + * @len: length of the VMID string 79 + * Returns the calculated hash value 80 + */ 81 + int lpfc_vmid_hash_fn(const char *vmid, int len) 82 + { 83 + int c; 84 + int hash = 0; 85 + 86 + if (len == 0) 87 + return 0; 88 + while (len--) { 89 + c = *vmid++; 90 + if (c >= 'A' && c <= 'Z') 91 + c += 'a' - 'A'; 92 + 93 + hash = (hash + (c << LPFC_VMID_HASH_SHIFT) + 94 + (c >> LPFC_VMID_HASH_SHIFT)) * 19; 95 + } 96 + 97 + return hash & LPFC_VMID_HASH_MASK; 98 + } 99 + 100 + /* 101 + * lpfc_vmid_update_entry - update the vmid entry in the hash table 102 + * @vport: The virtual port for which this call is being executed. 103 + * @iodir: io direction 104 + * @vmp: Pointer to a VMID entry representing a VM sending I/O 105 + * @tag: VMID tag 106 + */ 107 + static void lpfc_vmid_update_entry(struct lpfc_vport *vport, 108 + enum dma_data_direction iodir, 109 + struct lpfc_vmid *vmp, 110 + union lpfc_vmid_io_tag *tag) 111 + { 112 + u64 *lta; 113 + 114 + if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) 115 + tag->cs_ctl_vmid = vmp->un.cs_ctl_vmid; 116 + else if (vport->phba->cfg_vmid_app_header) 117 + tag->app_id = vmp->un.app_id; 118 + 119 + if (iodir == DMA_TO_DEVICE) 120 + vmp->io_wr_cnt++; 121 + else if (iodir == DMA_FROM_DEVICE) 122 + vmp->io_rd_cnt++; 123 + 124 + /* update the last access timestamp in the table */ 125 + lta = per_cpu_ptr(vmp->last_io_time, raw_smp_processor_id()); 126 + *lta = jiffies; 127 + } 128 + 129 + static void lpfc_vmid_assign_cs_ctl(struct lpfc_vport *vport, 130 + struct lpfc_vmid *vmid) 131 + { 132 + u32 hash; 133 + struct lpfc_vmid *pvmid; 134 + 135 + if (vport->port_type == LPFC_PHYSICAL_PORT) { 136 + vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport); 137 + } else { 138 + hash = lpfc_vmid_hash_fn(vmid->host_vmid, vmid->vmid_len); 139 + pvmid = 140 + lpfc_get_vmid_from_hashtable(vport->phba->pport, hash, 141 + vmid->host_vmid); 142 + if (pvmid) 143 + vmid->un.cs_ctl_vmid = pvmid->un.cs_ctl_vmid; 144 + else 145 + vmid->un.cs_ctl_vmid = lpfc_vmid_get_cs_ctl(vport); 146 + } 147 + } 148 + 149 + /* 150 + * lpfc_vmid_get_appid - get the VMID associated with the UUID 151 + * @vport: The virtual port for which this call is being executed. 152 + * @uuid: UUID associated with the VE 153 + * @cmd: address of scsi_cmd descriptor 154 + * @iodir: io direction 155 + * @tag: VMID tag 156 + * Returns status of the function 157 + */ 158 + int lpfc_vmid_get_appid(struct lpfc_vport *vport, char *uuid, 159 + enum dma_data_direction iodir, 160 + union lpfc_vmid_io_tag *tag) 161 + { 162 + struct lpfc_vmid *vmp = NULL; 163 + int hash, len, rc = -EPERM, i; 164 + 165 + /* check if QFPA is complete */ 166 + if (lpfc_vmid_is_type_priority_tag(vport) && 167 + !(vport->vmid_flag & LPFC_VMID_QFPA_CMPL) && 168 + (vport->vmid_flag & LPFC_VMID_ISSUE_QFPA)) { 169 + vport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA; 170 + return -EAGAIN; 171 + } 172 + 173 + /* search if the UUID has already been mapped to the VMID */ 174 + len = strlen(uuid); 175 + hash = lpfc_vmid_hash_fn(uuid, len); 176 + 177 + /* search for the VMID in the table */ 178 + read_lock(&vport->vmid_lock); 179 + vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid); 180 + 181 + /* if found, check if its already registered */ 182 + if (vmp && vmp->flag & LPFC_VMID_REGISTERED) { 183 + read_unlock(&vport->vmid_lock); 184 + lpfc_vmid_update_entry(vport, iodir, vmp, tag); 185 + rc = 0; 186 + } else if (vmp && (vmp->flag & LPFC_VMID_REQ_REGISTER || 187 + vmp->flag & LPFC_VMID_DE_REGISTER)) { 188 + /* else if register or dereg request has already been sent */ 189 + /* Hence VMID tag will not be added for this I/O */ 190 + read_unlock(&vport->vmid_lock); 191 + rc = -EBUSY; 192 + } else { 193 + /* The VMID was not found in the hashtable. At this point, */ 194 + /* drop the read lock first before proceeding further */ 195 + read_unlock(&vport->vmid_lock); 196 + /* start the process to obtain one as per the */ 197 + /* type of the VMID indicated */ 198 + write_lock(&vport->vmid_lock); 199 + vmp = lpfc_get_vmid_from_hashtable(vport, hash, uuid); 200 + 201 + /* while the read lock was released, in case the entry was */ 202 + /* added by other context or is in process of being added */ 203 + if (vmp && vmp->flag & LPFC_VMID_REGISTERED) { 204 + lpfc_vmid_update_entry(vport, iodir, vmp, tag); 205 + write_unlock(&vport->vmid_lock); 206 + return 0; 207 + } else if (vmp && vmp->flag & LPFC_VMID_REQ_REGISTER) { 208 + write_unlock(&vport->vmid_lock); 209 + return -EBUSY; 210 + } 211 + 212 + /* else search and allocate a free slot in the hash table */ 213 + if (vport->cur_vmid_cnt < vport->max_vmid) { 214 + for (i = 0; i < vport->max_vmid; i++) { 215 + vmp = vport->vmid + i; 216 + if (vmp->flag == LPFC_VMID_SLOT_FREE) 217 + break; 218 + } 219 + if (i == vport->max_vmid) 220 + vmp = NULL; 221 + } else { 222 + vmp = NULL; 223 + } 224 + 225 + if (!vmp) { 226 + write_unlock(&vport->vmid_lock); 227 + return -ENOMEM; 228 + } 229 + 230 + /* Add the vmid and register */ 231 + lpfc_put_vmid_in_hashtable(vport, hash, vmp); 232 + vmp->vmid_len = len; 233 + memcpy(vmp->host_vmid, uuid, vmp->vmid_len); 234 + vmp->io_rd_cnt = 0; 235 + vmp->io_wr_cnt = 0; 236 + vmp->flag = LPFC_VMID_SLOT_USED; 237 + 238 + vmp->delete_inactive = 239 + vport->vmid_inactivity_timeout ? 1 : 0; 240 + 241 + /* if type priority tag, get next available VMID */ 242 + if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) 243 + lpfc_vmid_assign_cs_ctl(vport, vmp); 244 + 245 + /* allocate the per cpu variable for holding */ 246 + /* the last access time stamp only if VMID is enabled */ 247 + if (!vmp->last_io_time) 248 + vmp->last_io_time = __alloc_percpu(sizeof(u64), 249 + __alignof__(struct 250 + lpfc_vmid)); 251 + if (!vmp->last_io_time) { 252 + hash_del(&vmp->hnode); 253 + vmp->flag = LPFC_VMID_SLOT_FREE; 254 + write_unlock(&vport->vmid_lock); 255 + return -EIO; 256 + } 257 + 258 + write_unlock(&vport->vmid_lock); 259 + 260 + /* complete transaction with switch */ 261 + if (vport->phba->pport->vmid_flag & LPFC_VMID_TYPE_PRIO) 262 + rc = lpfc_vmid_uvem(vport, vmp, true); 263 + else if (vport->phba->cfg_vmid_app_header) 264 + rc = lpfc_vmid_cmd(vport, SLI_CTAS_RAPP_IDENT, vmp); 265 + if (!rc) { 266 + write_lock(&vport->vmid_lock); 267 + vport->cur_vmid_cnt++; 268 + vmp->flag |= LPFC_VMID_REQ_REGISTER; 269 + write_unlock(&vport->vmid_lock); 270 + } else { 271 + write_lock(&vport->vmid_lock); 272 + hash_del(&vmp->hnode); 273 + vmp->flag = LPFC_VMID_SLOT_FREE; 274 + free_percpu(vmp->last_io_time); 275 + write_unlock(&vport->vmid_lock); 276 + return -EIO; 277 + } 278 + 279 + /* finally, enable the idle timer once */ 280 + if (!(vport->phba->pport->vmid_flag & LPFC_VMID_TIMER_ENBLD)) { 281 + mod_timer(&vport->phba->inactive_vmid_poll, 282 + jiffies + 283 + msecs_to_jiffies(1000 * LPFC_VMID_TIMER)); 284 + vport->phba->pport->vmid_flag |= LPFC_VMID_TIMER_ENBLD; 285 + } 286 + } 287 + return rc; 288 + }