diff options
Diffstat (limited to 'drivers/scsi/qla2xxx/qla_os.c')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 229 |
1 files changed, 133 insertions, 96 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 18baa5bf69c..a8658b1d284 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -29,8 +29,7 @@ static struct kmem_cache *srb_cachep; /* * Ioctl related information. */ -static int num_hosts; - +int num_hosts; int ql2xlogintimeout = 20; module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR); MODULE_PARM_DESC(ql2xlogintimeout, @@ -112,7 +111,7 @@ static int qla2x00_device_reset(scsi_qla_host_t *, fc_port_t *); static int qla2x00_change_queue_depth(struct scsi_device *, int); static int qla2x00_change_queue_type(struct scsi_device *, int); -static struct scsi_host_template qla2x00_driver_template = { +struct scsi_host_template qla2x00_driver_template = { .module = THIS_MODULE, .name = QLA2XXX_DRIVER_NAME, .queuecommand = qla2x00_queuecommand, @@ -143,7 +142,7 @@ static struct scsi_host_template qla2x00_driver_template = { .shost_attrs = qla2x00_host_attrs, }; -static struct scsi_host_template qla24xx_driver_template = { +struct scsi_host_template qla24xx_driver_template = { .module = THIS_MODULE, .name = QLA2XXX_DRIVER_NAME, .queuecommand = qla24xx_queuecommand, @@ -171,21 +170,21 @@ static struct scsi_host_template qla24xx_driver_template = { }; static struct scsi_transport_template *qla2xxx_transport_template = NULL; +struct scsi_transport_template *qla2xxx_transport_vport_template = NULL; /* TODO Convert to inlines * * Timer routines */ -#define WATCH_INTERVAL 1 /* number of seconds */ -static void qla2x00_timer(scsi_qla_host_t *); +void qla2x00_timer(scsi_qla_host_t *); -static __inline__ void qla2x00_start_timer(scsi_qla_host_t *, +__inline__ void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long); static __inline__ void qla2x00_restart_timer(scsi_qla_host_t *, unsigned long); -static __inline__ void qla2x00_stop_timer(scsi_qla_host_t *); +__inline__ void qla2x00_stop_timer(scsi_qla_host_t *); -static inline void +__inline__ void qla2x00_start_timer(scsi_qla_host_t *ha, void *func, unsigned long interval) { init_timer(&ha->timer); @@ -202,7 +201,7 @@ qla2x00_restart_timer(scsi_qla_host_t *ha, unsigned long interval) mod_timer(&ha->timer, jiffies + interval * HZ); } -static __inline__ void +__inline__ void qla2x00_stop_timer(scsi_qla_host_t *ha) { del_timer_sync(&ha->timer); @@ -213,8 +212,8 @@ static int qla2x00_do_dpc(void *data); static void qla2x00_rst_aen(scsi_qla_host_t *); -static uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); -static void qla2x00_mem_free(scsi_qla_host_t *ha); +uint8_t qla2x00_mem_alloc(scsi_qla_host_t *); +void qla2x00_mem_free(scsi_qla_host_t *ha); static int qla2x00_allocate_sp_pool( scsi_qla_host_t *ha); static void qla2x00_free_sp_pool(scsi_qla_host_t *ha); static void qla2x00_sp_free_dma(scsi_qla_host_t *, srb_t *); @@ -438,6 +437,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device)); srb_t *sp; int rval; + scsi_qla_host_t *pha = to_qla_parent(ha); rval = fc_remote_port_chkready(rport); if (rval) { @@ -453,7 +453,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) if (atomic_read(&fcport->state) != FCS_ONLINE) { if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD || - atomic_read(&ha->loop_state) == LOOP_DEAD) { + atomic_read(&pha->loop_state) == LOOP_DEAD) { cmd->result = DID_NO_CONNECT << 16; goto qc24_fail_command; } @@ -462,7 +462,7 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) spin_unlock_irq(ha->host->host_lock); - sp = qla2x00_get_new_sp(ha, fcport, cmd, done); + sp = qla2x00_get_new_sp(pha, fcport, cmd, done); if (!sp) goto qc24_host_busy_lock; @@ -475,8 +475,8 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) return 0; qc24_host_busy_free_sp: - qla2x00_sp_free_dma(ha, sp); - mempool_free(sp, ha->srb_mempool); + qla2x00_sp_free_dma(pha, sp); + mempool_free(sp, pha->srb_mempool); qc24_host_busy_lock: spin_lock_irq(ha->host->host_lock); @@ -548,16 +548,17 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *ha) { int return_status; unsigned long wait_online; + scsi_qla_host_t *pha = to_qla_parent(ha); wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ); - while (((test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) || - test_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags) || - test_bit(ISP_ABORT_RETRY, &ha->dpc_flags) || - ha->dpc_active) && time_before(jiffies, wait_online)) { + while (((test_bit(ISP_ABORT_NEEDED, &pha->dpc_flags)) || + test_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags) || + test_bit(ISP_ABORT_RETRY, &pha->dpc_flags) || + pha->dpc_active) && time_before(jiffies, wait_online)) { msleep(1000); } - if (ha->flags.online) + if (pha->flags.online) return_status = QLA_SUCCESS; else return_status = QLA_FUNCTION_FAILED; @@ -588,14 +589,15 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha) { int return_status = QLA_SUCCESS; unsigned long loop_timeout ; + scsi_qla_host_t *pha = to_qla_parent(ha); /* wait for 5 min at the max for loop to be ready */ loop_timeout = jiffies + (MAX_LOOP_TIMEOUT * HZ); - while ((!atomic_read(&ha->loop_down_timer) && - atomic_read(&ha->loop_state) == LOOP_DOWN) || - atomic_read(&ha->loop_state) != LOOP_READY) { - if (atomic_read(&ha->loop_state) == LOOP_DEAD) { + while ((!atomic_read(&pha->loop_down_timer) && + atomic_read(&pha->loop_state) == LOOP_DOWN) || + atomic_read(&pha->loop_state) != LOOP_READY) { + if (atomic_read(&pha->loop_state) == LOOP_DEAD) { return_status = QLA_FUNCTION_FAILED; break; } @@ -650,6 +652,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) unsigned long serial; unsigned long flags; int wait = 0; + scsi_qla_host_t *pha = to_qla_parent(ha); qla2x00_block_error_handler(cmd); @@ -663,9 +666,9 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) serial = cmd->serial_number; /* Check active list for command command. */ - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(&pha->hardware_lock, flags); for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) { - sp = ha->outstanding_cmds[i]; + sp = pha->outstanding_cmds[i]; if (sp == NULL) continue; @@ -677,7 +680,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) __func__, ha->host_no, sp, serial)); DEBUG3(qla2x00_print_scsi_cmd(cmd)); - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); if (ha->isp_ops.abort_command(ha, sp)) { DEBUG2(printk("%s(%ld): abort_command " "mbx failed.\n", __func__, ha->host_no)); @@ -686,11 +689,11 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) "mbx success.\n", __func__, ha->host_no)); wait = 1; } - spin_lock_irqsave(&ha->hardware_lock, flags); + spin_lock_irqsave(&pha->hardware_lock, flags); break; } - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); /* Wait for the command to be returned. */ if (wait) { @@ -731,6 +734,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) srb_t *sp; struct scsi_cmnd *cmd; unsigned long flags; + scsi_qla_host_t *pha = to_qla_parent(ha); status = 0; @@ -739,19 +743,20 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) * array */ for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { - spin_lock_irqsave(&ha->hardware_lock, flags); - sp = ha->outstanding_cmds[cnt]; + spin_lock_irqsave(&pha->hardware_lock, flags); + sp = pha->outstanding_cmds[cnt]; if (sp) { cmd = sp->cmd; - spin_unlock_irqrestore(&ha->hardware_lock, flags); - if (cmd->device->id == t) { + spin_unlock_irqrestore(&pha->hardware_lock, flags); + if (cmd->device->id == t && + ha->vp_idx == sp->ha->vp_idx) { if (!qla2x00_eh_wait_on_command(ha, cmd)) { status = 1; break; } } } else { - spin_unlock_irqrestore(&ha->hardware_lock, flags); + spin_unlock_irqrestore(&pha->hardware_lock, flags); } } return (status); @@ -782,14 +787,12 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; - int ret; + int ret = FAILED; unsigned int id, lun; unsigned long serial; qla2x00_block_error_handler(cmd); - ret = FAILED; - id = cmd->device->id; lun = cmd->device->lun; serial = cmd->serial_number; @@ -912,15 +915,14 @@ static int qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *pha = to_qla_parent(ha); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; - int ret; + int ret = FAILED; unsigned int id, lun; unsigned long serial; qla2x00_block_error_handler(cmd); - ret = FAILED; - id = cmd->device->id; lun = cmd->device->lun; serial = cmd->serial_number; @@ -944,7 +946,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) goto eh_bus_reset_done; /* Flush outstanding commands. */ - if (!qla2x00_eh_wait_for_pending_commands(ha)) + if (!qla2x00_eh_wait_for_pending_commands(pha)) ret = FAILED; eh_bus_reset_done: @@ -974,14 +976,13 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; - int ret; + int ret = FAILED; unsigned int id, lun; unsigned long serial; + scsi_qla_host_t *pha = to_qla_parent(ha); qla2x00_block_error_handler(cmd); - ret = FAILED; - id = cmd->device->id; lun = cmd->device->lun; serial = cmd->serial_number; @@ -1004,21 +1005,24 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) * while dpc is stuck for the mailbox to complete. */ qla2x00_wait_for_loop_ready(ha); - set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); - if (qla2x00_abort_isp(ha)) { - clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + set_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); + if (qla2x00_abort_isp(pha)) { + clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); /* failed. schedule dpc to try */ - set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + set_bit(ISP_ABORT_NEEDED, &pha->dpc_flags); if (qla2x00_wait_for_hba_online(ha) != QLA_SUCCESS) goto eh_host_reset_lock; } - clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + clear_bit(ABORT_ISP_ACTIVE, &pha->dpc_flags); /* Waiting for our command in done_queue to be returned to OS.*/ - if (qla2x00_eh_wait_for_pending_commands(ha)) + if (qla2x00_eh_wait_for_pending_commands(pha)) ret = SUCCESS; + if (ha->parent) + qla2x00_vp_abort_isp(ha); + eh_host_reset_lock: qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__, (ret == FAILED) ? "failed" : "succeded"); @@ -1435,6 +1439,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->host = host; ha->host_no = host->host_no; sprintf(ha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, ha->host_no); + ha->parent = NULL; /* Set ISP-type information. */ qla2x00_set_isp_flags(ha); @@ -1452,7 +1457,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->prev_topology = 0; ha->init_cb_size = sizeof(init_cb_t); - ha->mgmt_svr_loop_id = MANAGEMENT_SERVER; + ha->mgmt_svr_loop_id = MANAGEMENT_SERVER + ha->vp_idx; ha->link_data_rate = PORT_SPEED_UNKNOWN; ha->optrom_size = OPTROM_SIZE_2300; @@ -1524,8 +1529,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->request_q_length = REQUEST_ENTRY_CNT_24XX; ha->response_q_length = RESPONSE_ENTRY_CNT_2300; ha->last_loop_id = SNS_LAST_LOOP_ID_2300; - ha->init_cb_size = sizeof(struct init_cb_24xx); - ha->mgmt_svr_loop_id = 10; + ha->init_cb_size = sizeof(struct mid_init_cb_24xx); + ha->mgmt_svr_loop_id = 10 + ha->vp_idx; ha->isp_ops.pci_config = qla24xx_pci_config; ha->isp_ops.reset_chip = qla24xx_reset_chip; ha->isp_ops.chip_diag = qla24xx_chip_diag; @@ -1563,10 +1568,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) ha->instance = num_hosts; init_MUTEX(&ha->mbx_cmd_sem); + init_MUTEX(&ha->vport_sem); init_MUTEX_LOCKED(&ha->mbx_intr_sem); INIT_LIST_HEAD(&ha->list); INIT_LIST_HEAD(&ha->fcports); + INIT_LIST_HEAD(&ha->vp_list); + + set_bit(0, (unsigned long *) ha->vp_idx_map); qla2x00_config_dma_addressing(ha); if (qla2x00_mem_alloc(ha)) { @@ -1789,7 +1798,8 @@ qla2x00_schedule_rport_del(struct scsi_qla_host *ha, fc_port_t *fcport, void qla2x00_mark_device_lost(scsi_qla_host_t *ha, fc_port_t *fcport, int do_login, int defer) { - if (atomic_read(&fcport->state) == FCS_ONLINE) + if (atomic_read(&fcport->state) == FCS_ONLINE && + ha->vp_idx == fcport->vp_idx) qla2x00_schedule_rport_del(ha, fcport, defer); /* @@ -1840,19 +1850,23 @@ void qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) { fc_port_t *fcport; + scsi_qla_host_t *pha = to_qla_parent(ha); - list_for_each_entry(fcport, &ha->fcports, list) { - if (fcport->port_type != FCT_TARGET) + list_for_each_entry(fcport, &pha->fcports, list) { + if (ha->vp_idx != 0 && ha->vp_idx != fcport->vp_idx) continue; - /* * No point in marking the device as lost, if the device is * already DEAD. */ if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD) continue; - if (atomic_read(&fcport->state) == FCS_ONLINE) - qla2x00_schedule_rport_del(ha, fcport, defer); + if (atomic_read(&fcport->state) == FCS_ONLINE) { + if (defer) + qla2x00_schedule_rport_del(ha, fcport, defer); + else if (ha->vp_idx == fcport->vp_idx) + qla2x00_schedule_rport_del(ha, fcport, defer); + } atomic_set(&fcport->state, FCS_DEVICE_LOST); } @@ -1868,7 +1882,7 @@ qla2x00_mark_all_devices_lost(scsi_qla_host_t *ha, int defer) * 0 = success. * 1 = failure. */ -static uint8_t +uint8_t qla2x00_mem_alloc(scsi_qla_host_t *ha) { char name[16]; @@ -1920,33 +1934,33 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) continue; } - snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, - ha->host_no); - ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, - DMA_POOL_SIZE, 8, 0); - if (ha->s_dma_pool == NULL) { + /* get consistent memory allocated for init control block */ + ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, + ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); + if (ha->init_cb == NULL) { qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - s_dma_pool\n"); + "Memory Allocation failed - init_cb\n"); qla2x00_mem_free(ha); msleep(100); continue; } + memset(ha->init_cb, 0, ha->init_cb_size); - /* get consistent memory allocated for init control block */ - ha->init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, - &ha->init_cb_dma); - if (ha->init_cb == NULL) { + snprintf(name, sizeof(name), "%s_%ld", QLA2XXX_DRIVER_NAME, + ha->host_no); + ha->s_dma_pool = dma_pool_create(name, &ha->pdev->dev, + DMA_POOL_SIZE, 8, 0); + if (ha->s_dma_pool == NULL) { qla_printk(KERN_WARNING, ha, - "Memory Allocation failed - init_cb\n"); + "Memory Allocation failed - s_dma_pool\n"); qla2x00_mem_free(ha); msleep(100); continue; } - memset(ha->init_cb, 0, ha->init_cb_size); if (qla2x00_allocate_sp_pool(ha)) { qla_printk(KERN_WARNING, ha, @@ -2052,7 +2066,7 @@ qla2x00_mem_alloc(scsi_qla_host_t *ha) * Input: * ha = adapter block pointer. */ -static void +void qla2x00_mem_free(scsi_qla_host_t *ha) { struct list_head *fcpl, *fcptemp; @@ -2088,12 +2102,13 @@ qla2x00_mem_free(scsi_qla_host_t *ha) if (ha->ms_iocb) dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); - if (ha->init_cb) - dma_pool_free(ha->s_dma_pool, ha->init_cb, ha->init_cb_dma); - if (ha->s_dma_pool) dma_pool_destroy(ha->s_dma_pool); + if (ha->init_cb) + dma_free_coherent(&ha->pdev->dev, ha->init_cb_size, + ha->init_cb, ha->init_cb_dma); + if (ha->gid_list) dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list, ha->gid_list_dma); @@ -2199,6 +2214,7 @@ qla2x00_free_sp_pool( scsi_qla_host_t *ha) static int qla2x00_do_dpc(void *data) { + int rval; scsi_qla_host_t *ha; fc_port_t *fcport; uint8_t status; @@ -2347,7 +2363,7 @@ qla2x00_do_dpc(void *data) if (!(test_and_set_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags))) { - qla2x00_loop_resync(ha); + rval = qla2x00_loop_resync(ha); clear_bit(LOOP_RESYNC_ACTIVE, &ha->dpc_flags); } @@ -2374,6 +2390,8 @@ qla2x00_do_dpc(void *data) if (test_and_clear_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags)) ha->isp_ops.beacon_blink(ha); + qla2x00_do_dpc_all_vps(ha); + ha->dpc_active = 0; } /* End of while(1) */ @@ -2452,7 +2470,7 @@ qla2x00_sp_compl(scsi_qla_host_t *ha, srb_t *sp) * * Context: Interrupt ***************************************************************************/ -static void +void qla2x00_timer(scsi_qla_host_t *ha) { unsigned long cpu_flags = 0; @@ -2461,6 +2479,7 @@ qla2x00_timer(scsi_qla_host_t *ha) int index; srb_t *sp; int t; + scsi_qla_host_t *pha = to_qla_parent(ha); /* * Ports - Port down timer. @@ -2506,23 +2525,29 @@ qla2x00_timer(scsi_qla_host_t *ha) atomic_set(&ha->loop_state, LOOP_DEAD); /* Schedule an ISP abort to return any tape commands. */ - spin_lock_irqsave(&ha->hardware_lock, cpu_flags); - for (index = 1; index < MAX_OUTSTANDING_COMMANDS; - index++) { - fc_port_t *sfcp; + /* NPIV - scan physical port only */ + if (!ha->parent) { + spin_lock_irqsave(&ha->hardware_lock, + cpu_flags); + for (index = 1; + index < MAX_OUTSTANDING_COMMANDS; + index++) { + fc_port_t *sfcp; + + sp = ha->outstanding_cmds[index]; + if (!sp) + continue; + sfcp = sp->fcport; + if (!(sfcp->flags & FCF_TAPE_PRESENT)) + continue; - sp = ha->outstanding_cmds[index]; - if (!sp) - continue; - sfcp = sp->fcport; - if (!(sfcp->flags & FCF_TAPE_PRESENT)) - continue; - - set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); - break; + set_bit(ISP_ABORT_NEEDED, + &ha->dpc_flags); + break; + } + spin_unlock_irqrestore(&ha->hardware_lock, + cpu_flags); } - spin_unlock_irqrestore(&ha->hardware_lock, cpu_flags); - set_bit(ABORT_QUEUES_NEEDED, &ha->dpc_flags); start_dpc++; } @@ -2566,8 +2591,9 @@ qla2x00_timer(scsi_qla_host_t *ha) test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags) || test_bit(RESET_MARKER_NEEDED, &ha->dpc_flags) || test_bit(BEACON_BLINK_NEEDED, &ha->dpc_flags) || + test_bit(VP_DPC_NEEDED, &ha->dpc_flags) || test_bit(RELOGIN_NEEDED, &ha->dpc_flags))) - qla2xxx_wake_dpc(ha); + qla2xxx_wake_dpc(pha); qla2x00_restart_timer(ha, WATCH_INTERVAL); } @@ -2711,14 +2737,24 @@ qla2x00_module_init(void) qla2xxx_transport_template = fc_attach_transport(&qla2xxx_transport_functions); - if (!qla2xxx_transport_template) + if (!qla2xxx_transport_template) { + kmem_cache_destroy(srb_cachep); + return -ENODEV; + } + qla2xxx_transport_vport_template = + fc_attach_transport(&qla2xxx_transport_vport_functions); + if (!qla2xxx_transport_vport_template) { + kmem_cache_destroy(srb_cachep); + fc_release_transport(qla2xxx_transport_template); return -ENODEV; + } printk(KERN_INFO "QLogic Fibre Channel HBA Driver\n"); ret = pci_register_driver(&qla2xxx_pci_driver); if (ret) { kmem_cache_destroy(srb_cachep); fc_release_transport(qla2xxx_transport_template); + fc_release_transport(qla2xxx_transport_vport_template); } return ret; } @@ -2733,6 +2769,7 @@ qla2x00_module_exit(void) qla2x00_release_firmware(); kmem_cache_destroy(srb_cachep); fc_release_transport(qla2xxx_transport_template); + fc_release_transport(qla2xxx_transport_vport_template); } module_init(qla2x00_module_init); |