📄 megaraid.c
字号:
* Free a SCB structure * Note: We assume the scsi commands associated with this scb is not free yet. */static voidmega_free_scb(adapter_t *adapter, scb_t *scb){ switch( scb->dma_type ) { case MEGA_DMA_TYPE_NONE: break; case MEGA_SGLIST: scsi_dma_unmap(scb->cmd); break; default: break; } /* * Remove from the pending list */ list_del_init(&scb->list); /* Link the scb back into free list */ scb->state = SCB_FREE; scb->cmd = NULL; list_add(&scb->list, &adapter->free_list);}static int__mega_busywait_mbox (adapter_t *adapter){ volatile mbox_t *mbox = adapter->mbox; long counter; for (counter = 0; counter < 10000; counter++) { if (!mbox->m_in.busy) return 0; udelay(100); cond_resched(); } return -1; /* give up after 1 second */}/* * Copies data to SGLIST * Note: For 64 bit cards, we need a minimum of one SG element for read/write */static intmega_build_sglist(adapter_t *adapter, scb_t *scb, u32 *buf, u32 *len){ struct scatterlist *sg; Scsi_Cmnd *cmd; int sgcnt; int idx; cmd = scb->cmd; /* * Copy Scatter-Gather list info into controller structure. * * The number of sg elements returned must not exceed our limit */ sgcnt = scsi_dma_map(cmd); scb->dma_type = MEGA_SGLIST; BUG_ON(sgcnt > adapter->sglen || sgcnt < 0); *len = 0; if (scsi_sg_count(cmd) == 1 && !adapter->has_64bit_addr) { sg = scsi_sglist(cmd); scb->dma_h_bulkdata = sg_dma_address(sg); *buf = (u32)scb->dma_h_bulkdata; *len = sg_dma_len(sg); return 0; } scsi_for_each_sg(cmd, sg, sgcnt, idx) { if (adapter->has_64bit_addr) { scb->sgl64[idx].address = sg_dma_address(sg); *len += scb->sgl64[idx].length = sg_dma_len(sg); } else { scb->sgl[idx].address = sg_dma_address(sg); *len += scb->sgl[idx].length = sg_dma_len(sg); } } /* Reset pointer and length fields */ *buf = scb->sgl_dma_addr; /* Return count of SG requests */ return sgcnt;}/* * mega_8_to_40ld() * * takes all info in AdapterInquiry structure and puts it into ProductInfo and * Enquiry3 structures for later use */static voidmega_8_to_40ld(mraid_inquiry *inquiry, mega_inquiry3 *enquiry3, mega_product_info *product_info){ int i; product_info->max_commands = inquiry->adapter_info.max_commands; enquiry3->rebuild_rate = inquiry->adapter_info.rebuild_rate; product_info->nchannels = inquiry->adapter_info.nchannels; for (i = 0; i < 4; i++) { product_info->fw_version[i] = inquiry->adapter_info.fw_version[i]; product_info->bios_version[i] = inquiry->adapter_info.bios_version[i]; } enquiry3->cache_flush_interval = inquiry->adapter_info.cache_flush_interval; product_info->dram_size = inquiry->adapter_info.dram_size; enquiry3->num_ldrv = inquiry->logdrv_info.num_ldrv; for (i = 0; i < MAX_LOGICAL_DRIVES_8LD; i++) { enquiry3->ldrv_size[i] = inquiry->logdrv_info.ldrv_size[i]; enquiry3->ldrv_prop[i] = inquiry->logdrv_info.ldrv_prop[i]; enquiry3->ldrv_state[i] = inquiry->logdrv_info.ldrv_state[i]; } for (i = 0; i < (MAX_PHYSICAL_DRIVES); i++) enquiry3->pdrv_state[i] = inquiry->pdrv_info.pdrv_state[i];}static inline voidmega_free_sgl(adapter_t *adapter){ scb_t *scb; int i; for(i = 0; i < adapter->max_cmds; i++) { scb = &adapter->scb_list[i]; if( scb->sgl64 ) { pci_free_consistent(adapter->dev, sizeof(mega_sgl64) * adapter->sglen, scb->sgl64, scb->sgl_dma_addr); scb->sgl64 = NULL; } if( scb->pthru ) { pci_free_consistent(adapter->dev, sizeof(mega_passthru), scb->pthru, scb->pthru_dma_addr); scb->pthru = NULL; } if( scb->epthru ) { pci_free_consistent(adapter->dev, sizeof(mega_ext_passthru), scb->epthru, scb->epthru_dma_addr); scb->epthru = NULL; } }}/* * Get information about the card/driver */const char *megaraid_info(struct Scsi_Host *host){ static char buffer[512]; adapter_t *adapter; adapter = (adapter_t *)host->hostdata; sprintf (buffer, "LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns", adapter->fw_version, adapter->product_info.max_commands, adapter->host->max_id, adapter->host->max_channel, adapter->host->max_lun); return buffer;}/* * Abort a previous SCSI request. Only commands on the pending list can be * aborted. All the commands issued to the F/W must complete. */static intmegaraid_abort(Scsi_Cmnd *cmd){ adapter_t *adapter; int rval; adapter = (adapter_t *)cmd->device->host->hostdata; rval = megaraid_abort_and_reset(adapter, cmd, SCB_ABORT); /* * This is required here to complete any completed requests * to be communicated over to the mid layer. */ mega_rundoneq(adapter); return rval;}static intmegaraid_reset(struct scsi_cmnd *cmd){ adapter_t *adapter; megacmd_t mc; int rval; adapter = (adapter_t *)cmd->device->host->hostdata;#if MEGA_HAVE_CLUSTERING mc.cmd = MEGA_CLUSTER_CMD; mc.opcode = MEGA_RESET_RESERVATIONS; if( mega_internal_command(adapter, &mc, NULL) != 0 ) { printk(KERN_WARNING "megaraid: reservation reset failed.\n"); } else { printk(KERN_INFO "megaraid: reservation reset.\n"); }#endif spin_lock_irq(&adapter->lock); rval = megaraid_abort_and_reset(adapter, cmd, SCB_RESET); /* * This is required here to complete any completed requests * to be communicated over to the mid layer. */ mega_rundoneq(adapter); spin_unlock_irq(&adapter->lock); return rval;}/** * megaraid_abort_and_reset() * @adapter - megaraid soft state * @cmd - scsi command to be aborted or reset * @aor - abort or reset flag * * Try to locate the scsi command in the pending queue. If found and is not * issued to the controller, abort/reset it. Otherwise return failure */static intmegaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor){ struct list_head *pos, *next; scb_t *scb; printk(KERN_WARNING "megaraid: %s-%lx cmd=%x <c=%d t=%d l=%d>\n", (aor == SCB_ABORT)? "ABORTING":"RESET", cmd->serial_number, cmd->cmnd[0], cmd->device->channel, cmd->device->id, cmd->device->lun); if(list_empty(&adapter->pending_list)) return FALSE; list_for_each_safe(pos, next, &adapter->pending_list) { scb = list_entry(pos, scb_t, list); if (scb->cmd == cmd) { /* Found command */ scb->state |= aor; /* * Check if this command has firmare owenership. If * yes, we cannot reset this command. Whenever, f/w * completes this command, we will return appropriate * status from ISR. */ if( scb->state & SCB_ISSUED ) { printk(KERN_WARNING "megaraid: %s-%lx[%x], fw owner.\n", (aor==SCB_ABORT) ? "ABORTING":"RESET", cmd->serial_number, scb->idx); return FALSE; } else { /* * Not yet issued! Remove from the pending * list */ printk(KERN_WARNING "megaraid: %s-%lx[%x], driver owner.\n", (aor==SCB_ABORT) ? "ABORTING":"RESET", cmd->serial_number, scb->idx); mega_free_scb(adapter, scb); if( aor == SCB_ABORT ) { cmd->result = (DID_ABORT << 16); } else { cmd->result = (DID_RESET << 16); } list_add_tail(SCSI_LIST(cmd), &adapter->completed_list); return TRUE; } } } return FALSE;}static inline intmake_local_pdev(adapter_t *adapter, struct pci_dev **pdev){ *pdev = alloc_pci_dev(); if( *pdev == NULL ) return -1; memcpy(*pdev, adapter->dev, sizeof(struct pci_dev)); if( pci_set_dma_mask(*pdev, DMA_32BIT_MASK) != 0 ) { kfree(*pdev); return -1; } return 0;}static inline voidfree_local_pdev(struct pci_dev *pdev){ kfree(pdev);}/** * mega_allocate_inquiry() * @dma_handle - handle returned for dma address * @pdev - handle to pci device * * allocates memory for inquiry structure */static inline void *mega_allocate_inquiry(dma_addr_t *dma_handle, struct pci_dev *pdev){ return pci_alloc_consistent(pdev, sizeof(mega_inquiry3), dma_handle);}static inline voidmega_free_inquiry(void *inquiry, dma_addr_t dma_handle, struct pci_dev *pdev){ pci_free_consistent(pdev, sizeof(mega_inquiry3), inquiry, dma_handle);}#ifdef CONFIG_PROC_FS/* Following code handles /proc fs */#define CREATE_READ_PROC(string, func) create_proc_read_entry(string, \ S_IRUSR | S_IFREG, \ controller_proc_dir_entry, \ func, adapter)/** * mega_create_proc_entry() * @index - index in soft state array * @parent - parent node for this /proc entry * * Creates /proc entries for our controllers. */static voidmega_create_proc_entry(int index, struct proc_dir_entry *parent){ struct proc_dir_entry *controller_proc_dir_entry = NULL; u8 string[64] = { 0 }; adapter_t *adapter = hba_soft_state[index]; sprintf(string, "hba%d", adapter->host->host_no); controller_proc_dir_entry = adapter->controller_proc_dir_entry = proc_mkdir(string, parent); if(!controller_proc_dir_entry) { printk(KERN_WARNING "\nmegaraid: proc_mkdir failed\n"); return; } adapter->proc_read = CREATE_READ_PROC("config", proc_read_config); adapter->proc_stat = CREATE_READ_PROC("stat", proc_read_stat); adapter->proc_mbox = CREATE_READ_PROC("mailbox", proc_read_mbox);#if MEGA_HAVE_ENH_PROC adapter->proc_rr = CREATE_READ_PROC("rebuild-rate", proc_rebuild_rate); adapter->proc_battery = CREATE_READ_PROC("battery-status", proc_battery); /* * Display each physical drive on its channel */ adapter->proc_pdrvstat[0] = CREATE_READ_PROC("diskdrives-ch0", proc_pdrv_ch0); adapter->proc_pdrvstat[1] = CREATE_READ_PROC("diskdrives-ch1", proc_pdrv_ch1); adapter->proc_pdrvstat[2] = CREATE_READ_PROC("diskdrives-ch2", proc_pdrv_ch2); adapter->proc_pdrvstat[3] = CREATE_READ_PROC("diskdrives-ch3", proc_pdrv_ch3); /* * Display a set of up to 10 logical drive through each of following * /proc entries */ adapter->proc_rdrvstat[0] = CREATE_READ_PROC("raiddrives-0-9", proc_rdrv_10); adapter->proc_rdrvstat[1] = CREATE_READ_PROC("raiddrives-10-19", proc_rdrv_20); adapter->proc_rdrvstat[2] = CREATE_READ_PROC("raiddrives-20-29", proc_rdrv_30); adapter->proc_rdrvstat[3] = CREATE_READ_PROC("raiddrives-30-39", proc_rdrv_40);#endif}/** * proc_read_config() * @page - buffer to write the data in * @start - where the actual data has been written in page * @offset - same meaning as the read system call * @count - same meaning as the read system call * @eof - set if no more data needs to be returned * @data - pointer to our soft state * * Display configuration information about the controller. */static intproc_read_config(char *page, char **start, off_t offset, int count, int *eof, void *data){ adapter_t *adapter = (adapter_t *)data; int len = 0; len += sprintf(page+len, "%s", MEGARAID_VERSION); if(adapter->product_info.product_name[0]) len += sprintf(page+len, "%s\n", adapter->product_info.product_name); len += sprintf(page+len, "Controller Type: "); if( adapter->flag & BOARD_MEMMAP ) { len += sprintf(page+len, "438/466/467/471/493/518/520/531/532\n"); } else { len += sprintf(page+len, "418/428/434\n"); } if(adapter->flag & BOARD_40LD) { len += sprintf(page+len, "Controller Supports 40 Logical Drives\n"); } if(adapter->flag & BOARD_64BIT) { len += sprintf(page+len, "Controller capable of 64-bit memory addressing\n"); } if( adapter->has_64bit_addr ) { len += sprintf(page+len, "Controller using 64-bit memory addressing\n"); } else { len += sprintf(page+len, "Controller is not using 64-bit memory addressing\n"); } len += sprintf(page+len, "Base = %08lx, Irq = %d, ", adapter->base, adapter->host->irq); len += sprintf(page+len, "Logical Drives = %d, Channels = %d\n", adapter->numldrv, adapter->product_info.nchannels); len += sprintf(page+len, "Version =%s:%s, DRAM = %dMb\n", adapter->fw_version, adapter->bios_version, adapter->product_info.dram_size); len += sprintf(page+len, "Controller Queue Depth = %d, Driver Queue Depth = %d\n", adapter->product_info.max_commands, adapter->max_cmds); len += sprintf(page+len, "support_ext_cdb = %d\n", adapter->support_ext_cdb); len += sprintf(page+len, "support_random_del = %d\n", adapter->support_random_del); len += sprintf(page+len, "boot_ldrv_enabled = %d\n", adapter->boot_ldrv_enabled); len += sprintf(page+len, "boot_ldrv = %d\n", adapter->boot_ldrv); len += sprintf(page+len, "boot_pdrv_enabled = %d\n", adapter->boot_pdrv_enabled); len += sprintf(page+len, "boot_pdrv_ch = %d\n", adapter->boot_pdrv_ch); len += sprintf(page+len, "boot_pdrv_tgt = %d\n", adapter->boot_pdrv_tgt); len += sprintf(page+len, "quiescent = %d\n", atomic_read(&adapter->quiescent)); len += sprintf(page+len, "has_cluster = %d\n", adapter->has_cluster); len += sprintf(page+len, "\nModule Parameters:\n"); len += sprintf(page+len, "max_cmd_per_lun = %d\n", max_cmd_per_lun); len += sprintf(page+len, "max_sectors_per_io = %d\n", max_sectors_per_io); *eof = 1; return len;}/** * proc_read_stat() * @page - buffer to write the data in * @start - where the actual data has been written in page * @offset - same meaning as the read system call * @count - same meaning as the read system call * @eof - set if no more data needs to be returned * @data - pointer to our soft state * * Diaplay statistical information about the I/O activity. */static intproc_read_stat(char *page, char **start, off_t offset, int count, int *eof, void *data){ adapter_t *adapter;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -