📄 commsup.c
字号:
container < dev->maximum_num_containers; ++container) { if (dev->fsa_dev[container].config_waiting_on == le32_to_cpu(*(u32 *)aifcmd->data)) dev->fsa_dev[container].config_waiting_on = 0; } break; case AifCmdEventNotify: switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) { /* * Add an Array. */ case AifEnAddContainer: container = le32_to_cpu(((u32 *)aifcmd->data)[1]); if (container >= dev->maximum_num_containers) break; dev->fsa_dev[container].config_needed = ADD; dev->fsa_dev[container].config_waiting_on = AifEnConfigChange; break; /* * Delete an Array. */ case AifEnDeleteContainer: container = le32_to_cpu(((u32 *)aifcmd->data)[1]); if (container >= dev->maximum_num_containers) break; dev->fsa_dev[container].config_needed = DELETE; dev->fsa_dev[container].config_waiting_on = AifEnConfigChange; break; /* * Container change detected. If we currently are not * waiting on something else, setup to wait on a Config Change. */ case AifEnContainerChange: container = le32_to_cpu(((u32 *)aifcmd->data)[1]); if (container >= dev->maximum_num_containers) break; if (dev->fsa_dev[container].config_waiting_on) break; dev->fsa_dev[container].config_needed = CHANGE; dev->fsa_dev[container].config_waiting_on = AifEnConfigChange; break; case AifEnConfigChange: break; } /* * If we are waiting on something and this happens to be * that thing then set the re-configure flag. */ if (container != (u32)-1) { if (container >= dev->maximum_num_containers) break; if (dev->fsa_dev[container].config_waiting_on == le32_to_cpu(*(u32 *)aifcmd->data)) dev->fsa_dev[container].config_waiting_on = 0; } else for (container = 0; container < dev->maximum_num_containers; ++container) { if (dev->fsa_dev[container].config_waiting_on == le32_to_cpu(*(u32 *)aifcmd->data)) dev->fsa_dev[container].config_waiting_on = 0; } break; case AifCmdJobProgress: /* * These are job progress AIF's. When a Clear is being * done on a container it is initially created then hidden from * the OS. When the clear completes we don't get a config * change so we monitor the job status complete on a clear then * wait for a container change. */ if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero)) && ((((u32 *)aifcmd->data)[6] == ((u32 *)aifcmd->data)[5]) || (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsSuccess)))) { for (container = 0; container < dev->maximum_num_containers; ++container) { /* * Stomp on all config sequencing for all * containers? */ dev->fsa_dev[container].config_waiting_on = AifEnContainerChange; dev->fsa_dev[container].config_needed = ADD; } } if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero)) && (((u32 *)aifcmd->data)[6] == 0) && (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsRunning))) { for (container = 0; container < dev->maximum_num_containers; ++container) { /* * Stomp on all config sequencing for all * containers? */ dev->fsa_dev[container].config_waiting_on = AifEnContainerChange; dev->fsa_dev[container].config_needed = DELETE; } } break; } device_config_needed = NOTHING; for (container = 0; container < dev->maximum_num_containers; ++container) { if ((dev->fsa_dev[container].config_waiting_on == 0) && (dev->fsa_dev[container].config_needed != NOTHING)) { device_config_needed = dev->fsa_dev[container].config_needed; dev->fsa_dev[container].config_needed = NOTHING; break; } } if (device_config_needed == NOTHING) return; /* * If we decided that a re-configuration needs to be done, * schedule it here on the way out the door, please close the door * behind you. */ busy = 0; /* * Find the scsi_device associated with the SCSI address, * and mark it as changed, invalidating the cache. This deals * with changes to existing device IDs. */ if (!dev || !dev->scsi_host_ptr) return; /* * force reload of disk info via probe_container */ if ((device_config_needed == CHANGE) && (dev->fsa_dev[container].valid == 1)) dev->fsa_dev[container].valid = 2; if ((device_config_needed == CHANGE) || (device_config_needed == ADD)) probe_container(dev, container); device = scsi_device_lookup(dev->scsi_host_ptr, CONTAINER_TO_CHANNEL(container), CONTAINER_TO_ID(container), CONTAINER_TO_LUN(container)); if (device) { switch (device_config_needed) { case DELETE: scsi_remove_device(device); break; case CHANGE: if (!dev->fsa_dev[container].valid) { scsi_remove_device(device); break; } scsi_rescan_device(&device->sdev_gendev); default: break; } scsi_device_put(device); } if (device_config_needed == ADD) { scsi_add_device(dev->scsi_host_ptr, CONTAINER_TO_CHANNEL(container), CONTAINER_TO_ID(container), CONTAINER_TO_LUN(container)); }}/** * aac_command_thread - command processing thread * @dev: Adapter to monitor * * Waits on the commandready event in it's queue. When the event gets set * it will pull FIBs off it's queue. It will continue to pull FIBs off * until the queue is empty. When the queue is empty it will wait for * more FIBs. */ int aac_command_thread(struct aac_dev * dev){ struct hw_fib *hw_fib, *hw_newfib; struct fib *fib, *newfib; struct aac_fib_context *fibctx; unsigned long flags; DECLARE_WAITQUEUE(wait, current); /* * We can only have one thread per adapter for AIF's. */ if (dev->aif_thread) return -EINVAL; /* * Set up the name that will appear in 'ps' * stored in task_struct.comm[16]. */ daemonize("aacraid"); allow_signal(SIGKILL); /* * Let the DPC know it has a place to send the AIF's to. */ dev->aif_thread = 1; add_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); set_current_state(TASK_INTERRUPTIBLE); dprintk ((KERN_INFO "aac_command_thread start\n")); while(1) { spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); while(!list_empty(&(dev->queues->queue[HostNormCmdQueue].cmdq))) { struct list_head *entry; struct aac_aifcmd * aifcmd; set_current_state(TASK_RUNNING); entry = dev->queues->queue[HostNormCmdQueue].cmdq.next; list_del(entry); spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); fib = list_entry(entry, struct fib, fiblink); /* * We will process the FIB here or pass it to a * worker thread that is TBD. We Really can't * do anything at this point since we don't have * anything defined for this thread to do. */ hw_fib = fib->hw_fib; memset(fib, 0, sizeof(struct fib)); fib->type = FSAFS_NTC_FIB_CONTEXT; fib->size = sizeof( struct fib ); fib->hw_fib = hw_fib; fib->data = hw_fib->data; fib->dev = dev; /* * We only handle AifRequest fibs from the adapter. */ aifcmd = (struct aac_aifcmd *) hw_fib->data; if (aifcmd->command == cpu_to_le32(AifCmdDriverNotify)) { /* Handle Driver Notify Events */ aac_handle_aif(dev, fib); *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, (u16)sizeof(u32)); } else { struct list_head *entry; /* The u32 here is important and intended. We are using 32bit wrapping time to fit the adapter field */ u32 time_now, time_last; unsigned long flagv; unsigned num; struct hw_fib ** hw_fib_pool, ** hw_fib_p; struct fib ** fib_pool, ** fib_p; /* Sniff events */ if ((aifcmd->command == cpu_to_le32(AifCmdEventNotify)) || (aifcmd->command == cpu_to_le32(AifCmdJobProgress))) { aac_handle_aif(dev, fib); } time_now = jiffies/HZ; /* * Warning: no sleep allowed while * holding spinlock. We take the estimate * and pre-allocate a set of fibs outside the * lock. */ num = le32_to_cpu(dev->init->AdapterFibsSize) / sizeof(struct hw_fib); /* some extra */ spin_lock_irqsave(&dev->fib_lock, flagv); entry = dev->fib_list.next; while (entry != &dev->fib_list) { entry = entry->next; ++num; } spin_unlock_irqrestore(&dev->fib_lock, flagv); hw_fib_pool = NULL; fib_pool = NULL; if (num && ((hw_fib_pool = kmalloc(sizeof(struct hw_fib *) * num, GFP_KERNEL))) && ((fib_pool = kmalloc(sizeof(struct fib *) * num, GFP_KERNEL)))) { hw_fib_p = hw_fib_pool; fib_p = fib_pool; while (hw_fib_p < &hw_fib_pool[num]) { if (!(*(hw_fib_p++) = kmalloc(sizeof(struct hw_fib), GFP_KERNEL))) { --hw_fib_p; break; } if (!(*(fib_p++) = kmalloc(sizeof(struct fib), GFP_KERNEL))) { kfree(*(--hw_fib_p)); break; } } if ((num = hw_fib_p - hw_fib_pool) == 0) { kfree(fib_pool); fib_pool = NULL; kfree(hw_fib_pool); hw_fib_pool = NULL; } } else { kfree(hw_fib_pool); hw_fib_pool = NULL; } spin_lock_irqsave(&dev->fib_lock, flagv); entry = dev->fib_list.next; /* * For each Context that is on the * fibctxList, make a copy of the * fib, and then set the event to wake up the * thread that is waiting for it. */ hw_fib_p = hw_fib_pool; fib_p = fib_pool; while (entry != &dev->fib_list) { /* * Extract the fibctx */ fibctx = list_entry(entry, struct aac_fib_context, next); /* * Check if the queue is getting * backlogged */ if (fibctx->count > 20) { /* * It's *not* jiffies folks, * but jiffies / HZ so do not * panic ... */ time_last = fibctx->jiffies; /* * Has it been > 2 minutes * since the last read off * the queue? */ if ((time_now - time_last) > 120) { entry = entry->next; aac_close_fib_context(dev, fibctx); continue; } } /* * Warning: no sleep allowed while * holding spinlock */ if (hw_fib_p < &hw_fib_pool[num]) { hw_newfib = *hw_fib_p; *(hw_fib_p++) = NULL; newfib = *fib_p; *(fib_p++) = NULL; /* * Make the copy of the FIB */ memcpy(hw_newfib, hw_fib, sizeof(struct hw_fib)); memcpy(newfib, fib, sizeof(struct fib)); newfib->hw_fib = hw_newfib; /* * Put the FIB onto the * fibctx's fibs */ list_add_tail(&newfib->fiblink, &fibctx->fib_list); fibctx->count++; /* * Set the event to wake up the * thread that is waiting. */ up(&fibctx->wait_sem); } else { printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); } entry = entry->next; } /* * Set the status of this FIB */ *(__le32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); /* Free up the remaining resources */ hw_fib_p = hw_fib_pool; fib_p = fib_pool; while (hw_fib_p < &hw_fib_pool[num]) { kfree(*hw_fib_p); kfree(*fib_p); ++fib_p; ++hw_fib_p; } kfree(hw_fib_pool); kfree(fib_pool); } kfree(fib); spin_lock_irqsave(dev->queues->queue[HostNormCmdQueue].lock, flags); } /* * There are no more AIF's */ spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); schedule(); if(signal_pending(current)) break; set_current_state(TASK_INTERRUPTIBLE); } if (dev->queues) remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); dev->aif_thread = 0; complete_and_exit(&dev->aif_completion, 0); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -