diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_def.h | 21 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_fw.h | 20 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_glbl.h | 5 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 5 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_iocb.c | 92 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_isr.c | 72 | ||||
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_os.c | 113 |
7 files changed, 328 insertions, 0 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index f91808ce572e..776714d2d70d 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h | |||
@@ -221,6 +221,15 @@ struct srb { | |||
221 | uint16_t reserved2; | 221 | uint16_t reserved2; |
222 | }; | 222 | }; |
223 | 223 | ||
224 | /* Mailbox request block structure */ | ||
225 | struct mrb { | ||
226 | struct scsi_qla_host *ha; | ||
227 | struct mbox_cmd_iocb *mbox; | ||
228 | uint32_t mbox_cmd; | ||
229 | uint16_t iocb_cnt; /* Number of used iocbs */ | ||
230 | uint32_t pid; | ||
231 | }; | ||
232 | |||
224 | /* | 233 | /* |
225 | * Asynchronous Event Queue structure | 234 | * Asynchronous Event Queue structure |
226 | */ | 235 | */ |
@@ -303,6 +312,7 @@ struct ql4_tuple_ddb { | |||
303 | 312 | ||
304 | enum qla4_work_type { | 313 | enum qla4_work_type { |
305 | QLA4_EVENT_AEN, | 314 | QLA4_EVENT_AEN, |
315 | QLA4_EVENT_PING_STATUS, | ||
306 | }; | 316 | }; |
307 | 317 | ||
308 | struct qla4_work_evt { | 318 | struct qla4_work_evt { |
@@ -314,6 +324,12 @@ struct qla4_work_evt { | |||
314 | uint32_t data_size; | 324 | uint32_t data_size; |
315 | uint8_t data[0]; | 325 | uint8_t data[0]; |
316 | } aen; | 326 | } aen; |
327 | struct { | ||
328 | uint32_t status; | ||
329 | uint32_t pid; | ||
330 | uint32_t data_size; | ||
331 | uint8_t data[0]; | ||
332 | } ping; | ||
317 | } u; | 333 | } u; |
318 | }; | 334 | }; |
319 | 335 | ||
@@ -690,6 +706,11 @@ struct scsi_qla_host { | |||
690 | /* event work list */ | 706 | /* event work list */ |
691 | struct list_head work_list; | 707 | struct list_head work_list; |
692 | spinlock_t work_lock; | 708 | spinlock_t work_lock; |
709 | |||
710 | /* mbox iocb */ | ||
711 | #define MAX_MRB 128 | ||
712 | struct mrb *active_mrb_array[MAX_MRB]; | ||
713 | uint32_t mrb_index; | ||
693 | }; | 714 | }; |
694 | 715 | ||
695 | struct ql4_task_data { | 716 | struct ql4_task_data { |
diff --git a/drivers/scsi/qla4xxx/ql4_fw.h b/drivers/scsi/qla4xxx/ql4_fw.h index 5f82b5decd0f..210cd1d64475 100644 --- a/drivers/scsi/qla4xxx/ql4_fw.h +++ b/drivers/scsi/qla4xxx/ql4_fw.h | |||
@@ -331,6 +331,10 @@ struct qla_flt_region { | |||
331 | /* Mailbox command definitions */ | 331 | /* Mailbox command definitions */ |
332 | #define MBOX_CMD_ABOUT_FW 0x0009 | 332 | #define MBOX_CMD_ABOUT_FW 0x0009 |
333 | #define MBOX_CMD_PING 0x000B | 333 | #define MBOX_CMD_PING 0x000B |
334 | #define PING_IPV6_PROTOCOL_ENABLE 0x1 | ||
335 | #define PING_IPV6_LINKLOCAL_ADDR 0x4 | ||
336 | #define PING_IPV6_ADDR0 0x8 | ||
337 | #define PING_IPV6_ADDR1 0xC | ||
334 | #define MBOX_CMD_ENABLE_INTRS 0x0010 | 338 | #define MBOX_CMD_ENABLE_INTRS 0x0010 |
335 | #define INTR_DISABLE 0 | 339 | #define INTR_DISABLE 0 |
336 | #define INTR_ENABLE 1 | 340 | #define INTR_ENABLE 1 |
@@ -922,6 +926,8 @@ struct qla4_header { | |||
922 | #define ET_CMND_T3 0x19 | 926 | #define ET_CMND_T3 0x19 |
923 | #define ET_PASSTHRU0 0x3A | 927 | #define ET_PASSTHRU0 0x3A |
924 | #define ET_PASSTHRU_STATUS 0x3C | 928 | #define ET_PASSTHRU_STATUS 0x3C |
929 | #define ET_MBOX_CMD 0x38 | ||
930 | #define ET_MBOX_STATUS 0x39 | ||
925 | 931 | ||
926 | uint8_t entryStatus; | 932 | uint8_t entryStatus; |
927 | uint8_t systemDefined; | 933 | uint8_t systemDefined; |
@@ -1122,6 +1128,20 @@ struct passthru_status { | |||
1122 | uint8_t res4[16]; /* 30-3F */ | 1128 | uint8_t res4[16]; /* 30-3F */ |
1123 | }; | 1129 | }; |
1124 | 1130 | ||
1131 | struct mbox_cmd_iocb { | ||
1132 | struct qla4_header hdr; /* 00-03 */ | ||
1133 | uint32_t handle; /* 04-07 */ | ||
1134 | uint32_t in_mbox[8]; /* 08-25 */ | ||
1135 | uint32_t res1[6]; /* 26-3F */ | ||
1136 | }; | ||
1137 | |||
1138 | struct mbox_status_iocb { | ||
1139 | struct qla4_header hdr; /* 00-03 */ | ||
1140 | uint32_t handle; /* 04-07 */ | ||
1141 | uint32_t out_mbox[8]; /* 08-25 */ | ||
1142 | uint32_t res1[6]; /* 26-3F */ | ||
1143 | }; | ||
1144 | |||
1125 | /* | 1145 | /* |
1126 | * ISP queue - response queue entry definition. | 1146 | * ISP queue - response queue entry definition. |
1127 | */ | 1147 | */ |
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 34cf851978e9..954ba9188256 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h | |||
@@ -183,6 +183,11 @@ int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
183 | void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); | 183 | void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset); |
184 | int qla4xxx_post_aen_work(struct scsi_qla_host *ha, uint32_t aen_code, | 184 | int qla4xxx_post_aen_work(struct scsi_qla_host *ha, uint32_t aen_code, |
185 | uint32_t data_size, uint8_t *data); | 185 | uint32_t data_size, uint8_t *data); |
186 | int qla4xxx_ping_iocb(struct scsi_qla_host *ha, uint32_t options, | ||
187 | uint32_t payload_size, uint32_t pid, uint8_t *ipaddr); | ||
188 | int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha, | ||
189 | uint32_t status, uint32_t pid, | ||
190 | uint32_t data_size, uint8_t *data); | ||
186 | 191 | ||
187 | /* BSG Functions */ | 192 | /* BSG Functions */ |
188 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); | 193 | int qla4xxx_bsg_request(struct bsg_job *bsg_job); |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 90614f38b55d..90ee5d8fa731 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -86,6 +86,7 @@ static void qla4xxx_init_response_q_entries(struct scsi_qla_host *ha) | |||
86 | int qla4xxx_init_rings(struct scsi_qla_host *ha) | 86 | int qla4xxx_init_rings(struct scsi_qla_host *ha) |
87 | { | 87 | { |
88 | unsigned long flags = 0; | 88 | unsigned long flags = 0; |
89 | int i; | ||
89 | 90 | ||
90 | /* Initialize request queue. */ | 91 | /* Initialize request queue. */ |
91 | spin_lock_irqsave(&ha->hardware_lock, flags); | 92 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -125,6 +126,10 @@ int qla4xxx_init_rings(struct scsi_qla_host *ha) | |||
125 | 126 | ||
126 | qla4xxx_init_response_q_entries(ha); | 127 | qla4xxx_init_response_q_entries(ha); |
127 | 128 | ||
129 | /* Initialize mabilbox active array */ | ||
130 | for (i = 0; i < MAX_MRB; i++) | ||
131 | ha->active_mrb_array[i] = NULL; | ||
132 | |||
128 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 133 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
129 | 134 | ||
130 | return QLA_SUCCESS; | 135 | return QLA_SUCCESS; |
diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index 410669351906..c70651ddaf8b 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c | |||
@@ -445,3 +445,95 @@ queuing_error: | |||
445 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 445 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
446 | return ret; | 446 | return ret; |
447 | } | 447 | } |
448 | |||
449 | static struct mrb *qla4xxx_get_new_mrb(struct scsi_qla_host *ha) | ||
450 | { | ||
451 | struct mrb *mrb; | ||
452 | |||
453 | mrb = kzalloc(sizeof(*mrb), GFP_KERNEL); | ||
454 | if (!mrb) | ||
455 | return mrb; | ||
456 | |||
457 | mrb->ha = ha; | ||
458 | return mrb; | ||
459 | } | ||
460 | |||
461 | int qla4xxx_send_mbox_iocb(struct scsi_qla_host *ha, struct mrb *mrb, | ||
462 | uint32_t *in_mbox) | ||
463 | { | ||
464 | int rval = QLA_SUCCESS; | ||
465 | uint32_t i; | ||
466 | unsigned long flags; | ||
467 | uint32_t index = 0; | ||
468 | |||
469 | /* Acquire hardware specific lock */ | ||
470 | spin_lock_irqsave(&ha->hardware_lock, flags); | ||
471 | |||
472 | /* Get pointer to the queue entry for the marker */ | ||
473 | rval = qla4xxx_get_req_pkt(ha, (struct queue_entry **) &(mrb->mbox)); | ||
474 | if (rval != QLA_SUCCESS) | ||
475 | goto exit_mbox_iocb; | ||
476 | |||
477 | index = ha->mrb_index; | ||
478 | /* get valid mrb index*/ | ||
479 | for (i = 0; i < MAX_MRB; i++) { | ||
480 | index++; | ||
481 | if (index == MAX_MRB) | ||
482 | index = 1; | ||
483 | if (ha->active_mrb_array[index] == NULL) { | ||
484 | ha->mrb_index = index; | ||
485 | break; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | mrb->iocb_cnt = 1; | ||
490 | ha->active_mrb_array[index] = mrb; | ||
491 | mrb->mbox->handle = index; | ||
492 | mrb->mbox->hdr.entryType = ET_MBOX_CMD; | ||
493 | mrb->mbox->hdr.entryCount = mrb->iocb_cnt; | ||
494 | memcpy(mrb->mbox->in_mbox, in_mbox, 32); | ||
495 | mrb->mbox_cmd = in_mbox[0]; | ||
496 | wmb(); | ||
497 | |||
498 | ha->isp_ops->queue_iocb(ha); | ||
499 | exit_mbox_iocb: | ||
500 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | ||
501 | return rval; | ||
502 | } | ||
503 | |||
504 | int qla4xxx_ping_iocb(struct scsi_qla_host *ha, uint32_t options, | ||
505 | uint32_t payload_size, uint32_t pid, uint8_t *ipaddr) | ||
506 | { | ||
507 | uint32_t in_mbox[8]; | ||
508 | struct mrb *mrb = NULL; | ||
509 | int rval = QLA_SUCCESS; | ||
510 | |||
511 | memset(in_mbox, 0, sizeof(in_mbox)); | ||
512 | |||
513 | mrb = qla4xxx_get_new_mrb(ha); | ||
514 | if (!mrb) { | ||
515 | DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: fail to get new mrb\n", | ||
516 | __func__)); | ||
517 | rval = QLA_ERROR; | ||
518 | goto exit_ping; | ||
519 | } | ||
520 | |||
521 | in_mbox[0] = MBOX_CMD_PING; | ||
522 | in_mbox[1] = options; | ||
523 | memcpy(&in_mbox[2], &ipaddr[0], 4); | ||
524 | memcpy(&in_mbox[3], &ipaddr[4], 4); | ||
525 | memcpy(&in_mbox[4], &ipaddr[8], 4); | ||
526 | memcpy(&in_mbox[5], &ipaddr[12], 4); | ||
527 | in_mbox[6] = payload_size; | ||
528 | |||
529 | mrb->pid = pid; | ||
530 | rval = qla4xxx_send_mbox_iocb(ha, mrb, in_mbox); | ||
531 | |||
532 | if (rval != QLA_SUCCESS) | ||
533 | goto exit_ping; | ||
534 | |||
535 | return rval; | ||
536 | exit_ping: | ||
537 | kfree(mrb); | ||
538 | return rval; | ||
539 | } | ||
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 954fe84be575..7c9f28b7da72 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c | |||
@@ -385,6 +385,71 @@ static void qla4xxx_passthru_status_entry(struct scsi_qla_host *ha, | |||
385 | queue_work(ha->task_wq, &task_data->task_work); | 385 | queue_work(ha->task_wq, &task_data->task_work); |
386 | } | 386 | } |
387 | 387 | ||
388 | static struct mrb *qla4xxx_del_mrb_from_active_array(struct scsi_qla_host *ha, | ||
389 | uint32_t index) | ||
390 | { | ||
391 | struct mrb *mrb = NULL; | ||
392 | |||
393 | /* validate handle and remove from active array */ | ||
394 | if (index >= MAX_MRB) | ||
395 | return mrb; | ||
396 | |||
397 | mrb = ha->active_mrb_array[index]; | ||
398 | ha->active_mrb_array[index] = NULL; | ||
399 | if (!mrb) | ||
400 | return mrb; | ||
401 | |||
402 | /* update counters */ | ||
403 | ha->req_q_count += mrb->iocb_cnt; | ||
404 | ha->iocb_cnt -= mrb->iocb_cnt; | ||
405 | |||
406 | return mrb; | ||
407 | } | ||
408 | |||
409 | static void qla4xxx_mbox_status_entry(struct scsi_qla_host *ha, | ||
410 | struct mbox_status_iocb *mbox_sts_entry) | ||
411 | { | ||
412 | struct mrb *mrb; | ||
413 | uint32_t status; | ||
414 | uint32_t data_size; | ||
415 | |||
416 | mrb = qla4xxx_del_mrb_from_active_array(ha, | ||
417 | le32_to_cpu(mbox_sts_entry->handle)); | ||
418 | |||
419 | if (mrb == NULL) { | ||
420 | ql4_printk(KERN_WARNING, ha, "%s: mrb[%d] is null\n", __func__, | ||
421 | mbox_sts_entry->handle); | ||
422 | return; | ||
423 | } | ||
424 | |||
425 | switch (mrb->mbox_cmd) { | ||
426 | case MBOX_CMD_PING: | ||
427 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: mbox_cmd = 0x%x, " | ||
428 | "mbox_sts[0] = 0x%x, mbox_sts[6] = 0x%x\n", | ||
429 | __func__, mrb->mbox_cmd, | ||
430 | mbox_sts_entry->out_mbox[0], | ||
431 | mbox_sts_entry->out_mbox[6])); | ||
432 | |||
433 | if (mbox_sts_entry->out_mbox[0] == MBOX_STS_COMMAND_COMPLETE) | ||
434 | status = QLA_SUCCESS; | ||
435 | else | ||
436 | status = QLA_ERROR; | ||
437 | |||
438 | data_size = sizeof(mbox_sts_entry->out_mbox); | ||
439 | |||
440 | qla4xxx_post_ping_evt_work(ha, status, mrb->pid, data_size, | ||
441 | (uint8_t *) mbox_sts_entry->out_mbox); | ||
442 | break; | ||
443 | |||
444 | default: | ||
445 | DEBUG2(ql4_printk(KERN_WARNING, ha, "%s: invalid mbox_cmd = " | ||
446 | "0x%x\n", __func__, mrb->mbox_cmd)); | ||
447 | } | ||
448 | |||
449 | kfree(mrb); | ||
450 | return; | ||
451 | } | ||
452 | |||
388 | /** | 453 | /** |
389 | * qla4xxx_process_response_queue - process response queue completions | 454 | * qla4xxx_process_response_queue - process response queue completions |
390 | * @ha: Pointer to host adapter structure. | 455 | * @ha: Pointer to host adapter structure. |
@@ -461,6 +526,13 @@ void qla4xxx_process_response_queue(struct scsi_qla_host *ha) | |||
461 | "ignoring\n", ha->host_no, __func__)); | 526 | "ignoring\n", ha->host_no, __func__)); |
462 | break; | 527 | break; |
463 | 528 | ||
529 | case ET_MBOX_STATUS: | ||
530 | DEBUG2(ql4_printk(KERN_INFO, ha, | ||
531 | "%s: mbox status IOCB\n", __func__)); | ||
532 | qla4xxx_mbox_status_entry(ha, | ||
533 | (struct mbox_status_iocb *)sts_entry); | ||
534 | break; | ||
535 | |||
464 | default: | 536 | default: |
465 | /* | 537 | /* |
466 | * Invalid entry in response queue, reset RISC | 538 | * Invalid entry in response queue, reset RISC |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index d423f7afbbd7..877c0e220ac9 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -118,6 +118,10 @@ static void qla4xxx_task_cleanup(struct iscsi_task *); | |||
118 | static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session); | 118 | static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session); |
119 | static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, | 119 | static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, |
120 | struct iscsi_stats *stats); | 120 | struct iscsi_stats *stats); |
121 | static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, | ||
122 | uint32_t iface_type, uint32_t payload_size, | ||
123 | uint32_t pid, struct sockaddr *dst_addr); | ||
124 | |||
121 | /* | 125 | /* |
122 | * SCSI host template entry points | 126 | * SCSI host template entry points |
123 | */ | 127 | */ |
@@ -194,10 +198,91 @@ static struct iscsi_transport qla4xxx_iscsi_transport = { | |||
194 | .set_iface_param = qla4xxx_iface_set_param, | 198 | .set_iface_param = qla4xxx_iface_set_param, |
195 | .get_iface_param = qla4xxx_get_iface_param, | 199 | .get_iface_param = qla4xxx_get_iface_param, |
196 | .bsg_request = qla4xxx_bsg_request, | 200 | .bsg_request = qla4xxx_bsg_request, |
201 | .send_ping = qla4xxx_send_ping, | ||
197 | }; | 202 | }; |
198 | 203 | ||
199 | static struct scsi_transport_template *qla4xxx_scsi_transport; | 204 | static struct scsi_transport_template *qla4xxx_scsi_transport; |
200 | 205 | ||
206 | static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num, | ||
207 | uint32_t iface_type, uint32_t payload_size, | ||
208 | uint32_t pid, struct sockaddr *dst_addr) | ||
209 | { | ||
210 | struct scsi_qla_host *ha = to_qla_host(shost); | ||
211 | struct sockaddr_in *addr; | ||
212 | struct sockaddr_in6 *addr6; | ||
213 | uint32_t options = 0; | ||
214 | uint8_t ipaddr[IPv6_ADDR_LEN]; | ||
215 | int rval; | ||
216 | |||
217 | memset(ipaddr, 0, IPv6_ADDR_LEN); | ||
218 | /* IPv4 to IPv4 */ | ||
219 | if ((iface_type == ISCSI_IFACE_TYPE_IPV4) && | ||
220 | (dst_addr->sa_family == AF_INET)) { | ||
221 | addr = (struct sockaddr_in *)dst_addr; | ||
222 | memcpy(ipaddr, &addr->sin_addr.s_addr, IP_ADDR_LEN); | ||
223 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv4 Ping src: %pI4 " | ||
224 | "dest: %pI4\n", __func__, | ||
225 | &ha->ip_config.ip_address, ipaddr)); | ||
226 | rval = qla4xxx_ping_iocb(ha, options, payload_size, pid, | ||
227 | ipaddr); | ||
228 | if (rval) | ||
229 | rval = -EINVAL; | ||
230 | } else if ((iface_type == ISCSI_IFACE_TYPE_IPV6) && | ||
231 | (dst_addr->sa_family == AF_INET6)) { | ||
232 | /* IPv6 to IPv6 */ | ||
233 | addr6 = (struct sockaddr_in6 *)dst_addr; | ||
234 | memcpy(ipaddr, &addr6->sin6_addr.in6_u.u6_addr8, IPv6_ADDR_LEN); | ||
235 | |||
236 | options |= PING_IPV6_PROTOCOL_ENABLE; | ||
237 | |||
238 | /* Ping using LinkLocal address */ | ||
239 | if ((iface_num == 0) || (iface_num == 1)) { | ||
240 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: LinkLocal Ping " | ||
241 | "src: %pI6 dest: %pI6\n", __func__, | ||
242 | &ha->ip_config.ipv6_link_local_addr, | ||
243 | ipaddr)); | ||
244 | options |= PING_IPV6_LINKLOCAL_ADDR; | ||
245 | rval = qla4xxx_ping_iocb(ha, options, payload_size, | ||
246 | pid, ipaddr); | ||
247 | } else { | ||
248 | ql4_printk(KERN_WARNING, ha, "%s: iface num = %d " | ||
249 | "not supported\n", __func__, iface_num); | ||
250 | rval = -ENOSYS; | ||
251 | goto exit_send_ping; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * If ping using LinkLocal address fails, try ping using | ||
256 | * IPv6 address | ||
257 | */ | ||
258 | if (rval != QLA_SUCCESS) { | ||
259 | options &= ~PING_IPV6_LINKLOCAL_ADDR; | ||
260 | if (iface_num == 0) { | ||
261 | options |= PING_IPV6_ADDR0; | ||
262 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 " | ||
263 | "Ping src: %pI6 " | ||
264 | "dest: %pI6\n", __func__, | ||
265 | &ha->ip_config.ipv6_addr0, | ||
266 | ipaddr)); | ||
267 | } else if (iface_num == 1) { | ||
268 | options |= PING_IPV6_ADDR1; | ||
269 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IPv6 " | ||
270 | "Ping src: %pI6 " | ||
271 | "dest: %pI6\n", __func__, | ||
272 | &ha->ip_config.ipv6_addr1, | ||
273 | ipaddr)); | ||
274 | } | ||
275 | rval = qla4xxx_ping_iocb(ha, options, payload_size, | ||
276 | pid, ipaddr); | ||
277 | if (rval) | ||
278 | rval = -EINVAL; | ||
279 | } | ||
280 | } else | ||
281 | rval = -ENOSYS; | ||
282 | exit_send_ping: | ||
283 | return rval; | ||
284 | } | ||
285 | |||
201 | static umode_t ql4_attr_is_visible(int param_type, int param) | 286 | static umode_t ql4_attr_is_visible(int param_type, int param) |
202 | { | 287 | { |
203 | switch (param_type) { | 288 | switch (param_type) { |
@@ -2897,6 +2982,26 @@ int qla4xxx_post_aen_work(struct scsi_qla_host *ha, | |||
2897 | return QLA_SUCCESS; | 2982 | return QLA_SUCCESS; |
2898 | } | 2983 | } |
2899 | 2984 | ||
2985 | int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha, | ||
2986 | uint32_t status, uint32_t pid, | ||
2987 | uint32_t data_size, uint8_t *data) | ||
2988 | { | ||
2989 | struct qla4_work_evt *e; | ||
2990 | |||
2991 | e = qla4xxx_alloc_work(ha, data_size, QLA4_EVENT_PING_STATUS); | ||
2992 | if (!e) | ||
2993 | return QLA_ERROR; | ||
2994 | |||
2995 | e->u.ping.status = status; | ||
2996 | e->u.ping.pid = pid; | ||
2997 | e->u.ping.data_size = data_size; | ||
2998 | memcpy(e->u.ping.data, data, data_size); | ||
2999 | |||
3000 | qla4xxx_post_work(ha, e); | ||
3001 | |||
3002 | return QLA_SUCCESS; | ||
3003 | } | ||
3004 | |||
2900 | void qla4xxx_do_work(struct scsi_qla_host *ha) | 3005 | void qla4xxx_do_work(struct scsi_qla_host *ha) |
2901 | { | 3006 | { |
2902 | struct qla4_work_evt *e, *tmp; | 3007 | struct qla4_work_evt *e, *tmp; |
@@ -2918,6 +3023,14 @@ void qla4xxx_do_work(struct scsi_qla_host *ha) | |||
2918 | e->u.aen.data_size, | 3023 | e->u.aen.data_size, |
2919 | e->u.aen.data); | 3024 | e->u.aen.data); |
2920 | break; | 3025 | break; |
3026 | case QLA4_EVENT_PING_STATUS: | ||
3027 | iscsi_ping_comp_event(ha->host_no, | ||
3028 | &qla4xxx_iscsi_transport, | ||
3029 | e->u.ping.status, | ||
3030 | e->u.ping.pid, | ||
3031 | e->u.ping.data_size, | ||
3032 | e->u.ping.data); | ||
3033 | break; | ||
2921 | default: | 3034 | default: |
2922 | ql4_printk(KERN_WARNING, ha, "event type: 0x%x not " | 3035 | ql4_printk(KERN_WARNING, ha, "event type: 0x%x not " |
2923 | "supported", e->type); | 3036 | "supported", e->type); |