blob: a6b7f1588aa407a56b2ed767c2f3bfde8fd91269 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Andrew Vasquezfa90c542005-10-27 11:10:08 -07002 * QLogic Fibre Channel HBA Driver
Armen Baloyanbd21eaf2014-04-11 16:54:24 -04003 * Copyright (c) 2003-2014 QLogic Corporation
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
Andrew Vasquezfa90c542005-10-27 11:10:08 -07005 * See LICENSE.qla2xxx for copyright and licensing details.
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7
Quinn Tranf83adb62014-04-11 16:54:43 -04008#include "qla_target.h"
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -04009/**
10 * qla24xx_calc_iocbs() - Determine number of Command Type 3 and
11 * Continuation Type 1 IOCBs to allocate.
12 *
13 * @dsds: number of data segment decriptors needed
14 *
15 * Returns the number of IOCB entries needed to store @dsds.
16 */
17static inline uint16_t
18qla24xx_calc_iocbs(scsi_qla_host_t *vha, uint16_t dsds)
19{
20 uint16_t iocbs;
21
22 iocbs = 1;
23 if (dsds > 1) {
24 iocbs += (dsds - 1) / 5;
25 if ((dsds - 1) % 5)
26 iocbs++;
27 }
28 return iocbs;
29}
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031/*
32 * qla2x00_debounce_register
33 * Debounce register.
34 *
35 * Input:
36 * port = register address.
37 *
38 * Returns:
39 * register value.
40 */
41static __inline__ uint16_t
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -070042qla2x00_debounce_register(volatile uint16_t __iomem *addr)
Linus Torvalds1da177e2005-04-16 15:20:36 -070043{
44 volatile uint16_t first;
45 volatile uint16_t second;
46
47 do {
48 first = RD_REG_WORD(addr);
49 barrier();
50 cpu_relax();
51 second = RD_REG_WORD(addr);
52 } while (first != second);
53
54 return (first);
55}
56
Andrew Vasquezfa2a1ce2005-07-06 10:32:07 -070057static inline void
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080058qla2x00_poll(struct rsp_que *rsp)
Linus Torvalds1da177e2005-04-16 15:20:36 -070059{
Andrew Vasquezd2ba5672008-05-12 22:21:14 -070060 unsigned long flags;
Anirban Chakrabortye315cd22008-11-06 10:40:51 -080061 struct qla_hw_data *ha = rsp->hw;
Andrew Vasquezd2ba5672008-05-12 22:21:14 -070062 local_irq_save(flags);
Atul Deshmukh7ec0eff2013-08-27 01:37:28 -040063 if (IS_P3P_TYPE(ha))
Giridhar Malavalia9083012010-04-12 17:59:55 -070064 qla82xx_poll(0, rsp);
65 else
66 ha->isp_ops->intr_handler(0, rsp);
Andrew Vasquezd2ba5672008-05-12 22:21:14 -070067 local_irq_restore(flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070068}
69
Andrew Vasquez2b6c0ce2005-07-06 10:31:17 -070070static inline uint8_t *
71host_to_fcp_swap(uint8_t *fcp, uint32_t bsize)
72{
73 uint32_t *ifcp = (uint32_t *) fcp;
74 uint32_t *ofcp = (uint32_t *) fcp;
75 uint32_t iter = bsize >> 2;
76
77 for (; iter ; iter--)
78 *ofcp++ = swab32(*ifcp++);
79
80 return fcp;
81}
Andrew Vasquez3d716442005-07-06 10:30:26 -070082
Chad Dupuis5f16b332012-08-22 14:21:00 -040083static inline void
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -040084host_to_adap(uint8_t *src, uint8_t *dst, uint32_t bsize)
85{
86 uint32_t *isrc = (uint32_t *) src;
Saurav Kashyap1f8deef2013-06-25 11:27:21 -040087 __le32 *odest = (__le32 *) dst;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -040088 uint32_t iter = bsize >> 2;
89
90 for (; iter ; iter--)
91 *odest++ = cpu_to_le32(*isrc++);
92}
93
94static inline void
Chad Dupuis5f16b332012-08-22 14:21:00 -040095qla2x00_set_reserved_loop_ids(struct qla_hw_data *ha)
96{
97 int i;
98
99 if (IS_FWI2_CAPABLE(ha))
100 return;
101
102 for (i = 0; i < SNS_FIRST_LOOP_ID; i++)
103 set_bit(i, ha->loop_id_map);
104 set_bit(MANAGEMENT_SERVER, ha->loop_id_map);
105 set_bit(BROADCAST, ha->loop_id_map);
106}
107
Andrew Vasquez3d716442005-07-06 10:30:26 -0700108static inline int
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800109qla2x00_is_reserved_id(scsi_qla_host_t *vha, uint16_t loop_id)
Andrew Vasquez3d716442005-07-06 10:30:26 -0700110{
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800111 struct qla_hw_data *ha = vha->hw;
Andrew Vasqueze4289242007-07-19 15:05:56 -0700112 if (IS_FWI2_CAPABLE(ha))
Andrew Vasquez3d716442005-07-06 10:30:26 -0700113 return (loop_id > NPH_LAST_HANDLE);
114
Anirban Chakrabortye315cd22008-11-06 10:40:51 -0800115 return ((loop_id > ha->max_loop_id && loop_id < SNS_FIRST_LOOP_ID) ||
Andrew Vasquez3d716442005-07-06 10:30:26 -0700116 loop_id == MANAGEMENT_SERVER || loop_id == BROADCAST);
Anirban Chakraborty17d98632008-12-18 10:06:15 -0800117}
Arun Easibad75002010-05-04 15:01:30 -0700118
119static inline void
Chad Dupuis5f16b332012-08-22 14:21:00 -0400120qla2x00_clear_loop_id(fc_port_t *fcport) {
121 struct qla_hw_data *ha = fcport->vha->hw;
122
123 if (fcport->loop_id == FC_NO_LOOP_ID ||
124 qla2x00_is_reserved_id(fcport->vha, fcport->loop_id))
125 return;
126
127 clear_bit(fcport->loop_id, ha->loop_id_map);
128 fcport->loop_id = FC_NO_LOOP_ID;
129}
130
131static inline void
Quinn Tranf83adb62014-04-11 16:54:43 -0400132qla2x00_clean_dsd_pool(struct qla_hw_data *ha, srb_t *sp,
133 struct qla_tgt_cmd *tc)
Arun Easibad75002010-05-04 15:01:30 -0700134{
135 struct dsd_dma *dsd_ptr, *tdsd_ptr;
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800136 struct crc_context *ctx;
137
Quinn Tranf83adb62014-04-11 16:54:43 -0400138 if (sp)
139 ctx = (struct crc_context *)GET_CMD_CTX_SP(sp);
140 else if (tc)
141 ctx = (struct crc_context *)tc->ctx;
142 else {
143 BUG();
144 return;
145 }
Arun Easibad75002010-05-04 15:01:30 -0700146
147 /* clean up allocated prev pool */
148 list_for_each_entry_safe(dsd_ptr, tdsd_ptr,
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800149 &ctx->dsd_list, list) {
Arun Easibad75002010-05-04 15:01:30 -0700150 dma_pool_free(ha->dl_dma_pool, dsd_ptr->dsd_addr,
151 dsd_ptr->dsd_list_dma);
152 list_del(&dsd_ptr->list);
153 kfree(dsd_ptr);
154 }
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800155 INIT_LIST_HEAD(&ctx->dsd_list);
Arun Easibad75002010-05-04 15:01:30 -0700156}
Chad Dupuisec426e12011-03-30 11:46:32 -0700157
158static inline void
159qla2x00_set_fcport_state(fc_port_t *fcport, int state)
160{
161 int old_state;
162
163 old_state = atomic_read(&fcport->state);
164 atomic_set(&fcport->state, state);
165
166 /* Don't print state transitions during initial allocation of fcport */
167 if (old_state && old_state != state) {
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700168 ql_dbg(ql_dbg_disc, fcport->vha, 0x207d,
169 "FCPort state transitioned from %s to %s - "
170 "portid=%02x%02x%02x.\n",
Chad Dupuisec426e12011-03-30 11:46:32 -0700171 port_state_str[old_state], port_state_str[state],
172 fcport->d_id.b.domain, fcport->d_id.b.area,
Saurav Kashyap7c3df132011-07-14 12:00:13 -0700173 fcport->d_id.b.al_pa);
Chad Dupuisec426e12011-03-30 11:46:32 -0700174 }
175}
Arun Easi8cb20492011-08-16 11:29:22 -0700176
177static inline int
Arun Easie02587d2011-08-16 11:29:23 -0700178qla2x00_hba_err_chk_enabled(srb_t *sp)
Arun Easi8cb20492011-08-16 11:29:22 -0700179{
Arun Easie02587d2011-08-16 11:29:23 -0700180 /*
181 * Uncomment when corresponding SCSI changes are done.
182 *
183 if (!sp->cmd->prot_chk)
184 return 0;
185 *
186 */
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800187 switch (scsi_get_prot_op(GET_CMD_SP(sp))) {
Arun Easi8cb20492011-08-16 11:29:22 -0700188 case SCSI_PROT_READ_STRIP:
189 case SCSI_PROT_WRITE_INSERT:
190 if (ql2xenablehba_err_chk >= 1)
191 return 1;
192 break;
193 case SCSI_PROT_READ_PASS:
194 case SCSI_PROT_WRITE_PASS:
195 if (ql2xenablehba_err_chk >= 2)
196 return 1;
197 break;
198 case SCSI_PROT_READ_INSERT:
199 case SCSI_PROT_WRITE_STRIP:
200 return 1;
201 }
202 return 0;
203}
Andrew Vasquezd051a5aa2012-02-09 11:14:05 -0800204
205static inline int
206qla2x00_reset_active(scsi_qla_host_t *vha)
207{
208 scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev);
209
210 /* Test appropriate base-vha and vha flags. */
211 return test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) ||
212 test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
213 test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
214 test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
215 test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
216}
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800217
218static inline srb_t *
219qla2x00_get_sp(scsi_qla_host_t *vha, fc_port_t *fcport, gfp_t flag)
220{
221 srb_t *sp = NULL;
222 struct qla_hw_data *ha = vha->hw;
223 uint8_t bail;
224
225 QLA_VHA_MARK_BUSY(vha, bail);
226 if (unlikely(bail))
227 return NULL;
228
229 sp = mempool_alloc(ha->srb_mempool, flag);
230 if (!sp)
231 goto done;
232
233 memset(sp, 0, sizeof(*sp));
234 sp->fcport = fcport;
235 sp->iocbs = 1;
236done:
237 if (!sp)
238 QLA_VHA_MARK_NOT_BUSY(vha);
239 return sp;
240}
241
242static inline void
Chad Dupuisb00ee7d2013-02-08 01:57:50 -0500243qla2x00_rel_sp(scsi_qla_host_t *vha, srb_t *sp)
244{
245 mempool_free(sp, vha->hw->srb_mempool);
246 QLA_VHA_MARK_NOT_BUSY(vha);
247}
248
249static inline void
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800250qla2x00_init_timer(srb_t *sp, unsigned long tmo)
251{
252 init_timer(&sp->u.iocb_cmd.timer);
253 sp->u.iocb_cmd.timer.expires = jiffies + tmo * HZ;
254 sp->u.iocb_cmd.timer.data = (unsigned long)sp;
255 sp->u.iocb_cmd.timer.function = qla2x00_sp_timeout;
256 add_timer(&sp->u.iocb_cmd.timer);
257 sp->free = qla2x00_sp_free;
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -0400258 if ((IS_QLAFX00(sp->fcport->vha->hw)) &&
259 (sp->type == SRB_FXIOCB_DCMD))
260 init_completion(&sp->u.iocb_cmd.u.fxiocb.fxiocb_comp);
Himanshu Madhani6eb54712015-12-17 14:57:00 -0500261 if (sp->type == SRB_ELS_DCMD)
262 init_completion(&sp->u.iocb_cmd.u.els_logo.comp);
Giridhar Malavali9ba56b92012-02-09 11:15:36 -0800263}
Chad Dupuis642ef982012-02-09 11:15:57 -0800264
265static inline int
266qla2x00_gid_list_size(struct qla_hw_data *ha)
267{
Giridhar Malavali8ae6d9c2013-03-28 08:21:23 -0400268 if (IS_QLAFX00(ha))
269 return sizeof(uint32_t) * 32;
270 else
271 return sizeof(struct gid_list_info) * ha->max_fibre_devices;
Chad Dupuis642ef982012-02-09 11:15:57 -0800272}
Chad Dupuis3c290d02013-01-30 03:34:38 -0500273
274static inline void
gurinder.shergill@hp.com36439832013-04-23 10:13:17 -0700275qla2x00_handle_mbx_completion(struct qla_hw_data *ha, int status)
276{
277 if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) &&
278 (status & MBX_INTERRUPT) && ha->flags.mbox_int) {
279 set_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
280 clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
281 complete(&ha->mbx_intr_comp);
282 }
283}
Chad Dupuise05fe292014-09-25 05:16:59 -0400284
285static inline void
286qla2x00_set_retry_delay_timestamp(fc_port_t *fcport, uint16_t retry_delay)
287{
288 if (retry_delay)
289 fcport->retry_delay_timestamp = jiffies +
290 (retry_delay * HZ / 10);
291}