📄 commsup.c
字号:
fib_dealloc(fibptr); } else if(hw_fib->header.XferState & cpu_to_le32(SentFromHost)) { /* * This handles the case when the host has aborted the I/O * to the adapter because the adapter is not responding */ fib_dealloc(fibptr); } else if(hw_fib->header.XferState & cpu_to_le32(HostOwned)) { fib_dealloc(fibptr); } else { BUG(); } return 0;}/** * aac_printf - handle printf from firmware * @dev: Adapter * @val: Message info * * Print a message passed to us by the controller firmware on the * Adaptec board */void aac_printf(struct aac_dev *dev, u32 val){ int length = val & 0xffff; int level = (val >> 16) & 0xffff; char *cp = dev->printfbuf; /* * The size of the printfbuf is set in port.c * There is no variable or define for it */ if (length > 255) length = 255; if (cp[length] != 0) cp[length] = 0; if (level == LOG_HIGH_ERROR) printk(KERN_WARNING "aacraid:%s", cp); else printk(KERN_INFO "aacraid:%s", cp); memset(cp, 0, 256);}/** * aac_handle_aif - Handle a message from the firmware * @dev: Which adapter this fib is from * @fibptr: Pointer to fibptr from adapter * * This routine handles a driver notify fib from the adapter and * dispatches it to the appropriate routine for handling. */#define CONTAINER_TO_BUS(cont) (0)#define CONTAINER_TO_TARGET(cont) ((cont))#define CONTAINER_TO_LUN(cont) (0)static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr){ struct hw_fib * hw_fib = fibptr->hw_fib; struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data; int busy; u32 container; /* Sniff for container changes */ dprintk ((KERN_INFO "AifCmdDriverNotify=%x\n", le32_to_cpu(*(u32 *)aifcmd->data))); switch (le32_to_cpu(*(u32 *)aifcmd->data)) { case AifDenMorphComplete: case AifDenVolumeExtendComplete: case AifEnContainerChange: /* Not really a driver notify Event */ busy = 0; container = le32_to_cpu(((u32 *)aifcmd->data)[1]); dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d) ", container, (dev && dev->scsi_host_ptr) ? dev->scsi_host_ptr->host_no : -1, CONTAINER_TO_BUS(container), CONTAINER_TO_TARGET(container), CONTAINER_TO_LUN(container))); /* * 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 != (struct aac_dev *)NULL) && (dev->scsi_host_ptr != (struct Scsi_Host *)NULL)) { Scsi_Device * device; for (device = dev->scsi_host_ptr->host_queue; device != (Scsi_Device *)NULL; device = device->next) { dprintk((KERN_INFO "aifd: device (%d,%d,%d,%d)?\n", dev->scsi_host_ptr->host_no, device->channel, device->id, device->lun)); if ((device->channel == CONTAINER_TO_BUS(container)) && (device->id == CONTAINER_TO_TARGET(container)) && (device->lun == CONTAINER_TO_LUN(container))) { busy |= (device->access_count != 0); if (busy == 0) { device->removable = TRUE; } } } } dprintk (("busy=%d\n", busy)); /* * if (busy == 0) { * scan_scsis(dev->scsi_host_ptr, 1, * CONTAINER_TO_BUS(container), * CONTAINER_TO_TARGET(container), * CONTAINER_TO_LUN(container)); * } * is not exported as accessible, so we need to go around it * another way. So, we look for the "proc/scsi/scsi" entry in * the proc filesystem (using proc_scsi as a shortcut) and send * it a message. This deals with new devices that have * appeared. If the device has gone offline, scan_scsis will * also discover this, but we do not want the device to * go away. We need to check the access_count for the * device since we are not wanting the devices to go away. */ if ((busy == 0) && (proc_scsi != (struct proc_dir_entry *)NULL)) { struct proc_dir_entry * entry; dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi)); for (entry = proc_scsi->subdir; entry != (struct proc_dir_entry *)NULL; entry = entry->next) { dprintk(("\"%.*s\"[%d]=%x ", entry->namelen, entry->name, entry->namelen, entry->low_ino)); if ((entry->low_ino != 0) && (entry->namelen == 4) && (memcmp ("scsi", entry->name, 4) == 0)) { dprintk(("%p->write_proc=%p ", entry, entry->write_proc)); if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) { char buffer[80]; int length; mm_segment_t fs; sprintf (buffer, "scsi add-single-device %d %d %d %d\n", dev->scsi_host_ptr->host_no, CONTAINER_TO_BUS(container), CONTAINER_TO_TARGET(container), CONTAINER_TO_LUN(container)); length = strlen (buffer); dprintk((KERN_INFO "echo %.*s > /proc/scsi/scsi\n", length-1, buffer)); fs = get_fs(); set_fs(get_ds()); length = entry->write_proc( NULL, buffer, length, NULL); set_fs(fs); dprintk((KERN_INFO "returns %d\n", length)); } break; } } } }}/** * 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_queue_block *queues = dev->queues; 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]. */ sprintf(current->comm, "aacraid"); daemonize(); /* * Let the DPC know it has a place to send the AIF's to. */ dev->aif_thread = 1; add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); set_current_state(TASK_INTERRUPTIBLE); dprintk ((KERN_INFO "aac_command_thread start\n")); while(1) { spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) { struct list_head *entry; struct aac_aifcmd * aifcmd; set_current_state(TASK_RUNNING); entry = queues->queue[HostNormCmdQueue].cmdq.next; list_del(entry); spin_unlock_irqrestore(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); *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, 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; /* Sniff events */ if (aifcmd->command == cpu_to_le32(AifCmdEventNotify)) aac_handle_aif(dev, fib); time_now = jiffies/HZ; 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. */ 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 */ hw_newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC); newfib = kmalloc(sizeof(struct fib), GFP_ATOMIC); if (newfib && hw_newfib) { /* * Make the copy of the FIB * FIXME: check if we need to fix other fields up */ 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 will waiting. */ up(&fibctx->wait_sem); } else { printk(KERN_WARNING "aifd: didn't allocate NewFib.\n"); if(newfib) kfree(newfib); if(hw_newfib) kfree(hw_newfib); } entry = entry->next; } /* * Set the status of this FIB */ *(u32 *)hw_fib->data = cpu_to_le32(ST_OK); fib_adapter_complete(fib, sizeof(u32)); spin_unlock_irqrestore(&dev->fib_lock, flagv); } spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags); kfree(fib); } /* * There are no more AIF's */ spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags); schedule(); if(signal_pending(current)) break; set_current_state(TASK_INTERRUPTIBLE); } remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait); dev->aif_thread = 0; complete_and_exit(&dev->aif_completion, 0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -