X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Fmegaraid%2Fmegaraid_mm.c;h=e12024dda32ee6e2877f73660aae6b01acb783df;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=8a6bc9391e4e5a77b1975e54e03bef8dc22af99f;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index 8a6bc9391..e12024dda 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_mm.c - * Version : v2.20.2.0 (August 19 2004) + * Version : v2.20.2.5 (Jan 21 2005) * * Common management module */ @@ -58,14 +58,15 @@ MODULE_PARM_DESC(dlevel, "Debug level (default=0)"); EXPORT_SYMBOL(mraid_mm_register_adp); EXPORT_SYMBOL(mraid_mm_unregister_adp); +EXPORT_SYMBOL(mraid_mm_adapter_app_handle); static int majorno; -static uint32_t drvr_ver = 0x02200100; +static uint32_t drvr_ver = 0x02200201; static int adapters_count_g; static struct list_head adapters_list_g; -wait_queue_head_t wait_q; +static wait_queue_head_t wait_q; static struct file_operations lsi_fops = { .open = mraid_mm_open, @@ -155,6 +156,17 @@ mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, return rval; } + /* + * Check if adapter can accept ioctl. We may have marked it offline + * if any previous kioc had timedout on this controller. + */ + if (!adp->quiescent) { + con_log(CL_ANN, (KERN_WARNING + "megaraid cmm: controller cannot accept cmds due to " + "earlier errors\n" )); + return -EFAULT; + } + /* * The following call will block till a kioc is available */ @@ -171,10 +183,15 @@ mraid_mm_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, kioc->done = ioctl_done; /* - * Issue the IOCTL to the low level driver + * Issue the IOCTL to the low level driver. After the IOCTL completes + * release the kioc if and only if it was _not_ timedout. If it was + * timedout, that means that resources are still with low level driver. */ if ((rval = lld_ioctl(adp, kioc))) { - mraid_mm_dealloc_kioc(adp, kioc); + + if (!kioc->timedout) + mraid_mm_dealloc_kioc(adp, kioc); + return rval; } @@ -581,6 +598,7 @@ mraid_mm_alloc_kioc(mraid_mmadp_t *adp) kioc->user_data = NULL; kioc->user_data_len = 0; kioc->user_pthru = NULL; + kioc->timedout = 0; return kioc; } @@ -597,23 +615,27 @@ mraid_mm_dealloc_kioc(mraid_mmadp_t *adp, uioc_t *kioc) mm_dmapool_t *pool; unsigned long flags; - pool = &adp->dma_pool_list[kioc->pool_index]; + if (kioc->pool_index != -1) { + pool = &adp->dma_pool_list[kioc->pool_index]; - /* This routine may be called in non-isr context also */ - spin_lock_irqsave(&pool->lock, flags); - - /* - * While attaching the dma buffer, if we didn't get the required - * buffer from the pool, we would have allocated it at the run time - * and set the free_buf flag. We must free that buffer. Otherwise, - * just mark that the buffer is not in use - */ - if (kioc->free_buf == 1) - pci_pool_free(pool->handle, kioc->buf_vaddr, kioc->buf_paddr); - else - pool->in_use = 0; + /* This routine may be called in non-isr context also */ + spin_lock_irqsave(&pool->lock, flags); - spin_unlock_irqrestore(&pool->lock, flags); + /* + * While attaching the dma buffer, if we didn't get the + * required buffer from the pool, we would have allocated + * it at the run time and set the free_buf flag. We must + * free that buffer. Otherwise, just mark that the buffer is + * not in use + */ + if (kioc->free_buf == 1) + pci_pool_free(pool->handle, kioc->buf_vaddr, + kioc->buf_paddr); + else + pool->in_use = 0; + + spin_unlock_irqrestore(&pool->lock, flags); + } /* Return the kioc to the free pool */ spin_lock_irqsave(&adp->kioc_pool_lock, flags); @@ -667,6 +689,14 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) del_timer_sync(tp); } + /* + * If the command had timedout, we mark the controller offline + * before returning + */ + if (kioc->timedout) { + adp->quiescent = 0; + } + return kioc->status; } @@ -679,6 +709,10 @@ lld_ioctl(mraid_mmadp_t *adp, uioc_t *kioc) static void ioctl_done(uioc_t *kioc) { + uint32_t adapno; + int iterator; + mraid_mmadp_t* adapter; + /* * When the kioc returns from driver, make sure it still doesn't * have ENODATA in status. Otherwise, driver will hang on wait_event @@ -691,7 +725,32 @@ ioctl_done(uioc_t *kioc) kioc->status = -EINVAL; } - wake_up(&wait_q); + /* + * Check if this kioc was timedout before. If so, nobody is waiting + * on this kioc. We don't have to wake up anybody. Instead, we just + * have to free the kioc + */ + if (kioc->timedout) { + iterator = 0; + adapter = NULL; + adapno = kioc->adapno; + + con_log(CL_ANN, ( KERN_WARNING "megaraid cmm: completed " + "ioctl that was timedout before\n")); + + list_for_each_entry(adapter, &adapters_list_g, list) { + if (iterator++ == adapno) break; + } + + kioc->timedout = 0; + + if (adapter) { + mraid_mm_dealloc_kioc( adapter, kioc ); + } + } + else { + wake_up(&wait_q); + } } @@ -706,6 +765,7 @@ lld_timedout(unsigned long ptr) uioc_t *kioc = (uioc_t *)ptr; kioc->status = -ETIME; + kioc->timedout = 1; con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n")); @@ -850,6 +910,7 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp) adapter->issue_uioc = lld_adp->issue_uioc; adapter->timeout = lld_adp->timeout; adapter->max_kioc = lld_adp->max_kioc; + adapter->quiescent = 1; /* * Allocate single blocks of memory for all required kiocs, @@ -947,6 +1008,40 @@ memalloc_error: return rval; } + +/** + * mraid_mm_adapter_app_handle - return the application handle for this adapter + * + * For the given driver data, locate the adadpter in our global list and + * return the corresponding handle, which is also used by applications to + * uniquely identify an adapter. + * + * @param unique_id : adapter unique identifier + * + * @return adapter handle if found in the list + * @return 0 if adapter could not be located, should never happen though + */ +uint32_t +mraid_mm_adapter_app_handle(uint32_t unique_id) +{ + mraid_mmadp_t *adapter; + mraid_mmadp_t *tmp; + int index = 0; + + list_for_each_entry_safe(adapter, tmp, &adapters_list_g, list) { + + if (adapter->unique_id == unique_id) { + + return MKADAP(index); + } + + index++; + } + + return 0; +} + + /** * mraid_mm_setup_dma_pools - Set up dma buffer pools per adapter * @@ -1120,9 +1215,7 @@ mraid_mm_init(void) INIT_LIST_HEAD(&adapters_list_g); -#ifdef CONFIG_COMPAT register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl); -#endif return 0; }