* 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
*/
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,
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
*/
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;
}
kioc->user_data = NULL;
kioc->user_data_len = 0;
kioc->user_pthru = NULL;
+ kioc->timedout = 0;
return 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);
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;
}
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
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);
+ }
}
uioc_t *kioc = (uioc_t *)ptr;
kioc->status = -ETIME;
+ kioc->timedout = 1;
con_log(CL_ANN, (KERN_WARNING "megaraid cmm: ioctl timed out\n"));
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,
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
*
INIT_LIST_HEAD(&adapters_list_g);
-#ifdef CONFIG_COMPAT
register_ioctl32_conversion(MEGAIOCCMD, mraid_mm_compat_ioctl);
-#endif
return 0;
}