Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. |
| 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 | |
| 18 | /** |
| 19 | * port_api.c BFA FCS port |
| 20 | */ |
| 21 | |
| 22 | #include <fcs/bfa_fcs.h> |
| 23 | #include <fcs/bfa_fcs_lport.h> |
| 24 | #include <fcs/bfa_fcs_rport.h> |
| 25 | #include "fcs_rport.h" |
| 26 | #include "fcs_fabric.h" |
| 27 | #include "fcs_trcmod.h" |
| 28 | #include "fcs_vport.h" |
| 29 | |
| 30 | BFA_TRC_FILE(FCS, PORT_API); |
| 31 | |
| 32 | |
| 33 | |
| 34 | /** |
| 35 | * fcs_port_api BFA FCS port API |
| 36 | */ |
| 37 | |
| 38 | void |
| 39 | bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg) |
| 40 | { |
| 41 | } |
| 42 | |
| 43 | struct bfa_fcs_port_s * |
| 44 | bfa_fcs_get_base_port(struct bfa_fcs_s *fcs) |
| 45 | { |
Jing Huang | f8ceafd | 2009-09-25 12:29:54 -0700 | [diff] [blame] | 46 | return &fcs->fabric.bport; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | wwn_t |
| 50 | bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn, int index, |
| 51 | int nrports, bfa_boolean_t bwwn) |
| 52 | { |
| 53 | struct list_head *qh, *qe; |
| 54 | struct bfa_fcs_rport_s *rport = NULL; |
| 55 | int i; |
| 56 | struct bfa_fcs_s *fcs; |
| 57 | |
| 58 | if (port == NULL || nrports == 0) |
| 59 | return (wwn_t) 0; |
| 60 | |
| 61 | fcs = port->fcs; |
| 62 | bfa_trc(fcs, (u32) nrports); |
| 63 | |
| 64 | i = 0; |
| 65 | qh = &port->rport_q; |
| 66 | qe = bfa_q_first(qh); |
| 67 | |
| 68 | while ((qe != qh) && (i < nrports)) { |
| 69 | rport = (struct bfa_fcs_rport_s *)qe; |
| 70 | if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { |
| 71 | qe = bfa_q_next(qe); |
| 72 | bfa_trc(fcs, (u32) rport->pwwn); |
| 73 | bfa_trc(fcs, rport->pid); |
| 74 | bfa_trc(fcs, i); |
| 75 | continue; |
| 76 | } |
| 77 | |
| 78 | if (bwwn) { |
| 79 | if (!memcmp(&wwn, &rport->pwwn, 8)) |
| 80 | break; |
| 81 | } else { |
| 82 | if (i == index) |
| 83 | break; |
| 84 | } |
| 85 | |
| 86 | i++; |
| 87 | qe = bfa_q_next(qe); |
| 88 | } |
| 89 | |
| 90 | bfa_trc(fcs, i); |
Jing Huang | f8ceafd | 2009-09-25 12:29:54 -0700 | [diff] [blame] | 91 | if (rport) |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 92 | return rport->pwwn; |
Jing Huang | f8ceafd | 2009-09-25 12:29:54 -0700 | [diff] [blame] | 93 | else |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 94 | return (wwn_t) 0; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | void |
| 98 | bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, wwn_t rport_wwns[], |
| 99 | int *nrports) |
| 100 | { |
| 101 | struct list_head *qh, *qe; |
| 102 | struct bfa_fcs_rport_s *rport = NULL; |
| 103 | int i; |
| 104 | struct bfa_fcs_s *fcs; |
| 105 | |
| 106 | if (port == NULL || rport_wwns == NULL || *nrports == 0) |
| 107 | return; |
| 108 | |
| 109 | fcs = port->fcs; |
| 110 | bfa_trc(fcs, (u32) *nrports); |
| 111 | |
| 112 | i = 0; |
| 113 | qh = &port->rport_q; |
| 114 | qe = bfa_q_first(qh); |
| 115 | |
| 116 | while ((qe != qh) && (i < *nrports)) { |
| 117 | rport = (struct bfa_fcs_rport_s *)qe; |
| 118 | if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { |
| 119 | qe = bfa_q_next(qe); |
| 120 | bfa_trc(fcs, (u32) rport->pwwn); |
| 121 | bfa_trc(fcs, rport->pid); |
| 122 | bfa_trc(fcs, i); |
| 123 | continue; |
| 124 | } |
| 125 | |
| 126 | rport_wwns[i] = rport->pwwn; |
| 127 | |
| 128 | i++; |
| 129 | qe = bfa_q_next(qe); |
| 130 | } |
| 131 | |
| 132 | bfa_trc(fcs, i); |
| 133 | *nrports = i; |
| 134 | return; |
| 135 | } |
| 136 | |
| 137 | /* |
| 138 | * Iterate's through all the rport's in the given port to |
| 139 | * determine the maximum operating speed. |
Jing Huang | c507341 | 2010-07-08 19:51:28 -0700 | [diff] [blame] | 140 | * |
| 141 | * To be used in TRL Functionality only |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 142 | */ |
| 143 | enum bfa_pport_speed |
| 144 | bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port) |
| 145 | { |
| 146 | struct list_head *qh, *qe; |
| 147 | struct bfa_fcs_rport_s *rport = NULL; |
| 148 | struct bfa_fcs_s *fcs; |
| 149 | enum bfa_pport_speed max_speed = 0; |
| 150 | struct bfa_pport_attr_s pport_attr; |
Jing Huang | c507341 | 2010-07-08 19:51:28 -0700 | [diff] [blame] | 151 | enum bfa_pport_speed pport_speed, rport_speed; |
| 152 | bfa_boolean_t trl_enabled = bfa_fcport_is_ratelim(port->fcs->bfa); |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 153 | |
| 154 | if (port == NULL) |
| 155 | return 0; |
| 156 | |
| 157 | fcs = port->fcs; |
| 158 | |
| 159 | /* |
| 160 | * Get Physical port's current speed |
| 161 | */ |
Krishna Gudipati | 1c8a4c3 | 2010-03-05 19:37:37 -0800 | [diff] [blame] | 162 | bfa_fcport_get_attr(port->fcs->bfa, &pport_attr); |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 163 | pport_speed = pport_attr.speed; |
| 164 | bfa_trc(fcs, pport_speed); |
| 165 | |
| 166 | qh = &port->rport_q; |
| 167 | qe = bfa_q_first(qh); |
| 168 | |
| 169 | while (qe != qh) { |
Jing Huang | c507341 | 2010-07-08 19:51:28 -0700 | [diff] [blame] | 170 | rport = (struct bfa_fcs_rport_s *) qe; |
| 171 | if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) || |
| 172 | (bfa_fcs_rport_get_state(rport) == |
| 173 | BFA_RPORT_OFFLINE)) { |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 174 | qe = bfa_q_next(qe); |
| 175 | continue; |
| 176 | } |
| 177 | |
Jing Huang | c507341 | 2010-07-08 19:51:28 -0700 | [diff] [blame] | 178 | rport_speed = rport->rpf.rpsc_speed; |
| 179 | if ((trl_enabled) && (rport_speed == |
| 180 | BFA_PPORT_SPEED_UNKNOWN)) { |
| 181 | /* Use default ratelim speed setting */ |
| 182 | rport_speed = |
| 183 | bfa_fcport_get_ratelim_speed(port->fcs->bfa); |
| 184 | } |
| 185 | |
| 186 | if ((rport_speed == BFA_PPORT_SPEED_8GBPS) || |
| 187 | (rport_speed > pport_speed)) { |
| 188 | max_speed = rport_speed; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 189 | break; |
Jing Huang | c507341 | 2010-07-08 19:51:28 -0700 | [diff] [blame] | 190 | } else if (rport_speed > max_speed) { |
| 191 | max_speed = rport_speed; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 192 | } |
| 193 | |
| 194 | qe = bfa_q_next(qe); |
| 195 | } |
| 196 | |
| 197 | bfa_trc(fcs, max_speed); |
| 198 | return max_speed; |
| 199 | } |
| 200 | |
| 201 | struct bfa_fcs_port_s * |
| 202 | bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn) |
| 203 | { |
| 204 | struct bfa_fcs_vport_s *vport; |
| 205 | bfa_fcs_vf_t *vf; |
| 206 | |
| 207 | bfa_assert(fcs != NULL); |
| 208 | |
| 209 | vf = bfa_fcs_vf_lookup(fcs, vf_id); |
| 210 | if (vf == NULL) { |
| 211 | bfa_trc(fcs, vf_id); |
Jing Huang | f8ceafd | 2009-09-25 12:29:54 -0700 | [diff] [blame] | 212 | return NULL; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 213 | } |
| 214 | |
| 215 | if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn)) |
Jing Huang | f8ceafd | 2009-09-25 12:29:54 -0700 | [diff] [blame] | 216 | return &vf->bport; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 217 | |
| 218 | vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn); |
| 219 | if (vport) |
Jing Huang | f8ceafd | 2009-09-25 12:29:54 -0700 | [diff] [blame] | 220 | return &vport->lport; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 221 | |
Jing Huang | f8ceafd | 2009-09-25 12:29:54 -0700 | [diff] [blame] | 222 | return NULL; |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 223 | } |
| 224 | |
| 225 | /* |
| 226 | * API corresponding to VmWare's NPIV_VPORT_GETINFO. |
| 227 | */ |
| 228 | void |
| 229 | bfa_fcs_port_get_info(struct bfa_fcs_port_s *port, |
| 230 | struct bfa_port_info_s *port_info) |
| 231 | { |
| 232 | |
| 233 | bfa_trc(port->fcs, port->fabric->fabric_name); |
| 234 | |
| 235 | if (port->vport == NULL) { |
| 236 | /* |
| 237 | * This is a Physical port |
| 238 | */ |
| 239 | port_info->port_type = BFA_PORT_TYPE_PHYSICAL; |
| 240 | |
| 241 | /* |
| 242 | * @todo : need to fix the state & reason |
| 243 | */ |
| 244 | port_info->port_state = 0; |
| 245 | port_info->offline_reason = 0; |
| 246 | |
| 247 | port_info->port_wwn = bfa_fcs_port_get_pwwn(port); |
| 248 | port_info->node_wwn = bfa_fcs_port_get_nwwn(port); |
| 249 | |
Krishna Gudipati | a046bf0 | 2010-03-03 17:43:45 -0800 | [diff] [blame] | 250 | port_info->max_vports_supp = |
| 251 | bfa_lps_get_max_vport(port->fcs->bfa); |
Jing Huang | 7725ccf | 2009-09-23 17:46:15 -0700 | [diff] [blame] | 252 | port_info->num_vports_inuse = |
| 253 | bfa_fcs_fabric_vport_count(port->fabric); |
| 254 | port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP; |
| 255 | port_info->num_rports_inuse = port->num_rports; |
| 256 | } else { |
| 257 | /* |
| 258 | * This is a virtual port |
| 259 | */ |
| 260 | port_info->port_type = BFA_PORT_TYPE_VIRTUAL; |
| 261 | |
| 262 | /* |
| 263 | * @todo : need to fix the state & reason |
| 264 | */ |
| 265 | port_info->port_state = 0; |
| 266 | port_info->offline_reason = 0; |
| 267 | |
| 268 | port_info->port_wwn = bfa_fcs_port_get_pwwn(port); |
| 269 | port_info->node_wwn = bfa_fcs_port_get_nwwn(port); |
| 270 | } |
| 271 | } |
| 272 | |
| 273 | void |
| 274 | bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port, |
| 275 | struct bfa_port_stats_s *port_stats) |
| 276 | { |
| 277 | bfa_os_memcpy(port_stats, &fcs_port->stats, |
| 278 | sizeof(struct bfa_port_stats_s)); |
| 279 | return; |
| 280 | } |
| 281 | |
| 282 | void |
| 283 | bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port) |
| 284 | { |
| 285 | bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_port_stats_s)); |
| 286 | return; |
| 287 | } |
| 288 | |
| 289 | void |
| 290 | bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port) |
| 291 | { |
| 292 | fcs_port->port_cfg.roles |= BFA_PORT_ROLE_FCP_IPFC; |
| 293 | return; |
| 294 | } |
| 295 | |
| 296 | void |
| 297 | bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port) |
| 298 | { |
| 299 | fcs_port->port_cfg.roles &= ~BFA_PORT_ROLE_FCP_IPFC; |
| 300 | return; |
| 301 | } |
| 302 | |
| 303 | |