@@ -11,6 +11,14 @@
#include <linux/delay.h>
#include <linux/bsg-lib.h>
+static void qla2xxx_free_fcport_work(struct work_struct *work)
+{
+ struct fc_port *fcport = container_of(work, typeof(*fcport),
+ free_work);
+
+ qla2x00_free_fcport(fcport);
+}
+
/* BSG support for ELS/CT pass through */
void
qla2x00_bsg_job_done(void *ptr, int res)
@@ -57,8 +65,16 @@ qla2x00_bsg_sp_free(void *ptr)
if (sp->type == SRB_CT_CMD ||
sp->type == SRB_FXIOCB_BCMD ||
- sp->type == SRB_ELS_CMD_HST)
+ sp->type == SRB_ELS_CMD_HST) {
+ if (ha->free_fcport) {
+ INIT_WORK(&sp->fcport->free_work,
+ qla2xxx_free_fcport_work);
+ queue_work(ha->free_fcport, &sp->fcport->free_work);
+ goto done;
+ }
kfree(sp->fcport);
+ }
+done:
qla2x00_rel_sp(sp);
}
@@ -4190,6 +4190,7 @@ struct qla_hw_data {
struct work_struct idc_state_handler;
struct work_struct nic_core_unrecoverable;
struct work_struct board_disable;
+ struct workqueue_struct *free_fcport;
struct mr_data_fx00 mr;
uint32_t chip_reset;
@@ -3196,6 +3196,12 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
host->max_cmd_len, host->max_channel, host->max_lun,
host->transportt, sht->vendor_id);
+ ha->free_fcport = create_workqueue("free_fcport");
+ if (!ha->free_fcport) {
+ ql_log(ql_log_info, base_vha, 0xee00,
+ "Failed to allocate workqueue ha->free_fcport\n");
+ }
+
INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn);
/* Set up the irqs */
@@ -3650,6 +3656,11 @@ qla2x00_destroy_deferred_work(struct qla_hw_data *ha)
ha->dpc_hp_wq = NULL;
}
+ if (ha->free_fcport) {
+ destroy_workqueue(ha->free_fcport);
+ ha->free_fcport = NULL;
+ }
+
/* Kill the kernel thread for this host */
if (ha->dpc_thread) {
struct task_struct *t = ha->dpc_thread;