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

Configure Feed

Select the types of activity you want to include in your feed.

scsi: lpfc: vmid: Timeout implementation for VMID

Implement timeout functionality for the VMID. After the set time period of
inactivity, the VMID is deregistered from the switch.

Link: https://lore.kernel.org/r/20210608043556.274139-12-muneendra.kumar@broadcom.com
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Gaurav Srivastava <gaurav.srivastava@broadcom.com>
Signed-off-by: James Smart <jsmart2021@gmail.com>
Signed-off-by: Muneendra Kumar <muneendra.kumar@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Gaurav Srivastava and committed by
Martin K. Petersen
20397179 f56e86a0

+145
+105
drivers/scsi/lpfc/lpfc_hbadisc.c
··· 72 72 static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); 73 73 static int lpfc_fcf_inuse(struct lpfc_hba *); 74 74 static void lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *); 75 + static void lpfc_check_inactive_vmid(struct lpfc_hba *phba); 75 76 76 77 static int 77 78 lpfc_valid_xpt_node(struct lpfc_nodelist *ndlp) ··· 233 232 spin_unlock_irqrestore(&phba->hbalock, iflags); 234 233 235 234 return; 235 + } 236 + 237 + /** 238 + * lpfc_check_inactive_vmid_one - VMID inactivity checker for a vport 239 + * @vport: Pointer to vport context object. 240 + * 241 + * This function checks for idle VMID entries related to a particular vport. If 242 + * found unused/idle, free them accordingly. 243 + **/ 244 + static void lpfc_check_inactive_vmid_one(struct lpfc_vport *vport) 245 + { 246 + u16 keep; 247 + u32 difftime = 0, r, bucket; 248 + u64 *lta; 249 + int cpu; 250 + struct lpfc_vmid *vmp; 251 + 252 + write_lock(&vport->vmid_lock); 253 + 254 + if (!vport->cur_vmid_cnt) 255 + goto out; 256 + 257 + /* iterate through the table */ 258 + hash_for_each(vport->hash_table, bucket, vmp, hnode) { 259 + keep = 0; 260 + if (vmp->flag & LPFC_VMID_REGISTERED) { 261 + /* check if the particular VMID is in use */ 262 + /* for all available per cpu variable */ 263 + for_each_possible_cpu(cpu) { 264 + /* if last access time is less than timeout */ 265 + lta = per_cpu_ptr(vmp->last_io_time, cpu); 266 + if (!lta) 267 + continue; 268 + difftime = (jiffies) - (*lta); 269 + if ((vport->vmid_inactivity_timeout * 270 + JIFFIES_PER_HR) > difftime) { 271 + keep = 1; 272 + break; 273 + } 274 + } 275 + 276 + /* if none of the cpus have been used by the vm, */ 277 + /* remove the entry if already registered */ 278 + if (!keep) { 279 + /* mark the entry for deregistration */ 280 + vmp->flag = LPFC_VMID_DE_REGISTER; 281 + write_unlock(&vport->vmid_lock); 282 + if (vport->vmid_priority_tagging) 283 + r = lpfc_vmid_uvem(vport, vmp, false); 284 + else 285 + r = lpfc_vmid_cmd(vport, 286 + SLI_CTAS_DAPP_IDENT, 287 + vmp); 288 + 289 + /* decrement number of active vms and mark */ 290 + /* entry in slot as free */ 291 + write_lock(&vport->vmid_lock); 292 + if (!r) { 293 + struct lpfc_vmid *ht = vmp; 294 + 295 + vport->cur_vmid_cnt--; 296 + ht->flag = LPFC_VMID_SLOT_FREE; 297 + free_percpu(ht->last_io_time); 298 + ht->last_io_time = NULL; 299 + hash_del(&ht->hnode); 300 + } 301 + } 302 + } 303 + } 304 + out: 305 + write_unlock(&vport->vmid_lock); 306 + } 307 + 308 + /** 309 + * lpfc_check_inactive_vmid - VMID inactivity checker 310 + * @phba: Pointer to hba context object. 311 + * 312 + * This function is called from the worker thread to determine if an entry in 313 + * the VMID table can be released since there was no I/O activity seen from that 314 + * particular VM for the specified time. When this happens, the entry in the 315 + * table is released and also the resources on the switch cleared. 316 + **/ 317 + 318 + static void lpfc_check_inactive_vmid(struct lpfc_hba *phba) 319 + { 320 + struct lpfc_vport *vport; 321 + struct lpfc_vport **vports; 322 + int i; 323 + 324 + vports = lpfc_create_vport_work_array(phba); 325 + if (!vports) 326 + return; 327 + 328 + for (i = 0; i <= phba->max_vports; i++) { 329 + if ((!vports[i]) && (i == 0)) 330 + vport = phba->pport; 331 + else 332 + vport = vports[i]; 333 + if (!vport) 334 + break; 335 + 336 + lpfc_check_inactive_vmid_one(vport); 337 + } 338 + lpfc_destroy_vport_work_array(phba, vports); 236 339 } 237 340 238 341 /**
+40
drivers/scsi/lpfc/lpfc_init.c
··· 4844 4844 } 4845 4845 4846 4846 /** 4847 + * lpfc_vmid_poll - VMID timeout detection 4848 + * @ptr: Map to lpfc_hba data structure pointer. 4849 + * 4850 + * This routine is invoked when there is no I/O on by a VM for the specified 4851 + * amount of time. When this situation is detected, the VMID has to be 4852 + * deregistered from the switch and all the local resources freed. The VMID 4853 + * will be reassigned to the VM once the I/O begins. 4854 + **/ 4855 + static void 4856 + lpfc_vmid_poll(struct timer_list *t) 4857 + { 4858 + struct lpfc_hba *phba = from_timer(phba, t, inactive_vmid_poll); 4859 + u32 wake_up = 0; 4860 + 4861 + /* check if there is a need to issue QFPA */ 4862 + if (phba->pport->vmid_priority_tagging) { 4863 + wake_up = 1; 4864 + phba->pport->work_port_events |= WORKER_CHECK_VMID_ISSUE_QFPA; 4865 + } 4866 + 4867 + /* Is the vmid inactivity timer enabled */ 4868 + if (phba->pport->vmid_inactivity_timeout || 4869 + phba->pport->load_flag & FC_DEREGISTER_ALL_APP_ID) { 4870 + wake_up = 1; 4871 + phba->pport->work_port_events |= WORKER_CHECK_INACTIVE_VMID; 4872 + } 4873 + 4874 + if (wake_up) 4875 + lpfc_worker_wake_up(phba); 4876 + 4877 + /* restart the timer for the next iteration */ 4878 + mod_timer(&phba->inactive_vmid_poll, jiffies + msecs_to_jiffies(1000 * 4879 + LPFC_VMID_TIMER)); 4880 + } 4881 + 4882 + /** 4847 4883 * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code 4848 4884 * @phba: pointer to lpfc hba data structure. 4849 4885 * @acqe_link: pointer to the async link completion queue entry. ··· 6726 6690 INIT_LIST_HEAD(&phba->hbqs[LPFC_ELS_HBQ].hbq_buffer_list); 6727 6691 phba->hbqs[LPFC_ELS_HBQ].hbq_alloc_buffer = lpfc_sli4_rb_alloc; 6728 6692 phba->hbqs[LPFC_ELS_HBQ].hbq_free_buffer = lpfc_sli4_rb_free; 6693 + 6694 + /* for VMID idle timeout if VMID is enabled */ 6695 + if (lpfc_is_vmid_enabled(phba)) 6696 + timer_setup(&phba->inactive_vmid_poll, lpfc_vmid_poll, 0); 6729 6697 6730 6698 /* 6731 6699 * Initialize the SLI Layer to run with lpfc SLI4 HBAs.