Commit | Line | Data |
---|---|---|
7725ccfd | 1 | /* |
a36c61f9 | 2 | * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. |
7725ccfd JH |
3 | * All rights reserved |
4 | * www.brocade.com | |
5 | * | |
6 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License (GPL) Version 2 as | |
10 | * published by the Free Software Foundation | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | */ | |
17 | ||
5fbe25c7 | 18 | /* |
7725ccfd JH |
19 | * bfa_attr.c Linux driver configuration interface module. |
20 | */ | |
21 | ||
22 | #include "bfad_drv.h" | |
23 | #include "bfad_im.h" | |
7725ccfd | 24 | |
5fbe25c7 | 25 | /* |
7725ccfd JH |
26 | * FC transport template entry, get SCSI target port ID. |
27 | */ | |
52f94b6f | 28 | static void |
7725ccfd JH |
29 | bfad_im_get_starget_port_id(struct scsi_target *starget) |
30 | { | |
31 | struct Scsi_Host *shost; | |
32 | struct bfad_im_port_s *im_port; | |
33 | struct bfad_s *bfad; | |
34 | struct bfad_itnim_s *itnim = NULL; | |
35 | u32 fc_id = -1; | |
36 | unsigned long flags; | |
37 | ||
a36c61f9 | 38 | shost = dev_to_shost(starget->dev.parent); |
7725ccfd JH |
39 | im_port = (struct bfad_im_port_s *) shost->hostdata[0]; |
40 | bfad = im_port->bfad; | |
41 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
42 | ||
f16a1750 | 43 | itnim = bfad_get_itnim(im_port, starget->id); |
7725ccfd JH |
44 | if (itnim) |
45 | fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); | |
46 | ||
47 | fc_starget_port_id(starget) = fc_id; | |
48 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
49 | } | |
50 | ||
5fbe25c7 | 51 | /* |
7725ccfd JH |
52 | * FC transport template entry, get SCSI target nwwn. |
53 | */ | |
52f94b6f | 54 | static void |
7725ccfd JH |
55 | bfad_im_get_starget_node_name(struct scsi_target *starget) |
56 | { | |
57 | struct Scsi_Host *shost; | |
58 | struct bfad_im_port_s *im_port; | |
59 | struct bfad_s *bfad; | |
60 | struct bfad_itnim_s *itnim = NULL; | |
61 | u64 node_name = 0; | |
62 | unsigned long flags; | |
63 | ||
a36c61f9 | 64 | shost = dev_to_shost(starget->dev.parent); |
7725ccfd JH |
65 | im_port = (struct bfad_im_port_s *) shost->hostdata[0]; |
66 | bfad = im_port->bfad; | |
67 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
68 | ||
f16a1750 | 69 | itnim = bfad_get_itnim(im_port, starget->id); |
7725ccfd JH |
70 | if (itnim) |
71 | node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim); | |
72 | ||
ba816ea8 | 73 | fc_starget_node_name(starget) = cpu_to_be64(node_name); |
7725ccfd JH |
74 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
75 | } | |
76 | ||
5fbe25c7 | 77 | /* |
7725ccfd JH |
78 | * FC transport template entry, get SCSI target pwwn. |
79 | */ | |
52f94b6f | 80 | static void |
7725ccfd JH |
81 | bfad_im_get_starget_port_name(struct scsi_target *starget) |
82 | { | |
83 | struct Scsi_Host *shost; | |
84 | struct bfad_im_port_s *im_port; | |
85 | struct bfad_s *bfad; | |
86 | struct bfad_itnim_s *itnim = NULL; | |
87 | u64 port_name = 0; | |
88 | unsigned long flags; | |
89 | ||
a36c61f9 | 90 | shost = dev_to_shost(starget->dev.parent); |
7725ccfd JH |
91 | im_port = (struct bfad_im_port_s *) shost->hostdata[0]; |
92 | bfad = im_port->bfad; | |
93 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
94 | ||
f16a1750 | 95 | itnim = bfad_get_itnim(im_port, starget->id); |
7725ccfd JH |
96 | if (itnim) |
97 | port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); | |
98 | ||
ba816ea8 | 99 | fc_starget_port_name(starget) = cpu_to_be64(port_name); |
7725ccfd JH |
100 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
101 | } | |
102 | ||
5fbe25c7 | 103 | /* |
7725ccfd JH |
104 | * FC transport template entry, get SCSI host port ID. |
105 | */ | |
52f94b6f | 106 | static void |
7725ccfd JH |
107 | bfad_im_get_host_port_id(struct Scsi_Host *shost) |
108 | { | |
109 | struct bfad_im_port_s *im_port = | |
110 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
111 | struct bfad_port_s *port = im_port->port; | |
112 | ||
113 | fc_host_port_id(shost) = | |
f16a1750 | 114 | bfa_hton3b(bfa_fcs_lport_get_fcid(port->fcs_port)); |
7725ccfd JH |
115 | } |
116 | ||
5fbe25c7 | 117 | /* |
7725ccfd JH |
118 | * FC transport template entry, get SCSI host port type. |
119 | */ | |
120 | static void | |
121 | bfad_im_get_host_port_type(struct Scsi_Host *shost) | |
122 | { | |
123 | struct bfad_im_port_s *im_port = | |
124 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
125 | struct bfad_s *bfad = im_port->bfad; | |
a36c61f9 | 126 | struct bfa_lport_attr_s port_attr; |
7725ccfd | 127 | |
a36c61f9 | 128 | bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr); |
7725ccfd | 129 | |
a36c61f9 KG |
130 | switch (port_attr.port_type) { |
131 | case BFA_PORT_TYPE_NPORT: | |
7725ccfd JH |
132 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; |
133 | break; | |
a36c61f9 | 134 | case BFA_PORT_TYPE_NLPORT: |
7725ccfd JH |
135 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; |
136 | break; | |
a36c61f9 | 137 | case BFA_PORT_TYPE_P2P: |
7725ccfd JH |
138 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; |
139 | break; | |
a36c61f9 | 140 | case BFA_PORT_TYPE_LPORT: |
7725ccfd JH |
141 | fc_host_port_type(shost) = FC_PORTTYPE_LPORT; |
142 | break; | |
143 | default: | |
144 | fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; | |
145 | break; | |
146 | } | |
147 | } | |
148 | ||
5fbe25c7 | 149 | /* |
7725ccfd JH |
150 | * FC transport template entry, get SCSI host port state. |
151 | */ | |
152 | static void | |
153 | bfad_im_get_host_port_state(struct Scsi_Host *shost) | |
154 | { | |
155 | struct bfad_im_port_s *im_port = | |
156 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
157 | struct bfad_s *bfad = im_port->bfad; | |
a36c61f9 | 158 | struct bfa_port_attr_s attr; |
7725ccfd | 159 | |
1c8a4c37 | 160 | bfa_fcport_get_attr(&bfad->bfa, &attr); |
7725ccfd JH |
161 | |
162 | switch (attr.port_state) { | |
a36c61f9 | 163 | case BFA_PORT_ST_LINKDOWN: |
7725ccfd JH |
164 | fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; |
165 | break; | |
a36c61f9 | 166 | case BFA_PORT_ST_LINKUP: |
7725ccfd JH |
167 | fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; |
168 | break; | |
a36c61f9 KG |
169 | case BFA_PORT_ST_DISABLED: |
170 | case BFA_PORT_ST_STOPPED: | |
171 | case BFA_PORT_ST_IOCDOWN: | |
172 | case BFA_PORT_ST_IOCDIS: | |
173 | fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; | |
174 | break; | |
175 | case BFA_PORT_ST_UNINIT: | |
176 | case BFA_PORT_ST_ENABLING_QWAIT: | |
177 | case BFA_PORT_ST_ENABLING: | |
178 | case BFA_PORT_ST_DISABLING_QWAIT: | |
179 | case BFA_PORT_ST_DISABLING: | |
7725ccfd JH |
180 | default: |
181 | fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; | |
182 | break; | |
183 | } | |
184 | } | |
185 | ||
5fbe25c7 | 186 | /* |
7725ccfd JH |
187 | * FC transport template entry, get SCSI host active fc4s. |
188 | */ | |
189 | static void | |
190 | bfad_im_get_host_active_fc4s(struct Scsi_Host *shost) | |
191 | { | |
192 | struct bfad_im_port_s *im_port = | |
193 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
194 | struct bfad_port_s *port = im_port->port; | |
195 | ||
196 | memset(fc_host_active_fc4s(shost), 0, | |
197 | sizeof(fc_host_active_fc4s(shost))); | |
198 | ||
a36c61f9 | 199 | if (port->supported_fc4s & BFA_LPORT_ROLE_FCP_IM) |
7725ccfd JH |
200 | fc_host_active_fc4s(shost)[2] = 1; |
201 | ||
7725ccfd JH |
202 | fc_host_active_fc4s(shost)[7] = 1; |
203 | } | |
204 | ||
5fbe25c7 | 205 | /* |
7725ccfd JH |
206 | * FC transport template entry, get SCSI host link speed. |
207 | */ | |
208 | static void | |
209 | bfad_im_get_host_speed(struct Scsi_Host *shost) | |
210 | { | |
211 | struct bfad_im_port_s *im_port = | |
212 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
213 | struct bfad_s *bfad = im_port->bfad; | |
a36c61f9 | 214 | struct bfa_port_attr_s attr; |
7725ccfd | 215 | |
1c8a4c37 | 216 | bfa_fcport_get_attr(&bfad->bfa, &attr); |
7725ccfd | 217 | switch (attr.speed) { |
a36c61f9 KG |
218 | case BFA_PORT_SPEED_10GBPS: |
219 | fc_host_speed(shost) = FC_PORTSPEED_10GBIT; | |
220 | break; | |
8b070b4a KG |
221 | case BFA_PORT_SPEED_16GBPS: |
222 | fc_host_speed(shost) = FC_PORTSPEED_16GBIT; | |
223 | break; | |
a36c61f9 | 224 | case BFA_PORT_SPEED_8GBPS: |
7725ccfd JH |
225 | fc_host_speed(shost) = FC_PORTSPEED_8GBIT; |
226 | break; | |
a36c61f9 | 227 | case BFA_PORT_SPEED_4GBPS: |
7725ccfd JH |
228 | fc_host_speed(shost) = FC_PORTSPEED_4GBIT; |
229 | break; | |
a36c61f9 | 230 | case BFA_PORT_SPEED_2GBPS: |
7725ccfd JH |
231 | fc_host_speed(shost) = FC_PORTSPEED_2GBIT; |
232 | break; | |
a36c61f9 | 233 | case BFA_PORT_SPEED_1GBPS: |
7725ccfd JH |
234 | fc_host_speed(shost) = FC_PORTSPEED_1GBIT; |
235 | break; | |
236 | default: | |
237 | fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; | |
238 | break; | |
239 | } | |
240 | } | |
241 | ||
5fbe25c7 | 242 | /* |
7725ccfd JH |
243 | * FC transport template entry, get SCSI host port type. |
244 | */ | |
245 | static void | |
246 | bfad_im_get_host_fabric_name(struct Scsi_Host *shost) | |
247 | { | |
248 | struct bfad_im_port_s *im_port = | |
249 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
250 | struct bfad_port_s *port = im_port->port; | |
251 | wwn_t fabric_nwwn = 0; | |
252 | ||
a36c61f9 | 253 | fabric_nwwn = bfa_fcs_lport_get_fabric_name(port->fcs_port); |
7725ccfd | 254 | |
ba816ea8 | 255 | fc_host_fabric_name(shost) = cpu_to_be64(fabric_nwwn); |
7725ccfd JH |
256 | |
257 | } | |
258 | ||
5fbe25c7 | 259 | /* |
7725ccfd JH |
260 | * FC transport template entry, get BFAD statistics. |
261 | */ | |
262 | static struct fc_host_statistics * | |
263 | bfad_im_get_stats(struct Scsi_Host *shost) | |
264 | { | |
265 | struct bfad_im_port_s *im_port = | |
266 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
267 | struct bfad_s *bfad = im_port->bfad; | |
268 | struct bfad_hal_comp fcomp; | |
a36c61f9 | 269 | union bfa_port_stats_u *fcstats; |
7725ccfd JH |
270 | struct fc_host_statistics *hstats; |
271 | bfa_status_t rc; | |
272 | unsigned long flags; | |
273 | ||
a36c61f9 KG |
274 | fcstats = kzalloc(sizeof(union bfa_port_stats_u), GFP_KERNEL); |
275 | if (fcstats == NULL) | |
276 | return NULL; | |
277 | ||
7725ccfd JH |
278 | hstats = &bfad->link_stats; |
279 | init_completion(&fcomp.comp); | |
280 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
281 | memset(hstats, 0, sizeof(struct fc_host_statistics)); | |
a36c61f9 KG |
282 | rc = bfa_port_get_stats(BFA_FCPORT(&bfad->bfa), |
283 | fcstats, bfad_hcb_comp, &fcomp); | |
7725ccfd JH |
284 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
285 | if (rc != BFA_STATUS_OK) | |
286 | return NULL; | |
287 | ||
288 | wait_for_completion(&fcomp.comp); | |
289 | ||
a36c61f9 KG |
290 | /* Fill the fc_host_statistics structure */ |
291 | hstats->seconds_since_last_reset = fcstats->fc.secs_reset; | |
292 | hstats->tx_frames = fcstats->fc.tx_frames; | |
293 | hstats->tx_words = fcstats->fc.tx_words; | |
294 | hstats->rx_frames = fcstats->fc.rx_frames; | |
295 | hstats->rx_words = fcstats->fc.rx_words; | |
296 | hstats->lip_count = fcstats->fc.lip_count; | |
297 | hstats->nos_count = fcstats->fc.nos_count; | |
298 | hstats->error_frames = fcstats->fc.error_frames; | |
299 | hstats->dumped_frames = fcstats->fc.dropped_frames; | |
300 | hstats->link_failure_count = fcstats->fc.link_failures; | |
301 | hstats->loss_of_sync_count = fcstats->fc.loss_of_syncs; | |
302 | hstats->loss_of_signal_count = fcstats->fc.loss_of_signals; | |
303 | hstats->prim_seq_protocol_err_count = fcstats->fc.primseq_errs; | |
304 | hstats->invalid_crc_count = fcstats->fc.invalid_crcs; | |
305 | ||
306 | kfree(fcstats); | |
7725ccfd JH |
307 | return hstats; |
308 | } | |
309 | ||
5fbe25c7 | 310 | /* |
7725ccfd JH |
311 | * FC transport template entry, reset BFAD statistics. |
312 | */ | |
313 | static void | |
314 | bfad_im_reset_stats(struct Scsi_Host *shost) | |
315 | { | |
316 | struct bfad_im_port_s *im_port = | |
317 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
318 | struct bfad_s *bfad = im_port->bfad; | |
319 | struct bfad_hal_comp fcomp; | |
320 | unsigned long flags; | |
321 | bfa_status_t rc; | |
322 | ||
323 | init_completion(&fcomp.comp); | |
324 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
ca8b4327 | 325 | rc = bfa_port_clear_stats(BFA_FCPORT(&bfad->bfa), bfad_hcb_comp, |
a36c61f9 | 326 | &fcomp); |
7725ccfd JH |
327 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
328 | ||
329 | if (rc != BFA_STATUS_OK) | |
330 | return; | |
331 | ||
332 | wait_for_completion(&fcomp.comp); | |
333 | ||
334 | return; | |
335 | } | |
336 | ||
5fbe25c7 | 337 | /* |
7725ccfd | 338 | * FC transport template entry, set rport loss timeout. |
4dde5069 VMG |
339 | * Update dev_loss_tmo based on the value pushed down by the stack |
340 | * In case it is lesser than path_tov of driver, set it to path_tov + 1 | |
341 | * to ensure that the driver times out before the application | |
7725ccfd JH |
342 | */ |
343 | static void | |
344 | bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) | |
345 | { | |
346 | struct bfad_itnim_data_s *itnim_data = rport->dd_data; | |
347 | struct bfad_itnim_s *itnim = itnim_data->itnim; | |
348 | struct bfad_s *bfad = itnim->im->bfad; | |
4dde5069 | 349 | uint16_t path_tov = bfa_fcpim_path_tov_get(&bfad->bfa); |
7725ccfd | 350 | |
4dde5069 VMG |
351 | rport->dev_loss_tmo = timeout; |
352 | if (timeout < path_tov) | |
353 | rport->dev_loss_tmo = path_tov + 1; | |
7725ccfd JH |
354 | } |
355 | ||
b504293f JH |
356 | static int |
357 | bfad_im_vport_create(struct fc_vport *fc_vport, bool disable) | |
358 | { | |
359 | char *vname = fc_vport->symbolic_name; | |
360 | struct Scsi_Host *shost = fc_vport->shost; | |
361 | struct bfad_im_port_s *im_port = | |
362 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
363 | struct bfad_s *bfad = im_port->bfad; | |
a36c61f9 KG |
364 | struct bfa_lport_cfg_s port_cfg; |
365 | struct bfad_vport_s *vp; | |
b504293f JH |
366 | int status = 0, rc; |
367 | unsigned long flags; | |
368 | ||
369 | memset(&port_cfg, 0, sizeof(port_cfg)); | |
d9883548 JH |
370 | u64_to_wwn(fc_vport->node_name, (u8 *)&port_cfg.nwwn); |
371 | u64_to_wwn(fc_vport->port_name, (u8 *)&port_cfg.pwwn); | |
b504293f JH |
372 | if (strlen(vname) > 0) |
373 | strcpy((char *)&port_cfg.sym_name, vname); | |
a36c61f9 | 374 | port_cfg.roles = BFA_LPORT_ROLE_FCP_IM; |
b504293f | 375 | |
d9883548 | 376 | spin_lock_irqsave(&bfad->bfad_lock, flags); |
a36c61f9 KG |
377 | list_for_each_entry(vp, &bfad->pbc_vport_list, list_entry) { |
378 | if (port_cfg.pwwn == | |
379 | vp->fcs_vport.lport.port_cfg.pwwn) { | |
380 | port_cfg.preboot_vp = | |
381 | vp->fcs_vport.lport.port_cfg.preboot_vp; | |
d9883548 JH |
382 | break; |
383 | } | |
384 | } | |
385 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
386 | ||
387 | rc = bfad_vport_create(bfad, 0, &port_cfg, &fc_vport->dev); | |
b504293f | 388 | if (rc == BFA_STATUS_OK) { |
d9883548 | 389 | struct bfad_vport_s *vport; |
b504293f JH |
390 | struct bfa_fcs_vport_s *fcs_vport; |
391 | struct Scsi_Host *vshost; | |
392 | ||
393 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
394 | fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, | |
395 | port_cfg.pwwn); | |
d9883548 JH |
396 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
397 | if (fcs_vport == NULL) | |
b504293f | 398 | return VPCERR_BAD_WWN; |
b504293f JH |
399 | |
400 | fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); | |
401 | if (disable) { | |
d9883548 | 402 | spin_lock_irqsave(&bfad->bfad_lock, flags); |
b504293f | 403 | bfa_fcs_vport_stop(fcs_vport); |
d9883548 | 404 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
b504293f JH |
405 | fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); |
406 | } | |
b504293f JH |
407 | |
408 | vport = fcs_vport->vport_drv; | |
409 | vshost = vport->drv_port.im_port->shost; | |
d9883548 JH |
410 | fc_host_node_name(vshost) = wwn_to_u64((u8 *)&port_cfg.nwwn); |
411 | fc_host_port_name(vshost) = wwn_to_u64((u8 *)&port_cfg.pwwn); | |
6192bd7c KG |
412 | fc_host_supported_classes(vshost) = FC_COS_CLASS3; |
413 | ||
414 | memset(fc_host_supported_fc4s(vshost), 0, | |
415 | sizeof(fc_host_supported_fc4s(vshost))); | |
416 | ||
417 | /* For FCP type 0x08 */ | |
418 | if (supported_fc4s & BFA_LPORT_ROLE_FCP_IM) | |
419 | fc_host_supported_fc4s(vshost)[2] = 1; | |
420 | ||
421 | /* For fibre channel services type 0x20 */ | |
422 | fc_host_supported_fc4s(vshost)[7] = 1; | |
423 | ||
424 | fc_host_supported_speeds(vshost) = | |
425 | bfad_im_supported_speeds(&bfad->bfa); | |
426 | fc_host_maxframe_size(vshost) = | |
427 | bfa_fcport_get_maxfrsize(&bfad->bfa); | |
428 | ||
b504293f JH |
429 | fc_vport->dd_data = vport; |
430 | vport->drv_port.im_port->fc_vport = fc_vport; | |
b504293f JH |
431 | } else if (rc == BFA_STATUS_INVALID_WWN) |
432 | return VPCERR_BAD_WWN; | |
433 | else if (rc == BFA_STATUS_VPORT_EXISTS) | |
434 | return VPCERR_BAD_WWN; | |
435 | else if (rc == BFA_STATUS_VPORT_MAX) | |
436 | return VPCERR_NO_FABRIC_SUPP; | |
437 | else if (rc == BFA_STATUS_VPORT_WWN_BP) | |
438 | return VPCERR_BAD_WWN; | |
d9883548 | 439 | else |
b504293f JH |
440 | return FC_VPORT_FAILED; |
441 | ||
442 | return status; | |
443 | } | |
444 | ||
acea2415 KG |
445 | int |
446 | bfad_im_issue_fc_host_lip(struct Scsi_Host *shost) | |
447 | { | |
448 | struct bfad_im_port_s *im_port = | |
449 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
450 | struct bfad_s *bfad = im_port->bfad; | |
451 | struct bfad_hal_comp fcomp; | |
452 | unsigned long flags; | |
453 | uint32_t status; | |
454 | ||
455 | init_completion(&fcomp.comp); | |
456 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
457 | status = bfa_port_disable(&bfad->bfa.modules.port, | |
458 | bfad_hcb_comp, &fcomp); | |
459 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
460 | ||
461 | if (status != BFA_STATUS_OK) | |
462 | return -EIO; | |
463 | ||
464 | wait_for_completion(&fcomp.comp); | |
465 | if (fcomp.status != BFA_STATUS_OK) | |
466 | return -EIO; | |
467 | ||
468 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
469 | status = bfa_port_enable(&bfad->bfa.modules.port, | |
470 | bfad_hcb_comp, &fcomp); | |
471 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
472 | if (status != BFA_STATUS_OK) | |
473 | return -EIO; | |
474 | ||
475 | wait_for_completion(&fcomp.comp); | |
476 | if (fcomp.status != BFA_STATUS_OK) | |
477 | return -EIO; | |
478 | ||
479 | return 0; | |
480 | } | |
481 | ||
b504293f JH |
482 | static int |
483 | bfad_im_vport_delete(struct fc_vport *fc_vport) | |
484 | { | |
485 | struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data; | |
486 | struct bfad_im_port_s *im_port = | |
487 | (struct bfad_im_port_s *) vport->drv_port.im_port; | |
488 | struct bfad_s *bfad = im_port->bfad; | |
489 | struct bfad_port_s *port; | |
490 | struct bfa_fcs_vport_s *fcs_vport; | |
491 | struct Scsi_Host *vshost; | |
492 | wwn_t pwwn; | |
493 | int rc; | |
494 | unsigned long flags; | |
495 | struct completion fcomp; | |
496 | ||
ff179e0f KG |
497 | if (im_port->flags & BFAD_PORT_DELETE) { |
498 | bfad_scsi_host_free(bfad, im_port); | |
499 | list_del(&vport->list_entry); | |
17c201b3 | 500 | kfree(vport); |
ff179e0f KG |
501 | return 0; |
502 | } | |
b504293f JH |
503 | |
504 | port = im_port->port; | |
505 | ||
506 | vshost = vport->drv_port.im_port->shost; | |
d9883548 | 507 | u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); |
b504293f JH |
508 | |
509 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
510 | fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); | |
511 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
512 | ||
513 | if (fcs_vport == NULL) | |
514 | return VPCERR_BAD_WWN; | |
515 | ||
516 | vport->drv_port.flags |= BFAD_PORT_DELETE; | |
517 | ||
518 | vport->comp_del = &fcomp; | |
519 | init_completion(vport->comp_del); | |
520 | ||
521 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
522 | rc = bfa_fcs_vport_delete(&vport->fcs_vport); | |
523 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
524 | ||
c54d557c JH |
525 | if (rc == BFA_STATUS_PBC) { |
526 | vport->drv_port.flags &= ~BFAD_PORT_DELETE; | |
527 | vport->comp_del = NULL; | |
d9883548 | 528 | return -1; |
c54d557c | 529 | } |
d9883548 | 530 | |
b504293f JH |
531 | wait_for_completion(vport->comp_del); |
532 | ||
f16a1750 | 533 | bfad_scsi_host_free(bfad, im_port); |
5b7db7af | 534 | list_del(&vport->list_entry); |
b504293f JH |
535 | kfree(vport); |
536 | ||
537 | return 0; | |
538 | } | |
539 | ||
540 | static int | |
541 | bfad_im_vport_disable(struct fc_vport *fc_vport, bool disable) | |
542 | { | |
543 | struct bfad_vport_s *vport; | |
544 | struct bfad_s *bfad; | |
545 | struct bfa_fcs_vport_s *fcs_vport; | |
546 | struct Scsi_Host *vshost; | |
547 | wwn_t pwwn; | |
548 | unsigned long flags; | |
549 | ||
550 | vport = (struct bfad_vport_s *)fc_vport->dd_data; | |
551 | bfad = vport->drv_port.bfad; | |
552 | vshost = vport->drv_port.im_port->shost; | |
d9883548 | 553 | u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); |
b504293f JH |
554 | |
555 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
556 | fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); | |
557 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
558 | ||
559 | if (fcs_vport == NULL) | |
560 | return VPCERR_BAD_WWN; | |
561 | ||
562 | if (disable) { | |
563 | bfa_fcs_vport_stop(fcs_vport); | |
564 | fc_vport_set_state(fc_vport, FC_VPORT_DISABLED); | |
565 | } else { | |
566 | bfa_fcs_vport_start(fcs_vport); | |
567 | fc_vport_set_state(fc_vport, FC_VPORT_ACTIVE); | |
568 | } | |
569 | ||
570 | return 0; | |
571 | } | |
572 | ||
ebfe8392 KG |
573 | void |
574 | bfad_im_vport_set_symbolic_name(struct fc_vport *fc_vport) | |
575 | { | |
576 | struct bfad_vport_s *vport = (struct bfad_vport_s *)fc_vport->dd_data; | |
577 | struct bfad_im_port_s *im_port = | |
578 | (struct bfad_im_port_s *)vport->drv_port.im_port; | |
579 | struct bfad_s *bfad = im_port->bfad; | |
580 | struct Scsi_Host *vshost = vport->drv_port.im_port->shost; | |
581 | char *sym_name = fc_vport->symbolic_name; | |
582 | struct bfa_fcs_vport_s *fcs_vport; | |
583 | wwn_t pwwn; | |
584 | unsigned long flags; | |
585 | ||
586 | u64_to_wwn(fc_host_port_name(vshost), (u8 *)&pwwn); | |
587 | ||
588 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
589 | fcs_vport = bfa_fcs_vport_lookup(&bfad->bfa_fcs, 0, pwwn); | |
590 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | |
591 | ||
592 | if (fcs_vport == NULL) | |
593 | return; | |
594 | ||
595 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
22a08538 VMG |
596 | if (strlen(sym_name) > 0) |
597 | bfa_fcs_lport_set_symname(&fcs_vport->lport, sym_name); | |
ebfe8392 KG |
598 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
599 | } | |
600 | ||
7725ccfd JH |
601 | struct fc_function_template bfad_im_fc_function_template = { |
602 | ||
603 | /* Target dynamic attributes */ | |
604 | .get_starget_port_id = bfad_im_get_starget_port_id, | |
605 | .show_starget_port_id = 1, | |
606 | .get_starget_node_name = bfad_im_get_starget_node_name, | |
607 | .show_starget_node_name = 1, | |
608 | .get_starget_port_name = bfad_im_get_starget_port_name, | |
609 | .show_starget_port_name = 1, | |
b504293f JH |
610 | |
611 | /* Host dynamic attribute */ | |
612 | .get_host_port_id = bfad_im_get_host_port_id, | |
613 | .show_host_port_id = 1, | |
614 | ||
615 | /* Host fixed attributes */ | |
616 | .show_host_node_name = 1, | |
617 | .show_host_port_name = 1, | |
618 | .show_host_supported_classes = 1, | |
619 | .show_host_supported_fc4s = 1, | |
620 | .show_host_supported_speeds = 1, | |
621 | .show_host_maxframe_size = 1, | |
622 | ||
623 | /* More host dynamic attributes */ | |
624 | .show_host_port_type = 1, | |
625 | .get_host_port_type = bfad_im_get_host_port_type, | |
626 | .show_host_port_state = 1, | |
627 | .get_host_port_state = bfad_im_get_host_port_state, | |
628 | .show_host_active_fc4s = 1, | |
629 | .get_host_active_fc4s = bfad_im_get_host_active_fc4s, | |
630 | .show_host_speed = 1, | |
631 | .get_host_speed = bfad_im_get_host_speed, | |
632 | .show_host_fabric_name = 1, | |
633 | .get_host_fabric_name = bfad_im_get_host_fabric_name, | |
634 | ||
635 | .show_host_symbolic_name = 1, | |
636 | ||
637 | /* Statistics */ | |
638 | .get_fc_host_stats = bfad_im_get_stats, | |
639 | .reset_fc_host_stats = bfad_im_reset_stats, | |
640 | ||
641 | /* Allocation length for host specific data */ | |
642 | .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *), | |
643 | ||
644 | /* Remote port fixed attributes */ | |
645 | .show_rport_maxframe_size = 1, | |
646 | .show_rport_supported_classes = 1, | |
647 | .show_rport_dev_loss_tmo = 1, | |
b504293f | 648 | .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, |
acea2415 | 649 | .issue_fc_host_lip = bfad_im_issue_fc_host_lip, |
b504293f JH |
650 | .vport_create = bfad_im_vport_create, |
651 | .vport_delete = bfad_im_vport_delete, | |
652 | .vport_disable = bfad_im_vport_disable, | |
ebfe8392 | 653 | .set_vport_symbolic_name = bfad_im_vport_set_symbolic_name, |
b85daafe KG |
654 | .bsg_request = bfad_im_bsg_request, |
655 | .bsg_timeout = bfad_im_bsg_timeout, | |
b504293f JH |
656 | }; |
657 | ||
658 | struct fc_function_template bfad_im_vport_fc_function_template = { | |
659 | ||
660 | /* Target dynamic attributes */ | |
661 | .get_starget_port_id = bfad_im_get_starget_port_id, | |
662 | .show_starget_port_id = 1, | |
663 | .get_starget_node_name = bfad_im_get_starget_node_name, | |
664 | .show_starget_node_name = 1, | |
665 | .get_starget_port_name = bfad_im_get_starget_port_name, | |
666 | .show_starget_port_name = 1, | |
7725ccfd JH |
667 | |
668 | /* Host dynamic attribute */ | |
669 | .get_host_port_id = bfad_im_get_host_port_id, | |
670 | .show_host_port_id = 1, | |
671 | ||
672 | /* Host fixed attributes */ | |
673 | .show_host_node_name = 1, | |
674 | .show_host_port_name = 1, | |
675 | .show_host_supported_classes = 1, | |
676 | .show_host_supported_fc4s = 1, | |
677 | .show_host_supported_speeds = 1, | |
678 | .show_host_maxframe_size = 1, | |
679 | ||
680 | /* More host dynamic attributes */ | |
681 | .show_host_port_type = 1, | |
682 | .get_host_port_type = bfad_im_get_host_port_type, | |
683 | .show_host_port_state = 1, | |
684 | .get_host_port_state = bfad_im_get_host_port_state, | |
685 | .show_host_active_fc4s = 1, | |
686 | .get_host_active_fc4s = bfad_im_get_host_active_fc4s, | |
687 | .show_host_speed = 1, | |
688 | .get_host_speed = bfad_im_get_host_speed, | |
689 | .show_host_fabric_name = 1, | |
690 | .get_host_fabric_name = bfad_im_get_host_fabric_name, | |
691 | ||
692 | .show_host_symbolic_name = 1, | |
693 | ||
694 | /* Statistics */ | |
695 | .get_fc_host_stats = bfad_im_get_stats, | |
696 | .reset_fc_host_stats = bfad_im_reset_stats, | |
697 | ||
698 | /* Allocation length for host specific data */ | |
699 | .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *), | |
700 | ||
701 | /* Remote port fixed attributes */ | |
702 | .show_rport_maxframe_size = 1, | |
703 | .show_rport_supported_classes = 1, | |
704 | .show_rport_dev_loss_tmo = 1, | |
7725ccfd JH |
705 | .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, |
706 | }; | |
707 | ||
5fbe25c7 | 708 | /* |
7725ccfd JH |
709 | * Scsi_Host_attrs SCSI host attributes |
710 | */ | |
711 | static ssize_t | |
712 | bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr, | |
713 | char *buf) | |
714 | { | |
715 | struct Scsi_Host *shost = class_to_shost(dev); | |
716 | struct bfad_im_port_s *im_port = | |
717 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 | 718 | struct bfad_s *bfad = im_port->bfad; |
0a4b1fc0 | 719 | char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; |
7725ccfd | 720 | |
0a4b1fc0 KG |
721 | bfa_get_adapter_serial_num(&bfad->bfa, serial_num); |
722 | return snprintf(buf, PAGE_SIZE, "%s\n", serial_num); | |
7725ccfd JH |
723 | } |
724 | ||
725 | static ssize_t | |
726 | bfad_im_model_show(struct device *dev, struct device_attribute *attr, | |
727 | char *buf) | |
728 | { | |
729 | struct Scsi_Host *shost = class_to_shost(dev); | |
730 | struct bfad_im_port_s *im_port = | |
731 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 | 732 | struct bfad_s *bfad = im_port->bfad; |
0a4b1fc0 | 733 | char model[BFA_ADAPTER_MODEL_NAME_LEN]; |
7725ccfd | 734 | |
0a4b1fc0 KG |
735 | bfa_get_adapter_model(&bfad->bfa, model); |
736 | return snprintf(buf, PAGE_SIZE, "%s\n", model); | |
7725ccfd JH |
737 | } |
738 | ||
739 | static ssize_t | |
740 | bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr, | |
741 | char *buf) | |
742 | { | |
743 | struct Scsi_Host *shost = class_to_shost(dev); | |
744 | struct bfad_im_port_s *im_port = | |
745 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 KG |
746 | struct bfad_s *bfad = im_port->bfad; |
747 | char model[BFA_ADAPTER_MODEL_NAME_LEN]; | |
0a4b1fc0 | 748 | char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN]; |
75332a70 | 749 | int nports = 0; |
7725ccfd | 750 | |
a36c61f9 | 751 | bfa_get_adapter_model(&bfad->bfa, model); |
75332a70 | 752 | nports = bfa_get_nports(&bfad->bfa); |
a36c61f9 KG |
753 | if (!strcmp(model, "Brocade-425")) |
754 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
755 | "Brocade 4Gbps PCIe dual port FC HBA"); | |
756 | else if (!strcmp(model, "Brocade-825")) | |
757 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
758 | "Brocade 8Gbps PCIe dual port FC HBA"); | |
759 | else if (!strcmp(model, "Brocade-42B")) | |
760 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
75332a70 | 761 | "Brocade 4Gbps PCIe dual port FC HBA for HP"); |
a36c61f9 KG |
762 | else if (!strcmp(model, "Brocade-82B")) |
763 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
75332a70 | 764 | "Brocade 8Gbps PCIe dual port FC HBA for HP"); |
a36c61f9 KG |
765 | else if (!strcmp(model, "Brocade-1010")) |
766 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
767 | "Brocade 10Gbps single port CNA"); | |
768 | else if (!strcmp(model, "Brocade-1020")) | |
769 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
770 | "Brocade 10Gbps dual port CNA"); | |
771 | else if (!strcmp(model, "Brocade-1007")) | |
772 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
75332a70 | 773 | "Brocade 10Gbps CNA for IBM Blade Center"); |
a36c61f9 KG |
774 | else if (!strcmp(model, "Brocade-415")) |
775 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
776 | "Brocade 4Gbps PCIe single port FC HBA"); | |
777 | else if (!strcmp(model, "Brocade-815")) | |
778 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
779 | "Brocade 8Gbps PCIe single port FC HBA"); | |
780 | else if (!strcmp(model, "Brocade-41B")) | |
781 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
75332a70 | 782 | "Brocade 4Gbps PCIe single port FC HBA for HP"); |
a36c61f9 KG |
783 | else if (!strcmp(model, "Brocade-81B")) |
784 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
75332a70 | 785 | "Brocade 8Gbps PCIe single port FC HBA for HP"); |
a36c61f9 KG |
786 | else if (!strcmp(model, "Brocade-804")) |
787 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
75332a70 | 788 | "Brocade 8Gbps FC HBA for HP Bladesystem C-class"); |
9d8ad782 | 789 | else if (!strcmp(model, "Brocade-1741")) |
a36c61f9 | 790 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, |
75332a70 | 791 | "Brocade 10Gbps CNA for Dell M-Series Blade Servers"); |
9d8ad782 | 792 | else if (strstr(model, "Brocade-1860")) { |
75332a70 KG |
793 | if (nports == 1 && bfa_ioc_is_cna(&bfad->bfa.ioc)) |
794 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
795 | "Brocade 10Gbps single port CNA"); | |
796 | else if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) | |
797 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
798 | "Brocade 16Gbps PCIe single port FC HBA"); | |
799 | else if (nports == 2 && bfa_ioc_is_cna(&bfad->bfa.ioc)) | |
800 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
801 | "Brocade 10Gbps dual port CNA"); | |
802 | else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) | |
803 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
804 | "Brocade 16Gbps PCIe dual port FC HBA"); | |
6dca60a3 KG |
805 | } else if (!strcmp(model, "Brocade-1867")) { |
806 | if (nports == 1 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) | |
807 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
808 | "Brocade 16Gbps PCIe single port FC HBA for IBM"); | |
809 | else if (nports == 2 && !bfa_ioc_is_cna(&bfad->bfa.ioc)) | |
810 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, | |
811 | "Brocade 16Gbps PCIe dual port FC HBA for IBM"); | |
75332a70 | 812 | } else |
a36c61f9 KG |
813 | snprintf(model_descr, BFA_ADAPTER_MODEL_DESCR_LEN, |
814 | "Invalid Model"); | |
815 | ||
0a4b1fc0 | 816 | return snprintf(buf, PAGE_SIZE, "%s\n", model_descr); |
7725ccfd JH |
817 | } |
818 | ||
819 | static ssize_t | |
820 | bfad_im_node_name_show(struct device *dev, struct device_attribute *attr, | |
821 | char *buf) | |
822 | { | |
823 | struct Scsi_Host *shost = class_to_shost(dev); | |
824 | struct bfad_im_port_s *im_port = | |
825 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
826 | struct bfad_port_s *port = im_port->port; | |
827 | u64 nwwn; | |
828 | ||
a36c61f9 | 829 | nwwn = bfa_fcs_lport_get_nwwn(port->fcs_port); |
ba816ea8 | 830 | return snprintf(buf, PAGE_SIZE, "0x%llx\n", cpu_to_be64(nwwn)); |
7725ccfd JH |
831 | } |
832 | ||
833 | static ssize_t | |
834 | bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr, | |
835 | char *buf) | |
836 | { | |
837 | struct Scsi_Host *shost = class_to_shost(dev); | |
838 | struct bfad_im_port_s *im_port = | |
839 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 KG |
840 | struct bfad_s *bfad = im_port->bfad; |
841 | struct bfa_lport_attr_s port_attr; | |
842 | char symname[BFA_SYMNAME_MAXLEN]; | |
7725ccfd | 843 | |
a36c61f9 KG |
844 | bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr); |
845 | strncpy(symname, port_attr.port_cfg.sym_name.symname, | |
846 | BFA_SYMNAME_MAXLEN); | |
847 | return snprintf(buf, PAGE_SIZE, "%s\n", symname); | |
7725ccfd JH |
848 | } |
849 | ||
850 | static ssize_t | |
851 | bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr, | |
852 | char *buf) | |
853 | { | |
854 | struct Scsi_Host *shost = class_to_shost(dev); | |
855 | struct bfad_im_port_s *im_port = | |
856 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 | 857 | struct bfad_s *bfad = im_port->bfad; |
0a4b1fc0 | 858 | char hw_ver[BFA_VERSION_LEN]; |
7725ccfd | 859 | |
0a4b1fc0 KG |
860 | bfa_get_pci_chip_rev(&bfad->bfa, hw_ver); |
861 | return snprintf(buf, PAGE_SIZE, "%s\n", hw_ver); | |
7725ccfd JH |
862 | } |
863 | ||
864 | static ssize_t | |
865 | bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr, | |
866 | char *buf) | |
867 | { | |
868 | return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION); | |
869 | } | |
870 | ||
871 | static ssize_t | |
872 | bfad_im_optionrom_version_show(struct device *dev, | |
873 | struct device_attribute *attr, char *buf) | |
874 | { | |
875 | struct Scsi_Host *shost = class_to_shost(dev); | |
876 | struct bfad_im_port_s *im_port = | |
877 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 | 878 | struct bfad_s *bfad = im_port->bfad; |
0a4b1fc0 | 879 | char optrom_ver[BFA_VERSION_LEN]; |
7725ccfd | 880 | |
0a4b1fc0 KG |
881 | bfa_get_adapter_optrom_ver(&bfad->bfa, optrom_ver); |
882 | return snprintf(buf, PAGE_SIZE, "%s\n", optrom_ver); | |
7725ccfd JH |
883 | } |
884 | ||
885 | static ssize_t | |
886 | bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr, | |
887 | char *buf) | |
888 | { | |
889 | struct Scsi_Host *shost = class_to_shost(dev); | |
890 | struct bfad_im_port_s *im_port = | |
891 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 | 892 | struct bfad_s *bfad = im_port->bfad; |
0a4b1fc0 | 893 | char fw_ver[BFA_VERSION_LEN]; |
7725ccfd | 894 | |
0a4b1fc0 KG |
895 | bfa_get_adapter_fw_ver(&bfad->bfa, fw_ver); |
896 | return snprintf(buf, PAGE_SIZE, "%s\n", fw_ver); | |
7725ccfd JH |
897 | } |
898 | ||
899 | static ssize_t | |
900 | bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr, | |
901 | char *buf) | |
902 | { | |
903 | struct Scsi_Host *shost = class_to_shost(dev); | |
904 | struct bfad_im_port_s *im_port = | |
905 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
a36c61f9 | 906 | struct bfad_s *bfad = im_port->bfad; |
7725ccfd | 907 | |
0a4b1fc0 | 908 | return snprintf(buf, PAGE_SIZE, "%d\n", |
a36c61f9 | 909 | bfa_get_nports(&bfad->bfa)); |
7725ccfd JH |
910 | } |
911 | ||
912 | static ssize_t | |
913 | bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr, | |
914 | char *buf) | |
915 | { | |
916 | return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME); | |
917 | } | |
918 | ||
919 | static ssize_t | |
920 | bfad_im_num_of_discovered_ports_show(struct device *dev, | |
921 | struct device_attribute *attr, char *buf) | |
922 | { | |
923 | struct Scsi_Host *shost = class_to_shost(dev); | |
924 | struct bfad_im_port_s *im_port = | |
925 | (struct bfad_im_port_s *) shost->hostdata[0]; | |
926 | struct bfad_port_s *port = im_port->port; | |
927 | struct bfad_s *bfad = im_port->bfad; | |
928 | int nrports = 2048; | |
ee1a4a42 | 929 | struct bfa_rport_qualifier_s *rports = NULL; |
7725ccfd JH |
930 | unsigned long flags; |
931 | ||
ee1a4a42 KG |
932 | rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports, |
933 | GFP_ATOMIC); | |
7725ccfd | 934 | if (rports == NULL) |
a36c61f9 | 935 | return snprintf(buf, PAGE_SIZE, "Failed\n"); |
7725ccfd JH |
936 | |
937 | spin_lock_irqsave(&bfad->bfad_lock, flags); | |
ee1a4a42 | 938 | bfa_fcs_lport_get_rport_quals(port->fcs_port, rports, &nrports); |
7725ccfd JH |
939 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); |
940 | kfree(rports); | |
941 | ||
942 | return snprintf(buf, PAGE_SIZE, "%d\n", nrports); | |
943 | } | |
944 | ||
945 | static DEVICE_ATTR(serial_number, S_IRUGO, | |
946 | bfad_im_serial_num_show, NULL); | |
947 | static DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL); | |
948 | static DEVICE_ATTR(model_description, S_IRUGO, | |
949 | bfad_im_model_desc_show, NULL); | |
950 | static DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL); | |
951 | static DEVICE_ATTR(symbolic_name, S_IRUGO, | |
952 | bfad_im_symbolic_name_show, NULL); | |
953 | static DEVICE_ATTR(hardware_version, S_IRUGO, | |
954 | bfad_im_hw_version_show, NULL); | |
955 | static DEVICE_ATTR(driver_version, S_IRUGO, | |
956 | bfad_im_drv_version_show, NULL); | |
957 | static DEVICE_ATTR(option_rom_version, S_IRUGO, | |
958 | bfad_im_optionrom_version_show, NULL); | |
959 | static DEVICE_ATTR(firmware_version, S_IRUGO, | |
960 | bfad_im_fw_version_show, NULL); | |
961 | static DEVICE_ATTR(number_of_ports, S_IRUGO, | |
962 | bfad_im_num_of_ports_show, NULL); | |
963 | static DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL); | |
964 | static DEVICE_ATTR(number_of_discovered_ports, S_IRUGO, | |
965 | bfad_im_num_of_discovered_ports_show, NULL); | |
966 | ||
967 | struct device_attribute *bfad_im_host_attrs[] = { | |
968 | &dev_attr_serial_number, | |
969 | &dev_attr_model, | |
970 | &dev_attr_model_description, | |
971 | &dev_attr_node_name, | |
972 | &dev_attr_symbolic_name, | |
973 | &dev_attr_hardware_version, | |
974 | &dev_attr_driver_version, | |
975 | &dev_attr_option_rom_version, | |
976 | &dev_attr_firmware_version, | |
977 | &dev_attr_number_of_ports, | |
978 | &dev_attr_driver_name, | |
979 | &dev_attr_number_of_discovered_ports, | |
980 | NULL, | |
981 | }; | |
982 | ||
983 | struct device_attribute *bfad_im_vport_attrs[] = { | |
a36c61f9 KG |
984 | &dev_attr_serial_number, |
985 | &dev_attr_model, | |
986 | &dev_attr_model_description, | |
987 | &dev_attr_node_name, | |
988 | &dev_attr_symbolic_name, | |
989 | &dev_attr_hardware_version, | |
990 | &dev_attr_driver_version, | |
991 | &dev_attr_option_rom_version, | |
992 | &dev_attr_firmware_version, | |
993 | &dev_attr_number_of_ports, | |
994 | &dev_attr_driver_name, | |
995 | &dev_attr_number_of_discovered_ports, | |
996 | NULL, | |
7725ccfd JH |
997 | }; |
998 | ||
999 |