enum iscsi_param param, char *buf);
static int qla4xxx_host_get_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf);
-static int qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data,
- int count);
+static int qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data,
+ uint32_t len);
static int qla4xxx_get_iface_param(struct iscsi_iface *iface,
enum iscsi_param_type param_type,
int param, char *buf);
}
case ISCSI_PARAM:
switch (param) {
+ case ISCSI_PARAM_PERSISTENT_ADDRESS:
+ case ISCSI_PARAM_PERSISTENT_PORT:
case ISCSI_PARAM_CONN_ADDRESS:
case ISCSI_PARAM_CONN_PORT:
case ISCSI_PARAM_TARGET_NAME:
qla4xxx_destroy_ipv6_iface(ha);
}
break;
- case ISCSI_NET_PARAM_VLAN_ID:
+ case ISCSI_NET_PARAM_VLAN_TAG:
if (iface_param->len != sizeof(init_fw_cb->ipv6_vlan_tag))
break;
init_fw_cb->ipv6_vlan_tag =
qla4xxx_destroy_ipv4_iface(ha);
}
break;
- case ISCSI_NET_PARAM_VLAN_ID:
+ case ISCSI_NET_PARAM_VLAN_TAG:
if (iface_param->len != sizeof(init_fw_cb->ipv4_vlan_tag))
break;
init_fw_cb->ipv4_vlan_tag =
}
static int
-qla4xxx_iface_set_param(struct Scsi_Host *shost, char *data, int count)
+qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
{
struct scsi_qla_host *ha = to_qla_host(shost);
int rval = 0;
dma_addr_t init_fw_cb_dma;
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
- uint32_t total_param_count;
- uint32_t length;
+ uint32_t rem = len;
+ struct nlattr *attr;
init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
sizeof(struct addr_ctrl_blk),
goto exit_init_fw_cb;
}
- total_param_count = count;
- iface_param = (struct iscsi_iface_param_info *)data;
-
- for ( ; total_param_count != 0; total_param_count--) {
- length = iface_param->len;
+ nla_for_each_attr(attr, data, len, rem) {
+ iface_param = nla_data(attr);
if (iface_param->param_type != ISCSI_NET_PARAM)
continue;
ql4_printk(KERN_ERR, ha, "Invalid iface type\n");
break;
}
-
- iface_param = (struct iscsi_iface_param_info *)
- ((uint8_t *)iface_param +
- sizeof(struct iscsi_iface_param_info) + length);
}
init_fw_cb->cookie = cpu_to_le32(0x11BEAD5A);
qla_ep = ep->dd_data;
dst_addr = (struct sockaddr *)&qla_ep->dst_addr;
ha = to_qla_host(qla_ep->host);
+
get_ddb_index:
ddb_index = find_first_zero_bit(ha->ddb_idx_map, MAX_DDB_ENTRIES);
ddb_entry = sess->dd_data;
ha = ddb_entry->ha;
+ qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
+
spin_lock_irqsave(&ha->hardware_lock, flags);
qla4xxx_free_ddb(ha, ddb_entry);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
*/
if (mbx_sts)
if (ddb_entry->fw_ddb_device_state ==
- DDB_DS_SESSION_ACTIVE)
+ DDB_DS_SESSION_ACTIVE) {
+ iscsi_conn_start(ddb_entry->conn);
+ iscsi_conn_login_event(ddb_entry->conn,
+ ISCSI_CONN_STATE_LOGGED_IN);
goto exit_set_param;
+ }
ql4_printk(KERN_ERR, ha, "%s: Failed set param for index[%d]\n",
__func__, ddb_entry->fw_ddb_index);
goto exit_conn_start;
}
- ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
+ if (ddb_entry->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE)
+ ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
+
+ DEBUG2(printk(KERN_INFO "%s: DDB state [%d]\n", __func__,
+ ddb_entry->fw_ddb_device_state));
exit_set_param:
- iscsi_conn_start(cls_conn);
ret = 0;
exit_conn_start:
options = LOGOUT_OPTION_CLOSE_SESSION;
if (qla4xxx_session_logout_ddb(ha, ddb_entry, options) == QLA_ERROR)
ql4_printk(KERN_ERR, ha, "%s: Logout failed\n", __func__);
- else
- qla4xxx_clear_ddb_entry(ha, ddb_entry->fw_ddb_index);
-
- /*
- * Clear the DDB bit so that next login can use the bit
- * if FW is not clearing the DDB entry then set DDB will fail anyways
- */
- clear_bit(ddb_entry->fw_ddb_index, ha->ddb_idx_map);
}
static void qla4xxx_task_work(struct work_struct *wdata)
DEBUG2(ql4_printk(KERN_INFO, ha, "%s: MaxRecvLen %u, iscsi hrd %d\n",
__func__, task->conn->max_recv_dlength, hdr_len));
- task_data->resp_len = task->conn->max_recv_dlength;
+ task_data->resp_len = task->conn->max_recv_dlength + hdr_len;
task_data->resp_buffer = dma_alloc_coherent(&ha->pdev->dev,
task_data->resp_len,
&task_data->resp_dma,
if (!task_data->resp_buffer)
goto exit_alloc_pdu;
+ task_data->req_len = task->data_count + hdr_len;
task_data->req_buffer = dma_alloc_coherent(&ha->pdev->dev,
- task->data_count + hdr_len,
+ task_data->req_len,
&task_data->req_dma,
GFP_ATOMIC);
if (!task_data->req_buffer)
task_data->resp_buffer, task_data->resp_dma);
if (task_data->req_buffer)
- dma_free_coherent(&ha->pdev->dev, task->data_count + hdr_len,
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
task_data->req_buffer, task_data->req_dma);
return -ENOMEM;
}
dma_free_coherent(&ha->pdev->dev, task_data->resp_len,
task_data->resp_buffer, task_data->resp_dma);
- dma_free_coherent(&ha->pdev->dev, task->data_count + hdr_len,
+ dma_free_coherent(&ha->pdev->dev, task_data->req_len,
task_data->req_buffer, task_data->req_dma);
return;
}
func_num = PCI_FUNC(ha->pdev->devfn);
- DEBUG2(ql4_printk(KERN_INFO, ha,
- "%s: Get FW boot info for 0x%x func %d\n", __func__,
- (is_qla4032(ha) ? PCI_DEVICE_ID_QLOGIC_ISP4032 :
- PCI_DEVICE_ID_QLOGIC_ISP8022), func_num));
+ ql4_printk(KERN_INFO, ha, "%s: Get FW boot info for 0x%x func %d\n",
+ __func__, ha->pdev->device, func_num);
- if (is_qla4032(ha)) {
+ if (is_qla40XX(ha)) {
if (func_num == 1) {
addr = NVRAM_PORT0_BOOT_MODE;
pri_addr = NVRAM_PORT0_BOOT_PRI_TGT;
val = rd_nvram_byte(ha, pri_addr);
if (val & BIT_7)
ddb_index[0] = (val & 0x7f);
- else
- ddb_index[0] = 0;
/* get secondary valid target index */
val = rd_nvram_byte(ha, sec_addr);
if (val & BIT_7)
ddb_index[1] = (val & 0x7f);
- else
- ddb_index[1] = 1;
} else if (is_qla8022(ha)) {
buf = dma_alloc_coherent(&ha->pdev->dev, size,
/* get primary valid target index */
if (buf[2] & BIT_7)
ddb_index[0] = buf[2] & 0x7f;
- else
- ddb_index[0] = 0;
/* get secondary valid target index */
if (buf[11] & BIT_7)
ddb_index[1] = buf[11] & 0x7f;
- else
- ddb_index[1] = 1;
-
} else {
ret = QLA_ERROR;
goto exit_boot_info;
return ret;
}
+/**
+ * qla4xxx_get_bidi_chap - Get a BIDI CHAP user and password
+ * @ha: pointer to adapter structure
+ * @username: CHAP username to be returned
+ * @password: CHAP password to be returned
+ *
+ * If a boot entry has BIDI CHAP enabled then we need to set the BIDI CHAP
+ * user and password in the sysfs entry in /sys/firmware/iscsi_boot#/.
+ * So from the CHAP cache find the first BIDI CHAP entry and set it
+ * to the boot record in sysfs.
+ **/
+static int qla4xxx_get_bidi_chap(struct scsi_qla_host *ha, char *username,
+ char *password)
+{
+ int i, ret = -EINVAL;
+ int max_chap_entries = 0;
+ struct ql4_chap_table *chap_table;
+
+ if (is_qla8022(ha))
+ max_chap_entries = (ha->hw.flt_chap_size / 2) /
+ sizeof(struct ql4_chap_table);
+ else
+ max_chap_entries = MAX_CHAP_ENTRIES_40XX;
+
+ if (!ha->chap_list) {
+ ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
+ return ret;
+ }
+
+ mutex_lock(&ha->chap_sem);
+ for (i = 0; i < max_chap_entries; i++) {
+ chap_table = (struct ql4_chap_table *)ha->chap_list + i;
+ if (chap_table->cookie !=
+ __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
+ continue;
+ }
+
+ if (chap_table->flags & BIT_7) /* local */
+ continue;
+
+ if (!(chap_table->flags & BIT_6)) /* Not BIDI */
+ continue;
+
+ strncpy(password, chap_table->secret, QL4_CHAP_MAX_SECRET_LEN);
+ strncpy(username, chap_table->name, QL4_CHAP_MAX_NAME_LEN);
+ ret = 0;
+ break;
+ }
+ mutex_unlock(&ha->chap_sem);
+
+ return ret;
+}
+
+
static int qla4xxx_get_boot_target(struct scsi_qla_host *ha,
struct ql4_boot_session_info *boot_sess,
uint16_t ddb_index)
DEBUG2(ql4_printk(KERN_INFO, ha, "Setting BIDI chap\n"));
- ret = qla4xxx_get_chap(ha, (char *)&boot_conn->chap.
- intr_chap_name,
- (char *)&boot_conn->chap.intr_secret,
- (idx + 1));
+ ret = qla4xxx_get_bidi_chap(ha,
+ (char *)&boot_conn->chap.intr_chap_name,
+ (char *)&boot_conn->chap.intr_secret);
+
if (ret) {
ql4_printk(KERN_ERR, ha, "Failed to set BIDI chap\n");
ret = QLA_ERROR;
static int qla4xxx_get_boot_info(struct scsi_qla_host *ha)
{
uint16_t ddb_index[2];
- int ret = QLA_SUCCESS;
+ int ret = QLA_ERROR;
+ int rval;
memset(ddb_index, 0, sizeof(ddb_index));
+ ddb_index[0] = 0xffff;
+ ddb_index[1] = 0xffff;
ret = get_fw_boot_info(ha, ddb_index);
if (ret != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_ERR, ha,
return ret;
}
- ret = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
+ if (ddb_index[0] == 0xffff)
+ goto sec_target;
+
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_pri_sess),
ddb_index[0]);
- if (ret != QLA_SUCCESS) {
+ if (rval != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
"primary target\n", __func__));
- }
+ } else
+ ret = QLA_SUCCESS;
+
+sec_target:
+ if (ddb_index[1] == 0xffff)
+ goto exit_get_boot_info;
- ret = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
+ rval = qla4xxx_get_boot_target(ha, &(ha->boot_tgt.boot_sec_sess),
ddb_index[1]);
- if (ret != QLA_SUCCESS) {
+ if (rval != QLA_SUCCESS) {
DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Failed to get "
"secondary target\n", __func__));
- }
+ } else
+ ret = QLA_SUCCESS;
+
+exit_get_boot_info:
return ret;
}