aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_os.c
diff options
context:
space:
mode:
authorVikas Chaudhary <vikas.chaudhary@qlogic.com>2012-02-13 08:00:49 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 10:35:23 -0500
commitc0b9d3f750520ad3005b99144260e486ef01b5d9 (patch)
tree2c16adb36151017344dea7681e312fb4f68fd3d5 /drivers/scsi/qla4xxx/ql4_os.c
parentac20c7bf070df2b0feb410558ec4d75dbe59b701 (diff)
[SCSI] qla4xxx: Added ping support
Added ping support for network connection diagnostics. Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com> Reviewed-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_os.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c113
1 files changed, 113 insertions, 0 deletions
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 *);
118static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session); 118static void qla4xxx_fail_session(struct iscsi_cls_session *cls_session);
119static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn, 119static void qla4xxx_conn_get_stats(struct iscsi_cls_conn *cls_conn,
120 struct iscsi_stats *stats); 120 struct iscsi_stats *stats);
121static 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
199static struct scsi_transport_template *qla4xxx_scsi_transport; 204static struct scsi_transport_template *qla4xxx_scsi_transport;
200 205
206static 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;
282exit_send_ping:
283 return rval;
284}
285
201static umode_t ql4_attr_is_visible(int param_type, int param) 286static 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
2985int 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
2900void qla4xxx_do_work(struct scsi_qla_host *ha) 3005void 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);