diff options
Diffstat (limited to 'drivers/scsi')
250 files changed, 58329 insertions, 615 deletions
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 82bb3b2d207a..e11cca4c784c 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig | |||
@@ -366,6 +366,7 @@ config ISCSI_TCP | |||
366 | 366 | ||
367 | source "drivers/scsi/cxgb3i/Kconfig" | 367 | source "drivers/scsi/cxgb3i/Kconfig" |
368 | source "drivers/scsi/bnx2i/Kconfig" | 368 | source "drivers/scsi/bnx2i/Kconfig" |
369 | source "drivers/scsi/be2iscsi/Kconfig" | ||
369 | 370 | ||
370 | config SGIWD93_SCSI | 371 | config SGIWD93_SCSI |
371 | tristate "SGI WD93C93 SCSI Driver" | 372 | tristate "SGI WD93C93 SCSI Driver" |
@@ -1827,6 +1828,16 @@ config SCSI_SRP | |||
1827 | To compile this driver as a module, choose M here: the | 1828 | To compile this driver as a module, choose M here: the |
1828 | module will be called libsrp. | 1829 | module will be called libsrp. |
1829 | 1830 | ||
1831 | config SCSI_BFA_FC | ||
1832 | tristate "Brocade BFA Fibre Channel Support" | ||
1833 | depends on PCI && SCSI | ||
1834 | select SCSI_FC_ATTRS | ||
1835 | help | ||
1836 | This bfa driver supports all Brocade PCIe FC/FCOE host adapters. | ||
1837 | |||
1838 | To compile this driver as a module, choose M here. The module will | ||
1839 | be called bfa. | ||
1840 | |||
1830 | endif # SCSI_LOWLEVEL | 1841 | endif # SCSI_LOWLEVEL |
1831 | 1842 | ||
1832 | source "drivers/scsi/pcmcia/Kconfig" | 1843 | source "drivers/scsi/pcmcia/Kconfig" |
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 61a94af3cee7..3ad61db5e3fa 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile | |||
@@ -86,6 +86,7 @@ obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o | |||
86 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/ | 86 | obj-$(CONFIG_SCSI_QLA_FC) += qla2xxx/ |
87 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx/ | 87 | obj-$(CONFIG_SCSI_QLA_ISCSI) += qla4xxx/ |
88 | obj-$(CONFIG_SCSI_LPFC) += lpfc/ | 88 | obj-$(CONFIG_SCSI_LPFC) += lpfc/ |
89 | obj-$(CONFIG_SCSI_BFA_FC) += bfa/ | ||
89 | obj-$(CONFIG_SCSI_PAS16) += pas16.o | 90 | obj-$(CONFIG_SCSI_PAS16) += pas16.o |
90 | obj-$(CONFIG_SCSI_T128) += t128.o | 91 | obj-$(CONFIG_SCSI_T128) += t128.o |
91 | obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o | 92 | obj-$(CONFIG_SCSI_DMX3191D) += dmx3191d.o |
@@ -130,6 +131,7 @@ obj-$(CONFIG_SCSI_MVSAS) += mvsas/ | |||
130 | obj-$(CONFIG_PS3_ROM) += ps3rom.o | 131 | obj-$(CONFIG_PS3_ROM) += ps3rom.o |
131 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/ | 132 | obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/ |
132 | obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/ | 133 | obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/ |
134 | obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/ | ||
133 | obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o | 135 | obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o |
134 | 136 | ||
135 | obj-$(CONFIG_ARM) += arm/ | 137 | obj-$(CONFIG_ARM) += arm/ |
diff --git a/drivers/scsi/be2iscsi/Kconfig b/drivers/scsi/be2iscsi/Kconfig new file mode 100644 index 000000000000..2952fcd008ea --- /dev/null +++ b/drivers/scsi/be2iscsi/Kconfig | |||
@@ -0,0 +1,8 @@ | |||
1 | config BE2ISCSI | ||
2 | tristate "ServerEngines' 10Gbps iSCSI - BladeEngine 2" | ||
3 | depends on PCI && SCSI | ||
4 | select SCSI_ISCSI_ATTRS | ||
5 | |||
6 | help | ||
7 | This driver implements the iSCSI functionality for ServerEngines' | ||
8 | 10Gbps Storage adapter - BladeEngine 2. | ||
diff --git a/drivers/scsi/be2iscsi/Makefile b/drivers/scsi/be2iscsi/Makefile new file mode 100644 index 000000000000..c11f443e3f83 --- /dev/null +++ b/drivers/scsi/be2iscsi/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile to build the iSCSI driver for ServerEngine's BladeEngine. | ||
3 | # | ||
4 | # | ||
5 | |||
6 | obj-$(CONFIG_BE2ISCSI) += be2iscsi.o | ||
7 | |||
8 | be2iscsi-y := be_iscsi.o be_main.o be_mgmt.o be_cmds.o | ||
diff --git a/drivers/scsi/be2iscsi/be.h b/drivers/scsi/be2iscsi/be.h new file mode 100644 index 000000000000..b36020dcf012 --- /dev/null +++ b/drivers/scsi/be2iscsi/be.h | |||
@@ -0,0 +1,183 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Contact Information: | ||
11 | * linux-drivers@serverengines.com | ||
12 | * | ||
13 | * ServerEngines | ||
14 | * 209 N. Fair Oaks Ave | ||
15 | * Sunnyvale, CA 94085 | ||
16 | */ | ||
17 | |||
18 | #ifndef BEISCSI_H | ||
19 | #define BEISCSI_H | ||
20 | |||
21 | #include <linux/pci.h> | ||
22 | #include <linux/if_vlan.h> | ||
23 | |||
24 | #define FW_VER_LEN 32 | ||
25 | |||
26 | struct be_dma_mem { | ||
27 | void *va; | ||
28 | dma_addr_t dma; | ||
29 | u32 size; | ||
30 | }; | ||
31 | |||
32 | struct be_queue_info { | ||
33 | struct be_dma_mem dma_mem; | ||
34 | u16 len; | ||
35 | u16 entry_size; /* Size of an element in the queue */ | ||
36 | u16 id; | ||
37 | u16 tail, head; | ||
38 | bool created; | ||
39 | atomic_t used; /* Number of valid elements in the queue */ | ||
40 | }; | ||
41 | |||
42 | static inline u32 MODULO(u16 val, u16 limit) | ||
43 | { | ||
44 | WARN_ON(limit & (limit - 1)); | ||
45 | return val & (limit - 1); | ||
46 | } | ||
47 | |||
48 | static inline void index_inc(u16 *index, u16 limit) | ||
49 | { | ||
50 | *index = MODULO((*index + 1), limit); | ||
51 | } | ||
52 | |||
53 | static inline void *queue_head_node(struct be_queue_info *q) | ||
54 | { | ||
55 | return q->dma_mem.va + q->head * q->entry_size; | ||
56 | } | ||
57 | |||
58 | static inline void *queue_tail_node(struct be_queue_info *q) | ||
59 | { | ||
60 | return q->dma_mem.va + q->tail * q->entry_size; | ||
61 | } | ||
62 | |||
63 | static inline void queue_head_inc(struct be_queue_info *q) | ||
64 | { | ||
65 | index_inc(&q->head, q->len); | ||
66 | } | ||
67 | |||
68 | static inline void queue_tail_inc(struct be_queue_info *q) | ||
69 | { | ||
70 | index_inc(&q->tail, q->len); | ||
71 | } | ||
72 | |||
73 | /*ISCSI */ | ||
74 | |||
75 | struct be_eq_obj { | ||
76 | struct be_queue_info q; | ||
77 | char desc[32]; | ||
78 | |||
79 | /* Adaptive interrupt coalescing (AIC) info */ | ||
80 | bool enable_aic; | ||
81 | u16 min_eqd; /* in usecs */ | ||
82 | u16 max_eqd; /* in usecs */ | ||
83 | u16 cur_eqd; /* in usecs */ | ||
84 | }; | ||
85 | |||
86 | struct be_mcc_obj { | ||
87 | struct be_queue_info *q; | ||
88 | struct be_queue_info *cq; | ||
89 | }; | ||
90 | |||
91 | struct be_ctrl_info { | ||
92 | u8 __iomem *csr; | ||
93 | u8 __iomem *db; /* Door Bell */ | ||
94 | u8 __iomem *pcicfg; /* PCI config space */ | ||
95 | struct pci_dev *pdev; | ||
96 | |||
97 | /* Mbox used for cmd request/response */ | ||
98 | spinlock_t mbox_lock; /* For serializing mbox cmds to BE card */ | ||
99 | struct be_dma_mem mbox_mem; | ||
100 | /* Mbox mem is adjusted to align to 16 bytes. The allocated addr | ||
101 | * is stored for freeing purpose */ | ||
102 | struct be_dma_mem mbox_mem_alloced; | ||
103 | |||
104 | /* MCC Rings */ | ||
105 | struct be_mcc_obj mcc_obj; | ||
106 | spinlock_t mcc_lock; /* For serializing mcc cmds to BE card */ | ||
107 | spinlock_t mcc_cq_lock; | ||
108 | |||
109 | /* MCC Async callback */ | ||
110 | void (*async_cb) (void *adapter, bool link_up); | ||
111 | void *adapter_ctxt; | ||
112 | }; | ||
113 | |||
114 | #include "be_cmds.h" | ||
115 | |||
116 | #define PAGE_SHIFT_4K 12 | ||
117 | #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) | ||
118 | |||
119 | /* Returns number of pages spanned by the data starting at the given addr */ | ||
120 | #define PAGES_4K_SPANNED(_address, size) \ | ||
121 | ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ | ||
122 | (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K)) | ||
123 | |||
124 | /* Byte offset into the page corresponding to given address */ | ||
125 | #define OFFSET_IN_PAGE(addr) \ | ||
126 | ((size_t)(addr) & (PAGE_SIZE_4K-1)) | ||
127 | |||
128 | /* Returns bit offset within a DWORD of a bitfield */ | ||
129 | #define AMAP_BIT_OFFSET(_struct, field) \ | ||
130 | (((size_t)&(((_struct *)0)->field))%32) | ||
131 | |||
132 | /* Returns the bit mask of the field that is NOT shifted into location. */ | ||
133 | static inline u32 amap_mask(u32 bitsize) | ||
134 | { | ||
135 | return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1); | ||
136 | } | ||
137 | |||
138 | static inline void amap_set(void *ptr, u32 dw_offset, u32 mask, | ||
139 | u32 offset, u32 value) | ||
140 | { | ||
141 | u32 *dw = (u32 *) ptr + dw_offset; | ||
142 | *dw &= ~(mask << offset); | ||
143 | *dw |= (mask & value) << offset; | ||
144 | } | ||
145 | |||
146 | #define AMAP_SET_BITS(_struct, field, ptr, val) \ | ||
147 | amap_set(ptr, \ | ||
148 | offsetof(_struct, field)/32, \ | ||
149 | amap_mask(sizeof(((_struct *)0)->field)), \ | ||
150 | AMAP_BIT_OFFSET(_struct, field), \ | ||
151 | val) | ||
152 | |||
153 | static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) | ||
154 | { | ||
155 | u32 *dw = ptr; | ||
156 | return mask & (*(dw + dw_offset) >> offset); | ||
157 | } | ||
158 | |||
159 | #define AMAP_GET_BITS(_struct, field, ptr) \ | ||
160 | amap_get(ptr, \ | ||
161 | offsetof(_struct, field)/32, \ | ||
162 | amap_mask(sizeof(((_struct *)0)->field)), \ | ||
163 | AMAP_BIT_OFFSET(_struct, field)) | ||
164 | |||
165 | #define be_dws_cpu_to_le(wrb, len) swap_dws(wrb, len) | ||
166 | #define be_dws_le_to_cpu(wrb, len) swap_dws(wrb, len) | ||
167 | static inline void swap_dws(void *wrb, int len) | ||
168 | { | ||
169 | #ifdef __BIG_ENDIAN | ||
170 | u32 *dw = wrb; | ||
171 | WARN_ON(len % 4); | ||
172 | do { | ||
173 | *dw = cpu_to_le32(*dw); | ||
174 | dw++; | ||
175 | len -= 4; | ||
176 | } while (len); | ||
177 | #endif /* __BIG_ENDIAN */ | ||
178 | } | ||
179 | |||
180 | extern void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm, | ||
181 | u16 num_popped); | ||
182 | |||
183 | #endif /* BEISCSI_H */ | ||
diff --git a/drivers/scsi/be2iscsi/be_cmds.c b/drivers/scsi/be2iscsi/be_cmds.c new file mode 100644 index 000000000000..08007b6e42df --- /dev/null +++ b/drivers/scsi/be2iscsi/be_cmds.c | |||
@@ -0,0 +1,523 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Contact Information: | ||
11 | * linux-drivers@serverengines.com | ||
12 | * | ||
13 | * ServerEngines | ||
14 | * 209 N. Fair Oaks Ave | ||
15 | * Sunnyvale, CA 94085 | ||
16 | */ | ||
17 | |||
18 | #include "be.h" | ||
19 | #include "be_mgmt.h" | ||
20 | #include "be_main.h" | ||
21 | |||
22 | static inline bool be_mcc_compl_is_new(struct be_mcc_compl *compl) | ||
23 | { | ||
24 | if (compl->flags != 0) { | ||
25 | compl->flags = le32_to_cpu(compl->flags); | ||
26 | WARN_ON((compl->flags & CQE_FLAGS_VALID_MASK) == 0); | ||
27 | return true; | ||
28 | } else | ||
29 | return false; | ||
30 | } | ||
31 | |||
32 | static inline void be_mcc_compl_use(struct be_mcc_compl *compl) | ||
33 | { | ||
34 | compl->flags = 0; | ||
35 | } | ||
36 | |||
37 | static int be_mcc_compl_process(struct be_ctrl_info *ctrl, | ||
38 | struct be_mcc_compl *compl) | ||
39 | { | ||
40 | u16 compl_status, extd_status; | ||
41 | |||
42 | be_dws_le_to_cpu(compl, 4); | ||
43 | |||
44 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | ||
45 | CQE_STATUS_COMPL_MASK; | ||
46 | if (compl_status != MCC_STATUS_SUCCESS) { | ||
47 | extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & | ||
48 | CQE_STATUS_EXTD_MASK; | ||
49 | dev_err(&ctrl->pdev->dev, | ||
50 | "error in cmd completion: status(compl/extd)=%d/%d\n", | ||
51 | compl_status, extd_status); | ||
52 | return -1; | ||
53 | } | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static inline bool is_link_state_evt(u32 trailer) | ||
58 | { | ||
59 | return (((trailer >> ASYNC_TRAILER_EVENT_CODE_SHIFT) & | ||
60 | ASYNC_TRAILER_EVENT_CODE_MASK) == ASYNC_EVENT_CODE_LINK_STATE); | ||
61 | } | ||
62 | |||
63 | void beiscsi_cq_notify(struct be_ctrl_info *ctrl, u16 qid, bool arm, | ||
64 | u16 num_popped) | ||
65 | { | ||
66 | u32 val = 0; | ||
67 | val |= qid & DB_CQ_RING_ID_MASK; | ||
68 | if (arm) | ||
69 | val |= 1 << DB_CQ_REARM_SHIFT; | ||
70 | val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; | ||
71 | iowrite32(val, ctrl->db + DB_CQ_OFFSET); | ||
72 | } | ||
73 | |||
74 | static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl) | ||
75 | { | ||
76 | #define long_delay 2000 | ||
77 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | ||
78 | int cnt = 0, wait = 5; /* in usecs */ | ||
79 | u32 ready; | ||
80 | |||
81 | do { | ||
82 | ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; | ||
83 | if (ready) | ||
84 | break; | ||
85 | |||
86 | if (cnt > 6000000) { | ||
87 | dev_err(&ctrl->pdev->dev, "mbox_db poll timed out\n"); | ||
88 | return -1; | ||
89 | } | ||
90 | |||
91 | if (cnt > 50) { | ||
92 | wait = long_delay; | ||
93 | mdelay(long_delay / 1000); | ||
94 | } else | ||
95 | udelay(wait); | ||
96 | cnt += wait; | ||
97 | } while (true); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | int be_mbox_notify(struct be_ctrl_info *ctrl) | ||
102 | { | ||
103 | int status; | ||
104 | u32 val = 0; | ||
105 | void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; | ||
106 | struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; | ||
107 | struct be_mcc_mailbox *mbox = mbox_mem->va; | ||
108 | struct be_mcc_compl *compl = &mbox->compl; | ||
109 | |||
110 | val &= ~MPU_MAILBOX_DB_RDY_MASK; | ||
111 | val |= MPU_MAILBOX_DB_HI_MASK; | ||
112 | val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; | ||
113 | iowrite32(val, db); | ||
114 | |||
115 | status = be_mbox_db_ready_wait(ctrl); | ||
116 | if (status != 0) { | ||
117 | SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 1\n"); | ||
118 | return status; | ||
119 | } | ||
120 | val = 0; | ||
121 | val &= ~MPU_MAILBOX_DB_RDY_MASK; | ||
122 | val &= ~MPU_MAILBOX_DB_HI_MASK; | ||
123 | val |= (u32) (mbox_mem->dma >> 4) << 2; | ||
124 | iowrite32(val, db); | ||
125 | |||
126 | status = be_mbox_db_ready_wait(ctrl); | ||
127 | if (status != 0) { | ||
128 | SE_DEBUG(DBG_LVL_1, " be_mbox_db_ready_wait failed 2\n"); | ||
129 | return status; | ||
130 | } | ||
131 | if (be_mcc_compl_is_new(compl)) { | ||
132 | status = be_mcc_compl_process(ctrl, &mbox->compl); | ||
133 | be_mcc_compl_use(compl); | ||
134 | if (status) { | ||
135 | SE_DEBUG(DBG_LVL_1, "After be_mcc_compl_process \n"); | ||
136 | return status; | ||
137 | } | ||
138 | } else { | ||
139 | dev_err(&ctrl->pdev->dev, "invalid mailbox completion\n"); | ||
140 | return -1; | ||
141 | } | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, | ||
146 | bool embedded, u8 sge_cnt) | ||
147 | { | ||
148 | if (embedded) | ||
149 | wrb->embedded |= MCC_WRB_EMBEDDED_MASK; | ||
150 | else | ||
151 | wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << | ||
152 | MCC_WRB_SGE_CNT_SHIFT; | ||
153 | wrb->payload_length = payload_len; | ||
154 | be_dws_cpu_to_le(wrb, 8); | ||
155 | } | ||
156 | |||
157 | void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, | ||
158 | u8 subsystem, u8 opcode, int cmd_len) | ||
159 | { | ||
160 | req_hdr->opcode = opcode; | ||
161 | req_hdr->subsystem = subsystem; | ||
162 | req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); | ||
163 | } | ||
164 | |||
165 | static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, | ||
166 | struct be_dma_mem *mem) | ||
167 | { | ||
168 | int i, buf_pages; | ||
169 | u64 dma = (u64) mem->dma; | ||
170 | |||
171 | buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); | ||
172 | for (i = 0; i < buf_pages; i++) { | ||
173 | pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); | ||
174 | pages[i].hi = cpu_to_le32(upper_32_bits(dma)); | ||
175 | dma += PAGE_SIZE_4K; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | static u32 eq_delay_to_mult(u32 usec_delay) | ||
180 | { | ||
181 | #define MAX_INTR_RATE 651042 | ||
182 | const u32 round = 10; | ||
183 | u32 multiplier; | ||
184 | |||
185 | if (usec_delay == 0) | ||
186 | multiplier = 0; | ||
187 | else { | ||
188 | u32 interrupt_rate = 1000000 / usec_delay; | ||
189 | if (interrupt_rate == 0) | ||
190 | multiplier = 1023; | ||
191 | else { | ||
192 | multiplier = (MAX_INTR_RATE - interrupt_rate) * round; | ||
193 | multiplier /= interrupt_rate; | ||
194 | multiplier = (multiplier + round / 2) / round; | ||
195 | multiplier = min(multiplier, (u32) 1023); | ||
196 | } | ||
197 | } | ||
198 | return multiplier; | ||
199 | } | ||
200 | |||
201 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) | ||
202 | { | ||
203 | return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; | ||
204 | } | ||
205 | |||
206 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, | ||
207 | struct be_queue_info *eq, int eq_delay) | ||
208 | { | ||
209 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
210 | struct be_cmd_req_eq_create *req = embedded_payload(wrb); | ||
211 | struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); | ||
212 | struct be_dma_mem *q_mem = &eq->dma_mem; | ||
213 | int status; | ||
214 | |||
215 | spin_lock(&ctrl->mbox_lock); | ||
216 | memset(wrb, 0, sizeof(*wrb)); | ||
217 | |||
218 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
219 | |||
220 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
221 | OPCODE_COMMON_EQ_CREATE, sizeof(*req)); | ||
222 | |||
223 | req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); | ||
224 | |||
225 | AMAP_SET_BITS(struct amap_eq_context, func, req->context, | ||
226 | PCI_FUNC(ctrl->pdev->devfn)); | ||
227 | AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); | ||
228 | AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); | ||
229 | AMAP_SET_BITS(struct amap_eq_context, count, req->context, | ||
230 | __ilog2_u32(eq->len / 256)); | ||
231 | AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, | ||
232 | eq_delay_to_mult(eq_delay)); | ||
233 | be_dws_cpu_to_le(req->context, sizeof(req->context)); | ||
234 | |||
235 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
236 | |||
237 | status = be_mbox_notify(ctrl); | ||
238 | if (!status) { | ||
239 | eq->id = le16_to_cpu(resp->eq_id); | ||
240 | eq->created = true; | ||
241 | } | ||
242 | spin_unlock(&ctrl->mbox_lock); | ||
243 | return status; | ||
244 | } | ||
245 | |||
246 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl) | ||
247 | { | ||
248 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
249 | int status; | ||
250 | u8 *endian_check; | ||
251 | |||
252 | spin_lock(&ctrl->mbox_lock); | ||
253 | memset(wrb, 0, sizeof(*wrb)); | ||
254 | |||
255 | endian_check = (u8 *) wrb; | ||
256 | *endian_check++ = 0xFF; | ||
257 | *endian_check++ = 0x12; | ||
258 | *endian_check++ = 0x34; | ||
259 | *endian_check++ = 0xFF; | ||
260 | *endian_check++ = 0xFF; | ||
261 | *endian_check++ = 0x56; | ||
262 | *endian_check++ = 0x78; | ||
263 | *endian_check++ = 0xFF; | ||
264 | be_dws_cpu_to_le(wrb, sizeof(*wrb)); | ||
265 | |||
266 | status = be_mbox_notify(ctrl); | ||
267 | if (status) | ||
268 | SE_DEBUG(DBG_LVL_1, "be_cmd_fw_initialize Failed \n"); | ||
269 | |||
270 | spin_unlock(&ctrl->mbox_lock); | ||
271 | return status; | ||
272 | } | ||
273 | |||
274 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | ||
275 | struct be_queue_info *cq, struct be_queue_info *eq, | ||
276 | bool sol_evts, bool no_delay, int coalesce_wm) | ||
277 | { | ||
278 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
279 | struct be_cmd_req_cq_create *req = embedded_payload(wrb); | ||
280 | struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); | ||
281 | struct be_dma_mem *q_mem = &cq->dma_mem; | ||
282 | void *ctxt = &req->context; | ||
283 | int status; | ||
284 | |||
285 | spin_lock(&ctrl->mbox_lock); | ||
286 | memset(wrb, 0, sizeof(*wrb)); | ||
287 | |||
288 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
289 | |||
290 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
291 | OPCODE_COMMON_CQ_CREATE, sizeof(*req)); | ||
292 | |||
293 | if (!q_mem->va) | ||
294 | SE_DEBUG(DBG_LVL_1, "uninitialized q_mem->va\n"); | ||
295 | |||
296 | req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); | ||
297 | |||
298 | AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm); | ||
299 | AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); | ||
300 | AMAP_SET_BITS(struct amap_cq_context, count, ctxt, | ||
301 | __ilog2_u32(cq->len / 256)); | ||
302 | AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); | ||
303 | AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); | ||
304 | AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); | ||
305 | AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); | ||
306 | AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); | ||
307 | AMAP_SET_BITS(struct amap_cq_context, func, ctxt, | ||
308 | PCI_FUNC(ctrl->pdev->devfn)); | ||
309 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | ||
310 | |||
311 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
312 | |||
313 | status = be_mbox_notify(ctrl); | ||
314 | if (!status) { | ||
315 | cq->id = le16_to_cpu(resp->cq_id); | ||
316 | cq->created = true; | ||
317 | } else | ||
318 | SE_DEBUG(DBG_LVL_1, "In be_cmd_cq_create, status=ox%08x \n", | ||
319 | status); | ||
320 | spin_unlock(&ctrl->mbox_lock); | ||
321 | |||
322 | return status; | ||
323 | } | ||
324 | |||
325 | static u32 be_encoded_q_len(int q_len) | ||
326 | { | ||
327 | u32 len_encoded = fls(q_len); /* log2(len) + 1 */ | ||
328 | if (len_encoded == 16) | ||
329 | len_encoded = 0; | ||
330 | return len_encoded; | ||
331 | } | ||
332 | int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | ||
333 | int queue_type) | ||
334 | { | ||
335 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
336 | struct be_cmd_req_q_destroy *req = embedded_payload(wrb); | ||
337 | u8 subsys = 0, opcode = 0; | ||
338 | int status; | ||
339 | |||
340 | spin_lock(&ctrl->mbox_lock); | ||
341 | memset(wrb, 0, sizeof(*wrb)); | ||
342 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
343 | |||
344 | switch (queue_type) { | ||
345 | case QTYPE_EQ: | ||
346 | subsys = CMD_SUBSYSTEM_COMMON; | ||
347 | opcode = OPCODE_COMMON_EQ_DESTROY; | ||
348 | break; | ||
349 | case QTYPE_CQ: | ||
350 | subsys = CMD_SUBSYSTEM_COMMON; | ||
351 | opcode = OPCODE_COMMON_CQ_DESTROY; | ||
352 | break; | ||
353 | case QTYPE_WRBQ: | ||
354 | subsys = CMD_SUBSYSTEM_ISCSI; | ||
355 | opcode = OPCODE_COMMON_ISCSI_WRBQ_DESTROY; | ||
356 | break; | ||
357 | case QTYPE_DPDUQ: | ||
358 | subsys = CMD_SUBSYSTEM_ISCSI; | ||
359 | opcode = OPCODE_COMMON_ISCSI_DEFQ_DESTROY; | ||
360 | break; | ||
361 | case QTYPE_SGL: | ||
362 | subsys = CMD_SUBSYSTEM_ISCSI; | ||
363 | opcode = OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES; | ||
364 | break; | ||
365 | default: | ||
366 | spin_unlock(&ctrl->mbox_lock); | ||
367 | BUG(); | ||
368 | return -1; | ||
369 | } | ||
370 | be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); | ||
371 | if (queue_type != QTYPE_SGL) | ||
372 | req->id = cpu_to_le16(q->id); | ||
373 | |||
374 | status = be_mbox_notify(ctrl); | ||
375 | |||
376 | spin_unlock(&ctrl->mbox_lock); | ||
377 | return status; | ||
378 | } | ||
379 | |||
380 | int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr) | ||
381 | { | ||
382 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
383 | struct be_cmd_req_get_mac_addr *req = embedded_payload(wrb); | ||
384 | int status; | ||
385 | |||
386 | spin_lock(&ctrl->mbox_lock); | ||
387 | memset(wrb, 0, sizeof(*wrb)); | ||
388 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
389 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
390 | OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG, | ||
391 | sizeof(*req)); | ||
392 | |||
393 | status = be_mbox_notify(ctrl); | ||
394 | if (!status) { | ||
395 | struct be_cmd_resp_get_mac_addr *resp = embedded_payload(wrb); | ||
396 | |||
397 | memcpy(mac_addr, resp->mac_address, ETH_ALEN); | ||
398 | } | ||
399 | |||
400 | spin_unlock(&ctrl->mbox_lock); | ||
401 | return status; | ||
402 | } | ||
403 | |||
404 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | ||
405 | struct be_queue_info *cq, | ||
406 | struct be_queue_info *dq, int length, | ||
407 | int entry_size) | ||
408 | { | ||
409 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
410 | struct be_defq_create_req *req = embedded_payload(wrb); | ||
411 | struct be_dma_mem *q_mem = &dq->dma_mem; | ||
412 | void *ctxt = &req->context; | ||
413 | int status; | ||
414 | |||
415 | spin_lock(&ctrl->mbox_lock); | ||
416 | memset(wrb, 0, sizeof(*wrb)); | ||
417 | |||
418 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
419 | |||
420 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
421 | OPCODE_COMMON_ISCSI_DEFQ_CREATE, sizeof(*req)); | ||
422 | |||
423 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | ||
424 | AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid, ctxt, 0); | ||
425 | AMAP_SET_BITS(struct amap_be_default_pdu_context, rx_pdid_valid, ctxt, | ||
426 | 1); | ||
427 | AMAP_SET_BITS(struct amap_be_default_pdu_context, pci_func_id, ctxt, | ||
428 | PCI_FUNC(ctrl->pdev->devfn)); | ||
429 | AMAP_SET_BITS(struct amap_be_default_pdu_context, ring_size, ctxt, | ||
430 | be_encoded_q_len(length / sizeof(struct phys_addr))); | ||
431 | AMAP_SET_BITS(struct amap_be_default_pdu_context, default_buffer_size, | ||
432 | ctxt, entry_size); | ||
433 | AMAP_SET_BITS(struct amap_be_default_pdu_context, cq_id_recv, ctxt, | ||
434 | cq->id); | ||
435 | |||
436 | be_dws_cpu_to_le(ctxt, sizeof(req->context)); | ||
437 | |||
438 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
439 | |||
440 | status = be_mbox_notify(ctrl); | ||
441 | if (!status) { | ||
442 | struct be_defq_create_resp *resp = embedded_payload(wrb); | ||
443 | |||
444 | dq->id = le16_to_cpu(resp->id); | ||
445 | dq->created = true; | ||
446 | } | ||
447 | spin_unlock(&ctrl->mbox_lock); | ||
448 | |||
449 | return status; | ||
450 | } | ||
451 | |||
452 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | ||
453 | struct be_queue_info *wrbq) | ||
454 | { | ||
455 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
456 | struct be_wrbq_create_req *req = embedded_payload(wrb); | ||
457 | struct be_wrbq_create_resp *resp = embedded_payload(wrb); | ||
458 | int status; | ||
459 | |||
460 | spin_lock(&ctrl->mbox_lock); | ||
461 | memset(wrb, 0, sizeof(*wrb)); | ||
462 | |||
463 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
464 | |||
465 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
466 | OPCODE_COMMON_ISCSI_WRBQ_CREATE, sizeof(*req)); | ||
467 | req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); | ||
468 | be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); | ||
469 | |||
470 | status = be_mbox_notify(ctrl); | ||
471 | if (!status) | ||
472 | wrbq->id = le16_to_cpu(resp->cid); | ||
473 | spin_unlock(&ctrl->mbox_lock); | ||
474 | return status; | ||
475 | } | ||
476 | |||
477 | int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, | ||
478 | struct be_dma_mem *q_mem, | ||
479 | u32 page_offset, u32 num_pages) | ||
480 | { | ||
481 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
482 | struct be_post_sgl_pages_req *req = embedded_payload(wrb); | ||
483 | int status; | ||
484 | unsigned int curr_pages; | ||
485 | u32 internal_page_offset = 0; | ||
486 | u32 temp_num_pages = num_pages; | ||
487 | |||
488 | if (num_pages == 0xff) | ||
489 | num_pages = 1; | ||
490 | |||
491 | spin_lock(&ctrl->mbox_lock); | ||
492 | do { | ||
493 | memset(wrb, 0, sizeof(*wrb)); | ||
494 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
495 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
496 | OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES, | ||
497 | sizeof(*req)); | ||
498 | curr_pages = BE_NUMBER_OF_FIELD(struct be_post_sgl_pages_req, | ||
499 | pages); | ||
500 | req->num_pages = min(num_pages, curr_pages); | ||
501 | req->page_offset = page_offset; | ||
502 | be_cmd_page_addrs_prepare(req->pages, req->num_pages, q_mem); | ||
503 | q_mem->dma = q_mem->dma + (req->num_pages * PAGE_SIZE); | ||
504 | internal_page_offset += req->num_pages; | ||
505 | page_offset += req->num_pages; | ||
506 | num_pages -= req->num_pages; | ||
507 | |||
508 | if (temp_num_pages == 0xff) | ||
509 | req->num_pages = temp_num_pages; | ||
510 | |||
511 | status = be_mbox_notify(ctrl); | ||
512 | if (status) { | ||
513 | SE_DEBUG(DBG_LVL_1, | ||
514 | "FW CMD to map iscsi frags failed.\n"); | ||
515 | goto error; | ||
516 | } | ||
517 | } while (num_pages > 0); | ||
518 | error: | ||
519 | spin_unlock(&ctrl->mbox_lock); | ||
520 | if (status != 0) | ||
521 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); | ||
522 | return status; | ||
523 | } | ||
diff --git a/drivers/scsi/be2iscsi/be_cmds.h b/drivers/scsi/be2iscsi/be_cmds.h new file mode 100644 index 000000000000..c20d686cbb43 --- /dev/null +++ b/drivers/scsi/be2iscsi/be_cmds.h | |||
@@ -0,0 +1,877 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Contact Information: | ||
11 | * linux-drivers@serverengines.com | ||
12 | * | ||
13 | * ServerEngines | ||
14 | * 209 N. Fair Oaks Ave | ||
15 | * Sunnyvale, CA 94085 | ||
16 | */ | ||
17 | |||
18 | #ifndef BEISCSI_CMDS_H | ||
19 | #define BEISCSI_CMDS_H | ||
20 | |||
21 | /** | ||
22 | * The driver sends configuration and managements command requests to the | ||
23 | * firmware in the BE. These requests are communicated to the processor | ||
24 | * using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one | ||
25 | * WRB inside a MAILBOX. | ||
26 | * The commands are serviced by the ARM processor in the BladeEngine's MPU. | ||
27 | */ | ||
28 | struct be_sge { | ||
29 | u32 pa_lo; | ||
30 | u32 pa_hi; | ||
31 | u32 len; | ||
32 | }; | ||
33 | |||
34 | #define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */ | ||
35 | #define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */ | ||
36 | struct be_mcc_wrb { | ||
37 | u32 embedded; /* dword 0 */ | ||
38 | u32 payload_length; /* dword 1 */ | ||
39 | u32 tag0; /* dword 2 */ | ||
40 | u32 tag1; /* dword 3 */ | ||
41 | u32 rsvd; /* dword 4 */ | ||
42 | union { | ||
43 | u8 embedded_payload[236]; /* used by embedded cmds */ | ||
44 | struct be_sge sgl[19]; /* used by non-embedded cmds */ | ||
45 | } payload; | ||
46 | }; | ||
47 | |||
48 | #define CQE_FLAGS_VALID_MASK (1 << 31) | ||
49 | #define CQE_FLAGS_ASYNC_MASK (1 << 30) | ||
50 | |||
51 | /* Completion Status */ | ||
52 | #define MCC_STATUS_SUCCESS 0x0 | ||
53 | |||
54 | #define CQE_STATUS_COMPL_MASK 0xFFFF | ||
55 | #define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ | ||
56 | #define CQE_STATUS_EXTD_MASK 0xFFFF | ||
57 | #define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ | ||
58 | |||
59 | struct be_mcc_compl { | ||
60 | u32 status; /* dword 0 */ | ||
61 | u32 tag0; /* dword 1 */ | ||
62 | u32 tag1; /* dword 2 */ | ||
63 | u32 flags; /* dword 3 */ | ||
64 | }; | ||
65 | |||
66 | /********* Mailbox door bell *************/ | ||
67 | /** | ||
68 | * Used for driver communication with the FW. | ||
69 | * The software must write this register twice to post any command. First, | ||
70 | * it writes the register with hi=1 and the upper bits of the physical address | ||
71 | * for the MAILBOX structure. Software must poll the ready bit until this | ||
72 | * is acknowledged. Then, sotware writes the register with hi=0 with the lower | ||
73 | * bits in the address. It must poll the ready bit until the command is | ||
74 | * complete. Upon completion, the MAILBOX will contain a valid completion | ||
75 | * queue entry. | ||
76 | */ | ||
77 | #define MPU_MAILBOX_DB_OFFSET 0x160 | ||
78 | #define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */ | ||
79 | #define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */ | ||
80 | |||
81 | /********** MPU semphore ******************/ | ||
82 | #define MPU_EP_SEMAPHORE_OFFSET 0xac | ||
83 | #define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF | ||
84 | #define EP_SEMAPHORE_POST_ERR_MASK 0x1 | ||
85 | #define EP_SEMAPHORE_POST_ERR_SHIFT 31 | ||
86 | |||
87 | /********** MCC door bell ************/ | ||
88 | #define DB_MCCQ_OFFSET 0x140 | ||
89 | #define DB_MCCQ_RING_ID_MASK 0x7FF /* bits 0 - 10 */ | ||
90 | /* Number of entries posted */ | ||
91 | #define DB_MCCQ_NUM_POSTED_SHIFT 16 /* bits 16 - 29 */ | ||
92 | |||
93 | /* MPU semphore POST stage values */ | ||
94 | #define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ | ||
95 | |||
96 | /** | ||
97 | * When the async bit of mcc_compl is set, the last 4 bytes of | ||
98 | * mcc_compl is interpreted as follows: | ||
99 | */ | ||
100 | #define ASYNC_TRAILER_EVENT_CODE_SHIFT 8 /* bits 8 - 15 */ | ||
101 | #define ASYNC_TRAILER_EVENT_CODE_MASK 0xFF | ||
102 | #define ASYNC_EVENT_CODE_LINK_STATE 0x1 | ||
103 | struct be_async_event_trailer { | ||
104 | u32 code; | ||
105 | }; | ||
106 | |||
107 | enum { | ||
108 | ASYNC_EVENT_LINK_DOWN = 0x0, | ||
109 | ASYNC_EVENT_LINK_UP = 0x1 | ||
110 | }; | ||
111 | |||
112 | /** | ||
113 | * When the event code of an async trailer is link-state, the mcc_compl | ||
114 | * must be interpreted as follows | ||
115 | */ | ||
116 | struct be_async_event_link_state { | ||
117 | u8 physical_port; | ||
118 | u8 port_link_status; | ||
119 | u8 port_duplex; | ||
120 | u8 port_speed; | ||
121 | u8 port_fault; | ||
122 | u8 rsvd0[7]; | ||
123 | struct be_async_event_trailer trailer; | ||
124 | } __packed; | ||
125 | |||
126 | struct be_mcc_mailbox { | ||
127 | struct be_mcc_wrb wrb; | ||
128 | struct be_mcc_compl compl; | ||
129 | }; | ||
130 | |||
131 | /* Type of subsystems supported by FW */ | ||
132 | #define CMD_SUBSYSTEM_COMMON 0x1 | ||
133 | #define CMD_SUBSYSTEM_ISCSI 0x2 | ||
134 | #define CMD_SUBSYSTEM_ETH 0x3 | ||
135 | #define CMD_SUBSYSTEM_ISCSI_INI 0x6 | ||
136 | #define CMD_COMMON_TCP_UPLOAD 0x1 | ||
137 | |||
138 | /** | ||
139 | * List of common opcodes subsystem CMD_SUBSYSTEM_COMMON | ||
140 | * These opcodes are unique for each subsystem defined above | ||
141 | */ | ||
142 | #define OPCODE_COMMON_CQ_CREATE 12 | ||
143 | #define OPCODE_COMMON_EQ_CREATE 13 | ||
144 | #define OPCODE_COMMON_MCC_CREATE 21 | ||
145 | #define OPCODE_COMMON_GET_CNTL_ATTRIBUTES 32 | ||
146 | #define OPCODE_COMMON_GET_FW_VERSION 35 | ||
147 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 | ||
148 | #define OPCODE_COMMON_FIRMWARE_CONFIG 42 | ||
149 | #define OPCODE_COMMON_MCC_DESTROY 53 | ||
150 | #define OPCODE_COMMON_CQ_DESTROY 54 | ||
151 | #define OPCODE_COMMON_EQ_DESTROY 55 | ||
152 | #define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 | ||
153 | #define OPCODE_COMMON_FUNCTION_RESET 61 | ||
154 | |||
155 | /** | ||
156 | * LIST of opcodes that are common between Initiator and Target | ||
157 | * used by CMD_SUBSYSTEM_ISCSI | ||
158 | * These opcodes are unique for each subsystem defined above | ||
159 | */ | ||
160 | #define OPCODE_COMMON_ISCSI_CFG_POST_SGL_PAGES 2 | ||
161 | #define OPCODE_COMMON_ISCSI_CFG_REMOVE_SGL_PAGES 3 | ||
162 | #define OPCODE_COMMON_ISCSI_NTWK_GET_NIC_CONFIG 7 | ||
163 | #define OPCODE_COMMON_ISCSI_SET_FRAGNUM_BITS_FOR_SGL_CRA 61 | ||
164 | #define OPCODE_COMMON_ISCSI_DEFQ_CREATE 64 | ||
165 | #define OPCODE_COMMON_ISCSI_DEFQ_DESTROY 65 | ||
166 | #define OPCODE_COMMON_ISCSI_WRBQ_CREATE 66 | ||
167 | #define OPCODE_COMMON_ISCSI_WRBQ_DESTROY 67 | ||
168 | |||
169 | struct be_cmd_req_hdr { | ||
170 | u8 opcode; /* dword 0 */ | ||
171 | u8 subsystem; /* dword 0 */ | ||
172 | u8 port_number; /* dword 0 */ | ||
173 | u8 domain; /* dword 0 */ | ||
174 | u32 timeout; /* dword 1 */ | ||
175 | u32 request_length; /* dword 2 */ | ||
176 | u32 rsvd; /* dword 3 */ | ||
177 | }; | ||
178 | |||
179 | struct be_cmd_resp_hdr { | ||
180 | u32 info; /* dword 0 */ | ||
181 | u32 status; /* dword 1 */ | ||
182 | u32 response_length; /* dword 2 */ | ||
183 | u32 actual_resp_len; /* dword 3 */ | ||
184 | }; | ||
185 | |||
186 | struct phys_addr { | ||
187 | u32 lo; | ||
188 | u32 hi; | ||
189 | }; | ||
190 | |||
191 | /************************** | ||
192 | * BE Command definitions * | ||
193 | **************************/ | ||
194 | |||
195 | /** | ||
196 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
197 | * as a byte - used to calculate offset/shift/mask of each field | ||
198 | */ | ||
199 | struct amap_eq_context { | ||
200 | u8 cidx[13]; /* dword 0 */ | ||
201 | u8 rsvd0[3]; /* dword 0 */ | ||
202 | u8 epidx[13]; /* dword 0 */ | ||
203 | u8 valid; /* dword 0 */ | ||
204 | u8 rsvd1; /* dword 0 */ | ||
205 | u8 size; /* dword 0 */ | ||
206 | u8 pidx[13]; /* dword 1 */ | ||
207 | u8 rsvd2[3]; /* dword 1 */ | ||
208 | u8 pd[10]; /* dword 1 */ | ||
209 | u8 count[3]; /* dword 1 */ | ||
210 | u8 solevent; /* dword 1 */ | ||
211 | u8 stalled; /* dword 1 */ | ||
212 | u8 armed; /* dword 1 */ | ||
213 | u8 rsvd3[4]; /* dword 2 */ | ||
214 | u8 func[8]; /* dword 2 */ | ||
215 | u8 rsvd4; /* dword 2 */ | ||
216 | u8 delaymult[10]; /* dword 2 */ | ||
217 | u8 rsvd5[2]; /* dword 2 */ | ||
218 | u8 phase[2]; /* dword 2 */ | ||
219 | u8 nodelay; /* dword 2 */ | ||
220 | u8 rsvd6[4]; /* dword 2 */ | ||
221 | u8 rsvd7[32]; /* dword 3 */ | ||
222 | } __packed; | ||
223 | |||
224 | struct be_cmd_req_eq_create { | ||
225 | struct be_cmd_req_hdr hdr; /* dw[4] */ | ||
226 | u16 num_pages; /* sword */ | ||
227 | u16 rsvd0; /* sword */ | ||
228 | u8 context[sizeof(struct amap_eq_context) / 8]; /* dw[4] */ | ||
229 | struct phys_addr pages[8]; | ||
230 | } __packed; | ||
231 | |||
232 | struct be_cmd_resp_eq_create { | ||
233 | struct be_cmd_resp_hdr resp_hdr; | ||
234 | u16 eq_id; /* sword */ | ||
235 | u16 rsvd0; /* sword */ | ||
236 | } __packed; | ||
237 | |||
238 | struct mac_addr { | ||
239 | u16 size_of_struct; | ||
240 | u8 addr[ETH_ALEN]; | ||
241 | } __packed; | ||
242 | |||
243 | struct be_cmd_req_mac_query { | ||
244 | struct be_cmd_req_hdr hdr; | ||
245 | u8 type; | ||
246 | u8 permanent; | ||
247 | u16 if_id; | ||
248 | } __packed; | ||
249 | |||
250 | struct be_cmd_resp_mac_query { | ||
251 | struct be_cmd_resp_hdr hdr; | ||
252 | struct mac_addr mac; | ||
253 | }; | ||
254 | |||
255 | /******************** Create CQ ***************************/ | ||
256 | /** | ||
257 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
258 | * as a byte - used to calculate offset/shift/mask of each field | ||
259 | */ | ||
260 | struct amap_cq_context { | ||
261 | u8 cidx[11]; /* dword 0 */ | ||
262 | u8 rsvd0; /* dword 0 */ | ||
263 | u8 coalescwm[2]; /* dword 0 */ | ||
264 | u8 nodelay; /* dword 0 */ | ||
265 | u8 epidx[11]; /* dword 0 */ | ||
266 | u8 rsvd1; /* dword 0 */ | ||
267 | u8 count[2]; /* dword 0 */ | ||
268 | u8 valid; /* dword 0 */ | ||
269 | u8 solevent; /* dword 0 */ | ||
270 | u8 eventable; /* dword 0 */ | ||
271 | u8 pidx[11]; /* dword 1 */ | ||
272 | u8 rsvd2; /* dword 1 */ | ||
273 | u8 pd[10]; /* dword 1 */ | ||
274 | u8 eqid[8]; /* dword 1 */ | ||
275 | u8 stalled; /* dword 1 */ | ||
276 | u8 armed; /* dword 1 */ | ||
277 | u8 rsvd3[4]; /* dword 2 */ | ||
278 | u8 func[8]; /* dword 2 */ | ||
279 | u8 rsvd4[20]; /* dword 2 */ | ||
280 | u8 rsvd5[32]; /* dword 3 */ | ||
281 | } __packed; | ||
282 | |||
283 | struct be_cmd_req_cq_create { | ||
284 | struct be_cmd_req_hdr hdr; | ||
285 | u16 num_pages; | ||
286 | u16 rsvd0; | ||
287 | u8 context[sizeof(struct amap_cq_context) / 8]; | ||
288 | struct phys_addr pages[4]; | ||
289 | } __packed; | ||
290 | |||
291 | struct be_cmd_resp_cq_create { | ||
292 | struct be_cmd_resp_hdr hdr; | ||
293 | u16 cq_id; | ||
294 | u16 rsvd0; | ||
295 | } __packed; | ||
296 | |||
297 | /******************** Create MCCQ ***************************/ | ||
298 | /** | ||
299 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
300 | * as a byte - used to calculate offset/shift/mask of each field | ||
301 | */ | ||
302 | struct amap_mcc_context { | ||
303 | u8 con_index[14]; | ||
304 | u8 rsvd0[2]; | ||
305 | u8 ring_size[4]; | ||
306 | u8 fetch_wrb; | ||
307 | u8 fetch_r2t; | ||
308 | u8 cq_id[10]; | ||
309 | u8 prod_index[14]; | ||
310 | u8 fid[8]; | ||
311 | u8 pdid[9]; | ||
312 | u8 valid; | ||
313 | u8 rsvd1[32]; | ||
314 | u8 rsvd2[32]; | ||
315 | } __packed; | ||
316 | |||
317 | struct be_cmd_req_mcc_create { | ||
318 | struct be_cmd_req_hdr hdr; | ||
319 | u16 num_pages; | ||
320 | u16 rsvd0; | ||
321 | u8 context[sizeof(struct amap_mcc_context) / 8]; | ||
322 | struct phys_addr pages[8]; | ||
323 | } __packed; | ||
324 | |||
325 | struct be_cmd_resp_mcc_create { | ||
326 | struct be_cmd_resp_hdr hdr; | ||
327 | u16 id; | ||
328 | u16 rsvd0; | ||
329 | } __packed; | ||
330 | |||
331 | /******************** Q Destroy ***************************/ | ||
332 | /* Type of Queue to be destroyed */ | ||
333 | enum { | ||
334 | QTYPE_EQ = 1, | ||
335 | QTYPE_CQ, | ||
336 | QTYPE_MCCQ, | ||
337 | QTYPE_WRBQ, | ||
338 | QTYPE_DPDUQ, | ||
339 | QTYPE_SGL | ||
340 | }; | ||
341 | |||
342 | struct be_cmd_req_q_destroy { | ||
343 | struct be_cmd_req_hdr hdr; | ||
344 | u16 id; | ||
345 | u16 bypass_flush; /* valid only for rx q destroy */ | ||
346 | } __packed; | ||
347 | |||
348 | struct macaddr { | ||
349 | u8 byte[ETH_ALEN]; | ||
350 | }; | ||
351 | |||
352 | struct be_cmd_req_mcast_mac_config { | ||
353 | struct be_cmd_req_hdr hdr; | ||
354 | u16 num_mac; | ||
355 | u8 promiscuous; | ||
356 | u8 interface_id; | ||
357 | struct macaddr mac[32]; | ||
358 | } __packed; | ||
359 | |||
360 | static inline void *embedded_payload(struct be_mcc_wrb *wrb) | ||
361 | { | ||
362 | return wrb->payload.embedded_payload; | ||
363 | } | ||
364 | |||
365 | static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) | ||
366 | { | ||
367 | return &wrb->payload.sgl[0]; | ||
368 | } | ||
369 | |||
370 | /******************** Modify EQ Delay *******************/ | ||
371 | struct be_cmd_req_modify_eq_delay { | ||
372 | struct be_cmd_req_hdr hdr; | ||
373 | u32 num_eq; | ||
374 | struct { | ||
375 | u32 eq_id; | ||
376 | u32 phase; | ||
377 | u32 delay_multiplier; | ||
378 | } delay[8]; | ||
379 | } __packed; | ||
380 | |||
381 | /******************** Get MAC ADDR *******************/ | ||
382 | |||
383 | #define ETH_ALEN 6 | ||
384 | |||
385 | |||
386 | struct be_cmd_req_get_mac_addr { | ||
387 | struct be_cmd_req_hdr hdr; | ||
388 | u32 nic_port_count; | ||
389 | u32 speed; | ||
390 | u32 max_speed; | ||
391 | u32 link_state; | ||
392 | u32 max_frame_size; | ||
393 | u16 size_of_structure; | ||
394 | u8 mac_address[ETH_ALEN]; | ||
395 | u32 rsvd[23]; | ||
396 | }; | ||
397 | |||
398 | struct be_cmd_resp_get_mac_addr { | ||
399 | struct be_cmd_resp_hdr hdr; | ||
400 | u32 nic_port_count; | ||
401 | u32 speed; | ||
402 | u32 max_speed; | ||
403 | u32 link_state; | ||
404 | u32 max_frame_size; | ||
405 | u16 size_of_structure; | ||
406 | u8 mac_address[6]; | ||
407 | u32 rsvd[23]; | ||
408 | }; | ||
409 | |||
410 | int beiscsi_cmd_eq_create(struct be_ctrl_info *ctrl, | ||
411 | struct be_queue_info *eq, int eq_delay); | ||
412 | |||
413 | int beiscsi_cmd_cq_create(struct be_ctrl_info *ctrl, | ||
414 | struct be_queue_info *cq, struct be_queue_info *eq, | ||
415 | bool sol_evts, bool no_delay, | ||
416 | int num_cqe_dma_coalesce); | ||
417 | |||
418 | int beiscsi_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, | ||
419 | int type); | ||
420 | int be_poll_mcc(struct be_ctrl_info *ctrl); | ||
421 | unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl); | ||
422 | int be_cmd_get_mac_addr(struct be_ctrl_info *ctrl, u8 *mac_addr); | ||
423 | |||
424 | /*ISCSI Functuions */ | ||
425 | int be_cmd_fw_initialize(struct be_ctrl_info *ctrl); | ||
426 | |||
427 | struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem); | ||
428 | |||
429 | int be_mbox_notify(struct be_ctrl_info *ctrl); | ||
430 | |||
431 | int be_cmd_create_default_pdu_queue(struct be_ctrl_info *ctrl, | ||
432 | struct be_queue_info *cq, | ||
433 | struct be_queue_info *dq, int length, | ||
434 | int entry_size); | ||
435 | |||
436 | int be_cmd_iscsi_post_sgl_pages(struct be_ctrl_info *ctrl, | ||
437 | struct be_dma_mem *q_mem, u32 page_offset, | ||
438 | u32 num_pages); | ||
439 | |||
440 | int be_cmd_wrbq_create(struct be_ctrl_info *ctrl, struct be_dma_mem *q_mem, | ||
441 | struct be_queue_info *wrbq); | ||
442 | |||
443 | struct be_default_pdu_context { | ||
444 | u32 dw[4]; | ||
445 | } __packed; | ||
446 | |||
447 | struct amap_be_default_pdu_context { | ||
448 | u8 dbuf_cindex[13]; /* dword 0 */ | ||
449 | u8 rsvd0[3]; /* dword 0 */ | ||
450 | u8 ring_size[4]; /* dword 0 */ | ||
451 | u8 ring_state[4]; /* dword 0 */ | ||
452 | u8 rsvd1[8]; /* dword 0 */ | ||
453 | u8 dbuf_pindex[13]; /* dword 1 */ | ||
454 | u8 rsvd2; /* dword 1 */ | ||
455 | u8 pci_func_id[8]; /* dword 1 */ | ||
456 | u8 rx_pdid[9]; /* dword 1 */ | ||
457 | u8 rx_pdid_valid; /* dword 1 */ | ||
458 | u8 default_buffer_size[16]; /* dword 2 */ | ||
459 | u8 cq_id_recv[10]; /* dword 2 */ | ||
460 | u8 rx_pdid_not_valid; /* dword 2 */ | ||
461 | u8 rsvd3[5]; /* dword 2 */ | ||
462 | u8 rsvd4[32]; /* dword 3 */ | ||
463 | } __packed; | ||
464 | |||
465 | struct be_defq_create_req { | ||
466 | struct be_cmd_req_hdr hdr; | ||
467 | u16 num_pages; | ||
468 | u8 ulp_num; | ||
469 | u8 rsvd0; | ||
470 | struct be_default_pdu_context context; | ||
471 | struct phys_addr pages[8]; | ||
472 | } __packed; | ||
473 | |||
474 | struct be_defq_create_resp { | ||
475 | struct be_cmd_req_hdr hdr; | ||
476 | u16 id; | ||
477 | u16 rsvd0; | ||
478 | } __packed; | ||
479 | |||
480 | struct be_post_sgl_pages_req { | ||
481 | struct be_cmd_req_hdr hdr; | ||
482 | u16 num_pages; | ||
483 | u16 page_offset; | ||
484 | u32 rsvd0; | ||
485 | struct phys_addr pages[26]; | ||
486 | u32 rsvd1; | ||
487 | } __packed; | ||
488 | |||
489 | struct be_wrbq_create_req { | ||
490 | struct be_cmd_req_hdr hdr; | ||
491 | u16 num_pages; | ||
492 | u8 ulp_num; | ||
493 | u8 rsvd0; | ||
494 | struct phys_addr pages[8]; | ||
495 | } __packed; | ||
496 | |||
497 | struct be_wrbq_create_resp { | ||
498 | struct be_cmd_resp_hdr resp_hdr; | ||
499 | u16 cid; | ||
500 | u16 rsvd0; | ||
501 | } __packed; | ||
502 | |||
503 | #define SOL_CID_MASK 0x0000FFC0 | ||
504 | #define SOL_CODE_MASK 0x0000003F | ||
505 | #define SOL_WRB_INDEX_MASK 0x00FF0000 | ||
506 | #define SOL_CMD_WND_MASK 0xFF000000 | ||
507 | #define SOL_RES_CNT_MASK 0x7FFFFFFF | ||
508 | #define SOL_EXP_CMD_SN_MASK 0xFFFFFFFF | ||
509 | #define SOL_HW_STS_MASK 0x000000FF | ||
510 | #define SOL_STS_MASK 0x0000FF00 | ||
511 | #define SOL_RESP_MASK 0x00FF0000 | ||
512 | #define SOL_FLAGS_MASK 0x7F000000 | ||
513 | #define SOL_S_MASK 0x80000000 | ||
514 | |||
515 | struct sol_cqe { | ||
516 | u32 dw[4]; | ||
517 | }; | ||
518 | |||
519 | struct amap_sol_cqe { | ||
520 | u8 hw_sts[8]; /* dword 0 */ | ||
521 | u8 i_sts[8]; /* dword 0 */ | ||
522 | u8 i_resp[8]; /* dword 0 */ | ||
523 | u8 i_flags[7]; /* dword 0 */ | ||
524 | u8 s; /* dword 0 */ | ||
525 | u8 i_exp_cmd_sn[32]; /* dword 1 */ | ||
526 | u8 code[6]; /* dword 2 */ | ||
527 | u8 cid[10]; /* dword 2 */ | ||
528 | u8 wrb_index[8]; /* dword 2 */ | ||
529 | u8 i_cmd_wnd[8]; /* dword 2 */ | ||
530 | u8 i_res_cnt[31]; /* dword 3 */ | ||
531 | u8 valid; /* dword 3 */ | ||
532 | } __packed; | ||
533 | |||
534 | |||
535 | /** | ||
536 | * Post WRB Queue Doorbell Register used by the host Storage | ||
537 | * stack to notify the | ||
538 | * controller of a posted Work Request Block | ||
539 | */ | ||
540 | #define DB_WRB_POST_CID_MASK 0x3FF /* bits 0 - 9 */ | ||
541 | #define DB_DEF_PDU_WRB_INDEX_MASK 0xFF /* bits 0 - 9 */ | ||
542 | |||
543 | #define DB_DEF_PDU_WRB_INDEX_SHIFT 16 | ||
544 | #define DB_DEF_PDU_NUM_POSTED_SHIFT 24 | ||
545 | |||
546 | struct fragnum_bits_for_sgl_cra_in { | ||
547 | struct be_cmd_req_hdr hdr; | ||
548 | u32 num_bits; | ||
549 | } __packed; | ||
550 | |||
551 | struct iscsi_cleanup_req { | ||
552 | struct be_cmd_req_hdr hdr; | ||
553 | u16 chute; | ||
554 | u8 hdr_ring_id; | ||
555 | u8 data_ring_id; | ||
556 | |||
557 | } __packed; | ||
558 | |||
559 | struct eq_delay { | ||
560 | u32 eq_id; | ||
561 | u32 phase; | ||
562 | u32 delay_multiplier; | ||
563 | } __packed; | ||
564 | |||
565 | struct be_eq_delay_params_in { | ||
566 | struct be_cmd_req_hdr hdr; | ||
567 | u32 num_eq; | ||
568 | struct eq_delay delay[8]; | ||
569 | } __packed; | ||
570 | |||
571 | struct ip_address_format { | ||
572 | u16 size_of_structure; | ||
573 | u8 reserved; | ||
574 | u8 ip_type; | ||
575 | u8 ip_address[16]; | ||
576 | u32 rsvd0; | ||
577 | } __packed; | ||
578 | |||
579 | struct tcp_connect_and_offload_in { | ||
580 | struct be_cmd_req_hdr hdr; | ||
581 | struct ip_address_format ip_address; | ||
582 | u16 tcp_port; | ||
583 | u16 cid; | ||
584 | u16 cq_id; | ||
585 | u16 defq_id; | ||
586 | struct phys_addr dataout_template_pa; | ||
587 | u16 hdr_ring_id; | ||
588 | u16 data_ring_id; | ||
589 | u8 do_offload; | ||
590 | u8 rsvd0[3]; | ||
591 | } __packed; | ||
592 | |||
593 | struct tcp_connect_and_offload_out { | ||
594 | struct be_cmd_resp_hdr hdr; | ||
595 | u32 connection_handle; | ||
596 | u16 cid; | ||
597 | u16 rsvd0; | ||
598 | |||
599 | } __packed; | ||
600 | |||
601 | struct be_mcc_wrb_context { | ||
602 | struct MCC_WRB *wrb; | ||
603 | int *users_final_status; | ||
604 | } __packed; | ||
605 | |||
606 | #define DB_DEF_PDU_RING_ID_MASK 0x3FF /* bits 0 - 9 */ | ||
607 | #define DB_DEF_PDU_CQPROC_MASK 0x3FFF /* bits 0 - 9 */ | ||
608 | #define DB_DEF_PDU_REARM_SHIFT 14 | ||
609 | #define DB_DEF_PDU_EVENT_SHIFT 15 | ||
610 | #define DB_DEF_PDU_CQPROC_SHIFT 16 | ||
611 | |||
612 | struct dmsg_cqe { | ||
613 | u32 dw[4]; | ||
614 | } __packed; | ||
615 | |||
616 | struct tcp_upload_params_in { | ||
617 | struct be_cmd_req_hdr hdr; | ||
618 | u16 id; | ||
619 | u16 upload_type; | ||
620 | u32 reset_seq; | ||
621 | } __packed; | ||
622 | |||
623 | struct tcp_upload_params_out { | ||
624 | u32 dw[32]; | ||
625 | } __packed; | ||
626 | |||
627 | union tcp_upload_params { | ||
628 | struct tcp_upload_params_in request; | ||
629 | struct tcp_upload_params_out response; | ||
630 | } __packed; | ||
631 | |||
632 | struct be_ulp_fw_cfg { | ||
633 | u32 ulp_mode; | ||
634 | u32 etx_base; | ||
635 | u32 etx_count; | ||
636 | u32 sq_base; | ||
637 | u32 sq_count; | ||
638 | u32 rq_base; | ||
639 | u32 rq_count; | ||
640 | u32 dq_base; | ||
641 | u32 dq_count; | ||
642 | u32 lro_base; | ||
643 | u32 lro_count; | ||
644 | u32 icd_base; | ||
645 | u32 icd_count; | ||
646 | }; | ||
647 | |||
648 | struct be_fw_cfg { | ||
649 | struct be_cmd_req_hdr hdr; | ||
650 | u32 be_config_number; | ||
651 | u32 asic_revision; | ||
652 | u32 phys_port; | ||
653 | u32 function_mode; | ||
654 | struct be_ulp_fw_cfg ulp[2]; | ||
655 | u32 function_caps; | ||
656 | } __packed; | ||
657 | |||
658 | #define CMD_ISCSI_COMMAND_INVALIDATE 1 | ||
659 | #define ISCSI_OPCODE_SCSI_DATA_OUT 5 | ||
660 | #define OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD 70 | ||
661 | #define OPCODE_ISCSI_INI_DRIVER_OFFLOAD_SESSION 41 | ||
662 | #define OPCODE_COMMON_MODIFY_EQ_DELAY 41 | ||
663 | #define OPCODE_COMMON_ISCSI_CLEANUP 59 | ||
664 | #define OPCODE_COMMON_TCP_UPLOAD 56 | ||
665 | #define OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS 1 | ||
666 | /* --- CMD_ISCSI_INVALIDATE_CONNECTION_TYPE --- */ | ||
667 | #define CMD_ISCSI_CONNECTION_INVALIDATE 1 | ||
668 | #define CMD_ISCSI_CONNECTION_ISSUE_TCP_RST 2 | ||
669 | #define OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION 42 | ||
670 | |||
671 | #define INI_WR_CMD 1 /* Initiator write command */ | ||
672 | #define INI_TMF_CMD 2 /* Initiator TMF command */ | ||
673 | #define INI_NOPOUT_CMD 3 /* Initiator; Send a NOP-OUT */ | ||
674 | #define INI_RD_CMD 5 /* Initiator requesting to send | ||
675 | * a read command | ||
676 | */ | ||
677 | #define TGT_CTX_UPDT_CMD 7 /* Target context update */ | ||
678 | #define TGT_STS_CMD 8 /* Target R2T and other BHS | ||
679 | * where only the status number | ||
680 | * need to be updated | ||
681 | */ | ||
682 | #define TGT_DATAIN_CMD 9 /* Target Data-Ins in response | ||
683 | * to read command | ||
684 | */ | ||
685 | #define TGT_SOS_PDU 10 /* Target:standalone status | ||
686 | * response | ||
687 | */ | ||
688 | #define TGT_DM_CMD 11 /* Indicates that the bhs | ||
689 | * preparedby | ||
690 | * driver should not be touched | ||
691 | */ | ||
692 | /* --- CMD_CHUTE_TYPE --- */ | ||
693 | #define CMD_CONNECTION_CHUTE_0 1 | ||
694 | #define CMD_CONNECTION_CHUTE_1 2 | ||
695 | #define CMD_CONNECTION_CHUTE_2 3 | ||
696 | |||
697 | #define EQ_MAJOR_CODE_COMPLETION 0 | ||
698 | |||
699 | #define CMD_ISCSI_SESSION_DEL_CFG_FROM_FLASH 0 | ||
700 | #define CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH 1 | ||
701 | |||
702 | /* --- CONNECTION_UPLOAD_PARAMS --- */ | ||
703 | /* These parameters are used to define the type of upload desired. */ | ||
704 | #define CONNECTION_UPLOAD_GRACEFUL 1 /* Graceful upload */ | ||
705 | #define CONNECTION_UPLOAD_ABORT_RESET 2 /* Abortive upload with | ||
706 | * reset | ||
707 | */ | ||
708 | #define CONNECTION_UPLOAD_ABORT 3 /* Abortive upload without | ||
709 | * reset | ||
710 | */ | ||
711 | #define CONNECTION_UPLOAD_ABORT_WITH_SEQ 4 /* Abortive upload with reset, | ||
712 | * sequence number by driver */ | ||
713 | |||
714 | /* Returns byte size of given field with a structure. */ | ||
715 | |||
716 | /* Returns the number of items in the field array. */ | ||
717 | #define BE_NUMBER_OF_FIELD(_type_, _field_) \ | ||
718 | (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\ | ||
719 | |||
720 | /** | ||
721 | * Different types of iSCSI completions to host driver for both initiator | ||
722 | * and taget mode | ||
723 | * of operation. | ||
724 | */ | ||
725 | #define SOL_CMD_COMPLETE 1 /* Solicited command completed | ||
726 | * normally | ||
727 | */ | ||
728 | #define SOL_CMD_KILLED_DATA_DIGEST_ERR 2 /* Solicited command got | ||
729 | * invalidated internally due | ||
730 | * to Data Digest error | ||
731 | */ | ||
732 | #define CXN_KILLED_PDU_SIZE_EXCEEDS_DSL 3 /* Connection got invalidated | ||
733 | * internally | ||
734 | * due to a recieved PDU | ||
735 | * size > DSL | ||
736 | */ | ||
737 | #define CXN_KILLED_BURST_LEN_MISMATCH 4 /* Connection got invalidated | ||
738 | * internally due ti received | ||
739 | * PDU sequence size > | ||
740 | * FBL/MBL. | ||
741 | */ | ||
742 | #define CXN_KILLED_AHS_RCVD 5 /* Connection got invalidated | ||
743 | * internally due to a recieved | ||
744 | * PDU Hdr that has | ||
745 | * AHS */ | ||
746 | #define CXN_KILLED_HDR_DIGEST_ERR 6 /* Connection got invalidated | ||
747 | * internally due to Hdr Digest | ||
748 | * error | ||
749 | */ | ||
750 | #define CXN_KILLED_UNKNOWN_HDR 7 /* Connection got invalidated | ||
751 | * internally | ||
752 | * due to a bad opcode in the | ||
753 | * pdu hdr | ||
754 | */ | ||
755 | #define CXN_KILLED_STALE_ITT_TTT_RCVD 8 /* Connection got invalidated | ||
756 | * internally due to a recieved | ||
757 | * ITT/TTT that does not belong | ||
758 | * to this Connection | ||
759 | */ | ||
760 | #define CXN_KILLED_INVALID_ITT_TTT_RCVD 9 /* Connection got invalidated | ||
761 | * internally due to recieved | ||
762 | * ITT/TTT value > Max | ||
763 | * Supported ITTs/TTTs | ||
764 | */ | ||
765 | #define CXN_KILLED_RST_RCVD 10 /* Connection got invalidated | ||
766 | * internally due to an | ||
767 | * incoming TCP RST | ||
768 | */ | ||
769 | #define CXN_KILLED_TIMED_OUT 11 /* Connection got invalidated | ||
770 | * internally due to timeout on | ||
771 | * tcp segment 12 retransmit | ||
772 | * attempts failed | ||
773 | */ | ||
774 | #define CXN_KILLED_RST_SENT 12 /* Connection got invalidated | ||
775 | * internally due to TCP RST | ||
776 | * sent by the Tx side | ||
777 | */ | ||
778 | #define CXN_KILLED_FIN_RCVD 13 /* Connection got invalidated | ||
779 | * internally due to an | ||
780 | * incoming TCP FIN. | ||
781 | */ | ||
782 | #define CXN_KILLED_BAD_UNSOL_PDU_RCVD 14 /* Connection got invalidated | ||
783 | * internally due to bad | ||
784 | * unsolicited PDU Unsolicited | ||
785 | * PDUs are PDUs with | ||
786 | * ITT=0xffffffff | ||
787 | */ | ||
788 | #define CXN_KILLED_BAD_WRB_INDEX_ERROR 15 /* Connection got invalidated | ||
789 | * internally due to bad WRB | ||
790 | * index. | ||
791 | */ | ||
792 | #define CXN_KILLED_OVER_RUN_RESIDUAL 16 /* Command got invalidated | ||
793 | * internally due to recived | ||
794 | * command has residual | ||
795 | * over run bytes. | ||
796 | */ | ||
797 | #define CXN_KILLED_UNDER_RUN_RESIDUAL 17 /* Command got invalidated | ||
798 | * internally due to recived | ||
799 | * command has residual under | ||
800 | * run bytes. | ||
801 | */ | ||
802 | #define CMD_KILLED_INVALID_STATSN_RCVD 18 /* Command got invalidated | ||
803 | * internally due to a recieved | ||
804 | * PDU has an invalid StatusSN | ||
805 | */ | ||
806 | #define CMD_KILLED_INVALID_R2T_RCVD 19 /* Command got invalidated | ||
807 | * internally due to a recieved | ||
808 | * an R2T with some invalid | ||
809 | * fields in it | ||
810 | */ | ||
811 | #define CMD_CXN_KILLED_LUN_INVALID 20 /* Command got invalidated | ||
812 | * internally due to received | ||
813 | * PDU has an invalid LUN. | ||
814 | */ | ||
815 | #define CMD_CXN_KILLED_ICD_INVALID 21 /* Command got invalidated | ||
816 | * internally due to the | ||
817 | * corresponding ICD not in a | ||
818 | * valid state | ||
819 | */ | ||
820 | #define CMD_CXN_KILLED_ITT_INVALID 22 /* Command got invalidated due | ||
821 | * to received PDU has an | ||
822 | * invalid ITT. | ||
823 | */ | ||
824 | #define CMD_CXN_KILLED_SEQ_OUTOFORDER 23 /* Command got invalidated due | ||
825 | * to received sequence buffer | ||
826 | * offset is out of order. | ||
827 | */ | ||
828 | #define CMD_CXN_KILLED_INVALID_DATASN_RCVD 24 /* Command got invalidated | ||
829 | * internally due to a | ||
830 | * recieved PDU has an invalid | ||
831 | * DataSN | ||
832 | */ | ||
833 | #define CXN_INVALIDATE_NOTIFY 25 /* Connection invalidation | ||
834 | * completion notify. | ||
835 | */ | ||
836 | #define CXN_INVALIDATE_INDEX_NOTIFY 26 /* Connection invalidation | ||
837 | * completion | ||
838 | * with data PDU index. | ||
839 | */ | ||
840 | #define CMD_INVALIDATED_NOTIFY 27 /* Command invalidation | ||
841 | * completionnotifify. | ||
842 | */ | ||
843 | #define UNSOL_HDR_NOTIFY 28 /* Unsolicited header notify.*/ | ||
844 | #define UNSOL_DATA_NOTIFY 29 /* Unsolicited data notify.*/ | ||
845 | #define UNSOL_DATA_DIGEST_ERROR_NOTIFY 30 /* Unsolicited data digest | ||
846 | * error notify. | ||
847 | */ | ||
848 | #define DRIVERMSG_NOTIFY 31 /* TCP acknowledge based | ||
849 | * notification. | ||
850 | */ | ||
851 | #define CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN 32 /* Connection got invalidated | ||
852 | * internally due to command | ||
853 | * and data are not on same | ||
854 | * connection. | ||
855 | */ | ||
856 | #define SOL_CMD_KILLED_DIF_ERR 33 /* Solicited command got | ||
857 | * invalidated internally due | ||
858 | * to DIF error | ||
859 | */ | ||
860 | #define CXN_KILLED_SYN_RCVD 34 /* Connection got invalidated | ||
861 | * internally due to incoming | ||
862 | * TCP SYN | ||
863 | */ | ||
864 | #define CXN_KILLED_IMM_DATA_RCVD 35 /* Connection got invalidated | ||
865 | * internally due to an | ||
866 | * incoming Unsolicited PDU | ||
867 | * that has immediate data on | ||
868 | * the cxn | ||
869 | */ | ||
870 | |||
871 | void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, | ||
872 | bool embedded, u8 sge_cnt); | ||
873 | |||
874 | void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, | ||
875 | u8 subsystem, u8 opcode, int cmd_len); | ||
876 | |||
877 | #endif /* !BEISCSI_CMDS_H */ | ||
diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c new file mode 100644 index 000000000000..2fd25442cfaf --- /dev/null +++ b/drivers/scsi/be2iscsi/be_iscsi.c | |||
@@ -0,0 +1,638 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Written by: Jayamohan Kallickal (jayamohank@serverengines.com) | ||
11 | * | ||
12 | * Contact Information: | ||
13 | * linux-drivers@serverengines.com | ||
14 | * | ||
15 | * ServerEngines | ||
16 | * 209 N. Fair Oaks Ave | ||
17 | * Sunnyvale, CA 94085 | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <scsi/libiscsi.h> | ||
22 | #include <scsi/scsi_transport_iscsi.h> | ||
23 | #include <scsi/scsi_transport.h> | ||
24 | #include <scsi/scsi_cmnd.h> | ||
25 | #include <scsi/scsi_device.h> | ||
26 | #include <scsi/scsi_host.h> | ||
27 | #include <scsi/scsi.h> | ||
28 | |||
29 | #include "be_iscsi.h" | ||
30 | |||
31 | extern struct iscsi_transport beiscsi_iscsi_transport; | ||
32 | |||
33 | /** | ||
34 | * beiscsi_session_create - creates a new iscsi session | ||
35 | * @cmds_max: max commands supported | ||
36 | * @qdepth: max queue depth supported | ||
37 | * @initial_cmdsn: initial iscsi CMDSN | ||
38 | */ | ||
39 | struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, | ||
40 | u16 cmds_max, | ||
41 | u16 qdepth, | ||
42 | u32 initial_cmdsn) | ||
43 | { | ||
44 | struct Scsi_Host *shost; | ||
45 | struct beiscsi_endpoint *beiscsi_ep; | ||
46 | struct iscsi_cls_session *cls_session; | ||
47 | struct beiscsi_hba *phba; | ||
48 | struct iscsi_session *sess; | ||
49 | struct beiscsi_session *beiscsi_sess; | ||
50 | struct beiscsi_io_task *io_task; | ||
51 | |||
52 | SE_DEBUG(DBG_LVL_8, "In beiscsi_session_create\n"); | ||
53 | |||
54 | if (!ep) { | ||
55 | SE_DEBUG(DBG_LVL_1, "beiscsi_session_create: invalid ep \n"); | ||
56 | return NULL; | ||
57 | } | ||
58 | beiscsi_ep = ep->dd_data; | ||
59 | phba = beiscsi_ep->phba; | ||
60 | shost = phba->shost; | ||
61 | if (cmds_max > beiscsi_ep->phba->params.wrbs_per_cxn) { | ||
62 | shost_printk(KERN_ERR, shost, "Cannot handle %d cmds." | ||
63 | "Max cmds per session supported is %d. Using %d. " | ||
64 | "\n", cmds_max, | ||
65 | beiscsi_ep->phba->params.wrbs_per_cxn, | ||
66 | beiscsi_ep->phba->params.wrbs_per_cxn); | ||
67 | cmds_max = beiscsi_ep->phba->params.wrbs_per_cxn; | ||
68 | } | ||
69 | |||
70 | cls_session = iscsi_session_setup(&beiscsi_iscsi_transport, | ||
71 | shost, cmds_max, | ||
72 | sizeof(*beiscsi_sess), | ||
73 | sizeof(*io_task), | ||
74 | initial_cmdsn, ISCSI_MAX_TARGET); | ||
75 | if (!cls_session) | ||
76 | return NULL; | ||
77 | sess = cls_session->dd_data; | ||
78 | beiscsi_sess = sess->dd_data; | ||
79 | beiscsi_sess->bhs_pool = pci_pool_create("beiscsi_bhs_pool", | ||
80 | phba->pcidev, | ||
81 | sizeof(struct be_cmd_bhs), | ||
82 | 64, 0); | ||
83 | if (!beiscsi_sess->bhs_pool) | ||
84 | goto destroy_sess; | ||
85 | |||
86 | return cls_session; | ||
87 | destroy_sess: | ||
88 | iscsi_session_teardown(cls_session); | ||
89 | return NULL; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * beiscsi_session_destroy - destroys iscsi session | ||
94 | * @cls_session: pointer to iscsi cls session | ||
95 | * | ||
96 | * Destroys iSCSI session instance and releases | ||
97 | * resources allocated for it. | ||
98 | */ | ||
99 | void beiscsi_session_destroy(struct iscsi_cls_session *cls_session) | ||
100 | { | ||
101 | struct iscsi_session *sess = cls_session->dd_data; | ||
102 | struct beiscsi_session *beiscsi_sess = sess->dd_data; | ||
103 | |||
104 | pci_pool_destroy(beiscsi_sess->bhs_pool); | ||
105 | iscsi_session_teardown(cls_session); | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * beiscsi_conn_create - create an instance of iscsi connection | ||
110 | * @cls_session: ptr to iscsi_cls_session | ||
111 | * @cid: iscsi cid | ||
112 | */ | ||
113 | struct iscsi_cls_conn * | ||
114 | beiscsi_conn_create(struct iscsi_cls_session *cls_session, u32 cid) | ||
115 | { | ||
116 | struct beiscsi_hba *phba; | ||
117 | struct Scsi_Host *shost; | ||
118 | struct iscsi_cls_conn *cls_conn; | ||
119 | struct beiscsi_conn *beiscsi_conn; | ||
120 | struct iscsi_conn *conn; | ||
121 | struct iscsi_session *sess; | ||
122 | struct beiscsi_session *beiscsi_sess; | ||
123 | |||
124 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_create ,cid" | ||
125 | "from iscsi layer=%d\n", cid); | ||
126 | shost = iscsi_session_to_shost(cls_session); | ||
127 | phba = iscsi_host_priv(shost); | ||
128 | |||
129 | cls_conn = iscsi_conn_setup(cls_session, sizeof(*beiscsi_conn), cid); | ||
130 | if (!cls_conn) | ||
131 | return NULL; | ||
132 | |||
133 | conn = cls_conn->dd_data; | ||
134 | beiscsi_conn = conn->dd_data; | ||
135 | beiscsi_conn->ep = NULL; | ||
136 | beiscsi_conn->phba = phba; | ||
137 | beiscsi_conn->conn = conn; | ||
138 | sess = cls_session->dd_data; | ||
139 | beiscsi_sess = sess->dd_data; | ||
140 | beiscsi_conn->beiscsi_sess = beiscsi_sess; | ||
141 | return cls_conn; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * beiscsi_bindconn_cid - Bind the beiscsi_conn with phba connection table | ||
146 | * @beiscsi_conn: The pointer to beiscsi_conn structure | ||
147 | * @phba: The phba instance | ||
148 | * @cid: The cid to free | ||
149 | */ | ||
150 | static int beiscsi_bindconn_cid(struct beiscsi_hba *phba, | ||
151 | struct beiscsi_conn *beiscsi_conn, | ||
152 | unsigned int cid) | ||
153 | { | ||
154 | if (phba->conn_table[cid]) { | ||
155 | SE_DEBUG(DBG_LVL_1, | ||
156 | "Connection table already occupied. Detected clash\n"); | ||
157 | return -EINVAL; | ||
158 | } else { | ||
159 | SE_DEBUG(DBG_LVL_8, "phba->conn_table[%d]=%p(beiscsi_conn) \n", | ||
160 | cid, beiscsi_conn); | ||
161 | phba->conn_table[cid] = beiscsi_conn; | ||
162 | } | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * beiscsi_conn_bind - Binds iscsi session/connection with TCP connection | ||
168 | * @cls_session: pointer to iscsi cls session | ||
169 | * @cls_conn: pointer to iscsi cls conn | ||
170 | * @transport_fd: EP handle(64 bit) | ||
171 | * | ||
172 | * This function binds the TCP Conn with iSCSI Connection and Session. | ||
173 | */ | ||
174 | int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, | ||
175 | struct iscsi_cls_conn *cls_conn, | ||
176 | u64 transport_fd, int is_leading) | ||
177 | { | ||
178 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
179 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
180 | struct Scsi_Host *shost = | ||
181 | (struct Scsi_Host *)iscsi_session_to_shost(cls_session); | ||
182 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | ||
183 | struct beiscsi_endpoint *beiscsi_ep; | ||
184 | struct iscsi_endpoint *ep; | ||
185 | |||
186 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_bind\n"); | ||
187 | ep = iscsi_lookup_endpoint(transport_fd); | ||
188 | if (!ep) | ||
189 | return -EINVAL; | ||
190 | |||
191 | beiscsi_ep = ep->dd_data; | ||
192 | |||
193 | if (iscsi_conn_bind(cls_session, cls_conn, is_leading)) | ||
194 | return -EINVAL; | ||
195 | |||
196 | if (beiscsi_ep->phba != phba) { | ||
197 | SE_DEBUG(DBG_LVL_8, | ||
198 | "beiscsi_ep->hba=%p not equal to phba=%p \n", | ||
199 | beiscsi_ep->phba, phba); | ||
200 | return -EEXIST; | ||
201 | } | ||
202 | |||
203 | beiscsi_conn->beiscsi_conn_cid = beiscsi_ep->ep_cid; | ||
204 | beiscsi_conn->ep = beiscsi_ep; | ||
205 | beiscsi_ep->conn = beiscsi_conn; | ||
206 | SE_DEBUG(DBG_LVL_8, "beiscsi_conn=%p conn=%p ep_cid=%d \n", | ||
207 | beiscsi_conn, conn, beiscsi_ep->ep_cid); | ||
208 | return beiscsi_bindconn_cid(phba, beiscsi_conn, beiscsi_ep->ep_cid); | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * beiscsi_conn_get_param - get the iscsi parameter | ||
213 | * @cls_conn: pointer to iscsi cls conn | ||
214 | * @param: parameter type identifier | ||
215 | * @buf: buffer pointer | ||
216 | * | ||
217 | * returns iscsi parameter | ||
218 | */ | ||
219 | int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | ||
220 | enum iscsi_param param, char *buf) | ||
221 | { | ||
222 | struct beiscsi_endpoint *beiscsi_ep; | ||
223 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
224 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
225 | int len = 0; | ||
226 | |||
227 | beiscsi_ep = beiscsi_conn->ep; | ||
228 | if (!beiscsi_ep) { | ||
229 | SE_DEBUG(DBG_LVL_1, | ||
230 | "In beiscsi_conn_get_param , no beiscsi_ep\n"); | ||
231 | return -1; | ||
232 | } | ||
233 | |||
234 | switch (param) { | ||
235 | case ISCSI_PARAM_CONN_PORT: | ||
236 | len = sprintf(buf, "%hu\n", beiscsi_ep->dst_tcpport); | ||
237 | break; | ||
238 | case ISCSI_PARAM_CONN_ADDRESS: | ||
239 | if (beiscsi_ep->ip_type == BE2_IPV4) | ||
240 | len = sprintf(buf, "%pI4\n", &beiscsi_ep->dst_addr); | ||
241 | else | ||
242 | len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr); | ||
243 | break; | ||
244 | default: | ||
245 | return iscsi_conn_get_param(cls_conn, param, buf); | ||
246 | } | ||
247 | return len; | ||
248 | } | ||
249 | |||
250 | int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | ||
251 | enum iscsi_param param, char *buf, int buflen) | ||
252 | { | ||
253 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
254 | struct iscsi_session *session = conn->session; | ||
255 | int ret; | ||
256 | |||
257 | ret = iscsi_set_param(cls_conn, param, buf, buflen); | ||
258 | if (ret) | ||
259 | return ret; | ||
260 | /* | ||
261 | * If userspace tried to set the value to higher than we can | ||
262 | * support override here. | ||
263 | */ | ||
264 | switch (param) { | ||
265 | case ISCSI_PARAM_FIRST_BURST: | ||
266 | if (session->first_burst > 8192) | ||
267 | session->first_burst = 8192; | ||
268 | break; | ||
269 | case ISCSI_PARAM_MAX_RECV_DLENGTH: | ||
270 | if (conn->max_recv_dlength > 65536) | ||
271 | conn->max_recv_dlength = 65536; | ||
272 | break; | ||
273 | case ISCSI_PARAM_MAX_BURST: | ||
274 | if (session->first_burst > 262144) | ||
275 | session->first_burst = 262144; | ||
276 | break; | ||
277 | default: | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | return 0; | ||
282 | } | ||
283 | |||
284 | /** | ||
285 | * beiscsi_get_host_param - get the iscsi parameter | ||
286 | * @shost: pointer to scsi_host structure | ||
287 | * @param: parameter type identifier | ||
288 | * @buf: buffer pointer | ||
289 | * | ||
290 | * returns host parameter | ||
291 | */ | ||
292 | int beiscsi_get_host_param(struct Scsi_Host *shost, | ||
293 | enum iscsi_host_param param, char *buf) | ||
294 | { | ||
295 | struct beiscsi_hba *phba = (struct beiscsi_hba *)iscsi_host_priv(shost); | ||
296 | int len = 0; | ||
297 | |||
298 | switch (param) { | ||
299 | case ISCSI_HOST_PARAM_HWADDRESS: | ||
300 | be_cmd_get_mac_addr(&phba->ctrl, phba->mac_address); | ||
301 | len = sysfs_format_mac(buf, phba->mac_address, ETH_ALEN); | ||
302 | break; | ||
303 | default: | ||
304 | return iscsi_host_get_param(shost, param, buf); | ||
305 | } | ||
306 | return len; | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * beiscsi_conn_get_stats - get the iscsi stats | ||
311 | * @cls_conn: pointer to iscsi cls conn | ||
312 | * @stats: pointer to iscsi_stats structure | ||
313 | * | ||
314 | * returns iscsi stats | ||
315 | */ | ||
316 | void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, | ||
317 | struct iscsi_stats *stats) | ||
318 | { | ||
319 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
320 | |||
321 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_stats\n"); | ||
322 | stats->txdata_octets = conn->txdata_octets; | ||
323 | stats->rxdata_octets = conn->rxdata_octets; | ||
324 | stats->dataout_pdus = conn->dataout_pdus_cnt; | ||
325 | stats->scsirsp_pdus = conn->scsirsp_pdus_cnt; | ||
326 | stats->scsicmd_pdus = conn->scsicmd_pdus_cnt; | ||
327 | stats->datain_pdus = conn->datain_pdus_cnt; | ||
328 | stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; | ||
329 | stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; | ||
330 | stats->r2t_pdus = conn->r2t_pdus_cnt; | ||
331 | stats->digest_err = 0; | ||
332 | stats->timeout_err = 0; | ||
333 | stats->custom_length = 0; | ||
334 | strcpy(stats->custom[0].desc, "eh_abort_cnt"); | ||
335 | stats->custom[0].value = conn->eh_abort_cnt; | ||
336 | } | ||
337 | |||
338 | /** | ||
339 | * beiscsi_set_params_for_offld - get the parameters for offload | ||
340 | * @beiscsi_conn: pointer to beiscsi_conn | ||
341 | * @params: pointer to offload_params structure | ||
342 | */ | ||
343 | static void beiscsi_set_params_for_offld(struct beiscsi_conn *beiscsi_conn, | ||
344 | struct beiscsi_offload_params *params) | ||
345 | { | ||
346 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
347 | struct iscsi_session *session = conn->session; | ||
348 | |||
349 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, max_burst_length, | ||
350 | params, session->max_burst); | ||
351 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, | ||
352 | max_send_data_segment_length, params, | ||
353 | conn->max_xmit_dlength); | ||
354 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, first_burst_length, | ||
355 | params, session->first_burst); | ||
356 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, erl, params, | ||
357 | session->erl); | ||
358 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, dde, params, | ||
359 | conn->datadgst_en); | ||
360 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, hde, params, | ||
361 | conn->hdrdgst_en); | ||
362 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, ir2t, params, | ||
363 | session->initial_r2t_en); | ||
364 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, imd, params, | ||
365 | session->imm_data_en); | ||
366 | AMAP_SET_BITS(struct amap_beiscsi_offload_params, exp_statsn, params, | ||
367 | (conn->exp_statsn - 1)); | ||
368 | } | ||
369 | |||
370 | /** | ||
371 | * beiscsi_conn_start - offload of session to chip | ||
372 | * @cls_conn: pointer to beiscsi_conn | ||
373 | */ | ||
374 | int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn) | ||
375 | { | ||
376 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
377 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
378 | struct beiscsi_endpoint *beiscsi_ep; | ||
379 | struct beiscsi_offload_params params; | ||
380 | struct iscsi_session *session = conn->session; | ||
381 | struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); | ||
382 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
383 | |||
384 | memset(¶ms, 0, sizeof(struct beiscsi_offload_params)); | ||
385 | beiscsi_ep = beiscsi_conn->ep; | ||
386 | if (!beiscsi_ep) | ||
387 | SE_DEBUG(DBG_LVL_1, "In beiscsi_conn_start , no beiscsi_ep\n"); | ||
388 | |||
389 | free_mgmt_sgl_handle(phba, beiscsi_conn->plogin_sgl_handle); | ||
390 | beiscsi_conn->login_in_progress = 0; | ||
391 | beiscsi_set_params_for_offld(beiscsi_conn, ¶ms); | ||
392 | beiscsi_offload_connection(beiscsi_conn, ¶ms); | ||
393 | iscsi_conn_start(cls_conn); | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * beiscsi_get_cid - Allocate a cid | ||
399 | * @phba: The phba instance | ||
400 | */ | ||
401 | static int beiscsi_get_cid(struct beiscsi_hba *phba) | ||
402 | { | ||
403 | unsigned short cid = 0xFFFF; | ||
404 | |||
405 | if (!phba->avlbl_cids) | ||
406 | return cid; | ||
407 | |||
408 | cid = phba->cid_array[phba->cid_alloc++]; | ||
409 | if (phba->cid_alloc == phba->params.cxns_per_ctrl) | ||
410 | phba->cid_alloc = 0; | ||
411 | phba->avlbl_cids--; | ||
412 | return cid; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * beiscsi_open_conn - Ask FW to open a TCP connection | ||
417 | * @ep: endpoint to be used | ||
418 | * @src_addr: The source IP address | ||
419 | * @dst_addr: The Destination IP address | ||
420 | * | ||
421 | * Asks the FW to open a TCP connection | ||
422 | */ | ||
423 | static int beiscsi_open_conn(struct iscsi_endpoint *ep, | ||
424 | struct sockaddr *src_addr, | ||
425 | struct sockaddr *dst_addr, int non_blocking) | ||
426 | { | ||
427 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | ||
428 | struct beiscsi_hba *phba = beiscsi_ep->phba; | ||
429 | int ret = -1; | ||
430 | |||
431 | beiscsi_ep->ep_cid = beiscsi_get_cid(phba); | ||
432 | if (beiscsi_ep->ep_cid == 0xFFFF) { | ||
433 | SE_DEBUG(DBG_LVL_1, "No free cid available\n"); | ||
434 | return ret; | ||
435 | } | ||
436 | SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d ", | ||
437 | beiscsi_ep->ep_cid); | ||
438 | phba->ep_array[beiscsi_ep->ep_cid] = ep; | ||
439 | if (beiscsi_ep->ep_cid > | ||
440 | (phba->fw_config.iscsi_cid_start + phba->params.cxns_per_ctrl)) { | ||
441 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); | ||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | beiscsi_ep->cid_vld = 0; | ||
446 | return mgmt_open_connection(phba, dst_addr, beiscsi_ep); | ||
447 | } | ||
448 | |||
449 | /** | ||
450 | * beiscsi_put_cid - Free the cid | ||
451 | * @phba: The phba for which the cid is being freed | ||
452 | * @cid: The cid to free | ||
453 | */ | ||
454 | static void beiscsi_put_cid(struct beiscsi_hba *phba, unsigned short cid) | ||
455 | { | ||
456 | phba->avlbl_cids++; | ||
457 | phba->cid_array[phba->cid_free++] = cid; | ||
458 | if (phba->cid_free == phba->params.cxns_per_ctrl) | ||
459 | phba->cid_free = 0; | ||
460 | } | ||
461 | |||
462 | /** | ||
463 | * beiscsi_free_ep - free endpoint | ||
464 | * @ep: pointer to iscsi endpoint structure | ||
465 | */ | ||
466 | static void beiscsi_free_ep(struct iscsi_endpoint *ep) | ||
467 | { | ||
468 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | ||
469 | struct beiscsi_hba *phba = beiscsi_ep->phba; | ||
470 | |||
471 | beiscsi_put_cid(phba, beiscsi_ep->ep_cid); | ||
472 | beiscsi_ep->phba = NULL; | ||
473 | iscsi_destroy_endpoint(ep); | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * beiscsi_ep_connect - Ask chip to create TCP Conn | ||
478 | * @scsi_host: Pointer to scsi_host structure | ||
479 | * @dst_addr: The IP address of Target | ||
480 | * @non_blocking: blocking or non-blocking call | ||
481 | * | ||
482 | * This routines first asks chip to create a connection and then allocates an EP | ||
483 | */ | ||
484 | struct iscsi_endpoint * | ||
485 | beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, | ||
486 | int non_blocking) | ||
487 | { | ||
488 | struct beiscsi_hba *phba; | ||
489 | struct beiscsi_endpoint *beiscsi_ep; | ||
490 | struct iscsi_endpoint *ep; | ||
491 | int ret; | ||
492 | |||
493 | SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect \n"); | ||
494 | if (shost) | ||
495 | phba = iscsi_host_priv(shost); | ||
496 | else { | ||
497 | ret = -ENXIO; | ||
498 | SE_DEBUG(DBG_LVL_1, "shost is NULL \n"); | ||
499 | return ERR_PTR(ret); | ||
500 | } | ||
501 | ep = iscsi_create_endpoint(sizeof(struct beiscsi_endpoint)); | ||
502 | if (!ep) { | ||
503 | ret = -ENOMEM; | ||
504 | return ERR_PTR(ret); | ||
505 | } | ||
506 | |||
507 | beiscsi_ep = ep->dd_data; | ||
508 | beiscsi_ep->phba = phba; | ||
509 | |||
510 | if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) { | ||
511 | SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n"); | ||
512 | ret = -ENOMEM; | ||
513 | goto free_ep; | ||
514 | } | ||
515 | |||
516 | return ep; | ||
517 | |||
518 | free_ep: | ||
519 | beiscsi_free_ep(ep); | ||
520 | return ERR_PTR(ret); | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * beiscsi_ep_poll - Poll to see if connection is established | ||
525 | * @ep: endpoint to be used | ||
526 | * @timeout_ms: timeout specified in millisecs | ||
527 | * | ||
528 | * Poll to see if TCP connection established | ||
529 | */ | ||
530 | int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) | ||
531 | { | ||
532 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | ||
533 | |||
534 | SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_poll\n"); | ||
535 | if (beiscsi_ep->cid_vld == 1) | ||
536 | return 1; | ||
537 | else | ||
538 | return 0; | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * beiscsi_close_conn - Upload the connection | ||
543 | * @ep: The iscsi endpoint | ||
544 | * @flag: The type of connection closure | ||
545 | */ | ||
546 | static int beiscsi_close_conn(struct iscsi_endpoint *ep, int flag) | ||
547 | { | ||
548 | int ret = 0; | ||
549 | struct beiscsi_endpoint *beiscsi_ep = ep->dd_data; | ||
550 | struct beiscsi_hba *phba = beiscsi_ep->phba; | ||
551 | |||
552 | if (MGMT_STATUS_SUCCESS != | ||
553 | mgmt_upload_connection(phba, beiscsi_ep->ep_cid, | ||
554 | CONNECTION_UPLOAD_GRACEFUL)) { | ||
555 | SE_DEBUG(DBG_LVL_8, "upload failed for cid 0x%x", | ||
556 | beiscsi_ep->ep_cid); | ||
557 | ret = -1; | ||
558 | } | ||
559 | |||
560 | return ret; | ||
561 | } | ||
562 | |||
563 | /** | ||
564 | * beiscsi_ep_disconnect - Tears down the TCP connection | ||
565 | * @ep: endpoint to be used | ||
566 | * | ||
567 | * Tears down the TCP connection | ||
568 | */ | ||
569 | void beiscsi_ep_disconnect(struct iscsi_endpoint *ep) | ||
570 | { | ||
571 | struct beiscsi_conn *beiscsi_conn; | ||
572 | struct beiscsi_endpoint *beiscsi_ep; | ||
573 | struct beiscsi_hba *phba; | ||
574 | int flag = 0; | ||
575 | |||
576 | beiscsi_ep = ep->dd_data; | ||
577 | phba = beiscsi_ep->phba; | ||
578 | SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect\n"); | ||
579 | |||
580 | if (beiscsi_ep->conn) { | ||
581 | beiscsi_conn = beiscsi_ep->conn; | ||
582 | iscsi_suspend_queue(beiscsi_conn->conn); | ||
583 | beiscsi_close_conn(ep, flag); | ||
584 | } | ||
585 | |||
586 | beiscsi_free_ep(ep); | ||
587 | } | ||
588 | |||
589 | /** | ||
590 | * beiscsi_unbind_conn_to_cid - Unbind the beiscsi_conn from phba conn table | ||
591 | * @phba: The phba instance | ||
592 | * @cid: The cid to free | ||
593 | */ | ||
594 | static int beiscsi_unbind_conn_to_cid(struct beiscsi_hba *phba, | ||
595 | unsigned int cid) | ||
596 | { | ||
597 | if (phba->conn_table[cid]) | ||
598 | phba->conn_table[cid] = NULL; | ||
599 | else { | ||
600 | SE_DEBUG(DBG_LVL_8, "Connection table Not occupied. \n"); | ||
601 | return -EINVAL; | ||
602 | } | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | /** | ||
607 | * beiscsi_conn_stop - Invalidate and stop the connection | ||
608 | * @cls_conn: pointer to get iscsi_conn | ||
609 | * @flag: The type of connection closure | ||
610 | */ | ||
611 | void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | ||
612 | { | ||
613 | struct iscsi_conn *conn = cls_conn->dd_data; | ||
614 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
615 | struct beiscsi_endpoint *beiscsi_ep; | ||
616 | struct iscsi_session *session = conn->session; | ||
617 | struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session); | ||
618 | struct beiscsi_hba *phba = iscsi_host_priv(shost); | ||
619 | unsigned int status; | ||
620 | unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH; | ||
621 | |||
622 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop\n"); | ||
623 | beiscsi_ep = beiscsi_conn->ep; | ||
624 | if (!beiscsi_ep) { | ||
625 | SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n"); | ||
626 | return; | ||
627 | } | ||
628 | status = mgmt_invalidate_connection(phba, beiscsi_ep, | ||
629 | beiscsi_ep->ep_cid, 1, | ||
630 | savecfg_flag); | ||
631 | if (status != MGMT_STATUS_SUCCESS) { | ||
632 | SE_DEBUG(DBG_LVL_1, | ||
633 | "mgmt_invalidate_connection Failed for cid=%d \n", | ||
634 | beiscsi_ep->ep_cid); | ||
635 | } | ||
636 | beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid); | ||
637 | iscsi_conn_stop(cls_conn, flag); | ||
638 | } | ||
diff --git a/drivers/scsi/be2iscsi/be_iscsi.h b/drivers/scsi/be2iscsi/be_iscsi.h new file mode 100644 index 000000000000..f92ffc5349fb --- /dev/null +++ b/drivers/scsi/be2iscsi/be_iscsi.h | |||
@@ -0,0 +1,75 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Written by: Jayamohan Kallickal (jayamohank@serverengines.com) | ||
11 | * | ||
12 | * Contact Information: | ||
13 | * linux-drivers@serverengines.com | ||
14 | * | ||
15 | * ServerEngines | ||
16 | * 209 N. Fair Oaks Ave | ||
17 | * Sunnyvale, CA 94085 | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef _BE_ISCSI_ | ||
22 | #define _BE_ISCSI_ | ||
23 | |||
24 | #include "be_main.h" | ||
25 | #include "be_mgmt.h" | ||
26 | |||
27 | #define BE2_IPV4 0x1 | ||
28 | #define BE2_IPV6 0x10 | ||
29 | |||
30 | void beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | ||
31 | struct beiscsi_offload_params *params); | ||
32 | |||
33 | void beiscsi_offload_iscsi(struct beiscsi_hba *phba, struct iscsi_conn *conn, | ||
34 | struct beiscsi_conn *beiscsi_conn, | ||
35 | unsigned int fw_handle); | ||
36 | |||
37 | struct iscsi_cls_session *beiscsi_session_create(struct iscsi_endpoint *ep, | ||
38 | uint16_t cmds_max, | ||
39 | uint16_t qdepth, | ||
40 | uint32_t initial_cmdsn); | ||
41 | |||
42 | void beiscsi_session_destroy(struct iscsi_cls_session *cls_session); | ||
43 | |||
44 | struct iscsi_cls_conn *beiscsi_conn_create(struct iscsi_cls_session | ||
45 | *cls_session, uint32_t cid); | ||
46 | |||
47 | int beiscsi_conn_bind(struct iscsi_cls_session *cls_session, | ||
48 | struct iscsi_cls_conn *cls_conn, | ||
49 | uint64_t transport_fd, int is_leading); | ||
50 | |||
51 | int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn, | ||
52 | enum iscsi_param param, char *buf); | ||
53 | |||
54 | int beiscsi_get_host_param(struct Scsi_Host *shost, | ||
55 | enum iscsi_host_param param, char *buf); | ||
56 | |||
57 | int beiscsi_set_param(struct iscsi_cls_conn *cls_conn, | ||
58 | enum iscsi_param param, char *buf, int buflen); | ||
59 | |||
60 | int beiscsi_conn_start(struct iscsi_cls_conn *cls_conn); | ||
61 | |||
62 | void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag); | ||
63 | |||
64 | struct iscsi_endpoint *beiscsi_ep_connect(struct Scsi_Host *shost, | ||
65 | struct sockaddr *dst_addr, | ||
66 | int non_blocking); | ||
67 | |||
68 | int beiscsi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms); | ||
69 | |||
70 | void beiscsi_ep_disconnect(struct iscsi_endpoint *ep); | ||
71 | |||
72 | void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, | ||
73 | struct iscsi_stats *stats); | ||
74 | |||
75 | #endif | ||
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c new file mode 100644 index 000000000000..4f1aca346e38 --- /dev/null +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -0,0 +1,3390 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Written by: Jayamohan Kallickal (jayamohank@serverengines.com) | ||
11 | * | ||
12 | * Contact Information: | ||
13 | * linux-drivers@serverengines.com | ||
14 | * | ||
15 | * ServerEngines | ||
16 | * 209 N. Fair Oaks Ave | ||
17 | * Sunnyvale, CA 94085 | ||
18 | * | ||
19 | */ | ||
20 | #include <linux/reboot.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/blkdev.h> | ||
24 | #include <linux/pci.h> | ||
25 | #include <linux/string.h> | ||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/semaphore.h> | ||
28 | |||
29 | #include <scsi/libiscsi.h> | ||
30 | #include <scsi/scsi_transport_iscsi.h> | ||
31 | #include <scsi/scsi_transport.h> | ||
32 | #include <scsi/scsi_cmnd.h> | ||
33 | #include <scsi/scsi_device.h> | ||
34 | #include <scsi/scsi_host.h> | ||
35 | #include <scsi/scsi.h> | ||
36 | #include "be_main.h" | ||
37 | #include "be_iscsi.h" | ||
38 | #include "be_mgmt.h" | ||
39 | |||
40 | static unsigned int be_iopoll_budget = 10; | ||
41 | static unsigned int be_max_phys_size = 64; | ||
42 | static unsigned int enable_msix; | ||
43 | |||
44 | MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); | ||
45 | MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); | ||
46 | MODULE_AUTHOR("ServerEngines Corporation"); | ||
47 | MODULE_LICENSE("GPL"); | ||
48 | module_param(be_iopoll_budget, int, 0); | ||
49 | module_param(enable_msix, int, 0); | ||
50 | module_param(be_max_phys_size, uint, S_IRUGO); | ||
51 | MODULE_PARM_DESC(be_max_phys_size, "Maximum Size (In Kilobytes) of physically" | ||
52 | "contiguous memory that can be allocated." | ||
53 | "Range is 16 - 128"); | ||
54 | |||
55 | static int beiscsi_slave_configure(struct scsi_device *sdev) | ||
56 | { | ||
57 | blk_queue_max_segment_size(sdev->request_queue, 65536); | ||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static struct scsi_host_template beiscsi_sht = { | ||
62 | .module = THIS_MODULE, | ||
63 | .name = "ServerEngines 10Gbe open-iscsi Initiator Driver", | ||
64 | .proc_name = DRV_NAME, | ||
65 | .queuecommand = iscsi_queuecommand, | ||
66 | .eh_abort_handler = iscsi_eh_abort, | ||
67 | .change_queue_depth = iscsi_change_queue_depth, | ||
68 | .slave_configure = beiscsi_slave_configure, | ||
69 | .target_alloc = iscsi_target_alloc, | ||
70 | .eh_device_reset_handler = iscsi_eh_device_reset, | ||
71 | .eh_target_reset_handler = iscsi_eh_target_reset, | ||
72 | .sg_tablesize = BEISCSI_SGLIST_ELEMENTS, | ||
73 | .can_queue = BE2_IO_DEPTH, | ||
74 | .this_id = -1, | ||
75 | .max_sectors = BEISCSI_MAX_SECTORS, | ||
76 | .cmd_per_lun = BEISCSI_CMD_PER_LUN, | ||
77 | .use_clustering = ENABLE_CLUSTERING, | ||
78 | }; | ||
79 | static struct scsi_transport_template *beiscsi_scsi_transport; | ||
80 | |||
81 | /*------------------- PCI Driver operations and data ----------------- */ | ||
82 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | ||
83 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | ||
84 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) }, | ||
85 | { PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) }, | ||
86 | { 0 } | ||
87 | }; | ||
88 | MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); | ||
89 | |||
90 | static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) | ||
91 | { | ||
92 | struct beiscsi_hba *phba; | ||
93 | struct Scsi_Host *shost; | ||
94 | |||
95 | shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0); | ||
96 | if (!shost) { | ||
97 | dev_err(&pcidev->dev, "beiscsi_hba_alloc -" | ||
98 | "iscsi_host_alloc failed \n"); | ||
99 | return NULL; | ||
100 | } | ||
101 | shost->dma_boundary = pcidev->dma_mask; | ||
102 | shost->max_id = BE2_MAX_SESSIONS; | ||
103 | shost->max_channel = 0; | ||
104 | shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; | ||
105 | shost->max_lun = BEISCSI_NUM_MAX_LUN; | ||
106 | shost->transportt = beiscsi_scsi_transport; | ||
107 | |||
108 | phba = iscsi_host_priv(shost); | ||
109 | memset(phba, 0, sizeof(*phba)); | ||
110 | phba->shost = shost; | ||
111 | phba->pcidev = pci_dev_get(pcidev); | ||
112 | |||
113 | if (iscsi_host_add(shost, &phba->pcidev->dev)) | ||
114 | goto free_devices; | ||
115 | return phba; | ||
116 | |||
117 | free_devices: | ||
118 | pci_dev_put(phba->pcidev); | ||
119 | iscsi_host_free(phba->shost); | ||
120 | return NULL; | ||
121 | } | ||
122 | |||
123 | static void beiscsi_unmap_pci_function(struct beiscsi_hba *phba) | ||
124 | { | ||
125 | if (phba->csr_va) { | ||
126 | iounmap(phba->csr_va); | ||
127 | phba->csr_va = NULL; | ||
128 | } | ||
129 | if (phba->db_va) { | ||
130 | iounmap(phba->db_va); | ||
131 | phba->db_va = NULL; | ||
132 | } | ||
133 | if (phba->pci_va) { | ||
134 | iounmap(phba->pci_va); | ||
135 | phba->pci_va = NULL; | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static int beiscsi_map_pci_bars(struct beiscsi_hba *phba, | ||
140 | struct pci_dev *pcidev) | ||
141 | { | ||
142 | u8 __iomem *addr; | ||
143 | |||
144 | addr = ioremap_nocache(pci_resource_start(pcidev, 2), | ||
145 | pci_resource_len(pcidev, 2)); | ||
146 | if (addr == NULL) | ||
147 | return -ENOMEM; | ||
148 | phba->ctrl.csr = addr; | ||
149 | phba->csr_va = addr; | ||
150 | phba->csr_pa.u.a64.address = pci_resource_start(pcidev, 2); | ||
151 | |||
152 | addr = ioremap_nocache(pci_resource_start(pcidev, 4), 128 * 1024); | ||
153 | if (addr == NULL) | ||
154 | goto pci_map_err; | ||
155 | phba->ctrl.db = addr; | ||
156 | phba->db_va = addr; | ||
157 | phba->db_pa.u.a64.address = pci_resource_start(pcidev, 4); | ||
158 | |||
159 | addr = ioremap_nocache(pci_resource_start(pcidev, 1), | ||
160 | pci_resource_len(pcidev, 1)); | ||
161 | if (addr == NULL) | ||
162 | goto pci_map_err; | ||
163 | phba->ctrl.pcicfg = addr; | ||
164 | phba->pci_va = addr; | ||
165 | phba->pci_pa.u.a64.address = pci_resource_start(pcidev, 1); | ||
166 | return 0; | ||
167 | |||
168 | pci_map_err: | ||
169 | beiscsi_unmap_pci_function(phba); | ||
170 | return -ENOMEM; | ||
171 | } | ||
172 | |||
173 | static int beiscsi_enable_pci(struct pci_dev *pcidev) | ||
174 | { | ||
175 | int ret; | ||
176 | |||
177 | ret = pci_enable_device(pcidev); | ||
178 | if (ret) { | ||
179 | dev_err(&pcidev->dev, "beiscsi_enable_pci - enable device " | ||
180 | "failed. Returning -ENODEV\n"); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) { | ||
185 | ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32)); | ||
186 | if (ret) { | ||
187 | dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n"); | ||
188 | pci_disable_device(pcidev); | ||
189 | return ret; | ||
190 | } | ||
191 | } | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev) | ||
196 | { | ||
197 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
198 | struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced; | ||
199 | struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem; | ||
200 | int status = 0; | ||
201 | |||
202 | ctrl->pdev = pdev; | ||
203 | status = beiscsi_map_pci_bars(phba, pdev); | ||
204 | if (status) | ||
205 | return status; | ||
206 | |||
207 | mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; | ||
208 | mbox_mem_alloc->va = pci_alloc_consistent(pdev, | ||
209 | mbox_mem_alloc->size, | ||
210 | &mbox_mem_alloc->dma); | ||
211 | if (!mbox_mem_alloc->va) { | ||
212 | beiscsi_unmap_pci_function(phba); | ||
213 | status = -ENOMEM; | ||
214 | return status; | ||
215 | } | ||
216 | |||
217 | mbox_mem_align->size = sizeof(struct be_mcc_mailbox); | ||
218 | mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); | ||
219 | mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); | ||
220 | memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); | ||
221 | spin_lock_init(&ctrl->mbox_lock); | ||
222 | return status; | ||
223 | } | ||
224 | |||
225 | static void beiscsi_get_params(struct beiscsi_hba *phba) | ||
226 | { | ||
227 | phba->params.ios_per_ctrl = BE2_IO_DEPTH; | ||
228 | phba->params.cxns_per_ctrl = BE2_MAX_SESSIONS; | ||
229 | phba->params.asyncpdus_per_ctrl = BE2_ASYNCPDUS; | ||
230 | phba->params.icds_per_ctrl = BE2_MAX_ICDS / 2; | ||
231 | phba->params.num_sge_per_io = BE2_SGE; | ||
232 | phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ; | ||
233 | phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ; | ||
234 | phba->params.eq_timer = 64; | ||
235 | phba->params.num_eq_entries = | ||
236 | (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) / | ||
237 | 512) + 1) * 512; | ||
238 | phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024) | ||
239 | ? 1024 : phba->params.num_eq_entries; | ||
240 | SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d \n", | ||
241 | phba->params.num_eq_entries); | ||
242 | phba->params.num_cq_entries = | ||
243 | (((BE2_CMDS_PER_CXN * 2 + BE2_LOGOUTS + BE2_TMFS + BE2_ASYNCPDUS) / | ||
244 | 512) + 1) * 512; | ||
245 | SE_DEBUG(DBG_LVL_8, | ||
246 | "phba->params.num_cq_entries=%d BE2_CMDS_PER_CXN=%d" | ||
247 | "BE2_LOGOUTS=%d BE2_TMFS=%d BE2_ASYNCPDUS=%d \n", | ||
248 | phba->params.num_cq_entries, BE2_CMDS_PER_CXN, | ||
249 | BE2_LOGOUTS, BE2_TMFS, BE2_ASYNCPDUS); | ||
250 | phba->params.wrbs_per_cxn = 256; | ||
251 | } | ||
252 | |||
253 | static void hwi_ring_eq_db(struct beiscsi_hba *phba, | ||
254 | unsigned int id, unsigned int clr_interrupt, | ||
255 | unsigned int num_processed, | ||
256 | unsigned char rearm, unsigned char event) | ||
257 | { | ||
258 | u32 val = 0; | ||
259 | val |= id & DB_EQ_RING_ID_MASK; | ||
260 | if (rearm) | ||
261 | val |= 1 << DB_EQ_REARM_SHIFT; | ||
262 | if (clr_interrupt) | ||
263 | val |= 1 << DB_EQ_CLR_SHIFT; | ||
264 | if (event) | ||
265 | val |= 1 << DB_EQ_EVNT_SHIFT; | ||
266 | val |= num_processed << DB_EQ_NUM_POPPED_SHIFT; | ||
267 | iowrite32(val, phba->db_va + DB_EQ_OFFSET); | ||
268 | } | ||
269 | |||
270 | /** | ||
271 | * be_isr - The isr routine of the driver. | ||
272 | * @irq: Not used | ||
273 | * @dev_id: Pointer to host adapter structure | ||
274 | */ | ||
275 | static irqreturn_t be_isr(int irq, void *dev_id) | ||
276 | { | ||
277 | struct beiscsi_hba *phba; | ||
278 | struct hwi_controller *phwi_ctrlr; | ||
279 | struct hwi_context_memory *phwi_context; | ||
280 | struct be_eq_entry *eqe = NULL; | ||
281 | struct be_queue_info *eq; | ||
282 | struct be_queue_info *cq; | ||
283 | unsigned long flags, index; | ||
284 | unsigned int num_eq_processed; | ||
285 | struct be_ctrl_info *ctrl; | ||
286 | int isr; | ||
287 | |||
288 | phba = dev_id; | ||
289 | if (!enable_msix) { | ||
290 | ctrl = &phba->ctrl;; | ||
291 | isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET + | ||
292 | (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE)); | ||
293 | if (!isr) | ||
294 | return IRQ_NONE; | ||
295 | } | ||
296 | |||
297 | phwi_ctrlr = phba->phwi_ctrlr; | ||
298 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
299 | eq = &phwi_context->be_eq.q; | ||
300 | cq = &phwi_context->be_cq; | ||
301 | index = 0; | ||
302 | eqe = queue_tail_node(eq); | ||
303 | if (!eqe) | ||
304 | SE_DEBUG(DBG_LVL_1, "eqe is NULL\n"); | ||
305 | |||
306 | num_eq_processed = 0; | ||
307 | if (blk_iopoll_enabled) { | ||
308 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
309 | & EQE_VALID_MASK) { | ||
310 | if (!blk_iopoll_sched_prep(&phba->iopoll)) | ||
311 | blk_iopoll_sched(&phba->iopoll); | ||
312 | |||
313 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
314 | queue_tail_inc(eq); | ||
315 | eqe = queue_tail_node(eq); | ||
316 | num_eq_processed++; | ||
317 | SE_DEBUG(DBG_LVL_8, "Valid EQE\n"); | ||
318 | } | ||
319 | if (num_eq_processed) { | ||
320 | hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 0, 1); | ||
321 | return IRQ_HANDLED; | ||
322 | } else | ||
323 | return IRQ_NONE; | ||
324 | } else { | ||
325 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
326 | & EQE_VALID_MASK) { | ||
327 | |||
328 | if (((eqe->dw[offsetof(struct amap_eq_entry, | ||
329 | resource_id) / 32] & | ||
330 | EQE_RESID_MASK) >> 16) != cq->id) { | ||
331 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
332 | phba->todo_mcc_cq = 1; | ||
333 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
334 | } else { | ||
335 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
336 | phba->todo_cq = 1; | ||
337 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
338 | } | ||
339 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
340 | queue_tail_inc(eq); | ||
341 | eqe = queue_tail_node(eq); | ||
342 | num_eq_processed++; | ||
343 | } | ||
344 | if (phba->todo_cq || phba->todo_mcc_cq) | ||
345 | queue_work(phba->wq, &phba->work_cqs); | ||
346 | |||
347 | if (num_eq_processed) { | ||
348 | hwi_ring_eq_db(phba, eq->id, 0, num_eq_processed, 1, 1); | ||
349 | return IRQ_HANDLED; | ||
350 | } else | ||
351 | return IRQ_NONE; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | static int beiscsi_init_irqs(struct beiscsi_hba *phba) | ||
356 | { | ||
357 | struct pci_dev *pcidev = phba->pcidev; | ||
358 | int ret; | ||
359 | |||
360 | ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED, "beiscsi", phba); | ||
361 | if (ret) { | ||
362 | shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-" | ||
363 | "Failed to register irq\\n"); | ||
364 | return ret; | ||
365 | } | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static void hwi_ring_cq_db(struct beiscsi_hba *phba, | ||
370 | unsigned int id, unsigned int num_processed, | ||
371 | unsigned char rearm, unsigned char event) | ||
372 | { | ||
373 | u32 val = 0; | ||
374 | val |= id & DB_CQ_RING_ID_MASK; | ||
375 | if (rearm) | ||
376 | val |= 1 << DB_CQ_REARM_SHIFT; | ||
377 | val |= num_processed << DB_CQ_NUM_POPPED_SHIFT; | ||
378 | iowrite32(val, phba->db_va + DB_CQ_OFFSET); | ||
379 | } | ||
380 | |||
381 | /* | ||
382 | * async pdus include | ||
383 | * a. unsolicited NOP-In (target initiated NOP-In) | ||
384 | * b. Async Messages | ||
385 | * c. Reject PDU | ||
386 | * d. Login response | ||
387 | * These headers arrive unprocessed by the EP firmware and iSCSI layer | ||
388 | * process them | ||
389 | */ | ||
390 | static unsigned int | ||
391 | beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn, | ||
392 | struct beiscsi_hba *phba, | ||
393 | unsigned short cid, | ||
394 | struct pdu_base *ppdu, | ||
395 | unsigned long pdu_len, | ||
396 | void *pbuffer, unsigned long buf_len) | ||
397 | { | ||
398 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
399 | struct iscsi_session *session = conn->session; | ||
400 | |||
401 | switch (ppdu->dw[offsetof(struct amap_pdu_base, opcode) / 32] & | ||
402 | PDUBASE_OPCODE_MASK) { | ||
403 | case ISCSI_OP_NOOP_IN: | ||
404 | pbuffer = NULL; | ||
405 | buf_len = 0; | ||
406 | break; | ||
407 | case ISCSI_OP_ASYNC_EVENT: | ||
408 | break; | ||
409 | case ISCSI_OP_REJECT: | ||
410 | WARN_ON(!pbuffer); | ||
411 | WARN_ON(!(buf_len == 48)); | ||
412 | SE_DEBUG(DBG_LVL_1, "In ISCSI_OP_REJECT\n"); | ||
413 | break; | ||
414 | case ISCSI_OP_LOGIN_RSP: | ||
415 | break; | ||
416 | default: | ||
417 | shost_printk(KERN_WARNING, phba->shost, | ||
418 | "Unrecognized opcode 0x%x in async msg \n", | ||
419 | (ppdu-> | ||
420 | dw[offsetof(struct amap_pdu_base, opcode) / 32] | ||
421 | & PDUBASE_OPCODE_MASK)); | ||
422 | return 1; | ||
423 | } | ||
424 | |||
425 | spin_lock_bh(&session->lock); | ||
426 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)ppdu, pbuffer, buf_len); | ||
427 | spin_unlock_bh(&session->lock); | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba) | ||
432 | { | ||
433 | struct sgl_handle *psgl_handle; | ||
434 | |||
435 | if (phba->io_sgl_hndl_avbl) { | ||
436 | SE_DEBUG(DBG_LVL_8, | ||
437 | "In alloc_io_sgl_handle,io_sgl_alloc_index=%d \n", | ||
438 | phba->io_sgl_alloc_index); | ||
439 | psgl_handle = phba->io_sgl_hndl_base[phba-> | ||
440 | io_sgl_alloc_index]; | ||
441 | phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL; | ||
442 | phba->io_sgl_hndl_avbl--; | ||
443 | if (phba->io_sgl_alloc_index == (phba->params.ios_per_ctrl - 1)) | ||
444 | phba->io_sgl_alloc_index = 0; | ||
445 | else | ||
446 | phba->io_sgl_alloc_index++; | ||
447 | } else | ||
448 | psgl_handle = NULL; | ||
449 | return psgl_handle; | ||
450 | } | ||
451 | |||
452 | static void | ||
453 | free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) | ||
454 | { | ||
455 | SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d \n", | ||
456 | phba->io_sgl_free_index); | ||
457 | if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) { | ||
458 | /* | ||
459 | * this can happen if clean_task is called on a task that | ||
460 | * failed in xmit_task or alloc_pdu. | ||
461 | */ | ||
462 | SE_DEBUG(DBG_LVL_8, | ||
463 | "Double Free in IO SGL io_sgl_free_index=%d," | ||
464 | "value there=%p \n", phba->io_sgl_free_index, | ||
465 | phba->io_sgl_hndl_base[phba->io_sgl_free_index]); | ||
466 | return; | ||
467 | } | ||
468 | phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle; | ||
469 | phba->io_sgl_hndl_avbl++; | ||
470 | if (phba->io_sgl_free_index == (phba->params.ios_per_ctrl - 1)) | ||
471 | phba->io_sgl_free_index = 0; | ||
472 | else | ||
473 | phba->io_sgl_free_index++; | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * alloc_wrb_handle - To allocate a wrb handle | ||
478 | * @phba: The hba pointer | ||
479 | * @cid: The cid to use for allocation | ||
480 | * @index: index allocation and wrb index | ||
481 | * | ||
482 | * This happens under session_lock until submission to chip | ||
483 | */ | ||
484 | struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, | ||
485 | int index) | ||
486 | { | ||
487 | struct hwi_wrb_context *pwrb_context; | ||
488 | struct hwi_controller *phwi_ctrlr; | ||
489 | struct wrb_handle *pwrb_handle; | ||
490 | |||
491 | phwi_ctrlr = phba->phwi_ctrlr; | ||
492 | pwrb_context = &phwi_ctrlr->wrb_context[cid]; | ||
493 | pwrb_handle = pwrb_context->pwrb_handle_base[index]; | ||
494 | pwrb_handle->wrb_index = index; | ||
495 | pwrb_handle->nxt_wrb_index = index; | ||
496 | return pwrb_handle; | ||
497 | } | ||
498 | |||
499 | /** | ||
500 | * free_wrb_handle - To free the wrb handle back to pool | ||
501 | * @phba: The hba pointer | ||
502 | * @pwrb_context: The context to free from | ||
503 | * @pwrb_handle: The wrb_handle to free | ||
504 | * | ||
505 | * This happens under session_lock until submission to chip | ||
506 | */ | ||
507 | static void | ||
508 | free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context, | ||
509 | struct wrb_handle *pwrb_handle) | ||
510 | { | ||
511 | SE_DEBUG(DBG_LVL_8, | ||
512 | "FREE WRB: pwrb_handle=%p free_index=%d=0x%x" | ||
513 | "wrb_handles_available=%d \n", | ||
514 | pwrb_handle, pwrb_context->free_index, | ||
515 | pwrb_context->free_index, pwrb_context->wrb_handles_available); | ||
516 | } | ||
517 | |||
518 | static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) | ||
519 | { | ||
520 | struct sgl_handle *psgl_handle; | ||
521 | |||
522 | if (phba->eh_sgl_hndl_avbl) { | ||
523 | psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index]; | ||
524 | phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL; | ||
525 | SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x \n", | ||
526 | phba->eh_sgl_alloc_index, phba->eh_sgl_alloc_index); | ||
527 | phba->eh_sgl_hndl_avbl--; | ||
528 | if (phba->eh_sgl_alloc_index == | ||
529 | (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - | ||
530 | 1)) | ||
531 | phba->eh_sgl_alloc_index = 0; | ||
532 | else | ||
533 | phba->eh_sgl_alloc_index++; | ||
534 | } else | ||
535 | psgl_handle = NULL; | ||
536 | return psgl_handle; | ||
537 | } | ||
538 | |||
539 | void | ||
540 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle) | ||
541 | { | ||
542 | |||
543 | if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) { | ||
544 | /* | ||
545 | * this can happen if clean_task is called on a task that | ||
546 | * failed in xmit_task or alloc_pdu. | ||
547 | */ | ||
548 | SE_DEBUG(DBG_LVL_8, | ||
549 | "Double Free in eh SGL ,eh_sgl_free_index=%d \n", | ||
550 | phba->eh_sgl_free_index); | ||
551 | return; | ||
552 | } | ||
553 | phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle; | ||
554 | phba->eh_sgl_hndl_avbl++; | ||
555 | if (phba->eh_sgl_free_index == | ||
556 | (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - 1)) | ||
557 | phba->eh_sgl_free_index = 0; | ||
558 | else | ||
559 | phba->eh_sgl_free_index++; | ||
560 | } | ||
561 | |||
562 | static void | ||
563 | be_complete_io(struct beiscsi_conn *beiscsi_conn, | ||
564 | struct iscsi_task *task, struct sol_cqe *psol) | ||
565 | { | ||
566 | struct beiscsi_io_task *io_task = task->dd_data; | ||
567 | struct be_status_bhs *sts_bhs = | ||
568 | (struct be_status_bhs *)io_task->cmd_bhs; | ||
569 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
570 | unsigned int sense_len; | ||
571 | unsigned char *sense; | ||
572 | u32 resid = 0, exp_cmdsn, max_cmdsn; | ||
573 | u8 rsp, status, flags; | ||
574 | |||
575 | exp_cmdsn = be32_to_cpu(psol-> | ||
576 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] | ||
577 | & SOL_EXP_CMD_SN_MASK); | ||
578 | max_cmdsn = be32_to_cpu((psol-> | ||
579 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] | ||
580 | & SOL_EXP_CMD_SN_MASK) + | ||
581 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | ||
582 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); | ||
583 | rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32] | ||
584 | & SOL_RESP_MASK) >> 16); | ||
585 | status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32] | ||
586 | & SOL_STS_MASK) >> 8); | ||
587 | flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] | ||
588 | & SOL_FLAGS_MASK) >> 24) | 0x80; | ||
589 | |||
590 | task->sc->result = (DID_OK << 16) | status; | ||
591 | if (rsp != ISCSI_STATUS_CMD_COMPLETED) { | ||
592 | task->sc->result = DID_ERROR << 16; | ||
593 | goto unmap; | ||
594 | } | ||
595 | |||
596 | /* bidi not initially supported */ | ||
597 | if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) { | ||
598 | resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / | ||
599 | 32] & SOL_RES_CNT_MASK); | ||
600 | |||
601 | if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW)) | ||
602 | task->sc->result = DID_ERROR << 16; | ||
603 | |||
604 | if (flags & ISCSI_FLAG_CMD_UNDERFLOW) { | ||
605 | scsi_set_resid(task->sc, resid); | ||
606 | if (!status && (scsi_bufflen(task->sc) - resid < | ||
607 | task->sc->underflow)) | ||
608 | task->sc->result = DID_ERROR << 16; | ||
609 | } | ||
610 | } | ||
611 | |||
612 | if (status == SAM_STAT_CHECK_CONDITION) { | ||
613 | sense = sts_bhs->sense_info + sizeof(unsigned short); | ||
614 | sense_len = | ||
615 | cpu_to_be16((unsigned short)(sts_bhs->sense_info[0])); | ||
616 | memcpy(task->sc->sense_buffer, sense, | ||
617 | min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE)); | ||
618 | } | ||
619 | if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) { | ||
620 | if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] | ||
621 | & SOL_RES_CNT_MASK) | ||
622 | conn->rxdata_octets += (psol-> | ||
623 | dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] | ||
624 | & SOL_RES_CNT_MASK); | ||
625 | } | ||
626 | unmap: | ||
627 | scsi_dma_unmap(io_task->scsi_cmnd); | ||
628 | iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn); | ||
629 | } | ||
630 | |||
631 | static void | ||
632 | be_complete_logout(struct beiscsi_conn *beiscsi_conn, | ||
633 | struct iscsi_task *task, struct sol_cqe *psol) | ||
634 | { | ||
635 | struct iscsi_logout_rsp *hdr; | ||
636 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
637 | |||
638 | hdr = (struct iscsi_logout_rsp *)task->hdr; | ||
639 | hdr->t2wait = 5; | ||
640 | hdr->t2retain = 0; | ||
641 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] | ||
642 | & SOL_FLAGS_MASK) >> 24) | 0x80; | ||
643 | hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / | ||
644 | 32] & SOL_RESP_MASK); | ||
645 | hdr->exp_cmdsn = cpu_to_be32(psol-> | ||
646 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] | ||
647 | & SOL_EXP_CMD_SN_MASK); | ||
648 | hdr->max_cmdsn = be32_to_cpu((psol-> | ||
649 | dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] | ||
650 | & SOL_EXP_CMD_SN_MASK) + | ||
651 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | ||
652 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); | ||
653 | hdr->hlength = 0; | ||
654 | |||
655 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); | ||
656 | } | ||
657 | |||
658 | static void | ||
659 | be_complete_tmf(struct beiscsi_conn *beiscsi_conn, | ||
660 | struct iscsi_task *task, struct sol_cqe *psol) | ||
661 | { | ||
662 | struct iscsi_tm_rsp *hdr; | ||
663 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
664 | |||
665 | hdr = (struct iscsi_tm_rsp *)task->hdr; | ||
666 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] | ||
667 | & SOL_FLAGS_MASK) >> 24) | 0x80; | ||
668 | hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / | ||
669 | 32] & SOL_RESP_MASK); | ||
670 | hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, | ||
671 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); | ||
672 | hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, | ||
673 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + | ||
674 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | ||
675 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); | ||
676 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); | ||
677 | } | ||
678 | |||
679 | static void | ||
680 | hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, | ||
681 | struct beiscsi_hba *phba, struct sol_cqe *psol) | ||
682 | { | ||
683 | struct hwi_wrb_context *pwrb_context; | ||
684 | struct wrb_handle *pwrb_handle; | ||
685 | struct hwi_controller *phwi_ctrlr; | ||
686 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
687 | struct iscsi_session *session = conn->session; | ||
688 | |||
689 | phwi_ctrlr = phba->phwi_ctrlr; | ||
690 | pwrb_context = &phwi_ctrlr->wrb_context[((psol-> | ||
691 | dw[offsetof(struct amap_sol_cqe, cid) / 32] & | ||
692 | SOL_CID_MASK) >> 6)]; | ||
693 | pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> | ||
694 | dw[offsetof(struct amap_sol_cqe, wrb_index) / | ||
695 | 32] & SOL_WRB_INDEX_MASK) >> 16)]; | ||
696 | spin_lock_bh(&session->lock); | ||
697 | free_wrb_handle(phba, pwrb_context, pwrb_handle); | ||
698 | spin_unlock_bh(&session->lock); | ||
699 | } | ||
700 | |||
701 | static void | ||
702 | be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn, | ||
703 | struct iscsi_task *task, struct sol_cqe *psol) | ||
704 | { | ||
705 | struct iscsi_nopin *hdr; | ||
706 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
707 | |||
708 | hdr = (struct iscsi_nopin *)task->hdr; | ||
709 | hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] | ||
710 | & SOL_FLAGS_MASK) >> 24) | 0x80; | ||
711 | hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, | ||
712 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); | ||
713 | hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, | ||
714 | i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + | ||
715 | ((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) | ||
716 | / 32] & SOL_CMD_WND_MASK) >> 24) - 1); | ||
717 | hdr->opcode = ISCSI_OP_NOOP_IN; | ||
718 | __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0); | ||
719 | } | ||
720 | |||
721 | static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn, | ||
722 | struct beiscsi_hba *phba, struct sol_cqe *psol) | ||
723 | { | ||
724 | struct hwi_wrb_context *pwrb_context; | ||
725 | struct wrb_handle *pwrb_handle; | ||
726 | struct iscsi_wrb *pwrb = NULL; | ||
727 | struct hwi_controller *phwi_ctrlr; | ||
728 | struct iscsi_task *task; | ||
729 | struct beiscsi_io_task *io_task; | ||
730 | struct iscsi_conn *conn = beiscsi_conn->conn; | ||
731 | struct iscsi_session *session = conn->session; | ||
732 | |||
733 | phwi_ctrlr = phba->phwi_ctrlr; | ||
734 | |||
735 | pwrb_context = &phwi_ctrlr-> | ||
736 | wrb_context[((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32] | ||
737 | & SOL_CID_MASK) >> 6)]; | ||
738 | pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> | ||
739 | dw[offsetof(struct amap_sol_cqe, wrb_index) / | ||
740 | 32] & SOL_WRB_INDEX_MASK) >> 16)]; | ||
741 | |||
742 | task = pwrb_handle->pio_handle; | ||
743 | io_task = task->dd_data; | ||
744 | spin_lock_bh(&session->lock); | ||
745 | pwrb = pwrb_handle->pwrb; | ||
746 | switch ((pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] & | ||
747 | WRB_TYPE_MASK) >> 28) { | ||
748 | case HWH_TYPE_IO: | ||
749 | case HWH_TYPE_IO_RD: | ||
750 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == | ||
751 | ISCSI_OP_NOOP_OUT) { | ||
752 | be_complete_nopin_resp(beiscsi_conn, task, psol); | ||
753 | } else | ||
754 | be_complete_io(beiscsi_conn, task, psol); | ||
755 | break; | ||
756 | |||
757 | case HWH_TYPE_LOGOUT: | ||
758 | be_complete_logout(beiscsi_conn, task, psol); | ||
759 | break; | ||
760 | |||
761 | case HWH_TYPE_LOGIN: | ||
762 | SE_DEBUG(DBG_LVL_1, | ||
763 | "\t\t No HWH_TYPE_LOGIN Expected in hwi_complete_cmd" | ||
764 | "- Solicited path \n"); | ||
765 | break; | ||
766 | |||
767 | case HWH_TYPE_TMF: | ||
768 | be_complete_tmf(beiscsi_conn, task, psol); | ||
769 | break; | ||
770 | |||
771 | case HWH_TYPE_NOP: | ||
772 | be_complete_nopin_resp(beiscsi_conn, task, psol); | ||
773 | break; | ||
774 | |||
775 | default: | ||
776 | shost_printk(KERN_WARNING, phba->shost, | ||
777 | "wrb_index 0x%x CID 0x%x\n", | ||
778 | ((psol->dw[offsetof(struct amap_iscsi_wrb, type) / | ||
779 | 32] & SOL_WRB_INDEX_MASK) >> 16), | ||
780 | ((psol->dw[offsetof(struct amap_sol_cqe, cid) / 32] | ||
781 | & SOL_CID_MASK) >> 6)); | ||
782 | break; | ||
783 | } | ||
784 | |||
785 | spin_unlock_bh(&session->lock); | ||
786 | } | ||
787 | |||
788 | static struct list_head *hwi_get_async_busy_list(struct hwi_async_pdu_context | ||
789 | *pasync_ctx, unsigned int is_header, | ||
790 | unsigned int host_write_ptr) | ||
791 | { | ||
792 | if (is_header) | ||
793 | return &pasync_ctx->async_entry[host_write_ptr]. | ||
794 | header_busy_list; | ||
795 | else | ||
796 | return &pasync_ctx->async_entry[host_write_ptr].data_busy_list; | ||
797 | } | ||
798 | |||
799 | static struct async_pdu_handle * | ||
800 | hwi_get_async_handle(struct beiscsi_hba *phba, | ||
801 | struct beiscsi_conn *beiscsi_conn, | ||
802 | struct hwi_async_pdu_context *pasync_ctx, | ||
803 | struct i_t_dpdu_cqe *pdpdu_cqe, unsigned int *pcq_index) | ||
804 | { | ||
805 | struct be_bus_address phys_addr; | ||
806 | struct list_head *pbusy_list; | ||
807 | struct async_pdu_handle *pasync_handle = NULL; | ||
808 | int buffer_len = 0; | ||
809 | unsigned char buffer_index = -1; | ||
810 | unsigned char is_header = 0; | ||
811 | |||
812 | phys_addr.u.a32.address_lo = | ||
813 | pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] - | ||
814 | ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] | ||
815 | & PDUCQE_DPL_MASK) >> 16); | ||
816 | phys_addr.u.a32.address_hi = | ||
817 | pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32]; | ||
818 | |||
819 | phys_addr.u.a64.address = | ||
820 | *((unsigned long long *)(&phys_addr.u.a64.address)); | ||
821 | |||
822 | switch (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, code) / 32] | ||
823 | & PDUCQE_CODE_MASK) { | ||
824 | case UNSOL_HDR_NOTIFY: | ||
825 | is_header = 1; | ||
826 | |||
827 | pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1, | ||
828 | (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | ||
829 | index) / 32] & PDUCQE_INDEX_MASK)); | ||
830 | |||
831 | buffer_len = (unsigned int)(phys_addr.u.a64.address - | ||
832 | pasync_ctx->async_header.pa_base.u.a64.address); | ||
833 | |||
834 | buffer_index = buffer_len / | ||
835 | pasync_ctx->async_header.buffer_size; | ||
836 | |||
837 | break; | ||
838 | case UNSOL_DATA_NOTIFY: | ||
839 | pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe-> | ||
840 | dw[offsetof(struct amap_i_t_dpdu_cqe, | ||
841 | index) / 32] & PDUCQE_INDEX_MASK)); | ||
842 | buffer_len = (unsigned long)(phys_addr.u.a64.address - | ||
843 | pasync_ctx->async_data.pa_base.u. | ||
844 | a64.address); | ||
845 | buffer_index = buffer_len / pasync_ctx->async_data.buffer_size; | ||
846 | break; | ||
847 | default: | ||
848 | pbusy_list = NULL; | ||
849 | shost_printk(KERN_WARNING, phba->shost, | ||
850 | "Unexpected code=%d \n", | ||
851 | pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | ||
852 | code) / 32] & PDUCQE_CODE_MASK); | ||
853 | return NULL; | ||
854 | } | ||
855 | |||
856 | WARN_ON(!(buffer_index <= pasync_ctx->async_data.num_entries)); | ||
857 | WARN_ON(list_empty(pbusy_list)); | ||
858 | list_for_each_entry(pasync_handle, pbusy_list, link) { | ||
859 | WARN_ON(pasync_handle->consumed); | ||
860 | if (pasync_handle->index == buffer_index) | ||
861 | break; | ||
862 | } | ||
863 | |||
864 | WARN_ON(!pasync_handle); | ||
865 | |||
866 | pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid; | ||
867 | pasync_handle->is_header = is_header; | ||
868 | pasync_handle->buffer_len = ((pdpdu_cqe-> | ||
869 | dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] | ||
870 | & PDUCQE_DPL_MASK) >> 16); | ||
871 | |||
872 | *pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, | ||
873 | index) / 32] & PDUCQE_INDEX_MASK); | ||
874 | return pasync_handle; | ||
875 | } | ||
876 | |||
877 | static unsigned int | ||
878 | hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx, | ||
879 | unsigned int is_header, unsigned int cq_index) | ||
880 | { | ||
881 | struct list_head *pbusy_list; | ||
882 | struct async_pdu_handle *pasync_handle; | ||
883 | unsigned int num_entries, writables = 0; | ||
884 | unsigned int *pep_read_ptr, *pwritables; | ||
885 | |||
886 | |||
887 | if (is_header) { | ||
888 | pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr; | ||
889 | pwritables = &pasync_ctx->async_header.writables; | ||
890 | num_entries = pasync_ctx->async_header.num_entries; | ||
891 | } else { | ||
892 | pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr; | ||
893 | pwritables = &pasync_ctx->async_data.writables; | ||
894 | num_entries = pasync_ctx->async_data.num_entries; | ||
895 | } | ||
896 | |||
897 | while ((*pep_read_ptr) != cq_index) { | ||
898 | (*pep_read_ptr)++; | ||
899 | *pep_read_ptr = (*pep_read_ptr) % num_entries; | ||
900 | |||
901 | pbusy_list = hwi_get_async_busy_list(pasync_ctx, is_header, | ||
902 | *pep_read_ptr); | ||
903 | if (writables == 0) | ||
904 | WARN_ON(list_empty(pbusy_list)); | ||
905 | |||
906 | if (!list_empty(pbusy_list)) { | ||
907 | pasync_handle = list_entry(pbusy_list->next, | ||
908 | struct async_pdu_handle, | ||
909 | link); | ||
910 | WARN_ON(!pasync_handle); | ||
911 | pasync_handle->consumed = 1; | ||
912 | } | ||
913 | |||
914 | writables++; | ||
915 | } | ||
916 | |||
917 | if (!writables) { | ||
918 | SE_DEBUG(DBG_LVL_1, | ||
919 | "Duplicate notification received - index 0x%x!!\n", | ||
920 | cq_index); | ||
921 | WARN_ON(1); | ||
922 | } | ||
923 | |||
924 | *pwritables = *pwritables + writables; | ||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static unsigned int hwi_free_async_msg(struct beiscsi_hba *phba, | ||
929 | unsigned int cri) | ||
930 | { | ||
931 | struct hwi_controller *phwi_ctrlr; | ||
932 | struct hwi_async_pdu_context *pasync_ctx; | ||
933 | struct async_pdu_handle *pasync_handle, *tmp_handle; | ||
934 | struct list_head *plist; | ||
935 | unsigned int i = 0; | ||
936 | |||
937 | phwi_ctrlr = phba->phwi_ctrlr; | ||
938 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | ||
939 | |||
940 | plist = &pasync_ctx->async_entry[cri].wait_queue.list; | ||
941 | |||
942 | list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) { | ||
943 | list_del(&pasync_handle->link); | ||
944 | |||
945 | if (i == 0) { | ||
946 | list_add_tail(&pasync_handle->link, | ||
947 | &pasync_ctx->async_header.free_list); | ||
948 | pasync_ctx->async_header.free_entries++; | ||
949 | i++; | ||
950 | } else { | ||
951 | list_add_tail(&pasync_handle->link, | ||
952 | &pasync_ctx->async_data.free_list); | ||
953 | pasync_ctx->async_data.free_entries++; | ||
954 | i++; | ||
955 | } | ||
956 | } | ||
957 | |||
958 | INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list); | ||
959 | pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0; | ||
960 | pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; | ||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | static struct phys_addr * | ||
965 | hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx, | ||
966 | unsigned int is_header, unsigned int host_write_ptr) | ||
967 | { | ||
968 | struct phys_addr *pasync_sge = NULL; | ||
969 | |||
970 | if (is_header) | ||
971 | pasync_sge = pasync_ctx->async_header.ring_base; | ||
972 | else | ||
973 | pasync_sge = pasync_ctx->async_data.ring_base; | ||
974 | |||
975 | return pasync_sge + host_write_ptr; | ||
976 | } | ||
977 | |||
978 | static void hwi_post_async_buffers(struct beiscsi_hba *phba, | ||
979 | unsigned int is_header) | ||
980 | { | ||
981 | struct hwi_controller *phwi_ctrlr; | ||
982 | struct hwi_async_pdu_context *pasync_ctx; | ||
983 | struct async_pdu_handle *pasync_handle; | ||
984 | struct list_head *pfree_link, *pbusy_list; | ||
985 | struct phys_addr *pasync_sge; | ||
986 | unsigned int ring_id, num_entries; | ||
987 | unsigned int host_write_num; | ||
988 | unsigned int writables; | ||
989 | unsigned int i = 0; | ||
990 | u32 doorbell = 0; | ||
991 | |||
992 | phwi_ctrlr = phba->phwi_ctrlr; | ||
993 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | ||
994 | |||
995 | if (is_header) { | ||
996 | num_entries = pasync_ctx->async_header.num_entries; | ||
997 | writables = min(pasync_ctx->async_header.writables, | ||
998 | pasync_ctx->async_header.free_entries); | ||
999 | pfree_link = pasync_ctx->async_header.free_list.next; | ||
1000 | host_write_num = pasync_ctx->async_header.host_write_ptr; | ||
1001 | ring_id = phwi_ctrlr->default_pdu_hdr.id; | ||
1002 | } else { | ||
1003 | num_entries = pasync_ctx->async_data.num_entries; | ||
1004 | writables = min(pasync_ctx->async_data.writables, | ||
1005 | pasync_ctx->async_data.free_entries); | ||
1006 | pfree_link = pasync_ctx->async_data.free_list.next; | ||
1007 | host_write_num = pasync_ctx->async_data.host_write_ptr; | ||
1008 | ring_id = phwi_ctrlr->default_pdu_data.id; | ||
1009 | } | ||
1010 | |||
1011 | writables = (writables / 8) * 8; | ||
1012 | if (writables) { | ||
1013 | for (i = 0; i < writables; i++) { | ||
1014 | pbusy_list = | ||
1015 | hwi_get_async_busy_list(pasync_ctx, is_header, | ||
1016 | host_write_num); | ||
1017 | pasync_handle = | ||
1018 | list_entry(pfree_link, struct async_pdu_handle, | ||
1019 | link); | ||
1020 | WARN_ON(!pasync_handle); | ||
1021 | pasync_handle->consumed = 0; | ||
1022 | |||
1023 | pfree_link = pfree_link->next; | ||
1024 | |||
1025 | pasync_sge = hwi_get_ring_address(pasync_ctx, | ||
1026 | is_header, host_write_num); | ||
1027 | |||
1028 | pasync_sge->hi = pasync_handle->pa.u.a32.address_lo; | ||
1029 | pasync_sge->lo = pasync_handle->pa.u.a32.address_hi; | ||
1030 | |||
1031 | list_move(&pasync_handle->link, pbusy_list); | ||
1032 | |||
1033 | host_write_num++; | ||
1034 | host_write_num = host_write_num % num_entries; | ||
1035 | } | ||
1036 | |||
1037 | if (is_header) { | ||
1038 | pasync_ctx->async_header.host_write_ptr = | ||
1039 | host_write_num; | ||
1040 | pasync_ctx->async_header.free_entries -= writables; | ||
1041 | pasync_ctx->async_header.writables -= writables; | ||
1042 | pasync_ctx->async_header.busy_entries += writables; | ||
1043 | } else { | ||
1044 | pasync_ctx->async_data.host_write_ptr = host_write_num; | ||
1045 | pasync_ctx->async_data.free_entries -= writables; | ||
1046 | pasync_ctx->async_data.writables -= writables; | ||
1047 | pasync_ctx->async_data.busy_entries += writables; | ||
1048 | } | ||
1049 | |||
1050 | doorbell |= ring_id & DB_DEF_PDU_RING_ID_MASK; | ||
1051 | doorbell |= 1 << DB_DEF_PDU_REARM_SHIFT; | ||
1052 | doorbell |= 0 << DB_DEF_PDU_EVENT_SHIFT; | ||
1053 | doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK) | ||
1054 | << DB_DEF_PDU_CQPROC_SHIFT; | ||
1055 | |||
1056 | iowrite32(doorbell, phba->db_va + DB_RXULP0_OFFSET); | ||
1057 | } | ||
1058 | } | ||
1059 | |||
1060 | static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba, | ||
1061 | struct beiscsi_conn *beiscsi_conn, | ||
1062 | struct i_t_dpdu_cqe *pdpdu_cqe) | ||
1063 | { | ||
1064 | struct hwi_controller *phwi_ctrlr; | ||
1065 | struct hwi_async_pdu_context *pasync_ctx; | ||
1066 | struct async_pdu_handle *pasync_handle = NULL; | ||
1067 | unsigned int cq_index = -1; | ||
1068 | |||
1069 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1070 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | ||
1071 | |||
1072 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, | ||
1073 | pdpdu_cqe, &cq_index); | ||
1074 | BUG_ON(pasync_handle->is_header != 0); | ||
1075 | if (pasync_handle->consumed == 0) | ||
1076 | hwi_update_async_writables(pasync_ctx, pasync_handle->is_header, | ||
1077 | cq_index); | ||
1078 | |||
1079 | hwi_free_async_msg(phba, pasync_handle->cri); | ||
1080 | hwi_post_async_buffers(phba, pasync_handle->is_header); | ||
1081 | } | ||
1082 | |||
1083 | static unsigned int | ||
1084 | hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn, | ||
1085 | struct beiscsi_hba *phba, | ||
1086 | struct hwi_async_pdu_context *pasync_ctx, unsigned short cri) | ||
1087 | { | ||
1088 | struct list_head *plist; | ||
1089 | struct async_pdu_handle *pasync_handle; | ||
1090 | void *phdr = NULL; | ||
1091 | unsigned int hdr_len = 0, buf_len = 0; | ||
1092 | unsigned int status, index = 0, offset = 0; | ||
1093 | void *pfirst_buffer = NULL; | ||
1094 | unsigned int num_buf = 0; | ||
1095 | |||
1096 | plist = &pasync_ctx->async_entry[cri].wait_queue.list; | ||
1097 | |||
1098 | list_for_each_entry(pasync_handle, plist, link) { | ||
1099 | if (index == 0) { | ||
1100 | phdr = pasync_handle->pbuffer; | ||
1101 | hdr_len = pasync_handle->buffer_len; | ||
1102 | } else { | ||
1103 | buf_len = pasync_handle->buffer_len; | ||
1104 | if (!num_buf) { | ||
1105 | pfirst_buffer = pasync_handle->pbuffer; | ||
1106 | num_buf++; | ||
1107 | } | ||
1108 | memcpy(pfirst_buffer + offset, | ||
1109 | pasync_handle->pbuffer, buf_len); | ||
1110 | offset = buf_len; | ||
1111 | } | ||
1112 | index++; | ||
1113 | } | ||
1114 | |||
1115 | status = beiscsi_process_async_pdu(beiscsi_conn, phba, | ||
1116 | beiscsi_conn->beiscsi_conn_cid, | ||
1117 | phdr, hdr_len, pfirst_buffer, | ||
1118 | buf_len); | ||
1119 | |||
1120 | if (status == 0) | ||
1121 | hwi_free_async_msg(phba, cri); | ||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1125 | static unsigned int | ||
1126 | hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn, | ||
1127 | struct beiscsi_hba *phba, | ||
1128 | struct async_pdu_handle *pasync_handle) | ||
1129 | { | ||
1130 | struct hwi_async_pdu_context *pasync_ctx; | ||
1131 | struct hwi_controller *phwi_ctrlr; | ||
1132 | unsigned int bytes_needed = 0, status = 0; | ||
1133 | unsigned short cri = pasync_handle->cri; | ||
1134 | struct pdu_base *ppdu; | ||
1135 | |||
1136 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1137 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | ||
1138 | |||
1139 | list_del(&pasync_handle->link); | ||
1140 | if (pasync_handle->is_header) { | ||
1141 | pasync_ctx->async_header.busy_entries--; | ||
1142 | if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { | ||
1143 | hwi_free_async_msg(phba, cri); | ||
1144 | BUG(); | ||
1145 | } | ||
1146 | |||
1147 | pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; | ||
1148 | pasync_ctx->async_entry[cri].wait_queue.hdr_received = 1; | ||
1149 | pasync_ctx->async_entry[cri].wait_queue.hdr_len = | ||
1150 | (unsigned short)pasync_handle->buffer_len; | ||
1151 | list_add_tail(&pasync_handle->link, | ||
1152 | &pasync_ctx->async_entry[cri].wait_queue.list); | ||
1153 | |||
1154 | ppdu = pasync_handle->pbuffer; | ||
1155 | bytes_needed = ((((ppdu->dw[offsetof(struct amap_pdu_base, | ||
1156 | data_len_hi) / 32] & PDUBASE_DATALENHI_MASK) << 8) & | ||
1157 | 0xFFFF0000) | ((be16_to_cpu((ppdu-> | ||
1158 | dw[offsetof(struct amap_pdu_base, data_len_lo) / 32] | ||
1159 | & PDUBASE_DATALENLO_MASK) >> 16)) & 0x0000FFFF)); | ||
1160 | |||
1161 | if (status == 0) { | ||
1162 | pasync_ctx->async_entry[cri].wait_queue.bytes_needed = | ||
1163 | bytes_needed; | ||
1164 | |||
1165 | if (bytes_needed == 0) | ||
1166 | status = hwi_fwd_async_msg(beiscsi_conn, phba, | ||
1167 | pasync_ctx, cri); | ||
1168 | } | ||
1169 | } else { | ||
1170 | pasync_ctx->async_data.busy_entries--; | ||
1171 | if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { | ||
1172 | list_add_tail(&pasync_handle->link, | ||
1173 | &pasync_ctx->async_entry[cri].wait_queue. | ||
1174 | list); | ||
1175 | pasync_ctx->async_entry[cri].wait_queue. | ||
1176 | bytes_received += | ||
1177 | (unsigned short)pasync_handle->buffer_len; | ||
1178 | |||
1179 | if (pasync_ctx->async_entry[cri].wait_queue. | ||
1180 | bytes_received >= | ||
1181 | pasync_ctx->async_entry[cri].wait_queue. | ||
1182 | bytes_needed) | ||
1183 | status = hwi_fwd_async_msg(beiscsi_conn, phba, | ||
1184 | pasync_ctx, cri); | ||
1185 | } | ||
1186 | } | ||
1187 | return status; | ||
1188 | } | ||
1189 | |||
1190 | static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn, | ||
1191 | struct beiscsi_hba *phba, | ||
1192 | struct i_t_dpdu_cqe *pdpdu_cqe) | ||
1193 | { | ||
1194 | struct hwi_controller *phwi_ctrlr; | ||
1195 | struct hwi_async_pdu_context *pasync_ctx; | ||
1196 | struct async_pdu_handle *pasync_handle = NULL; | ||
1197 | unsigned int cq_index = -1; | ||
1198 | |||
1199 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1200 | pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); | ||
1201 | pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx, | ||
1202 | pdpdu_cqe, &cq_index); | ||
1203 | |||
1204 | if (pasync_handle->consumed == 0) | ||
1205 | hwi_update_async_writables(pasync_ctx, pasync_handle->is_header, | ||
1206 | cq_index); | ||
1207 | hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle); | ||
1208 | hwi_post_async_buffers(phba, pasync_handle->is_header); | ||
1209 | } | ||
1210 | |||
1211 | static unsigned int beiscsi_process_cq(struct beiscsi_hba *phba) | ||
1212 | { | ||
1213 | struct hwi_controller *phwi_ctrlr; | ||
1214 | struct hwi_context_memory *phwi_context; | ||
1215 | struct be_queue_info *cq; | ||
1216 | struct sol_cqe *sol; | ||
1217 | struct dmsg_cqe *dmsg; | ||
1218 | unsigned int num_processed = 0; | ||
1219 | unsigned int tot_nump = 0; | ||
1220 | struct beiscsi_conn *beiscsi_conn; | ||
1221 | |||
1222 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1223 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
1224 | cq = &phwi_context->be_cq; | ||
1225 | sol = queue_tail_node(cq); | ||
1226 | |||
1227 | while (sol->dw[offsetof(struct amap_sol_cqe, valid) / 32] & | ||
1228 | CQE_VALID_MASK) { | ||
1229 | be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); | ||
1230 | |||
1231 | beiscsi_conn = phba->conn_table[(u32) (sol-> | ||
1232 | dw[offsetof(struct amap_sol_cqe, cid) / 32] & | ||
1233 | SOL_CID_MASK) >> 6]; | ||
1234 | |||
1235 | if (!beiscsi_conn || !beiscsi_conn->ep) { | ||
1236 | shost_printk(KERN_WARNING, phba->shost, | ||
1237 | "Connection table empty for cid = %d\n", | ||
1238 | (u32)(sol->dw[offsetof(struct amap_sol_cqe, | ||
1239 | cid) / 32] & SOL_CID_MASK) >> 6); | ||
1240 | return 0; | ||
1241 | } | ||
1242 | |||
1243 | if (num_processed >= 32) { | ||
1244 | hwi_ring_cq_db(phba, phwi_context->be_cq.id, | ||
1245 | num_processed, 0, 0); | ||
1246 | tot_nump += num_processed; | ||
1247 | num_processed = 0; | ||
1248 | } | ||
1249 | |||
1250 | switch ((u32) sol->dw[offsetof(struct amap_sol_cqe, code) / | ||
1251 | 32] & CQE_CODE_MASK) { | ||
1252 | case SOL_CMD_COMPLETE: | ||
1253 | hwi_complete_cmd(beiscsi_conn, phba, sol); | ||
1254 | break; | ||
1255 | case DRIVERMSG_NOTIFY: | ||
1256 | SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY \n"); | ||
1257 | dmsg = (struct dmsg_cqe *)sol; | ||
1258 | hwi_complete_drvr_msgs(beiscsi_conn, phba, sol); | ||
1259 | break; | ||
1260 | case UNSOL_HDR_NOTIFY: | ||
1261 | case UNSOL_DATA_NOTIFY: | ||
1262 | SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR/DATA_NOTIFY\n"); | ||
1263 | hwi_process_default_pdu_ring(beiscsi_conn, phba, | ||
1264 | (struct i_t_dpdu_cqe *)sol); | ||
1265 | break; | ||
1266 | case CXN_INVALIDATE_INDEX_NOTIFY: | ||
1267 | case CMD_INVALIDATED_NOTIFY: | ||
1268 | case CXN_INVALIDATE_NOTIFY: | ||
1269 | SE_DEBUG(DBG_LVL_1, | ||
1270 | "Ignoring CQ Error notification for cmd/cxn" | ||
1271 | "invalidate\n"); | ||
1272 | break; | ||
1273 | case SOL_CMD_KILLED_DATA_DIGEST_ERR: | ||
1274 | case CMD_KILLED_INVALID_STATSN_RCVD: | ||
1275 | case CMD_KILLED_INVALID_R2T_RCVD: | ||
1276 | case CMD_CXN_KILLED_LUN_INVALID: | ||
1277 | case CMD_CXN_KILLED_ICD_INVALID: | ||
1278 | case CMD_CXN_KILLED_ITT_INVALID: | ||
1279 | case CMD_CXN_KILLED_SEQ_OUTOFORDER: | ||
1280 | case CMD_CXN_KILLED_INVALID_DATASN_RCVD: | ||
1281 | SE_DEBUG(DBG_LVL_1, | ||
1282 | "CQ Error notification for cmd.. " | ||
1283 | "code %d cid 0x%x\n", | ||
1284 | sol->dw[offsetof(struct amap_sol_cqe, code) / | ||
1285 | 32] & CQE_CODE_MASK, | ||
1286 | (sol->dw[offsetof(struct amap_sol_cqe, cid) / | ||
1287 | 32] & SOL_CID_MASK)); | ||
1288 | break; | ||
1289 | case UNSOL_DATA_DIGEST_ERROR_NOTIFY: | ||
1290 | SE_DEBUG(DBG_LVL_1, | ||
1291 | "Digest error on def pdu ring, dropping..\n"); | ||
1292 | hwi_flush_default_pdu_buffer(phba, beiscsi_conn, | ||
1293 | (struct i_t_dpdu_cqe *) sol); | ||
1294 | break; | ||
1295 | case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL: | ||
1296 | case CXN_KILLED_BURST_LEN_MISMATCH: | ||
1297 | case CXN_KILLED_AHS_RCVD: | ||
1298 | case CXN_KILLED_HDR_DIGEST_ERR: | ||
1299 | case CXN_KILLED_UNKNOWN_HDR: | ||
1300 | case CXN_KILLED_STALE_ITT_TTT_RCVD: | ||
1301 | case CXN_KILLED_INVALID_ITT_TTT_RCVD: | ||
1302 | case CXN_KILLED_TIMED_OUT: | ||
1303 | case CXN_KILLED_FIN_RCVD: | ||
1304 | case CXN_KILLED_BAD_UNSOL_PDU_RCVD: | ||
1305 | case CXN_KILLED_BAD_WRB_INDEX_ERROR: | ||
1306 | case CXN_KILLED_OVER_RUN_RESIDUAL: | ||
1307 | case CXN_KILLED_UNDER_RUN_RESIDUAL: | ||
1308 | case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN: | ||
1309 | SE_DEBUG(DBG_LVL_1, "CQ Error %d, resetting CID " | ||
1310 | "0x%x...\n", | ||
1311 | sol->dw[offsetof(struct amap_sol_cqe, code) / | ||
1312 | 32] & CQE_CODE_MASK, | ||
1313 | sol->dw[offsetof(struct amap_sol_cqe, cid) / | ||
1314 | 32] & CQE_CID_MASK); | ||
1315 | iscsi_conn_failure(beiscsi_conn->conn, | ||
1316 | ISCSI_ERR_CONN_FAILED); | ||
1317 | break; | ||
1318 | case CXN_KILLED_RST_SENT: | ||
1319 | case CXN_KILLED_RST_RCVD: | ||
1320 | SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset received/sent " | ||
1321 | "on CID 0x%x...\n", | ||
1322 | sol->dw[offsetof(struct amap_sol_cqe, code) / | ||
1323 | 32] & CQE_CODE_MASK, | ||
1324 | sol->dw[offsetof(struct amap_sol_cqe, cid) / | ||
1325 | 32] & CQE_CID_MASK); | ||
1326 | iscsi_conn_failure(beiscsi_conn->conn, | ||
1327 | ISCSI_ERR_CONN_FAILED); | ||
1328 | break; | ||
1329 | default: | ||
1330 | SE_DEBUG(DBG_LVL_1, "CQ Error Invalid code= %d " | ||
1331 | "received on CID 0x%x...\n", | ||
1332 | sol->dw[offsetof(struct amap_sol_cqe, code) / | ||
1333 | 32] & CQE_CODE_MASK, | ||
1334 | sol->dw[offsetof(struct amap_sol_cqe, cid) / | ||
1335 | 32] & CQE_CID_MASK); | ||
1336 | break; | ||
1337 | } | ||
1338 | |||
1339 | AMAP_SET_BITS(struct amap_sol_cqe, valid, sol, 0); | ||
1340 | queue_tail_inc(cq); | ||
1341 | sol = queue_tail_node(cq); | ||
1342 | num_processed++; | ||
1343 | } | ||
1344 | |||
1345 | if (num_processed > 0) { | ||
1346 | tot_nump += num_processed; | ||
1347 | hwi_ring_cq_db(phba, phwi_context->be_cq.id, num_processed, | ||
1348 | 1, 0); | ||
1349 | } | ||
1350 | return tot_nump; | ||
1351 | } | ||
1352 | |||
1353 | static void beiscsi_process_all_cqs(struct work_struct *work) | ||
1354 | { | ||
1355 | unsigned long flags; | ||
1356 | struct beiscsi_hba *phba = | ||
1357 | container_of(work, struct beiscsi_hba, work_cqs); | ||
1358 | |||
1359 | if (phba->todo_mcc_cq) { | ||
1360 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
1361 | phba->todo_mcc_cq = 0; | ||
1362 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
1363 | SE_DEBUG(DBG_LVL_1, "MCC Interrupt Not expected \n"); | ||
1364 | } | ||
1365 | |||
1366 | if (phba->todo_cq) { | ||
1367 | spin_lock_irqsave(&phba->isr_lock, flags); | ||
1368 | phba->todo_cq = 0; | ||
1369 | spin_unlock_irqrestore(&phba->isr_lock, flags); | ||
1370 | beiscsi_process_cq(phba); | ||
1371 | } | ||
1372 | } | ||
1373 | |||
1374 | static int be_iopoll(struct blk_iopoll *iop, int budget) | ||
1375 | { | ||
1376 | static unsigned int ret; | ||
1377 | struct beiscsi_hba *phba; | ||
1378 | |||
1379 | phba = container_of(iop, struct beiscsi_hba, iopoll); | ||
1380 | |||
1381 | ret = beiscsi_process_cq(phba); | ||
1382 | if (ret < budget) { | ||
1383 | struct hwi_controller *phwi_ctrlr; | ||
1384 | struct hwi_context_memory *phwi_context; | ||
1385 | |||
1386 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1387 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
1388 | blk_iopoll_complete(iop); | ||
1389 | hwi_ring_eq_db(phba, phwi_context->be_eq.q.id, 0, | ||
1390 | 0, 1, 1); | ||
1391 | } | ||
1392 | return ret; | ||
1393 | } | ||
1394 | |||
1395 | static void | ||
1396 | hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg, | ||
1397 | unsigned int num_sg, struct beiscsi_io_task *io_task) | ||
1398 | { | ||
1399 | struct iscsi_sge *psgl; | ||
1400 | unsigned short sg_len, index; | ||
1401 | unsigned int sge_len = 0; | ||
1402 | unsigned long long addr; | ||
1403 | struct scatterlist *l_sg; | ||
1404 | unsigned int offset; | ||
1405 | |||
1406 | AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb, | ||
1407 | io_task->bhs_pa.u.a32.address_lo); | ||
1408 | AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb, | ||
1409 | io_task->bhs_pa.u.a32.address_hi); | ||
1410 | |||
1411 | l_sg = sg; | ||
1412 | for (index = 0; (index < num_sg) && (index < 2); index++, sg_next(sg)) { | ||
1413 | if (index == 0) { | ||
1414 | sg_len = sg_dma_len(sg); | ||
1415 | addr = (u64) sg_dma_address(sg); | ||
1416 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, | ||
1417 | (addr & 0xFFFFFFFF)); | ||
1418 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, | ||
1419 | (addr >> 32)); | ||
1420 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, | ||
1421 | sg_len); | ||
1422 | sge_len = sg_len; | ||
1423 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, | ||
1424 | 1); | ||
1425 | } else { | ||
1426 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, | ||
1427 | 0); | ||
1428 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_r2t_offset, | ||
1429 | pwrb, sge_len); | ||
1430 | sg_len = sg_dma_len(sg); | ||
1431 | addr = (u64) sg_dma_address(sg); | ||
1432 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_lo, pwrb, | ||
1433 | (addr & 0xFFFFFFFF)); | ||
1434 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_addr_hi, pwrb, | ||
1435 | (addr >> 32)); | ||
1436 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_len, pwrb, | ||
1437 | sg_len); | ||
1438 | } | ||
1439 | } | ||
1440 | psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; | ||
1441 | memset(psgl, 0, sizeof(*psgl) * BE2_SGE); | ||
1442 | |||
1443 | AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2); | ||
1444 | |||
1445 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, | ||
1446 | io_task->bhs_pa.u.a32.address_hi); | ||
1447 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, | ||
1448 | io_task->bhs_pa.u.a32.address_lo); | ||
1449 | |||
1450 | if (num_sg == 2) | ||
1451 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge1_last, pwrb, 1); | ||
1452 | sg = l_sg; | ||
1453 | psgl++; | ||
1454 | psgl++; | ||
1455 | offset = 0; | ||
1456 | for (index = 0; index < num_sg; index++, sg_next(sg), psgl++) { | ||
1457 | sg_len = sg_dma_len(sg); | ||
1458 | addr = (u64) sg_dma_address(sg); | ||
1459 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, | ||
1460 | (addr & 0xFFFFFFFF)); | ||
1461 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, | ||
1462 | (addr >> 32)); | ||
1463 | AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len); | ||
1464 | AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset); | ||
1465 | AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0); | ||
1466 | offset += sg_len; | ||
1467 | } | ||
1468 | psgl--; | ||
1469 | AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); | ||
1470 | } | ||
1471 | |||
1472 | static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task) | ||
1473 | { | ||
1474 | struct iscsi_sge *psgl; | ||
1475 | unsigned long long addr; | ||
1476 | struct beiscsi_io_task *io_task = task->dd_data; | ||
1477 | struct beiscsi_conn *beiscsi_conn = io_task->conn; | ||
1478 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
1479 | |||
1480 | io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2; | ||
1481 | AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb, | ||
1482 | io_task->bhs_pa.u.a32.address_lo); | ||
1483 | AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_hi, pwrb, | ||
1484 | io_task->bhs_pa.u.a32.address_hi); | ||
1485 | |||
1486 | if (task->data) { | ||
1487 | if (task->data_count) { | ||
1488 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); | ||
1489 | addr = (u64) pci_map_single(phba->pcidev, | ||
1490 | task->data, | ||
1491 | task->data_count, 1); | ||
1492 | } else { | ||
1493 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); | ||
1494 | addr = 0; | ||
1495 | } | ||
1496 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, | ||
1497 | (addr & 0xFFFFFFFF)); | ||
1498 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, | ||
1499 | (addr >> 32)); | ||
1500 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb, | ||
1501 | task->data_count); | ||
1502 | |||
1503 | AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1); | ||
1504 | } else { | ||
1505 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); | ||
1506 | addr = 0; | ||
1507 | } | ||
1508 | |||
1509 | psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; | ||
1510 | |||
1511 | AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len); | ||
1512 | |||
1513 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, | ||
1514 | io_task->bhs_pa.u.a32.address_hi); | ||
1515 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, | ||
1516 | io_task->bhs_pa.u.a32.address_lo); | ||
1517 | if (task->data) { | ||
1518 | psgl++; | ||
1519 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, 0); | ||
1520 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, 0); | ||
1521 | AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0); | ||
1522 | AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, 0); | ||
1523 | AMAP_SET_BITS(struct amap_iscsi_sge, rsvd0, psgl, 0); | ||
1524 | AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0); | ||
1525 | |||
1526 | psgl++; | ||
1527 | if (task->data) { | ||
1528 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, | ||
1529 | (addr & 0xFFFFFFFF)); | ||
1530 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, | ||
1531 | (addr >> 32)); | ||
1532 | } | ||
1533 | AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106); | ||
1534 | } | ||
1535 | AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); | ||
1536 | } | ||
1537 | |||
1538 | static void beiscsi_find_mem_req(struct beiscsi_hba *phba) | ||
1539 | { | ||
1540 | unsigned int num_cq_pages, num_eq_pages, num_async_pdu_buf_pages; | ||
1541 | unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn; | ||
1542 | unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages; | ||
1543 | |||
1544 | num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \ | ||
1545 | sizeof(struct sol_cqe)); | ||
1546 | num_eq_pages = PAGES_REQUIRED(phba->params.num_eq_entries * \ | ||
1547 | sizeof(struct be_eq_entry)); | ||
1548 | num_async_pdu_buf_pages = | ||
1549 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
1550 | phba->params.defpdu_hdr_sz); | ||
1551 | num_async_pdu_buf_sgl_pages = | ||
1552 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
1553 | sizeof(struct phys_addr)); | ||
1554 | num_async_pdu_data_pages = | ||
1555 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
1556 | phba->params.defpdu_data_sz); | ||
1557 | num_async_pdu_data_sgl_pages = | ||
1558 | PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ | ||
1559 | sizeof(struct phys_addr)); | ||
1560 | |||
1561 | phba->params.hwi_ws_sz = sizeof(struct hwi_controller); | ||
1562 | |||
1563 | phba->mem_req[ISCSI_MEM_GLOBAL_HEADER] = 2 * | ||
1564 | BE_ISCSI_PDU_HEADER_SIZE; | ||
1565 | phba->mem_req[HWI_MEM_ADDN_CONTEXT] = | ||
1566 | sizeof(struct hwi_context_memory); | ||
1567 | |||
1568 | phba->mem_req[HWI_MEM_CQ] = num_cq_pages * PAGE_SIZE; | ||
1569 | phba->mem_req[HWI_MEM_EQ] = num_eq_pages * PAGE_SIZE; | ||
1570 | |||
1571 | phba->mem_req[HWI_MEM_WRB] = sizeof(struct iscsi_wrb) | ||
1572 | * (phba->params.wrbs_per_cxn) | ||
1573 | * phba->params.cxns_per_ctrl; | ||
1574 | wrb_sz_per_cxn = sizeof(struct wrb_handle) * | ||
1575 | (phba->params.wrbs_per_cxn); | ||
1576 | phba->mem_req[HWI_MEM_WRBH] = roundup_pow_of_two((wrb_sz_per_cxn) * | ||
1577 | phba->params.cxns_per_ctrl); | ||
1578 | |||
1579 | phba->mem_req[HWI_MEM_SGLH] = sizeof(struct sgl_handle) * | ||
1580 | phba->params.icds_per_ctrl; | ||
1581 | phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) * | ||
1582 | phba->params.num_sge_per_io * phba->params.icds_per_ctrl; | ||
1583 | |||
1584 | phba->mem_req[HWI_MEM_ASYNC_HEADER_BUF] = | ||
1585 | num_async_pdu_buf_pages * PAGE_SIZE; | ||
1586 | phba->mem_req[HWI_MEM_ASYNC_DATA_BUF] = | ||
1587 | num_async_pdu_data_pages * PAGE_SIZE; | ||
1588 | phba->mem_req[HWI_MEM_ASYNC_HEADER_RING] = | ||
1589 | num_async_pdu_buf_sgl_pages * PAGE_SIZE; | ||
1590 | phba->mem_req[HWI_MEM_ASYNC_DATA_RING] = | ||
1591 | num_async_pdu_data_sgl_pages * PAGE_SIZE; | ||
1592 | phba->mem_req[HWI_MEM_ASYNC_HEADER_HANDLE] = | ||
1593 | phba->params.asyncpdus_per_ctrl * | ||
1594 | sizeof(struct async_pdu_handle); | ||
1595 | phba->mem_req[HWI_MEM_ASYNC_DATA_HANDLE] = | ||
1596 | phba->params.asyncpdus_per_ctrl * | ||
1597 | sizeof(struct async_pdu_handle); | ||
1598 | phba->mem_req[HWI_MEM_ASYNC_PDU_CONTEXT] = | ||
1599 | sizeof(struct hwi_async_pdu_context) + | ||
1600 | (phba->params.cxns_per_ctrl * sizeof(struct hwi_async_entry)); | ||
1601 | } | ||
1602 | |||
1603 | static int beiscsi_alloc_mem(struct beiscsi_hba *phba) | ||
1604 | { | ||
1605 | struct be_mem_descriptor *mem_descr; | ||
1606 | dma_addr_t bus_add; | ||
1607 | struct mem_array *mem_arr, *mem_arr_orig; | ||
1608 | unsigned int i, j, alloc_size, curr_alloc_size; | ||
1609 | |||
1610 | phba->phwi_ctrlr = kmalloc(phba->params.hwi_ws_sz, GFP_KERNEL); | ||
1611 | if (!phba->phwi_ctrlr) | ||
1612 | return -ENOMEM; | ||
1613 | |||
1614 | phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr), | ||
1615 | GFP_KERNEL); | ||
1616 | if (!phba->init_mem) { | ||
1617 | kfree(phba->phwi_ctrlr); | ||
1618 | return -ENOMEM; | ||
1619 | } | ||
1620 | |||
1621 | mem_arr_orig = kmalloc(sizeof(*mem_arr_orig) * BEISCSI_MAX_FRAGS_INIT, | ||
1622 | GFP_KERNEL); | ||
1623 | if (!mem_arr_orig) { | ||
1624 | kfree(phba->init_mem); | ||
1625 | kfree(phba->phwi_ctrlr); | ||
1626 | return -ENOMEM; | ||
1627 | } | ||
1628 | |||
1629 | mem_descr = phba->init_mem; | ||
1630 | for (i = 0; i < SE_MEM_MAX; i++) { | ||
1631 | j = 0; | ||
1632 | mem_arr = mem_arr_orig; | ||
1633 | alloc_size = phba->mem_req[i]; | ||
1634 | memset(mem_arr, 0, sizeof(struct mem_array) * | ||
1635 | BEISCSI_MAX_FRAGS_INIT); | ||
1636 | curr_alloc_size = min(be_max_phys_size * 1024, alloc_size); | ||
1637 | do { | ||
1638 | mem_arr->virtual_address = pci_alloc_consistent( | ||
1639 | phba->pcidev, | ||
1640 | curr_alloc_size, | ||
1641 | &bus_add); | ||
1642 | if (!mem_arr->virtual_address) { | ||
1643 | if (curr_alloc_size <= BE_MIN_MEM_SIZE) | ||
1644 | goto free_mem; | ||
1645 | if (curr_alloc_size - | ||
1646 | rounddown_pow_of_two(curr_alloc_size)) | ||
1647 | curr_alloc_size = rounddown_pow_of_two | ||
1648 | (curr_alloc_size); | ||
1649 | else | ||
1650 | curr_alloc_size = curr_alloc_size / 2; | ||
1651 | } else { | ||
1652 | mem_arr->bus_address.u. | ||
1653 | a64.address = (__u64) bus_add; | ||
1654 | mem_arr->size = curr_alloc_size; | ||
1655 | alloc_size -= curr_alloc_size; | ||
1656 | curr_alloc_size = min(be_max_phys_size * | ||
1657 | 1024, alloc_size); | ||
1658 | j++; | ||
1659 | mem_arr++; | ||
1660 | } | ||
1661 | } while (alloc_size); | ||
1662 | mem_descr->num_elements = j; | ||
1663 | mem_descr->size_in_bytes = phba->mem_req[i]; | ||
1664 | mem_descr->mem_array = kmalloc(sizeof(*mem_arr) * j, | ||
1665 | GFP_KERNEL); | ||
1666 | if (!mem_descr->mem_array) | ||
1667 | goto free_mem; | ||
1668 | |||
1669 | memcpy(mem_descr->mem_array, mem_arr_orig, | ||
1670 | sizeof(struct mem_array) * j); | ||
1671 | mem_descr++; | ||
1672 | } | ||
1673 | kfree(mem_arr_orig); | ||
1674 | return 0; | ||
1675 | free_mem: | ||
1676 | mem_descr->num_elements = j; | ||
1677 | while ((i) || (j)) { | ||
1678 | for (j = mem_descr->num_elements; j > 0; j--) { | ||
1679 | pci_free_consistent(phba->pcidev, | ||
1680 | mem_descr->mem_array[j - 1].size, | ||
1681 | mem_descr->mem_array[j - 1]. | ||
1682 | virtual_address, | ||
1683 | mem_descr->mem_array[j - 1]. | ||
1684 | bus_address.u.a64.address); | ||
1685 | } | ||
1686 | if (i) { | ||
1687 | i--; | ||
1688 | kfree(mem_descr->mem_array); | ||
1689 | mem_descr--; | ||
1690 | } | ||
1691 | } | ||
1692 | kfree(mem_arr_orig); | ||
1693 | kfree(phba->init_mem); | ||
1694 | kfree(phba->phwi_ctrlr); | ||
1695 | return -ENOMEM; | ||
1696 | } | ||
1697 | |||
1698 | static int beiscsi_get_memory(struct beiscsi_hba *phba) | ||
1699 | { | ||
1700 | beiscsi_find_mem_req(phba); | ||
1701 | return beiscsi_alloc_mem(phba); | ||
1702 | } | ||
1703 | |||
1704 | static void iscsi_init_global_templates(struct beiscsi_hba *phba) | ||
1705 | { | ||
1706 | struct pdu_data_out *pdata_out; | ||
1707 | struct pdu_nop_out *pnop_out; | ||
1708 | struct be_mem_descriptor *mem_descr; | ||
1709 | |||
1710 | mem_descr = phba->init_mem; | ||
1711 | mem_descr += ISCSI_MEM_GLOBAL_HEADER; | ||
1712 | pdata_out = | ||
1713 | (struct pdu_data_out *)mem_descr->mem_array[0].virtual_address; | ||
1714 | memset(pdata_out, 0, BE_ISCSI_PDU_HEADER_SIZE); | ||
1715 | |||
1716 | AMAP_SET_BITS(struct amap_pdu_data_out, opcode, pdata_out, | ||
1717 | IIOC_SCSI_DATA); | ||
1718 | |||
1719 | pnop_out = | ||
1720 | (struct pdu_nop_out *)((unsigned char *)mem_descr->mem_array[0]. | ||
1721 | virtual_address + BE_ISCSI_PDU_HEADER_SIZE); | ||
1722 | |||
1723 | memset(pnop_out, 0, BE_ISCSI_PDU_HEADER_SIZE); | ||
1724 | AMAP_SET_BITS(struct amap_pdu_nop_out, ttt, pnop_out, 0xFFFFFFFF); | ||
1725 | AMAP_SET_BITS(struct amap_pdu_nop_out, f_bit, pnop_out, 1); | ||
1726 | AMAP_SET_BITS(struct amap_pdu_nop_out, i_bit, pnop_out, 0); | ||
1727 | } | ||
1728 | |||
1729 | static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) | ||
1730 | { | ||
1731 | struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb; | ||
1732 | struct wrb_handle *pwrb_handle; | ||
1733 | struct hwi_controller *phwi_ctrlr; | ||
1734 | struct hwi_wrb_context *pwrb_context; | ||
1735 | struct iscsi_wrb *pwrb; | ||
1736 | unsigned int num_cxn_wrbh; | ||
1737 | unsigned int num_cxn_wrb, j, idx, index; | ||
1738 | |||
1739 | mem_descr_wrbh = phba->init_mem; | ||
1740 | mem_descr_wrbh += HWI_MEM_WRBH; | ||
1741 | |||
1742 | mem_descr_wrb = phba->init_mem; | ||
1743 | mem_descr_wrb += HWI_MEM_WRB; | ||
1744 | |||
1745 | idx = 0; | ||
1746 | pwrb_handle = mem_descr_wrbh->mem_array[idx].virtual_address; | ||
1747 | num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) / | ||
1748 | ((sizeof(struct wrb_handle)) * | ||
1749 | phba->params.wrbs_per_cxn)); | ||
1750 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1751 | |||
1752 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { | ||
1753 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | ||
1754 | SE_DEBUG(DBG_LVL_8, "cid=%d pwrb_context=%p \n", index, | ||
1755 | pwrb_context); | ||
1756 | pwrb_context->pwrb_handle_base = | ||
1757 | kzalloc(sizeof(struct wrb_handle *) * | ||
1758 | phba->params.wrbs_per_cxn, GFP_KERNEL); | ||
1759 | pwrb_context->pwrb_handle_basestd = | ||
1760 | kzalloc(sizeof(struct wrb_handle *) * | ||
1761 | phba->params.wrbs_per_cxn, GFP_KERNEL); | ||
1762 | if (num_cxn_wrbh) { | ||
1763 | pwrb_context->alloc_index = 0; | ||
1764 | pwrb_context->wrb_handles_available = 0; | ||
1765 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { | ||
1766 | pwrb_context->pwrb_handle_base[j] = pwrb_handle; | ||
1767 | pwrb_context->pwrb_handle_basestd[j] = | ||
1768 | pwrb_handle; | ||
1769 | pwrb_context->wrb_handles_available++; | ||
1770 | pwrb_handle++; | ||
1771 | } | ||
1772 | pwrb_context->free_index = 0; | ||
1773 | num_cxn_wrbh--; | ||
1774 | } else { | ||
1775 | idx++; | ||
1776 | pwrb_handle = | ||
1777 | mem_descr_wrbh->mem_array[idx].virtual_address; | ||
1778 | num_cxn_wrbh = | ||
1779 | ((mem_descr_wrbh->mem_array[idx].size) / | ||
1780 | ((sizeof(struct wrb_handle)) * | ||
1781 | phba->params.wrbs_per_cxn)); | ||
1782 | pwrb_context->alloc_index = 0; | ||
1783 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { | ||
1784 | pwrb_context->pwrb_handle_base[j] = pwrb_handle; | ||
1785 | pwrb_context->pwrb_handle_basestd[j] = | ||
1786 | pwrb_handle; | ||
1787 | pwrb_context->wrb_handles_available++; | ||
1788 | pwrb_handle++; | ||
1789 | } | ||
1790 | pwrb_context->free_index = 0; | ||
1791 | num_cxn_wrbh--; | ||
1792 | } | ||
1793 | } | ||
1794 | idx = 0; | ||
1795 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; | ||
1796 | num_cxn_wrb = | ||
1797 | ((mem_descr_wrb->mem_array[idx].size) / (sizeof(struct iscsi_wrb)) * | ||
1798 | phba->params.wrbs_per_cxn); | ||
1799 | |||
1800 | for (index = 0; index < phba->params.cxns_per_ctrl; index += 2) { | ||
1801 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | ||
1802 | if (num_cxn_wrb) { | ||
1803 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { | ||
1804 | pwrb_handle = pwrb_context->pwrb_handle_base[j]; | ||
1805 | pwrb_handle->pwrb = pwrb; | ||
1806 | pwrb++; | ||
1807 | } | ||
1808 | num_cxn_wrb--; | ||
1809 | } else { | ||
1810 | idx++; | ||
1811 | pwrb = mem_descr_wrb->mem_array[idx].virtual_address; | ||
1812 | num_cxn_wrb = ((mem_descr_wrb->mem_array[idx].size) / | ||
1813 | (sizeof(struct iscsi_wrb)) * | ||
1814 | phba->params.wrbs_per_cxn); | ||
1815 | for (j = 0; j < phba->params.wrbs_per_cxn; j++) { | ||
1816 | pwrb_handle = pwrb_context->pwrb_handle_base[j]; | ||
1817 | pwrb_handle->pwrb = pwrb; | ||
1818 | pwrb++; | ||
1819 | } | ||
1820 | num_cxn_wrb--; | ||
1821 | } | ||
1822 | } | ||
1823 | } | ||
1824 | |||
1825 | static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) | ||
1826 | { | ||
1827 | struct hwi_controller *phwi_ctrlr; | ||
1828 | struct hba_parameters *p = &phba->params; | ||
1829 | struct hwi_async_pdu_context *pasync_ctx; | ||
1830 | struct async_pdu_handle *pasync_header_h, *pasync_data_h; | ||
1831 | unsigned int index; | ||
1832 | struct be_mem_descriptor *mem_descr; | ||
1833 | |||
1834 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
1835 | mem_descr += HWI_MEM_ASYNC_PDU_CONTEXT; | ||
1836 | |||
1837 | phwi_ctrlr = phba->phwi_ctrlr; | ||
1838 | phwi_ctrlr->phwi_ctxt->pasync_ctx = (struct hwi_async_pdu_context *) | ||
1839 | mem_descr->mem_array[0].virtual_address; | ||
1840 | pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx; | ||
1841 | memset(pasync_ctx, 0, sizeof(*pasync_ctx)); | ||
1842 | |||
1843 | pasync_ctx->async_header.num_entries = p->asyncpdus_per_ctrl; | ||
1844 | pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz; | ||
1845 | pasync_ctx->async_data.buffer_size = p->defpdu_data_sz; | ||
1846 | pasync_ctx->async_data.num_entries = p->asyncpdus_per_ctrl; | ||
1847 | |||
1848 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
1849 | mem_descr += HWI_MEM_ASYNC_HEADER_BUF; | ||
1850 | if (mem_descr->mem_array[0].virtual_address) { | ||
1851 | SE_DEBUG(DBG_LVL_8, | ||
1852 | "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_BUF" | ||
1853 | "va=%p \n", mem_descr->mem_array[0].virtual_address); | ||
1854 | } else | ||
1855 | shost_printk(KERN_WARNING, phba->shost, | ||
1856 | "No Virtual address \n"); | ||
1857 | |||
1858 | pasync_ctx->async_header.va_base = | ||
1859 | mem_descr->mem_array[0].virtual_address; | ||
1860 | |||
1861 | pasync_ctx->async_header.pa_base.u.a64.address = | ||
1862 | mem_descr->mem_array[0].bus_address.u.a64.address; | ||
1863 | |||
1864 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
1865 | mem_descr += HWI_MEM_ASYNC_HEADER_RING; | ||
1866 | if (mem_descr->mem_array[0].virtual_address) { | ||
1867 | SE_DEBUG(DBG_LVL_8, | ||
1868 | "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_RING" | ||
1869 | "va=%p \n", mem_descr->mem_array[0].virtual_address); | ||
1870 | } else | ||
1871 | shost_printk(KERN_WARNING, phba->shost, | ||
1872 | "No Virtual address \n"); | ||
1873 | pasync_ctx->async_header.ring_base = | ||
1874 | mem_descr->mem_array[0].virtual_address; | ||
1875 | |||
1876 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
1877 | mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE; | ||
1878 | if (mem_descr->mem_array[0].virtual_address) { | ||
1879 | SE_DEBUG(DBG_LVL_8, | ||
1880 | "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_HANDLE" | ||
1881 | "va=%p \n", mem_descr->mem_array[0].virtual_address); | ||
1882 | } else | ||
1883 | shost_printk(KERN_WARNING, phba->shost, | ||
1884 | "No Virtual address \n"); | ||
1885 | |||
1886 | pasync_ctx->async_header.handle_base = | ||
1887 | mem_descr->mem_array[0].virtual_address; | ||
1888 | pasync_ctx->async_header.writables = 0; | ||
1889 | INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); | ||
1890 | |||
1891 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
1892 | mem_descr += HWI_MEM_ASYNC_DATA_BUF; | ||
1893 | if (mem_descr->mem_array[0].virtual_address) { | ||
1894 | SE_DEBUG(DBG_LVL_8, | ||
1895 | "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF" | ||
1896 | "va=%p \n", mem_descr->mem_array[0].virtual_address); | ||
1897 | } else | ||
1898 | shost_printk(KERN_WARNING, phba->shost, | ||
1899 | "No Virtual address \n"); | ||
1900 | pasync_ctx->async_data.va_base = | ||
1901 | mem_descr->mem_array[0].virtual_address; | ||
1902 | pasync_ctx->async_data.pa_base.u.a64.address = | ||
1903 | mem_descr->mem_array[0].bus_address.u.a64.address; | ||
1904 | |||
1905 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
1906 | mem_descr += HWI_MEM_ASYNC_DATA_RING; | ||
1907 | if (mem_descr->mem_array[0].virtual_address) { | ||
1908 | SE_DEBUG(DBG_LVL_8, | ||
1909 | "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_RING" | ||
1910 | "va=%p \n", mem_descr->mem_array[0].virtual_address); | ||
1911 | } else | ||
1912 | shost_printk(KERN_WARNING, phba->shost, | ||
1913 | "No Virtual address \n"); | ||
1914 | |||
1915 | pasync_ctx->async_data.ring_base = | ||
1916 | mem_descr->mem_array[0].virtual_address; | ||
1917 | |||
1918 | mem_descr = (struct be_mem_descriptor *)phba->init_mem; | ||
1919 | mem_descr += HWI_MEM_ASYNC_DATA_HANDLE; | ||
1920 | if (!mem_descr->mem_array[0].virtual_address) | ||
1921 | shost_printk(KERN_WARNING, phba->shost, | ||
1922 | "No Virtual address \n"); | ||
1923 | |||
1924 | pasync_ctx->async_data.handle_base = | ||
1925 | mem_descr->mem_array[0].virtual_address; | ||
1926 | pasync_ctx->async_data.writables = 0; | ||
1927 | INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); | ||
1928 | |||
1929 | pasync_header_h = | ||
1930 | (struct async_pdu_handle *)pasync_ctx->async_header.handle_base; | ||
1931 | pasync_data_h = | ||
1932 | (struct async_pdu_handle *)pasync_ctx->async_data.handle_base; | ||
1933 | |||
1934 | for (index = 0; index < p->asyncpdus_per_ctrl; index++) { | ||
1935 | pasync_header_h->cri = -1; | ||
1936 | pasync_header_h->index = (char)index; | ||
1937 | INIT_LIST_HEAD(&pasync_header_h->link); | ||
1938 | pasync_header_h->pbuffer = | ||
1939 | (void *)((unsigned long) | ||
1940 | (pasync_ctx->async_header.va_base) + | ||
1941 | (p->defpdu_hdr_sz * index)); | ||
1942 | |||
1943 | pasync_header_h->pa.u.a64.address = | ||
1944 | pasync_ctx->async_header.pa_base.u.a64.address + | ||
1945 | (p->defpdu_hdr_sz * index); | ||
1946 | |||
1947 | list_add_tail(&pasync_header_h->link, | ||
1948 | &pasync_ctx->async_header.free_list); | ||
1949 | pasync_header_h++; | ||
1950 | pasync_ctx->async_header.free_entries++; | ||
1951 | pasync_ctx->async_header.writables++; | ||
1952 | |||
1953 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index].wait_queue.list); | ||
1954 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. | ||
1955 | header_busy_list); | ||
1956 | pasync_data_h->cri = -1; | ||
1957 | pasync_data_h->index = (char)index; | ||
1958 | INIT_LIST_HEAD(&pasync_data_h->link); | ||
1959 | pasync_data_h->pbuffer = | ||
1960 | (void *)((unsigned long) | ||
1961 | (pasync_ctx->async_data.va_base) + | ||
1962 | (p->defpdu_data_sz * index)); | ||
1963 | |||
1964 | pasync_data_h->pa.u.a64.address = | ||
1965 | pasync_ctx->async_data.pa_base.u.a64.address + | ||
1966 | (p->defpdu_data_sz * index); | ||
1967 | |||
1968 | list_add_tail(&pasync_data_h->link, | ||
1969 | &pasync_ctx->async_data.free_list); | ||
1970 | pasync_data_h++; | ||
1971 | pasync_ctx->async_data.free_entries++; | ||
1972 | pasync_ctx->async_data.writables++; | ||
1973 | |||
1974 | INIT_LIST_HEAD(&pasync_ctx->async_entry[index].data_busy_list); | ||
1975 | } | ||
1976 | |||
1977 | pasync_ctx->async_header.host_write_ptr = 0; | ||
1978 | pasync_ctx->async_header.ep_read_ptr = -1; | ||
1979 | pasync_ctx->async_data.host_write_ptr = 0; | ||
1980 | pasync_ctx->async_data.ep_read_ptr = -1; | ||
1981 | } | ||
1982 | |||
1983 | static int | ||
1984 | be_sgl_create_contiguous(void *virtual_address, | ||
1985 | u64 physical_address, u32 length, | ||
1986 | struct be_dma_mem *sgl) | ||
1987 | { | ||
1988 | WARN_ON(!virtual_address); | ||
1989 | WARN_ON(!physical_address); | ||
1990 | WARN_ON(!length > 0); | ||
1991 | WARN_ON(!sgl); | ||
1992 | |||
1993 | sgl->va = virtual_address; | ||
1994 | sgl->dma = physical_address; | ||
1995 | sgl->size = length; | ||
1996 | |||
1997 | return 0; | ||
1998 | } | ||
1999 | |||
2000 | static void be_sgl_destroy_contiguous(struct be_dma_mem *sgl) | ||
2001 | { | ||
2002 | memset(sgl, 0, sizeof(*sgl)); | ||
2003 | } | ||
2004 | |||
2005 | static void | ||
2006 | hwi_build_be_sgl_arr(struct beiscsi_hba *phba, | ||
2007 | struct mem_array *pmem, struct be_dma_mem *sgl) | ||
2008 | { | ||
2009 | if (sgl->va) | ||
2010 | be_sgl_destroy_contiguous(sgl); | ||
2011 | |||
2012 | be_sgl_create_contiguous(pmem->virtual_address, | ||
2013 | pmem->bus_address.u.a64.address, | ||
2014 | pmem->size, sgl); | ||
2015 | } | ||
2016 | |||
2017 | static void | ||
2018 | hwi_build_be_sgl_by_offset(struct beiscsi_hba *phba, | ||
2019 | struct mem_array *pmem, struct be_dma_mem *sgl) | ||
2020 | { | ||
2021 | if (sgl->va) | ||
2022 | be_sgl_destroy_contiguous(sgl); | ||
2023 | |||
2024 | be_sgl_create_contiguous((unsigned char *)pmem->virtual_address, | ||
2025 | pmem->bus_address.u.a64.address, | ||
2026 | pmem->size, sgl); | ||
2027 | } | ||
2028 | |||
2029 | static int be_fill_queue(struct be_queue_info *q, | ||
2030 | u16 len, u16 entry_size, void *vaddress) | ||
2031 | { | ||
2032 | struct be_dma_mem *mem = &q->dma_mem; | ||
2033 | |||
2034 | memset(q, 0, sizeof(*q)); | ||
2035 | q->len = len; | ||
2036 | q->entry_size = entry_size; | ||
2037 | mem->size = len * entry_size; | ||
2038 | mem->va = vaddress; | ||
2039 | if (!mem->va) | ||
2040 | return -ENOMEM; | ||
2041 | memset(mem->va, 0, mem->size); | ||
2042 | return 0; | ||
2043 | } | ||
2044 | |||
2045 | static int beiscsi_create_eq(struct beiscsi_hba *phba, | ||
2046 | struct hwi_context_memory *phwi_context) | ||
2047 | { | ||
2048 | unsigned int idx; | ||
2049 | int ret; | ||
2050 | struct be_queue_info *eq; | ||
2051 | struct be_dma_mem *mem; | ||
2052 | struct be_mem_descriptor *mem_descr; | ||
2053 | void *eq_vaddress; | ||
2054 | |||
2055 | idx = 0; | ||
2056 | eq = &phwi_context->be_eq.q; | ||
2057 | mem = &eq->dma_mem; | ||
2058 | mem_descr = phba->init_mem; | ||
2059 | mem_descr += HWI_MEM_EQ; | ||
2060 | eq_vaddress = mem_descr->mem_array[idx].virtual_address; | ||
2061 | |||
2062 | ret = be_fill_queue(eq, phba->params.num_eq_entries, | ||
2063 | sizeof(struct be_eq_entry), eq_vaddress); | ||
2064 | if (ret) { | ||
2065 | shost_printk(KERN_ERR, phba->shost, | ||
2066 | "be_fill_queue Failed for EQ \n"); | ||
2067 | return ret; | ||
2068 | } | ||
2069 | |||
2070 | mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; | ||
2071 | |||
2072 | ret = beiscsi_cmd_eq_create(&phba->ctrl, eq, | ||
2073 | phwi_context->be_eq.cur_eqd); | ||
2074 | if (ret) { | ||
2075 | shost_printk(KERN_ERR, phba->shost, "beiscsi_cmd_eq_create" | ||
2076 | "Failedfor EQ \n"); | ||
2077 | return ret; | ||
2078 | } | ||
2079 | SE_DEBUG(DBG_LVL_8, "eq id is %d\n", phwi_context->be_eq.q.id); | ||
2080 | return 0; | ||
2081 | } | ||
2082 | |||
2083 | static int beiscsi_create_cq(struct beiscsi_hba *phba, | ||
2084 | struct hwi_context_memory *phwi_context) | ||
2085 | { | ||
2086 | unsigned int idx; | ||
2087 | int ret; | ||
2088 | struct be_queue_info *cq, *eq; | ||
2089 | struct be_dma_mem *mem; | ||
2090 | struct be_mem_descriptor *mem_descr; | ||
2091 | void *cq_vaddress; | ||
2092 | |||
2093 | idx = 0; | ||
2094 | cq = &phwi_context->be_cq; | ||
2095 | eq = &phwi_context->be_eq.q; | ||
2096 | mem = &cq->dma_mem; | ||
2097 | mem_descr = phba->init_mem; | ||
2098 | mem_descr += HWI_MEM_CQ; | ||
2099 | cq_vaddress = mem_descr->mem_array[idx].virtual_address; | ||
2100 | ret = be_fill_queue(cq, phba->params.icds_per_ctrl / 2, | ||
2101 | sizeof(struct sol_cqe), cq_vaddress); | ||
2102 | if (ret) { | ||
2103 | shost_printk(KERN_ERR, phba->shost, | ||
2104 | "be_fill_queue Failed for ISCSI CQ \n"); | ||
2105 | return ret; | ||
2106 | } | ||
2107 | |||
2108 | mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; | ||
2109 | ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false, false, 0); | ||
2110 | if (ret) { | ||
2111 | shost_printk(KERN_ERR, phba->shost, | ||
2112 | "beiscsi_cmd_eq_create Failed for ISCSI CQ \n"); | ||
2113 | return ret; | ||
2114 | } | ||
2115 | SE_DEBUG(DBG_LVL_8, "iscsi cq id is %d\n", phwi_context->be_cq.id); | ||
2116 | SE_DEBUG(DBG_LVL_8, "ISCSI CQ CREATED\n"); | ||
2117 | return 0; | ||
2118 | } | ||
2119 | |||
2120 | static int | ||
2121 | beiscsi_create_def_hdr(struct beiscsi_hba *phba, | ||
2122 | struct hwi_context_memory *phwi_context, | ||
2123 | struct hwi_controller *phwi_ctrlr, | ||
2124 | unsigned int def_pdu_ring_sz) | ||
2125 | { | ||
2126 | unsigned int idx; | ||
2127 | int ret; | ||
2128 | struct be_queue_info *dq, *cq; | ||
2129 | struct be_dma_mem *mem; | ||
2130 | struct be_mem_descriptor *mem_descr; | ||
2131 | void *dq_vaddress; | ||
2132 | |||
2133 | idx = 0; | ||
2134 | dq = &phwi_context->be_def_hdrq; | ||
2135 | cq = &phwi_context->be_cq; | ||
2136 | mem = &dq->dma_mem; | ||
2137 | mem_descr = phba->init_mem; | ||
2138 | mem_descr += HWI_MEM_ASYNC_HEADER_RING; | ||
2139 | dq_vaddress = mem_descr->mem_array[idx].virtual_address; | ||
2140 | ret = be_fill_queue(dq, mem_descr->mem_array[0].size / | ||
2141 | sizeof(struct phys_addr), | ||
2142 | sizeof(struct phys_addr), dq_vaddress); | ||
2143 | if (ret) { | ||
2144 | shost_printk(KERN_ERR, phba->shost, | ||
2145 | "be_fill_queue Failed for DEF PDU HDR\n"); | ||
2146 | return ret; | ||
2147 | } | ||
2148 | mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; | ||
2149 | ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq, | ||
2150 | def_pdu_ring_sz, | ||
2151 | phba->params.defpdu_hdr_sz); | ||
2152 | if (ret) { | ||
2153 | shost_printk(KERN_ERR, phba->shost, | ||
2154 | "be_cmd_create_default_pdu_queue Failed DEFHDR\n"); | ||
2155 | return ret; | ||
2156 | } | ||
2157 | phwi_ctrlr->default_pdu_hdr.id = phwi_context->be_def_hdrq.id; | ||
2158 | SE_DEBUG(DBG_LVL_8, "iscsi def pdu id is %d\n", | ||
2159 | phwi_context->be_def_hdrq.id); | ||
2160 | hwi_post_async_buffers(phba, 1); | ||
2161 | return 0; | ||
2162 | } | ||
2163 | |||
2164 | static int | ||
2165 | beiscsi_create_def_data(struct beiscsi_hba *phba, | ||
2166 | struct hwi_context_memory *phwi_context, | ||
2167 | struct hwi_controller *phwi_ctrlr, | ||
2168 | unsigned int def_pdu_ring_sz) | ||
2169 | { | ||
2170 | unsigned int idx; | ||
2171 | int ret; | ||
2172 | struct be_queue_info *dataq, *cq; | ||
2173 | struct be_dma_mem *mem; | ||
2174 | struct be_mem_descriptor *mem_descr; | ||
2175 | void *dq_vaddress; | ||
2176 | |||
2177 | idx = 0; | ||
2178 | dataq = &phwi_context->be_def_dataq; | ||
2179 | cq = &phwi_context->be_cq; | ||
2180 | mem = &dataq->dma_mem; | ||
2181 | mem_descr = phba->init_mem; | ||
2182 | mem_descr += HWI_MEM_ASYNC_DATA_RING; | ||
2183 | dq_vaddress = mem_descr->mem_array[idx].virtual_address; | ||
2184 | ret = be_fill_queue(dataq, mem_descr->mem_array[0].size / | ||
2185 | sizeof(struct phys_addr), | ||
2186 | sizeof(struct phys_addr), dq_vaddress); | ||
2187 | if (ret) { | ||
2188 | shost_printk(KERN_ERR, phba->shost, | ||
2189 | "be_fill_queue Failed for DEF PDU DATA\n"); | ||
2190 | return ret; | ||
2191 | } | ||
2192 | mem->dma = mem_descr->mem_array[idx].bus_address.u.a64.address; | ||
2193 | ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq, | ||
2194 | def_pdu_ring_sz, | ||
2195 | phba->params.defpdu_data_sz); | ||
2196 | if (ret) { | ||
2197 | shost_printk(KERN_ERR, phba->shost, | ||
2198 | "be_cmd_create_default_pdu_queue Failed" | ||
2199 | " for DEF PDU DATA\n"); | ||
2200 | return ret; | ||
2201 | } | ||
2202 | phwi_ctrlr->default_pdu_data.id = phwi_context->be_def_dataq.id; | ||
2203 | SE_DEBUG(DBG_LVL_8, "iscsi def data id is %d\n", | ||
2204 | phwi_context->be_def_dataq.id); | ||
2205 | hwi_post_async_buffers(phba, 0); | ||
2206 | SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED \n"); | ||
2207 | return 0; | ||
2208 | } | ||
2209 | |||
2210 | static int | ||
2211 | beiscsi_post_pages(struct beiscsi_hba *phba) | ||
2212 | { | ||
2213 | struct be_mem_descriptor *mem_descr; | ||
2214 | struct mem_array *pm_arr; | ||
2215 | unsigned int page_offset, i; | ||
2216 | struct be_dma_mem sgl; | ||
2217 | int status; | ||
2218 | |||
2219 | mem_descr = phba->init_mem; | ||
2220 | mem_descr += HWI_MEM_SGE; | ||
2221 | pm_arr = mem_descr->mem_array; | ||
2222 | |||
2223 | page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io * | ||
2224 | phba->fw_config.iscsi_icd_start) / PAGE_SIZE; | ||
2225 | for (i = 0; i < mem_descr->num_elements; i++) { | ||
2226 | hwi_build_be_sgl_arr(phba, pm_arr, &sgl); | ||
2227 | status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl, | ||
2228 | page_offset, | ||
2229 | (pm_arr->size / PAGE_SIZE)); | ||
2230 | page_offset += pm_arr->size / PAGE_SIZE; | ||
2231 | if (status != 0) { | ||
2232 | shost_printk(KERN_ERR, phba->shost, | ||
2233 | "post sgl failed.\n"); | ||
2234 | return status; | ||
2235 | } | ||
2236 | pm_arr++; | ||
2237 | } | ||
2238 | SE_DEBUG(DBG_LVL_8, "POSTED PAGES \n"); | ||
2239 | return 0; | ||
2240 | } | ||
2241 | |||
2242 | static int | ||
2243 | beiscsi_create_wrb_rings(struct beiscsi_hba *phba, | ||
2244 | struct hwi_context_memory *phwi_context, | ||
2245 | struct hwi_controller *phwi_ctrlr) | ||
2246 | { | ||
2247 | unsigned int wrb_mem_index, offset, size, num_wrb_rings; | ||
2248 | u64 pa_addr_lo; | ||
2249 | unsigned int idx, num, i; | ||
2250 | struct mem_array *pwrb_arr; | ||
2251 | void *wrb_vaddr; | ||
2252 | struct be_dma_mem sgl; | ||
2253 | struct be_mem_descriptor *mem_descr; | ||
2254 | int status; | ||
2255 | |||
2256 | idx = 0; | ||
2257 | mem_descr = phba->init_mem; | ||
2258 | mem_descr += HWI_MEM_WRB; | ||
2259 | pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl, | ||
2260 | GFP_KERNEL); | ||
2261 | if (!pwrb_arr) { | ||
2262 | shost_printk(KERN_ERR, phba->shost, | ||
2263 | "Memory alloc failed in create wrb ring.\n"); | ||
2264 | return -ENOMEM; | ||
2265 | } | ||
2266 | wrb_vaddr = mem_descr->mem_array[idx].virtual_address; | ||
2267 | pa_addr_lo = mem_descr->mem_array[idx].bus_address.u.a64.address; | ||
2268 | num_wrb_rings = mem_descr->mem_array[idx].size / | ||
2269 | (phba->params.wrbs_per_cxn * sizeof(struct iscsi_wrb)); | ||
2270 | |||
2271 | for (num = 0; num < phba->params.cxns_per_ctrl; num++) { | ||
2272 | if (num_wrb_rings) { | ||
2273 | pwrb_arr[num].virtual_address = wrb_vaddr; | ||
2274 | pwrb_arr[num].bus_address.u.a64.address = pa_addr_lo; | ||
2275 | pwrb_arr[num].size = phba->params.wrbs_per_cxn * | ||
2276 | sizeof(struct iscsi_wrb); | ||
2277 | wrb_vaddr += pwrb_arr[num].size; | ||
2278 | pa_addr_lo += pwrb_arr[num].size; | ||
2279 | num_wrb_rings--; | ||
2280 | } else { | ||
2281 | idx++; | ||
2282 | wrb_vaddr = mem_descr->mem_array[idx].virtual_address; | ||
2283 | pa_addr_lo = mem_descr->mem_array[idx].\ | ||
2284 | bus_address.u.a64.address; | ||
2285 | num_wrb_rings = mem_descr->mem_array[idx].size / | ||
2286 | (phba->params.wrbs_per_cxn * | ||
2287 | sizeof(struct iscsi_wrb)); | ||
2288 | pwrb_arr[num].virtual_address = wrb_vaddr; | ||
2289 | pwrb_arr[num].bus_address.u.a64.address\ | ||
2290 | = pa_addr_lo; | ||
2291 | pwrb_arr[num].size = phba->params.wrbs_per_cxn * | ||
2292 | sizeof(struct iscsi_wrb); | ||
2293 | wrb_vaddr += pwrb_arr[num].size; | ||
2294 | pa_addr_lo += pwrb_arr[num].size; | ||
2295 | num_wrb_rings--; | ||
2296 | } | ||
2297 | } | ||
2298 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | ||
2299 | wrb_mem_index = 0; | ||
2300 | offset = 0; | ||
2301 | size = 0; | ||
2302 | |||
2303 | hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl); | ||
2304 | status = be_cmd_wrbq_create(&phba->ctrl, &sgl, | ||
2305 | &phwi_context->be_wrbq[i]); | ||
2306 | if (status != 0) { | ||
2307 | shost_printk(KERN_ERR, phba->shost, | ||
2308 | "wrbq create failed."); | ||
2309 | return status; | ||
2310 | } | ||
2311 | phwi_ctrlr->wrb_context[i].cid = phwi_context->be_wrbq[i].id; | ||
2312 | } | ||
2313 | kfree(pwrb_arr); | ||
2314 | return 0; | ||
2315 | } | ||
2316 | |||
2317 | static void free_wrb_handles(struct beiscsi_hba *phba) | ||
2318 | { | ||
2319 | unsigned int index; | ||
2320 | struct hwi_controller *phwi_ctrlr; | ||
2321 | struct hwi_wrb_context *pwrb_context; | ||
2322 | |||
2323 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2324 | for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { | ||
2325 | pwrb_context = &phwi_ctrlr->wrb_context[index]; | ||
2326 | kfree(pwrb_context->pwrb_handle_base); | ||
2327 | kfree(pwrb_context->pwrb_handle_basestd); | ||
2328 | } | ||
2329 | } | ||
2330 | |||
2331 | static void hwi_cleanup(struct beiscsi_hba *phba) | ||
2332 | { | ||
2333 | struct be_queue_info *q; | ||
2334 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
2335 | struct hwi_controller *phwi_ctrlr; | ||
2336 | struct hwi_context_memory *phwi_context; | ||
2337 | int i; | ||
2338 | |||
2339 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2340 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
2341 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | ||
2342 | q = &phwi_context->be_wrbq[i]; | ||
2343 | if (q->created) | ||
2344 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ); | ||
2345 | } | ||
2346 | |||
2347 | free_wrb_handles(phba); | ||
2348 | |||
2349 | q = &phwi_context->be_def_hdrq; | ||
2350 | if (q->created) | ||
2351 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
2352 | |||
2353 | q = &phwi_context->be_def_dataq; | ||
2354 | if (q->created) | ||
2355 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); | ||
2356 | |||
2357 | beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); | ||
2358 | |||
2359 | q = &phwi_context->be_cq; | ||
2360 | if (q->created) | ||
2361 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ); | ||
2362 | |||
2363 | q = &phwi_context->be_eq.q; | ||
2364 | if (q->created) | ||
2365 | beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ); | ||
2366 | } | ||
2367 | |||
2368 | static int hwi_init_port(struct beiscsi_hba *phba) | ||
2369 | { | ||
2370 | struct hwi_controller *phwi_ctrlr; | ||
2371 | struct hwi_context_memory *phwi_context; | ||
2372 | unsigned int def_pdu_ring_sz; | ||
2373 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
2374 | int status; | ||
2375 | |||
2376 | def_pdu_ring_sz = | ||
2377 | phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr); | ||
2378 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2379 | |||
2380 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
2381 | phwi_context->be_eq.max_eqd = 0; | ||
2382 | phwi_context->be_eq.min_eqd = 0; | ||
2383 | phwi_context->be_eq.cur_eqd = 64; | ||
2384 | phwi_context->be_eq.enable_aic = false; | ||
2385 | be_cmd_fw_initialize(&phba->ctrl); | ||
2386 | status = beiscsi_create_eq(phba, phwi_context); | ||
2387 | if (status != 0) { | ||
2388 | shost_printk(KERN_ERR, phba->shost, "EQ not created \n"); | ||
2389 | goto error; | ||
2390 | } | ||
2391 | |||
2392 | status = mgmt_check_supported_fw(ctrl); | ||
2393 | if (status != 0) { | ||
2394 | shost_printk(KERN_ERR, phba->shost, | ||
2395 | "Unsupported fw version \n"); | ||
2396 | goto error; | ||
2397 | } | ||
2398 | |||
2399 | status = mgmt_get_fw_config(ctrl, phba); | ||
2400 | if (status != 0) { | ||
2401 | shost_printk(KERN_ERR, phba->shost, | ||
2402 | "Error getting fw config\n"); | ||
2403 | goto error; | ||
2404 | } | ||
2405 | |||
2406 | status = beiscsi_create_cq(phba, phwi_context); | ||
2407 | if (status != 0) { | ||
2408 | shost_printk(KERN_ERR, phba->shost, "CQ not created\n"); | ||
2409 | goto error; | ||
2410 | } | ||
2411 | |||
2412 | status = beiscsi_create_def_hdr(phba, phwi_context, phwi_ctrlr, | ||
2413 | def_pdu_ring_sz); | ||
2414 | if (status != 0) { | ||
2415 | shost_printk(KERN_ERR, phba->shost, | ||
2416 | "Default Header not created\n"); | ||
2417 | goto error; | ||
2418 | } | ||
2419 | |||
2420 | status = beiscsi_create_def_data(phba, phwi_context, | ||
2421 | phwi_ctrlr, def_pdu_ring_sz); | ||
2422 | if (status != 0) { | ||
2423 | shost_printk(KERN_ERR, phba->shost, | ||
2424 | "Default Data not created\n"); | ||
2425 | goto error; | ||
2426 | } | ||
2427 | |||
2428 | status = beiscsi_post_pages(phba); | ||
2429 | if (status != 0) { | ||
2430 | shost_printk(KERN_ERR, phba->shost, "Post SGL Pages Failed\n"); | ||
2431 | goto error; | ||
2432 | } | ||
2433 | |||
2434 | status = beiscsi_create_wrb_rings(phba, phwi_context, phwi_ctrlr); | ||
2435 | if (status != 0) { | ||
2436 | shost_printk(KERN_ERR, phba->shost, | ||
2437 | "WRB Rings not created\n"); | ||
2438 | goto error; | ||
2439 | } | ||
2440 | |||
2441 | SE_DEBUG(DBG_LVL_8, "hwi_init_port success\n"); | ||
2442 | return 0; | ||
2443 | |||
2444 | error: | ||
2445 | shost_printk(KERN_ERR, phba->shost, "hwi_init_port failed"); | ||
2446 | hwi_cleanup(phba); | ||
2447 | return -ENOMEM; | ||
2448 | } | ||
2449 | |||
2450 | |||
2451 | static int hwi_init_controller(struct beiscsi_hba *phba) | ||
2452 | { | ||
2453 | struct hwi_controller *phwi_ctrlr; | ||
2454 | |||
2455 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2456 | if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) { | ||
2457 | phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba-> | ||
2458 | init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address; | ||
2459 | SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p \n", | ||
2460 | phwi_ctrlr->phwi_ctxt); | ||
2461 | } else { | ||
2462 | shost_printk(KERN_ERR, phba->shost, | ||
2463 | "HWI_MEM_ADDN_CONTEXT is more than one element." | ||
2464 | "Failing to load\n"); | ||
2465 | return -ENOMEM; | ||
2466 | } | ||
2467 | |||
2468 | iscsi_init_global_templates(phba); | ||
2469 | beiscsi_init_wrb_handle(phba); | ||
2470 | hwi_init_async_pdu_ctx(phba); | ||
2471 | if (hwi_init_port(phba) != 0) { | ||
2472 | shost_printk(KERN_ERR, phba->shost, | ||
2473 | "hwi_init_controller failed\n"); | ||
2474 | return -ENOMEM; | ||
2475 | } | ||
2476 | return 0; | ||
2477 | } | ||
2478 | |||
2479 | static void beiscsi_free_mem(struct beiscsi_hba *phba) | ||
2480 | { | ||
2481 | struct be_mem_descriptor *mem_descr; | ||
2482 | int i, j; | ||
2483 | |||
2484 | mem_descr = phba->init_mem; | ||
2485 | i = 0; | ||
2486 | j = 0; | ||
2487 | for (i = 0; i < SE_MEM_MAX; i++) { | ||
2488 | for (j = mem_descr->num_elements; j > 0; j--) { | ||
2489 | pci_free_consistent(phba->pcidev, | ||
2490 | mem_descr->mem_array[j - 1].size, | ||
2491 | mem_descr->mem_array[j - 1].virtual_address, | ||
2492 | mem_descr->mem_array[j - 1].bus_address. | ||
2493 | u.a64.address); | ||
2494 | } | ||
2495 | kfree(mem_descr->mem_array); | ||
2496 | mem_descr++; | ||
2497 | } | ||
2498 | kfree(phba->init_mem); | ||
2499 | kfree(phba->phwi_ctrlr); | ||
2500 | } | ||
2501 | |||
2502 | static int beiscsi_init_controller(struct beiscsi_hba *phba) | ||
2503 | { | ||
2504 | int ret = -ENOMEM; | ||
2505 | |||
2506 | ret = beiscsi_get_memory(phba); | ||
2507 | if (ret < 0) { | ||
2508 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe -" | ||
2509 | "Failed in beiscsi_alloc_memory \n"); | ||
2510 | return ret; | ||
2511 | } | ||
2512 | |||
2513 | ret = hwi_init_controller(phba); | ||
2514 | if (ret) | ||
2515 | goto free_init; | ||
2516 | SE_DEBUG(DBG_LVL_8, "Return success from beiscsi_init_controller"); | ||
2517 | return 0; | ||
2518 | |||
2519 | free_init: | ||
2520 | beiscsi_free_mem(phba); | ||
2521 | return -ENOMEM; | ||
2522 | } | ||
2523 | |||
2524 | static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) | ||
2525 | { | ||
2526 | struct be_mem_descriptor *mem_descr_sglh, *mem_descr_sg; | ||
2527 | struct sgl_handle *psgl_handle; | ||
2528 | struct iscsi_sge *pfrag; | ||
2529 | unsigned int arr_index, i, idx; | ||
2530 | |||
2531 | phba->io_sgl_hndl_avbl = 0; | ||
2532 | phba->eh_sgl_hndl_avbl = 0; | ||
2533 | mem_descr_sglh = phba->init_mem; | ||
2534 | mem_descr_sglh += HWI_MEM_SGLH; | ||
2535 | if (1 == mem_descr_sglh->num_elements) { | ||
2536 | phba->io_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) * | ||
2537 | phba->params.ios_per_ctrl, | ||
2538 | GFP_KERNEL); | ||
2539 | if (!phba->io_sgl_hndl_base) { | ||
2540 | shost_printk(KERN_ERR, phba->shost, | ||
2541 | "Mem Alloc Failed. Failing to load\n"); | ||
2542 | return -ENOMEM; | ||
2543 | } | ||
2544 | phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) * | ||
2545 | (phba->params.icds_per_ctrl - | ||
2546 | phba->params.ios_per_ctrl), | ||
2547 | GFP_KERNEL); | ||
2548 | if (!phba->eh_sgl_hndl_base) { | ||
2549 | kfree(phba->io_sgl_hndl_base); | ||
2550 | shost_printk(KERN_ERR, phba->shost, | ||
2551 | "Mem Alloc Failed. Failing to load\n"); | ||
2552 | return -ENOMEM; | ||
2553 | } | ||
2554 | } else { | ||
2555 | shost_printk(KERN_ERR, phba->shost, | ||
2556 | "HWI_MEM_SGLH is more than one element." | ||
2557 | "Failing to load\n"); | ||
2558 | return -ENOMEM; | ||
2559 | } | ||
2560 | |||
2561 | arr_index = 0; | ||
2562 | idx = 0; | ||
2563 | while (idx < mem_descr_sglh->num_elements) { | ||
2564 | psgl_handle = mem_descr_sglh->mem_array[idx].virtual_address; | ||
2565 | |||
2566 | for (i = 0; i < (mem_descr_sglh->mem_array[idx].size / | ||
2567 | sizeof(struct sgl_handle)); i++) { | ||
2568 | if (arr_index < phba->params.ios_per_ctrl) { | ||
2569 | phba->io_sgl_hndl_base[arr_index] = psgl_handle; | ||
2570 | phba->io_sgl_hndl_avbl++; | ||
2571 | arr_index++; | ||
2572 | } else { | ||
2573 | phba->eh_sgl_hndl_base[arr_index - | ||
2574 | phba->params.ios_per_ctrl] = | ||
2575 | psgl_handle; | ||
2576 | arr_index++; | ||
2577 | phba->eh_sgl_hndl_avbl++; | ||
2578 | } | ||
2579 | psgl_handle++; | ||
2580 | } | ||
2581 | idx++; | ||
2582 | } | ||
2583 | SE_DEBUG(DBG_LVL_8, | ||
2584 | "phba->io_sgl_hndl_avbl=%d" | ||
2585 | "phba->eh_sgl_hndl_avbl=%d \n", | ||
2586 | phba->io_sgl_hndl_avbl, | ||
2587 | phba->eh_sgl_hndl_avbl); | ||
2588 | mem_descr_sg = phba->init_mem; | ||
2589 | mem_descr_sg += HWI_MEM_SGE; | ||
2590 | SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d \n", | ||
2591 | mem_descr_sg->num_elements); | ||
2592 | arr_index = 0; | ||
2593 | idx = 0; | ||
2594 | while (idx < mem_descr_sg->num_elements) { | ||
2595 | pfrag = mem_descr_sg->mem_array[idx].virtual_address; | ||
2596 | |||
2597 | for (i = 0; | ||
2598 | i < (mem_descr_sg->mem_array[idx].size) / | ||
2599 | (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io); | ||
2600 | i++) { | ||
2601 | if (arr_index < phba->params.ios_per_ctrl) | ||
2602 | psgl_handle = phba->io_sgl_hndl_base[arr_index]; | ||
2603 | else | ||
2604 | psgl_handle = phba->eh_sgl_hndl_base[arr_index - | ||
2605 | phba->params.ios_per_ctrl]; | ||
2606 | psgl_handle->pfrag = pfrag; | ||
2607 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0); | ||
2608 | AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0); | ||
2609 | pfrag += phba->params.num_sge_per_io; | ||
2610 | psgl_handle->sgl_index = | ||
2611 | phba->fw_config.iscsi_cid_start + arr_index++; | ||
2612 | } | ||
2613 | idx++; | ||
2614 | } | ||
2615 | phba->io_sgl_free_index = 0; | ||
2616 | phba->io_sgl_alloc_index = 0; | ||
2617 | phba->eh_sgl_free_index = 0; | ||
2618 | phba->eh_sgl_alloc_index = 0; | ||
2619 | return 0; | ||
2620 | } | ||
2621 | |||
2622 | static int hba_setup_cid_tbls(struct beiscsi_hba *phba) | ||
2623 | { | ||
2624 | int i, new_cid; | ||
2625 | |||
2626 | phba->cid_array = kmalloc(sizeof(void *) * phba->params.cxns_per_ctrl, | ||
2627 | GFP_KERNEL); | ||
2628 | if (!phba->cid_array) { | ||
2629 | shost_printk(KERN_ERR, phba->shost, | ||
2630 | "Failed to allocate memory in " | ||
2631 | "hba_setup_cid_tbls\n"); | ||
2632 | return -ENOMEM; | ||
2633 | } | ||
2634 | phba->ep_array = kmalloc(sizeof(struct iscsi_endpoint *) * | ||
2635 | phba->params.cxns_per_ctrl * 2, GFP_KERNEL); | ||
2636 | if (!phba->ep_array) { | ||
2637 | shost_printk(KERN_ERR, phba->shost, | ||
2638 | "Failed to allocate memory in " | ||
2639 | "hba_setup_cid_tbls \n"); | ||
2640 | kfree(phba->cid_array); | ||
2641 | return -ENOMEM; | ||
2642 | } | ||
2643 | new_cid = phba->fw_config.iscsi_icd_start; | ||
2644 | for (i = 0; i < phba->params.cxns_per_ctrl; i++) { | ||
2645 | phba->cid_array[i] = new_cid; | ||
2646 | new_cid += 2; | ||
2647 | } | ||
2648 | phba->avlbl_cids = phba->params.cxns_per_ctrl; | ||
2649 | return 0; | ||
2650 | } | ||
2651 | |||
2652 | static unsigned char hwi_enable_intr(struct beiscsi_hba *phba) | ||
2653 | { | ||
2654 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
2655 | struct hwi_controller *phwi_ctrlr; | ||
2656 | struct hwi_context_memory *phwi_context; | ||
2657 | struct be_queue_info *eq; | ||
2658 | u8 __iomem *addr; | ||
2659 | u32 reg; | ||
2660 | u32 enabled; | ||
2661 | |||
2662 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2663 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
2664 | |||
2665 | eq = &phwi_context->be_eq.q; | ||
2666 | addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg + | ||
2667 | PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); | ||
2668 | reg = ioread32(addr); | ||
2669 | SE_DEBUG(DBG_LVL_8, "reg =x%08x \n", reg); | ||
2670 | |||
2671 | enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | ||
2672 | if (!enabled) { | ||
2673 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | ||
2674 | SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p \n", reg, addr); | ||
2675 | iowrite32(reg, addr); | ||
2676 | SE_DEBUG(DBG_LVL_8, "eq->id=%d \n", eq->id); | ||
2677 | |||
2678 | hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); | ||
2679 | } else | ||
2680 | shost_printk(KERN_WARNING, phba->shost, | ||
2681 | "In hwi_enable_intr, Not Enabled \n"); | ||
2682 | return true; | ||
2683 | } | ||
2684 | |||
2685 | static void hwi_disable_intr(struct beiscsi_hba *phba) | ||
2686 | { | ||
2687 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
2688 | |||
2689 | u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; | ||
2690 | u32 reg = ioread32(addr); | ||
2691 | |||
2692 | u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | ||
2693 | if (enabled) { | ||
2694 | reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | ||
2695 | iowrite32(reg, addr); | ||
2696 | } else | ||
2697 | shost_printk(KERN_WARNING, phba->shost, | ||
2698 | "In hwi_disable_intr, Already Disabled \n"); | ||
2699 | } | ||
2700 | |||
2701 | static int beiscsi_init_port(struct beiscsi_hba *phba) | ||
2702 | { | ||
2703 | int ret; | ||
2704 | |||
2705 | ret = beiscsi_init_controller(phba); | ||
2706 | if (ret < 0) { | ||
2707 | shost_printk(KERN_ERR, phba->shost, | ||
2708 | "beiscsi_dev_probe - Failed in" | ||
2709 | "beiscsi_init_controller \n"); | ||
2710 | return ret; | ||
2711 | } | ||
2712 | ret = beiscsi_init_sgl_handle(phba); | ||
2713 | if (ret < 0) { | ||
2714 | shost_printk(KERN_ERR, phba->shost, | ||
2715 | "beiscsi_dev_probe - Failed in" | ||
2716 | "beiscsi_init_sgl_handle \n"); | ||
2717 | goto do_cleanup_ctrlr; | ||
2718 | } | ||
2719 | |||
2720 | if (hba_setup_cid_tbls(phba)) { | ||
2721 | shost_printk(KERN_ERR, phba->shost, | ||
2722 | "Failed in hba_setup_cid_tbls\n"); | ||
2723 | kfree(phba->io_sgl_hndl_base); | ||
2724 | kfree(phba->eh_sgl_hndl_base); | ||
2725 | goto do_cleanup_ctrlr; | ||
2726 | } | ||
2727 | |||
2728 | return ret; | ||
2729 | |||
2730 | do_cleanup_ctrlr: | ||
2731 | hwi_cleanup(phba); | ||
2732 | return ret; | ||
2733 | } | ||
2734 | |||
2735 | static void hwi_purge_eq(struct beiscsi_hba *phba) | ||
2736 | { | ||
2737 | struct hwi_controller *phwi_ctrlr; | ||
2738 | struct hwi_context_memory *phwi_context; | ||
2739 | struct be_queue_info *eq; | ||
2740 | struct be_eq_entry *eqe = NULL; | ||
2741 | |||
2742 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2743 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
2744 | eq = &phwi_context->be_eq.q; | ||
2745 | eqe = queue_tail_node(eq); | ||
2746 | |||
2747 | while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] | ||
2748 | & EQE_VALID_MASK) { | ||
2749 | AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); | ||
2750 | queue_tail_inc(eq); | ||
2751 | eqe = queue_tail_node(eq); | ||
2752 | } | ||
2753 | } | ||
2754 | |||
2755 | static void beiscsi_clean_port(struct beiscsi_hba *phba) | ||
2756 | { | ||
2757 | unsigned char mgmt_status; | ||
2758 | |||
2759 | mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0); | ||
2760 | if (mgmt_status) | ||
2761 | shost_printk(KERN_WARNING, phba->shost, | ||
2762 | "mgmt_epfw_cleanup FAILED \n"); | ||
2763 | hwi_cleanup(phba); | ||
2764 | hwi_purge_eq(phba); | ||
2765 | kfree(phba->io_sgl_hndl_base); | ||
2766 | kfree(phba->eh_sgl_hndl_base); | ||
2767 | kfree(phba->cid_array); | ||
2768 | kfree(phba->ep_array); | ||
2769 | } | ||
2770 | |||
2771 | void | ||
2772 | beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn, | ||
2773 | struct beiscsi_offload_params *params) | ||
2774 | { | ||
2775 | struct wrb_handle *pwrb_handle; | ||
2776 | struct iscsi_target_context_update_wrb *pwrb = NULL; | ||
2777 | struct be_mem_descriptor *mem_descr; | ||
2778 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
2779 | u32 doorbell = 0; | ||
2780 | |||
2781 | /* | ||
2782 | * We can always use 0 here because it is reserved by libiscsi for | ||
2783 | * login/startup related tasks. | ||
2784 | */ | ||
2785 | pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid, 0); | ||
2786 | pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb; | ||
2787 | memset(pwrb, 0, sizeof(*pwrb)); | ||
2788 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | ||
2789 | max_burst_length, pwrb, params->dw[offsetof | ||
2790 | (struct amap_beiscsi_offload_params, | ||
2791 | max_burst_length) / 32]); | ||
2792 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | ||
2793 | max_send_data_segment_length, pwrb, | ||
2794 | params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2795 | max_send_data_segment_length) / 32]); | ||
2796 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | ||
2797 | first_burst_length, | ||
2798 | pwrb, | ||
2799 | params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2800 | first_burst_length) / 32]); | ||
2801 | |||
2802 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb, | ||
2803 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2804 | erl) / 32] & OFFLD_PARAMS_ERL)); | ||
2805 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb, | ||
2806 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2807 | dde) / 32] & OFFLD_PARAMS_DDE) >> 2); | ||
2808 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb, | ||
2809 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2810 | hde) / 32] & OFFLD_PARAMS_HDE) >> 3); | ||
2811 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb, | ||
2812 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2813 | ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); | ||
2814 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb, | ||
2815 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2816 | imd) / 32] & OFFLD_PARAMS_IMD) >> 5); | ||
2817 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn, | ||
2818 | pwrb, | ||
2819 | (params->dw[offsetof(struct amap_beiscsi_offload_params, | ||
2820 | exp_statsn) / 32] + 1)); | ||
2821 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb, | ||
2822 | 0x7); | ||
2823 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx, | ||
2824 | pwrb, pwrb_handle->wrb_index); | ||
2825 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb, | ||
2826 | pwrb, pwrb_handle->nxt_wrb_index); | ||
2827 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | ||
2828 | session_state, pwrb, 0); | ||
2829 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack, | ||
2830 | pwrb, 1); | ||
2831 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq, | ||
2832 | pwrb, 0); | ||
2833 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb, | ||
2834 | 0); | ||
2835 | |||
2836 | mem_descr = phba->init_mem; | ||
2837 | mem_descr += ISCSI_MEM_GLOBAL_HEADER; | ||
2838 | |||
2839 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | ||
2840 | pad_buffer_addr_hi, pwrb, | ||
2841 | mem_descr->mem_array[0].bus_address.u.a32.address_hi); | ||
2842 | AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, | ||
2843 | pad_buffer_addr_lo, pwrb, | ||
2844 | mem_descr->mem_array[0].bus_address.u.a32.address_lo); | ||
2845 | |||
2846 | be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb)); | ||
2847 | |||
2848 | doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; | ||
2849 | doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK) << | ||
2850 | DB_DEF_PDU_WRB_INDEX_SHIFT; | ||
2851 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | ||
2852 | |||
2853 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | ||
2854 | } | ||
2855 | |||
2856 | static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt, | ||
2857 | int *index, int *age) | ||
2858 | { | ||
2859 | *index = be32_to_cpu(itt) >> 16; | ||
2860 | if (age) | ||
2861 | *age = conn->session->age; | ||
2862 | } | ||
2863 | |||
2864 | /** | ||
2865 | * beiscsi_alloc_pdu - allocates pdu and related resources | ||
2866 | * @task: libiscsi task | ||
2867 | * @opcode: opcode of pdu for task | ||
2868 | * | ||
2869 | * This is called with the session lock held. It will allocate | ||
2870 | * the wrb and sgl if needed for the command. And it will prep | ||
2871 | * the pdu's itt. beiscsi_parse_pdu will later translate | ||
2872 | * the pdu itt to the libiscsi task itt. | ||
2873 | */ | ||
2874 | static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode) | ||
2875 | { | ||
2876 | struct beiscsi_io_task *io_task = task->dd_data; | ||
2877 | struct iscsi_conn *conn = task->conn; | ||
2878 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
2879 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
2880 | struct hwi_wrb_context *pwrb_context; | ||
2881 | struct hwi_controller *phwi_ctrlr; | ||
2882 | itt_t itt; | ||
2883 | struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; | ||
2884 | dma_addr_t paddr; | ||
2885 | |||
2886 | io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool, | ||
2887 | GFP_KERNEL, &paddr); | ||
2888 | |||
2889 | if (!io_task->cmd_bhs) | ||
2890 | return -ENOMEM; | ||
2891 | |||
2892 | io_task->bhs_pa.u.a64.address = paddr; | ||
2893 | io_task->pwrb_handle = alloc_wrb_handle(phba, | ||
2894 | beiscsi_conn->beiscsi_conn_cid, | ||
2895 | task->itt); | ||
2896 | io_task->pwrb_handle->pio_handle = task; | ||
2897 | io_task->conn = beiscsi_conn; | ||
2898 | |||
2899 | task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr; | ||
2900 | task->hdr_max = sizeof(struct be_cmd_bhs); | ||
2901 | |||
2902 | if (task->sc) { | ||
2903 | spin_lock(&phba->io_sgl_lock); | ||
2904 | io_task->psgl_handle = alloc_io_sgl_handle(phba); | ||
2905 | spin_unlock(&phba->io_sgl_lock); | ||
2906 | if (!io_task->psgl_handle) | ||
2907 | goto free_hndls; | ||
2908 | |||
2909 | } else { | ||
2910 | io_task->scsi_cmnd = NULL; | ||
2911 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { | ||
2912 | if (!beiscsi_conn->login_in_progress) { | ||
2913 | spin_lock(&phba->mgmt_sgl_lock); | ||
2914 | io_task->psgl_handle = (struct sgl_handle *) | ||
2915 | alloc_mgmt_sgl_handle(phba); | ||
2916 | spin_unlock(&phba->mgmt_sgl_lock); | ||
2917 | if (!io_task->psgl_handle) | ||
2918 | goto free_hndls; | ||
2919 | |||
2920 | beiscsi_conn->login_in_progress = 1; | ||
2921 | beiscsi_conn->plogin_sgl_handle = | ||
2922 | io_task->psgl_handle; | ||
2923 | } else { | ||
2924 | io_task->psgl_handle = | ||
2925 | beiscsi_conn->plogin_sgl_handle; | ||
2926 | } | ||
2927 | } else { | ||
2928 | spin_lock(&phba->mgmt_sgl_lock); | ||
2929 | io_task->psgl_handle = alloc_mgmt_sgl_handle(phba); | ||
2930 | spin_unlock(&phba->mgmt_sgl_lock); | ||
2931 | if (!io_task->psgl_handle) | ||
2932 | goto free_hndls; | ||
2933 | } | ||
2934 | } | ||
2935 | itt = (itt_t) cpu_to_be32(((unsigned int)task->itt << 16) | | ||
2936 | (unsigned int)(io_task->psgl_handle->sgl_index)); | ||
2937 | io_task->cmd_bhs->iscsi_hdr.itt = itt; | ||
2938 | return 0; | ||
2939 | |||
2940 | free_hndls: | ||
2941 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2942 | pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid]; | ||
2943 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); | ||
2944 | io_task->pwrb_handle = NULL; | ||
2945 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, | ||
2946 | io_task->bhs_pa.u.a64.address); | ||
2947 | SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed \n"); | ||
2948 | return -ENOMEM; | ||
2949 | } | ||
2950 | |||
2951 | static void beiscsi_cleanup_task(struct iscsi_task *task) | ||
2952 | { | ||
2953 | struct beiscsi_io_task *io_task = task->dd_data; | ||
2954 | struct iscsi_conn *conn = task->conn; | ||
2955 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
2956 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
2957 | struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; | ||
2958 | struct hwi_wrb_context *pwrb_context; | ||
2959 | struct hwi_controller *phwi_ctrlr; | ||
2960 | |||
2961 | phwi_ctrlr = phba->phwi_ctrlr; | ||
2962 | pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid]; | ||
2963 | if (io_task->pwrb_handle) { | ||
2964 | free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); | ||
2965 | io_task->pwrb_handle = NULL; | ||
2966 | } | ||
2967 | |||
2968 | if (io_task->cmd_bhs) { | ||
2969 | pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, | ||
2970 | io_task->bhs_pa.u.a64.address); | ||
2971 | } | ||
2972 | |||
2973 | if (task->sc) { | ||
2974 | if (io_task->psgl_handle) { | ||
2975 | spin_lock(&phba->io_sgl_lock); | ||
2976 | free_io_sgl_handle(phba, io_task->psgl_handle); | ||
2977 | spin_unlock(&phba->io_sgl_lock); | ||
2978 | io_task->psgl_handle = NULL; | ||
2979 | } | ||
2980 | } else { | ||
2981 | if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) | ||
2982 | return; | ||
2983 | if (io_task->psgl_handle) { | ||
2984 | spin_lock(&phba->mgmt_sgl_lock); | ||
2985 | free_mgmt_sgl_handle(phba, io_task->psgl_handle); | ||
2986 | spin_unlock(&phba->mgmt_sgl_lock); | ||
2987 | io_task->psgl_handle = NULL; | ||
2988 | } | ||
2989 | } | ||
2990 | } | ||
2991 | |||
2992 | static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, | ||
2993 | unsigned int num_sg, unsigned int xferlen, | ||
2994 | unsigned int writedir) | ||
2995 | { | ||
2996 | |||
2997 | struct beiscsi_io_task *io_task = task->dd_data; | ||
2998 | struct iscsi_conn *conn = task->conn; | ||
2999 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
3000 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
3001 | struct iscsi_wrb *pwrb = NULL; | ||
3002 | unsigned int doorbell = 0; | ||
3003 | |||
3004 | pwrb = io_task->pwrb_handle->pwrb; | ||
3005 | io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; | ||
3006 | io_task->bhs_len = sizeof(struct be_cmd_bhs); | ||
3007 | |||
3008 | if (writedir) { | ||
3009 | SE_DEBUG(DBG_LVL_4, " WRITE Command \t"); | ||
3010 | memset(&io_task->cmd_bhs->iscsi_data_pdu, 0, 48); | ||
3011 | AMAP_SET_BITS(struct amap_pdu_data_out, itt, | ||
3012 | &io_task->cmd_bhs->iscsi_data_pdu, | ||
3013 | (unsigned int)io_task->cmd_bhs->iscsi_hdr.itt); | ||
3014 | AMAP_SET_BITS(struct amap_pdu_data_out, opcode, | ||
3015 | &io_task->cmd_bhs->iscsi_data_pdu, | ||
3016 | ISCSI_OPCODE_SCSI_DATA_OUT); | ||
3017 | AMAP_SET_BITS(struct amap_pdu_data_out, final_bit, | ||
3018 | &io_task->cmd_bhs->iscsi_data_pdu, 1); | ||
3019 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD); | ||
3020 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); | ||
3021 | } else { | ||
3022 | SE_DEBUG(DBG_LVL_4, "READ Command \t"); | ||
3023 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD); | ||
3024 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); | ||
3025 | } | ||
3026 | memcpy(&io_task->cmd_bhs->iscsi_data_pdu. | ||
3027 | dw[offsetof(struct amap_pdu_data_out, lun) / 32], | ||
3028 | io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun)); | ||
3029 | |||
3030 | AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb, | ||
3031 | cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr. | ||
3032 | lun[0])); | ||
3033 | AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen); | ||
3034 | AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, | ||
3035 | io_task->pwrb_handle->wrb_index); | ||
3036 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, | ||
3037 | be32_to_cpu(task->cmdsn)); | ||
3038 | AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, | ||
3039 | io_task->psgl_handle->sgl_index); | ||
3040 | |||
3041 | hwi_write_sgl(pwrb, sg, num_sg, io_task); | ||
3042 | |||
3043 | AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, | ||
3044 | io_task->pwrb_handle->nxt_wrb_index); | ||
3045 | be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); | ||
3046 | |||
3047 | doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; | ||
3048 | doorbell |= (io_task->pwrb_handle->wrb_index & | ||
3049 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; | ||
3050 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | ||
3051 | |||
3052 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | ||
3053 | return 0; | ||
3054 | } | ||
3055 | |||
3056 | static int beiscsi_mtask(struct iscsi_task *task) | ||
3057 | { | ||
3058 | struct beiscsi_io_task *aborted_io_task, *io_task = task->dd_data; | ||
3059 | struct iscsi_conn *conn = task->conn; | ||
3060 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
3061 | struct beiscsi_hba *phba = beiscsi_conn->phba; | ||
3062 | struct iscsi_wrb *pwrb = NULL; | ||
3063 | unsigned int doorbell = 0; | ||
3064 | struct iscsi_task *aborted_task; | ||
3065 | |||
3066 | pwrb = io_task->pwrb_handle->pwrb; | ||
3067 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, | ||
3068 | be32_to_cpu(task->cmdsn)); | ||
3069 | AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, | ||
3070 | io_task->pwrb_handle->wrb_index); | ||
3071 | AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, | ||
3072 | io_task->psgl_handle->sgl_index); | ||
3073 | |||
3074 | switch (task->hdr->opcode & ISCSI_OPCODE_MASK) { | ||
3075 | case ISCSI_OP_LOGIN: | ||
3076 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, TGT_DM_CMD); | ||
3077 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | ||
3078 | AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1); | ||
3079 | hwi_write_buffer(pwrb, task); | ||
3080 | break; | ||
3081 | case ISCSI_OP_NOOP_OUT: | ||
3082 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_RD_CMD); | ||
3083 | hwi_write_buffer(pwrb, task); | ||
3084 | break; | ||
3085 | case ISCSI_OP_TEXT: | ||
3086 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_WR_CMD); | ||
3087 | AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); | ||
3088 | hwi_write_buffer(pwrb, task); | ||
3089 | break; | ||
3090 | case ISCSI_OP_SCSI_TMFUNC: | ||
3091 | aborted_task = iscsi_itt_to_task(conn, | ||
3092 | ((struct iscsi_tm *)task->hdr)->rtt); | ||
3093 | if (!aborted_task) | ||
3094 | return 0; | ||
3095 | aborted_io_task = aborted_task->dd_data; | ||
3096 | if (!aborted_io_task->scsi_cmnd) | ||
3097 | return 0; | ||
3098 | |||
3099 | mgmt_invalidate_icds(phba, | ||
3100 | aborted_io_task->psgl_handle->sgl_index, | ||
3101 | beiscsi_conn->beiscsi_conn_cid); | ||
3102 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, INI_TMF_CMD); | ||
3103 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | ||
3104 | hwi_write_buffer(pwrb, task); | ||
3105 | break; | ||
3106 | case ISCSI_OP_LOGOUT: | ||
3107 | AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); | ||
3108 | AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, | ||
3109 | HWH_TYPE_LOGOUT); | ||
3110 | hwi_write_buffer(pwrb, task); | ||
3111 | break; | ||
3112 | |||
3113 | default: | ||
3114 | SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported \n", | ||
3115 | task->hdr->opcode & ISCSI_OPCODE_MASK); | ||
3116 | return -EINVAL; | ||
3117 | } | ||
3118 | |||
3119 | AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, | ||
3120 | be32_to_cpu(task->data_count)); | ||
3121 | AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, | ||
3122 | io_task->pwrb_handle->nxt_wrb_index); | ||
3123 | be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); | ||
3124 | |||
3125 | doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; | ||
3126 | doorbell |= (io_task->pwrb_handle->wrb_index & | ||
3127 | DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT; | ||
3128 | doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; | ||
3129 | iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); | ||
3130 | return 0; | ||
3131 | } | ||
3132 | |||
3133 | static int beiscsi_task_xmit(struct iscsi_task *task) | ||
3134 | { | ||
3135 | struct iscsi_conn *conn = task->conn; | ||
3136 | struct beiscsi_io_task *io_task = task->dd_data; | ||
3137 | struct scsi_cmnd *sc = task->sc; | ||
3138 | struct beiscsi_conn *beiscsi_conn = conn->dd_data; | ||
3139 | struct scatterlist *sg; | ||
3140 | int num_sg; | ||
3141 | unsigned int writedir = 0, xferlen = 0; | ||
3142 | |||
3143 | SE_DEBUG(DBG_LVL_4, "\n cid=%d In beiscsi_task_xmit task=%p conn=%p \t" | ||
3144 | "beiscsi_conn=%p \n", beiscsi_conn->beiscsi_conn_cid, | ||
3145 | task, conn, beiscsi_conn); | ||
3146 | if (!sc) | ||
3147 | return beiscsi_mtask(task); | ||
3148 | |||
3149 | io_task->scsi_cmnd = sc; | ||
3150 | num_sg = scsi_dma_map(sc); | ||
3151 | if (num_sg < 0) { | ||
3152 | SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n") | ||
3153 | return num_sg; | ||
3154 | } | ||
3155 | SE_DEBUG(DBG_LVL_4, "xferlen=0x%08x scmd=%p num_sg=%d sernum=%lu\n", | ||
3156 | (scsi_bufflen(sc)), sc, num_sg, sc->serial_number); | ||
3157 | xferlen = scsi_bufflen(sc); | ||
3158 | sg = scsi_sglist(sc); | ||
3159 | if (sc->sc_data_direction == DMA_TO_DEVICE) { | ||
3160 | writedir = 1; | ||
3161 | SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x \n", | ||
3162 | task->imm_count); | ||
3163 | } else | ||
3164 | writedir = 0; | ||
3165 | return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); | ||
3166 | } | ||
3167 | |||
3168 | static void beiscsi_remove(struct pci_dev *pcidev) | ||
3169 | { | ||
3170 | struct beiscsi_hba *phba = NULL; | ||
3171 | |||
3172 | phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); | ||
3173 | if (!phba) { | ||
3174 | dev_err(&pcidev->dev, "beiscsi_remove called with no phba \n"); | ||
3175 | return; | ||
3176 | } | ||
3177 | |||
3178 | hwi_disable_intr(phba); | ||
3179 | if (phba->pcidev->irq) | ||
3180 | free_irq(phba->pcidev->irq, phba); | ||
3181 | destroy_workqueue(phba->wq); | ||
3182 | if (blk_iopoll_enabled) | ||
3183 | blk_iopoll_disable(&phba->iopoll); | ||
3184 | |||
3185 | beiscsi_clean_port(phba); | ||
3186 | beiscsi_free_mem(phba); | ||
3187 | beiscsi_unmap_pci_function(phba); | ||
3188 | pci_free_consistent(phba->pcidev, | ||
3189 | phba->ctrl.mbox_mem_alloced.size, | ||
3190 | phba->ctrl.mbox_mem_alloced.va, | ||
3191 | phba->ctrl.mbox_mem_alloced.dma); | ||
3192 | iscsi_host_remove(phba->shost); | ||
3193 | pci_dev_put(phba->pcidev); | ||
3194 | iscsi_host_free(phba->shost); | ||
3195 | } | ||
3196 | |||
3197 | static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | ||
3198 | const struct pci_device_id *id) | ||
3199 | { | ||
3200 | struct beiscsi_hba *phba = NULL; | ||
3201 | int ret; | ||
3202 | |||
3203 | ret = beiscsi_enable_pci(pcidev); | ||
3204 | if (ret < 0) { | ||
3205 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
3206 | "Failed to enable pci device \n"); | ||
3207 | return ret; | ||
3208 | } | ||
3209 | |||
3210 | phba = beiscsi_hba_alloc(pcidev); | ||
3211 | if (!phba) { | ||
3212 | dev_err(&pcidev->dev, "beiscsi_dev_probe-" | ||
3213 | " Failed in beiscsi_hba_alloc \n"); | ||
3214 | goto disable_pci; | ||
3215 | } | ||
3216 | |||
3217 | pci_set_drvdata(pcidev, phba); | ||
3218 | ret = be_ctrl_init(phba, pcidev); | ||
3219 | if (ret) { | ||
3220 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
3221 | "Failed in be_ctrl_init\n"); | ||
3222 | goto hba_free; | ||
3223 | } | ||
3224 | |||
3225 | spin_lock_init(&phba->io_sgl_lock); | ||
3226 | spin_lock_init(&phba->mgmt_sgl_lock); | ||
3227 | spin_lock_init(&phba->isr_lock); | ||
3228 | beiscsi_get_params(phba); | ||
3229 | ret = beiscsi_init_port(phba); | ||
3230 | if (ret < 0) { | ||
3231 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
3232 | "Failed in beiscsi_init_port\n"); | ||
3233 | goto free_port; | ||
3234 | } | ||
3235 | |||
3236 | snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", | ||
3237 | phba->shost->host_no); | ||
3238 | phba->wq = create_singlethread_workqueue(phba->wq_name); | ||
3239 | if (!phba->wq) { | ||
3240 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
3241 | "Failed to allocate work queue\n"); | ||
3242 | goto free_twq; | ||
3243 | } | ||
3244 | |||
3245 | INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs); | ||
3246 | |||
3247 | if (blk_iopoll_enabled) { | ||
3248 | blk_iopoll_init(&phba->iopoll, be_iopoll_budget, be_iopoll); | ||
3249 | blk_iopoll_enable(&phba->iopoll); | ||
3250 | } | ||
3251 | |||
3252 | ret = beiscsi_init_irqs(phba); | ||
3253 | if (ret < 0) { | ||
3254 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
3255 | "Failed to beiscsi_init_irqs\n"); | ||
3256 | goto free_blkenbld; | ||
3257 | } | ||
3258 | ret = hwi_enable_intr(phba); | ||
3259 | if (ret < 0) { | ||
3260 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
3261 | "Failed to hwi_enable_intr\n"); | ||
3262 | goto free_ctrlr; | ||
3263 | } | ||
3264 | |||
3265 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED \n\n\n"); | ||
3266 | return 0; | ||
3267 | |||
3268 | free_ctrlr: | ||
3269 | if (phba->pcidev->irq) | ||
3270 | free_irq(phba->pcidev->irq, phba); | ||
3271 | free_blkenbld: | ||
3272 | destroy_workqueue(phba->wq); | ||
3273 | if (blk_iopoll_enabled) | ||
3274 | blk_iopoll_disable(&phba->iopoll); | ||
3275 | free_twq: | ||
3276 | beiscsi_clean_port(phba); | ||
3277 | beiscsi_free_mem(phba); | ||
3278 | free_port: | ||
3279 | pci_free_consistent(phba->pcidev, | ||
3280 | phba->ctrl.mbox_mem_alloced.size, | ||
3281 | phba->ctrl.mbox_mem_alloced.va, | ||
3282 | phba->ctrl.mbox_mem_alloced.dma); | ||
3283 | beiscsi_unmap_pci_function(phba); | ||
3284 | hba_free: | ||
3285 | iscsi_host_remove(phba->shost); | ||
3286 | pci_dev_put(phba->pcidev); | ||
3287 | iscsi_host_free(phba->shost); | ||
3288 | disable_pci: | ||
3289 | pci_disable_device(pcidev); | ||
3290 | return ret; | ||
3291 | } | ||
3292 | |||
3293 | struct iscsi_transport beiscsi_iscsi_transport = { | ||
3294 | .owner = THIS_MODULE, | ||
3295 | .name = DRV_NAME, | ||
3296 | .caps = CAP_RECOVERY_L0 | CAP_HDRDGST | | ||
3297 | CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD, | ||
3298 | .param_mask = ISCSI_MAX_RECV_DLENGTH | | ||
3299 | ISCSI_MAX_XMIT_DLENGTH | | ||
3300 | ISCSI_HDRDGST_EN | | ||
3301 | ISCSI_DATADGST_EN | | ||
3302 | ISCSI_INITIAL_R2T_EN | | ||
3303 | ISCSI_MAX_R2T | | ||
3304 | ISCSI_IMM_DATA_EN | | ||
3305 | ISCSI_FIRST_BURST | | ||
3306 | ISCSI_MAX_BURST | | ||
3307 | ISCSI_PDU_INORDER_EN | | ||
3308 | ISCSI_DATASEQ_INORDER_EN | | ||
3309 | ISCSI_ERL | | ||
3310 | ISCSI_CONN_PORT | | ||
3311 | ISCSI_CONN_ADDRESS | | ||
3312 | ISCSI_EXP_STATSN | | ||
3313 | ISCSI_PERSISTENT_PORT | | ||
3314 | ISCSI_PERSISTENT_ADDRESS | | ||
3315 | ISCSI_TARGET_NAME | ISCSI_TPGT | | ||
3316 | ISCSI_USERNAME | ISCSI_PASSWORD | | ||
3317 | ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | | ||
3318 | ISCSI_FAST_ABORT | ISCSI_ABORT_TMO | | ||
3319 | ISCSI_LU_RESET_TMO | | ||
3320 | ISCSI_PING_TMO | ISCSI_RECV_TMO | | ||
3321 | ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME, | ||
3322 | .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | | ||
3323 | ISCSI_HOST_INITIATOR_NAME, | ||
3324 | .create_session = beiscsi_session_create, | ||
3325 | .destroy_session = beiscsi_session_destroy, | ||
3326 | .create_conn = beiscsi_conn_create, | ||
3327 | .bind_conn = beiscsi_conn_bind, | ||
3328 | .destroy_conn = iscsi_conn_teardown, | ||
3329 | .set_param = beiscsi_set_param, | ||
3330 | .get_conn_param = beiscsi_conn_get_param, | ||
3331 | .get_session_param = iscsi_session_get_param, | ||
3332 | .get_host_param = beiscsi_get_host_param, | ||
3333 | .start_conn = beiscsi_conn_start, | ||
3334 | .stop_conn = beiscsi_conn_stop, | ||
3335 | .send_pdu = iscsi_conn_send_pdu, | ||
3336 | .xmit_task = beiscsi_task_xmit, | ||
3337 | .cleanup_task = beiscsi_cleanup_task, | ||
3338 | .alloc_pdu = beiscsi_alloc_pdu, | ||
3339 | .parse_pdu_itt = beiscsi_parse_pdu, | ||
3340 | .get_stats = beiscsi_conn_get_stats, | ||
3341 | .ep_connect = beiscsi_ep_connect, | ||
3342 | .ep_poll = beiscsi_ep_poll, | ||
3343 | .ep_disconnect = beiscsi_ep_disconnect, | ||
3344 | .session_recovery_timedout = iscsi_session_recovery_timedout, | ||
3345 | }; | ||
3346 | |||
3347 | static struct pci_driver beiscsi_pci_driver = { | ||
3348 | .name = DRV_NAME, | ||
3349 | .probe = beiscsi_dev_probe, | ||
3350 | .remove = beiscsi_remove, | ||
3351 | .id_table = beiscsi_pci_id_table | ||
3352 | }; | ||
3353 | |||
3354 | static int __init beiscsi_module_init(void) | ||
3355 | { | ||
3356 | int ret; | ||
3357 | |||
3358 | beiscsi_scsi_transport = | ||
3359 | iscsi_register_transport(&beiscsi_iscsi_transport); | ||
3360 | if (!beiscsi_scsi_transport) { | ||
3361 | SE_DEBUG(DBG_LVL_1, | ||
3362 | "beiscsi_module_init - Unable to register beiscsi" | ||
3363 | "transport.\n"); | ||
3364 | ret = -ENOMEM; | ||
3365 | } | ||
3366 | SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p \n", | ||
3367 | &beiscsi_iscsi_transport); | ||
3368 | |||
3369 | ret = pci_register_driver(&beiscsi_pci_driver); | ||
3370 | if (ret) { | ||
3371 | SE_DEBUG(DBG_LVL_1, | ||
3372 | "beiscsi_module_init - Unable to register" | ||
3373 | "beiscsi pci driver.\n"); | ||
3374 | goto unregister_iscsi_transport; | ||
3375 | } | ||
3376 | return 0; | ||
3377 | |||
3378 | unregister_iscsi_transport: | ||
3379 | iscsi_unregister_transport(&beiscsi_iscsi_transport); | ||
3380 | return ret; | ||
3381 | } | ||
3382 | |||
3383 | static void __exit beiscsi_module_exit(void) | ||
3384 | { | ||
3385 | pci_unregister_driver(&beiscsi_pci_driver); | ||
3386 | iscsi_unregister_transport(&beiscsi_iscsi_transport); | ||
3387 | } | ||
3388 | |||
3389 | module_init(beiscsi_module_init); | ||
3390 | module_exit(beiscsi_module_exit); | ||
diff --git a/drivers/scsi/be2iscsi/be_main.h b/drivers/scsi/be2iscsi/be_main.h new file mode 100644 index 000000000000..53c9b70ac7ac --- /dev/null +++ b/drivers/scsi/be2iscsi/be_main.h | |||
@@ -0,0 +1,837 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Written by: Jayamohan Kallickal (jayamohank@serverengines.com) | ||
11 | * | ||
12 | * Contact Information: | ||
13 | * linux-drivers@serverengines.com | ||
14 | * | ||
15 | * ServerEngines | ||
16 | * 209 N. Fair Oaks Ave | ||
17 | * Sunnyvale, CA 94085 | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef _BEISCSI_MAIN_ | ||
22 | #define _BEISCSI_MAIN_ | ||
23 | |||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/in.h> | ||
28 | #include <linux/blk-iopoll.h> | ||
29 | #include <scsi/scsi.h> | ||
30 | #include <scsi/scsi_cmnd.h> | ||
31 | #include <scsi/scsi_device.h> | ||
32 | #include <scsi/scsi_host.h> | ||
33 | #include <scsi/iscsi_proto.h> | ||
34 | #include <scsi/libiscsi.h> | ||
35 | #include <scsi/scsi_transport_iscsi.h> | ||
36 | |||
37 | #include "be.h" | ||
38 | |||
39 | |||
40 | |||
41 | #define DRV_NAME "be2iscsi" | ||
42 | #define BUILD_STR "2.0.527.0" | ||
43 | |||
44 | #define BE_NAME "ServerEngines BladeEngine2" \ | ||
45 | "Linux iSCSI Driver version" BUILD_STR | ||
46 | #define DRV_DESC BE_NAME " " "Driver" | ||
47 | |||
48 | #define BE_VENDOR_ID 0x19A2 | ||
49 | #define BE_DEVICE_ID1 0x212 | ||
50 | #define OC_DEVICE_ID1 0x702 | ||
51 | #define OC_DEVICE_ID2 0x703 | ||
52 | |||
53 | #define BE2_MAX_SESSIONS 64 | ||
54 | #define BE2_CMDS_PER_CXN 128 | ||
55 | #define BE2_LOGOUTS BE2_MAX_SESSIONS | ||
56 | #define BE2_TMFS 16 | ||
57 | #define BE2_NOPOUT_REQ 16 | ||
58 | #define BE2_ASYNCPDUS BE2_MAX_SESSIONS | ||
59 | #define BE2_MAX_ICDS 2048 | ||
60 | #define BE2_SGE 32 | ||
61 | #define BE2_DEFPDU_HDR_SZ 64 | ||
62 | #define BE2_DEFPDU_DATA_SZ 8192 | ||
63 | #define BE2_IO_DEPTH \ | ||
64 | (BE2_MAX_ICDS / 2 - (BE2_LOGOUTS + BE2_TMFS + BE2_NOPOUT_REQ)) | ||
65 | |||
66 | #define BEISCSI_SGLIST_ELEMENTS BE2_SGE | ||
67 | |||
68 | #define BEISCSI_MAX_CMNDS 1024 /* Max IO's per Ctrlr sht->can_queue */ | ||
69 | #define BEISCSI_CMD_PER_LUN 128 /* scsi_host->cmd_per_lun */ | ||
70 | #define BEISCSI_MAX_SECTORS 2048 /* scsi_host->max_sectors */ | ||
71 | |||
72 | #define BEISCSI_MAX_CMD_LEN 16 /* scsi_host->max_cmd_len */ | ||
73 | #define BEISCSI_NUM_MAX_LUN 256 /* scsi_host->max_lun */ | ||
74 | #define BEISCSI_NUM_DEVICES_SUPPORTED 0x01 | ||
75 | #define BEISCSI_MAX_FRAGS_INIT 192 | ||
76 | #define BE_NUM_MSIX_ENTRIES 1 | ||
77 | #define MPU_EP_SEMAPHORE 0xac | ||
78 | |||
79 | #define BE_SENSE_INFO_SIZE 258 | ||
80 | #define BE_ISCSI_PDU_HEADER_SIZE 64 | ||
81 | #define BE_MIN_MEM_SIZE 16384 | ||
82 | |||
83 | #define IIOC_SCSI_DATA 0x05 /* Write Operation */ | ||
84 | |||
85 | #define DBG_LVL 0x00000001 | ||
86 | #define DBG_LVL_1 0x00000001 | ||
87 | #define DBG_LVL_2 0x00000002 | ||
88 | #define DBG_LVL_3 0x00000004 | ||
89 | #define DBG_LVL_4 0x00000008 | ||
90 | #define DBG_LVL_5 0x00000010 | ||
91 | #define DBG_LVL_6 0x00000020 | ||
92 | #define DBG_LVL_7 0x00000040 | ||
93 | #define DBG_LVL_8 0x00000080 | ||
94 | |||
95 | #define SE_DEBUG(debug_mask, fmt, args...) \ | ||
96 | do { \ | ||
97 | if (debug_mask & DBG_LVL) { \ | ||
98 | printk(KERN_ERR "(%s():%d):", __func__, __LINE__);\ | ||
99 | printk(fmt, ##args); \ | ||
100 | } \ | ||
101 | } while (0); | ||
102 | |||
103 | /** | ||
104 | * hardware needs the async PDU buffers to be posted in multiples of 8 | ||
105 | * So have atleast 8 of them by default | ||
106 | */ | ||
107 | |||
108 | #define HWI_GET_ASYNC_PDU_CTX(phwi) (phwi->phwi_ctxt->pasync_ctx) | ||
109 | |||
110 | /********* Memory BAR register ************/ | ||
111 | #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc | ||
112 | /** | ||
113 | * Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt | ||
114 | * Disable" may still globally block interrupts in addition to individual | ||
115 | * interrupt masks; a mechanism for the device driver to block all interrupts | ||
116 | * atomically without having to arbitrate for the PCI Interrupt Disable bit | ||
117 | * with the OS. | ||
118 | */ | ||
119 | #define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ | ||
120 | |||
121 | /********* ISR0 Register offset **********/ | ||
122 | #define CEV_ISR0_OFFSET 0xC18 | ||
123 | #define CEV_ISR_SIZE 4 | ||
124 | |||
125 | /** | ||
126 | * Macros for reading/writing a protection domain or CSR registers | ||
127 | * in BladeEngine. | ||
128 | */ | ||
129 | |||
130 | #define DB_TXULP0_OFFSET 0x40 | ||
131 | #define DB_RXULP0_OFFSET 0xA0 | ||
132 | /********* Event Q door bell *************/ | ||
133 | #define DB_EQ_OFFSET DB_CQ_OFFSET | ||
134 | #define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ | ||
135 | /* Clear the interrupt for this eq */ | ||
136 | #define DB_EQ_CLR_SHIFT (9) /* bit 9 */ | ||
137 | /* Must be 1 */ | ||
138 | #define DB_EQ_EVNT_SHIFT (10) /* bit 10 */ | ||
139 | /* Number of event entries processed */ | ||
140 | #define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ | ||
141 | /* Rearm bit */ | ||
142 | #define DB_EQ_REARM_SHIFT (29) /* bit 29 */ | ||
143 | |||
144 | /********* Compl Q door bell *************/ | ||
145 | #define DB_CQ_OFFSET 0x120 | ||
146 | #define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ | ||
147 | /* Number of event entries processed */ | ||
148 | #define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ | ||
149 | /* Rearm bit */ | ||
150 | #define DB_CQ_REARM_SHIFT (29) /* bit 29 */ | ||
151 | |||
152 | #define GET_HWI_CONTROLLER_WS(pc) (pc->phwi_ctrlr) | ||
153 | #define HWI_GET_DEF_BUFQ_ID(pc) (((struct hwi_controller *)\ | ||
154 | (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_data.id) | ||
155 | #define HWI_GET_DEF_HDRQ_ID(pc) (((struct hwi_controller *)\ | ||
156 | (GET_HWI_CONTROLLER_WS(pc)))->default_pdu_hdr.id) | ||
157 | |||
158 | #define PAGES_REQUIRED(x) \ | ||
159 | ((x < PAGE_SIZE) ? 1 : ((x + PAGE_SIZE - 1) / PAGE_SIZE)) | ||
160 | |||
161 | enum be_mem_enum { | ||
162 | HWI_MEM_ADDN_CONTEXT, | ||
163 | HWI_MEM_CQ, | ||
164 | HWI_MEM_EQ, | ||
165 | HWI_MEM_WRB, | ||
166 | HWI_MEM_WRBH, | ||
167 | HWI_MEM_SGLH, /* 5 */ | ||
168 | HWI_MEM_SGE, | ||
169 | HWI_MEM_ASYNC_HEADER_BUF, | ||
170 | HWI_MEM_ASYNC_DATA_BUF, | ||
171 | HWI_MEM_ASYNC_HEADER_RING, | ||
172 | HWI_MEM_ASYNC_DATA_RING, /* 10 */ | ||
173 | HWI_MEM_ASYNC_HEADER_HANDLE, | ||
174 | HWI_MEM_ASYNC_DATA_HANDLE, | ||
175 | HWI_MEM_ASYNC_PDU_CONTEXT, | ||
176 | ISCSI_MEM_GLOBAL_HEADER, | ||
177 | SE_MEM_MAX /* 15 */ | ||
178 | }; | ||
179 | |||
180 | struct be_bus_address32 { | ||
181 | unsigned int address_lo; | ||
182 | unsigned int address_hi; | ||
183 | }; | ||
184 | |||
185 | struct be_bus_address64 { | ||
186 | unsigned long long address; | ||
187 | }; | ||
188 | |||
189 | struct be_bus_address { | ||
190 | union { | ||
191 | struct be_bus_address32 a32; | ||
192 | struct be_bus_address64 a64; | ||
193 | } u; | ||
194 | }; | ||
195 | |||
196 | struct mem_array { | ||
197 | struct be_bus_address bus_address; /* Bus address of location */ | ||
198 | void *virtual_address; /* virtual address to the location */ | ||
199 | unsigned int size; /* Size required by memory block */ | ||
200 | }; | ||
201 | |||
202 | struct be_mem_descriptor { | ||
203 | unsigned int index; /* Index of this memory parameter */ | ||
204 | unsigned int category; /* type indicates cached/non-cached */ | ||
205 | unsigned int num_elements; /* number of elements in this | ||
206 | * descriptor | ||
207 | */ | ||
208 | unsigned int alignment_mask; /* Alignment mask for this block */ | ||
209 | unsigned int size_in_bytes; /* Size required by memory block */ | ||
210 | struct mem_array *mem_array; | ||
211 | }; | ||
212 | |||
213 | struct sgl_handle { | ||
214 | unsigned int sgl_index; | ||
215 | struct iscsi_sge *pfrag; | ||
216 | }; | ||
217 | |||
218 | struct hba_parameters { | ||
219 | unsigned int ios_per_ctrl; | ||
220 | unsigned int cxns_per_ctrl; | ||
221 | unsigned int asyncpdus_per_ctrl; | ||
222 | unsigned int icds_per_ctrl; | ||
223 | unsigned int num_sge_per_io; | ||
224 | unsigned int defpdu_hdr_sz; | ||
225 | unsigned int defpdu_data_sz; | ||
226 | unsigned int num_cq_entries; | ||
227 | unsigned int num_eq_entries; | ||
228 | unsigned int wrbs_per_cxn; | ||
229 | unsigned int crashmode; | ||
230 | unsigned int hba_num; | ||
231 | |||
232 | unsigned int mgmt_ws_sz; | ||
233 | unsigned int hwi_ws_sz; | ||
234 | |||
235 | unsigned int eto; | ||
236 | unsigned int ldto; | ||
237 | |||
238 | unsigned int dbg_flags; | ||
239 | unsigned int num_cxn; | ||
240 | |||
241 | unsigned int eq_timer; | ||
242 | /** | ||
243 | * These are calculated from other params. They're here | ||
244 | * for debug purposes | ||
245 | */ | ||
246 | unsigned int num_mcc_pages; | ||
247 | unsigned int num_mcc_cq_pages; | ||
248 | unsigned int num_cq_pages; | ||
249 | unsigned int num_eq_pages; | ||
250 | |||
251 | unsigned int num_async_pdu_buf_pages; | ||
252 | unsigned int num_async_pdu_buf_sgl_pages; | ||
253 | unsigned int num_async_pdu_buf_cq_pages; | ||
254 | |||
255 | unsigned int num_async_pdu_hdr_pages; | ||
256 | unsigned int num_async_pdu_hdr_sgl_pages; | ||
257 | unsigned int num_async_pdu_hdr_cq_pages; | ||
258 | |||
259 | unsigned int num_sge; | ||
260 | }; | ||
261 | |||
262 | struct beiscsi_hba { | ||
263 | struct hba_parameters params; | ||
264 | struct hwi_controller *phwi_ctrlr; | ||
265 | unsigned int mem_req[SE_MEM_MAX]; | ||
266 | /* PCI BAR mapped addresses */ | ||
267 | u8 __iomem *csr_va; /* CSR */ | ||
268 | u8 __iomem *db_va; /* Door Bell */ | ||
269 | u8 __iomem *pci_va; /* PCI Config */ | ||
270 | struct be_bus_address csr_pa; /* CSR */ | ||
271 | struct be_bus_address db_pa; /* CSR */ | ||
272 | struct be_bus_address pci_pa; /* CSR */ | ||
273 | /* PCI representation of our HBA */ | ||
274 | struct pci_dev *pcidev; | ||
275 | unsigned int state; | ||
276 | unsigned short asic_revision; | ||
277 | struct blk_iopoll iopoll; | ||
278 | struct be_mem_descriptor *init_mem; | ||
279 | |||
280 | unsigned short io_sgl_alloc_index; | ||
281 | unsigned short io_sgl_free_index; | ||
282 | unsigned short io_sgl_hndl_avbl; | ||
283 | struct sgl_handle **io_sgl_hndl_base; | ||
284 | |||
285 | unsigned short eh_sgl_alloc_index; | ||
286 | unsigned short eh_sgl_free_index; | ||
287 | unsigned short eh_sgl_hndl_avbl; | ||
288 | struct sgl_handle **eh_sgl_hndl_base; | ||
289 | spinlock_t io_sgl_lock; | ||
290 | spinlock_t mgmt_sgl_lock; | ||
291 | spinlock_t isr_lock; | ||
292 | unsigned int age; | ||
293 | unsigned short avlbl_cids; | ||
294 | unsigned short cid_alloc; | ||
295 | unsigned short cid_free; | ||
296 | struct beiscsi_conn *conn_table[BE2_MAX_SESSIONS * 2]; | ||
297 | struct list_head hba_queue; | ||
298 | unsigned short *cid_array; | ||
299 | struct iscsi_endpoint **ep_array; | ||
300 | struct Scsi_Host *shost; | ||
301 | struct { | ||
302 | /** | ||
303 | * group together since they are used most frequently | ||
304 | * for cid to cri conversion | ||
305 | */ | ||
306 | unsigned int iscsi_cid_start; | ||
307 | unsigned int phys_port; | ||
308 | |||
309 | unsigned int isr_offset; | ||
310 | unsigned int iscsi_icd_start; | ||
311 | unsigned int iscsi_cid_count; | ||
312 | unsigned int iscsi_icd_count; | ||
313 | unsigned int pci_function; | ||
314 | |||
315 | unsigned short cid_alloc; | ||
316 | unsigned short cid_free; | ||
317 | unsigned short avlbl_cids; | ||
318 | spinlock_t cid_lock; | ||
319 | } fw_config; | ||
320 | |||
321 | u8 mac_address[ETH_ALEN]; | ||
322 | unsigned short todo_cq; | ||
323 | unsigned short todo_mcc_cq; | ||
324 | char wq_name[20]; | ||
325 | struct workqueue_struct *wq; /* The actuak work queue */ | ||
326 | struct work_struct work_cqs; /* The work being queued */ | ||
327 | struct be_ctrl_info ctrl; | ||
328 | }; | ||
329 | |||
330 | struct beiscsi_session { | ||
331 | struct pci_pool *bhs_pool; | ||
332 | }; | ||
333 | |||
334 | /** | ||
335 | * struct beiscsi_conn - iscsi connection structure | ||
336 | */ | ||
337 | struct beiscsi_conn { | ||
338 | struct iscsi_conn *conn; | ||
339 | struct beiscsi_hba *phba; | ||
340 | u32 exp_statsn; | ||
341 | u32 beiscsi_conn_cid; | ||
342 | struct beiscsi_endpoint *ep; | ||
343 | unsigned short login_in_progress; | ||
344 | struct sgl_handle *plogin_sgl_handle; | ||
345 | struct beiscsi_session *beiscsi_sess; | ||
346 | }; | ||
347 | |||
348 | /* This structure is used by the chip */ | ||
349 | struct pdu_data_out { | ||
350 | u32 dw[12]; | ||
351 | }; | ||
352 | /** | ||
353 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
354 | * as a byte: used to calculate offset/shift/mask of each field | ||
355 | */ | ||
356 | struct amap_pdu_data_out { | ||
357 | u8 opcode[6]; /* opcode */ | ||
358 | u8 rsvd0[2]; /* should be 0 */ | ||
359 | u8 rsvd1[7]; | ||
360 | u8 final_bit; /* F bit */ | ||
361 | u8 rsvd2[16]; | ||
362 | u8 ahs_length[8]; /* no AHS */ | ||
363 | u8 data_len_hi[8]; | ||
364 | u8 data_len_lo[16]; /* DataSegmentLength */ | ||
365 | u8 lun[64]; | ||
366 | u8 itt[32]; /* ITT; initiator task tag */ | ||
367 | u8 ttt[32]; /* TTT; valid for R2T or 0xffffffff */ | ||
368 | u8 rsvd3[32]; | ||
369 | u8 exp_stat_sn[32]; | ||
370 | u8 rsvd4[32]; | ||
371 | u8 data_sn[32]; | ||
372 | u8 buffer_offset[32]; | ||
373 | u8 rsvd5[32]; | ||
374 | }; | ||
375 | |||
376 | struct be_cmd_bhs { | ||
377 | struct iscsi_cmd iscsi_hdr; | ||
378 | unsigned char pad1[16]; | ||
379 | struct pdu_data_out iscsi_data_pdu; | ||
380 | unsigned char pad2[BE_SENSE_INFO_SIZE - | ||
381 | sizeof(struct pdu_data_out)]; | ||
382 | }; | ||
383 | |||
384 | struct beiscsi_io_task { | ||
385 | struct wrb_handle *pwrb_handle; | ||
386 | struct sgl_handle *psgl_handle; | ||
387 | struct beiscsi_conn *conn; | ||
388 | struct scsi_cmnd *scsi_cmnd; | ||
389 | unsigned int cmd_sn; | ||
390 | unsigned int flags; | ||
391 | unsigned short cid; | ||
392 | unsigned short header_len; | ||
393 | |||
394 | struct be_cmd_bhs *cmd_bhs; | ||
395 | struct be_bus_address bhs_pa; | ||
396 | unsigned short bhs_len; | ||
397 | }; | ||
398 | |||
399 | struct be_nonio_bhs { | ||
400 | struct iscsi_hdr iscsi_hdr; | ||
401 | unsigned char pad1[16]; | ||
402 | struct pdu_data_out iscsi_data_pdu; | ||
403 | unsigned char pad2[BE_SENSE_INFO_SIZE - | ||
404 | sizeof(struct pdu_data_out)]; | ||
405 | }; | ||
406 | |||
407 | struct be_status_bhs { | ||
408 | struct iscsi_cmd iscsi_hdr; | ||
409 | unsigned char pad1[16]; | ||
410 | /** | ||
411 | * The plus 2 below is to hold the sense info length that gets | ||
412 | * DMA'ed by RxULP | ||
413 | */ | ||
414 | unsigned char sense_info[BE_SENSE_INFO_SIZE]; | ||
415 | }; | ||
416 | |||
417 | struct iscsi_sge { | ||
418 | u32 dw[4]; | ||
419 | }; | ||
420 | |||
421 | /** | ||
422 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
423 | * as a byte: used to calculate offset/shift/mask of each field | ||
424 | */ | ||
425 | struct amap_iscsi_sge { | ||
426 | u8 addr_hi[32]; | ||
427 | u8 addr_lo[32]; | ||
428 | u8 sge_offset[22]; /* DWORD 2 */ | ||
429 | u8 rsvd0[9]; /* DWORD 2 */ | ||
430 | u8 last_sge; /* DWORD 2 */ | ||
431 | u8 len[17]; /* DWORD 3 */ | ||
432 | u8 rsvd1[15]; /* DWORD 3 */ | ||
433 | }; | ||
434 | |||
435 | struct beiscsi_offload_params { | ||
436 | u32 dw[5]; | ||
437 | }; | ||
438 | |||
439 | #define OFFLD_PARAMS_ERL 0x00000003 | ||
440 | #define OFFLD_PARAMS_DDE 0x00000004 | ||
441 | #define OFFLD_PARAMS_HDE 0x00000008 | ||
442 | #define OFFLD_PARAMS_IR2T 0x00000010 | ||
443 | #define OFFLD_PARAMS_IMD 0x00000020 | ||
444 | |||
445 | /** | ||
446 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
447 | * as a byte: used to calculate offset/shift/mask of each field | ||
448 | */ | ||
449 | struct amap_beiscsi_offload_params { | ||
450 | u8 max_burst_length[32]; | ||
451 | u8 max_send_data_segment_length[32]; | ||
452 | u8 first_burst_length[32]; | ||
453 | u8 erl[2]; | ||
454 | u8 dde[1]; | ||
455 | u8 hde[1]; | ||
456 | u8 ir2t[1]; | ||
457 | u8 imd[1]; | ||
458 | u8 pad[26]; | ||
459 | u8 exp_statsn[32]; | ||
460 | }; | ||
461 | |||
462 | /* void hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn, | ||
463 | struct beiscsi_hba *phba, struct sol_cqe *psol);*/ | ||
464 | |||
465 | struct async_pdu_handle { | ||
466 | struct list_head link; | ||
467 | struct be_bus_address pa; | ||
468 | void *pbuffer; | ||
469 | unsigned int consumed; | ||
470 | unsigned char index; | ||
471 | unsigned char is_header; | ||
472 | unsigned short cri; | ||
473 | unsigned long buffer_len; | ||
474 | }; | ||
475 | |||
476 | struct hwi_async_entry { | ||
477 | struct { | ||
478 | unsigned char hdr_received; | ||
479 | unsigned char hdr_len; | ||
480 | unsigned short bytes_received; | ||
481 | unsigned int bytes_needed; | ||
482 | struct list_head list; | ||
483 | } wait_queue; | ||
484 | |||
485 | struct list_head header_busy_list; | ||
486 | struct list_head data_busy_list; | ||
487 | }; | ||
488 | |||
489 | #define BE_MIN_ASYNC_ENTRIES 128 | ||
490 | |||
491 | struct hwi_async_pdu_context { | ||
492 | struct { | ||
493 | struct be_bus_address pa_base; | ||
494 | void *va_base; | ||
495 | void *ring_base; | ||
496 | struct async_pdu_handle *handle_base; | ||
497 | |||
498 | unsigned int host_write_ptr; | ||
499 | unsigned int ep_read_ptr; | ||
500 | unsigned int writables; | ||
501 | |||
502 | unsigned int free_entries; | ||
503 | unsigned int busy_entries; | ||
504 | unsigned int buffer_size; | ||
505 | unsigned int num_entries; | ||
506 | |||
507 | struct list_head free_list; | ||
508 | } async_header; | ||
509 | |||
510 | struct { | ||
511 | struct be_bus_address pa_base; | ||
512 | void *va_base; | ||
513 | void *ring_base; | ||
514 | struct async_pdu_handle *handle_base; | ||
515 | |||
516 | unsigned int host_write_ptr; | ||
517 | unsigned int ep_read_ptr; | ||
518 | unsigned int writables; | ||
519 | |||
520 | unsigned int free_entries; | ||
521 | unsigned int busy_entries; | ||
522 | unsigned int buffer_size; | ||
523 | struct list_head free_list; | ||
524 | unsigned int num_entries; | ||
525 | } async_data; | ||
526 | |||
527 | /** | ||
528 | * This is a varying size list! Do not add anything | ||
529 | * after this entry!! | ||
530 | */ | ||
531 | struct hwi_async_entry async_entry[BE_MIN_ASYNC_ENTRIES]; | ||
532 | }; | ||
533 | |||
534 | #define PDUCQE_CODE_MASK 0x0000003F | ||
535 | #define PDUCQE_DPL_MASK 0xFFFF0000 | ||
536 | #define PDUCQE_INDEX_MASK 0x0000FFFF | ||
537 | |||
538 | struct i_t_dpdu_cqe { | ||
539 | u32 dw[4]; | ||
540 | } __packed; | ||
541 | |||
542 | /** | ||
543 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
544 | * as a byte: used to calculate offset/shift/mask of each field | ||
545 | */ | ||
546 | struct amap_i_t_dpdu_cqe { | ||
547 | u8 db_addr_hi[32]; | ||
548 | u8 db_addr_lo[32]; | ||
549 | u8 code[6]; | ||
550 | u8 cid[10]; | ||
551 | u8 dpl[16]; | ||
552 | u8 index[16]; | ||
553 | u8 num_cons[10]; | ||
554 | u8 rsvd0[4]; | ||
555 | u8 final; | ||
556 | u8 valid; | ||
557 | } __packed; | ||
558 | |||
559 | #define CQE_VALID_MASK 0x80000000 | ||
560 | #define CQE_CODE_MASK 0x0000003F | ||
561 | #define CQE_CID_MASK 0x0000FFC0 | ||
562 | |||
563 | #define EQE_VALID_MASK 0x00000001 | ||
564 | #define EQE_MAJORCODE_MASK 0x0000000E | ||
565 | #define EQE_RESID_MASK 0xFFFF0000 | ||
566 | |||
567 | struct be_eq_entry { | ||
568 | u32 dw[1]; | ||
569 | } __packed; | ||
570 | |||
571 | /** | ||
572 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
573 | * as a byte: used to calculate offset/shift/mask of each field | ||
574 | */ | ||
575 | struct amap_eq_entry { | ||
576 | u8 valid; /* DWORD 0 */ | ||
577 | u8 major_code[3]; /* DWORD 0 */ | ||
578 | u8 minor_code[12]; /* DWORD 0 */ | ||
579 | u8 resource_id[16]; /* DWORD 0 */ | ||
580 | |||
581 | } __packed; | ||
582 | |||
583 | struct cq_db { | ||
584 | u32 dw[1]; | ||
585 | } __packed; | ||
586 | |||
587 | /** | ||
588 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
589 | * as a byte: used to calculate offset/shift/mask of each field | ||
590 | */ | ||
591 | struct amap_cq_db { | ||
592 | u8 qid[10]; | ||
593 | u8 event[1]; | ||
594 | u8 rsvd0[5]; | ||
595 | u8 num_popped[13]; | ||
596 | u8 rearm[1]; | ||
597 | u8 rsvd1[2]; | ||
598 | } __packed; | ||
599 | |||
600 | void beiscsi_process_eq(struct beiscsi_hba *phba); | ||
601 | |||
602 | |||
603 | struct iscsi_wrb { | ||
604 | u32 dw[16]; | ||
605 | } __packed; | ||
606 | |||
607 | #define WRB_TYPE_MASK 0xF0000000 | ||
608 | |||
609 | /** | ||
610 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
611 | * as a byte: used to calculate offset/shift/mask of each field | ||
612 | */ | ||
613 | struct amap_iscsi_wrb { | ||
614 | u8 lun[14]; /* DWORD 0 */ | ||
615 | u8 lt; /* DWORD 0 */ | ||
616 | u8 invld; /* DWORD 0 */ | ||
617 | u8 wrb_idx[8]; /* DWORD 0 */ | ||
618 | u8 dsp; /* DWORD 0 */ | ||
619 | u8 dmsg; /* DWORD 0 */ | ||
620 | u8 undr_run; /* DWORD 0 */ | ||
621 | u8 over_run; /* DWORD 0 */ | ||
622 | u8 type[4]; /* DWORD 0 */ | ||
623 | u8 ptr2nextwrb[8]; /* DWORD 1 */ | ||
624 | u8 r2t_exp_dtl[24]; /* DWORD 1 */ | ||
625 | u8 sgl_icd_idx[12]; /* DWORD 2 */ | ||
626 | u8 rsvd0[20]; /* DWORD 2 */ | ||
627 | u8 exp_data_sn[32]; /* DWORD 3 */ | ||
628 | u8 iscsi_bhs_addr_hi[32]; /* DWORD 4 */ | ||
629 | u8 iscsi_bhs_addr_lo[32]; /* DWORD 5 */ | ||
630 | u8 cmdsn_itt[32]; /* DWORD 6 */ | ||
631 | u8 dif_ref_tag[32]; /* DWORD 7 */ | ||
632 | u8 sge0_addr_hi[32]; /* DWORD 8 */ | ||
633 | u8 sge0_addr_lo[32]; /* DWORD 9 */ | ||
634 | u8 sge0_offset[22]; /* DWORD 10 */ | ||
635 | u8 pbs; /* DWORD 10 */ | ||
636 | u8 dif_mode[2]; /* DWORD 10 */ | ||
637 | u8 rsvd1[6]; /* DWORD 10 */ | ||
638 | u8 sge0_last; /* DWORD 10 */ | ||
639 | u8 sge0_len[17]; /* DWORD 11 */ | ||
640 | u8 dif_meta_tag[14]; /* DWORD 11 */ | ||
641 | u8 sge0_in_ddr; /* DWORD 11 */ | ||
642 | u8 sge1_addr_hi[32]; /* DWORD 12 */ | ||
643 | u8 sge1_addr_lo[32]; /* DWORD 13 */ | ||
644 | u8 sge1_r2t_offset[22]; /* DWORD 14 */ | ||
645 | u8 rsvd2[9]; /* DWORD 14 */ | ||
646 | u8 sge1_last; /* DWORD 14 */ | ||
647 | u8 sge1_len[17]; /* DWORD 15 */ | ||
648 | u8 ref_sgl_icd_idx[12]; /* DWORD 15 */ | ||
649 | u8 rsvd3[2]; /* DWORD 15 */ | ||
650 | u8 sge1_in_ddr; /* DWORD 15 */ | ||
651 | |||
652 | } __packed; | ||
653 | |||
654 | struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid, | ||
655 | int index); | ||
656 | void | ||
657 | free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle); | ||
658 | |||
659 | struct pdu_nop_out { | ||
660 | u32 dw[12]; | ||
661 | }; | ||
662 | |||
663 | /** | ||
664 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
665 | * as a byte: used to calculate offset/shift/mask of each field | ||
666 | */ | ||
667 | struct amap_pdu_nop_out { | ||
668 | u8 opcode[6]; /* opcode 0x00 */ | ||
669 | u8 i_bit; /* I Bit */ | ||
670 | u8 x_bit; /* reserved; should be 0 */ | ||
671 | u8 fp_bit_filler1[7]; | ||
672 | u8 f_bit; /* always 1 */ | ||
673 | u8 reserved1[16]; | ||
674 | u8 ahs_length[8]; /* no AHS */ | ||
675 | u8 data_len_hi[8]; | ||
676 | u8 data_len_lo[16]; /* DataSegmentLength */ | ||
677 | u8 lun[64]; | ||
678 | u8 itt[32]; /* initiator id for ping or 0xffffffff */ | ||
679 | u8 ttt[32]; /* target id for ping or 0xffffffff */ | ||
680 | u8 cmd_sn[32]; | ||
681 | u8 exp_stat_sn[32]; | ||
682 | u8 reserved5[128]; | ||
683 | }; | ||
684 | |||
685 | #define PDUBASE_OPCODE_MASK 0x0000003F | ||
686 | #define PDUBASE_DATALENHI_MASK 0x0000FF00 | ||
687 | #define PDUBASE_DATALENLO_MASK 0xFFFF0000 | ||
688 | |||
689 | struct pdu_base { | ||
690 | u32 dw[16]; | ||
691 | } __packed; | ||
692 | |||
693 | /** | ||
694 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
695 | * as a byte: used to calculate offset/shift/mask of each field | ||
696 | */ | ||
697 | struct amap_pdu_base { | ||
698 | u8 opcode[6]; | ||
699 | u8 i_bit; /* immediate bit */ | ||
700 | u8 x_bit; /* reserved, always 0 */ | ||
701 | u8 reserved1[24]; /* opcode-specific fields */ | ||
702 | u8 ahs_length[8]; /* length units is 4 byte words */ | ||
703 | u8 data_len_hi[8]; | ||
704 | u8 data_len_lo[16]; /* DatasegmentLength */ | ||
705 | u8 lun[64]; /* lun or opcode-specific fields */ | ||
706 | u8 itt[32]; /* initiator task tag */ | ||
707 | u8 reserved4[224]; | ||
708 | }; | ||
709 | |||
710 | struct iscsi_target_context_update_wrb { | ||
711 | u32 dw[16]; | ||
712 | } __packed; | ||
713 | |||
714 | /** | ||
715 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
716 | * as a byte: used to calculate offset/shift/mask of each field | ||
717 | */ | ||
718 | struct amap_iscsi_target_context_update_wrb { | ||
719 | u8 lun[14]; /* DWORD 0 */ | ||
720 | u8 lt; /* DWORD 0 */ | ||
721 | u8 invld; /* DWORD 0 */ | ||
722 | u8 wrb_idx[8]; /* DWORD 0 */ | ||
723 | u8 dsp; /* DWORD 0 */ | ||
724 | u8 dmsg; /* DWORD 0 */ | ||
725 | u8 undr_run; /* DWORD 0 */ | ||
726 | u8 over_run; /* DWORD 0 */ | ||
727 | u8 type[4]; /* DWORD 0 */ | ||
728 | u8 ptr2nextwrb[8]; /* DWORD 1 */ | ||
729 | u8 max_burst_length[19]; /* DWORD 1 */ | ||
730 | u8 rsvd0[5]; /* DWORD 1 */ | ||
731 | u8 rsvd1[15]; /* DWORD 2 */ | ||
732 | u8 max_send_data_segment_length[17]; /* DWORD 2 */ | ||
733 | u8 first_burst_length[14]; /* DWORD 3 */ | ||
734 | u8 rsvd2[2]; /* DWORD 3 */ | ||
735 | u8 tx_wrbindex_drv_msg[8]; /* DWORD 3 */ | ||
736 | u8 rsvd3[5]; /* DWORD 3 */ | ||
737 | u8 session_state[3]; /* DWORD 3 */ | ||
738 | u8 rsvd4[16]; /* DWORD 4 */ | ||
739 | u8 tx_jumbo; /* DWORD 4 */ | ||
740 | u8 hde; /* DWORD 4 */ | ||
741 | u8 dde; /* DWORD 4 */ | ||
742 | u8 erl[2]; /* DWORD 4 */ | ||
743 | u8 domain_id[5]; /* DWORD 4 */ | ||
744 | u8 mode; /* DWORD 4 */ | ||
745 | u8 imd; /* DWORD 4 */ | ||
746 | u8 ir2t; /* DWORD 4 */ | ||
747 | u8 notpredblq[2]; /* DWORD 4 */ | ||
748 | u8 compltonack; /* DWORD 4 */ | ||
749 | u8 stat_sn[32]; /* DWORD 5 */ | ||
750 | u8 pad_buffer_addr_hi[32]; /* DWORD 6 */ | ||
751 | u8 pad_buffer_addr_lo[32]; /* DWORD 7 */ | ||
752 | u8 pad_addr_hi[32]; /* DWORD 8 */ | ||
753 | u8 pad_addr_lo[32]; /* DWORD 9 */ | ||
754 | u8 rsvd5[32]; /* DWORD 10 */ | ||
755 | u8 rsvd6[32]; /* DWORD 11 */ | ||
756 | u8 rsvd7[32]; /* DWORD 12 */ | ||
757 | u8 rsvd8[32]; /* DWORD 13 */ | ||
758 | u8 rsvd9[32]; /* DWORD 14 */ | ||
759 | u8 rsvd10[32]; /* DWORD 15 */ | ||
760 | |||
761 | } __packed; | ||
762 | |||
763 | struct be_ring { | ||
764 | u32 pages; /* queue size in pages */ | ||
765 | u32 id; /* queue id assigned by beklib */ | ||
766 | u32 num; /* number of elements in queue */ | ||
767 | u32 cidx; /* consumer index */ | ||
768 | u32 pidx; /* producer index -- not used by most rings */ | ||
769 | u32 item_size; /* size in bytes of one object */ | ||
770 | |||
771 | void *va; /* The virtual address of the ring. This | ||
772 | * should be last to allow 32 & 64 bit debugger | ||
773 | * extensions to work. | ||
774 | */ | ||
775 | }; | ||
776 | |||
777 | struct hwi_wrb_context { | ||
778 | struct list_head wrb_handle_list; | ||
779 | struct list_head wrb_handle_drvr_list; | ||
780 | struct wrb_handle **pwrb_handle_base; | ||
781 | struct wrb_handle **pwrb_handle_basestd; | ||
782 | struct iscsi_wrb *plast_wrb; | ||
783 | unsigned short alloc_index; | ||
784 | unsigned short free_index; | ||
785 | unsigned short wrb_handles_available; | ||
786 | unsigned short cid; | ||
787 | }; | ||
788 | |||
789 | struct hwi_controller { | ||
790 | struct list_head io_sgl_list; | ||
791 | struct list_head eh_sgl_list; | ||
792 | struct sgl_handle *psgl_handle_base; | ||
793 | unsigned int wrb_mem_index; | ||
794 | |||
795 | struct hwi_wrb_context wrb_context[BE2_MAX_SESSIONS * 2]; | ||
796 | struct mcc_wrb *pmcc_wrb_base; | ||
797 | struct be_ring default_pdu_hdr; | ||
798 | struct be_ring default_pdu_data; | ||
799 | struct hwi_context_memory *phwi_ctxt; | ||
800 | unsigned short cq_errors[CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN]; | ||
801 | }; | ||
802 | |||
803 | enum hwh_type_enum { | ||
804 | HWH_TYPE_IO = 1, | ||
805 | HWH_TYPE_LOGOUT = 2, | ||
806 | HWH_TYPE_TMF = 3, | ||
807 | HWH_TYPE_NOP = 4, | ||
808 | HWH_TYPE_IO_RD = 5, | ||
809 | HWH_TYPE_LOGIN = 11, | ||
810 | HWH_TYPE_INVALID = 0xFFFFFFFF | ||
811 | }; | ||
812 | |||
813 | struct wrb_handle { | ||
814 | enum hwh_type_enum type; | ||
815 | unsigned short wrb_index; | ||
816 | unsigned short nxt_wrb_index; | ||
817 | |||
818 | struct iscsi_task *pio_handle; | ||
819 | struct iscsi_wrb *pwrb; | ||
820 | }; | ||
821 | |||
822 | struct hwi_context_memory { | ||
823 | struct be_eq_obj be_eq; | ||
824 | struct be_queue_info be_cq; | ||
825 | struct be_queue_info be_mcc_cq; | ||
826 | struct be_queue_info be_mcc; | ||
827 | |||
828 | struct be_queue_info be_def_hdrq; | ||
829 | struct be_queue_info be_def_dataq; | ||
830 | |||
831 | struct be_queue_info be_wrbq[BE2_MAX_SESSIONS]; | ||
832 | struct be_mcc_wrb_context *pbe_mcc_context; | ||
833 | |||
834 | struct hwi_async_pdu_context *pasync_ctx; | ||
835 | }; | ||
836 | |||
837 | #endif | ||
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c new file mode 100644 index 000000000000..12e644fc746e --- /dev/null +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -0,0 +1,321 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Written by: Jayamohan Kallickal (jayamohank@serverengines.com) | ||
11 | * | ||
12 | * Contact Information: | ||
13 | * linux-drivers@serverengines.com | ||
14 | * | ||
15 | * ServerEngines | ||
16 | * 209 N. Fair Oaks Ave | ||
17 | * Sunnyvale, CA 94085 | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include "be_mgmt.h" | ||
22 | #include "be_iscsi.h" | ||
23 | |||
24 | unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, | ||
25 | struct beiscsi_hba *phba) | ||
26 | { | ||
27 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
28 | struct be_fw_cfg *req = embedded_payload(wrb); | ||
29 | int status = 0; | ||
30 | |||
31 | spin_lock(&ctrl->mbox_lock); | ||
32 | memset(wrb, 0, sizeof(*wrb)); | ||
33 | |||
34 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
35 | |||
36 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
37 | OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); | ||
38 | |||
39 | status = be_mbox_notify(ctrl); | ||
40 | if (!status) { | ||
41 | struct be_fw_cfg *pfw_cfg; | ||
42 | pfw_cfg = req; | ||
43 | phba->fw_config.phys_port = pfw_cfg->phys_port; | ||
44 | phba->fw_config.iscsi_icd_start = | ||
45 | pfw_cfg->ulp[0].icd_base; | ||
46 | phba->fw_config.iscsi_icd_count = | ||
47 | pfw_cfg->ulp[0].icd_count; | ||
48 | phba->fw_config.iscsi_cid_start = | ||
49 | pfw_cfg->ulp[0].sq_base; | ||
50 | phba->fw_config.iscsi_cid_count = | ||
51 | pfw_cfg->ulp[0].sq_count; | ||
52 | } else { | ||
53 | shost_printk(KERN_WARNING, phba->shost, | ||
54 | "Failed in mgmt_get_fw_config \n"); | ||
55 | } | ||
56 | |||
57 | spin_unlock(&ctrl->mbox_lock); | ||
58 | return status; | ||
59 | } | ||
60 | |||
61 | unsigned char mgmt_check_supported_fw(struct be_ctrl_info *ctrl) | ||
62 | { | ||
63 | struct be_dma_mem nonemb_cmd; | ||
64 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
65 | struct be_mgmt_controller_attributes *req; | ||
66 | struct be_sge *sge = nonembedded_sgl(wrb); | ||
67 | int status = 0; | ||
68 | |||
69 | nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, | ||
70 | sizeof(struct be_mgmt_controller_attributes), | ||
71 | &nonemb_cmd.dma); | ||
72 | if (nonemb_cmd.va == NULL) { | ||
73 | SE_DEBUG(DBG_LVL_1, | ||
74 | "Failed to allocate memory for mgmt_check_supported_fw" | ||
75 | "\n"); | ||
76 | return -1; | ||
77 | } | ||
78 | nonemb_cmd.size = sizeof(struct be_mgmt_controller_attributes); | ||
79 | req = nonemb_cmd.va; | ||
80 | spin_lock(&ctrl->mbox_lock); | ||
81 | memset(wrb, 0, sizeof(*wrb)); | ||
82 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
83 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | ||
84 | OPCODE_COMMON_GET_CNTL_ATTRIBUTES, sizeof(*req)); | ||
85 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | ||
86 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); | ||
87 | sge->len = cpu_to_le32(nonemb_cmd.size); | ||
88 | |||
89 | status = be_mbox_notify(ctrl); | ||
90 | if (!status) { | ||
91 | struct be_mgmt_controller_attributes_resp *resp = nonemb_cmd.va; | ||
92 | SE_DEBUG(DBG_LVL_8, "Firmware version of CMD: %s\n", | ||
93 | resp->params.hba_attribs.flashrom_version_string); | ||
94 | SE_DEBUG(DBG_LVL_8, "Firmware version is : %s\n", | ||
95 | resp->params.hba_attribs.firmware_version_string); | ||
96 | SE_DEBUG(DBG_LVL_8, | ||
97 | "Developer Build, not performing version check...\n"); | ||
98 | |||
99 | } else | ||
100 | SE_DEBUG(DBG_LVL_1, " Failed in mgmt_check_supported_fw\n"); | ||
101 | if (nonemb_cmd.va) | ||
102 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, | ||
103 | nonemb_cmd.va, nonemb_cmd.dma); | ||
104 | |||
105 | spin_unlock(&ctrl->mbox_lock); | ||
106 | return status; | ||
107 | } | ||
108 | |||
109 | unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute) | ||
110 | { | ||
111 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
112 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
113 | struct iscsi_cleanup_req *req = embedded_payload(wrb); | ||
114 | int status = 0; | ||
115 | |||
116 | spin_lock(&ctrl->mbox_lock); | ||
117 | memset(wrb, 0, sizeof(*wrb)); | ||
118 | |||
119 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
120 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
121 | OPCODE_COMMON_ISCSI_CLEANUP, sizeof(*req)); | ||
122 | |||
123 | req->chute = chute; | ||
124 | req->hdr_ring_id = 0; | ||
125 | req->data_ring_id = 0; | ||
126 | |||
127 | status = be_mbox_notify(ctrl); | ||
128 | if (status) | ||
129 | shost_printk(KERN_WARNING, phba->shost, | ||
130 | " mgmt_epfw_cleanup , FAILED\n"); | ||
131 | spin_unlock(&ctrl->mbox_lock); | ||
132 | return status; | ||
133 | } | ||
134 | |||
135 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | ||
136 | unsigned int icd, unsigned int cid) | ||
137 | { | ||
138 | struct be_dma_mem nonemb_cmd; | ||
139 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
140 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
141 | struct be_sge *sge = nonembedded_sgl(wrb); | ||
142 | struct invalidate_commands_params_in *req; | ||
143 | int status = 0; | ||
144 | |||
145 | nonemb_cmd.va = pci_alloc_consistent(ctrl->pdev, | ||
146 | sizeof(struct invalidate_commands_params_in), | ||
147 | &nonemb_cmd.dma); | ||
148 | if (nonemb_cmd.va == NULL) { | ||
149 | SE_DEBUG(DBG_LVL_1, | ||
150 | "Failed to allocate memory for" | ||
151 | "mgmt_invalidate_icds \n"); | ||
152 | return -1; | ||
153 | } | ||
154 | nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); | ||
155 | req = nonemb_cmd.va; | ||
156 | spin_lock(&ctrl->mbox_lock); | ||
157 | memset(wrb, 0, sizeof(*wrb)); | ||
158 | |||
159 | be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); | ||
160 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
161 | OPCODE_COMMON_ISCSI_ERROR_RECOVERY_INVALIDATE_COMMANDS, | ||
162 | sizeof(*req)); | ||
163 | req->ref_handle = 0; | ||
164 | req->cleanup_type = CMD_ISCSI_COMMAND_INVALIDATE; | ||
165 | req->icd_count = 0; | ||
166 | req->table[req->icd_count].icd = icd; | ||
167 | req->table[req->icd_count].cid = cid; | ||
168 | sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd.dma)); | ||
169 | sge->pa_lo = cpu_to_le32(nonemb_cmd.dma & 0xFFFFFFFF); | ||
170 | sge->len = cpu_to_le32(nonemb_cmd.size); | ||
171 | |||
172 | status = be_mbox_notify(ctrl); | ||
173 | if (status) | ||
174 | SE_DEBUG(DBG_LVL_1, "ICDS Invalidation Failed\n"); | ||
175 | spin_unlock(&ctrl->mbox_lock); | ||
176 | if (nonemb_cmd.va) | ||
177 | pci_free_consistent(ctrl->pdev, nonemb_cmd.size, | ||
178 | nonemb_cmd.va, nonemb_cmd.dma); | ||
179 | return status; | ||
180 | } | ||
181 | |||
182 | unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, | ||
183 | struct beiscsi_endpoint *beiscsi_ep, | ||
184 | unsigned short cid, | ||
185 | unsigned short issue_reset, | ||
186 | unsigned short savecfg_flag) | ||
187 | { | ||
188 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
189 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
190 | struct iscsi_invalidate_connection_params_in *req = | ||
191 | embedded_payload(wrb); | ||
192 | int status = 0; | ||
193 | |||
194 | spin_lock(&ctrl->mbox_lock); | ||
195 | memset(wrb, 0, sizeof(*wrb)); | ||
196 | |||
197 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
198 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI_INI, | ||
199 | OPCODE_ISCSI_INI_DRIVER_INVALIDATE_CONNECTION, | ||
200 | sizeof(*req)); | ||
201 | req->session_handle = beiscsi_ep->fw_handle; | ||
202 | req->cid = cid; | ||
203 | if (issue_reset) | ||
204 | req->cleanup_type = CMD_ISCSI_CONNECTION_ISSUE_TCP_RST; | ||
205 | else | ||
206 | req->cleanup_type = CMD_ISCSI_CONNECTION_INVALIDATE; | ||
207 | req->save_cfg = savecfg_flag; | ||
208 | status = be_mbox_notify(ctrl); | ||
209 | if (status) | ||
210 | SE_DEBUG(DBG_LVL_1, "Invalidation Failed\n"); | ||
211 | |||
212 | spin_unlock(&ctrl->mbox_lock); | ||
213 | return status; | ||
214 | } | ||
215 | |||
216 | unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, | ||
217 | unsigned short cid, unsigned int upload_flag) | ||
218 | { | ||
219 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
220 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
221 | struct tcp_upload_params_in *req = embedded_payload(wrb); | ||
222 | int status = 0; | ||
223 | |||
224 | spin_lock(&ctrl->mbox_lock); | ||
225 | memset(wrb, 0, sizeof(*wrb)); | ||
226 | |||
227 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
228 | be_cmd_hdr_prepare(&req->hdr, CMD_COMMON_TCP_UPLOAD, | ||
229 | OPCODE_COMMON_TCP_UPLOAD, sizeof(*req)); | ||
230 | req->id = (unsigned short)cid; | ||
231 | req->upload_type = (unsigned char)upload_flag; | ||
232 | status = be_mbox_notify(ctrl); | ||
233 | if (status) | ||
234 | SE_DEBUG(DBG_LVL_1, "mgmt_upload_connection Failed\n"); | ||
235 | spin_unlock(&ctrl->mbox_lock); | ||
236 | return status; | ||
237 | } | ||
238 | |||
239 | int mgmt_open_connection(struct beiscsi_hba *phba, | ||
240 | struct sockaddr *dst_addr, | ||
241 | struct beiscsi_endpoint *beiscsi_ep) | ||
242 | { | ||
243 | struct hwi_controller *phwi_ctrlr; | ||
244 | struct hwi_context_memory *phwi_context; | ||
245 | struct sockaddr_in *daddr_in = (struct sockaddr_in *)dst_addr; | ||
246 | struct sockaddr_in6 *daddr_in6 = (struct sockaddr_in6 *)dst_addr; | ||
247 | struct be_ctrl_info *ctrl = &phba->ctrl; | ||
248 | struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); | ||
249 | struct tcp_connect_and_offload_in *req = embedded_payload(wrb); | ||
250 | unsigned short def_hdr_id; | ||
251 | unsigned short def_data_id; | ||
252 | struct phys_addr template_address = { 0, 0 }; | ||
253 | struct phys_addr *ptemplate_address; | ||
254 | int status = 0; | ||
255 | unsigned short cid = beiscsi_ep->ep_cid; | ||
256 | |||
257 | phwi_ctrlr = phba->phwi_ctrlr; | ||
258 | phwi_context = phwi_ctrlr->phwi_ctxt; | ||
259 | def_hdr_id = (unsigned short)HWI_GET_DEF_HDRQ_ID(phba); | ||
260 | def_data_id = (unsigned short)HWI_GET_DEF_BUFQ_ID(phba); | ||
261 | |||
262 | ptemplate_address = &template_address; | ||
263 | ISCSI_GET_PDU_TEMPLATE_ADDRESS(phba, ptemplate_address); | ||
264 | spin_lock(&ctrl->mbox_lock); | ||
265 | memset(wrb, 0, sizeof(*wrb)); | ||
266 | |||
267 | be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); | ||
268 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ISCSI, | ||
269 | OPCODE_COMMON_ISCSI_TCP_CONNECT_AND_OFFLOAD, | ||
270 | sizeof(*req)); | ||
271 | if (dst_addr->sa_family == PF_INET) { | ||
272 | __be32 s_addr = daddr_in->sin_addr.s_addr; | ||
273 | req->ip_address.ip_type = BE2_IPV4; | ||
274 | req->ip_address.ip_address[0] = s_addr & 0x000000ff; | ||
275 | req->ip_address.ip_address[1] = (s_addr & 0x0000ff00) >> 8; | ||
276 | req->ip_address.ip_address[2] = (s_addr & 0x00ff0000) >> 16; | ||
277 | req->ip_address.ip_address[3] = (s_addr & 0xff000000) >> 24; | ||
278 | req->tcp_port = ntohs(daddr_in->sin_port); | ||
279 | beiscsi_ep->dst_addr = daddr_in->sin_addr.s_addr; | ||
280 | beiscsi_ep->dst_tcpport = ntohs(daddr_in->sin_port); | ||
281 | beiscsi_ep->ip_type = BE2_IPV4; | ||
282 | } else if (dst_addr->sa_family == PF_INET6) { | ||
283 | req->ip_address.ip_type = BE2_IPV6; | ||
284 | memcpy(&req->ip_address.ip_address, | ||
285 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); | ||
286 | req->tcp_port = ntohs(daddr_in6->sin6_port); | ||
287 | beiscsi_ep->dst_tcpport = ntohs(daddr_in6->sin6_port); | ||
288 | memcpy(&beiscsi_ep->dst6_addr, | ||
289 | &daddr_in6->sin6_addr.in6_u.u6_addr8, 16); | ||
290 | beiscsi_ep->ip_type = BE2_IPV6; | ||
291 | } else{ | ||
292 | shost_printk(KERN_ERR, phba->shost, "unknown addr family %d\n", | ||
293 | dst_addr->sa_family); | ||
294 | spin_unlock(&ctrl->mbox_lock); | ||
295 | return -EINVAL; | ||
296 | |||
297 | } | ||
298 | req->cid = cid; | ||
299 | req->cq_id = phwi_context->be_cq.id; | ||
300 | req->defq_id = def_hdr_id; | ||
301 | req->hdr_ring_id = def_hdr_id; | ||
302 | req->data_ring_id = def_data_id; | ||
303 | req->do_offload = 1; | ||
304 | req->dataout_template_pa.lo = ptemplate_address->lo; | ||
305 | req->dataout_template_pa.hi = ptemplate_address->hi; | ||
306 | status = be_mbox_notify(ctrl); | ||
307 | if (!status) { | ||
308 | struct iscsi_endpoint *ep; | ||
309 | struct tcp_connect_and_offload_out *ptcpcnct_out = | ||
310 | embedded_payload(wrb); | ||
311 | |||
312 | ep = phba->ep_array[ptcpcnct_out->cid]; | ||
313 | beiscsi_ep = ep->dd_data; | ||
314 | beiscsi_ep->fw_handle = 0; | ||
315 | beiscsi_ep->cid_vld = 1; | ||
316 | SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n"); | ||
317 | } else | ||
318 | SE_DEBUG(DBG_LVL_1, "mgmt_open_connection Failed\n"); | ||
319 | spin_unlock(&ctrl->mbox_lock); | ||
320 | return status; | ||
321 | } | ||
diff --git a/drivers/scsi/be2iscsi/be_mgmt.h b/drivers/scsi/be2iscsi/be_mgmt.h new file mode 100644 index 000000000000..00e816ee8070 --- /dev/null +++ b/drivers/scsi/be2iscsi/be_mgmt.h | |||
@@ -0,0 +1,249 @@ | |||
1 | /** | ||
2 | * Copyright (C) 2005 - 2009 ServerEngines | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License version 2 | ||
7 | * as published by the Free Software Foundation. The full GNU General | ||
8 | * Public License is included in this distribution in the file called COPYING. | ||
9 | * | ||
10 | * Written by: Jayamohan Kallickal (jayamohank@serverengines.com) | ||
11 | * | ||
12 | * Contact Information: | ||
13 | * linux-drivers@serverengines.com | ||
14 | * | ||
15 | * ServerEngines | ||
16 | * 209 N. Fair Oaks Ave | ||
17 | * Sunnyvale, CA 94085 | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #ifndef _BEISCSI_MGMT_ | ||
22 | #define _BEISCSI_MGMT_ | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | #include <linux/list.h> | ||
26 | #include "be_iscsi.h" | ||
27 | #include "be_main.h" | ||
28 | |||
29 | /** | ||
30 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
31 | * as a byte: used to calculate offset/shift/mask of each field | ||
32 | */ | ||
33 | struct amap_mcc_sge { | ||
34 | u8 pa_lo[32]; /* dword 0 */ | ||
35 | u8 pa_hi[32]; /* dword 1 */ | ||
36 | u8 length[32]; /* DWORD 2 */ | ||
37 | } __packed; | ||
38 | |||
39 | /** | ||
40 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
41 | * as a byte: used to calculate offset/shift/mask of each field | ||
42 | */ | ||
43 | struct amap_mcc_wrb_payload { | ||
44 | union { | ||
45 | struct amap_mcc_sge sgl[19]; | ||
46 | u8 embedded[59 * 32]; /* DWORDS 57 to 115 */ | ||
47 | } u; | ||
48 | } __packed; | ||
49 | |||
50 | /** | ||
51 | * Pseudo amap definition in which each bit of the actual structure is defined | ||
52 | * as a byte: used to calculate offset/shift/mask of each field | ||
53 | */ | ||
54 | struct amap_mcc_wrb { | ||
55 | u8 embedded; /* DWORD 0 */ | ||
56 | u8 rsvd0[2]; /* DWORD 0 */ | ||
57 | u8 sge_count[5]; /* DWORD 0 */ | ||
58 | u8 rsvd1[16]; /* DWORD 0 */ | ||
59 | u8 special[8]; /* DWORD 0 */ | ||
60 | u8 payload_length[32]; | ||
61 | u8 tag[64]; /* DWORD 2 */ | ||
62 | u8 rsvd2[32]; /* DWORD 4 */ | ||
63 | struct amap_mcc_wrb_payload payload; | ||
64 | }; | ||
65 | |||
66 | struct mcc_sge { | ||
67 | u32 pa_lo; /* dword 0 */ | ||
68 | u32 pa_hi; /* dword 1 */ | ||
69 | u32 length; /* DWORD 2 */ | ||
70 | } __packed; | ||
71 | |||
72 | struct mcc_wrb_payload { | ||
73 | union { | ||
74 | struct mcc_sge sgl[19]; | ||
75 | u32 embedded[59]; /* DWORDS 57 to 115 */ | ||
76 | } u; | ||
77 | } __packed; | ||
78 | |||
79 | #define MCC_WRB_EMBEDDED_MASK 0x00000001 | ||
80 | |||
81 | struct mcc_wrb { | ||
82 | u32 dw[0]; /* DWORD 0 */ | ||
83 | u32 payload_length; | ||
84 | u32 tag[2]; /* DWORD 2 */ | ||
85 | u32 rsvd2[1]; /* DWORD 4 */ | ||
86 | struct mcc_wrb_payload payload; | ||
87 | }; | ||
88 | |||
89 | unsigned char mgmt_epfw_cleanup(struct beiscsi_hba *phba, unsigned short chute); | ||
90 | int mgmt_open_connection(struct beiscsi_hba *phba, struct sockaddr *dst_addr, | ||
91 | struct beiscsi_endpoint *beiscsi_ep); | ||
92 | |||
93 | unsigned char mgmt_upload_connection(struct beiscsi_hba *phba, | ||
94 | unsigned short cid, | ||
95 | unsigned int upload_flag); | ||
96 | unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | ||
97 | unsigned int icd, unsigned int cid); | ||
98 | |||
99 | struct iscsi_invalidate_connection_params_in { | ||
100 | struct be_cmd_req_hdr hdr; | ||
101 | unsigned int session_handle; | ||
102 | unsigned short cid; | ||
103 | unsigned short unused; | ||
104 | unsigned short cleanup_type; | ||
105 | unsigned short save_cfg; | ||
106 | } __packed; | ||
107 | |||
108 | struct iscsi_invalidate_connection_params_out { | ||
109 | unsigned int session_handle; | ||
110 | unsigned short cid; | ||
111 | unsigned short unused; | ||
112 | } __packed; | ||
113 | |||
114 | union iscsi_invalidate_connection_params { | ||
115 | struct iscsi_invalidate_connection_params_in request; | ||
116 | struct iscsi_invalidate_connection_params_out response; | ||
117 | } __packed; | ||
118 | |||
119 | struct invalidate_command_table { | ||
120 | unsigned short icd; | ||
121 | unsigned short cid; | ||
122 | } __packed; | ||
123 | |||
124 | struct invalidate_commands_params_in { | ||
125 | struct be_cmd_req_hdr hdr; | ||
126 | unsigned int ref_handle; | ||
127 | unsigned int icd_count; | ||
128 | struct invalidate_command_table table[128]; | ||
129 | unsigned short cleanup_type; | ||
130 | unsigned short unused; | ||
131 | } __packed; | ||
132 | |||
133 | struct invalidate_commands_params_out { | ||
134 | unsigned int ref_handle; | ||
135 | unsigned int icd_count; | ||
136 | unsigned int icd_status[128]; | ||
137 | } __packed; | ||
138 | |||
139 | union invalidate_commands_params { | ||
140 | struct invalidate_commands_params_in request; | ||
141 | struct invalidate_commands_params_out response; | ||
142 | } __packed; | ||
143 | |||
144 | struct mgmt_hba_attributes { | ||
145 | u8 flashrom_version_string[32]; | ||
146 | u8 manufacturer_name[32]; | ||
147 | u32 supported_modes; | ||
148 | u8 seeprom_version_lo; | ||
149 | u8 seeprom_version_hi; | ||
150 | u8 rsvd0[2]; | ||
151 | u32 fw_cmd_data_struct_version; | ||
152 | u32 ep_fw_data_struct_version; | ||
153 | u32 future_reserved[12]; | ||
154 | u32 default_extended_timeout; | ||
155 | u8 controller_model_number[32]; | ||
156 | u8 controller_description[64]; | ||
157 | u8 controller_serial_number[32]; | ||
158 | u8 ip_version_string[32]; | ||
159 | u8 firmware_version_string[32]; | ||
160 | u8 bios_version_string[32]; | ||
161 | u8 redboot_version_string[32]; | ||
162 | u8 driver_version_string[32]; | ||
163 | u8 fw_on_flash_version_string[32]; | ||
164 | u32 functionalities_supported; | ||
165 | u16 max_cdblength; | ||
166 | u8 asic_revision; | ||
167 | u8 generational_guid[16]; | ||
168 | u8 hba_port_count; | ||
169 | u16 default_link_down_timeout; | ||
170 | u8 iscsi_ver_min_max; | ||
171 | u8 multifunction_device; | ||
172 | u8 cache_valid; | ||
173 | u8 hba_status; | ||
174 | u8 max_domains_supported; | ||
175 | u8 phy_port; | ||
176 | u32 firmware_post_status; | ||
177 | u32 hba_mtu[8]; | ||
178 | u32 future_u32[4]; | ||
179 | } __packed; | ||
180 | |||
181 | struct mgmt_controller_attributes { | ||
182 | struct mgmt_hba_attributes hba_attribs; | ||
183 | u16 pci_vendor_id; | ||
184 | u16 pci_device_id; | ||
185 | u16 pci_sub_vendor_id; | ||
186 | u16 pci_sub_system_id; | ||
187 | u8 pci_bus_number; | ||
188 | u8 pci_device_number; | ||
189 | u8 pci_function_number; | ||
190 | u8 interface_type; | ||
191 | u64 unique_identifier; | ||
192 | u8 netfilters; | ||
193 | u8 rsvd0[3]; | ||
194 | u8 future_u32[4]; | ||
195 | } __packed; | ||
196 | |||
197 | struct be_mgmt_controller_attributes { | ||
198 | struct be_cmd_req_hdr hdr; | ||
199 | struct mgmt_controller_attributes params; | ||
200 | } __packed; | ||
201 | |||
202 | struct be_mgmt_controller_attributes_resp { | ||
203 | struct be_cmd_resp_hdr hdr; | ||
204 | struct mgmt_controller_attributes params; | ||
205 | } __packed; | ||
206 | |||
207 | /* configuration management */ | ||
208 | |||
209 | #define GET_MGMT_CONTROLLER_WS(phba) (phba->pmgmt_ws) | ||
210 | |||
211 | /* MGMT CMD flags */ | ||
212 | |||
213 | #define MGMT_CMDH_FREE (1<<0) | ||
214 | |||
215 | /* --- MGMT_ERROR_CODES --- */ | ||
216 | /* Error Codes returned in the status field of the CMD response header */ | ||
217 | #define MGMT_STATUS_SUCCESS 0 /* The CMD completed without errors */ | ||
218 | #define MGMT_STATUS_FAILED 1 /* Error status in the Status field of */ | ||
219 | /* the CMD_RESPONSE_HEADER */ | ||
220 | |||
221 | #define ISCSI_GET_PDU_TEMPLATE_ADDRESS(pc, pa) {\ | ||
222 | pa->lo = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\ | ||
223 | bus_address.u.a32.address_lo; \ | ||
224 | pa->hi = phba->init_mem[ISCSI_MEM_GLOBAL_HEADER].mem_array[0].\ | ||
225 | bus_address.u.a32.address_hi; \ | ||
226 | } | ||
227 | |||
228 | struct beiscsi_endpoint { | ||
229 | struct beiscsi_hba *phba; | ||
230 | struct beiscsi_sess *sess; | ||
231 | struct beiscsi_conn *conn; | ||
232 | unsigned short ip_type; | ||
233 | char dst6_addr[ISCSI_ADDRESS_BUF_LEN]; | ||
234 | unsigned long dst_addr; | ||
235 | unsigned short ep_cid; | ||
236 | unsigned int fw_handle; | ||
237 | u16 dst_tcpport; | ||
238 | u16 cid_vld; | ||
239 | }; | ||
240 | |||
241 | unsigned char mgmt_get_fw_config(struct be_ctrl_info *ctrl, | ||
242 | struct beiscsi_hba *phba); | ||
243 | |||
244 | unsigned char mgmt_invalidate_connection(struct beiscsi_hba *phba, | ||
245 | struct beiscsi_endpoint *beiscsi_ep, | ||
246 | unsigned short cid, | ||
247 | unsigned short issue_reset, | ||
248 | unsigned short savecfg_flag); | ||
249 | #endif | ||
diff --git a/drivers/scsi/bfa/Makefile b/drivers/scsi/bfa/Makefile new file mode 100644 index 000000000000..1d6009490d1c --- /dev/null +++ b/drivers/scsi/bfa/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | obj-$(CONFIG_SCSI_BFA_FC) := bfa.o | ||
2 | |||
3 | bfa-y := bfad.o bfad_intr.o bfad_os.o bfad_im.o bfad_attr.o bfad_fwimg.o | ||
4 | |||
5 | bfa-y += bfa_core.o bfa_ioc.o bfa_iocfc.o bfa_fcxp.o bfa_lps.o | ||
6 | bfa-y += bfa_hw_cb.o bfa_hw_ct.o bfa_intr.o bfa_timer.o bfa_rport.o | ||
7 | bfa-y += bfa_fcport.o bfa_port.o bfa_uf.o bfa_sgpg.o bfa_module.o bfa_ioim.o | ||
8 | bfa-y += bfa_itnim.o bfa_fcpim.o bfa_tskim.o bfa_log.o bfa_log_module.o | ||
9 | bfa-y += bfa_csdebug.o bfa_sm.o plog.o | ||
10 | |||
11 | bfa-y += fcbuild.o fabric.o fcpim.o vfapi.o fcptm.o bfa_fcs.o bfa_fcs_port.o | ||
12 | bfa-y += bfa_fcs_uf.o bfa_fcs_lport.o fab.o fdmi.o ms.o ns.o scn.o loop.o | ||
13 | bfa-y += lport_api.o n2n.o rport.o rport_api.o rport_ftrs.o vport.o | ||
14 | |||
15 | ccflags-y := -I$(obj) -I$(obj)/include -I$(obj)/include/cna | ||
diff --git a/drivers/scsi/bfa/bfa_callback_priv.h b/drivers/scsi/bfa/bfa_callback_priv.h new file mode 100644 index 000000000000..1e3265c9f7d4 --- /dev/null +++ b/drivers/scsi/bfa/bfa_callback_priv.h | |||
@@ -0,0 +1,57 @@ | |||
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 | #ifndef __BFA_CALLBACK_PRIV_H__ | ||
19 | #define __BFA_CALLBACK_PRIV_H__ | ||
20 | |||
21 | #include <cs/bfa_q.h> | ||
22 | |||
23 | typedef void (*bfa_cb_cbfn_t) (void *cbarg, bfa_boolean_t complete); | ||
24 | |||
25 | /** | ||
26 | * Generic BFA callback element. | ||
27 | */ | ||
28 | struct bfa_cb_qe_s { | ||
29 | struct list_head qe; | ||
30 | bfa_cb_cbfn_t cbfn; | ||
31 | bfa_boolean_t once; | ||
32 | u32 rsvd; | ||
33 | void *cbarg; | ||
34 | }; | ||
35 | |||
36 | #define bfa_cb_queue(__bfa, __hcb_qe, __cbfn, __cbarg) do { \ | ||
37 | (__hcb_qe)->cbfn = (__cbfn); \ | ||
38 | (__hcb_qe)->cbarg = (__cbarg); \ | ||
39 | list_add_tail(&(__hcb_qe)->qe, &(__bfa)->comp_q); \ | ||
40 | } while (0) | ||
41 | |||
42 | #define bfa_cb_dequeue(__hcb_qe) list_del(&(__hcb_qe)->qe) | ||
43 | |||
44 | #define bfa_cb_queue_once(__bfa, __hcb_qe, __cbfn, __cbarg) do { \ | ||
45 | (__hcb_qe)->cbfn = (__cbfn); \ | ||
46 | (__hcb_qe)->cbarg = (__cbarg); \ | ||
47 | if (!(__hcb_qe)->once) { \ | ||
48 | list_add_tail((__hcb_qe), &(__bfa)->comp_q); \ | ||
49 | (__hcb_qe)->once = BFA_TRUE; \ | ||
50 | } \ | ||
51 | } while (0) | ||
52 | |||
53 | #define bfa_cb_queue_done(__hcb_qe) do { \ | ||
54 | (__hcb_qe)->once = BFA_FALSE; \ | ||
55 | } while (0) | ||
56 | |||
57 | #endif /* __BFA_CALLBACK_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_cb_ioim_macros.h b/drivers/scsi/bfa/bfa_cb_ioim_macros.h new file mode 100644 index 000000000000..0050c838c358 --- /dev/null +++ b/drivers/scsi/bfa/bfa_cb_ioim_macros.h | |||
@@ -0,0 +1,205 @@ | |||
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 | * bfa_cb_ioim_macros.h BFA IOIM driver interface macros. | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_HCB_IOIM_MACROS_H__ | ||
23 | #define __BFA_HCB_IOIM_MACROS_H__ | ||
24 | |||
25 | #include <bfa_os_inc.h> | ||
26 | /* | ||
27 | * #include <linux/dma-mapping.h> | ||
28 | * | ||
29 | * #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include | ||
30 | * <scsi/scsi_device.h> #include <scsi/scsi_host.h> | ||
31 | */ | ||
32 | #include "bfad_im_compat.h" | ||
33 | |||
34 | /* | ||
35 | * task attribute values in FCP-2 FCP_CMND IU | ||
36 | */ | ||
37 | #define SIMPLE_Q 0 | ||
38 | #define HEAD_OF_Q 1 | ||
39 | #define ORDERED_Q 2 | ||
40 | #define ACA_Q 4 | ||
41 | #define UNTAGGED 5 | ||
42 | |||
43 | static inline lun_t | ||
44 | bfad_int_to_lun(u32 luno) | ||
45 | { | ||
46 | union { | ||
47 | u16 scsi_lun[4]; | ||
48 | lun_t bfa_lun; | ||
49 | } lun; | ||
50 | |||
51 | lun.bfa_lun = 0; | ||
52 | lun.scsi_lun[0] = bfa_os_htons(luno); | ||
53 | |||
54 | return (lun.bfa_lun); | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * Get LUN for the I/O request | ||
59 | */ | ||
60 | #define bfa_cb_ioim_get_lun(__dio) \ | ||
61 | bfad_int_to_lun(((struct scsi_cmnd *)__dio)->device->lun) | ||
62 | |||
63 | /** | ||
64 | * Get CDB for the I/O request | ||
65 | */ | ||
66 | static inline u8 * | ||
67 | bfa_cb_ioim_get_cdb(struct bfad_ioim_s *dio) | ||
68 | { | ||
69 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
70 | |||
71 | return ((u8 *) cmnd->cmnd); | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * Get I/O direction (read/write) for the I/O request | ||
76 | */ | ||
77 | static inline enum fcp_iodir | ||
78 | bfa_cb_ioim_get_iodir(struct bfad_ioim_s *dio) | ||
79 | { | ||
80 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
81 | enum dma_data_direction dmadir; | ||
82 | |||
83 | dmadir = cmnd->sc_data_direction; | ||
84 | if (dmadir == DMA_TO_DEVICE) | ||
85 | return FCP_IODIR_WRITE; | ||
86 | else if (dmadir == DMA_FROM_DEVICE) | ||
87 | return FCP_IODIR_READ; | ||
88 | else | ||
89 | return FCP_IODIR_NONE; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * Get IO size in bytes for the I/O request | ||
94 | */ | ||
95 | static inline u32 | ||
96 | bfa_cb_ioim_get_size(struct bfad_ioim_s *dio) | ||
97 | { | ||
98 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
99 | |||
100 | return (scsi_bufflen(cmnd)); | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * Get timeout for the I/O request | ||
105 | */ | ||
106 | static inline u8 | ||
107 | bfa_cb_ioim_get_timeout(struct bfad_ioim_s *dio) | ||
108 | { | ||
109 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
110 | /* | ||
111 | * TBD: need a timeout for scsi passthru | ||
112 | */ | ||
113 | if (cmnd->device->host == NULL) | ||
114 | return 4; | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * Get SG element for the I/O request given the SG element index | ||
121 | */ | ||
122 | static inline union bfi_addr_u | ||
123 | bfa_cb_ioim_get_sgaddr(struct bfad_ioim_s *dio, int sgeid) | ||
124 | { | ||
125 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
126 | struct scatterlist *sge; | ||
127 | u64 addr; | ||
128 | |||
129 | sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid; | ||
130 | addr = (u64) sg_dma_address(sge); | ||
131 | |||
132 | return (*(union bfi_addr_u *) &addr); | ||
133 | } | ||
134 | |||
135 | static inline u32 | ||
136 | bfa_cb_ioim_get_sglen(struct bfad_ioim_s *dio, int sgeid) | ||
137 | { | ||
138 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
139 | struct scatterlist *sge; | ||
140 | u32 len; | ||
141 | |||
142 | sge = (struct scatterlist *)scsi_sglist(cmnd) + sgeid; | ||
143 | len = sg_dma_len(sge); | ||
144 | |||
145 | return len; | ||
146 | } | ||
147 | |||
148 | /** | ||
149 | * Get Command Reference Number for the I/O request. 0 if none. | ||
150 | */ | ||
151 | static inline u8 | ||
152 | bfa_cb_ioim_get_crn(struct bfad_ioim_s *dio) | ||
153 | { | ||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * Get SAM-3 priority for the I/O request. 0 is default. | ||
159 | */ | ||
160 | static inline u8 | ||
161 | bfa_cb_ioim_get_priority(struct bfad_ioim_s *dio) | ||
162 | { | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * Get task attributes for the I/O request. Default is FCP_TASK_ATTR_SIMPLE(0). | ||
168 | */ | ||
169 | static inline u8 | ||
170 | bfa_cb_ioim_get_taskattr(struct bfad_ioim_s *dio) | ||
171 | { | ||
172 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
173 | u8 task_attr = UNTAGGED; | ||
174 | |||
175 | if (cmnd->device->tagged_supported) { | ||
176 | switch (cmnd->tag) { | ||
177 | case HEAD_OF_QUEUE_TAG: | ||
178 | task_attr = HEAD_OF_Q; | ||
179 | break; | ||
180 | case ORDERED_QUEUE_TAG: | ||
181 | task_attr = ORDERED_Q; | ||
182 | break; | ||
183 | default: | ||
184 | task_attr = SIMPLE_Q; | ||
185 | break; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | return task_attr; | ||
190 | } | ||
191 | |||
192 | /** | ||
193 | * Get CDB length in bytes for the I/O request. Default is FCP_CMND_CDB_LEN(16). | ||
194 | */ | ||
195 | static inline u8 | ||
196 | bfa_cb_ioim_get_cdblen(struct bfad_ioim_s *dio) | ||
197 | { | ||
198 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
199 | |||
200 | return (cmnd->cmd_len); | ||
201 | } | ||
202 | |||
203 | |||
204 | |||
205 | #endif /* __BFA_HCB_IOIM_MACROS_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_cee.c b/drivers/scsi/bfa/bfa_cee.c new file mode 100644 index 000000000000..7a959c34e789 --- /dev/null +++ b/drivers/scsi/bfa/bfa_cee.c | |||
@@ -0,0 +1,492 @@ | |||
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 | #include <defs/bfa_defs_cee.h> | ||
19 | #include <cs/bfa_trc.h> | ||
20 | #include <cs/bfa_log.h> | ||
21 | #include <cs/bfa_debug.h> | ||
22 | #include <cee/bfa_cee.h> | ||
23 | #include <bfi/bfi_cee.h> | ||
24 | #include <bfi/bfi.h> | ||
25 | #include <bfa_ioc.h> | ||
26 | #include <cna/bfa_cna_trcmod.h> | ||
27 | |||
28 | BFA_TRC_FILE(CNA, CEE); | ||
29 | |||
30 | #define bfa_ioc_portid(__ioc) ((__ioc)->port_id) | ||
31 | #define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc) | ||
32 | |||
33 | static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg); | ||
34 | static void bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s | ||
35 | *dcbcx_stats); | ||
36 | static void bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s | ||
37 | *lldp_stats); | ||
38 | static void bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats); | ||
39 | static void bfa_cee_format_cee_cfg(void *buffer); | ||
40 | static void bfa_cee_format_cee_stats(void *buffer); | ||
41 | |||
42 | static void | ||
43 | bfa_cee_format_cee_stats(void *buffer) | ||
44 | { | ||
45 | struct bfa_cee_stats_s *cee_stats = buffer; | ||
46 | bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats); | ||
47 | bfa_cee_format_lldp_stats(&cee_stats->lldp_stats); | ||
48 | bfa_cee_format_cfg_stats(&cee_stats->cfg_stats); | ||
49 | } | ||
50 | |||
51 | static void | ||
52 | bfa_cee_format_cee_cfg(void *buffer) | ||
53 | { | ||
54 | struct bfa_cee_attr_s *cee_cfg = buffer; | ||
55 | bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote); | ||
56 | } | ||
57 | |||
58 | static void | ||
59 | bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats) | ||
60 | { | ||
61 | dcbcx_stats->subtlvs_unrecognized = | ||
62 | bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized); | ||
63 | dcbcx_stats->negotiation_failed = | ||
64 | bfa_os_ntohl(dcbcx_stats->negotiation_failed); | ||
65 | dcbcx_stats->remote_cfg_changed = | ||
66 | bfa_os_ntohl(dcbcx_stats->remote_cfg_changed); | ||
67 | dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received); | ||
68 | dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid); | ||
69 | dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno); | ||
70 | dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno); | ||
71 | dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno); | ||
72 | dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno); | ||
73 | } | ||
74 | |||
75 | static void | ||
76 | bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats) | ||
77 | { | ||
78 | lldp_stats->frames_transmitted = | ||
79 | bfa_os_ntohl(lldp_stats->frames_transmitted); | ||
80 | lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out); | ||
81 | lldp_stats->frames_discarded = | ||
82 | bfa_os_ntohl(lldp_stats->frames_discarded); | ||
83 | lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error); | ||
84 | lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd); | ||
85 | lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded); | ||
86 | lldp_stats->tlvs_unrecognized = | ||
87 | bfa_os_ntohl(lldp_stats->tlvs_unrecognized); | ||
88 | } | ||
89 | |||
90 | static void | ||
91 | bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats) | ||
92 | { | ||
93 | cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down); | ||
94 | cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up); | ||
95 | cfg_stats->cee_hw_cfg_changed = | ||
96 | bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed); | ||
97 | cfg_stats->recvd_invalid_cfg = | ||
98 | bfa_os_ntohl(cfg_stats->recvd_invalid_cfg); | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg) | ||
103 | { | ||
104 | lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval); | ||
105 | lldp_cfg->enabled_system_cap = | ||
106 | bfa_os_ntohs(lldp_cfg->enabled_system_cap); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * bfa_cee_attr_meminfo() | ||
111 | * | ||
112 | * | ||
113 | * @param[in] void | ||
114 | * | ||
115 | * @return Size of DMA region | ||
116 | */ | ||
117 | static u32 | ||
118 | bfa_cee_attr_meminfo(void) | ||
119 | { | ||
120 | return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * bfa_cee_stats_meminfo() | ||
125 | * | ||
126 | * | ||
127 | * @param[in] void | ||
128 | * | ||
129 | * @return Size of DMA region | ||
130 | */ | ||
131 | static u32 | ||
132 | bfa_cee_stats_meminfo(void) | ||
133 | { | ||
134 | return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ); | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * bfa_cee_get_attr_isr() | ||
139 | * | ||
140 | * | ||
141 | * @param[in] cee - Pointer to the CEE module | ||
142 | * status - Return status from the f/w | ||
143 | * | ||
144 | * @return void | ||
145 | */ | ||
146 | static void | ||
147 | bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status) | ||
148 | { | ||
149 | cee->get_attr_status = status; | ||
150 | bfa_trc(cee, 0); | ||
151 | if (status == BFA_STATUS_OK) { | ||
152 | bfa_trc(cee, 0); | ||
153 | /* | ||
154 | * The requested data has been copied to the DMA area, *process | ||
155 | * it. | ||
156 | */ | ||
157 | memcpy(cee->attr, cee->attr_dma.kva, | ||
158 | sizeof(struct bfa_cee_attr_s)); | ||
159 | bfa_cee_format_cee_cfg(cee->attr); | ||
160 | } | ||
161 | cee->get_attr_pending = BFA_FALSE; | ||
162 | if (cee->cbfn.get_attr_cbfn) { | ||
163 | bfa_trc(cee, 0); | ||
164 | cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status); | ||
165 | } | ||
166 | bfa_trc(cee, 0); | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * bfa_cee_get_attr_isr() | ||
171 | * | ||
172 | * | ||
173 | * @param[in] cee - Pointer to the CEE module | ||
174 | * status - Return status from the f/w | ||
175 | * | ||
176 | * @return void | ||
177 | */ | ||
178 | static void | ||
179 | bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) | ||
180 | { | ||
181 | cee->get_stats_status = status; | ||
182 | bfa_trc(cee, 0); | ||
183 | if (status == BFA_STATUS_OK) { | ||
184 | bfa_trc(cee, 0); | ||
185 | /* | ||
186 | * The requested data has been copied to the DMA area, process | ||
187 | * it. | ||
188 | */ | ||
189 | memcpy(cee->stats, cee->stats_dma.kva, | ||
190 | sizeof(struct bfa_cee_stats_s)); | ||
191 | bfa_cee_format_cee_stats(cee->stats); | ||
192 | } | ||
193 | cee->get_stats_pending = BFA_FALSE; | ||
194 | bfa_trc(cee, 0); | ||
195 | if (cee->cbfn.get_stats_cbfn) { | ||
196 | bfa_trc(cee, 0); | ||
197 | cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status); | ||
198 | } | ||
199 | bfa_trc(cee, 0); | ||
200 | } | ||
201 | |||
202 | /** | ||
203 | * bfa_cee_get_attr_isr() | ||
204 | * | ||
205 | * | ||
206 | * @param[in] cee - Pointer to the CEE module | ||
207 | * status - Return status from the f/w | ||
208 | * | ||
209 | * @return void | ||
210 | */ | ||
211 | static void | ||
212 | bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) | ||
213 | { | ||
214 | cee->reset_stats_status = status; | ||
215 | cee->reset_stats_pending = BFA_FALSE; | ||
216 | if (cee->cbfn.reset_stats_cbfn) | ||
217 | cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * bfa_cee_meminfo() | ||
222 | * | ||
223 | * | ||
224 | * @param[in] void | ||
225 | * | ||
226 | * @return Size of DMA region | ||
227 | */ | ||
228 | u32 | ||
229 | bfa_cee_meminfo(void) | ||
230 | { | ||
231 | return (bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo()); | ||
232 | } | ||
233 | |||
234 | /** | ||
235 | * bfa_cee_mem_claim() | ||
236 | * | ||
237 | * | ||
238 | * @param[in] cee CEE module pointer | ||
239 | * dma_kva Kernel Virtual Address of CEE DMA Memory | ||
240 | * dma_pa Physical Address of CEE DMA Memory | ||
241 | * | ||
242 | * @return void | ||
243 | */ | ||
244 | void | ||
245 | bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa) | ||
246 | { | ||
247 | cee->attr_dma.kva = dma_kva; | ||
248 | cee->attr_dma.pa = dma_pa; | ||
249 | cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo(); | ||
250 | cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo(); | ||
251 | cee->attr = (struct bfa_cee_attr_s *)dma_kva; | ||
252 | cee->stats = | ||
253 | (struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo()); | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * bfa_cee_get_attr() | ||
258 | * | ||
259 | * Send the request to the f/w to fetch CEE attributes. | ||
260 | * | ||
261 | * @param[in] Pointer to the CEE module data structure. | ||
262 | * | ||
263 | * @return Status | ||
264 | */ | ||
265 | |||
266 | bfa_status_t | ||
267 | bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr, | ||
268 | bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) | ||
269 | { | ||
270 | struct bfi_cee_get_req_s *cmd; | ||
271 | |||
272 | bfa_assert((cee != NULL) && (cee->ioc != NULL)); | ||
273 | bfa_trc(cee, 0); | ||
274 | if (!bfa_ioc_is_operational(cee->ioc)) { | ||
275 | bfa_trc(cee, 0); | ||
276 | return BFA_STATUS_IOC_FAILURE; | ||
277 | } | ||
278 | if (cee->get_attr_pending == BFA_TRUE) { | ||
279 | bfa_trc(cee, 0); | ||
280 | return BFA_STATUS_DEVBUSY; | ||
281 | } | ||
282 | cee->get_attr_pending = BFA_TRUE; | ||
283 | cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg; | ||
284 | cee->attr = attr; | ||
285 | cee->cbfn.get_attr_cbfn = cbfn; | ||
286 | cee->cbfn.get_attr_cbarg = cbarg; | ||
287 | bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, | ||
288 | bfa_ioc_portid(cee->ioc)); | ||
289 | bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); | ||
290 | bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb); | ||
291 | bfa_trc(cee, 0); | ||
292 | |||
293 | return BFA_STATUS_OK; | ||
294 | } | ||
295 | |||
296 | /** | ||
297 | * bfa_cee_get_stats() | ||
298 | * | ||
299 | * Send the request to the f/w to fetch CEE statistics. | ||
300 | * | ||
301 | * @param[in] Pointer to the CEE module data structure. | ||
302 | * | ||
303 | * @return Status | ||
304 | */ | ||
305 | |||
306 | bfa_status_t | ||
307 | bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats, | ||
308 | bfa_cee_get_stats_cbfn_t cbfn, void *cbarg) | ||
309 | { | ||
310 | struct bfi_cee_get_req_s *cmd; | ||
311 | |||
312 | bfa_assert((cee != NULL) && (cee->ioc != NULL)); | ||
313 | |||
314 | if (!bfa_ioc_is_operational(cee->ioc)) { | ||
315 | bfa_trc(cee, 0); | ||
316 | return BFA_STATUS_IOC_FAILURE; | ||
317 | } | ||
318 | if (cee->get_stats_pending == BFA_TRUE) { | ||
319 | bfa_trc(cee, 0); | ||
320 | return BFA_STATUS_DEVBUSY; | ||
321 | } | ||
322 | cee->get_stats_pending = BFA_TRUE; | ||
323 | cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg; | ||
324 | cee->stats = stats; | ||
325 | cee->cbfn.get_stats_cbfn = cbfn; | ||
326 | cee->cbfn.get_stats_cbarg = cbarg; | ||
327 | bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, | ||
328 | bfa_ioc_portid(cee->ioc)); | ||
329 | bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa); | ||
330 | bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb); | ||
331 | bfa_trc(cee, 0); | ||
332 | |||
333 | return BFA_STATUS_OK; | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * bfa_cee_reset_stats() | ||
338 | * | ||
339 | * | ||
340 | * @param[in] Pointer to the CEE module data structure. | ||
341 | * | ||
342 | * @return Status | ||
343 | */ | ||
344 | |||
345 | bfa_status_t | ||
346 | bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn, | ||
347 | void *cbarg) | ||
348 | { | ||
349 | struct bfi_cee_reset_stats_s *cmd; | ||
350 | |||
351 | bfa_assert((cee != NULL) && (cee->ioc != NULL)); | ||
352 | if (!bfa_ioc_is_operational(cee->ioc)) { | ||
353 | bfa_trc(cee, 0); | ||
354 | return BFA_STATUS_IOC_FAILURE; | ||
355 | } | ||
356 | if (cee->reset_stats_pending == BFA_TRUE) { | ||
357 | bfa_trc(cee, 0); | ||
358 | return BFA_STATUS_DEVBUSY; | ||
359 | } | ||
360 | cee->reset_stats_pending = BFA_TRUE; | ||
361 | cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg; | ||
362 | cee->cbfn.reset_stats_cbfn = cbfn; | ||
363 | cee->cbfn.reset_stats_cbarg = cbarg; | ||
364 | bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, | ||
365 | bfa_ioc_portid(cee->ioc)); | ||
366 | bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb); | ||
367 | bfa_trc(cee, 0); | ||
368 | return BFA_STATUS_OK; | ||
369 | } | ||
370 | |||
371 | /** | ||
372 | * bfa_cee_isrs() | ||
373 | * | ||
374 | * | ||
375 | * @param[in] Pointer to the CEE module data structure. | ||
376 | * | ||
377 | * @return void | ||
378 | */ | ||
379 | |||
380 | void | ||
381 | bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m) | ||
382 | { | ||
383 | union bfi_cee_i2h_msg_u *msg; | ||
384 | struct bfi_cee_get_rsp_s *get_rsp; | ||
385 | struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg; | ||
386 | msg = (union bfi_cee_i2h_msg_u *)m; | ||
387 | get_rsp = (struct bfi_cee_get_rsp_s *)m; | ||
388 | bfa_trc(cee, msg->mh.msg_id); | ||
389 | switch (msg->mh.msg_id) { | ||
390 | case BFI_CEE_I2H_GET_CFG_RSP: | ||
391 | bfa_trc(cee, get_rsp->cmd_status); | ||
392 | bfa_cee_get_attr_isr(cee, get_rsp->cmd_status); | ||
393 | break; | ||
394 | case BFI_CEE_I2H_GET_STATS_RSP: | ||
395 | bfa_cee_get_stats_isr(cee, get_rsp->cmd_status); | ||
396 | break; | ||
397 | case BFI_CEE_I2H_RESET_STATS_RSP: | ||
398 | bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status); | ||
399 | break; | ||
400 | default: | ||
401 | bfa_assert(0); | ||
402 | } | ||
403 | } | ||
404 | |||
405 | /** | ||
406 | * bfa_cee_hbfail() | ||
407 | * | ||
408 | * | ||
409 | * @param[in] Pointer to the CEE module data structure. | ||
410 | * | ||
411 | * @return void | ||
412 | */ | ||
413 | |||
414 | void | ||
415 | bfa_cee_hbfail(void *arg) | ||
416 | { | ||
417 | struct bfa_cee_s *cee; | ||
418 | cee = (struct bfa_cee_s *)arg; | ||
419 | |||
420 | if (cee->get_attr_pending == BFA_TRUE) { | ||
421 | cee->get_attr_status = BFA_STATUS_FAILED; | ||
422 | cee->get_attr_pending = BFA_FALSE; | ||
423 | if (cee->cbfn.get_attr_cbfn) { | ||
424 | cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, | ||
425 | BFA_STATUS_FAILED); | ||
426 | } | ||
427 | } | ||
428 | if (cee->get_stats_pending == BFA_TRUE) { | ||
429 | cee->get_stats_status = BFA_STATUS_FAILED; | ||
430 | cee->get_stats_pending = BFA_FALSE; | ||
431 | if (cee->cbfn.get_stats_cbfn) { | ||
432 | cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, | ||
433 | BFA_STATUS_FAILED); | ||
434 | } | ||
435 | } | ||
436 | if (cee->reset_stats_pending == BFA_TRUE) { | ||
437 | cee->reset_stats_status = BFA_STATUS_FAILED; | ||
438 | cee->reset_stats_pending = BFA_FALSE; | ||
439 | if (cee->cbfn.reset_stats_cbfn) { | ||
440 | cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, | ||
441 | BFA_STATUS_FAILED); | ||
442 | } | ||
443 | } | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * bfa_cee_attach() | ||
448 | * | ||
449 | * | ||
450 | * @param[in] cee - Pointer to the CEE module data structure | ||
451 | * ioc - Pointer to the ioc module data structure | ||
452 | * dev - Pointer to the device driver module data structure | ||
453 | * The device driver specific mbox ISR functions have | ||
454 | * this pointer as one of the parameters. | ||
455 | * trcmod - | ||
456 | * logmod - | ||
457 | * | ||
458 | * @return void | ||
459 | */ | ||
460 | void | ||
461 | bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev, | ||
462 | struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod) | ||
463 | { | ||
464 | bfa_assert(cee != NULL); | ||
465 | cee->dev = dev; | ||
466 | cee->trcmod = trcmod; | ||
467 | cee->logmod = logmod; | ||
468 | cee->ioc = ioc; | ||
469 | |||
470 | bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); | ||
471 | bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee); | ||
472 | bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail); | ||
473 | bfa_trc(cee, 0); | ||
474 | } | ||
475 | |||
476 | /** | ||
477 | * bfa_cee_detach() | ||
478 | * | ||
479 | * | ||
480 | * @param[in] cee - Pointer to the CEE module data structure | ||
481 | * | ||
482 | * @return void | ||
483 | */ | ||
484 | void | ||
485 | bfa_cee_detach(struct bfa_cee_s *cee) | ||
486 | { | ||
487 | /* | ||
488 | * For now, just check if there is some ioctl pending and mark that as | ||
489 | * failed? | ||
490 | */ | ||
491 | /* bfa_cee_hbfail(cee); */ | ||
492 | } | ||
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c new file mode 100644 index 000000000000..44e2d1155c51 --- /dev/null +++ b/drivers/scsi/bfa/bfa_core.c | |||
@@ -0,0 +1,402 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <defs/bfa_defs_pci.h> | ||
20 | #include <cs/bfa_debug.h> | ||
21 | #include <bfa_iocfc.h> | ||
22 | |||
23 | #define DEF_CFG_NUM_FABRICS 1 | ||
24 | #define DEF_CFG_NUM_LPORTS 256 | ||
25 | #define DEF_CFG_NUM_CQS 4 | ||
26 | #define DEF_CFG_NUM_IOIM_REQS (BFA_IOIM_MAX) | ||
27 | #define DEF_CFG_NUM_TSKIM_REQS 128 | ||
28 | #define DEF_CFG_NUM_FCXP_REQS 64 | ||
29 | #define DEF_CFG_NUM_UF_BUFS 64 | ||
30 | #define DEF_CFG_NUM_RPORTS 1024 | ||
31 | #define DEF_CFG_NUM_ITNIMS (DEF_CFG_NUM_RPORTS) | ||
32 | #define DEF_CFG_NUM_TINS 256 | ||
33 | |||
34 | #define DEF_CFG_NUM_SGPGS 2048 | ||
35 | #define DEF_CFG_NUM_REQQ_ELEMS 256 | ||
36 | #define DEF_CFG_NUM_RSPQ_ELEMS 64 | ||
37 | #define DEF_CFG_NUM_SBOOT_TGTS 16 | ||
38 | #define DEF_CFG_NUM_SBOOT_LUNS 16 | ||
39 | |||
40 | /** | ||
41 | * Use this function query the memory requirement of the BFA library. | ||
42 | * This function needs to be called before bfa_attach() to get the | ||
43 | * memory required of the BFA layer for a given driver configuration. | ||
44 | * | ||
45 | * This call will fail, if the cap is out of range compared to pre-defined | ||
46 | * values within the BFA library | ||
47 | * | ||
48 | * @param[in] cfg - pointer to bfa_ioc_cfg_t. Driver layer should indicate | ||
49 | * its configuration in this structure. | ||
50 | * The default values for struct bfa_iocfc_cfg_s can be | ||
51 | * fetched using bfa_cfg_get_default() API. | ||
52 | * | ||
53 | * If cap's boundary check fails, the library will use | ||
54 | * the default bfa_cap_t values (and log a warning msg). | ||
55 | * | ||
56 | * @param[out] meminfo - pointer to bfa_meminfo_t. This content | ||
57 | * indicates the memory type (see bfa_mem_type_t) and | ||
58 | * amount of memory required. | ||
59 | * | ||
60 | * Driver should allocate the memory, populate the | ||
61 | * starting address for each block and provide the same | ||
62 | * structure as input parameter to bfa_attach() call. | ||
63 | * | ||
64 | * @return void | ||
65 | * | ||
66 | * Special Considerations: @note | ||
67 | */ | ||
68 | void | ||
69 | bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo) | ||
70 | { | ||
71 | int i; | ||
72 | u32 km_len = 0, dm_len = 0; | ||
73 | |||
74 | bfa_assert((cfg != NULL) && (meminfo != NULL)); | ||
75 | |||
76 | bfa_os_memset((void *)meminfo, 0, sizeof(struct bfa_meminfo_s)); | ||
77 | meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_type = | ||
78 | BFA_MEM_TYPE_KVA; | ||
79 | meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_type = | ||
80 | BFA_MEM_TYPE_DMA; | ||
81 | |||
82 | bfa_iocfc_meminfo(cfg, &km_len, &dm_len); | ||
83 | |||
84 | for (i = 0; hal_mods[i]; i++) | ||
85 | hal_mods[i]->meminfo(cfg, &km_len, &dm_len); | ||
86 | |||
87 | |||
88 | meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len; | ||
89 | meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * Use this function to do attach the driver instance with the BFA | ||
94 | * library. This function will not trigger any HW initialization | ||
95 | * process (which will be done in bfa_init() call) | ||
96 | * | ||
97 | * This call will fail, if the cap is out of range compared to | ||
98 | * pre-defined values within the BFA library | ||
99 | * | ||
100 | * @param[out] bfa Pointer to bfa_t. | ||
101 | * @param[in] bfad Opaque handle back to the driver's IOC structure | ||
102 | * @param[in] cfg Pointer to bfa_ioc_cfg_t. Should be same structure | ||
103 | * that was used in bfa_cfg_get_meminfo(). | ||
104 | * @param[in] meminfo Pointer to bfa_meminfo_t. The driver should | ||
105 | * use the bfa_cfg_get_meminfo() call to | ||
106 | * find the memory blocks required, allocate the | ||
107 | * required memory and provide the starting addresses. | ||
108 | * @param[in] pcidev pointer to struct bfa_pcidev_s | ||
109 | * | ||
110 | * @return | ||
111 | * void | ||
112 | * | ||
113 | * Special Considerations: | ||
114 | * | ||
115 | * @note | ||
116 | * | ||
117 | */ | ||
118 | void | ||
119 | bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
120 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
121 | { | ||
122 | int i; | ||
123 | struct bfa_mem_elem_s *melem; | ||
124 | |||
125 | bfa->fcs = BFA_FALSE; | ||
126 | |||
127 | bfa_assert((cfg != NULL) && (meminfo != NULL)); | ||
128 | |||
129 | /** | ||
130 | * initialize all memory pointers for iterative allocation | ||
131 | */ | ||
132 | for (i = 0; i < BFA_MEM_TYPE_MAX; i++) { | ||
133 | melem = meminfo->meminfo + i; | ||
134 | melem->kva_curp = melem->kva; | ||
135 | melem->dma_curp = melem->dma; | ||
136 | } | ||
137 | |||
138 | bfa_iocfc_attach(bfa, bfad, cfg, meminfo, pcidev); | ||
139 | |||
140 | for (i = 0; hal_mods[i]; i++) | ||
141 | hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev); | ||
142 | |||
143 | } | ||
144 | |||
145 | /** | ||
146 | * Use this function to delete a BFA IOC. IOC should be stopped (by | ||
147 | * calling bfa_stop()) before this function call. | ||
148 | * | ||
149 | * @param[in] bfa - pointer to bfa_t. | ||
150 | * | ||
151 | * @return | ||
152 | * void | ||
153 | * | ||
154 | * Special Considerations: | ||
155 | * | ||
156 | * @note | ||
157 | */ | ||
158 | void | ||
159 | bfa_detach(struct bfa_s *bfa) | ||
160 | { | ||
161 | int i; | ||
162 | |||
163 | for (i = 0; hal_mods[i]; i++) | ||
164 | hal_mods[i]->detach(bfa); | ||
165 | |||
166 | bfa_iocfc_detach(bfa); | ||
167 | } | ||
168 | |||
169 | |||
170 | void | ||
171 | bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod) | ||
172 | { | ||
173 | bfa->trcmod = trcmod; | ||
174 | } | ||
175 | |||
176 | |||
177 | void | ||
178 | bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod) | ||
179 | { | ||
180 | bfa->logm = logmod; | ||
181 | } | ||
182 | |||
183 | |||
184 | void | ||
185 | bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen) | ||
186 | { | ||
187 | bfa->aen = aen; | ||
188 | } | ||
189 | |||
190 | void | ||
191 | bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog) | ||
192 | { | ||
193 | bfa->plog = plog; | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * Initialize IOC. | ||
198 | * | ||
199 | * This function will return immediately, when the IOC initialization is | ||
200 | * completed, the bfa_cb_init() will be called. | ||
201 | * | ||
202 | * @param[in] bfa instance | ||
203 | * | ||
204 | * @return void | ||
205 | * | ||
206 | * Special Considerations: | ||
207 | * | ||
208 | * @note | ||
209 | * When this function returns, the driver should register the interrupt service | ||
210 | * routine(s) and enable the device interrupts. If this is not done, | ||
211 | * bfa_cb_init() will never get called | ||
212 | */ | ||
213 | void | ||
214 | bfa_init(struct bfa_s *bfa) | ||
215 | { | ||
216 | bfa_iocfc_init(bfa); | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * Use this function initiate the IOC configuration setup. This function | ||
221 | * will return immediately. | ||
222 | * | ||
223 | * @param[in] bfa instance | ||
224 | * | ||
225 | * @return None | ||
226 | */ | ||
227 | void | ||
228 | bfa_start(struct bfa_s *bfa) | ||
229 | { | ||
230 | bfa_iocfc_start(bfa); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * Use this function quiese the IOC. This function will return immediately, | ||
235 | * when the IOC is actually stopped, the bfa_cb_stop() will be called. | ||
236 | * | ||
237 | * @param[in] bfa - pointer to bfa_t. | ||
238 | * | ||
239 | * @return None | ||
240 | * | ||
241 | * Special Considerations: | ||
242 | * bfa_cb_stop() could be called before or after bfa_stop() returns. | ||
243 | * | ||
244 | * @note | ||
245 | * In case of any failure, we could handle it automatically by doing a | ||
246 | * reset and then succeed the bfa_stop() call. | ||
247 | */ | ||
248 | void | ||
249 | bfa_stop(struct bfa_s *bfa) | ||
250 | { | ||
251 | bfa_iocfc_stop(bfa); | ||
252 | } | ||
253 | |||
254 | void | ||
255 | bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q) | ||
256 | { | ||
257 | INIT_LIST_HEAD(comp_q); | ||
258 | list_splice_tail_init(&bfa->comp_q, comp_q); | ||
259 | } | ||
260 | |||
261 | void | ||
262 | bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q) | ||
263 | { | ||
264 | struct list_head *qe; | ||
265 | struct list_head *qen; | ||
266 | struct bfa_cb_qe_s *hcb_qe; | ||
267 | |||
268 | list_for_each_safe(qe, qen, comp_q) { | ||
269 | hcb_qe = (struct bfa_cb_qe_s *) qe; | ||
270 | hcb_qe->cbfn(hcb_qe->cbarg, BFA_TRUE); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | void | ||
275 | bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q) | ||
276 | { | ||
277 | struct list_head *qe; | ||
278 | struct bfa_cb_qe_s *hcb_qe; | ||
279 | |||
280 | while (!list_empty(comp_q)) { | ||
281 | bfa_q_deq(comp_q, &qe); | ||
282 | hcb_qe = (struct bfa_cb_qe_s *) qe; | ||
283 | hcb_qe->cbfn(hcb_qe->cbarg, BFA_FALSE); | ||
284 | } | ||
285 | } | ||
286 | |||
287 | void | ||
288 | bfa_attach_fcs(struct bfa_s *bfa) | ||
289 | { | ||
290 | bfa->fcs = BFA_TRUE; | ||
291 | } | ||
292 | |||
293 | /** | ||
294 | * Periodic timer heart beat from driver | ||
295 | */ | ||
296 | void | ||
297 | bfa_timer_tick(struct bfa_s *bfa) | ||
298 | { | ||
299 | bfa_timer_beat(&bfa->timer_mod); | ||
300 | } | ||
301 | |||
302 | #ifndef BFA_BIOS_BUILD | ||
303 | /** | ||
304 | * Return the list of PCI vendor/device id lists supported by this | ||
305 | * BFA instance. | ||
306 | */ | ||
307 | void | ||
308 | bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids) | ||
309 | { | ||
310 | static struct bfa_pciid_s __pciids[] = { | ||
311 | {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G2P}, | ||
312 | {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_FC_8G1P}, | ||
313 | {BFA_PCI_VENDOR_ID_BROCADE, BFA_PCI_DEVICE_ID_CT}, | ||
314 | }; | ||
315 | |||
316 | *npciids = sizeof(__pciids) / sizeof(__pciids[0]); | ||
317 | *pciids = __pciids; | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * Use this function query the default struct bfa_iocfc_cfg_s value (compiled | ||
322 | * into BFA layer). The OS driver can then turn back and overwrite entries that | ||
323 | * have been configured by the user. | ||
324 | * | ||
325 | * @param[in] cfg - pointer to bfa_ioc_cfg_t | ||
326 | * | ||
327 | * @return | ||
328 | * void | ||
329 | * | ||
330 | * Special Considerations: | ||
331 | * note | ||
332 | */ | ||
333 | void | ||
334 | bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg) | ||
335 | { | ||
336 | cfg->fwcfg.num_fabrics = DEF_CFG_NUM_FABRICS; | ||
337 | cfg->fwcfg.num_lports = DEF_CFG_NUM_LPORTS; | ||
338 | cfg->fwcfg.num_rports = DEF_CFG_NUM_RPORTS; | ||
339 | cfg->fwcfg.num_ioim_reqs = DEF_CFG_NUM_IOIM_REQS; | ||
340 | cfg->fwcfg.num_tskim_reqs = DEF_CFG_NUM_TSKIM_REQS; | ||
341 | cfg->fwcfg.num_fcxp_reqs = DEF_CFG_NUM_FCXP_REQS; | ||
342 | cfg->fwcfg.num_uf_bufs = DEF_CFG_NUM_UF_BUFS; | ||
343 | cfg->fwcfg.num_cqs = DEF_CFG_NUM_CQS; | ||
344 | |||
345 | cfg->drvcfg.num_reqq_elems = DEF_CFG_NUM_REQQ_ELEMS; | ||
346 | cfg->drvcfg.num_rspq_elems = DEF_CFG_NUM_RSPQ_ELEMS; | ||
347 | cfg->drvcfg.num_sgpgs = DEF_CFG_NUM_SGPGS; | ||
348 | cfg->drvcfg.num_sboot_tgts = DEF_CFG_NUM_SBOOT_TGTS; | ||
349 | cfg->drvcfg.num_sboot_luns = DEF_CFG_NUM_SBOOT_LUNS; | ||
350 | cfg->drvcfg.path_tov = BFA_FCPIM_PATHTOV_DEF; | ||
351 | cfg->drvcfg.ioc_recover = BFA_FALSE; | ||
352 | cfg->drvcfg.delay_comp = BFA_FALSE; | ||
353 | |||
354 | } | ||
355 | |||
356 | void | ||
357 | bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg) | ||
358 | { | ||
359 | bfa_cfg_get_default(cfg); | ||
360 | cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN; | ||
361 | cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN; | ||
362 | cfg->fwcfg.num_fcxp_reqs = BFA_FCXP_MIN; | ||
363 | cfg->fwcfg.num_uf_bufs = BFA_UF_MIN; | ||
364 | cfg->fwcfg.num_rports = BFA_RPORT_MIN; | ||
365 | |||
366 | cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN; | ||
367 | cfg->drvcfg.num_reqq_elems = BFA_REQQ_NELEMS_MIN; | ||
368 | cfg->drvcfg.num_rspq_elems = BFA_RSPQ_NELEMS_MIN; | ||
369 | cfg->drvcfg.min_cfg = BFA_TRUE; | ||
370 | } | ||
371 | |||
372 | void | ||
373 | bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr) | ||
374 | { | ||
375 | bfa_ioc_get_attr(&bfa->ioc, ioc_attr); | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * Retrieve firmware trace information on IOC failure. | ||
380 | */ | ||
381 | bfa_status_t | ||
382 | bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen) | ||
383 | { | ||
384 | return bfa_ioc_debug_fwsave(&bfa->ioc, trcdata, trclen); | ||
385 | } | ||
386 | |||
387 | /** | ||
388 | * Fetch firmware trace data. | ||
389 | * | ||
390 | * @param[in] bfa BFA instance | ||
391 | * @param[out] trcdata Firmware trace buffer | ||
392 | * @param[in,out] trclen Firmware trace buffer len | ||
393 | * | ||
394 | * @retval BFA_STATUS_OK Firmware trace is fetched. | ||
395 | * @retval BFA_STATUS_INPROGRESS Firmware trace fetch is in progress. | ||
396 | */ | ||
397 | bfa_status_t | ||
398 | bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen) | ||
399 | { | ||
400 | return bfa_ioc_debug_fwtrc(&bfa->ioc, trcdata, trclen); | ||
401 | } | ||
402 | #endif | ||
diff --git a/drivers/scsi/bfa/bfa_csdebug.c b/drivers/scsi/bfa/bfa_csdebug.c new file mode 100644 index 000000000000..1b71d349451a --- /dev/null +++ b/drivers/scsi/bfa/bfa_csdebug.c | |||
@@ -0,0 +1,58 @@ | |||
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 | #include <cs/bfa_debug.h> | ||
19 | #include <bfa_os_inc.h> | ||
20 | #include <cs/bfa_q.h> | ||
21 | #include <log/bfa_log_hal.h> | ||
22 | |||
23 | /** | ||
24 | * cs_debug_api | ||
25 | */ | ||
26 | |||
27 | |||
28 | void | ||
29 | bfa_panic(int line, char *file, char *panicstr) | ||
30 | { | ||
31 | bfa_log(NULL, BFA_LOG_HAL_ASSERT, file, line, panicstr); | ||
32 | bfa_os_panic(); | ||
33 | } | ||
34 | |||
35 | void | ||
36 | bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event) | ||
37 | { | ||
38 | bfa_log(logm, BFA_LOG_HAL_SM_ASSERT, file, line, event); | ||
39 | bfa_os_panic(); | ||
40 | } | ||
41 | |||
42 | int | ||
43 | bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe) | ||
44 | { | ||
45 | struct list_head *tqe; | ||
46 | |||
47 | tqe = bfa_q_next(q); | ||
48 | while (tqe != q) { | ||
49 | if (tqe == qe) | ||
50 | return (1); | ||
51 | tqe = bfa_q_next(tqe); | ||
52 | if (tqe == NULL) | ||
53 | break; | ||
54 | } | ||
55 | return (0); | ||
56 | } | ||
57 | |||
58 | |||
diff --git a/drivers/scsi/bfa/bfa_fcpim.c b/drivers/scsi/bfa/bfa_fcpim.c new file mode 100644 index 000000000000..401babe3494e --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcpim.c | |||
@@ -0,0 +1,175 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <log/bfa_log_hal.h> | ||
20 | |||
21 | BFA_TRC_FILE(HAL, FCPIM); | ||
22 | BFA_MODULE(fcpim); | ||
23 | |||
24 | /** | ||
25 | * hal_fcpim_mod BFA FCP Initiator Mode module | ||
26 | */ | ||
27 | |||
28 | /** | ||
29 | * Compute and return memory needed by FCP(im) module. | ||
30 | */ | ||
31 | static void | ||
32 | bfa_fcpim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
33 | u32 *dm_len) | ||
34 | { | ||
35 | bfa_itnim_meminfo(cfg, km_len, dm_len); | ||
36 | |||
37 | /** | ||
38 | * IO memory | ||
39 | */ | ||
40 | if (cfg->fwcfg.num_ioim_reqs < BFA_IOIM_MIN) | ||
41 | cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MIN; | ||
42 | else if (cfg->fwcfg.num_ioim_reqs > BFA_IOIM_MAX) | ||
43 | cfg->fwcfg.num_ioim_reqs = BFA_IOIM_MAX; | ||
44 | |||
45 | *km_len += cfg->fwcfg.num_ioim_reqs * | ||
46 | (sizeof(struct bfa_ioim_s) + sizeof(struct bfa_ioim_sp_s)); | ||
47 | |||
48 | *dm_len += cfg->fwcfg.num_ioim_reqs * BFI_IOIM_SNSLEN; | ||
49 | |||
50 | /** | ||
51 | * task management command memory | ||
52 | */ | ||
53 | if (cfg->fwcfg.num_tskim_reqs < BFA_TSKIM_MIN) | ||
54 | cfg->fwcfg.num_tskim_reqs = BFA_TSKIM_MIN; | ||
55 | *km_len += cfg->fwcfg.num_tskim_reqs * sizeof(struct bfa_tskim_s); | ||
56 | } | ||
57 | |||
58 | |||
59 | static void | ||
60 | bfa_fcpim_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
61 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
62 | { | ||
63 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
64 | |||
65 | bfa_trc(bfa, cfg->drvcfg.path_tov); | ||
66 | bfa_trc(bfa, cfg->fwcfg.num_rports); | ||
67 | bfa_trc(bfa, cfg->fwcfg.num_ioim_reqs); | ||
68 | bfa_trc(bfa, cfg->fwcfg.num_tskim_reqs); | ||
69 | |||
70 | fcpim->bfa = bfa; | ||
71 | fcpim->num_itnims = cfg->fwcfg.num_rports; | ||
72 | fcpim->num_ioim_reqs = cfg->fwcfg.num_ioim_reqs; | ||
73 | fcpim->num_tskim_reqs = cfg->fwcfg.num_tskim_reqs; | ||
74 | fcpim->path_tov = cfg->drvcfg.path_tov; | ||
75 | fcpim->delay_comp = cfg->drvcfg.delay_comp; | ||
76 | |||
77 | bfa_itnim_attach(fcpim, meminfo); | ||
78 | bfa_tskim_attach(fcpim, meminfo); | ||
79 | bfa_ioim_attach(fcpim, meminfo); | ||
80 | } | ||
81 | |||
82 | static void | ||
83 | bfa_fcpim_initdone(struct bfa_s *bfa) | ||
84 | { | ||
85 | } | ||
86 | |||
87 | static void | ||
88 | bfa_fcpim_detach(struct bfa_s *bfa) | ||
89 | { | ||
90 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
91 | |||
92 | bfa_ioim_detach(fcpim); | ||
93 | bfa_tskim_detach(fcpim); | ||
94 | } | ||
95 | |||
96 | static void | ||
97 | bfa_fcpim_start(struct bfa_s *bfa) | ||
98 | { | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | bfa_fcpim_stop(struct bfa_s *bfa) | ||
103 | { | ||
104 | } | ||
105 | |||
106 | static void | ||
107 | bfa_fcpim_iocdisable(struct bfa_s *bfa) | ||
108 | { | ||
109 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
110 | struct bfa_itnim_s *itnim; | ||
111 | struct list_head *qe, *qen; | ||
112 | |||
113 | list_for_each_safe(qe, qen, &fcpim->itnim_q) { | ||
114 | itnim = (struct bfa_itnim_s *) qe; | ||
115 | bfa_itnim_iocdisable(itnim); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | void | ||
120 | bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov) | ||
121 | { | ||
122 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
123 | |||
124 | fcpim->path_tov = path_tov * 1000; | ||
125 | if (fcpim->path_tov > BFA_FCPIM_PATHTOV_MAX) | ||
126 | fcpim->path_tov = BFA_FCPIM_PATHTOV_MAX; | ||
127 | } | ||
128 | |||
129 | u16 | ||
130 | bfa_fcpim_path_tov_get(struct bfa_s *bfa) | ||
131 | { | ||
132 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
133 | |||
134 | return (fcpim->path_tov / 1000); | ||
135 | } | ||
136 | |||
137 | bfa_status_t | ||
138 | bfa_fcpim_get_modstats(struct bfa_s *bfa, struct bfa_fcpim_stats_s *modstats) | ||
139 | { | ||
140 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
141 | |||
142 | *modstats = fcpim->stats; | ||
143 | |||
144 | return BFA_STATUS_OK; | ||
145 | } | ||
146 | |||
147 | bfa_status_t | ||
148 | bfa_fcpim_clr_modstats(struct bfa_s *bfa) | ||
149 | { | ||
150 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
151 | |||
152 | memset(&fcpim->stats, 0, sizeof(struct bfa_fcpim_stats_s)); | ||
153 | |||
154 | return BFA_STATUS_OK; | ||
155 | } | ||
156 | |||
157 | void | ||
158 | bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth) | ||
159 | { | ||
160 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
161 | |||
162 | bfa_assert(q_depth <= BFA_IOCFC_QDEPTH_MAX); | ||
163 | |||
164 | fcpim->q_depth = q_depth; | ||
165 | } | ||
166 | |||
167 | u16 | ||
168 | bfa_fcpim_qdepth_get(struct bfa_s *bfa) | ||
169 | { | ||
170 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
171 | |||
172 | return (fcpim->q_depth); | ||
173 | } | ||
174 | |||
175 | |||
diff --git a/drivers/scsi/bfa/bfa_fcpim_priv.h b/drivers/scsi/bfa/bfa_fcpim_priv.h new file mode 100644 index 000000000000..153206cfb37a --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcpim_priv.h | |||
@@ -0,0 +1,188 @@ | |||
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 | #ifndef __BFA_FCPIM_PRIV_H__ | ||
19 | #define __BFA_FCPIM_PRIV_H__ | ||
20 | |||
21 | #include <bfa_fcpim.h> | ||
22 | #include <defs/bfa_defs_fcpim.h> | ||
23 | #include <cs/bfa_wc.h> | ||
24 | #include "bfa_sgpg_priv.h" | ||
25 | |||
26 | #define BFA_ITNIM_MIN 32 | ||
27 | #define BFA_ITNIM_MAX 1024 | ||
28 | |||
29 | #define BFA_IOIM_MIN 8 | ||
30 | #define BFA_IOIM_MAX 2000 | ||
31 | |||
32 | #define BFA_TSKIM_MIN 4 | ||
33 | #define BFA_TSKIM_MAX 512 | ||
34 | #define BFA_FCPIM_PATHTOV_DEF (30 * 1000) /* in millisecs */ | ||
35 | #define BFA_FCPIM_PATHTOV_MAX (90 * 1000) /* in millisecs */ | ||
36 | |||
37 | #define bfa_fcpim_stats(__fcpim, __stats) \ | ||
38 | (__fcpim)->stats.__stats ++ | ||
39 | |||
40 | struct bfa_fcpim_mod_s { | ||
41 | struct bfa_s *bfa; | ||
42 | struct bfa_itnim_s *itnim_arr; | ||
43 | struct bfa_ioim_s *ioim_arr; | ||
44 | struct bfa_ioim_sp_s *ioim_sp_arr; | ||
45 | struct bfa_tskim_s *tskim_arr; | ||
46 | struct bfa_dma_s snsbase; | ||
47 | int num_itnims; | ||
48 | int num_ioim_reqs; | ||
49 | int num_tskim_reqs; | ||
50 | u32 path_tov; | ||
51 | u16 q_depth; | ||
52 | u16 rsvd; | ||
53 | struct list_head itnim_q; /* queue of active itnim */ | ||
54 | struct list_head ioim_free_q; /* free IO resources */ | ||
55 | struct list_head ioim_resfree_q; /* IOs waiting for f/w */ | ||
56 | struct list_head ioim_comp_q; /* IO global comp Q */ | ||
57 | struct list_head tskim_free_q; | ||
58 | u32 ios_active; /* current active IOs */ | ||
59 | u32 delay_comp; | ||
60 | struct bfa_fcpim_stats_s stats; | ||
61 | }; | ||
62 | |||
63 | struct bfa_ioim_s; | ||
64 | struct bfa_tskim_s; | ||
65 | |||
66 | /** | ||
67 | * BFA IO (initiator mode) | ||
68 | */ | ||
69 | struct bfa_ioim_s { | ||
70 | struct list_head qe; /* queue elememt */ | ||
71 | bfa_sm_t sm; /* BFA ioim state machine */ | ||
72 | struct bfa_s *bfa; /* BFA module */ | ||
73 | struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */ | ||
74 | struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */ | ||
75 | struct bfad_ioim_s *dio; /* driver IO handle */ | ||
76 | u16 iotag; /* FWI IO tag */ | ||
77 | u16 abort_tag; /* unqiue abort request tag */ | ||
78 | u16 nsges; /* number of SG elements */ | ||
79 | u16 nsgpgs; /* number of SG pages */ | ||
80 | struct bfa_sgpg_s *sgpg; /* first SG page */ | ||
81 | struct list_head sgpg_q; /* allocated SG pages */ | ||
82 | struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */ | ||
83 | bfa_cb_cbfn_t io_cbfn; /* IO completion handler */ | ||
84 | struct bfa_ioim_sp_s *iosp; /* slow-path IO handling */ | ||
85 | }; | ||
86 | |||
87 | struct bfa_ioim_sp_s { | ||
88 | struct bfi_msg_s comp_rspmsg; /* IO comp f/w response */ | ||
89 | u8 *snsinfo; /* sense info for this IO */ | ||
90 | struct bfa_sgpg_wqe_s sgpg_wqe; /* waitq elem for sgpg */ | ||
91 | struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ | ||
92 | bfa_boolean_t abort_explicit; /* aborted by OS */ | ||
93 | struct bfa_tskim_s *tskim; /* Relevant TM cmd */ | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * BFA Task management command (initiator mode) | ||
98 | */ | ||
99 | struct bfa_tskim_s { | ||
100 | struct list_head qe; | ||
101 | bfa_sm_t sm; | ||
102 | struct bfa_s *bfa; /* BFA module */ | ||
103 | struct bfa_fcpim_mod_s *fcpim; /* parent fcpim module */ | ||
104 | struct bfa_itnim_s *itnim; /* i-t-n nexus for this IO */ | ||
105 | struct bfad_tskim_s *dtsk; /* driver task mgmt cmnd */ | ||
106 | bfa_boolean_t notify; /* notify itnim on TM comp */ | ||
107 | lun_t lun; /* lun if applicable */ | ||
108 | enum fcp_tm_cmnd tm_cmnd; /* task management command */ | ||
109 | u16 tsk_tag; /* FWI IO tag */ | ||
110 | u8 tsecs; /* timeout in seconds */ | ||
111 | struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ | ||
112 | struct list_head io_q; /* queue of affected IOs */ | ||
113 | struct bfa_wc_s wc; /* waiting counter */ | ||
114 | struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */ | ||
115 | enum bfi_tskim_status tsk_status; /* TM status */ | ||
116 | }; | ||
117 | |||
118 | /** | ||
119 | * BFA i-t-n (initiator mode) | ||
120 | */ | ||
121 | struct bfa_itnim_s { | ||
122 | struct list_head qe; /* queue element */ | ||
123 | bfa_sm_t sm; /* i-t-n im BFA state machine */ | ||
124 | struct bfa_s *bfa; /* bfa instance */ | ||
125 | struct bfa_rport_s *rport; /* bfa rport */ | ||
126 | void *ditn; /* driver i-t-n structure */ | ||
127 | struct bfi_mhdr_s mhdr; /* pre-built mhdr */ | ||
128 | u8 msg_no; /* itnim/rport firmware handle */ | ||
129 | u8 reqq; /* CQ for requests */ | ||
130 | struct bfa_cb_qe_s hcb_qe; /* bfa callback qelem */ | ||
131 | struct list_head pending_q; /* queue of pending IO requests*/ | ||
132 | struct list_head io_q; /* queue of active IO requests */ | ||
133 | struct list_head io_cleanup_q; /* IO being cleaned up */ | ||
134 | struct list_head tsk_q; /* queue of active TM commands */ | ||
135 | struct list_head delay_comp_q;/* queue of failed inflight cmds */ | ||
136 | bfa_boolean_t seq_rec; /* SQER supported */ | ||
137 | bfa_boolean_t is_online; /* itnim is ONLINE for IO */ | ||
138 | bfa_boolean_t iotov_active; /* IO TOV timer is active */ | ||
139 | struct bfa_wc_s wc; /* waiting counter */ | ||
140 | struct bfa_timer_s timer; /* pending IO TOV */ | ||
141 | struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ | ||
142 | struct bfa_fcpim_mod_s *fcpim; /* fcpim module */ | ||
143 | struct bfa_itnim_hal_stats_s stats; | ||
144 | }; | ||
145 | |||
146 | #define bfa_itnim_is_online(_itnim) (_itnim)->is_online | ||
147 | #define BFA_FCPIM_MOD(_hal) (&(_hal)->modules.fcpim_mod) | ||
148 | #define BFA_IOIM_FROM_TAG(_fcpim, _iotag) \ | ||
149 | (&fcpim->ioim_arr[_iotag]) | ||
150 | #define BFA_TSKIM_FROM_TAG(_fcpim, _tmtag) \ | ||
151 | (&fcpim->tskim_arr[_tmtag & (fcpim->num_tskim_reqs - 1)]) | ||
152 | |||
153 | /* | ||
154 | * function prototypes | ||
155 | */ | ||
156 | void bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, | ||
157 | struct bfa_meminfo_s *minfo); | ||
158 | void bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim); | ||
159 | void bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
160 | void bfa_ioim_good_comp_isr(struct bfa_s *bfa, | ||
161 | struct bfi_msg_s *msg); | ||
162 | void bfa_ioim_cleanup(struct bfa_ioim_s *ioim); | ||
163 | void bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, | ||
164 | struct bfa_tskim_s *tskim); | ||
165 | void bfa_ioim_iocdisable(struct bfa_ioim_s *ioim); | ||
166 | void bfa_ioim_tov(struct bfa_ioim_s *ioim); | ||
167 | |||
168 | void bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, | ||
169 | struct bfa_meminfo_s *minfo); | ||
170 | void bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim); | ||
171 | void bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
172 | void bfa_tskim_iodone(struct bfa_tskim_s *tskim); | ||
173 | void bfa_tskim_iocdisable(struct bfa_tskim_s *tskim); | ||
174 | void bfa_tskim_cleanup(struct bfa_tskim_s *tskim); | ||
175 | |||
176 | void bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
177 | u32 *dm_len); | ||
178 | void bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, | ||
179 | struct bfa_meminfo_s *minfo); | ||
180 | void bfa_itnim_detach(struct bfa_fcpim_mod_s *fcpim); | ||
181 | void bfa_itnim_iocdisable(struct bfa_itnim_s *itnim); | ||
182 | void bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
183 | void bfa_itnim_iodone(struct bfa_itnim_s *itnim); | ||
184 | void bfa_itnim_tskdone(struct bfa_itnim_s *itnim); | ||
185 | bfa_boolean_t bfa_itnim_hold_io(struct bfa_itnim_s *itnim); | ||
186 | |||
187 | #endif /* __BFA_FCPIM_PRIV_H__ */ | ||
188 | |||
diff --git a/drivers/scsi/bfa/bfa_fcport.c b/drivers/scsi/bfa/bfa_fcport.c new file mode 100644 index 000000000000..992435987deb --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcport.c | |||
@@ -0,0 +1,1671 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfa_svc.h> | ||
20 | #include <bfi/bfi_pport.h> | ||
21 | #include <cs/bfa_debug.h> | ||
22 | #include <aen/bfa_aen.h> | ||
23 | #include <cs/bfa_plog.h> | ||
24 | #include <aen/bfa_aen_port.h> | ||
25 | |||
26 | BFA_TRC_FILE(HAL, PPORT); | ||
27 | BFA_MODULE(pport); | ||
28 | |||
29 | #define bfa_pport_callback(__pport, __event) do { \ | ||
30 | if ((__pport)->bfa->fcs) { \ | ||
31 | (__pport)->event_cbfn((__pport)->event_cbarg, (__event)); \ | ||
32 | } else { \ | ||
33 | (__pport)->hcb_event = (__event); \ | ||
34 | bfa_cb_queue((__pport)->bfa, &(__pport)->hcb_qe, \ | ||
35 | __bfa_cb_port_event, (__pport)); \ | ||
36 | } \ | ||
37 | } while (0) | ||
38 | |||
39 | /* | ||
40 | * The port is considered disabled if corresponding physical port or IOC are | ||
41 | * disabled explicitly | ||
42 | */ | ||
43 | #define BFA_PORT_IS_DISABLED(bfa) \ | ||
44 | ((bfa_pport_is_disabled(bfa) == BFA_TRUE) || \ | ||
45 | (bfa_ioc_is_disabled(&bfa->ioc) == BFA_TRUE)) | ||
46 | |||
47 | /* | ||
48 | * forward declarations | ||
49 | */ | ||
50 | static bfa_boolean_t bfa_pport_send_enable(struct bfa_pport_s *port); | ||
51 | static bfa_boolean_t bfa_pport_send_disable(struct bfa_pport_s *port); | ||
52 | static void bfa_pport_update_linkinfo(struct bfa_pport_s *pport); | ||
53 | static void bfa_pport_reset_linkinfo(struct bfa_pport_s *pport); | ||
54 | static void bfa_pport_set_wwns(struct bfa_pport_s *port); | ||
55 | static void __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete); | ||
56 | static void __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete); | ||
57 | static void __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete); | ||
58 | static void bfa_port_stats_timeout(void *cbarg); | ||
59 | static void bfa_port_stats_clr_timeout(void *cbarg); | ||
60 | |||
61 | /** | ||
62 | * bfa_pport_private | ||
63 | */ | ||
64 | |||
65 | /** | ||
66 | * BFA port state machine events | ||
67 | */ | ||
68 | enum bfa_pport_sm_event { | ||
69 | BFA_PPORT_SM_START = 1, /* start port state machine */ | ||
70 | BFA_PPORT_SM_STOP = 2, /* stop port state machine */ | ||
71 | BFA_PPORT_SM_ENABLE = 3, /* enable port */ | ||
72 | BFA_PPORT_SM_DISABLE = 4, /* disable port state machine */ | ||
73 | BFA_PPORT_SM_FWRSP = 5, /* firmware enable/disable rsp */ | ||
74 | BFA_PPORT_SM_LINKUP = 6, /* firmware linkup event */ | ||
75 | BFA_PPORT_SM_LINKDOWN = 7, /* firmware linkup down */ | ||
76 | BFA_PPORT_SM_QRESUME = 8, /* CQ space available */ | ||
77 | BFA_PPORT_SM_HWFAIL = 9, /* IOC h/w failure */ | ||
78 | }; | ||
79 | |||
80 | static void bfa_pport_sm_uninit(struct bfa_pport_s *pport, | ||
81 | enum bfa_pport_sm_event event); | ||
82 | static void bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport, | ||
83 | enum bfa_pport_sm_event event); | ||
84 | static void bfa_pport_sm_enabling(struct bfa_pport_s *pport, | ||
85 | enum bfa_pport_sm_event event); | ||
86 | static void bfa_pport_sm_linkdown(struct bfa_pport_s *pport, | ||
87 | enum bfa_pport_sm_event event); | ||
88 | static void bfa_pport_sm_linkup(struct bfa_pport_s *pport, | ||
89 | enum bfa_pport_sm_event event); | ||
90 | static void bfa_pport_sm_disabling(struct bfa_pport_s *pport, | ||
91 | enum bfa_pport_sm_event event); | ||
92 | static void bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport, | ||
93 | enum bfa_pport_sm_event event); | ||
94 | static void bfa_pport_sm_disabled(struct bfa_pport_s *pport, | ||
95 | enum bfa_pport_sm_event event); | ||
96 | static void bfa_pport_sm_stopped(struct bfa_pport_s *pport, | ||
97 | enum bfa_pport_sm_event event); | ||
98 | static void bfa_pport_sm_iocdown(struct bfa_pport_s *pport, | ||
99 | enum bfa_pport_sm_event event); | ||
100 | static void bfa_pport_sm_iocfail(struct bfa_pport_s *pport, | ||
101 | enum bfa_pport_sm_event event); | ||
102 | |||
103 | static struct bfa_sm_table_s hal_pport_sm_table[] = { | ||
104 | {BFA_SM(bfa_pport_sm_uninit), BFA_PPORT_ST_UNINIT}, | ||
105 | {BFA_SM(bfa_pport_sm_enabling_qwait), BFA_PPORT_ST_ENABLING_QWAIT}, | ||
106 | {BFA_SM(bfa_pport_sm_enabling), BFA_PPORT_ST_ENABLING}, | ||
107 | {BFA_SM(bfa_pport_sm_linkdown), BFA_PPORT_ST_LINKDOWN}, | ||
108 | {BFA_SM(bfa_pport_sm_linkup), BFA_PPORT_ST_LINKUP}, | ||
109 | {BFA_SM(bfa_pport_sm_disabling_qwait), | ||
110 | BFA_PPORT_ST_DISABLING_QWAIT}, | ||
111 | {BFA_SM(bfa_pport_sm_disabling), BFA_PPORT_ST_DISABLING}, | ||
112 | {BFA_SM(bfa_pport_sm_disabled), BFA_PPORT_ST_DISABLED}, | ||
113 | {BFA_SM(bfa_pport_sm_stopped), BFA_PPORT_ST_STOPPED}, | ||
114 | {BFA_SM(bfa_pport_sm_iocdown), BFA_PPORT_ST_IOCDOWN}, | ||
115 | {BFA_SM(bfa_pport_sm_iocfail), BFA_PPORT_ST_IOCDOWN}, | ||
116 | }; | ||
117 | |||
118 | static void | ||
119 | bfa_pport_aen_post(struct bfa_pport_s *pport, enum bfa_port_aen_event event) | ||
120 | { | ||
121 | union bfa_aen_data_u aen_data; | ||
122 | struct bfa_log_mod_s *logmod = pport->bfa->logm; | ||
123 | wwn_t pwwn = pport->pwwn; | ||
124 | char pwwn_ptr[BFA_STRING_32]; | ||
125 | struct bfa_ioc_attr_s ioc_attr; | ||
126 | |||
127 | wwn2str(pwwn_ptr, pwwn); | ||
128 | switch (event) { | ||
129 | case BFA_PORT_AEN_ONLINE: | ||
130 | bfa_log(logmod, BFA_AEN_PORT_ONLINE, pwwn_ptr); | ||
131 | break; | ||
132 | case BFA_PORT_AEN_OFFLINE: | ||
133 | bfa_log(logmod, BFA_AEN_PORT_OFFLINE, pwwn_ptr); | ||
134 | break; | ||
135 | case BFA_PORT_AEN_ENABLE: | ||
136 | bfa_log(logmod, BFA_AEN_PORT_ENABLE, pwwn_ptr); | ||
137 | break; | ||
138 | case BFA_PORT_AEN_DISABLE: | ||
139 | bfa_log(logmod, BFA_AEN_PORT_DISABLE, pwwn_ptr); | ||
140 | break; | ||
141 | case BFA_PORT_AEN_DISCONNECT: | ||
142 | bfa_log(logmod, BFA_AEN_PORT_DISCONNECT, pwwn_ptr); | ||
143 | break; | ||
144 | case BFA_PORT_AEN_QOS_NEG: | ||
145 | bfa_log(logmod, BFA_AEN_PORT_QOS_NEG, pwwn_ptr); | ||
146 | break; | ||
147 | default: | ||
148 | break; | ||
149 | } | ||
150 | |||
151 | bfa_ioc_get_attr(&pport->bfa->ioc, &ioc_attr); | ||
152 | aen_data.port.ioc_type = ioc_attr.ioc_type; | ||
153 | aen_data.port.pwwn = pwwn; | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | bfa_pport_sm_uninit(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
158 | { | ||
159 | bfa_trc(pport->bfa, event); | ||
160 | |||
161 | switch (event) { | ||
162 | case BFA_PPORT_SM_START: | ||
163 | /** | ||
164 | * Start event after IOC is configured and BFA is started. | ||
165 | */ | ||
166 | if (bfa_pport_send_enable(pport)) | ||
167 | bfa_sm_set_state(pport, bfa_pport_sm_enabling); | ||
168 | else | ||
169 | bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait); | ||
170 | break; | ||
171 | |||
172 | case BFA_PPORT_SM_ENABLE: | ||
173 | /** | ||
174 | * Port is persistently configured to be in enabled state. Do | ||
175 | * not change state. Port enabling is done when START event is | ||
176 | * received. | ||
177 | */ | ||
178 | break; | ||
179 | |||
180 | case BFA_PPORT_SM_DISABLE: | ||
181 | /** | ||
182 | * If a port is persistently configured to be disabled, the | ||
183 | * first event will a port disable request. | ||
184 | */ | ||
185 | bfa_sm_set_state(pport, bfa_pport_sm_disabled); | ||
186 | break; | ||
187 | |||
188 | case BFA_PPORT_SM_HWFAIL: | ||
189 | bfa_sm_set_state(pport, bfa_pport_sm_iocdown); | ||
190 | break; | ||
191 | |||
192 | default: | ||
193 | bfa_sm_fault(pport->bfa, event); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | static void | ||
198 | bfa_pport_sm_enabling_qwait(struct bfa_pport_s *pport, | ||
199 | enum bfa_pport_sm_event event) | ||
200 | { | ||
201 | bfa_trc(pport->bfa, event); | ||
202 | |||
203 | switch (event) { | ||
204 | case BFA_PPORT_SM_QRESUME: | ||
205 | bfa_sm_set_state(pport, bfa_pport_sm_enabling); | ||
206 | bfa_pport_send_enable(pport); | ||
207 | break; | ||
208 | |||
209 | case BFA_PPORT_SM_STOP: | ||
210 | bfa_reqq_wcancel(&pport->reqq_wait); | ||
211 | bfa_sm_set_state(pport, bfa_pport_sm_stopped); | ||
212 | break; | ||
213 | |||
214 | case BFA_PPORT_SM_ENABLE: | ||
215 | /** | ||
216 | * Already enable is in progress. | ||
217 | */ | ||
218 | break; | ||
219 | |||
220 | case BFA_PPORT_SM_DISABLE: | ||
221 | /** | ||
222 | * Just send disable request to firmware when room becomes | ||
223 | * available in request queue. | ||
224 | */ | ||
225 | bfa_sm_set_state(pport, bfa_pport_sm_disabled); | ||
226 | bfa_reqq_wcancel(&pport->reqq_wait); | ||
227 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
228 | BFA_PL_EID_PORT_DISABLE, 0, "Port Disable"); | ||
229 | bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE); | ||
230 | break; | ||
231 | |||
232 | case BFA_PPORT_SM_LINKUP: | ||
233 | case BFA_PPORT_SM_LINKDOWN: | ||
234 | /** | ||
235 | * Possible to get link events when doing back-to-back | ||
236 | * enable/disables. | ||
237 | */ | ||
238 | break; | ||
239 | |||
240 | case BFA_PPORT_SM_HWFAIL: | ||
241 | bfa_reqq_wcancel(&pport->reqq_wait); | ||
242 | bfa_sm_set_state(pport, bfa_pport_sm_iocdown); | ||
243 | break; | ||
244 | |||
245 | default: | ||
246 | bfa_sm_fault(pport->bfa, event); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void | ||
251 | bfa_pport_sm_enabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
252 | { | ||
253 | bfa_trc(pport->bfa, event); | ||
254 | |||
255 | switch (event) { | ||
256 | case BFA_PPORT_SM_FWRSP: | ||
257 | case BFA_PPORT_SM_LINKDOWN: | ||
258 | bfa_sm_set_state(pport, bfa_pport_sm_linkdown); | ||
259 | break; | ||
260 | |||
261 | case BFA_PPORT_SM_LINKUP: | ||
262 | bfa_pport_update_linkinfo(pport); | ||
263 | bfa_sm_set_state(pport, bfa_pport_sm_linkup); | ||
264 | |||
265 | bfa_assert(pport->event_cbfn); | ||
266 | bfa_pport_callback(pport, BFA_PPORT_LINKUP); | ||
267 | break; | ||
268 | |||
269 | case BFA_PPORT_SM_ENABLE: | ||
270 | /** | ||
271 | * Already being enabled. | ||
272 | */ | ||
273 | break; | ||
274 | |||
275 | case BFA_PPORT_SM_DISABLE: | ||
276 | if (bfa_pport_send_disable(pport)) | ||
277 | bfa_sm_set_state(pport, bfa_pport_sm_disabling); | ||
278 | else | ||
279 | bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait); | ||
280 | |||
281 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
282 | BFA_PL_EID_PORT_DISABLE, 0, "Port Disable"); | ||
283 | bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE); | ||
284 | break; | ||
285 | |||
286 | case BFA_PPORT_SM_STOP: | ||
287 | bfa_sm_set_state(pport, bfa_pport_sm_stopped); | ||
288 | break; | ||
289 | |||
290 | case BFA_PPORT_SM_HWFAIL: | ||
291 | bfa_sm_set_state(pport, bfa_pport_sm_iocdown); | ||
292 | break; | ||
293 | |||
294 | default: | ||
295 | bfa_sm_fault(pport->bfa, event); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | static void | ||
300 | bfa_pport_sm_linkdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
301 | { | ||
302 | bfa_trc(pport->bfa, event); | ||
303 | |||
304 | switch (event) { | ||
305 | case BFA_PPORT_SM_LINKUP: | ||
306 | bfa_pport_update_linkinfo(pport); | ||
307 | bfa_sm_set_state(pport, bfa_pport_sm_linkup); | ||
308 | bfa_assert(pport->event_cbfn); | ||
309 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
310 | BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkup"); | ||
311 | bfa_pport_callback(pport, BFA_PPORT_LINKUP); | ||
312 | bfa_pport_aen_post(pport, BFA_PORT_AEN_ONLINE); | ||
313 | /** | ||
314 | * If QoS is enabled and it is not online, | ||
315 | * Send a separate event. | ||
316 | */ | ||
317 | if ((pport->cfg.qos_enabled) | ||
318 | && (bfa_os_ntohl(pport->qos_attr.state) != BFA_QOS_ONLINE)) | ||
319 | bfa_pport_aen_post(pport, BFA_PORT_AEN_QOS_NEG); | ||
320 | |||
321 | break; | ||
322 | |||
323 | case BFA_PPORT_SM_LINKDOWN: | ||
324 | /** | ||
325 | * Possible to get link down event. | ||
326 | */ | ||
327 | break; | ||
328 | |||
329 | case BFA_PPORT_SM_ENABLE: | ||
330 | /** | ||
331 | * Already enabled. | ||
332 | */ | ||
333 | break; | ||
334 | |||
335 | case BFA_PPORT_SM_DISABLE: | ||
336 | if (bfa_pport_send_disable(pport)) | ||
337 | bfa_sm_set_state(pport, bfa_pport_sm_disabling); | ||
338 | else | ||
339 | bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait); | ||
340 | |||
341 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
342 | BFA_PL_EID_PORT_DISABLE, 0, "Port Disable"); | ||
343 | bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE); | ||
344 | break; | ||
345 | |||
346 | case BFA_PPORT_SM_STOP: | ||
347 | bfa_sm_set_state(pport, bfa_pport_sm_stopped); | ||
348 | break; | ||
349 | |||
350 | case BFA_PPORT_SM_HWFAIL: | ||
351 | bfa_sm_set_state(pport, bfa_pport_sm_iocdown); | ||
352 | break; | ||
353 | |||
354 | default: | ||
355 | bfa_sm_fault(pport->bfa, event); | ||
356 | } | ||
357 | } | ||
358 | |||
359 | static void | ||
360 | bfa_pport_sm_linkup(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
361 | { | ||
362 | bfa_trc(pport->bfa, event); | ||
363 | |||
364 | switch (event) { | ||
365 | case BFA_PPORT_SM_ENABLE: | ||
366 | /** | ||
367 | * Already enabled. | ||
368 | */ | ||
369 | break; | ||
370 | |||
371 | case BFA_PPORT_SM_DISABLE: | ||
372 | if (bfa_pport_send_disable(pport)) | ||
373 | bfa_sm_set_state(pport, bfa_pport_sm_disabling); | ||
374 | else | ||
375 | bfa_sm_set_state(pport, bfa_pport_sm_disabling_qwait); | ||
376 | |||
377 | bfa_pport_reset_linkinfo(pport); | ||
378 | bfa_pport_callback(pport, BFA_PPORT_LINKDOWN); | ||
379 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
380 | BFA_PL_EID_PORT_DISABLE, 0, "Port Disable"); | ||
381 | bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE); | ||
382 | bfa_pport_aen_post(pport, BFA_PORT_AEN_DISABLE); | ||
383 | break; | ||
384 | |||
385 | case BFA_PPORT_SM_LINKDOWN: | ||
386 | bfa_sm_set_state(pport, bfa_pport_sm_linkdown); | ||
387 | bfa_pport_reset_linkinfo(pport); | ||
388 | bfa_pport_callback(pport, BFA_PPORT_LINKDOWN); | ||
389 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
390 | BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown"); | ||
391 | if (BFA_PORT_IS_DISABLED(pport->bfa)) { | ||
392 | bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE); | ||
393 | } else { | ||
394 | bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT); | ||
395 | } | ||
396 | break; | ||
397 | |||
398 | case BFA_PPORT_SM_STOP: | ||
399 | bfa_sm_set_state(pport, bfa_pport_sm_stopped); | ||
400 | bfa_pport_reset_linkinfo(pport); | ||
401 | if (BFA_PORT_IS_DISABLED(pport->bfa)) { | ||
402 | bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE); | ||
403 | } else { | ||
404 | bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT); | ||
405 | } | ||
406 | break; | ||
407 | |||
408 | case BFA_PPORT_SM_HWFAIL: | ||
409 | bfa_sm_set_state(pport, bfa_pport_sm_iocdown); | ||
410 | bfa_pport_reset_linkinfo(pport); | ||
411 | bfa_pport_callback(pport, BFA_PPORT_LINKDOWN); | ||
412 | if (BFA_PORT_IS_DISABLED(pport->bfa)) { | ||
413 | bfa_pport_aen_post(pport, BFA_PORT_AEN_OFFLINE); | ||
414 | } else { | ||
415 | bfa_pport_aen_post(pport, BFA_PORT_AEN_DISCONNECT); | ||
416 | } | ||
417 | break; | ||
418 | |||
419 | default: | ||
420 | bfa_sm_fault(pport->bfa, event); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | static void | ||
425 | bfa_pport_sm_disabling_qwait(struct bfa_pport_s *pport, | ||
426 | enum bfa_pport_sm_event event) | ||
427 | { | ||
428 | bfa_trc(pport->bfa, event); | ||
429 | |||
430 | switch (event) { | ||
431 | case BFA_PPORT_SM_QRESUME: | ||
432 | bfa_sm_set_state(pport, bfa_pport_sm_disabling); | ||
433 | bfa_pport_send_disable(pport); | ||
434 | break; | ||
435 | |||
436 | case BFA_PPORT_SM_STOP: | ||
437 | bfa_sm_set_state(pport, bfa_pport_sm_stopped); | ||
438 | bfa_reqq_wcancel(&pport->reqq_wait); | ||
439 | break; | ||
440 | |||
441 | case BFA_PPORT_SM_DISABLE: | ||
442 | /** | ||
443 | * Already being disabled. | ||
444 | */ | ||
445 | break; | ||
446 | |||
447 | case BFA_PPORT_SM_LINKUP: | ||
448 | case BFA_PPORT_SM_LINKDOWN: | ||
449 | /** | ||
450 | * Possible to get link events when doing back-to-back | ||
451 | * enable/disables. | ||
452 | */ | ||
453 | break; | ||
454 | |||
455 | case BFA_PPORT_SM_HWFAIL: | ||
456 | bfa_sm_set_state(pport, bfa_pport_sm_iocfail); | ||
457 | bfa_reqq_wcancel(&pport->reqq_wait); | ||
458 | break; | ||
459 | |||
460 | default: | ||
461 | bfa_sm_fault(pport->bfa, event); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | static void | ||
466 | bfa_pport_sm_disabling(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
467 | { | ||
468 | bfa_trc(pport->bfa, event); | ||
469 | |||
470 | switch (event) { | ||
471 | case BFA_PPORT_SM_FWRSP: | ||
472 | bfa_sm_set_state(pport, bfa_pport_sm_disabled); | ||
473 | break; | ||
474 | |||
475 | case BFA_PPORT_SM_DISABLE: | ||
476 | /** | ||
477 | * Already being disabled. | ||
478 | */ | ||
479 | break; | ||
480 | |||
481 | case BFA_PPORT_SM_ENABLE: | ||
482 | if (bfa_pport_send_enable(pport)) | ||
483 | bfa_sm_set_state(pport, bfa_pport_sm_enabling); | ||
484 | else | ||
485 | bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait); | ||
486 | |||
487 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
488 | BFA_PL_EID_PORT_ENABLE, 0, "Port Enable"); | ||
489 | bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE); | ||
490 | break; | ||
491 | |||
492 | case BFA_PPORT_SM_STOP: | ||
493 | bfa_sm_set_state(pport, bfa_pport_sm_stopped); | ||
494 | break; | ||
495 | |||
496 | case BFA_PPORT_SM_LINKUP: | ||
497 | case BFA_PPORT_SM_LINKDOWN: | ||
498 | /** | ||
499 | * Possible to get link events when doing back-to-back | ||
500 | * enable/disables. | ||
501 | */ | ||
502 | break; | ||
503 | |||
504 | case BFA_PPORT_SM_HWFAIL: | ||
505 | bfa_sm_set_state(pport, bfa_pport_sm_iocfail); | ||
506 | break; | ||
507 | |||
508 | default: | ||
509 | bfa_sm_fault(pport->bfa, event); | ||
510 | } | ||
511 | } | ||
512 | |||
513 | static void | ||
514 | bfa_pport_sm_disabled(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
515 | { | ||
516 | bfa_trc(pport->bfa, event); | ||
517 | |||
518 | switch (event) { | ||
519 | case BFA_PPORT_SM_START: | ||
520 | /** | ||
521 | * Ignore start event for a port that is disabled. | ||
522 | */ | ||
523 | break; | ||
524 | |||
525 | case BFA_PPORT_SM_STOP: | ||
526 | bfa_sm_set_state(pport, bfa_pport_sm_stopped); | ||
527 | break; | ||
528 | |||
529 | case BFA_PPORT_SM_ENABLE: | ||
530 | if (bfa_pport_send_enable(pport)) | ||
531 | bfa_sm_set_state(pport, bfa_pport_sm_enabling); | ||
532 | else | ||
533 | bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait); | ||
534 | |||
535 | bfa_plog_str(pport->bfa->plog, BFA_PL_MID_HAL, | ||
536 | BFA_PL_EID_PORT_ENABLE, 0, "Port Enable"); | ||
537 | bfa_pport_aen_post(pport, BFA_PORT_AEN_ENABLE); | ||
538 | break; | ||
539 | |||
540 | case BFA_PPORT_SM_DISABLE: | ||
541 | /** | ||
542 | * Already disabled. | ||
543 | */ | ||
544 | break; | ||
545 | |||
546 | case BFA_PPORT_SM_HWFAIL: | ||
547 | bfa_sm_set_state(pport, bfa_pport_sm_iocfail); | ||
548 | break; | ||
549 | |||
550 | default: | ||
551 | bfa_sm_fault(pport->bfa, event); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | static void | ||
556 | bfa_pport_sm_stopped(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
557 | { | ||
558 | bfa_trc(pport->bfa, event); | ||
559 | |||
560 | switch (event) { | ||
561 | case BFA_PPORT_SM_START: | ||
562 | if (bfa_pport_send_enable(pport)) | ||
563 | bfa_sm_set_state(pport, bfa_pport_sm_enabling); | ||
564 | else | ||
565 | bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait); | ||
566 | break; | ||
567 | |||
568 | default: | ||
569 | /** | ||
570 | * Ignore all other events. | ||
571 | */ | ||
572 | ; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | /** | ||
577 | * Port is enabled. IOC is down/failed. | ||
578 | */ | ||
579 | static void | ||
580 | bfa_pport_sm_iocdown(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
581 | { | ||
582 | bfa_trc(pport->bfa, event); | ||
583 | |||
584 | switch (event) { | ||
585 | case BFA_PPORT_SM_START: | ||
586 | if (bfa_pport_send_enable(pport)) | ||
587 | bfa_sm_set_state(pport, bfa_pport_sm_enabling); | ||
588 | else | ||
589 | bfa_sm_set_state(pport, bfa_pport_sm_enabling_qwait); | ||
590 | break; | ||
591 | |||
592 | default: | ||
593 | /** | ||
594 | * Ignore all events. | ||
595 | */ | ||
596 | ; | ||
597 | } | ||
598 | } | ||
599 | |||
600 | /** | ||
601 | * Port is disabled. IOC is down/failed. | ||
602 | */ | ||
603 | static void | ||
604 | bfa_pport_sm_iocfail(struct bfa_pport_s *pport, enum bfa_pport_sm_event event) | ||
605 | { | ||
606 | bfa_trc(pport->bfa, event); | ||
607 | |||
608 | switch (event) { | ||
609 | case BFA_PPORT_SM_START: | ||
610 | bfa_sm_set_state(pport, bfa_pport_sm_disabled); | ||
611 | break; | ||
612 | |||
613 | case BFA_PPORT_SM_ENABLE: | ||
614 | bfa_sm_set_state(pport, bfa_pport_sm_iocdown); | ||
615 | break; | ||
616 | |||
617 | default: | ||
618 | /** | ||
619 | * Ignore all events. | ||
620 | */ | ||
621 | ; | ||
622 | } | ||
623 | } | ||
624 | |||
625 | |||
626 | |||
627 | /** | ||
628 | * bfa_pport_private | ||
629 | */ | ||
630 | |||
631 | static void | ||
632 | __bfa_cb_port_event(void *cbarg, bfa_boolean_t complete) | ||
633 | { | ||
634 | struct bfa_pport_s *pport = cbarg; | ||
635 | |||
636 | if (complete) | ||
637 | pport->event_cbfn(pport->event_cbarg, pport->hcb_event); | ||
638 | } | ||
639 | |||
640 | #define PPORT_STATS_DMA_SZ (BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), \ | ||
641 | BFA_CACHELINE_SZ)) | ||
642 | |||
643 | static void | ||
644 | bfa_pport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, | ||
645 | u32 *dm_len) | ||
646 | { | ||
647 | *dm_len += PPORT_STATS_DMA_SZ; | ||
648 | } | ||
649 | |||
650 | static void | ||
651 | bfa_pport_qresume(void *cbarg) | ||
652 | { | ||
653 | struct bfa_pport_s *port = cbarg; | ||
654 | |||
655 | bfa_sm_send_event(port, BFA_PPORT_SM_QRESUME); | ||
656 | } | ||
657 | |||
658 | static void | ||
659 | bfa_pport_mem_claim(struct bfa_pport_s *pport, struct bfa_meminfo_s *meminfo) | ||
660 | { | ||
661 | u8 *dm_kva; | ||
662 | u64 dm_pa; | ||
663 | |||
664 | dm_kva = bfa_meminfo_dma_virt(meminfo); | ||
665 | dm_pa = bfa_meminfo_dma_phys(meminfo); | ||
666 | |||
667 | pport->stats_kva = dm_kva; | ||
668 | pport->stats_pa = dm_pa; | ||
669 | pport->stats = (union bfa_pport_stats_u *)dm_kva; | ||
670 | |||
671 | dm_kva += PPORT_STATS_DMA_SZ; | ||
672 | dm_pa += PPORT_STATS_DMA_SZ; | ||
673 | |||
674 | bfa_meminfo_dma_virt(meminfo) = dm_kva; | ||
675 | bfa_meminfo_dma_phys(meminfo) = dm_pa; | ||
676 | } | ||
677 | |||
678 | /** | ||
679 | * Memory initialization. | ||
680 | */ | ||
681 | static void | ||
682 | bfa_pport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
683 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
684 | { | ||
685 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
686 | struct bfa_pport_cfg_s *port_cfg = &pport->cfg; | ||
687 | |||
688 | bfa_os_memset(pport, 0, sizeof(struct bfa_pport_s)); | ||
689 | pport->bfa = bfa; | ||
690 | |||
691 | bfa_pport_mem_claim(pport, meminfo); | ||
692 | |||
693 | bfa_sm_set_state(pport, bfa_pport_sm_uninit); | ||
694 | |||
695 | /** | ||
696 | * initialize and set default configuration | ||
697 | */ | ||
698 | port_cfg->topology = BFA_PPORT_TOPOLOGY_P2P; | ||
699 | port_cfg->speed = BFA_PPORT_SPEED_AUTO; | ||
700 | port_cfg->trunked = BFA_FALSE; | ||
701 | port_cfg->maxfrsize = 0; | ||
702 | |||
703 | port_cfg->trl_def_speed = BFA_PPORT_SPEED_1GBPS; | ||
704 | |||
705 | bfa_reqq_winit(&pport->reqq_wait, bfa_pport_qresume, pport); | ||
706 | } | ||
707 | |||
708 | static void | ||
709 | bfa_pport_initdone(struct bfa_s *bfa) | ||
710 | { | ||
711 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
712 | |||
713 | /** | ||
714 | * Initialize port attributes from IOC hardware data. | ||
715 | */ | ||
716 | bfa_pport_set_wwns(pport); | ||
717 | if (pport->cfg.maxfrsize == 0) | ||
718 | pport->cfg.maxfrsize = bfa_ioc_maxfrsize(&bfa->ioc); | ||
719 | pport->cfg.rx_bbcredit = bfa_ioc_rx_bbcredit(&bfa->ioc); | ||
720 | pport->speed_sup = bfa_ioc_speed_sup(&bfa->ioc); | ||
721 | |||
722 | bfa_assert(pport->cfg.maxfrsize); | ||
723 | bfa_assert(pport->cfg.rx_bbcredit); | ||
724 | bfa_assert(pport->speed_sup); | ||
725 | } | ||
726 | |||
727 | static void | ||
728 | bfa_pport_detach(struct bfa_s *bfa) | ||
729 | { | ||
730 | } | ||
731 | |||
732 | /** | ||
733 | * Called when IOC is ready. | ||
734 | */ | ||
735 | static void | ||
736 | bfa_pport_start(struct bfa_s *bfa) | ||
737 | { | ||
738 | bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_START); | ||
739 | } | ||
740 | |||
741 | /** | ||
742 | * Called before IOC is stopped. | ||
743 | */ | ||
744 | static void | ||
745 | bfa_pport_stop(struct bfa_s *bfa) | ||
746 | { | ||
747 | bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_STOP); | ||
748 | } | ||
749 | |||
750 | /** | ||
751 | * Called when IOC failure is detected. | ||
752 | */ | ||
753 | static void | ||
754 | bfa_pport_iocdisable(struct bfa_s *bfa) | ||
755 | { | ||
756 | bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_HWFAIL); | ||
757 | } | ||
758 | |||
759 | static void | ||
760 | bfa_pport_update_linkinfo(struct bfa_pport_s *pport) | ||
761 | { | ||
762 | struct bfi_pport_event_s *pevent = pport->event_arg.i2hmsg.event; | ||
763 | |||
764 | pport->speed = pevent->link_state.speed; | ||
765 | pport->topology = pevent->link_state.topology; | ||
766 | |||
767 | if (pport->topology == BFA_PPORT_TOPOLOGY_LOOP) | ||
768 | pport->myalpa = pevent->link_state.tl.loop_info.myalpa; | ||
769 | |||
770 | /* | ||
771 | * QoS Details | ||
772 | */ | ||
773 | bfa_os_assign(pport->qos_attr, pevent->link_state.qos_attr); | ||
774 | bfa_os_assign(pport->qos_vc_attr, pevent->link_state.qos_vc_attr); | ||
775 | |||
776 | bfa_trc(pport->bfa, pport->speed); | ||
777 | bfa_trc(pport->bfa, pport->topology); | ||
778 | } | ||
779 | |||
780 | static void | ||
781 | bfa_pport_reset_linkinfo(struct bfa_pport_s *pport) | ||
782 | { | ||
783 | pport->speed = BFA_PPORT_SPEED_UNKNOWN; | ||
784 | pport->topology = BFA_PPORT_TOPOLOGY_NONE; | ||
785 | } | ||
786 | |||
787 | /** | ||
788 | * Send port enable message to firmware. | ||
789 | */ | ||
790 | static bfa_boolean_t | ||
791 | bfa_pport_send_enable(struct bfa_pport_s *port) | ||
792 | { | ||
793 | struct bfi_pport_enable_req_s *m; | ||
794 | |||
795 | /** | ||
796 | * Increment message tag before queue check, so that responses to old | ||
797 | * requests are discarded. | ||
798 | */ | ||
799 | port->msgtag++; | ||
800 | |||
801 | /** | ||
802 | * check for room in queue to send request now | ||
803 | */ | ||
804 | m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT); | ||
805 | if (!m) { | ||
806 | bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait); | ||
807 | return BFA_FALSE; | ||
808 | } | ||
809 | |||
810 | bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_ENABLE_REQ, | ||
811 | bfa_lpuid(port->bfa)); | ||
812 | m->nwwn = port->nwwn; | ||
813 | m->pwwn = port->pwwn; | ||
814 | m->port_cfg = port->cfg; | ||
815 | m->msgtag = port->msgtag; | ||
816 | m->port_cfg.maxfrsize = bfa_os_htons(port->cfg.maxfrsize); | ||
817 | bfa_dma_be_addr_set(m->stats_dma_addr, port->stats_pa); | ||
818 | bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_lo); | ||
819 | bfa_trc(port->bfa, m->stats_dma_addr.a32.addr_hi); | ||
820 | |||
821 | /** | ||
822 | * queue I/O message to firmware | ||
823 | */ | ||
824 | bfa_reqq_produce(port->bfa, BFA_REQQ_PORT); | ||
825 | return BFA_TRUE; | ||
826 | } | ||
827 | |||
828 | /** | ||
829 | * Send port disable message to firmware. | ||
830 | */ | ||
831 | static bfa_boolean_t | ||
832 | bfa_pport_send_disable(struct bfa_pport_s *port) | ||
833 | { | ||
834 | bfi_pport_disable_req_t *m; | ||
835 | |||
836 | /** | ||
837 | * Increment message tag before queue check, so that responses to old | ||
838 | * requests are discarded. | ||
839 | */ | ||
840 | port->msgtag++; | ||
841 | |||
842 | /** | ||
843 | * check for room in queue to send request now | ||
844 | */ | ||
845 | m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT); | ||
846 | if (!m) { | ||
847 | bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->reqq_wait); | ||
848 | return BFA_FALSE; | ||
849 | } | ||
850 | |||
851 | bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_DISABLE_REQ, | ||
852 | bfa_lpuid(port->bfa)); | ||
853 | m->msgtag = port->msgtag; | ||
854 | |||
855 | /** | ||
856 | * queue I/O message to firmware | ||
857 | */ | ||
858 | bfa_reqq_produce(port->bfa, BFA_REQQ_PORT); | ||
859 | |||
860 | return BFA_TRUE; | ||
861 | } | ||
862 | |||
863 | static void | ||
864 | bfa_pport_set_wwns(struct bfa_pport_s *port) | ||
865 | { | ||
866 | port->pwwn = bfa_ioc_get_pwwn(&port->bfa->ioc); | ||
867 | port->nwwn = bfa_ioc_get_nwwn(&port->bfa->ioc); | ||
868 | |||
869 | bfa_trc(port->bfa, port->pwwn); | ||
870 | bfa_trc(port->bfa, port->nwwn); | ||
871 | } | ||
872 | |||
873 | static void | ||
874 | bfa_port_send_txcredit(void *port_cbarg) | ||
875 | { | ||
876 | |||
877 | struct bfa_pport_s *port = port_cbarg; | ||
878 | struct bfi_pport_set_svc_params_req_s *m; | ||
879 | |||
880 | /** | ||
881 | * check for room in queue to send request now | ||
882 | */ | ||
883 | m = bfa_reqq_next(port->bfa, BFA_REQQ_PORT); | ||
884 | if (!m) { | ||
885 | bfa_trc(port->bfa, port->cfg.tx_bbcredit); | ||
886 | return; | ||
887 | } | ||
888 | |||
889 | bfi_h2i_set(m->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_SET_SVC_PARAMS_REQ, | ||
890 | bfa_lpuid(port->bfa)); | ||
891 | m->tx_bbcredit = bfa_os_htons((u16) port->cfg.tx_bbcredit); | ||
892 | |||
893 | /** | ||
894 | * queue I/O message to firmware | ||
895 | */ | ||
896 | bfa_reqq_produce(port->bfa, BFA_REQQ_PORT); | ||
897 | } | ||
898 | |||
899 | |||
900 | |||
901 | /** | ||
902 | * bfa_pport_public | ||
903 | */ | ||
904 | |||
905 | /** | ||
906 | * Firmware message handler. | ||
907 | */ | ||
908 | void | ||
909 | bfa_pport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) | ||
910 | { | ||
911 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
912 | union bfi_pport_i2h_msg_u i2hmsg; | ||
913 | |||
914 | i2hmsg.msg = msg; | ||
915 | pport->event_arg.i2hmsg = i2hmsg; | ||
916 | |||
917 | switch (msg->mhdr.msg_id) { | ||
918 | case BFI_PPORT_I2H_ENABLE_RSP: | ||
919 | if (pport->msgtag == i2hmsg.enable_rsp->msgtag) | ||
920 | bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP); | ||
921 | break; | ||
922 | |||
923 | case BFI_PPORT_I2H_DISABLE_RSP: | ||
924 | if (pport->msgtag == i2hmsg.enable_rsp->msgtag) | ||
925 | bfa_sm_send_event(pport, BFA_PPORT_SM_FWRSP); | ||
926 | break; | ||
927 | |||
928 | case BFI_PPORT_I2H_EVENT: | ||
929 | switch (i2hmsg.event->link_state.linkstate) { | ||
930 | case BFA_PPORT_LINKUP: | ||
931 | bfa_sm_send_event(pport, BFA_PPORT_SM_LINKUP); | ||
932 | break; | ||
933 | case BFA_PPORT_LINKDOWN: | ||
934 | bfa_sm_send_event(pport, BFA_PPORT_SM_LINKDOWN); | ||
935 | break; | ||
936 | case BFA_PPORT_TRUNK_LINKDOWN: | ||
937 | /** todo: event notification */ | ||
938 | break; | ||
939 | } | ||
940 | break; | ||
941 | |||
942 | case BFI_PPORT_I2H_GET_STATS_RSP: | ||
943 | case BFI_PPORT_I2H_GET_QOS_STATS_RSP: | ||
944 | /* | ||
945 | * check for timer pop before processing the rsp | ||
946 | */ | ||
947 | if (pport->stats_busy == BFA_FALSE | ||
948 | || pport->stats_status == BFA_STATUS_ETIMER) | ||
949 | break; | ||
950 | |||
951 | bfa_timer_stop(&pport->timer); | ||
952 | pport->stats_status = i2hmsg.getstats_rsp->status; | ||
953 | bfa_cb_queue(pport->bfa, &pport->hcb_qe, __bfa_cb_port_stats, | ||
954 | pport); | ||
955 | break; | ||
956 | case BFI_PPORT_I2H_CLEAR_STATS_RSP: | ||
957 | case BFI_PPORT_I2H_CLEAR_QOS_STATS_RSP: | ||
958 | /* | ||
959 | * check for timer pop before processing the rsp | ||
960 | */ | ||
961 | if (pport->stats_busy == BFA_FALSE | ||
962 | || pport->stats_status == BFA_STATUS_ETIMER) | ||
963 | break; | ||
964 | |||
965 | bfa_timer_stop(&pport->timer); | ||
966 | pport->stats_status = BFA_STATUS_OK; | ||
967 | bfa_cb_queue(pport->bfa, &pport->hcb_qe, | ||
968 | __bfa_cb_port_stats_clr, pport); | ||
969 | break; | ||
970 | |||
971 | default: | ||
972 | bfa_assert(0); | ||
973 | } | ||
974 | } | ||
975 | |||
976 | |||
977 | |||
978 | /** | ||
979 | * bfa_pport_api | ||
980 | */ | ||
981 | |||
982 | /** | ||
983 | * Registered callback for port events. | ||
984 | */ | ||
985 | void | ||
986 | bfa_pport_event_register(struct bfa_s *bfa, | ||
987 | void (*cbfn) (void *cbarg, bfa_pport_event_t event), | ||
988 | void *cbarg) | ||
989 | { | ||
990 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
991 | |||
992 | pport->event_cbfn = cbfn; | ||
993 | pport->event_cbarg = cbarg; | ||
994 | } | ||
995 | |||
996 | bfa_status_t | ||
997 | bfa_pport_enable(struct bfa_s *bfa) | ||
998 | { | ||
999 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1000 | |||
1001 | if (pport->diag_busy) | ||
1002 | return (BFA_STATUS_DIAG_BUSY); | ||
1003 | else if (bfa_sm_cmp_state | ||
1004 | (BFA_PORT_MOD(bfa), bfa_pport_sm_disabling_qwait)) | ||
1005 | return (BFA_STATUS_DEVBUSY); | ||
1006 | |||
1007 | bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_ENABLE); | ||
1008 | return BFA_STATUS_OK; | ||
1009 | } | ||
1010 | |||
1011 | bfa_status_t | ||
1012 | bfa_pport_disable(struct bfa_s *bfa) | ||
1013 | { | ||
1014 | bfa_sm_send_event(BFA_PORT_MOD(bfa), BFA_PPORT_SM_DISABLE); | ||
1015 | return BFA_STATUS_OK; | ||
1016 | } | ||
1017 | |||
1018 | /** | ||
1019 | * Configure port speed. | ||
1020 | */ | ||
1021 | bfa_status_t | ||
1022 | bfa_pport_cfg_speed(struct bfa_s *bfa, enum bfa_pport_speed speed) | ||
1023 | { | ||
1024 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1025 | |||
1026 | bfa_trc(bfa, speed); | ||
1027 | |||
1028 | if ((speed != BFA_PPORT_SPEED_AUTO) && (speed > pport->speed_sup)) { | ||
1029 | bfa_trc(bfa, pport->speed_sup); | ||
1030 | return BFA_STATUS_UNSUPP_SPEED; | ||
1031 | } | ||
1032 | |||
1033 | pport->cfg.speed = speed; | ||
1034 | |||
1035 | return (BFA_STATUS_OK); | ||
1036 | } | ||
1037 | |||
1038 | /** | ||
1039 | * Get current speed. | ||
1040 | */ | ||
1041 | enum bfa_pport_speed | ||
1042 | bfa_pport_get_speed(struct bfa_s *bfa) | ||
1043 | { | ||
1044 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1045 | |||
1046 | return port->speed; | ||
1047 | } | ||
1048 | |||
1049 | /** | ||
1050 | * Configure port topology. | ||
1051 | */ | ||
1052 | bfa_status_t | ||
1053 | bfa_pport_cfg_topology(struct bfa_s *bfa, enum bfa_pport_topology topology) | ||
1054 | { | ||
1055 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1056 | |||
1057 | bfa_trc(bfa, topology); | ||
1058 | bfa_trc(bfa, pport->cfg.topology); | ||
1059 | |||
1060 | switch (topology) { | ||
1061 | case BFA_PPORT_TOPOLOGY_P2P: | ||
1062 | case BFA_PPORT_TOPOLOGY_LOOP: | ||
1063 | case BFA_PPORT_TOPOLOGY_AUTO: | ||
1064 | break; | ||
1065 | |||
1066 | default: | ||
1067 | return BFA_STATUS_EINVAL; | ||
1068 | } | ||
1069 | |||
1070 | pport->cfg.topology = topology; | ||
1071 | return (BFA_STATUS_OK); | ||
1072 | } | ||
1073 | |||
1074 | /** | ||
1075 | * Get current topology. | ||
1076 | */ | ||
1077 | enum bfa_pport_topology | ||
1078 | bfa_pport_get_topology(struct bfa_s *bfa) | ||
1079 | { | ||
1080 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1081 | |||
1082 | return port->topology; | ||
1083 | } | ||
1084 | |||
1085 | bfa_status_t | ||
1086 | bfa_pport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa) | ||
1087 | { | ||
1088 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1089 | |||
1090 | bfa_trc(bfa, alpa); | ||
1091 | bfa_trc(bfa, pport->cfg.cfg_hardalpa); | ||
1092 | bfa_trc(bfa, pport->cfg.hardalpa); | ||
1093 | |||
1094 | pport->cfg.cfg_hardalpa = BFA_TRUE; | ||
1095 | pport->cfg.hardalpa = alpa; | ||
1096 | |||
1097 | return (BFA_STATUS_OK); | ||
1098 | } | ||
1099 | |||
1100 | bfa_status_t | ||
1101 | bfa_pport_clr_hardalpa(struct bfa_s *bfa) | ||
1102 | { | ||
1103 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1104 | |||
1105 | bfa_trc(bfa, pport->cfg.cfg_hardalpa); | ||
1106 | bfa_trc(bfa, pport->cfg.hardalpa); | ||
1107 | |||
1108 | pport->cfg.cfg_hardalpa = BFA_FALSE; | ||
1109 | return (BFA_STATUS_OK); | ||
1110 | } | ||
1111 | |||
1112 | bfa_boolean_t | ||
1113 | bfa_pport_get_hardalpa(struct bfa_s *bfa, u8 *alpa) | ||
1114 | { | ||
1115 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1116 | |||
1117 | *alpa = port->cfg.hardalpa; | ||
1118 | return port->cfg.cfg_hardalpa; | ||
1119 | } | ||
1120 | |||
1121 | u8 | ||
1122 | bfa_pport_get_myalpa(struct bfa_s *bfa) | ||
1123 | { | ||
1124 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1125 | |||
1126 | return port->myalpa; | ||
1127 | } | ||
1128 | |||
1129 | bfa_status_t | ||
1130 | bfa_pport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxfrsize) | ||
1131 | { | ||
1132 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1133 | |||
1134 | bfa_trc(bfa, maxfrsize); | ||
1135 | bfa_trc(bfa, pport->cfg.maxfrsize); | ||
1136 | |||
1137 | /* | ||
1138 | * with in range | ||
1139 | */ | ||
1140 | if ((maxfrsize > FC_MAX_PDUSZ) || (maxfrsize < FC_MIN_PDUSZ)) | ||
1141 | return (BFA_STATUS_INVLD_DFSZ); | ||
1142 | |||
1143 | /* | ||
1144 | * power of 2, if not the max frame size of 2112 | ||
1145 | */ | ||
1146 | if ((maxfrsize != FC_MAX_PDUSZ) && (maxfrsize & (maxfrsize - 1))) | ||
1147 | return (BFA_STATUS_INVLD_DFSZ); | ||
1148 | |||
1149 | pport->cfg.maxfrsize = maxfrsize; | ||
1150 | return (BFA_STATUS_OK); | ||
1151 | } | ||
1152 | |||
1153 | u16 | ||
1154 | bfa_pport_get_maxfrsize(struct bfa_s *bfa) | ||
1155 | { | ||
1156 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1157 | |||
1158 | return port->cfg.maxfrsize; | ||
1159 | } | ||
1160 | |||
1161 | u32 | ||
1162 | bfa_pport_mypid(struct bfa_s *bfa) | ||
1163 | { | ||
1164 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1165 | |||
1166 | return port->mypid; | ||
1167 | } | ||
1168 | |||
1169 | u8 | ||
1170 | bfa_pport_get_rx_bbcredit(struct bfa_s *bfa) | ||
1171 | { | ||
1172 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1173 | |||
1174 | return port->cfg.rx_bbcredit; | ||
1175 | } | ||
1176 | |||
1177 | void | ||
1178 | bfa_pport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit) | ||
1179 | { | ||
1180 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1181 | |||
1182 | port->cfg.tx_bbcredit = (u8) tx_bbcredit; | ||
1183 | bfa_port_send_txcredit(port); | ||
1184 | } | ||
1185 | |||
1186 | /** | ||
1187 | * Get port attributes. | ||
1188 | */ | ||
1189 | |||
1190 | wwn_t | ||
1191 | bfa_pport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node) | ||
1192 | { | ||
1193 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1194 | if (node) | ||
1195 | return pport->nwwn; | ||
1196 | else | ||
1197 | return pport->pwwn; | ||
1198 | } | ||
1199 | |||
1200 | void | ||
1201 | bfa_pport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr) | ||
1202 | { | ||
1203 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1204 | |||
1205 | bfa_os_memset(attr, 0, sizeof(struct bfa_pport_attr_s)); | ||
1206 | |||
1207 | attr->nwwn = pport->nwwn; | ||
1208 | attr->pwwn = pport->pwwn; | ||
1209 | |||
1210 | bfa_os_memcpy(&attr->pport_cfg, &pport->cfg, | ||
1211 | sizeof(struct bfa_pport_cfg_s)); | ||
1212 | /* | ||
1213 | * speed attributes | ||
1214 | */ | ||
1215 | attr->pport_cfg.speed = pport->cfg.speed; | ||
1216 | attr->speed_supported = pport->speed_sup; | ||
1217 | attr->speed = pport->speed; | ||
1218 | attr->cos_supported = FC_CLASS_3; | ||
1219 | |||
1220 | /* | ||
1221 | * topology attributes | ||
1222 | */ | ||
1223 | attr->pport_cfg.topology = pport->cfg.topology; | ||
1224 | attr->topology = pport->topology; | ||
1225 | |||
1226 | /* | ||
1227 | * beacon attributes | ||
1228 | */ | ||
1229 | attr->beacon = pport->beacon; | ||
1230 | attr->link_e2e_beacon = pport->link_e2e_beacon; | ||
1231 | attr->plog_enabled = bfa_plog_get_setting(pport->bfa->plog); | ||
1232 | |||
1233 | attr->pport_cfg.path_tov = bfa_fcpim_path_tov_get(bfa); | ||
1234 | attr->pport_cfg.q_depth = bfa_fcpim_qdepth_get(bfa); | ||
1235 | attr->port_state = bfa_sm_to_state(hal_pport_sm_table, pport->sm); | ||
1236 | if (bfa_ioc_is_disabled(&pport->bfa->ioc)) | ||
1237 | attr->port_state = BFA_PPORT_ST_IOCDIS; | ||
1238 | else if (bfa_ioc_fw_mismatch(&pport->bfa->ioc)) | ||
1239 | attr->port_state = BFA_PPORT_ST_FWMISMATCH; | ||
1240 | } | ||
1241 | |||
1242 | static void | ||
1243 | bfa_port_stats_query(void *cbarg) | ||
1244 | { | ||
1245 | struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg; | ||
1246 | bfi_pport_get_stats_req_t *msg; | ||
1247 | |||
1248 | msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT); | ||
1249 | |||
1250 | if (!msg) { | ||
1251 | port->stats_qfull = BFA_TRUE; | ||
1252 | bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_query, | ||
1253 | port); | ||
1254 | bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait); | ||
1255 | return; | ||
1256 | } | ||
1257 | port->stats_qfull = BFA_FALSE; | ||
1258 | |||
1259 | bfa_os_memset(msg, 0, sizeof(bfi_pport_get_stats_req_t)); | ||
1260 | bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_GET_STATS_REQ, | ||
1261 | bfa_lpuid(port->bfa)); | ||
1262 | bfa_reqq_produce(port->bfa, BFA_REQQ_PORT); | ||
1263 | |||
1264 | return; | ||
1265 | } | ||
1266 | |||
1267 | static void | ||
1268 | bfa_port_stats_clear(void *cbarg) | ||
1269 | { | ||
1270 | struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg; | ||
1271 | bfi_pport_clear_stats_req_t *msg; | ||
1272 | |||
1273 | msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT); | ||
1274 | |||
1275 | if (!msg) { | ||
1276 | port->stats_qfull = BFA_TRUE; | ||
1277 | bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_stats_clear, | ||
1278 | port); | ||
1279 | bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait); | ||
1280 | return; | ||
1281 | } | ||
1282 | port->stats_qfull = BFA_FALSE; | ||
1283 | |||
1284 | bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_stats_req_t)); | ||
1285 | bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_STATS_REQ, | ||
1286 | bfa_lpuid(port->bfa)); | ||
1287 | bfa_reqq_produce(port->bfa, BFA_REQQ_PORT); | ||
1288 | return; | ||
1289 | } | ||
1290 | |||
1291 | static void | ||
1292 | bfa_port_qos_stats_clear(void *cbarg) | ||
1293 | { | ||
1294 | struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg; | ||
1295 | bfi_pport_clear_qos_stats_req_t *msg; | ||
1296 | |||
1297 | msg = bfa_reqq_next(port->bfa, BFA_REQQ_PORT); | ||
1298 | |||
1299 | if (!msg) { | ||
1300 | port->stats_qfull = BFA_TRUE; | ||
1301 | bfa_reqq_winit(&port->stats_reqq_wait, bfa_port_qos_stats_clear, | ||
1302 | port); | ||
1303 | bfa_reqq_wait(port->bfa, BFA_REQQ_PORT, &port->stats_reqq_wait); | ||
1304 | return; | ||
1305 | } | ||
1306 | port->stats_qfull = BFA_FALSE; | ||
1307 | |||
1308 | bfa_os_memset(msg, 0, sizeof(bfi_pport_clear_qos_stats_req_t)); | ||
1309 | bfi_h2i_set(msg->mh, BFI_MC_FC_PORT, BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ, | ||
1310 | bfa_lpuid(port->bfa)); | ||
1311 | bfa_reqq_produce(port->bfa, BFA_REQQ_PORT); | ||
1312 | return; | ||
1313 | } | ||
1314 | |||
1315 | static void | ||
1316 | bfa_pport_stats_swap(union bfa_pport_stats_u *d, union bfa_pport_stats_u *s) | ||
1317 | { | ||
1318 | u32 *dip = (u32 *) d; | ||
1319 | u32 *sip = (u32 *) s; | ||
1320 | int i; | ||
1321 | |||
1322 | /* | ||
1323 | * Do 64 bit fields swap first | ||
1324 | */ | ||
1325 | for (i = 0; | ||
1326 | i < | ||
1327 | ((sizeof(union bfa_pport_stats_u) - | ||
1328 | sizeof(struct bfa_qos_stats_s)) / sizeof(u32)); i = i + 2) { | ||
1329 | #ifdef __BIGENDIAN | ||
1330 | dip[i] = bfa_os_ntohl(sip[i]); | ||
1331 | dip[i + 1] = bfa_os_ntohl(sip[i + 1]); | ||
1332 | #else | ||
1333 | dip[i] = bfa_os_ntohl(sip[i + 1]); | ||
1334 | dip[i + 1] = bfa_os_ntohl(sip[i]); | ||
1335 | #endif | ||
1336 | } | ||
1337 | |||
1338 | /* | ||
1339 | * Now swap the 32 bit fields | ||
1340 | */ | ||
1341 | for (; i < (sizeof(union bfa_pport_stats_u) / sizeof(u32)); ++i) | ||
1342 | dip[i] = bfa_os_ntohl(sip[i]); | ||
1343 | } | ||
1344 | |||
1345 | static void | ||
1346 | __bfa_cb_port_stats_clr(void *cbarg, bfa_boolean_t complete) | ||
1347 | { | ||
1348 | struct bfa_pport_s *port = cbarg; | ||
1349 | |||
1350 | if (complete) { | ||
1351 | port->stats_cbfn(port->stats_cbarg, port->stats_status); | ||
1352 | } else { | ||
1353 | port->stats_busy = BFA_FALSE; | ||
1354 | port->stats_status = BFA_STATUS_OK; | ||
1355 | } | ||
1356 | } | ||
1357 | |||
1358 | static void | ||
1359 | bfa_port_stats_clr_timeout(void *cbarg) | ||
1360 | { | ||
1361 | struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg; | ||
1362 | |||
1363 | bfa_trc(port->bfa, port->stats_qfull); | ||
1364 | |||
1365 | if (port->stats_qfull) { | ||
1366 | bfa_reqq_wcancel(&port->stats_reqq_wait); | ||
1367 | port->stats_qfull = BFA_FALSE; | ||
1368 | } | ||
1369 | |||
1370 | port->stats_status = BFA_STATUS_ETIMER; | ||
1371 | bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats_clr, port); | ||
1372 | } | ||
1373 | |||
1374 | static void | ||
1375 | __bfa_cb_port_stats(void *cbarg, bfa_boolean_t complete) | ||
1376 | { | ||
1377 | struct bfa_pport_s *port = cbarg; | ||
1378 | |||
1379 | if (complete) { | ||
1380 | if (port->stats_status == BFA_STATUS_OK) | ||
1381 | bfa_pport_stats_swap(port->stats_ret, port->stats); | ||
1382 | port->stats_cbfn(port->stats_cbarg, port->stats_status); | ||
1383 | } else { | ||
1384 | port->stats_busy = BFA_FALSE; | ||
1385 | port->stats_status = BFA_STATUS_OK; | ||
1386 | } | ||
1387 | } | ||
1388 | |||
1389 | static void | ||
1390 | bfa_port_stats_timeout(void *cbarg) | ||
1391 | { | ||
1392 | struct bfa_pport_s *port = (struct bfa_pport_s *)cbarg; | ||
1393 | |||
1394 | bfa_trc(port->bfa, port->stats_qfull); | ||
1395 | |||
1396 | if (port->stats_qfull) { | ||
1397 | bfa_reqq_wcancel(&port->stats_reqq_wait); | ||
1398 | port->stats_qfull = BFA_FALSE; | ||
1399 | } | ||
1400 | |||
1401 | port->stats_status = BFA_STATUS_ETIMER; | ||
1402 | bfa_cb_queue(port->bfa, &port->hcb_qe, __bfa_cb_port_stats, port); | ||
1403 | } | ||
1404 | |||
1405 | #define BFA_PORT_STATS_TOV 1000 | ||
1406 | |||
1407 | /** | ||
1408 | * Fetch port attributes. | ||
1409 | */ | ||
1410 | bfa_status_t | ||
1411 | bfa_pport_get_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats, | ||
1412 | bfa_cb_pport_t cbfn, void *cbarg) | ||
1413 | { | ||
1414 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1415 | |||
1416 | if (port->stats_busy) { | ||
1417 | bfa_trc(bfa, port->stats_busy); | ||
1418 | return (BFA_STATUS_DEVBUSY); | ||
1419 | } | ||
1420 | |||
1421 | port->stats_busy = BFA_TRUE; | ||
1422 | port->stats_ret = stats; | ||
1423 | port->stats_cbfn = cbfn; | ||
1424 | port->stats_cbarg = cbarg; | ||
1425 | |||
1426 | bfa_port_stats_query(port); | ||
1427 | |||
1428 | bfa_timer_start(bfa, &port->timer, bfa_port_stats_timeout, port, | ||
1429 | BFA_PORT_STATS_TOV); | ||
1430 | return (BFA_STATUS_OK); | ||
1431 | } | ||
1432 | |||
1433 | bfa_status_t | ||
1434 | bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg) | ||
1435 | { | ||
1436 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1437 | |||
1438 | if (port->stats_busy) { | ||
1439 | bfa_trc(bfa, port->stats_busy); | ||
1440 | return (BFA_STATUS_DEVBUSY); | ||
1441 | } | ||
1442 | |||
1443 | port->stats_busy = BFA_TRUE; | ||
1444 | port->stats_cbfn = cbfn; | ||
1445 | port->stats_cbarg = cbarg; | ||
1446 | |||
1447 | bfa_port_stats_clear(port); | ||
1448 | |||
1449 | bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port, | ||
1450 | BFA_PORT_STATS_TOV); | ||
1451 | return (BFA_STATUS_OK); | ||
1452 | } | ||
1453 | |||
1454 | bfa_status_t | ||
1455 | bfa_pport_trunk_enable(struct bfa_s *bfa, u8 bitmap) | ||
1456 | { | ||
1457 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1458 | |||
1459 | bfa_trc(bfa, bitmap); | ||
1460 | bfa_trc(bfa, pport->cfg.trunked); | ||
1461 | bfa_trc(bfa, pport->cfg.trunk_ports); | ||
1462 | |||
1463 | if (!bitmap || (bitmap & (bitmap - 1))) | ||
1464 | return BFA_STATUS_EINVAL; | ||
1465 | |||
1466 | pport->cfg.trunked = BFA_TRUE; | ||
1467 | pport->cfg.trunk_ports = bitmap; | ||
1468 | |||
1469 | return BFA_STATUS_OK; | ||
1470 | } | ||
1471 | |||
1472 | void | ||
1473 | bfa_pport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr) | ||
1474 | { | ||
1475 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1476 | |||
1477 | qos_attr->state = bfa_os_ntohl(pport->qos_attr.state); | ||
1478 | qos_attr->total_bb_cr = bfa_os_ntohl(pport->qos_attr.total_bb_cr); | ||
1479 | } | ||
1480 | |||
1481 | void | ||
1482 | bfa_pport_qos_get_vc_attr(struct bfa_s *bfa, | ||
1483 | struct bfa_qos_vc_attr_s *qos_vc_attr) | ||
1484 | { | ||
1485 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1486 | struct bfa_qos_vc_attr_s *bfa_vc_attr = &pport->qos_vc_attr; | ||
1487 | u32 i = 0; | ||
1488 | |||
1489 | qos_vc_attr->total_vc_count = bfa_os_ntohs(bfa_vc_attr->total_vc_count); | ||
1490 | qos_vc_attr->shared_credit = bfa_os_ntohs(bfa_vc_attr->shared_credit); | ||
1491 | qos_vc_attr->elp_opmode_flags = | ||
1492 | bfa_os_ntohl(bfa_vc_attr->elp_opmode_flags); | ||
1493 | |||
1494 | /* | ||
1495 | * Individual VC info | ||
1496 | */ | ||
1497 | while (i < qos_vc_attr->total_vc_count) { | ||
1498 | qos_vc_attr->vc_info[i].vc_credit = | ||
1499 | bfa_vc_attr->vc_info[i].vc_credit; | ||
1500 | qos_vc_attr->vc_info[i].borrow_credit = | ||
1501 | bfa_vc_attr->vc_info[i].borrow_credit; | ||
1502 | qos_vc_attr->vc_info[i].priority = | ||
1503 | bfa_vc_attr->vc_info[i].priority; | ||
1504 | ++i; | ||
1505 | } | ||
1506 | } | ||
1507 | |||
1508 | /** | ||
1509 | * Fetch QoS Stats. | ||
1510 | */ | ||
1511 | bfa_status_t | ||
1512 | bfa_pport_get_qos_stats(struct bfa_s *bfa, union bfa_pport_stats_u *stats, | ||
1513 | bfa_cb_pport_t cbfn, void *cbarg) | ||
1514 | { | ||
1515 | /* | ||
1516 | * QoS stats is embedded in port stats | ||
1517 | */ | ||
1518 | return (bfa_pport_get_stats(bfa, stats, cbfn, cbarg)); | ||
1519 | } | ||
1520 | |||
1521 | bfa_status_t | ||
1522 | bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, void *cbarg) | ||
1523 | { | ||
1524 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1525 | |||
1526 | if (port->stats_busy) { | ||
1527 | bfa_trc(bfa, port->stats_busy); | ||
1528 | return (BFA_STATUS_DEVBUSY); | ||
1529 | } | ||
1530 | |||
1531 | port->stats_busy = BFA_TRUE; | ||
1532 | port->stats_cbfn = cbfn; | ||
1533 | port->stats_cbarg = cbarg; | ||
1534 | |||
1535 | bfa_port_qos_stats_clear(port); | ||
1536 | |||
1537 | bfa_timer_start(bfa, &port->timer, bfa_port_stats_clr_timeout, port, | ||
1538 | BFA_PORT_STATS_TOV); | ||
1539 | return (BFA_STATUS_OK); | ||
1540 | } | ||
1541 | |||
1542 | /** | ||
1543 | * Fetch port attributes. | ||
1544 | */ | ||
1545 | bfa_status_t | ||
1546 | bfa_pport_trunk_disable(struct bfa_s *bfa) | ||
1547 | { | ||
1548 | return (BFA_STATUS_OK); | ||
1549 | } | ||
1550 | |||
1551 | bfa_boolean_t | ||
1552 | bfa_pport_trunk_query(struct bfa_s *bfa, u32 *bitmap) | ||
1553 | { | ||
1554 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1555 | |||
1556 | *bitmap = port->cfg.trunk_ports; | ||
1557 | return port->cfg.trunked; | ||
1558 | } | ||
1559 | |||
1560 | bfa_boolean_t | ||
1561 | bfa_pport_is_disabled(struct bfa_s *bfa) | ||
1562 | { | ||
1563 | struct bfa_pport_s *port = BFA_PORT_MOD(bfa); | ||
1564 | |||
1565 | return (bfa_sm_to_state(hal_pport_sm_table, port->sm) == | ||
1566 | BFA_PPORT_ST_DISABLED); | ||
1567 | |||
1568 | } | ||
1569 | |||
1570 | bfa_boolean_t | ||
1571 | bfa_pport_is_ratelim(struct bfa_s *bfa) | ||
1572 | { | ||
1573 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1574 | |||
1575 | return (pport->cfg.ratelimit ? BFA_TRUE : BFA_FALSE); | ||
1576 | |||
1577 | } | ||
1578 | |||
1579 | void | ||
1580 | bfa_pport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off) | ||
1581 | { | ||
1582 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1583 | |||
1584 | bfa_trc(bfa, on_off); | ||
1585 | bfa_trc(bfa, pport->cfg.qos_enabled); | ||
1586 | |||
1587 | pport->cfg.qos_enabled = on_off; | ||
1588 | } | ||
1589 | |||
1590 | void | ||
1591 | bfa_pport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off) | ||
1592 | { | ||
1593 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1594 | |||
1595 | bfa_trc(bfa, on_off); | ||
1596 | bfa_trc(bfa, pport->cfg.ratelimit); | ||
1597 | |||
1598 | pport->cfg.ratelimit = on_off; | ||
1599 | if (pport->cfg.trl_def_speed == BFA_PPORT_SPEED_UNKNOWN) | ||
1600 | pport->cfg.trl_def_speed = BFA_PPORT_SPEED_1GBPS; | ||
1601 | } | ||
1602 | |||
1603 | /** | ||
1604 | * Configure default minimum ratelim speed | ||
1605 | */ | ||
1606 | bfa_status_t | ||
1607 | bfa_pport_cfg_ratelim_speed(struct bfa_s *bfa, enum bfa_pport_speed speed) | ||
1608 | { | ||
1609 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1610 | |||
1611 | bfa_trc(bfa, speed); | ||
1612 | |||
1613 | /* | ||
1614 | * Auto and speeds greater than the supported speed, are invalid | ||
1615 | */ | ||
1616 | if ((speed == BFA_PPORT_SPEED_AUTO) || (speed > pport->speed_sup)) { | ||
1617 | bfa_trc(bfa, pport->speed_sup); | ||
1618 | return BFA_STATUS_UNSUPP_SPEED; | ||
1619 | } | ||
1620 | |||
1621 | pport->cfg.trl_def_speed = speed; | ||
1622 | |||
1623 | return (BFA_STATUS_OK); | ||
1624 | } | ||
1625 | |||
1626 | /** | ||
1627 | * Get default minimum ratelim speed | ||
1628 | */ | ||
1629 | enum bfa_pport_speed | ||
1630 | bfa_pport_get_ratelim_speed(struct bfa_s *bfa) | ||
1631 | { | ||
1632 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1633 | |||
1634 | bfa_trc(bfa, pport->cfg.trl_def_speed); | ||
1635 | return (pport->cfg.trl_def_speed); | ||
1636 | |||
1637 | } | ||
1638 | |||
1639 | void | ||
1640 | bfa_pport_busy(struct bfa_s *bfa, bfa_boolean_t status) | ||
1641 | { | ||
1642 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1643 | |||
1644 | bfa_trc(bfa, status); | ||
1645 | bfa_trc(bfa, pport->diag_busy); | ||
1646 | |||
1647 | pport->diag_busy = status; | ||
1648 | } | ||
1649 | |||
1650 | void | ||
1651 | bfa_pport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon, | ||
1652 | bfa_boolean_t link_e2e_beacon) | ||
1653 | { | ||
1654 | struct bfa_pport_s *pport = BFA_PORT_MOD(bfa); | ||
1655 | |||
1656 | bfa_trc(bfa, beacon); | ||
1657 | bfa_trc(bfa, link_e2e_beacon); | ||
1658 | bfa_trc(bfa, pport->beacon); | ||
1659 | bfa_trc(bfa, pport->link_e2e_beacon); | ||
1660 | |||
1661 | pport->beacon = beacon; | ||
1662 | pport->link_e2e_beacon = link_e2e_beacon; | ||
1663 | } | ||
1664 | |||
1665 | bfa_boolean_t | ||
1666 | bfa_pport_is_linkup(struct bfa_s *bfa) | ||
1667 | { | ||
1668 | return bfa_sm_cmp_state(BFA_PORT_MOD(bfa), bfa_pport_sm_linkup); | ||
1669 | } | ||
1670 | |||
1671 | |||
diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c new file mode 100644 index 000000000000..7cb39a306ea9 --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcs.c | |||
@@ -0,0 +1,182 @@ | |||
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 | * bfa_fcs.c BFA FCS main | ||
20 | */ | ||
21 | |||
22 | #include <fcs/bfa_fcs.h> | ||
23 | #include "fcs_port.h" | ||
24 | #include "fcs_uf.h" | ||
25 | #include "fcs_vport.h" | ||
26 | #include "fcs_rport.h" | ||
27 | #include "fcs_fabric.h" | ||
28 | #include "fcs_fcpim.h" | ||
29 | #include "fcs_fcptm.h" | ||
30 | #include "fcbuild.h" | ||
31 | #include "fcs.h" | ||
32 | #include "bfad_drv.h" | ||
33 | #include <fcb/bfa_fcb.h> | ||
34 | |||
35 | /** | ||
36 | * FCS sub-modules | ||
37 | */ | ||
38 | struct bfa_fcs_mod_s { | ||
39 | void (*modinit) (struct bfa_fcs_s *fcs); | ||
40 | void (*modexit) (struct bfa_fcs_s *fcs); | ||
41 | }; | ||
42 | |||
43 | #define BFA_FCS_MODULE(_mod) { _mod ## _modinit, _mod ## _modexit } | ||
44 | |||
45 | static struct bfa_fcs_mod_s fcs_modules[] = { | ||
46 | BFA_FCS_MODULE(bfa_fcs_pport), | ||
47 | BFA_FCS_MODULE(bfa_fcs_uf), | ||
48 | BFA_FCS_MODULE(bfa_fcs_fabric), | ||
49 | BFA_FCS_MODULE(bfa_fcs_vport), | ||
50 | BFA_FCS_MODULE(bfa_fcs_rport), | ||
51 | BFA_FCS_MODULE(bfa_fcs_fcpim), | ||
52 | }; | ||
53 | |||
54 | /** | ||
55 | * fcs_api BFA FCS API | ||
56 | */ | ||
57 | |||
58 | static void | ||
59 | bfa_fcs_exit_comp(void *fcs_cbarg) | ||
60 | { | ||
61 | struct bfa_fcs_s *fcs = fcs_cbarg; | ||
62 | struct bfad_s *bfad = fcs->bfad; | ||
63 | |||
64 | complete(&bfad->comp); | ||
65 | } | ||
66 | |||
67 | |||
68 | |||
69 | /** | ||
70 | * fcs_api BFA FCS API | ||
71 | */ | ||
72 | |||
73 | /** | ||
74 | * FCS instance initialization. | ||
75 | * | ||
76 | * param[in] fcs FCS instance | ||
77 | * param[in] bfa BFA instance | ||
78 | * param[in] bfad BFA driver instance | ||
79 | * | ||
80 | * return None | ||
81 | */ | ||
82 | void | ||
83 | bfa_fcs_init(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, | ||
84 | bfa_boolean_t min_cfg) | ||
85 | { | ||
86 | int i; | ||
87 | struct bfa_fcs_mod_s *mod; | ||
88 | |||
89 | fcs->bfa = bfa; | ||
90 | fcs->bfad = bfad; | ||
91 | fcs->min_cfg = min_cfg; | ||
92 | |||
93 | bfa_attach_fcs(bfa); | ||
94 | fcbuild_init(); | ||
95 | |||
96 | for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { | ||
97 | mod = &fcs_modules[i]; | ||
98 | mod->modinit(fcs); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Start FCS operations. | ||
104 | */ | ||
105 | void | ||
106 | bfa_fcs_start(struct bfa_fcs_s *fcs) | ||
107 | { | ||
108 | bfa_fcs_fabric_modstart(fcs); | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * FCS driver details initialization. | ||
113 | * | ||
114 | * param[in] fcs FCS instance | ||
115 | * param[in] driver_info Driver Details | ||
116 | * | ||
117 | * return None | ||
118 | */ | ||
119 | void | ||
120 | bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, | ||
121 | struct bfa_fcs_driver_info_s *driver_info) | ||
122 | { | ||
123 | |||
124 | fcs->driver_info = *driver_info; | ||
125 | |||
126 | bfa_fcs_fabric_psymb_init(&fcs->fabric); | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * FCS instance cleanup and exit. | ||
131 | * | ||
132 | * param[in] fcs FCS instance | ||
133 | * return None | ||
134 | */ | ||
135 | void | ||
136 | bfa_fcs_exit(struct bfa_fcs_s *fcs) | ||
137 | { | ||
138 | struct bfa_fcs_mod_s *mod; | ||
139 | int nmods, i; | ||
140 | |||
141 | bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); | ||
142 | |||
143 | nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]); | ||
144 | |||
145 | for (i = 0; i < nmods; i++) { | ||
146 | bfa_wc_up(&fcs->wc); | ||
147 | |||
148 | mod = &fcs_modules[i]; | ||
149 | mod->modexit(fcs); | ||
150 | } | ||
151 | |||
152 | bfa_wc_wait(&fcs->wc); | ||
153 | } | ||
154 | |||
155 | |||
156 | void | ||
157 | bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod) | ||
158 | { | ||
159 | fcs->trcmod = trcmod; | ||
160 | } | ||
161 | |||
162 | |||
163 | void | ||
164 | bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod) | ||
165 | { | ||
166 | fcs->logm = logmod; | ||
167 | } | ||
168 | |||
169 | |||
170 | void | ||
171 | bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen) | ||
172 | { | ||
173 | fcs->aen = aen; | ||
174 | } | ||
175 | |||
176 | void | ||
177 | bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs) | ||
178 | { | ||
179 | bfa_wc_down(&fcs->wc); | ||
180 | } | ||
181 | |||
182 | |||
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c new file mode 100644 index 000000000000..8975ed041dc0 --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcs_lport.c | |||
@@ -0,0 +1,940 @@ | |||
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 | * bfa_fcs_port.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 <fcb/bfa_fcb_port.h> | ||
26 | #include <bfa_svc.h> | ||
27 | #include <log/bfa_log_fcs.h> | ||
28 | #include "fcs.h" | ||
29 | #include "fcs_lport.h" | ||
30 | #include "fcs_vport.h" | ||
31 | #include "fcs_rport.h" | ||
32 | #include "fcs_fcxp.h" | ||
33 | #include "fcs_trcmod.h" | ||
34 | #include "lport_priv.h" | ||
35 | #include <aen/bfa_aen_lport.h> | ||
36 | |||
37 | BFA_TRC_FILE(FCS, PORT); | ||
38 | |||
39 | /** | ||
40 | * Forward declarations | ||
41 | */ | ||
42 | |||
43 | static void bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port, | ||
44 | enum bfa_lport_aen_event event); | ||
45 | static void bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, | ||
46 | struct fchs_s *rx_fchs, u8 reason_code, | ||
47 | u8 reason_code_expl); | ||
48 | static void bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, | ||
49 | struct fchs_s *rx_fchs, | ||
50 | struct fc_logi_s *plogi); | ||
51 | static void bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port); | ||
52 | static void bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port); | ||
53 | static void bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port); | ||
54 | static void bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port); | ||
55 | static void bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port); | ||
56 | static void bfa_fcs_port_deleted(struct bfa_fcs_port_s *port); | ||
57 | static void bfa_fcs_port_echo(struct bfa_fcs_port_s *port, | ||
58 | struct fchs_s *rx_fchs, | ||
59 | struct fc_echo_s *echo, u16 len); | ||
60 | static void bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, | ||
61 | struct fchs_s *rx_fchs, | ||
62 | struct fc_rnid_cmd_s *rnid, u16 len); | ||
63 | static void bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port, | ||
64 | struct fc_rnid_general_topology_data_s *gen_topo_data); | ||
65 | |||
66 | static struct { | ||
67 | void (*init) (struct bfa_fcs_port_s *port); | ||
68 | void (*online) (struct bfa_fcs_port_s *port); | ||
69 | void (*offline) (struct bfa_fcs_port_s *port); | ||
70 | } __port_action[] = { | ||
71 | { | ||
72 | bfa_fcs_port_unknown_init, bfa_fcs_port_unknown_online, | ||
73 | bfa_fcs_port_unknown_offline}, { | ||
74 | bfa_fcs_port_fab_init, bfa_fcs_port_fab_online, | ||
75 | bfa_fcs_port_fab_offline}, { | ||
76 | bfa_fcs_port_loop_init, bfa_fcs_port_loop_online, | ||
77 | bfa_fcs_port_loop_offline}, { | ||
78 | bfa_fcs_port_n2n_init, bfa_fcs_port_n2n_online, | ||
79 | bfa_fcs_port_n2n_offline},}; | ||
80 | |||
81 | /** | ||
82 | * fcs_port_sm FCS logical port state machine | ||
83 | */ | ||
84 | |||
85 | enum bfa_fcs_port_event { | ||
86 | BFA_FCS_PORT_SM_CREATE = 1, | ||
87 | BFA_FCS_PORT_SM_ONLINE = 2, | ||
88 | BFA_FCS_PORT_SM_OFFLINE = 3, | ||
89 | BFA_FCS_PORT_SM_DELETE = 4, | ||
90 | BFA_FCS_PORT_SM_DELRPORT = 5, | ||
91 | }; | ||
92 | |||
93 | static void bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port, | ||
94 | enum bfa_fcs_port_event event); | ||
95 | static void bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, | ||
96 | enum bfa_fcs_port_event event); | ||
97 | static void bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port, | ||
98 | enum bfa_fcs_port_event event); | ||
99 | static void bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port, | ||
100 | enum bfa_fcs_port_event event); | ||
101 | static void bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port, | ||
102 | enum bfa_fcs_port_event event); | ||
103 | |||
104 | static void | ||
105 | bfa_fcs_port_sm_uninit(struct bfa_fcs_port_s *port, | ||
106 | enum bfa_fcs_port_event event) | ||
107 | { | ||
108 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
109 | bfa_trc(port->fcs, event); | ||
110 | |||
111 | switch (event) { | ||
112 | case BFA_FCS_PORT_SM_CREATE: | ||
113 | bfa_sm_set_state(port, bfa_fcs_port_sm_init); | ||
114 | break; | ||
115 | |||
116 | default: | ||
117 | bfa_assert(0); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | static void | ||
122 | bfa_fcs_port_sm_init(struct bfa_fcs_port_s *port, enum bfa_fcs_port_event event) | ||
123 | { | ||
124 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
125 | bfa_trc(port->fcs, event); | ||
126 | |||
127 | switch (event) { | ||
128 | case BFA_FCS_PORT_SM_ONLINE: | ||
129 | bfa_sm_set_state(port, bfa_fcs_port_sm_online); | ||
130 | bfa_fcs_port_online_actions(port); | ||
131 | break; | ||
132 | |||
133 | case BFA_FCS_PORT_SM_DELETE: | ||
134 | bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); | ||
135 | bfa_fcs_port_deleted(port); | ||
136 | break; | ||
137 | |||
138 | default: | ||
139 | bfa_assert(0); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static void | ||
144 | bfa_fcs_port_sm_online(struct bfa_fcs_port_s *port, | ||
145 | enum bfa_fcs_port_event event) | ||
146 | { | ||
147 | struct bfa_fcs_rport_s *rport; | ||
148 | struct list_head *qe, *qen; | ||
149 | |||
150 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
151 | bfa_trc(port->fcs, event); | ||
152 | |||
153 | switch (event) { | ||
154 | case BFA_FCS_PORT_SM_OFFLINE: | ||
155 | bfa_sm_set_state(port, bfa_fcs_port_sm_offline); | ||
156 | bfa_fcs_port_offline_actions(port); | ||
157 | break; | ||
158 | |||
159 | case BFA_FCS_PORT_SM_DELETE: | ||
160 | |||
161 | __port_action[port->fabric->fab_type].offline(port); | ||
162 | |||
163 | if (port->num_rports == 0) { | ||
164 | bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); | ||
165 | bfa_fcs_port_deleted(port); | ||
166 | } else { | ||
167 | bfa_sm_set_state(port, bfa_fcs_port_sm_deleting); | ||
168 | list_for_each_safe(qe, qen, &port->rport_q) { | ||
169 | rport = (struct bfa_fcs_rport_s *)qe; | ||
170 | bfa_fcs_rport_delete(rport); | ||
171 | } | ||
172 | } | ||
173 | break; | ||
174 | |||
175 | case BFA_FCS_PORT_SM_DELRPORT: | ||
176 | break; | ||
177 | |||
178 | default: | ||
179 | bfa_assert(0); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | static void | ||
184 | bfa_fcs_port_sm_offline(struct bfa_fcs_port_s *port, | ||
185 | enum bfa_fcs_port_event event) | ||
186 | { | ||
187 | struct bfa_fcs_rport_s *rport; | ||
188 | struct list_head *qe, *qen; | ||
189 | |||
190 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
191 | bfa_trc(port->fcs, event); | ||
192 | |||
193 | switch (event) { | ||
194 | case BFA_FCS_PORT_SM_ONLINE: | ||
195 | bfa_sm_set_state(port, bfa_fcs_port_sm_online); | ||
196 | bfa_fcs_port_online_actions(port); | ||
197 | break; | ||
198 | |||
199 | case BFA_FCS_PORT_SM_DELETE: | ||
200 | if (port->num_rports == 0) { | ||
201 | bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); | ||
202 | bfa_fcs_port_deleted(port); | ||
203 | } else { | ||
204 | bfa_sm_set_state(port, bfa_fcs_port_sm_deleting); | ||
205 | list_for_each_safe(qe, qen, &port->rport_q) { | ||
206 | rport = (struct bfa_fcs_rport_s *)qe; | ||
207 | bfa_fcs_rport_delete(rport); | ||
208 | } | ||
209 | } | ||
210 | break; | ||
211 | |||
212 | case BFA_FCS_PORT_SM_DELRPORT: | ||
213 | case BFA_FCS_PORT_SM_OFFLINE: | ||
214 | break; | ||
215 | |||
216 | default: | ||
217 | bfa_assert(0); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static void | ||
222 | bfa_fcs_port_sm_deleting(struct bfa_fcs_port_s *port, | ||
223 | enum bfa_fcs_port_event event) | ||
224 | { | ||
225 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
226 | bfa_trc(port->fcs, event); | ||
227 | |||
228 | switch (event) { | ||
229 | case BFA_FCS_PORT_SM_DELRPORT: | ||
230 | if (port->num_rports == 0) { | ||
231 | bfa_sm_set_state(port, bfa_fcs_port_sm_uninit); | ||
232 | bfa_fcs_port_deleted(port); | ||
233 | } | ||
234 | break; | ||
235 | |||
236 | default: | ||
237 | bfa_assert(0); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | |||
242 | |||
243 | /** | ||
244 | * fcs_port_pvt | ||
245 | */ | ||
246 | |||
247 | /** | ||
248 | * Send AEN notification | ||
249 | */ | ||
250 | static void | ||
251 | bfa_fcs_port_aen_post(struct bfa_fcs_port_s *port, | ||
252 | enum bfa_lport_aen_event event) | ||
253 | { | ||
254 | union bfa_aen_data_u aen_data; | ||
255 | struct bfa_log_mod_s *logmod = port->fcs->logm; | ||
256 | enum bfa_port_role role = port->port_cfg.roles; | ||
257 | wwn_t lpwwn = bfa_fcs_port_get_pwwn(port); | ||
258 | char lpwwn_ptr[BFA_STRING_32]; | ||
259 | char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] = | ||
260 | { "Initiator", "Target", "IPFC" }; | ||
261 | |||
262 | wwn2str(lpwwn_ptr, lpwwn); | ||
263 | |||
264 | bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX); | ||
265 | |||
266 | switch (event) { | ||
267 | case BFA_LPORT_AEN_ONLINE: | ||
268 | bfa_log(logmod, BFA_AEN_LPORT_ONLINE, lpwwn_ptr, | ||
269 | role_str[role / 2]); | ||
270 | break; | ||
271 | case BFA_LPORT_AEN_OFFLINE: | ||
272 | bfa_log(logmod, BFA_AEN_LPORT_OFFLINE, lpwwn_ptr, | ||
273 | role_str[role / 2]); | ||
274 | break; | ||
275 | case BFA_LPORT_AEN_NEW: | ||
276 | bfa_log(logmod, BFA_AEN_LPORT_NEW, lpwwn_ptr, | ||
277 | role_str[role / 2]); | ||
278 | break; | ||
279 | case BFA_LPORT_AEN_DELETE: | ||
280 | bfa_log(logmod, BFA_AEN_LPORT_DELETE, lpwwn_ptr, | ||
281 | role_str[role / 2]); | ||
282 | break; | ||
283 | case BFA_LPORT_AEN_DISCONNECT: | ||
284 | bfa_log(logmod, BFA_AEN_LPORT_DISCONNECT, lpwwn_ptr, | ||
285 | role_str[role / 2]); | ||
286 | break; | ||
287 | default: | ||
288 | break; | ||
289 | } | ||
290 | |||
291 | aen_data.lport.vf_id = port->fabric->vf_id; | ||
292 | aen_data.lport.roles = role; | ||
293 | aen_data.lport.ppwwn = | ||
294 | bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs)); | ||
295 | aen_data.lport.lpwwn = lpwwn; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Send a LS reject | ||
300 | */ | ||
301 | static void | ||
302 | bfa_fcs_port_send_ls_rjt(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, | ||
303 | u8 reason_code, u8 reason_code_expl) | ||
304 | { | ||
305 | struct fchs_s fchs; | ||
306 | struct bfa_fcxp_s *fcxp; | ||
307 | struct bfa_rport_s *bfa_rport = NULL; | ||
308 | int len; | ||
309 | |||
310 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
311 | |||
312 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
313 | if (!fcxp) | ||
314 | return; | ||
315 | |||
316 | len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, | ||
317 | bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, | ||
318 | reason_code, reason_code_expl); | ||
319 | |||
320 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | ||
321 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, | ||
322 | FC_MAX_PDUSZ, 0); | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * Process incoming plogi from a remote port. | ||
327 | */ | ||
328 | static void | ||
329 | bfa_fcs_port_plogi(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, | ||
330 | struct fc_logi_s *plogi) | ||
331 | { | ||
332 | struct bfa_fcs_rport_s *rport; | ||
333 | |||
334 | bfa_trc(port->fcs, rx_fchs->d_id); | ||
335 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
336 | |||
337 | /* | ||
338 | * If min cfg mode is enabled, drop any incoming PLOGIs | ||
339 | */ | ||
340 | if (__fcs_min_cfg(port->fcs)) { | ||
341 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
342 | return; | ||
343 | } | ||
344 | |||
345 | if (fc_plogi_parse(rx_fchs) != FC_PARSE_OK) { | ||
346 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
347 | /* | ||
348 | * send a LS reject | ||
349 | */ | ||
350 | bfa_fcs_port_send_ls_rjt(port, rx_fchs, | ||
351 | FC_LS_RJT_RSN_PROTOCOL_ERROR, | ||
352 | FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS); | ||
353 | return; | ||
354 | } | ||
355 | |||
356 | /** | ||
357 | * Direct Attach P2P mode : verify address assigned by the r-port. | ||
358 | */ | ||
359 | if ((!bfa_fcs_fabric_is_switched(port->fabric)) | ||
360 | && | ||
361 | (memcmp | ||
362 | ((void *)&bfa_fcs_port_get_pwwn(port), (void *)&plogi->port_name, | ||
363 | sizeof(wwn_t)) < 0)) { | ||
364 | if (BFA_FCS_PID_IS_WKA(rx_fchs->d_id)) { | ||
365 | /* | ||
366 | * Address assigned to us cannot be a WKA | ||
367 | */ | ||
368 | bfa_fcs_port_send_ls_rjt(port, rx_fchs, | ||
369 | FC_LS_RJT_RSN_PROTOCOL_ERROR, | ||
370 | FC_LS_RJT_EXP_INVALID_NPORT_ID); | ||
371 | return; | ||
372 | } | ||
373 | port->pid = rx_fchs->d_id; | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * First, check if we know the device by pwwn. | ||
378 | */ | ||
379 | rport = bfa_fcs_port_get_rport_by_pwwn(port, plogi->port_name); | ||
380 | if (rport) { | ||
381 | /** | ||
382 | * Direct Attach P2P mode: handle address assigned by the rport. | ||
383 | */ | ||
384 | if ((!bfa_fcs_fabric_is_switched(port->fabric)) | ||
385 | && | ||
386 | (memcmp | ||
387 | ((void *)&bfa_fcs_port_get_pwwn(port), | ||
388 | (void *)&plogi->port_name, sizeof(wwn_t)) < 0)) { | ||
389 | port->pid = rx_fchs->d_id; | ||
390 | rport->pid = rx_fchs->s_id; | ||
391 | } | ||
392 | bfa_fcs_rport_plogi(rport, rx_fchs, plogi); | ||
393 | return; | ||
394 | } | ||
395 | |||
396 | /** | ||
397 | * Next, lookup rport by PID. | ||
398 | */ | ||
399 | rport = bfa_fcs_port_get_rport_by_pid(port, rx_fchs->s_id); | ||
400 | if (!rport) { | ||
401 | /** | ||
402 | * Inbound PLOGI from a new device. | ||
403 | */ | ||
404 | bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); | ||
405 | return; | ||
406 | } | ||
407 | |||
408 | /** | ||
409 | * Rport is known only by PID. | ||
410 | */ | ||
411 | if (rport->pwwn) { | ||
412 | /** | ||
413 | * This is a different device with the same pid. Old device | ||
414 | * disappeared. Send implicit LOGO to old device. | ||
415 | */ | ||
416 | bfa_assert(rport->pwwn != plogi->port_name); | ||
417 | bfa_fcs_rport_logo_imp(rport); | ||
418 | |||
419 | /** | ||
420 | * Inbound PLOGI from a new device (with old PID). | ||
421 | */ | ||
422 | bfa_fcs_rport_plogi_create(port, rx_fchs, plogi); | ||
423 | return; | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * PLOGI crossing each other. | ||
428 | */ | ||
429 | bfa_assert(rport->pwwn == WWN_NULL); | ||
430 | bfa_fcs_rport_plogi(rport, rx_fchs, plogi); | ||
431 | } | ||
432 | |||
433 | /* | ||
434 | * Process incoming ECHO. | ||
435 | * Since it does not require a login, it is processed here. | ||
436 | */ | ||
437 | static void | ||
438 | bfa_fcs_port_echo(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, | ||
439 | struct fc_echo_s *echo, u16 rx_len) | ||
440 | { | ||
441 | struct fchs_s fchs; | ||
442 | struct bfa_fcxp_s *fcxp; | ||
443 | struct bfa_rport_s *bfa_rport = NULL; | ||
444 | int len, pyld_len; | ||
445 | |||
446 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
447 | bfa_trc(port->fcs, rx_fchs->d_id); | ||
448 | bfa_trc(port->fcs, rx_len); | ||
449 | |||
450 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
451 | if (!fcxp) | ||
452 | return; | ||
453 | |||
454 | len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, | ||
455 | bfa_fcs_port_get_fcid(port), rx_fchs->ox_id); | ||
456 | |||
457 | /* | ||
458 | * Copy the payload (if any) from the echo frame | ||
459 | */ | ||
460 | pyld_len = rx_len - sizeof(struct fchs_s); | ||
461 | bfa_trc(port->fcs, pyld_len); | ||
462 | |||
463 | if (pyld_len > len) | ||
464 | memcpy(((u8 *) bfa_fcxp_get_reqbuf(fcxp)) + | ||
465 | sizeof(struct fc_echo_s), (echo + 1), | ||
466 | (pyld_len - sizeof(struct fc_echo_s))); | ||
467 | |||
468 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | ||
469 | BFA_FALSE, FC_CLASS_3, pyld_len, &fchs, NULL, NULL, | ||
470 | FC_MAX_PDUSZ, 0); | ||
471 | } | ||
472 | |||
473 | /* | ||
474 | * Process incoming RNID. | ||
475 | * Since it does not require a login, it is processed here. | ||
476 | */ | ||
477 | static void | ||
478 | bfa_fcs_port_rnid(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, | ||
479 | struct fc_rnid_cmd_s *rnid, u16 rx_len) | ||
480 | { | ||
481 | struct fc_rnid_common_id_data_s common_id_data; | ||
482 | struct fc_rnid_general_topology_data_s gen_topo_data; | ||
483 | struct fchs_s fchs; | ||
484 | struct bfa_fcxp_s *fcxp; | ||
485 | struct bfa_rport_s *bfa_rport = NULL; | ||
486 | u16 len; | ||
487 | u32 data_format; | ||
488 | |||
489 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
490 | bfa_trc(port->fcs, rx_fchs->d_id); | ||
491 | bfa_trc(port->fcs, rx_len); | ||
492 | |||
493 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
494 | if (!fcxp) | ||
495 | return; | ||
496 | |||
497 | /* | ||
498 | * Check Node Indentification Data Format | ||
499 | * We only support General Topology Discovery Format. | ||
500 | * For any other requested Data Formats, we return Common Node Id Data | ||
501 | * only, as per FC-LS. | ||
502 | */ | ||
503 | bfa_trc(port->fcs, rnid->node_id_data_format); | ||
504 | if (rnid->node_id_data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { | ||
505 | data_format = RNID_NODEID_DATA_FORMAT_DISCOVERY; | ||
506 | /* | ||
507 | * Get General topology data for this port | ||
508 | */ | ||
509 | bfa_fs_port_get_gen_topo_data(port, &gen_topo_data); | ||
510 | } else { | ||
511 | data_format = RNID_NODEID_DATA_FORMAT_COMMON; | ||
512 | } | ||
513 | |||
514 | /* | ||
515 | * Copy the Node Id Info | ||
516 | */ | ||
517 | common_id_data.port_name = bfa_fcs_port_get_pwwn(port); | ||
518 | common_id_data.node_name = bfa_fcs_port_get_nwwn(port); | ||
519 | |||
520 | len = fc_rnid_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, | ||
521 | bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, | ||
522 | data_format, &common_id_data, &gen_topo_data); | ||
523 | |||
524 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | ||
525 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, | ||
526 | FC_MAX_PDUSZ, 0); | ||
527 | |||
528 | return; | ||
529 | } | ||
530 | |||
531 | /* | ||
532 | * Fill out General Topolpgy Discovery Data for RNID ELS. | ||
533 | */ | ||
534 | static void | ||
535 | bfa_fs_port_get_gen_topo_data(struct bfa_fcs_port_s *port, | ||
536 | struct fc_rnid_general_topology_data_s *gen_topo_data) | ||
537 | { | ||
538 | |||
539 | bfa_os_memset(gen_topo_data, 0, | ||
540 | sizeof(struct fc_rnid_general_topology_data_s)); | ||
541 | |||
542 | gen_topo_data->asso_type = bfa_os_htonl(RNID_ASSOCIATED_TYPE_HOST); | ||
543 | gen_topo_data->phy_port_num = 0; /* @todo */ | ||
544 | gen_topo_data->num_attached_nodes = bfa_os_htonl(1); | ||
545 | } | ||
546 | |||
547 | static void | ||
548 | bfa_fcs_port_online_actions(struct bfa_fcs_port_s *port) | ||
549 | { | ||
550 | bfa_trc(port->fcs, port->fabric->oper_type); | ||
551 | |||
552 | __port_action[port->fabric->fab_type].init(port); | ||
553 | __port_action[port->fabric->fab_type].online(port); | ||
554 | |||
555 | bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_ONLINE); | ||
556 | bfa_fcb_port_online(port->fcs->bfad, port->port_cfg.roles, | ||
557 | port->fabric->vf_drv, (port->vport == NULL) ? | ||
558 | NULL : port->vport->vport_drv); | ||
559 | } | ||
560 | |||
561 | static void | ||
562 | bfa_fcs_port_offline_actions(struct bfa_fcs_port_s *port) | ||
563 | { | ||
564 | struct list_head *qe, *qen; | ||
565 | struct bfa_fcs_rport_s *rport; | ||
566 | |||
567 | bfa_trc(port->fcs, port->fabric->oper_type); | ||
568 | |||
569 | __port_action[port->fabric->fab_type].offline(port); | ||
570 | |||
571 | if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE) { | ||
572 | bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DISCONNECT); | ||
573 | } else { | ||
574 | bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_OFFLINE); | ||
575 | } | ||
576 | bfa_fcb_port_offline(port->fcs->bfad, port->port_cfg.roles, | ||
577 | port->fabric->vf_drv, | ||
578 | (port->vport == NULL) ? NULL : port->vport->vport_drv); | ||
579 | |||
580 | list_for_each_safe(qe, qen, &port->rport_q) { | ||
581 | rport = (struct bfa_fcs_rport_s *)qe; | ||
582 | bfa_fcs_rport_offline(rport); | ||
583 | } | ||
584 | } | ||
585 | |||
586 | static void | ||
587 | bfa_fcs_port_unknown_init(struct bfa_fcs_port_s *port) | ||
588 | { | ||
589 | bfa_assert(0); | ||
590 | } | ||
591 | |||
592 | static void | ||
593 | bfa_fcs_port_unknown_online(struct bfa_fcs_port_s *port) | ||
594 | { | ||
595 | bfa_assert(0); | ||
596 | } | ||
597 | |||
598 | static void | ||
599 | bfa_fcs_port_unknown_offline(struct bfa_fcs_port_s *port) | ||
600 | { | ||
601 | bfa_assert(0); | ||
602 | } | ||
603 | |||
604 | static void | ||
605 | bfa_fcs_port_deleted(struct bfa_fcs_port_s *port) | ||
606 | { | ||
607 | bfa_fcs_port_aen_post(port, BFA_LPORT_AEN_DELETE); | ||
608 | |||
609 | /* | ||
610 | * Base port will be deleted by the OS driver | ||
611 | */ | ||
612 | if (port->vport) { | ||
613 | bfa_fcb_port_delete(port->fcs->bfad, port->port_cfg.roles, | ||
614 | port->fabric->vf_drv, | ||
615 | port->vport ? port->vport->vport_drv : NULL); | ||
616 | bfa_fcs_vport_delete_comp(port->vport); | ||
617 | } else { | ||
618 | bfa_fcs_fabric_port_delete_comp(port->fabric); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | |||
623 | |||
624 | /** | ||
625 | * fcs_lport_api BFA FCS port API | ||
626 | */ | ||
627 | /** | ||
628 | * Module initialization | ||
629 | */ | ||
630 | void | ||
631 | bfa_fcs_port_modinit(struct bfa_fcs_s *fcs) | ||
632 | { | ||
633 | |||
634 | } | ||
635 | |||
636 | /** | ||
637 | * Module cleanup | ||
638 | */ | ||
639 | void | ||
640 | bfa_fcs_port_modexit(struct bfa_fcs_s *fcs) | ||
641 | { | ||
642 | bfa_fcs_modexit_comp(fcs); | ||
643 | } | ||
644 | |||
645 | /** | ||
646 | * Unsolicited frame receive handling. | ||
647 | */ | ||
648 | void | ||
649 | bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs, | ||
650 | u16 len) | ||
651 | { | ||
652 | u32 pid = fchs->s_id; | ||
653 | struct bfa_fcs_rport_s *rport = NULL; | ||
654 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
655 | |||
656 | bfa_stats(lport, uf_recvs); | ||
657 | |||
658 | if (!bfa_fcs_port_is_online(lport)) { | ||
659 | bfa_stats(lport, uf_recv_drops); | ||
660 | return; | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * First, handle ELSs that donot require a login. | ||
665 | */ | ||
666 | /* | ||
667 | * Handle PLOGI first | ||
668 | */ | ||
669 | if ((fchs->type == FC_TYPE_ELS) && | ||
670 | (els_cmd->els_code == FC_ELS_PLOGI)) { | ||
671 | bfa_fcs_port_plogi(lport, fchs, (struct fc_logi_s *) els_cmd); | ||
672 | return; | ||
673 | } | ||
674 | |||
675 | /* | ||
676 | * Handle ECHO separately. | ||
677 | */ | ||
678 | if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_ECHO)) { | ||
679 | bfa_fcs_port_echo(lport, fchs, | ||
680 | (struct fc_echo_s *) els_cmd, len); | ||
681 | return; | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * Handle RNID separately. | ||
686 | */ | ||
687 | if ((fchs->type == FC_TYPE_ELS) && (els_cmd->els_code == FC_ELS_RNID)) { | ||
688 | bfa_fcs_port_rnid(lport, fchs, | ||
689 | (struct fc_rnid_cmd_s *) els_cmd, len); | ||
690 | return; | ||
691 | } | ||
692 | |||
693 | /** | ||
694 | * look for a matching remote port ID | ||
695 | */ | ||
696 | rport = bfa_fcs_port_get_rport_by_pid(lport, pid); | ||
697 | if (rport) { | ||
698 | bfa_trc(rport->fcs, fchs->s_id); | ||
699 | bfa_trc(rport->fcs, fchs->d_id); | ||
700 | bfa_trc(rport->fcs, fchs->type); | ||
701 | |||
702 | bfa_fcs_rport_uf_recv(rport, fchs, len); | ||
703 | return; | ||
704 | } | ||
705 | |||
706 | /** | ||
707 | * Only handles ELS frames for now. | ||
708 | */ | ||
709 | if (fchs->type != FC_TYPE_ELS) { | ||
710 | bfa_trc(lport->fcs, fchs->type); | ||
711 | bfa_assert(0); | ||
712 | return; | ||
713 | } | ||
714 | |||
715 | bfa_trc(lport->fcs, els_cmd->els_code); | ||
716 | if (els_cmd->els_code == FC_ELS_RSCN) { | ||
717 | bfa_fcs_port_scn_process_rscn(lport, fchs, len); | ||
718 | return; | ||
719 | } | ||
720 | |||
721 | if (els_cmd->els_code == FC_ELS_LOGO) { | ||
722 | /** | ||
723 | * @todo Handle LOGO frames received. | ||
724 | */ | ||
725 | bfa_trc(lport->fcs, els_cmd->els_code); | ||
726 | return; | ||
727 | } | ||
728 | |||
729 | if (els_cmd->els_code == FC_ELS_PRLI) { | ||
730 | /** | ||
731 | * @todo Handle PRLI frames received. | ||
732 | */ | ||
733 | bfa_trc(lport->fcs, els_cmd->els_code); | ||
734 | return; | ||
735 | } | ||
736 | |||
737 | /** | ||
738 | * Unhandled ELS frames. Send a LS_RJT. | ||
739 | */ | ||
740 | bfa_fcs_port_send_ls_rjt(lport, fchs, FC_LS_RJT_RSN_CMD_NOT_SUPP, | ||
741 | FC_LS_RJT_EXP_NO_ADDL_INFO); | ||
742 | |||
743 | } | ||
744 | |||
745 | /** | ||
746 | * PID based Lookup for a R-Port in the Port R-Port Queue | ||
747 | */ | ||
748 | struct bfa_fcs_rport_s * | ||
749 | bfa_fcs_port_get_rport_by_pid(struct bfa_fcs_port_s *port, u32 pid) | ||
750 | { | ||
751 | struct bfa_fcs_rport_s *rport; | ||
752 | struct list_head *qe; | ||
753 | |||
754 | list_for_each(qe, &port->rport_q) { | ||
755 | rport = (struct bfa_fcs_rport_s *)qe; | ||
756 | if (rport->pid == pid) | ||
757 | return rport; | ||
758 | } | ||
759 | |||
760 | bfa_trc(port->fcs, pid); | ||
761 | return NULL; | ||
762 | } | ||
763 | |||
764 | /** | ||
765 | * PWWN based Lookup for a R-Port in the Port R-Port Queue | ||
766 | */ | ||
767 | struct bfa_fcs_rport_s * | ||
768 | bfa_fcs_port_get_rport_by_pwwn(struct bfa_fcs_port_s *port, wwn_t pwwn) | ||
769 | { | ||
770 | struct bfa_fcs_rport_s *rport; | ||
771 | struct list_head *qe; | ||
772 | |||
773 | list_for_each(qe, &port->rport_q) { | ||
774 | rport = (struct bfa_fcs_rport_s *)qe; | ||
775 | if (wwn_is_equal(rport->pwwn, pwwn)) | ||
776 | return rport; | ||
777 | } | ||
778 | |||
779 | bfa_trc(port->fcs, pwwn); | ||
780 | return (NULL); | ||
781 | } | ||
782 | |||
783 | /** | ||
784 | * NWWN based Lookup for a R-Port in the Port R-Port Queue | ||
785 | */ | ||
786 | struct bfa_fcs_rport_s * | ||
787 | bfa_fcs_port_get_rport_by_nwwn(struct bfa_fcs_port_s *port, wwn_t nwwn) | ||
788 | { | ||
789 | struct bfa_fcs_rport_s *rport; | ||
790 | struct list_head *qe; | ||
791 | |||
792 | list_for_each(qe, &port->rport_q) { | ||
793 | rport = (struct bfa_fcs_rport_s *)qe; | ||
794 | if (wwn_is_equal(rport->nwwn, nwwn)) | ||
795 | return rport; | ||
796 | } | ||
797 | |||
798 | bfa_trc(port->fcs, nwwn); | ||
799 | return (NULL); | ||
800 | } | ||
801 | |||
802 | /** | ||
803 | * Called by rport module when new rports are discovered. | ||
804 | */ | ||
805 | void | ||
806 | bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port, | ||
807 | struct bfa_fcs_rport_s *rport) | ||
808 | { | ||
809 | list_add_tail(&rport->qe, &port->rport_q); | ||
810 | port->num_rports++; | ||
811 | } | ||
812 | |||
813 | /** | ||
814 | * Called by rport module to when rports are deleted. | ||
815 | */ | ||
816 | void | ||
817 | bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port, | ||
818 | struct bfa_fcs_rport_s *rport) | ||
819 | { | ||
820 | bfa_assert(bfa_q_is_on_q(&port->rport_q, rport)); | ||
821 | list_del(&rport->qe); | ||
822 | port->num_rports--; | ||
823 | |||
824 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELRPORT); | ||
825 | } | ||
826 | |||
827 | /** | ||
828 | * Called by fabric for base port when fabric login is complete. | ||
829 | * Called by vport for virtual ports when FDISC is complete. | ||
830 | */ | ||
831 | void | ||
832 | bfa_fcs_port_online(struct bfa_fcs_port_s *port) | ||
833 | { | ||
834 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_ONLINE); | ||
835 | } | ||
836 | |||
837 | /** | ||
838 | * Called by fabric for base port when fabric goes offline. | ||
839 | * Called by vport for virtual ports when virtual port becomes offline. | ||
840 | */ | ||
841 | void | ||
842 | bfa_fcs_port_offline(struct bfa_fcs_port_s *port) | ||
843 | { | ||
844 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_OFFLINE); | ||
845 | } | ||
846 | |||
847 | /** | ||
848 | * Called by fabric to delete base lport and associated resources. | ||
849 | * | ||
850 | * Called by vport to delete lport and associated resources. Should call | ||
851 | * bfa_fcs_vport_delete_comp() for vports on completion. | ||
852 | */ | ||
853 | void | ||
854 | bfa_fcs_port_delete(struct bfa_fcs_port_s *port) | ||
855 | { | ||
856 | bfa_sm_send_event(port, BFA_FCS_PORT_SM_DELETE); | ||
857 | } | ||
858 | |||
859 | /** | ||
860 | * Called by fabric in private loop topology to process LIP event. | ||
861 | */ | ||
862 | void | ||
863 | bfa_fcs_port_lip(struct bfa_fcs_port_s *port) | ||
864 | { | ||
865 | } | ||
866 | |||
867 | /** | ||
868 | * Return TRUE if port is online, else return FALSE | ||
869 | */ | ||
870 | bfa_boolean_t | ||
871 | bfa_fcs_port_is_online(struct bfa_fcs_port_s *port) | ||
872 | { | ||
873 | return (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online)); | ||
874 | } | ||
875 | |||
876 | /** | ||
877 | * Logical port initialization of base or virtual port. | ||
878 | * Called by fabric for base port or by vport for virtual ports. | ||
879 | */ | ||
880 | void | ||
881 | bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs, | ||
882 | u16 vf_id, struct bfa_port_cfg_s *port_cfg, | ||
883 | struct bfa_fcs_vport_s *vport) | ||
884 | { | ||
885 | lport->fcs = fcs; | ||
886 | lport->fabric = bfa_fcs_vf_lookup(fcs, vf_id); | ||
887 | bfa_os_assign(lport->port_cfg, *port_cfg); | ||
888 | lport->vport = vport; | ||
889 | lport->lp_tag = (vport) ? bfa_lps_get_tag(vport->lps) : | ||
890 | bfa_lps_get_tag(lport->fabric->lps); | ||
891 | |||
892 | INIT_LIST_HEAD(&lport->rport_q); | ||
893 | lport->num_rports = 0; | ||
894 | |||
895 | lport->bfad_port = | ||
896 | bfa_fcb_port_new(fcs->bfad, lport, lport->port_cfg.roles, | ||
897 | lport->fabric->vf_drv, | ||
898 | vport ? vport->vport_drv : NULL); | ||
899 | bfa_fcs_port_aen_post(lport, BFA_LPORT_AEN_NEW); | ||
900 | |||
901 | bfa_sm_set_state(lport, bfa_fcs_port_sm_uninit); | ||
902 | bfa_sm_send_event(lport, BFA_FCS_PORT_SM_CREATE); | ||
903 | } | ||
904 | |||
905 | |||
906 | |||
907 | /** | ||
908 | * fcs_lport_api | ||
909 | */ | ||
910 | |||
911 | void | ||
912 | bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port, | ||
913 | struct bfa_port_attr_s *port_attr) | ||
914 | { | ||
915 | if (bfa_sm_cmp_state(port, bfa_fcs_port_sm_online)) | ||
916 | port_attr->pid = port->pid; | ||
917 | else | ||
918 | port_attr->pid = 0; | ||
919 | |||
920 | port_attr->port_cfg = port->port_cfg; | ||
921 | |||
922 | if (port->fabric) { | ||
923 | port_attr->port_type = bfa_fcs_fabric_port_type(port->fabric); | ||
924 | port_attr->loopback = bfa_fcs_fabric_is_loopback(port->fabric); | ||
925 | port_attr->fabric_name = bfa_fcs_port_get_fabric_name(port); | ||
926 | memcpy(port_attr->fabric_ip_addr, | ||
927 | bfa_fcs_port_get_fabric_ipaddr(port), | ||
928 | BFA_FCS_FABRIC_IPADDR_SZ); | ||
929 | |||
930 | if (port->vport != NULL) | ||
931 | port_attr->port_type = BFA_PPORT_TYPE_VPORT; | ||
932 | |||
933 | } else { | ||
934 | port_attr->port_type = BFA_PPORT_TYPE_UNKNOWN; | ||
935 | port_attr->state = BFA_PORT_UNINIT; | ||
936 | } | ||
937 | |||
938 | } | ||
939 | |||
940 | |||
diff --git a/drivers/scsi/bfa/bfa_fcs_port.c b/drivers/scsi/bfa/bfa_fcs_port.c new file mode 100644 index 000000000000..9c4b24e62de1 --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcs_port.c | |||
@@ -0,0 +1,68 @@ | |||
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 | * bfa_fcs_pport.c BFA FCS PPORT ( physical port) | ||
20 | */ | ||
21 | |||
22 | #include <fcs/bfa_fcs.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include <fcs/bfa_fcs_fabric.h> | ||
25 | #include "fcs_trcmod.h" | ||
26 | #include "fcs.h" | ||
27 | #include "fcs_fabric.h" | ||
28 | #include "fcs_port.h" | ||
29 | |||
30 | BFA_TRC_FILE(FCS, PPORT); | ||
31 | |||
32 | static void | ||
33 | bfa_fcs_pport_event_handler(void *cbarg, bfa_pport_event_t event) | ||
34 | { | ||
35 | struct bfa_fcs_s *fcs = cbarg; | ||
36 | |||
37 | bfa_trc(fcs, event); | ||
38 | |||
39 | switch (event) { | ||
40 | case BFA_PPORT_LINKUP: | ||
41 | bfa_fcs_fabric_link_up(&fcs->fabric); | ||
42 | break; | ||
43 | |||
44 | case BFA_PPORT_LINKDOWN: | ||
45 | bfa_fcs_fabric_link_down(&fcs->fabric); | ||
46 | break; | ||
47 | |||
48 | case BFA_PPORT_TRUNK_LINKDOWN: | ||
49 | bfa_assert(0); | ||
50 | break; | ||
51 | |||
52 | default: | ||
53 | bfa_assert(0); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | void | ||
58 | bfa_fcs_pport_modinit(struct bfa_fcs_s *fcs) | ||
59 | { | ||
60 | bfa_pport_event_register(fcs->bfa, bfa_fcs_pport_event_handler, | ||
61 | fcs); | ||
62 | } | ||
63 | |||
64 | void | ||
65 | bfa_fcs_pport_modexit(struct bfa_fcs_s *fcs) | ||
66 | { | ||
67 | bfa_fcs_modexit_comp(fcs); | ||
68 | } | ||
diff --git a/drivers/scsi/bfa/bfa_fcs_uf.c b/drivers/scsi/bfa/bfa_fcs_uf.c new file mode 100644 index 000000000000..ad01db6444b2 --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcs_uf.c | |||
@@ -0,0 +1,105 @@ | |||
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 | * bfa_fcs_uf.c BFA FCS UF ( Unsolicited Frames) | ||
20 | */ | ||
21 | |||
22 | #include <fcs/bfa_fcs.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include <fcs/bfa_fcs_fabric.h> | ||
25 | #include "fcs.h" | ||
26 | #include "fcs_trcmod.h" | ||
27 | #include "fcs_fabric.h" | ||
28 | #include "fcs_uf.h" | ||
29 | |||
30 | BFA_TRC_FILE(FCS, UF); | ||
31 | |||
32 | /** | ||
33 | * BFA callback for unsolicited frame receive handler. | ||
34 | * | ||
35 | * @param[in] cbarg callback arg for receive handler | ||
36 | * @param[in] uf unsolicited frame descriptor | ||
37 | * | ||
38 | * @return None | ||
39 | */ | ||
40 | static void | ||
41 | bfa_fcs_uf_recv(void *cbarg, struct bfa_uf_s *uf) | ||
42 | { | ||
43 | struct bfa_fcs_s *fcs = (struct bfa_fcs_s *) cbarg; | ||
44 | struct fchs_s *fchs = bfa_uf_get_frmbuf(uf); | ||
45 | u16 len = bfa_uf_get_frmlen(uf); | ||
46 | struct fc_vft_s *vft; | ||
47 | struct bfa_fcs_fabric_s *fabric; | ||
48 | |||
49 | /** | ||
50 | * check for VFT header | ||
51 | */ | ||
52 | if (fchs->routing == FC_RTG_EXT_HDR && | ||
53 | fchs->cat_info == FC_CAT_VFT_HDR) { | ||
54 | bfa_stats(fcs, uf.tagged); | ||
55 | vft = bfa_uf_get_frmbuf(uf); | ||
56 | if (fcs->port_vfid == vft->vf_id) | ||
57 | fabric = &fcs->fabric; | ||
58 | else | ||
59 | fabric = bfa_fcs_vf_lookup(fcs, (u16) vft->vf_id); | ||
60 | |||
61 | /** | ||
62 | * drop frame if vfid is unknown | ||
63 | */ | ||
64 | if (!fabric) { | ||
65 | bfa_assert(0); | ||
66 | bfa_stats(fcs, uf.vfid_unknown); | ||
67 | bfa_uf_free(uf); | ||
68 | return; | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * skip vft header | ||
73 | */ | ||
74 | fchs = (struct fchs_s *) (vft + 1); | ||
75 | len -= sizeof(struct fc_vft_s); | ||
76 | |||
77 | bfa_trc(fcs, vft->vf_id); | ||
78 | } else { | ||
79 | bfa_stats(fcs, uf.untagged); | ||
80 | fabric = &fcs->fabric; | ||
81 | } | ||
82 | |||
83 | bfa_trc(fcs, ((u32 *) fchs)[0]); | ||
84 | bfa_trc(fcs, ((u32 *) fchs)[1]); | ||
85 | bfa_trc(fcs, ((u32 *) fchs)[2]); | ||
86 | bfa_trc(fcs, ((u32 *) fchs)[3]); | ||
87 | bfa_trc(fcs, ((u32 *) fchs)[4]); | ||
88 | bfa_trc(fcs, ((u32 *) fchs)[5]); | ||
89 | bfa_trc(fcs, len); | ||
90 | |||
91 | bfa_fcs_fabric_uf_recv(fabric, fchs, len); | ||
92 | bfa_uf_free(uf); | ||
93 | } | ||
94 | |||
95 | void | ||
96 | bfa_fcs_uf_modinit(struct bfa_fcs_s *fcs) | ||
97 | { | ||
98 | bfa_uf_recv_register(fcs->bfa, bfa_fcs_uf_recv, fcs); | ||
99 | } | ||
100 | |||
101 | void | ||
102 | bfa_fcs_uf_modexit(struct bfa_fcs_s *fcs) | ||
103 | { | ||
104 | bfa_fcs_modexit_comp(fcs); | ||
105 | } | ||
diff --git a/drivers/scsi/bfa/bfa_fcxp.c b/drivers/scsi/bfa/bfa_fcxp.c new file mode 100644 index 000000000000..4754a0e9006a --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcxp.c | |||
@@ -0,0 +1,782 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfi/bfi_uf.h> | ||
20 | #include <cs/bfa_debug.h> | ||
21 | |||
22 | BFA_TRC_FILE(HAL, FCXP); | ||
23 | BFA_MODULE(fcxp); | ||
24 | |||
25 | /** | ||
26 | * forward declarations | ||
27 | */ | ||
28 | static void __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete); | ||
29 | static void hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp, | ||
30 | struct bfi_fcxp_send_rsp_s *fcxp_rsp); | ||
31 | static void hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, | ||
32 | struct bfa_fcxp_s *fcxp, struct fchs_s *fchs); | ||
33 | static void bfa_fcxp_qresume(void *cbarg); | ||
34 | static void bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, | ||
35 | struct bfi_fcxp_send_req_s *send_req); | ||
36 | |||
37 | /** | ||
38 | * fcxp_pvt BFA FCXP private functions | ||
39 | */ | ||
40 | |||
41 | static void | ||
42 | claim_fcxp_req_rsp_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi) | ||
43 | { | ||
44 | u8 *dm_kva = NULL; | ||
45 | u64 dm_pa; | ||
46 | u32 buf_pool_sz; | ||
47 | |||
48 | dm_kva = bfa_meminfo_dma_virt(mi); | ||
49 | dm_pa = bfa_meminfo_dma_phys(mi); | ||
50 | |||
51 | buf_pool_sz = mod->req_pld_sz * mod->num_fcxps; | ||
52 | |||
53 | /* | ||
54 | * Initialize the fcxp req payload list | ||
55 | */ | ||
56 | mod->req_pld_list_kva = dm_kva; | ||
57 | mod->req_pld_list_pa = dm_pa; | ||
58 | dm_kva += buf_pool_sz; | ||
59 | dm_pa += buf_pool_sz; | ||
60 | bfa_os_memset(mod->req_pld_list_kva, 0, buf_pool_sz); | ||
61 | |||
62 | /* | ||
63 | * Initialize the fcxp rsp payload list | ||
64 | */ | ||
65 | buf_pool_sz = mod->rsp_pld_sz * mod->num_fcxps; | ||
66 | mod->rsp_pld_list_kva = dm_kva; | ||
67 | mod->rsp_pld_list_pa = dm_pa; | ||
68 | dm_kva += buf_pool_sz; | ||
69 | dm_pa += buf_pool_sz; | ||
70 | bfa_os_memset(mod->rsp_pld_list_kva, 0, buf_pool_sz); | ||
71 | |||
72 | bfa_meminfo_dma_virt(mi) = dm_kva; | ||
73 | bfa_meminfo_dma_phys(mi) = dm_pa; | ||
74 | } | ||
75 | |||
76 | static void | ||
77 | claim_fcxps_mem(struct bfa_fcxp_mod_s *mod, struct bfa_meminfo_s *mi) | ||
78 | { | ||
79 | u16 i; | ||
80 | struct bfa_fcxp_s *fcxp; | ||
81 | |||
82 | fcxp = (struct bfa_fcxp_s *) bfa_meminfo_kva(mi); | ||
83 | bfa_os_memset(fcxp, 0, sizeof(struct bfa_fcxp_s) * mod->num_fcxps); | ||
84 | |||
85 | INIT_LIST_HEAD(&mod->fcxp_free_q); | ||
86 | INIT_LIST_HEAD(&mod->fcxp_active_q); | ||
87 | |||
88 | mod->fcxp_list = fcxp; | ||
89 | |||
90 | for (i = 0; i < mod->num_fcxps; i++) { | ||
91 | fcxp->fcxp_mod = mod; | ||
92 | fcxp->fcxp_tag = i; | ||
93 | |||
94 | list_add_tail(&fcxp->qe, &mod->fcxp_free_q); | ||
95 | bfa_reqq_winit(&fcxp->reqq_wqe, bfa_fcxp_qresume, fcxp); | ||
96 | fcxp->reqq_waiting = BFA_FALSE; | ||
97 | |||
98 | fcxp = fcxp + 1; | ||
99 | } | ||
100 | |||
101 | bfa_meminfo_kva(mi) = (void *)fcxp; | ||
102 | } | ||
103 | |||
104 | static void | ||
105 | bfa_fcxp_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, | ||
106 | u32 *dm_len) | ||
107 | { | ||
108 | u16 num_fcxp_reqs = cfg->fwcfg.num_fcxp_reqs; | ||
109 | |||
110 | if (num_fcxp_reqs == 0) | ||
111 | return; | ||
112 | |||
113 | /* | ||
114 | * Account for req/rsp payload | ||
115 | */ | ||
116 | *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs; | ||
117 | if (cfg->drvcfg.min_cfg) | ||
118 | *dm_len += BFA_FCXP_MAX_IBUF_SZ * num_fcxp_reqs; | ||
119 | else | ||
120 | *dm_len += BFA_FCXP_MAX_LBUF_SZ * num_fcxp_reqs; | ||
121 | |||
122 | /* | ||
123 | * Account for fcxp structs | ||
124 | */ | ||
125 | *ndm_len += sizeof(struct bfa_fcxp_s) * num_fcxp_reqs; | ||
126 | } | ||
127 | |||
128 | static void | ||
129 | bfa_fcxp_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
130 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
131 | { | ||
132 | struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); | ||
133 | |||
134 | bfa_os_memset(mod, 0, sizeof(struct bfa_fcxp_mod_s)); | ||
135 | mod->bfa = bfa; | ||
136 | mod->num_fcxps = cfg->fwcfg.num_fcxp_reqs; | ||
137 | |||
138 | /** | ||
139 | * Initialize FCXP request and response payload sizes. | ||
140 | */ | ||
141 | mod->req_pld_sz = mod->rsp_pld_sz = BFA_FCXP_MAX_IBUF_SZ; | ||
142 | if (!cfg->drvcfg.min_cfg) | ||
143 | mod->rsp_pld_sz = BFA_FCXP_MAX_LBUF_SZ; | ||
144 | |||
145 | INIT_LIST_HEAD(&mod->wait_q); | ||
146 | |||
147 | claim_fcxp_req_rsp_mem(mod, meminfo); | ||
148 | claim_fcxps_mem(mod, meminfo); | ||
149 | } | ||
150 | |||
151 | static void | ||
152 | bfa_fcxp_initdone(struct bfa_s *bfa) | ||
153 | { | ||
154 | } | ||
155 | |||
156 | static void | ||
157 | bfa_fcxp_detach(struct bfa_s *bfa) | ||
158 | { | ||
159 | } | ||
160 | |||
161 | static void | ||
162 | bfa_fcxp_start(struct bfa_s *bfa) | ||
163 | { | ||
164 | } | ||
165 | |||
166 | static void | ||
167 | bfa_fcxp_stop(struct bfa_s *bfa) | ||
168 | { | ||
169 | } | ||
170 | |||
171 | static void | ||
172 | bfa_fcxp_iocdisable(struct bfa_s *bfa) | ||
173 | { | ||
174 | struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); | ||
175 | struct bfa_fcxp_s *fcxp; | ||
176 | struct list_head *qe, *qen; | ||
177 | |||
178 | list_for_each_safe(qe, qen, &mod->fcxp_active_q) { | ||
179 | fcxp = (struct bfa_fcxp_s *) qe; | ||
180 | if (fcxp->caller == NULL) { | ||
181 | fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg, | ||
182 | BFA_STATUS_IOC_FAILURE, 0, 0, NULL); | ||
183 | bfa_fcxp_free(fcxp); | ||
184 | } else { | ||
185 | fcxp->rsp_status = BFA_STATUS_IOC_FAILURE; | ||
186 | bfa_cb_queue(bfa, &fcxp->hcb_qe, | ||
187 | __bfa_fcxp_send_cbfn, fcxp); | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
192 | static struct bfa_fcxp_s * | ||
193 | bfa_fcxp_get(struct bfa_fcxp_mod_s *fm) | ||
194 | { | ||
195 | struct bfa_fcxp_s *fcxp; | ||
196 | |||
197 | bfa_q_deq(&fm->fcxp_free_q, &fcxp); | ||
198 | |||
199 | if (fcxp) | ||
200 | list_add_tail(&fcxp->qe, &fm->fcxp_active_q); | ||
201 | |||
202 | return (fcxp); | ||
203 | } | ||
204 | |||
205 | static void | ||
206 | bfa_fcxp_put(struct bfa_fcxp_s *fcxp) | ||
207 | { | ||
208 | struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; | ||
209 | struct bfa_fcxp_wqe_s *wqe; | ||
210 | |||
211 | bfa_q_deq(&mod->wait_q, &wqe); | ||
212 | if (wqe) { | ||
213 | bfa_trc(mod->bfa, fcxp->fcxp_tag); | ||
214 | wqe->alloc_cbfn(wqe->alloc_cbarg, fcxp); | ||
215 | return; | ||
216 | } | ||
217 | |||
218 | bfa_assert(bfa_q_is_on_q(&mod->fcxp_active_q, fcxp)); | ||
219 | list_del(&fcxp->qe); | ||
220 | list_add_tail(&fcxp->qe, &mod->fcxp_free_q); | ||
221 | } | ||
222 | |||
223 | static void | ||
224 | bfa_fcxp_null_comp(void *bfad_fcxp, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
225 | bfa_status_t req_status, u32 rsp_len, | ||
226 | u32 resid_len, struct fchs_s *rsp_fchs) | ||
227 | { | ||
228 | /**discarded fcxp completion */ | ||
229 | } | ||
230 | |||
231 | static void | ||
232 | __bfa_fcxp_send_cbfn(void *cbarg, bfa_boolean_t complete) | ||
233 | { | ||
234 | struct bfa_fcxp_s *fcxp = cbarg; | ||
235 | |||
236 | if (complete) { | ||
237 | fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg, | ||
238 | fcxp->rsp_status, fcxp->rsp_len, | ||
239 | fcxp->residue_len, &fcxp->rsp_fchs); | ||
240 | } else { | ||
241 | bfa_fcxp_free(fcxp); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | static void | ||
246 | hal_fcxp_send_comp(struct bfa_s *bfa, struct bfi_fcxp_send_rsp_s *fcxp_rsp) | ||
247 | { | ||
248 | struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); | ||
249 | struct bfa_fcxp_s *fcxp; | ||
250 | u16 fcxp_tag = bfa_os_ntohs(fcxp_rsp->fcxp_tag); | ||
251 | |||
252 | bfa_trc(bfa, fcxp_tag); | ||
253 | |||
254 | fcxp_rsp->rsp_len = bfa_os_ntohl(fcxp_rsp->rsp_len); | ||
255 | |||
256 | /** | ||
257 | * @todo f/w should not set residue to non-0 when everything | ||
258 | * is received. | ||
259 | */ | ||
260 | if (fcxp_rsp->req_status == BFA_STATUS_OK) | ||
261 | fcxp_rsp->residue_len = 0; | ||
262 | else | ||
263 | fcxp_rsp->residue_len = bfa_os_ntohl(fcxp_rsp->residue_len); | ||
264 | |||
265 | fcxp = BFA_FCXP_FROM_TAG(mod, fcxp_tag); | ||
266 | |||
267 | bfa_assert(fcxp->send_cbfn != NULL); | ||
268 | |||
269 | hal_fcxp_rx_plog(mod->bfa, fcxp, fcxp_rsp); | ||
270 | |||
271 | if (fcxp->send_cbfn != NULL) { | ||
272 | if (fcxp->caller == NULL) { | ||
273 | bfa_trc(mod->bfa, fcxp->fcxp_tag); | ||
274 | |||
275 | fcxp->send_cbfn(fcxp->caller, fcxp, fcxp->send_cbarg, | ||
276 | fcxp_rsp->req_status, fcxp_rsp->rsp_len, | ||
277 | fcxp_rsp->residue_len, &fcxp_rsp->fchs); | ||
278 | /* | ||
279 | * fcxp automatically freed on return from the callback | ||
280 | */ | ||
281 | bfa_fcxp_free(fcxp); | ||
282 | } else { | ||
283 | bfa_trc(mod->bfa, fcxp->fcxp_tag); | ||
284 | fcxp->rsp_status = fcxp_rsp->req_status; | ||
285 | fcxp->rsp_len = fcxp_rsp->rsp_len; | ||
286 | fcxp->residue_len = fcxp_rsp->residue_len; | ||
287 | fcxp->rsp_fchs = fcxp_rsp->fchs; | ||
288 | |||
289 | bfa_cb_queue(bfa, &fcxp->hcb_qe, | ||
290 | __bfa_fcxp_send_cbfn, fcxp); | ||
291 | } | ||
292 | } else { | ||
293 | bfa_trc(bfa, fcxp_tag); | ||
294 | } | ||
295 | } | ||
296 | |||
297 | static void | ||
298 | hal_fcxp_set_local_sges(struct bfi_sge_s *sge, u32 reqlen, u64 req_pa) | ||
299 | { | ||
300 | union bfi_addr_u sga_zero = { {0} }; | ||
301 | |||
302 | sge->sg_len = reqlen; | ||
303 | sge->flags = BFI_SGE_DATA_LAST; | ||
304 | bfa_dma_addr_set(sge[0].sga, req_pa); | ||
305 | bfa_sge_to_be(sge); | ||
306 | sge++; | ||
307 | |||
308 | sge->sga = sga_zero; | ||
309 | sge->sg_len = reqlen; | ||
310 | sge->flags = BFI_SGE_PGDLEN; | ||
311 | bfa_sge_to_be(sge); | ||
312 | } | ||
313 | |||
314 | static void | ||
315 | hal_fcxp_tx_plog(struct bfa_s *bfa, u32 reqlen, struct bfa_fcxp_s *fcxp, | ||
316 | struct fchs_s *fchs) | ||
317 | { | ||
318 | /* | ||
319 | * TODO: TX ox_id | ||
320 | */ | ||
321 | if (reqlen > 0) { | ||
322 | if (fcxp->use_ireqbuf) { | ||
323 | u32 pld_w0 = | ||
324 | *((u32 *) BFA_FCXP_REQ_PLD(fcxp)); | ||
325 | |||
326 | bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP, | ||
327 | BFA_PL_EID_TX, | ||
328 | reqlen + sizeof(struct fchs_s), fchs, pld_w0); | ||
329 | } else { | ||
330 | bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, | ||
331 | BFA_PL_EID_TX, reqlen + sizeof(struct fchs_s), | ||
332 | fchs); | ||
333 | } | ||
334 | } else { | ||
335 | bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_TX, | ||
336 | reqlen + sizeof(struct fchs_s), fchs); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | static void | ||
341 | hal_fcxp_rx_plog(struct bfa_s *bfa, struct bfa_fcxp_s *fcxp, | ||
342 | struct bfi_fcxp_send_rsp_s *fcxp_rsp) | ||
343 | { | ||
344 | if (fcxp_rsp->rsp_len > 0) { | ||
345 | if (fcxp->use_irspbuf) { | ||
346 | u32 pld_w0 = | ||
347 | *((u32 *) BFA_FCXP_RSP_PLD(fcxp)); | ||
348 | |||
349 | bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_FCXP, | ||
350 | BFA_PL_EID_RX, | ||
351 | (u16) fcxp_rsp->rsp_len, | ||
352 | &fcxp_rsp->fchs, pld_w0); | ||
353 | } else { | ||
354 | bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, | ||
355 | BFA_PL_EID_RX, | ||
356 | (u16) fcxp_rsp->rsp_len, | ||
357 | &fcxp_rsp->fchs); | ||
358 | } | ||
359 | } else { | ||
360 | bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_FCXP, BFA_PL_EID_RX, | ||
361 | (u16) fcxp_rsp->rsp_len, &fcxp_rsp->fchs); | ||
362 | } | ||
363 | } | ||
364 | |||
365 | /** | ||
366 | * Handler to resume sending fcxp when space in available in cpe queue. | ||
367 | */ | ||
368 | static void | ||
369 | bfa_fcxp_qresume(void *cbarg) | ||
370 | { | ||
371 | struct bfa_fcxp_s *fcxp = cbarg; | ||
372 | struct bfa_s *bfa = fcxp->fcxp_mod->bfa; | ||
373 | struct bfi_fcxp_send_req_s *send_req; | ||
374 | |||
375 | fcxp->reqq_waiting = BFA_FALSE; | ||
376 | send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP); | ||
377 | bfa_fcxp_queue(fcxp, send_req); | ||
378 | } | ||
379 | |||
380 | /** | ||
381 | * Queue fcxp send request to foimrware. | ||
382 | */ | ||
383 | static void | ||
384 | bfa_fcxp_queue(struct bfa_fcxp_s *fcxp, struct bfi_fcxp_send_req_s *send_req) | ||
385 | { | ||
386 | struct bfa_s *bfa = fcxp->fcxp_mod->bfa; | ||
387 | struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info; | ||
388 | struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info; | ||
389 | struct bfa_rport_s *rport = reqi->bfa_rport; | ||
390 | |||
391 | bfi_h2i_set(send_req->mh, BFI_MC_FCXP, BFI_FCXP_H2I_SEND_REQ, | ||
392 | bfa_lpuid(bfa)); | ||
393 | |||
394 | send_req->fcxp_tag = bfa_os_htons(fcxp->fcxp_tag); | ||
395 | if (rport) { | ||
396 | send_req->rport_fw_hndl = rport->fw_handle; | ||
397 | send_req->max_frmsz = bfa_os_htons(rport->rport_info.max_frmsz); | ||
398 | if (send_req->max_frmsz == 0) | ||
399 | send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ); | ||
400 | } else { | ||
401 | send_req->rport_fw_hndl = 0; | ||
402 | send_req->max_frmsz = bfa_os_htons(FC_MAX_PDUSZ); | ||
403 | } | ||
404 | |||
405 | send_req->vf_id = bfa_os_htons(reqi->vf_id); | ||
406 | send_req->lp_tag = reqi->lp_tag; | ||
407 | send_req->class = reqi->class; | ||
408 | send_req->rsp_timeout = rspi->rsp_timeout; | ||
409 | send_req->cts = reqi->cts; | ||
410 | send_req->fchs = reqi->fchs; | ||
411 | |||
412 | send_req->req_len = bfa_os_htonl(reqi->req_tot_len); | ||
413 | send_req->rsp_maxlen = bfa_os_htonl(rspi->rsp_maxlen); | ||
414 | |||
415 | /* | ||
416 | * setup req sgles | ||
417 | */ | ||
418 | if (fcxp->use_ireqbuf == 1) { | ||
419 | hal_fcxp_set_local_sges(send_req->req_sge, reqi->req_tot_len, | ||
420 | BFA_FCXP_REQ_PLD_PA(fcxp)); | ||
421 | } else { | ||
422 | if (fcxp->nreq_sgles > 0) { | ||
423 | bfa_assert(fcxp->nreq_sgles == 1); | ||
424 | hal_fcxp_set_local_sges(send_req->req_sge, | ||
425 | reqi->req_tot_len, | ||
426 | fcxp->req_sga_cbfn(fcxp->caller, | ||
427 | 0)); | ||
428 | } else { | ||
429 | bfa_assert(reqi->req_tot_len == 0); | ||
430 | hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0); | ||
431 | } | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * setup rsp sgles | ||
436 | */ | ||
437 | if (fcxp->use_irspbuf == 1) { | ||
438 | bfa_assert(rspi->rsp_maxlen <= BFA_FCXP_MAX_LBUF_SZ); | ||
439 | |||
440 | hal_fcxp_set_local_sges(send_req->rsp_sge, rspi->rsp_maxlen, | ||
441 | BFA_FCXP_RSP_PLD_PA(fcxp)); | ||
442 | |||
443 | } else { | ||
444 | if (fcxp->nrsp_sgles > 0) { | ||
445 | bfa_assert(fcxp->nrsp_sgles == 1); | ||
446 | hal_fcxp_set_local_sges(send_req->rsp_sge, | ||
447 | rspi->rsp_maxlen, | ||
448 | fcxp->rsp_sga_cbfn(fcxp->caller, | ||
449 | 0)); | ||
450 | } else { | ||
451 | bfa_assert(rspi->rsp_maxlen == 0); | ||
452 | hal_fcxp_set_local_sges(send_req->rsp_sge, 0, 0); | ||
453 | } | ||
454 | } | ||
455 | |||
456 | hal_fcxp_tx_plog(bfa, reqi->req_tot_len, fcxp, &reqi->fchs); | ||
457 | |||
458 | bfa_reqq_produce(bfa, BFA_REQQ_FCXP); | ||
459 | |||
460 | bfa_trc(bfa, bfa_reqq_pi(bfa, BFA_REQQ_FCXP)); | ||
461 | bfa_trc(bfa, bfa_reqq_ci(bfa, BFA_REQQ_FCXP)); | ||
462 | } | ||
463 | |||
464 | |||
465 | /** | ||
466 | * hal_fcxp_api BFA FCXP API | ||
467 | */ | ||
468 | |||
469 | /** | ||
470 | * Allocate an FCXP instance to send a response or to send a request | ||
471 | * that has a response. Request/response buffers are allocated by caller. | ||
472 | * | ||
473 | * @param[in] bfa BFA bfa instance | ||
474 | * @param[in] nreq_sgles Number of SG elements required for request | ||
475 | * buffer. 0, if fcxp internal buffers are used. | ||
476 | * Use bfa_fcxp_get_reqbuf() to get the | ||
477 | * internal req buffer. | ||
478 | * @param[in] req_sgles SG elements describing request buffer. Will be | ||
479 | * copied in by BFA and hence can be freed on | ||
480 | * return from this function. | ||
481 | * @param[in] get_req_sga function ptr to be called to get a request SG | ||
482 | * Address (given the sge index). | ||
483 | * @param[in] get_req_sglen function ptr to be called to get a request SG | ||
484 | * len (given the sge index). | ||
485 | * @param[in] get_rsp_sga function ptr to be called to get a response SG | ||
486 | * Address (given the sge index). | ||
487 | * @param[in] get_rsp_sglen function ptr to be called to get a response SG | ||
488 | * len (given the sge index). | ||
489 | * | ||
490 | * @return FCXP instance. NULL on failure. | ||
491 | */ | ||
492 | struct bfa_fcxp_s * | ||
493 | bfa_fcxp_alloc(void *caller, struct bfa_s *bfa, int nreq_sgles, | ||
494 | int nrsp_sgles, bfa_fcxp_get_sgaddr_t req_sga_cbfn, | ||
495 | bfa_fcxp_get_sglen_t req_sglen_cbfn, | ||
496 | bfa_fcxp_get_sgaddr_t rsp_sga_cbfn, | ||
497 | bfa_fcxp_get_sglen_t rsp_sglen_cbfn) | ||
498 | { | ||
499 | struct bfa_fcxp_s *fcxp = NULL; | ||
500 | u32 nreq_sgpg, nrsp_sgpg; | ||
501 | |||
502 | bfa_assert(bfa != NULL); | ||
503 | |||
504 | fcxp = bfa_fcxp_get(BFA_FCXP_MOD(bfa)); | ||
505 | if (fcxp == NULL) | ||
506 | return (NULL); | ||
507 | |||
508 | bfa_trc(bfa, fcxp->fcxp_tag); | ||
509 | |||
510 | fcxp->caller = caller; | ||
511 | |||
512 | if (nreq_sgles == 0) { | ||
513 | fcxp->use_ireqbuf = 1; | ||
514 | } else { | ||
515 | bfa_assert(req_sga_cbfn != NULL); | ||
516 | bfa_assert(req_sglen_cbfn != NULL); | ||
517 | |||
518 | fcxp->use_ireqbuf = 0; | ||
519 | fcxp->req_sga_cbfn = req_sga_cbfn; | ||
520 | fcxp->req_sglen_cbfn = req_sglen_cbfn; | ||
521 | |||
522 | fcxp->nreq_sgles = nreq_sgles; | ||
523 | |||
524 | /* | ||
525 | * alloc required sgpgs | ||
526 | */ | ||
527 | if (nreq_sgles > BFI_SGE_INLINE) { | ||
528 | nreq_sgpg = BFA_SGPG_NPAGE(nreq_sgles); | ||
529 | |||
530 | if (bfa_sgpg_malloc | ||
531 | (bfa, &fcxp->req_sgpg_q, nreq_sgpg) | ||
532 | != BFA_STATUS_OK) { | ||
533 | /* bfa_sgpg_wait(bfa, &fcxp->req_sgpg_wqe, | ||
534 | nreq_sgpg); */ | ||
535 | /* | ||
536 | * TODO | ||
537 | */ | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | |||
542 | if (nrsp_sgles == 0) { | ||
543 | fcxp->use_irspbuf = 1; | ||
544 | } else { | ||
545 | bfa_assert(rsp_sga_cbfn != NULL); | ||
546 | bfa_assert(rsp_sglen_cbfn != NULL); | ||
547 | |||
548 | fcxp->use_irspbuf = 0; | ||
549 | fcxp->rsp_sga_cbfn = rsp_sga_cbfn; | ||
550 | fcxp->rsp_sglen_cbfn = rsp_sglen_cbfn; | ||
551 | |||
552 | fcxp->nrsp_sgles = nrsp_sgles; | ||
553 | /* | ||
554 | * alloc required sgpgs | ||
555 | */ | ||
556 | if (nrsp_sgles > BFI_SGE_INLINE) { | ||
557 | nrsp_sgpg = BFA_SGPG_NPAGE(nreq_sgles); | ||
558 | |||
559 | if (bfa_sgpg_malloc | ||
560 | (bfa, &fcxp->rsp_sgpg_q, nrsp_sgpg) | ||
561 | != BFA_STATUS_OK) { | ||
562 | /* bfa_sgpg_wait(bfa, &fcxp->rsp_sgpg_wqe, | ||
563 | nrsp_sgpg); */ | ||
564 | /* | ||
565 | * TODO | ||
566 | */ | ||
567 | } | ||
568 | } | ||
569 | } | ||
570 | |||
571 | return (fcxp); | ||
572 | } | ||
573 | |||
574 | /** | ||
575 | * Get the internal request buffer pointer | ||
576 | * | ||
577 | * @param[in] fcxp BFA fcxp pointer | ||
578 | * | ||
579 | * @return pointer to the internal request buffer | ||
580 | */ | ||
581 | void * | ||
582 | bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp) | ||
583 | { | ||
584 | struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; | ||
585 | void *reqbuf; | ||
586 | |||
587 | bfa_assert(fcxp->use_ireqbuf == 1); | ||
588 | reqbuf = ((u8 *)mod->req_pld_list_kva) + | ||
589 | fcxp->fcxp_tag * mod->req_pld_sz; | ||
590 | return reqbuf; | ||
591 | } | ||
592 | |||
593 | u32 | ||
594 | bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp) | ||
595 | { | ||
596 | struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; | ||
597 | |||
598 | return mod->req_pld_sz; | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * Get the internal response buffer pointer | ||
603 | * | ||
604 | * @param[in] fcxp BFA fcxp pointer | ||
605 | * | ||
606 | * @return pointer to the internal request buffer | ||
607 | */ | ||
608 | void * | ||
609 | bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp) | ||
610 | { | ||
611 | struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; | ||
612 | void *rspbuf; | ||
613 | |||
614 | bfa_assert(fcxp->use_irspbuf == 1); | ||
615 | |||
616 | rspbuf = ((u8 *)mod->rsp_pld_list_kva) + | ||
617 | fcxp->fcxp_tag * mod->rsp_pld_sz; | ||
618 | return rspbuf; | ||
619 | } | ||
620 | |||
621 | /** | ||
622 | * Free the BFA FCXP | ||
623 | * | ||
624 | * @param[in] fcxp BFA fcxp pointer | ||
625 | * | ||
626 | * @return void | ||
627 | */ | ||
628 | void | ||
629 | bfa_fcxp_free(struct bfa_fcxp_s *fcxp) | ||
630 | { | ||
631 | struct bfa_fcxp_mod_s *mod = fcxp->fcxp_mod; | ||
632 | |||
633 | bfa_assert(fcxp != NULL); | ||
634 | bfa_trc(mod->bfa, fcxp->fcxp_tag); | ||
635 | bfa_fcxp_put(fcxp); | ||
636 | } | ||
637 | |||
638 | /** | ||
639 | * Send a FCXP request | ||
640 | * | ||
641 | * @param[in] fcxp BFA fcxp pointer | ||
642 | * @param[in] rport BFA rport pointer. Could be left NULL for WKA rports | ||
643 | * @param[in] vf_id virtual Fabric ID | ||
644 | * @param[in] lp_tag lport tag | ||
645 | * @param[in] cts use Continous sequence | ||
646 | * @param[in] cos fc Class of Service | ||
647 | * @param[in] reqlen request length, does not include FCHS length | ||
648 | * @param[in] fchs fc Header Pointer. The header content will be copied | ||
649 | * in by BFA. | ||
650 | * | ||
651 | * @param[in] cbfn call back function to be called on receiving | ||
652 | * the response | ||
653 | * @param[in] cbarg arg for cbfn | ||
654 | * @param[in] rsp_timeout | ||
655 | * response timeout | ||
656 | * | ||
657 | * @return bfa_status_t | ||
658 | */ | ||
659 | void | ||
660 | bfa_fcxp_send(struct bfa_fcxp_s *fcxp, struct bfa_rport_s *rport, | ||
661 | u16 vf_id, u8 lp_tag, bfa_boolean_t cts, enum fc_cos cos, | ||
662 | u32 reqlen, struct fchs_s *fchs, bfa_cb_fcxp_send_t cbfn, | ||
663 | void *cbarg, u32 rsp_maxlen, u8 rsp_timeout) | ||
664 | { | ||
665 | struct bfa_s *bfa = fcxp->fcxp_mod->bfa; | ||
666 | struct bfa_fcxp_req_info_s *reqi = &fcxp->req_info; | ||
667 | struct bfa_fcxp_rsp_info_s *rspi = &fcxp->rsp_info; | ||
668 | struct bfi_fcxp_send_req_s *send_req; | ||
669 | |||
670 | bfa_trc(bfa, fcxp->fcxp_tag); | ||
671 | |||
672 | /** | ||
673 | * setup request/response info | ||
674 | */ | ||
675 | reqi->bfa_rport = rport; | ||
676 | reqi->vf_id = vf_id; | ||
677 | reqi->lp_tag = lp_tag; | ||
678 | reqi->class = cos; | ||
679 | rspi->rsp_timeout = rsp_timeout; | ||
680 | reqi->cts = cts; | ||
681 | reqi->fchs = *fchs; | ||
682 | reqi->req_tot_len = reqlen; | ||
683 | rspi->rsp_maxlen = rsp_maxlen; | ||
684 | fcxp->send_cbfn = cbfn ? cbfn : bfa_fcxp_null_comp; | ||
685 | fcxp->send_cbarg = cbarg; | ||
686 | |||
687 | /** | ||
688 | * If no room in CPE queue, wait for | ||
689 | */ | ||
690 | send_req = bfa_reqq_next(bfa, BFA_REQQ_FCXP); | ||
691 | if (!send_req) { | ||
692 | bfa_trc(bfa, fcxp->fcxp_tag); | ||
693 | fcxp->reqq_waiting = BFA_TRUE; | ||
694 | bfa_reqq_wait(bfa, BFA_REQQ_FCXP, &fcxp->reqq_wqe); | ||
695 | return; | ||
696 | } | ||
697 | |||
698 | bfa_fcxp_queue(fcxp, send_req); | ||
699 | } | ||
700 | |||
701 | /** | ||
702 | * Abort a BFA FCXP | ||
703 | * | ||
704 | * @param[in] fcxp BFA fcxp pointer | ||
705 | * | ||
706 | * @return void | ||
707 | */ | ||
708 | bfa_status_t | ||
709 | bfa_fcxp_abort(struct bfa_fcxp_s *fcxp) | ||
710 | { | ||
711 | bfa_assert(0); | ||
712 | return (BFA_STATUS_OK); | ||
713 | } | ||
714 | |||
715 | void | ||
716 | bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe, | ||
717 | bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *alloc_cbarg) | ||
718 | { | ||
719 | struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); | ||
720 | |||
721 | bfa_assert(list_empty(&mod->fcxp_free_q)); | ||
722 | |||
723 | wqe->alloc_cbfn = alloc_cbfn; | ||
724 | wqe->alloc_cbarg = alloc_cbarg; | ||
725 | list_add_tail(&wqe->qe, &mod->wait_q); | ||
726 | } | ||
727 | |||
728 | void | ||
729 | bfa_fcxp_walloc_cancel(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe) | ||
730 | { | ||
731 | struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); | ||
732 | |||
733 | bfa_assert(bfa_q_is_on_q(&mod->wait_q, wqe)); | ||
734 | list_del(&wqe->qe); | ||
735 | } | ||
736 | |||
737 | void | ||
738 | bfa_fcxp_discard(struct bfa_fcxp_s *fcxp) | ||
739 | { | ||
740 | /** | ||
741 | * If waiting for room in request queue, cancel reqq wait | ||
742 | * and free fcxp. | ||
743 | */ | ||
744 | if (fcxp->reqq_waiting) { | ||
745 | fcxp->reqq_waiting = BFA_FALSE; | ||
746 | bfa_reqq_wcancel(&fcxp->reqq_wqe); | ||
747 | bfa_fcxp_free(fcxp); | ||
748 | return; | ||
749 | } | ||
750 | |||
751 | fcxp->send_cbfn = bfa_fcxp_null_comp; | ||
752 | } | ||
753 | |||
754 | |||
755 | |||
756 | /** | ||
757 | * hal_fcxp_public BFA FCXP public functions | ||
758 | */ | ||
759 | |||
760 | void | ||
761 | bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) | ||
762 | { | ||
763 | switch (msg->mhdr.msg_id) { | ||
764 | case BFI_FCXP_I2H_SEND_RSP: | ||
765 | hal_fcxp_send_comp(bfa, (struct bfi_fcxp_send_rsp_s *) msg); | ||
766 | break; | ||
767 | |||
768 | default: | ||
769 | bfa_trc(bfa, msg->mhdr.msg_id); | ||
770 | bfa_assert(0); | ||
771 | } | ||
772 | } | ||
773 | |||
774 | u32 | ||
775 | bfa_fcxp_get_maxrsp(struct bfa_s *bfa) | ||
776 | { | ||
777 | struct bfa_fcxp_mod_s *mod = BFA_FCXP_MOD(bfa); | ||
778 | |||
779 | return mod->rsp_pld_sz; | ||
780 | } | ||
781 | |||
782 | |||
diff --git a/drivers/scsi/bfa/bfa_fcxp_priv.h b/drivers/scsi/bfa/bfa_fcxp_priv.h new file mode 100644 index 000000000000..4cda49397da0 --- /dev/null +++ b/drivers/scsi/bfa/bfa_fcxp_priv.h | |||
@@ -0,0 +1,138 @@ | |||
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 | #ifndef __BFA_FCXP_PRIV_H__ | ||
19 | #define __BFA_FCXP_PRIV_H__ | ||
20 | |||
21 | #include <cs/bfa_sm.h> | ||
22 | #include <protocol/fc.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include <bfi/bfi_fcxp.h> | ||
25 | |||
26 | #define BFA_FCXP_MIN (1) | ||
27 | #define BFA_FCXP_MAX_IBUF_SZ (2 * 1024 + 256) | ||
28 | #define BFA_FCXP_MAX_LBUF_SZ (4 * 1024 + 256) | ||
29 | |||
30 | struct bfa_fcxp_mod_s { | ||
31 | struct bfa_s *bfa; /* backpointer to BFA */ | ||
32 | struct bfa_fcxp_s *fcxp_list; /* array of FCXPs */ | ||
33 | u16 num_fcxps; /* max num FCXP requests */ | ||
34 | struct list_head fcxp_free_q; /* free FCXPs */ | ||
35 | struct list_head fcxp_active_q; /* active FCXPs */ | ||
36 | void *req_pld_list_kva; /* list of FCXP req pld */ | ||
37 | u64 req_pld_list_pa; /* list of FCXP req pld */ | ||
38 | void *rsp_pld_list_kva; /* list of FCXP resp pld */ | ||
39 | u64 rsp_pld_list_pa; /* list of FCXP resp pld */ | ||
40 | struct list_head wait_q; /* wait queue for free fcxp */ | ||
41 | u32 req_pld_sz; | ||
42 | u32 rsp_pld_sz; | ||
43 | }; | ||
44 | |||
45 | #define BFA_FCXP_MOD(__bfa) (&(__bfa)->modules.fcxp_mod) | ||
46 | #define BFA_FCXP_FROM_TAG(__mod, __tag) (&(__mod)->fcxp_list[__tag]) | ||
47 | |||
48 | typedef void (*fcxp_send_cb_t) (struct bfa_s *ioc, struct bfa_fcxp_s *fcxp, | ||
49 | void *cb_arg, bfa_status_t req_status, | ||
50 | u32 rsp_len, u32 resid_len, | ||
51 | struct fchs_s *rsp_fchs); | ||
52 | |||
53 | /** | ||
54 | * Information needed for a FCXP request | ||
55 | */ | ||
56 | struct bfa_fcxp_req_info_s { | ||
57 | struct bfa_rport_s *bfa_rport; /* Pointer to the bfa rport that was | ||
58 | *returned from bfa_rport_create(). | ||
59 | *This could be left NULL for WKA or for | ||
60 | *FCXP interactions before the rport | ||
61 | *nexus is established | ||
62 | */ | ||
63 | struct fchs_s fchs; /* request FC header structure */ | ||
64 | u8 cts; /* continous sequence */ | ||
65 | u8 class; /* FC class for the request/response */ | ||
66 | u16 max_frmsz; /* max send frame size */ | ||
67 | u16 vf_id; /* vsan tag if applicable */ | ||
68 | u8 lp_tag; /* lport tag */ | ||
69 | u32 req_tot_len; /* request payload total length */ | ||
70 | }; | ||
71 | |||
72 | struct bfa_fcxp_rsp_info_s { | ||
73 | struct fchs_s rsp_fchs; /* Response frame's FC header will | ||
74 | * be *sent back in this field */ | ||
75 | u8 rsp_timeout; /* timeout in seconds, 0-no response | ||
76 | */ | ||
77 | u8 rsvd2[3]; | ||
78 | u32 rsp_maxlen; /* max response length expected */ | ||
79 | }; | ||
80 | |||
81 | struct bfa_fcxp_s { | ||
82 | struct list_head qe; /* fcxp queue element */ | ||
83 | bfa_sm_t sm; /* state machine */ | ||
84 | void *caller; /* driver or fcs */ | ||
85 | struct bfa_fcxp_mod_s *fcxp_mod; | ||
86 | /* back pointer to fcxp mod */ | ||
87 | u16 fcxp_tag; /* internal tag */ | ||
88 | struct bfa_fcxp_req_info_s req_info; | ||
89 | /* request info */ | ||
90 | struct bfa_fcxp_rsp_info_s rsp_info; | ||
91 | /* response info */ | ||
92 | u8 use_ireqbuf; /* use internal req buf */ | ||
93 | u8 use_irspbuf; /* use internal rsp buf */ | ||
94 | u32 nreq_sgles; /* num request SGLEs */ | ||
95 | u32 nrsp_sgles; /* num response SGLEs */ | ||
96 | struct list_head req_sgpg_q; /* SG pages for request buf */ | ||
97 | struct list_head req_sgpg_wqe; /* wait queue for req SG page */ | ||
98 | struct list_head rsp_sgpg_q; /* SG pages for response buf */ | ||
99 | struct list_head rsp_sgpg_wqe; /* wait queue for rsp SG page */ | ||
100 | |||
101 | bfa_fcxp_get_sgaddr_t req_sga_cbfn; | ||
102 | /* SG elem addr user function */ | ||
103 | bfa_fcxp_get_sglen_t req_sglen_cbfn; | ||
104 | /* SG elem len user function */ | ||
105 | bfa_fcxp_get_sgaddr_t rsp_sga_cbfn; | ||
106 | /* SG elem addr user function */ | ||
107 | bfa_fcxp_get_sglen_t rsp_sglen_cbfn; | ||
108 | /* SG elem len user function */ | ||
109 | bfa_cb_fcxp_send_t send_cbfn; /* send completion callback */ | ||
110 | void *send_cbarg; /* callback arg */ | ||
111 | struct bfa_sge_s req_sge[BFA_FCXP_MAX_SGES]; | ||
112 | /* req SG elems */ | ||
113 | struct bfa_sge_s rsp_sge[BFA_FCXP_MAX_SGES]; | ||
114 | /* rsp SG elems */ | ||
115 | u8 rsp_status; /* comp: rsp status */ | ||
116 | u32 rsp_len; /* comp: actual response len */ | ||
117 | u32 residue_len; /* comp: residual rsp length */ | ||
118 | struct fchs_s rsp_fchs; /* comp: response fchs */ | ||
119 | struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */ | ||
120 | struct bfa_reqq_wait_s reqq_wqe; | ||
121 | bfa_boolean_t reqq_waiting; | ||
122 | }; | ||
123 | |||
124 | #define BFA_FCXP_REQ_PLD(_fcxp) (bfa_fcxp_get_reqbuf(_fcxp)) | ||
125 | |||
126 | #define BFA_FCXP_RSP_FCHS(_fcxp) (&((_fcxp)->rsp_info.fchs)) | ||
127 | #define BFA_FCXP_RSP_PLD(_fcxp) (bfa_fcxp_get_rspbuf(_fcxp)) | ||
128 | |||
129 | #define BFA_FCXP_REQ_PLD_PA(_fcxp) \ | ||
130 | ((_fcxp)->fcxp_mod->req_pld_list_pa + \ | ||
131 | ((_fcxp)->fcxp_mod->req_pld_sz * (_fcxp)->fcxp_tag)) | ||
132 | |||
133 | #define BFA_FCXP_RSP_PLD_PA(_fcxp) \ | ||
134 | ((_fcxp)->fcxp_mod->rsp_pld_list_pa + \ | ||
135 | ((_fcxp)->fcxp_mod->rsp_pld_sz * (_fcxp)->fcxp_tag)) | ||
136 | |||
137 | void bfa_fcxp_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
138 | #endif /* __BFA_FCXP_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_fwimg_priv.h b/drivers/scsi/bfa/bfa_fwimg_priv.h new file mode 100644 index 000000000000..1ec1355924d9 --- /dev/null +++ b/drivers/scsi/bfa/bfa_fwimg_priv.h | |||
@@ -0,0 +1,31 @@ | |||
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 | #ifndef __BFA_FWIMG_PRIV_H__ | ||
19 | #define __BFA_FWIMG_PRIV_H__ | ||
20 | |||
21 | #define BFI_FLASH_CHUNK_SZ 256 /* Flash chunk size */ | ||
22 | #define BFI_FLASH_CHUNK_SZ_WORDS (BFI_FLASH_CHUNK_SZ/sizeof(u32)) | ||
23 | |||
24 | extern u32 *bfi_image_ct_get_chunk(u32 off); | ||
25 | extern u32 bfi_image_ct_size; | ||
26 | extern u32 *bfi_image_cb_get_chunk(u32 off); | ||
27 | extern u32 bfi_image_cb_size; | ||
28 | extern u32 *bfi_image_cb; | ||
29 | extern u32 *bfi_image_ct; | ||
30 | |||
31 | #endif /* __BFA_FWIMG_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_hw_cb.c b/drivers/scsi/bfa/bfa_hw_cb.c new file mode 100644 index 000000000000..ede1438619e2 --- /dev/null +++ b/drivers/scsi/bfa/bfa_hw_cb.c | |||
@@ -0,0 +1,142 @@ | |||
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 | #include <bfa_priv.h> | ||
19 | #include <bfi/bfi_cbreg.h> | ||
20 | |||
21 | void | ||
22 | bfa_hwcb_reginit(struct bfa_s *bfa) | ||
23 | { | ||
24 | struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; | ||
25 | bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc); | ||
26 | int i, q, fn = bfa_ioc_pcifn(&bfa->ioc); | ||
27 | |||
28 | if (fn == 0) { | ||
29 | bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); | ||
30 | bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK); | ||
31 | } else { | ||
32 | bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS); | ||
33 | bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK); | ||
34 | } | ||
35 | |||
36 | for (i = 0; i < BFI_IOC_MAX_CQS; i++) { | ||
37 | /* | ||
38 | * CPE registers | ||
39 | */ | ||
40 | q = CPE_Q_NUM(fn, i); | ||
41 | bfa_regs->cpe_q_pi[i] = (kva + CPE_Q_PI(q)); | ||
42 | bfa_regs->cpe_q_ci[i] = (kva + CPE_Q_CI(q)); | ||
43 | bfa_regs->cpe_q_depth[i] = (kva + CPE_Q_DEPTH(q)); | ||
44 | |||
45 | /* | ||
46 | * RME registers | ||
47 | */ | ||
48 | q = CPE_Q_NUM(fn, i); | ||
49 | bfa_regs->rme_q_pi[i] = (kva + RME_Q_PI(q)); | ||
50 | bfa_regs->rme_q_ci[i] = (kva + RME_Q_CI(q)); | ||
51 | bfa_regs->rme_q_depth[i] = (kva + RME_Q_DEPTH(q)); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | void | ||
56 | bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | static void | ||
61 | bfa_hwcb_rspq_ack_msix(struct bfa_s *bfa, int rspq) | ||
62 | { | ||
63 | bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, | ||
64 | __HFN_INT_RME_Q0 << RME_Q_NUM(bfa_ioc_pcifn(&bfa->ioc), rspq)); | ||
65 | } | ||
66 | |||
67 | void | ||
68 | bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap, | ||
69 | u32 *num_vecs, u32 *max_vec_bit) | ||
70 | { | ||
71 | #define __HFN_NUMINTS 13 | ||
72 | if (bfa_ioc_pcifn(&bfa->ioc) == 0) { | ||
73 | *msix_vecs_bmap = (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | | ||
74 | __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 | | ||
75 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | | ||
76 | __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | | ||
77 | __HFN_INT_MBOX_LPU0); | ||
78 | *max_vec_bit = __HFN_INT_MBOX_LPU0; | ||
79 | } else { | ||
80 | *msix_vecs_bmap = (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | | ||
81 | __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 | | ||
82 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | | ||
83 | __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | | ||
84 | __HFN_INT_MBOX_LPU1); | ||
85 | *max_vec_bit = __HFN_INT_MBOX_LPU1; | ||
86 | } | ||
87 | |||
88 | *msix_vecs_bmap |= (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | | ||
89 | __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS); | ||
90 | *num_vecs = __HFN_NUMINTS; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * No special setup required for crossbow -- vector assignments are implicit. | ||
95 | */ | ||
96 | void | ||
97 | bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs) | ||
98 | { | ||
99 | int i; | ||
100 | |||
101 | bfa_assert((nvecs == 1) || (nvecs == __HFN_NUMINTS)); | ||
102 | |||
103 | bfa->msix.nvecs = nvecs; | ||
104 | if (nvecs == 1) { | ||
105 | for (i = 0; i < BFA_MSIX_CB_MAX; i++) | ||
106 | bfa->msix.handler[i] = bfa_msix_all; | ||
107 | return; | ||
108 | } | ||
109 | |||
110 | for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q7; i++) | ||
111 | bfa->msix.handler[i] = bfa_msix_reqq; | ||
112 | |||
113 | for (i = BFA_MSIX_RME_Q0; i <= BFA_MSIX_RME_Q7; i++) | ||
114 | bfa->msix.handler[i] = bfa_msix_rspq; | ||
115 | |||
116 | for (; i < BFA_MSIX_CB_MAX; i++) | ||
117 | bfa->msix.handler[i] = bfa_msix_lpu_err; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * Crossbow -- dummy, interrupts are masked | ||
122 | */ | ||
123 | void | ||
124 | bfa_hwcb_msix_install(struct bfa_s *bfa) | ||
125 | { | ||
126 | } | ||
127 | |||
128 | void | ||
129 | bfa_hwcb_msix_uninstall(struct bfa_s *bfa) | ||
130 | { | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * No special enable/disable -- vector assignments are implicit. | ||
135 | */ | ||
136 | void | ||
137 | bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) | ||
138 | { | ||
139 | bfa->iocfc.hwif.hw_rspq_ack = bfa_hwcb_rspq_ack_msix; | ||
140 | } | ||
141 | |||
142 | |||
diff --git a/drivers/scsi/bfa/bfa_hw_ct.c b/drivers/scsi/bfa/bfa_hw_ct.c new file mode 100644 index 000000000000..51ae5740e6e9 --- /dev/null +++ b/drivers/scsi/bfa/bfa_hw_ct.c | |||
@@ -0,0 +1,162 @@ | |||
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 | #include <bfa_priv.h> | ||
19 | #include <bfi/bfi_ctreg.h> | ||
20 | #include <bfa_ioc.h> | ||
21 | |||
22 | BFA_TRC_FILE(HAL, IOCFC_CT); | ||
23 | |||
24 | static u32 __ct_msix_err_vec_reg[] = { | ||
25 | HOST_MSIX_ERR_INDEX_FN0, | ||
26 | HOST_MSIX_ERR_INDEX_FN1, | ||
27 | HOST_MSIX_ERR_INDEX_FN2, | ||
28 | HOST_MSIX_ERR_INDEX_FN3, | ||
29 | }; | ||
30 | |||
31 | static void | ||
32 | bfa_hwct_msix_lpu_err_set(struct bfa_s *bfa, bfa_boolean_t msix, int vec) | ||
33 | { | ||
34 | int fn = bfa_ioc_pcifn(&bfa->ioc); | ||
35 | bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc); | ||
36 | |||
37 | if (msix) | ||
38 | bfa_reg_write(kva + __ct_msix_err_vec_reg[fn], vec); | ||
39 | else | ||
40 | bfa_reg_write(kva + __ct_msix_err_vec_reg[fn], 0); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Dummy interrupt handler for handling spurious interrupt during chip-reinit. | ||
45 | */ | ||
46 | static void | ||
47 | bfa_hwct_msix_dummy(struct bfa_s *bfa, int vec) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | void | ||
52 | bfa_hwct_reginit(struct bfa_s *bfa) | ||
53 | { | ||
54 | struct bfa_iocfc_regs_s *bfa_regs = &bfa->iocfc.bfa_regs; | ||
55 | bfa_os_addr_t kva = bfa_ioc_bar0(&bfa->ioc); | ||
56 | int i, q, fn = bfa_ioc_pcifn(&bfa->ioc); | ||
57 | |||
58 | if (fn == 0) { | ||
59 | bfa_regs->intr_status = (kva + HOSTFN0_INT_STATUS); | ||
60 | bfa_regs->intr_mask = (kva + HOSTFN0_INT_MSK); | ||
61 | } else { | ||
62 | bfa_regs->intr_status = (kva + HOSTFN1_INT_STATUS); | ||
63 | bfa_regs->intr_mask = (kva + HOSTFN1_INT_MSK); | ||
64 | } | ||
65 | |||
66 | for (i = 0; i < BFI_IOC_MAX_CQS; i++) { | ||
67 | /* | ||
68 | * CPE registers | ||
69 | */ | ||
70 | q = CPE_Q_NUM(fn, i); | ||
71 | bfa_regs->cpe_q_pi[i] = (kva + CPE_PI_PTR_Q(q << 5)); | ||
72 | bfa_regs->cpe_q_ci[i] = (kva + CPE_CI_PTR_Q(q << 5)); | ||
73 | bfa_regs->cpe_q_depth[i] = (kva + CPE_DEPTH_Q(q << 5)); | ||
74 | bfa_regs->cpe_q_ctrl[i] = (kva + CPE_QCTRL_Q(q << 5)); | ||
75 | |||
76 | /* | ||
77 | * RME registers | ||
78 | */ | ||
79 | q = CPE_Q_NUM(fn, i); | ||
80 | bfa_regs->rme_q_pi[i] = (kva + RME_PI_PTR_Q(q << 5)); | ||
81 | bfa_regs->rme_q_ci[i] = (kva + RME_CI_PTR_Q(q << 5)); | ||
82 | bfa_regs->rme_q_depth[i] = (kva + RME_DEPTH_Q(q << 5)); | ||
83 | bfa_regs->rme_q_ctrl[i] = (kva + RME_QCTRL_Q(q << 5)); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | void | ||
88 | bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq) | ||
89 | { | ||
90 | u32 r32; | ||
91 | |||
92 | r32 = bfa_reg_read(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq]); | ||
93 | bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ctrl[rspq], r32); | ||
94 | } | ||
95 | |||
96 | void | ||
97 | bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap, | ||
98 | u32 *num_vecs, u32 *max_vec_bit) | ||
99 | { | ||
100 | *msix_vecs_bmap = (1 << BFA_MSIX_CT_MAX) - 1; | ||
101 | *max_vec_bit = (1 << (BFA_MSIX_CT_MAX - 1)); | ||
102 | *num_vecs = BFA_MSIX_CT_MAX; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * Setup MSI-X vector for catapult | ||
107 | */ | ||
108 | void | ||
109 | bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs) | ||
110 | { | ||
111 | bfa_assert((nvecs == 1) || (nvecs == BFA_MSIX_CT_MAX)); | ||
112 | bfa_trc(bfa, nvecs); | ||
113 | |||
114 | bfa->msix.nvecs = nvecs; | ||
115 | bfa_hwct_msix_uninstall(bfa); | ||
116 | } | ||
117 | |||
118 | void | ||
119 | bfa_hwct_msix_install(struct bfa_s *bfa) | ||
120 | { | ||
121 | int i; | ||
122 | |||
123 | if (bfa->msix.nvecs == 0) | ||
124 | return; | ||
125 | |||
126 | if (bfa->msix.nvecs == 1) { | ||
127 | for (i = 0; i < BFA_MSIX_CT_MAX; i++) | ||
128 | bfa->msix.handler[i] = bfa_msix_all; | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | for (i = BFA_MSIX_CPE_Q0; i <= BFA_MSIX_CPE_Q3; i++) | ||
133 | bfa->msix.handler[i] = bfa_msix_reqq; | ||
134 | |||
135 | for (; i <= BFA_MSIX_RME_Q3; i++) | ||
136 | bfa->msix.handler[i] = bfa_msix_rspq; | ||
137 | |||
138 | bfa_assert(i == BFA_MSIX_LPU_ERR); | ||
139 | bfa->msix.handler[BFA_MSIX_LPU_ERR] = bfa_msix_lpu_err; | ||
140 | } | ||
141 | |||
142 | void | ||
143 | bfa_hwct_msix_uninstall(struct bfa_s *bfa) | ||
144 | { | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i < BFA_MSIX_CT_MAX; i++) | ||
148 | bfa->msix.handler[i] = bfa_hwct_msix_dummy; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Enable MSI-X vectors | ||
153 | */ | ||
154 | void | ||
155 | bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix) | ||
156 | { | ||
157 | bfa_trc(bfa, 0); | ||
158 | bfa_hwct_msix_lpu_err_set(bfa, msix, BFA_MSIX_LPU_ERR); | ||
159 | bfa_ioc_isr_mode_set(&bfa->ioc, msix); | ||
160 | } | ||
161 | |||
162 | |||
diff --git a/drivers/scsi/bfa/bfa_intr.c b/drivers/scsi/bfa/bfa_intr.c new file mode 100644 index 000000000000..0ca125712a04 --- /dev/null +++ b/drivers/scsi/bfa/bfa_intr.c | |||
@@ -0,0 +1,218 @@ | |||
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 | #include <bfa.h> | ||
18 | #include <bfi/bfi_cbreg.h> | ||
19 | #include <bfa_port_priv.h> | ||
20 | #include <bfa_intr_priv.h> | ||
21 | #include <cs/bfa_debug.h> | ||
22 | |||
23 | BFA_TRC_FILE(HAL, INTR); | ||
24 | |||
25 | static void | ||
26 | bfa_msix_errint(struct bfa_s *bfa, u32 intr) | ||
27 | { | ||
28 | bfa_ioc_error_isr(&bfa->ioc); | ||
29 | } | ||
30 | |||
31 | static void | ||
32 | bfa_msix_lpu(struct bfa_s *bfa) | ||
33 | { | ||
34 | bfa_ioc_mbox_isr(&bfa->ioc); | ||
35 | } | ||
36 | |||
37 | void | ||
38 | bfa_msix_all(struct bfa_s *bfa, int vec) | ||
39 | { | ||
40 | bfa_intx(bfa); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * hal_intr_api | ||
45 | */ | ||
46 | bfa_boolean_t | ||
47 | bfa_intx(struct bfa_s *bfa) | ||
48 | { | ||
49 | u32 intr, qintr; | ||
50 | int queue; | ||
51 | |||
52 | intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status); | ||
53 | if (!intr) | ||
54 | return BFA_FALSE; | ||
55 | |||
56 | /** | ||
57 | * RME completion queue interrupt | ||
58 | */ | ||
59 | qintr = intr & __HFN_INT_RME_MASK; | ||
60 | bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr); | ||
61 | |||
62 | for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue ++) { | ||
63 | if (intr & (__HFN_INT_RME_Q0 << queue)) | ||
64 | bfa_msix_rspq(bfa, queue & (BFI_IOC_MAX_CQS - 1)); | ||
65 | } | ||
66 | intr &= ~qintr; | ||
67 | if (!intr) | ||
68 | return BFA_TRUE; | ||
69 | |||
70 | /** | ||
71 | * CPE completion queue interrupt | ||
72 | */ | ||
73 | qintr = intr & __HFN_INT_CPE_MASK; | ||
74 | bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, qintr); | ||
75 | |||
76 | for (queue = 0; queue < BFI_IOC_MAX_CQS_ASIC; queue++) { | ||
77 | if (intr & (__HFN_INT_CPE_Q0 << queue)) | ||
78 | bfa_msix_reqq(bfa, queue & (BFI_IOC_MAX_CQS - 1)); | ||
79 | } | ||
80 | intr &= ~qintr; | ||
81 | if (!intr) | ||
82 | return BFA_TRUE; | ||
83 | |||
84 | bfa_msix_lpu_err(bfa, intr); | ||
85 | |||
86 | return BFA_TRUE; | ||
87 | } | ||
88 | |||
89 | void | ||
90 | bfa_isr_enable(struct bfa_s *bfa) | ||
91 | { | ||
92 | u32 intr_unmask; | ||
93 | int pci_func = bfa_ioc_pcifn(&bfa->ioc); | ||
94 | |||
95 | bfa_trc(bfa, pci_func); | ||
96 | |||
97 | bfa_msix_install(bfa); | ||
98 | intr_unmask = (__HFN_INT_ERR_EMC | __HFN_INT_ERR_LPU0 | | ||
99 | __HFN_INT_ERR_LPU1 | __HFN_INT_ERR_PSS); | ||
100 | |||
101 | if (pci_func == 0) | ||
102 | intr_unmask |= (__HFN_INT_CPE_Q0 | __HFN_INT_CPE_Q1 | | ||
103 | __HFN_INT_CPE_Q2 | __HFN_INT_CPE_Q3 | | ||
104 | __HFN_INT_RME_Q0 | __HFN_INT_RME_Q1 | | ||
105 | __HFN_INT_RME_Q2 | __HFN_INT_RME_Q3 | | ||
106 | __HFN_INT_MBOX_LPU0); | ||
107 | else | ||
108 | intr_unmask |= (__HFN_INT_CPE_Q4 | __HFN_INT_CPE_Q5 | | ||
109 | __HFN_INT_CPE_Q6 | __HFN_INT_CPE_Q7 | | ||
110 | __HFN_INT_RME_Q4 | __HFN_INT_RME_Q5 | | ||
111 | __HFN_INT_RME_Q6 | __HFN_INT_RME_Q7 | | ||
112 | __HFN_INT_MBOX_LPU1); | ||
113 | |||
114 | bfa_reg_write(bfa->iocfc.bfa_regs.intr_status, intr_unmask); | ||
115 | bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, ~intr_unmask); | ||
116 | bfa_isr_mode_set(bfa, bfa->msix.nvecs != 0); | ||
117 | } | ||
118 | |||
119 | void | ||
120 | bfa_isr_disable(struct bfa_s *bfa) | ||
121 | { | ||
122 | bfa_isr_mode_set(bfa, BFA_FALSE); | ||
123 | bfa_reg_write(bfa->iocfc.bfa_regs.intr_mask, -1L); | ||
124 | bfa_msix_uninstall(bfa); | ||
125 | } | ||
126 | |||
127 | void | ||
128 | bfa_msix_reqq(struct bfa_s *bfa, int qid) | ||
129 | { | ||
130 | struct list_head *waitq, *qe, *qen; | ||
131 | struct bfa_reqq_wait_s *wqe; | ||
132 | |||
133 | qid &= (BFI_IOC_MAX_CQS - 1); | ||
134 | |||
135 | waitq = bfa_reqq(bfa, qid); | ||
136 | list_for_each_safe(qe, qen, waitq) { | ||
137 | /** | ||
138 | * Callback only as long as there is room in request queue | ||
139 | */ | ||
140 | if (bfa_reqq_full(bfa, qid)) | ||
141 | break; | ||
142 | |||
143 | list_del(qe); | ||
144 | wqe = (struct bfa_reqq_wait_s *) qe; | ||
145 | wqe->qresume(wqe->cbarg); | ||
146 | } | ||
147 | } | ||
148 | |||
149 | void | ||
150 | bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
151 | { | ||
152 | bfa_trc(bfa, m->mhdr.msg_class); | ||
153 | bfa_trc(bfa, m->mhdr.msg_id); | ||
154 | bfa_trc(bfa, m->mhdr.mtag.i2htok); | ||
155 | bfa_assert(0); | ||
156 | bfa_trc_stop(bfa->trcmod); | ||
157 | } | ||
158 | |||
159 | void | ||
160 | bfa_msix_rspq(struct bfa_s *bfa, int rsp_qid) | ||
161 | { | ||
162 | struct bfi_msg_s *m; | ||
163 | u32 pi, ci; | ||
164 | |||
165 | bfa_trc_fp(bfa, rsp_qid); | ||
166 | |||
167 | rsp_qid &= (BFI_IOC_MAX_CQS - 1); | ||
168 | |||
169 | bfa->iocfc.hwif.hw_rspq_ack(bfa, rsp_qid); | ||
170 | |||
171 | ci = bfa_rspq_ci(bfa, rsp_qid); | ||
172 | pi = bfa_rspq_pi(bfa, rsp_qid); | ||
173 | |||
174 | bfa_trc_fp(bfa, ci); | ||
175 | bfa_trc_fp(bfa, pi); | ||
176 | |||
177 | if (bfa->rme_process) { | ||
178 | while (ci != pi) { | ||
179 | m = bfa_rspq_elem(bfa, rsp_qid, ci); | ||
180 | bfa_assert_fp(m->mhdr.msg_class < BFI_MC_MAX); | ||
181 | |||
182 | bfa_isrs[m->mhdr.msg_class] (bfa, m); | ||
183 | |||
184 | CQ_INCR(ci, bfa->iocfc.cfg.drvcfg.num_rspq_elems); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * update CI | ||
190 | */ | ||
191 | bfa_rspq_ci(bfa, rsp_qid) = pi; | ||
192 | bfa_reg_write(bfa->iocfc.bfa_regs.rme_q_ci[rsp_qid], pi); | ||
193 | bfa_os_mmiowb(); | ||
194 | } | ||
195 | |||
196 | void | ||
197 | bfa_msix_lpu_err(struct bfa_s *bfa, int vec) | ||
198 | { | ||
199 | u32 intr; | ||
200 | |||
201 | intr = bfa_reg_read(bfa->iocfc.bfa_regs.intr_status); | ||
202 | |||
203 | if (intr & (__HFN_INT_MBOX_LPU0 | __HFN_INT_MBOX_LPU1)) | ||
204 | bfa_msix_lpu(bfa); | ||
205 | |||
206 | if (intr & (__HFN_INT_ERR_EMC | | ||
207 | __HFN_INT_ERR_LPU0 | __HFN_INT_ERR_LPU1 | | ||
208 | __HFN_INT_ERR_PSS)) | ||
209 | bfa_msix_errint(bfa, intr); | ||
210 | } | ||
211 | |||
212 | void | ||
213 | bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func) | ||
214 | { | ||
215 | bfa_isrs[mc] = isr_func; | ||
216 | } | ||
217 | |||
218 | |||
diff --git a/drivers/scsi/bfa/bfa_intr_priv.h b/drivers/scsi/bfa/bfa_intr_priv.h new file mode 100644 index 000000000000..8ce6e6b105c8 --- /dev/null +++ b/drivers/scsi/bfa/bfa_intr_priv.h | |||
@@ -0,0 +1,115 @@ | |||
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 | #ifndef __BFA_INTR_PRIV_H__ | ||
19 | #define __BFA_INTR_PRIV_H__ | ||
20 | |||
21 | /** | ||
22 | * Message handler | ||
23 | */ | ||
24 | typedef void (*bfa_isr_func_t) (struct bfa_s *bfa, struct bfi_msg_s *m); | ||
25 | void bfa_isr_unhandled(struct bfa_s *bfa, struct bfi_msg_s *m); | ||
26 | void bfa_isr_bind(enum bfi_mclass mc, bfa_isr_func_t isr_func); | ||
27 | |||
28 | |||
29 | #define bfa_reqq_pi(__bfa, __reqq) (__bfa)->iocfc.req_cq_pi[__reqq] | ||
30 | #define bfa_reqq_ci(__bfa, __reqq) \ | ||
31 | *(u32 *)((__bfa)->iocfc.req_cq_shadow_ci[__reqq].kva) | ||
32 | |||
33 | #define bfa_reqq_full(__bfa, __reqq) \ | ||
34 | (((bfa_reqq_pi(__bfa, __reqq) + 1) & \ | ||
35 | ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1)) == \ | ||
36 | bfa_reqq_ci(__bfa, __reqq)) | ||
37 | |||
38 | #define bfa_reqq_next(__bfa, __reqq) \ | ||
39 | (bfa_reqq_full(__bfa, __reqq) ? NULL : \ | ||
40 | ((void *)((struct bfi_msg_s *)((__bfa)->iocfc.req_cq_ba[__reqq].kva) \ | ||
41 | + bfa_reqq_pi((__bfa), (__reqq))))) | ||
42 | |||
43 | #define bfa_reqq_produce(__bfa, __reqq) do { \ | ||
44 | (__bfa)->iocfc.req_cq_pi[__reqq]++; \ | ||
45 | (__bfa)->iocfc.req_cq_pi[__reqq] &= \ | ||
46 | ((__bfa)->iocfc.cfg.drvcfg.num_reqq_elems - 1); \ | ||
47 | bfa_reg_write((__bfa)->iocfc.bfa_regs.cpe_q_pi[__reqq], \ | ||
48 | (__bfa)->iocfc.req_cq_pi[__reqq]); \ | ||
49 | bfa_os_mmiowb(); \ | ||
50 | } while (0) | ||
51 | |||
52 | #define bfa_rspq_pi(__bfa, __rspq) \ | ||
53 | *(u32 *)((__bfa)->iocfc.rsp_cq_shadow_pi[__rspq].kva) | ||
54 | |||
55 | #define bfa_rspq_ci(__bfa, __rspq) (__bfa)->iocfc.rsp_cq_ci[__rspq] | ||
56 | #define bfa_rspq_elem(__bfa, __rspq, __ci) \ | ||
57 | &((struct bfi_msg_s *)((__bfa)->iocfc.rsp_cq_ba[__rspq].kva))[__ci] | ||
58 | |||
59 | #define CQ_INCR(__index, __size) \ | ||
60 | (__index)++; (__index) &= ((__size) - 1) | ||
61 | |||
62 | /** | ||
63 | * Queue element to wait for room in request queue. FIFO order is | ||
64 | * maintained when fullfilling requests. | ||
65 | */ | ||
66 | struct bfa_reqq_wait_s { | ||
67 | struct list_head qe; | ||
68 | void (*qresume) (void *cbarg); | ||
69 | void *cbarg; | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * Circular queue usage assignments | ||
74 | */ | ||
75 | enum { | ||
76 | BFA_REQQ_IOC = 0, /* all low-priority IOC msgs */ | ||
77 | BFA_REQQ_FCXP = 0, /* all FCXP messages */ | ||
78 | BFA_REQQ_LPS = 0, /* all lport service msgs */ | ||
79 | BFA_REQQ_PORT = 0, /* all port messages */ | ||
80 | BFA_REQQ_FLASH = 0, /* for flash module */ | ||
81 | BFA_REQQ_DIAG = 0, /* for diag module */ | ||
82 | BFA_REQQ_RPORT = 0, /* all port messages */ | ||
83 | BFA_REQQ_SBOOT = 0, /* all san boot messages */ | ||
84 | BFA_REQQ_QOS_LO = 1, /* all low priority IO */ | ||
85 | BFA_REQQ_QOS_MD = 2, /* all medium priority IO */ | ||
86 | BFA_REQQ_QOS_HI = 3, /* all high priority IO */ | ||
87 | }; | ||
88 | |||
89 | static inline void | ||
90 | bfa_reqq_winit(struct bfa_reqq_wait_s *wqe, void (*qresume) (void *cbarg), | ||
91 | void *cbarg) | ||
92 | { | ||
93 | wqe->qresume = qresume; | ||
94 | wqe->cbarg = cbarg; | ||
95 | } | ||
96 | |||
97 | #define bfa_reqq(__bfa, __reqq) &(__bfa)->reqq_waitq[__reqq] | ||
98 | |||
99 | /** | ||
100 | * static inline void | ||
101 | * bfa_reqq_wait(struct bfa_s *bfa, int reqq, struct bfa_reqq_wait_s *wqe) | ||
102 | */ | ||
103 | #define bfa_reqq_wait(__bfa, __reqq, __wqe) do { \ | ||
104 | \ | ||
105 | struct list_head *waitq = bfa_reqq(__bfa, __reqq); \ | ||
106 | \ | ||
107 | bfa_assert(((__reqq) < BFI_IOC_MAX_CQS)); \ | ||
108 | bfa_assert((__wqe)->qresume && (__wqe)->cbarg); \ | ||
109 | \ | ||
110 | list_add_tail(&(__wqe)->qe, waitq); \ | ||
111 | } while (0) | ||
112 | |||
113 | #define bfa_reqq_wcancel(__wqe) list_del(&(__wqe)->qe) | ||
114 | |||
115 | #endif /* __BFA_INTR_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c new file mode 100644 index 000000000000..149348934ce3 --- /dev/null +++ b/drivers/scsi/bfa/bfa_ioc.c | |||
@@ -0,0 +1,2382 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfa_ioc.h> | ||
20 | #include <bfa_fwimg_priv.h> | ||
21 | #include <bfa_trcmod_priv.h> | ||
22 | #include <cs/bfa_debug.h> | ||
23 | #include <bfi/bfi_ioc.h> | ||
24 | #include <bfi/bfi_ctreg.h> | ||
25 | #include <aen/bfa_aen_ioc.h> | ||
26 | #include <aen/bfa_aen.h> | ||
27 | #include <log/bfa_log_hal.h> | ||
28 | #include <defs/bfa_defs_pci.h> | ||
29 | |||
30 | BFA_TRC_FILE(HAL, IOC); | ||
31 | |||
32 | /** | ||
33 | * IOC local definitions | ||
34 | */ | ||
35 | #define BFA_IOC_TOV 2000 /* msecs */ | ||
36 | #define BFA_IOC_HB_TOV 1000 /* msecs */ | ||
37 | #define BFA_IOC_HB_FAIL_MAX 4 | ||
38 | #define BFA_IOC_HWINIT_MAX 2 | ||
39 | #define BFA_IOC_FWIMG_MINSZ (16 * 1024) | ||
40 | #define BFA_IOC_TOV_RECOVER (BFA_IOC_HB_FAIL_MAX * BFA_IOC_HB_TOV \ | ||
41 | + BFA_IOC_TOV) | ||
42 | |||
43 | #define bfa_ioc_timer_start(__ioc) \ | ||
44 | bfa_timer_begin((__ioc)->timer_mod, &(__ioc)->ioc_timer, \ | ||
45 | bfa_ioc_timeout, (__ioc), BFA_IOC_TOV) | ||
46 | #define bfa_ioc_timer_stop(__ioc) bfa_timer_stop(&(__ioc)->ioc_timer) | ||
47 | |||
48 | #define BFA_DBG_FWTRC_ENTS (BFI_IOC_TRC_ENTS) | ||
49 | #define BFA_DBG_FWTRC_LEN \ | ||
50 | (BFA_DBG_FWTRC_ENTS * sizeof(struct bfa_trc_s) + \ | ||
51 | (sizeof(struct bfa_trc_mod_s) - \ | ||
52 | BFA_TRC_MAX * sizeof(struct bfa_trc_s))) | ||
53 | #define BFA_DBG_FWTRC_OFF(_fn) (BFI_IOC_TRC_OFF + BFA_DBG_FWTRC_LEN * (_fn)) | ||
54 | #define bfa_ioc_stats(_ioc, _stats) (_ioc)->stats._stats ++ | ||
55 | |||
56 | #define BFA_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS) | ||
57 | #define BFA_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) | ||
58 | #define BFA_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) | ||
59 | bfa_boolean_t bfa_auto_recover = BFA_FALSE; | ||
60 | |||
61 | /* | ||
62 | * forward declarations | ||
63 | */ | ||
64 | static void bfa_ioc_aen_post(struct bfa_ioc_s *bfa, | ||
65 | enum bfa_ioc_aen_event event); | ||
66 | static void bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc); | ||
67 | static void bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc); | ||
68 | static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc); | ||
69 | static void bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force); | ||
70 | static void bfa_ioc_timeout(void *ioc); | ||
71 | static void bfa_ioc_send_enable(struct bfa_ioc_s *ioc); | ||
72 | static void bfa_ioc_send_disable(struct bfa_ioc_s *ioc); | ||
73 | static void bfa_ioc_send_getattr(struct bfa_ioc_s *ioc); | ||
74 | static void bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc); | ||
75 | static void bfa_ioc_hb_stop(struct bfa_ioc_s *ioc); | ||
76 | static void bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force); | ||
77 | static void bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc); | ||
78 | static void bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc); | ||
79 | static void bfa_ioc_recover(struct bfa_ioc_s *ioc); | ||
80 | static bfa_boolean_t bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc); | ||
81 | static void bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc); | ||
82 | static void bfa_ioc_disable_comp(struct bfa_ioc_s *ioc); | ||
83 | static void bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc); | ||
84 | |||
85 | /** | ||
86 | * bfa_ioc_sm | ||
87 | */ | ||
88 | |||
89 | /** | ||
90 | * IOC state machine events | ||
91 | */ | ||
92 | enum ioc_event { | ||
93 | IOC_E_ENABLE = 1, /* IOC enable request */ | ||
94 | IOC_E_DISABLE = 2, /* IOC disable request */ | ||
95 | IOC_E_TIMEOUT = 3, /* f/w response timeout */ | ||
96 | IOC_E_FWREADY = 4, /* f/w initialization done */ | ||
97 | IOC_E_FWRSP_GETATTR = 5, /* IOC get attribute response */ | ||
98 | IOC_E_FWRSP_ENABLE = 6, /* enable f/w response */ | ||
99 | IOC_E_FWRSP_DISABLE = 7, /* disable f/w response */ | ||
100 | IOC_E_HBFAIL = 8, /* heartbeat failure */ | ||
101 | IOC_E_HWERROR = 9, /* hardware error interrupt */ | ||
102 | IOC_E_SEMLOCKED = 10, /* h/w semaphore is locked */ | ||
103 | IOC_E_DETACH = 11, /* driver detach cleanup */ | ||
104 | }; | ||
105 | |||
106 | bfa_fsm_state_decl(bfa_ioc, reset, struct bfa_ioc_s, enum ioc_event); | ||
107 | bfa_fsm_state_decl(bfa_ioc, fwcheck, struct bfa_ioc_s, enum ioc_event); | ||
108 | bfa_fsm_state_decl(bfa_ioc, mismatch, struct bfa_ioc_s, enum ioc_event); | ||
109 | bfa_fsm_state_decl(bfa_ioc, semwait, struct bfa_ioc_s, enum ioc_event); | ||
110 | bfa_fsm_state_decl(bfa_ioc, hwinit, struct bfa_ioc_s, enum ioc_event); | ||
111 | bfa_fsm_state_decl(bfa_ioc, enabling, struct bfa_ioc_s, enum ioc_event); | ||
112 | bfa_fsm_state_decl(bfa_ioc, getattr, struct bfa_ioc_s, enum ioc_event); | ||
113 | bfa_fsm_state_decl(bfa_ioc, op, struct bfa_ioc_s, enum ioc_event); | ||
114 | bfa_fsm_state_decl(bfa_ioc, initfail, struct bfa_ioc_s, enum ioc_event); | ||
115 | bfa_fsm_state_decl(bfa_ioc, hbfail, struct bfa_ioc_s, enum ioc_event); | ||
116 | bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc_s, enum ioc_event); | ||
117 | bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc_s, enum ioc_event); | ||
118 | |||
119 | static struct bfa_sm_table_s ioc_sm_table[] = { | ||
120 | {BFA_SM(bfa_ioc_sm_reset), BFA_IOC_RESET}, | ||
121 | {BFA_SM(bfa_ioc_sm_fwcheck), BFA_IOC_FWMISMATCH}, | ||
122 | {BFA_SM(bfa_ioc_sm_mismatch), BFA_IOC_FWMISMATCH}, | ||
123 | {BFA_SM(bfa_ioc_sm_semwait), BFA_IOC_SEMWAIT}, | ||
124 | {BFA_SM(bfa_ioc_sm_hwinit), BFA_IOC_HWINIT}, | ||
125 | {BFA_SM(bfa_ioc_sm_enabling), BFA_IOC_HWINIT}, | ||
126 | {BFA_SM(bfa_ioc_sm_getattr), BFA_IOC_GETATTR}, | ||
127 | {BFA_SM(bfa_ioc_sm_op), BFA_IOC_OPERATIONAL}, | ||
128 | {BFA_SM(bfa_ioc_sm_initfail), BFA_IOC_INITFAIL}, | ||
129 | {BFA_SM(bfa_ioc_sm_hbfail), BFA_IOC_HBFAIL}, | ||
130 | {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, | ||
131 | {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, | ||
132 | }; | ||
133 | |||
134 | /** | ||
135 | * Reset entry actions -- initialize state machine | ||
136 | */ | ||
137 | static void | ||
138 | bfa_ioc_sm_reset_entry(struct bfa_ioc_s *ioc) | ||
139 | { | ||
140 | ioc->retry_count = 0; | ||
141 | ioc->auto_recover = bfa_auto_recover; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * Beginning state. IOC is in reset state. | ||
146 | */ | ||
147 | static void | ||
148 | bfa_ioc_sm_reset(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
149 | { | ||
150 | bfa_trc(ioc, event); | ||
151 | |||
152 | switch (event) { | ||
153 | case IOC_E_ENABLE: | ||
154 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck); | ||
155 | break; | ||
156 | |||
157 | case IOC_E_DISABLE: | ||
158 | bfa_ioc_disable_comp(ioc); | ||
159 | break; | ||
160 | |||
161 | case IOC_E_DETACH: | ||
162 | break; | ||
163 | |||
164 | default: | ||
165 | bfa_sm_fault(ioc, event); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | /** | ||
170 | * Semaphore should be acquired for version check. | ||
171 | */ | ||
172 | static void | ||
173 | bfa_ioc_sm_fwcheck_entry(struct bfa_ioc_s *ioc) | ||
174 | { | ||
175 | bfa_ioc_hw_sem_get(ioc); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * Awaiting h/w semaphore to continue with version check. | ||
180 | */ | ||
181 | static void | ||
182 | bfa_ioc_sm_fwcheck(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
183 | { | ||
184 | bfa_trc(ioc, event); | ||
185 | |||
186 | switch (event) { | ||
187 | case IOC_E_SEMLOCKED: | ||
188 | if (bfa_ioc_firmware_lock(ioc)) { | ||
189 | ioc->retry_count = 0; | ||
190 | bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit); | ||
191 | } else { | ||
192 | bfa_ioc_hw_sem_release(ioc); | ||
193 | bfa_fsm_set_state(ioc, bfa_ioc_sm_mismatch); | ||
194 | } | ||
195 | break; | ||
196 | |||
197 | case IOC_E_DISABLE: | ||
198 | bfa_ioc_disable_comp(ioc); | ||
199 | /* | ||
200 | * fall through | ||
201 | */ | ||
202 | |||
203 | case IOC_E_DETACH: | ||
204 | bfa_ioc_hw_sem_get_cancel(ioc); | ||
205 | bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); | ||
206 | break; | ||
207 | |||
208 | case IOC_E_FWREADY: | ||
209 | break; | ||
210 | |||
211 | default: | ||
212 | bfa_sm_fault(ioc, event); | ||
213 | } | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * Notify enable completion callback and generate mismatch AEN. | ||
218 | */ | ||
219 | static void | ||
220 | bfa_ioc_sm_mismatch_entry(struct bfa_ioc_s *ioc) | ||
221 | { | ||
222 | /** | ||
223 | * Provide enable completion callback and AEN notification only once. | ||
224 | */ | ||
225 | if (ioc->retry_count == 0) { | ||
226 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); | ||
227 | bfa_ioc_aen_post(ioc, BFA_IOC_AEN_FWMISMATCH); | ||
228 | } | ||
229 | ioc->retry_count++; | ||
230 | bfa_ioc_timer_start(ioc); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * Awaiting firmware version match. | ||
235 | */ | ||
236 | static void | ||
237 | bfa_ioc_sm_mismatch(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
238 | { | ||
239 | bfa_trc(ioc, event); | ||
240 | |||
241 | switch (event) { | ||
242 | case IOC_E_TIMEOUT: | ||
243 | bfa_fsm_set_state(ioc, bfa_ioc_sm_fwcheck); | ||
244 | break; | ||
245 | |||
246 | case IOC_E_DISABLE: | ||
247 | bfa_ioc_disable_comp(ioc); | ||
248 | /* | ||
249 | * fall through | ||
250 | */ | ||
251 | |||
252 | case IOC_E_DETACH: | ||
253 | bfa_ioc_timer_stop(ioc); | ||
254 | bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); | ||
255 | break; | ||
256 | |||
257 | case IOC_E_FWREADY: | ||
258 | break; | ||
259 | |||
260 | default: | ||
261 | bfa_sm_fault(ioc, event); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * Request for semaphore. | ||
267 | */ | ||
268 | static void | ||
269 | bfa_ioc_sm_semwait_entry(struct bfa_ioc_s *ioc) | ||
270 | { | ||
271 | bfa_ioc_hw_sem_get(ioc); | ||
272 | } | ||
273 | |||
274 | /** | ||
275 | * Awaiting semaphore for h/w initialzation. | ||
276 | */ | ||
277 | static void | ||
278 | bfa_ioc_sm_semwait(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
279 | { | ||
280 | bfa_trc(ioc, event); | ||
281 | |||
282 | switch (event) { | ||
283 | case IOC_E_SEMLOCKED: | ||
284 | ioc->retry_count = 0; | ||
285 | bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit); | ||
286 | break; | ||
287 | |||
288 | case IOC_E_DISABLE: | ||
289 | bfa_ioc_hw_sem_get_cancel(ioc); | ||
290 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); | ||
291 | break; | ||
292 | |||
293 | default: | ||
294 | bfa_sm_fault(ioc, event); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | |||
299 | static void | ||
300 | bfa_ioc_sm_hwinit_entry(struct bfa_ioc_s *ioc) | ||
301 | { | ||
302 | bfa_ioc_timer_start(ioc); | ||
303 | bfa_ioc_reset(ioc, BFA_FALSE); | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * Hardware is being initialized. Interrupts are enabled. | ||
308 | * Holding hardware semaphore lock. | ||
309 | */ | ||
310 | static void | ||
311 | bfa_ioc_sm_hwinit(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
312 | { | ||
313 | bfa_trc(ioc, event); | ||
314 | |||
315 | switch (event) { | ||
316 | case IOC_E_FWREADY: | ||
317 | bfa_ioc_timer_stop(ioc); | ||
318 | bfa_fsm_set_state(ioc, bfa_ioc_sm_enabling); | ||
319 | break; | ||
320 | |||
321 | case IOC_E_HWERROR: | ||
322 | bfa_ioc_timer_stop(ioc); | ||
323 | /* | ||
324 | * fall through | ||
325 | */ | ||
326 | |||
327 | case IOC_E_TIMEOUT: | ||
328 | ioc->retry_count++; | ||
329 | if (ioc->retry_count < BFA_IOC_HWINIT_MAX) { | ||
330 | bfa_ioc_timer_start(ioc); | ||
331 | bfa_ioc_reset(ioc, BFA_TRUE); | ||
332 | break; | ||
333 | } | ||
334 | |||
335 | bfa_ioc_hw_sem_release(ioc); | ||
336 | bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); | ||
337 | break; | ||
338 | |||
339 | case IOC_E_DISABLE: | ||
340 | bfa_ioc_hw_sem_release(ioc); | ||
341 | bfa_ioc_timer_stop(ioc); | ||
342 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); | ||
343 | break; | ||
344 | |||
345 | default: | ||
346 | bfa_sm_fault(ioc, event); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | |||
351 | static void | ||
352 | bfa_ioc_sm_enabling_entry(struct bfa_ioc_s *ioc) | ||
353 | { | ||
354 | bfa_ioc_timer_start(ioc); | ||
355 | bfa_ioc_send_enable(ioc); | ||
356 | } | ||
357 | |||
358 | /** | ||
359 | * Host IOC function is being enabled, awaiting response from firmware. | ||
360 | * Semaphore is acquired. | ||
361 | */ | ||
362 | static void | ||
363 | bfa_ioc_sm_enabling(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
364 | { | ||
365 | bfa_trc(ioc, event); | ||
366 | |||
367 | switch (event) { | ||
368 | case IOC_E_FWRSP_ENABLE: | ||
369 | bfa_ioc_timer_stop(ioc); | ||
370 | bfa_ioc_hw_sem_release(ioc); | ||
371 | bfa_fsm_set_state(ioc, bfa_ioc_sm_getattr); | ||
372 | break; | ||
373 | |||
374 | case IOC_E_HWERROR: | ||
375 | bfa_ioc_timer_stop(ioc); | ||
376 | /* | ||
377 | * fall through | ||
378 | */ | ||
379 | |||
380 | case IOC_E_TIMEOUT: | ||
381 | ioc->retry_count++; | ||
382 | if (ioc->retry_count < BFA_IOC_HWINIT_MAX) { | ||
383 | bfa_reg_write(ioc->ioc_regs.ioc_fwstate, | ||
384 | BFI_IOC_UNINIT); | ||
385 | bfa_fsm_set_state(ioc, bfa_ioc_sm_hwinit); | ||
386 | break; | ||
387 | } | ||
388 | |||
389 | bfa_ioc_hw_sem_release(ioc); | ||
390 | bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); | ||
391 | break; | ||
392 | |||
393 | case IOC_E_DISABLE: | ||
394 | bfa_ioc_timer_stop(ioc); | ||
395 | bfa_ioc_hw_sem_release(ioc); | ||
396 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); | ||
397 | break; | ||
398 | |||
399 | case IOC_E_FWREADY: | ||
400 | bfa_ioc_send_enable(ioc); | ||
401 | break; | ||
402 | |||
403 | default: | ||
404 | bfa_sm_fault(ioc, event); | ||
405 | } | ||
406 | } | ||
407 | |||
408 | |||
409 | static void | ||
410 | bfa_ioc_sm_getattr_entry(struct bfa_ioc_s *ioc) | ||
411 | { | ||
412 | bfa_ioc_timer_start(ioc); | ||
413 | bfa_ioc_send_getattr(ioc); | ||
414 | } | ||
415 | |||
416 | /** | ||
417 | * IOC configuration in progress. Timer is active. | ||
418 | */ | ||
419 | static void | ||
420 | bfa_ioc_sm_getattr(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
421 | { | ||
422 | bfa_trc(ioc, event); | ||
423 | |||
424 | switch (event) { | ||
425 | case IOC_E_FWRSP_GETATTR: | ||
426 | bfa_ioc_timer_stop(ioc); | ||
427 | bfa_fsm_set_state(ioc, bfa_ioc_sm_op); | ||
428 | break; | ||
429 | |||
430 | case IOC_E_HWERROR: | ||
431 | bfa_ioc_timer_stop(ioc); | ||
432 | /* | ||
433 | * fall through | ||
434 | */ | ||
435 | |||
436 | case IOC_E_TIMEOUT: | ||
437 | bfa_fsm_set_state(ioc, bfa_ioc_sm_initfail); | ||
438 | break; | ||
439 | |||
440 | case IOC_E_DISABLE: | ||
441 | bfa_ioc_timer_stop(ioc); | ||
442 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); | ||
443 | break; | ||
444 | |||
445 | default: | ||
446 | bfa_sm_fault(ioc, event); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | |||
451 | static void | ||
452 | bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc) | ||
453 | { | ||
454 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK); | ||
455 | bfa_ioc_hb_monitor(ioc); | ||
456 | bfa_ioc_aen_post(ioc, BFA_IOC_AEN_ENABLE); | ||
457 | } | ||
458 | |||
459 | static void | ||
460 | bfa_ioc_sm_op(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
461 | { | ||
462 | bfa_trc(ioc, event); | ||
463 | |||
464 | switch (event) { | ||
465 | case IOC_E_ENABLE: | ||
466 | break; | ||
467 | |||
468 | case IOC_E_DISABLE: | ||
469 | bfa_ioc_hb_stop(ioc); | ||
470 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); | ||
471 | break; | ||
472 | |||
473 | case IOC_E_HWERROR: | ||
474 | case IOC_E_FWREADY: | ||
475 | /** | ||
476 | * Hard error or IOC recovery by other function. | ||
477 | * Treat it same as heartbeat failure. | ||
478 | */ | ||
479 | bfa_ioc_hb_stop(ioc); | ||
480 | /* | ||
481 | * !!! fall through !!! | ||
482 | */ | ||
483 | |||
484 | case IOC_E_HBFAIL: | ||
485 | bfa_fsm_set_state(ioc, bfa_ioc_sm_hbfail); | ||
486 | break; | ||
487 | |||
488 | default: | ||
489 | bfa_sm_fault(ioc, event); | ||
490 | } | ||
491 | } | ||
492 | |||
493 | |||
494 | static void | ||
495 | bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc) | ||
496 | { | ||
497 | bfa_ioc_aen_post(ioc, BFA_IOC_AEN_DISABLE); | ||
498 | bfa_ioc_timer_start(ioc); | ||
499 | bfa_ioc_send_disable(ioc); | ||
500 | } | ||
501 | |||
502 | /** | ||
503 | * IOC is being disabled | ||
504 | */ | ||
505 | static void | ||
506 | bfa_ioc_sm_disabling(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
507 | { | ||
508 | bfa_trc(ioc, event); | ||
509 | |||
510 | switch (event) { | ||
511 | case IOC_E_HWERROR: | ||
512 | case IOC_E_FWRSP_DISABLE: | ||
513 | bfa_ioc_timer_stop(ioc); | ||
514 | /* | ||
515 | * !!! fall through !!! | ||
516 | */ | ||
517 | |||
518 | case IOC_E_TIMEOUT: | ||
519 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); | ||
520 | break; | ||
521 | |||
522 | default: | ||
523 | bfa_sm_fault(ioc, event); | ||
524 | } | ||
525 | } | ||
526 | |||
527 | /** | ||
528 | * IOC disable completion entry. | ||
529 | */ | ||
530 | static void | ||
531 | bfa_ioc_sm_disabled_entry(struct bfa_ioc_s *ioc) | ||
532 | { | ||
533 | bfa_ioc_disable_comp(ioc); | ||
534 | } | ||
535 | |||
536 | static void | ||
537 | bfa_ioc_sm_disabled(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
538 | { | ||
539 | bfa_trc(ioc, event); | ||
540 | |||
541 | switch (event) { | ||
542 | case IOC_E_ENABLE: | ||
543 | bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait); | ||
544 | break; | ||
545 | |||
546 | case IOC_E_DISABLE: | ||
547 | ioc->cbfn->disable_cbfn(ioc->bfa); | ||
548 | break; | ||
549 | |||
550 | case IOC_E_FWREADY: | ||
551 | break; | ||
552 | |||
553 | case IOC_E_DETACH: | ||
554 | bfa_ioc_firmware_unlock(ioc); | ||
555 | bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); | ||
556 | break; | ||
557 | |||
558 | default: | ||
559 | bfa_sm_fault(ioc, event); | ||
560 | } | ||
561 | } | ||
562 | |||
563 | |||
564 | static void | ||
565 | bfa_ioc_sm_initfail_entry(struct bfa_ioc_s *ioc) | ||
566 | { | ||
567 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); | ||
568 | bfa_ioc_timer_start(ioc); | ||
569 | } | ||
570 | |||
571 | /** | ||
572 | * Hardware initialization failed. | ||
573 | */ | ||
574 | static void | ||
575 | bfa_ioc_sm_initfail(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
576 | { | ||
577 | bfa_trc(ioc, event); | ||
578 | |||
579 | switch (event) { | ||
580 | case IOC_E_DISABLE: | ||
581 | bfa_ioc_timer_stop(ioc); | ||
582 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); | ||
583 | break; | ||
584 | |||
585 | case IOC_E_DETACH: | ||
586 | bfa_ioc_timer_stop(ioc); | ||
587 | bfa_ioc_firmware_unlock(ioc); | ||
588 | bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); | ||
589 | break; | ||
590 | |||
591 | case IOC_E_TIMEOUT: | ||
592 | bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait); | ||
593 | break; | ||
594 | |||
595 | default: | ||
596 | bfa_sm_fault(ioc, event); | ||
597 | } | ||
598 | } | ||
599 | |||
600 | |||
601 | static void | ||
602 | bfa_ioc_sm_hbfail_entry(struct bfa_ioc_s *ioc) | ||
603 | { | ||
604 | struct list_head *qe; | ||
605 | struct bfa_ioc_hbfail_notify_s *notify; | ||
606 | |||
607 | /** | ||
608 | * Mark IOC as failed in hardware and stop firmware. | ||
609 | */ | ||
610 | bfa_ioc_lpu_stop(ioc); | ||
611 | bfa_reg_write(ioc->ioc_regs.ioc_fwstate, BFI_IOC_HBFAIL); | ||
612 | |||
613 | if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) { | ||
614 | bfa_reg_write(ioc->ioc_regs.ll_halt, __FW_INIT_HALT_P); | ||
615 | /* | ||
616 | * Wait for halt to take effect | ||
617 | */ | ||
618 | bfa_reg_read(ioc->ioc_regs.ll_halt); | ||
619 | } | ||
620 | |||
621 | /** | ||
622 | * Notify driver and common modules registered for notification. | ||
623 | */ | ||
624 | ioc->cbfn->hbfail_cbfn(ioc->bfa); | ||
625 | list_for_each(qe, &ioc->hb_notify_q) { | ||
626 | notify = (struct bfa_ioc_hbfail_notify_s *)qe; | ||
627 | notify->cbfn(notify->cbarg); | ||
628 | } | ||
629 | |||
630 | /** | ||
631 | * Flush any queued up mailbox requests. | ||
632 | */ | ||
633 | bfa_ioc_mbox_hbfail(ioc); | ||
634 | bfa_ioc_aen_post(ioc, BFA_IOC_AEN_HBFAIL); | ||
635 | |||
636 | /** | ||
637 | * Trigger auto-recovery after a delay. | ||
638 | */ | ||
639 | if (ioc->auto_recover) { | ||
640 | bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, | ||
641 | bfa_ioc_timeout, ioc, BFA_IOC_TOV_RECOVER); | ||
642 | } | ||
643 | } | ||
644 | |||
645 | /** | ||
646 | * IOC heartbeat failure. | ||
647 | */ | ||
648 | static void | ||
649 | bfa_ioc_sm_hbfail(struct bfa_ioc_s *ioc, enum ioc_event event) | ||
650 | { | ||
651 | bfa_trc(ioc, event); | ||
652 | |||
653 | switch (event) { | ||
654 | |||
655 | case IOC_E_ENABLE: | ||
656 | ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); | ||
657 | break; | ||
658 | |||
659 | case IOC_E_DISABLE: | ||
660 | if (ioc->auto_recover) | ||
661 | bfa_ioc_timer_stop(ioc); | ||
662 | bfa_fsm_set_state(ioc, bfa_ioc_sm_disabled); | ||
663 | break; | ||
664 | |||
665 | case IOC_E_TIMEOUT: | ||
666 | bfa_fsm_set_state(ioc, bfa_ioc_sm_semwait); | ||
667 | break; | ||
668 | |||
669 | case IOC_E_FWREADY: | ||
670 | /** | ||
671 | * Recovery is already initiated by other function. | ||
672 | */ | ||
673 | break; | ||
674 | |||
675 | default: | ||
676 | bfa_sm_fault(ioc, event); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | |||
681 | |||
682 | /** | ||
683 | * bfa_ioc_pvt BFA IOC private functions | ||
684 | */ | ||
685 | |||
686 | static void | ||
687 | bfa_ioc_disable_comp(struct bfa_ioc_s *ioc) | ||
688 | { | ||
689 | struct list_head *qe; | ||
690 | struct bfa_ioc_hbfail_notify_s *notify; | ||
691 | |||
692 | ioc->cbfn->disable_cbfn(ioc->bfa); | ||
693 | |||
694 | /** | ||
695 | * Notify common modules registered for notification. | ||
696 | */ | ||
697 | list_for_each(qe, &ioc->hb_notify_q) { | ||
698 | notify = (struct bfa_ioc_hbfail_notify_s *)qe; | ||
699 | notify->cbfn(notify->cbarg); | ||
700 | } | ||
701 | } | ||
702 | |||
703 | static void | ||
704 | bfa_ioc_sem_timeout(void *ioc_arg) | ||
705 | { | ||
706 | struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg; | ||
707 | |||
708 | bfa_ioc_hw_sem_get(ioc); | ||
709 | } | ||
710 | |||
711 | static void | ||
712 | bfa_ioc_usage_sem_get(struct bfa_ioc_s *ioc) | ||
713 | { | ||
714 | u32 r32; | ||
715 | int cnt = 0; | ||
716 | #define BFA_SEM_SPINCNT 1000 | ||
717 | |||
718 | do { | ||
719 | r32 = bfa_reg_read(ioc->ioc_regs.ioc_usage_sem_reg); | ||
720 | cnt++; | ||
721 | if (cnt > BFA_SEM_SPINCNT) | ||
722 | break; | ||
723 | } while (r32 != 0); | ||
724 | bfa_assert(cnt < BFA_SEM_SPINCNT); | ||
725 | } | ||
726 | |||
727 | static void | ||
728 | bfa_ioc_usage_sem_release(struct bfa_ioc_s *ioc) | ||
729 | { | ||
730 | bfa_reg_write(ioc->ioc_regs.ioc_usage_sem_reg, 1); | ||
731 | } | ||
732 | |||
733 | static void | ||
734 | bfa_ioc_hw_sem_get(struct bfa_ioc_s *ioc) | ||
735 | { | ||
736 | u32 r32; | ||
737 | |||
738 | /** | ||
739 | * First read to the semaphore register will return 0, subsequent reads | ||
740 | * will return 1. Semaphore is released by writing 0 to the register | ||
741 | */ | ||
742 | r32 = bfa_reg_read(ioc->ioc_regs.ioc_sem_reg); | ||
743 | if (r32 == 0) { | ||
744 | bfa_fsm_send_event(ioc, IOC_E_SEMLOCKED); | ||
745 | return; | ||
746 | } | ||
747 | |||
748 | bfa_timer_begin(ioc->timer_mod, &ioc->sem_timer, bfa_ioc_sem_timeout, | ||
749 | ioc, BFA_IOC_TOV); | ||
750 | } | ||
751 | |||
752 | static void | ||
753 | bfa_ioc_hw_sem_release(struct bfa_ioc_s *ioc) | ||
754 | { | ||
755 | bfa_reg_write(ioc->ioc_regs.ioc_sem_reg, 1); | ||
756 | } | ||
757 | |||
758 | static void | ||
759 | bfa_ioc_hw_sem_get_cancel(struct bfa_ioc_s *ioc) | ||
760 | { | ||
761 | bfa_timer_stop(&ioc->sem_timer); | ||
762 | } | ||
763 | |||
764 | /** | ||
765 | * Initialize LPU local memory (aka secondary memory / SRAM) | ||
766 | */ | ||
767 | static void | ||
768 | bfa_ioc_lmem_init(struct bfa_ioc_s *ioc) | ||
769 | { | ||
770 | u32 pss_ctl; | ||
771 | int i; | ||
772 | #define PSS_LMEM_INIT_TIME 10000 | ||
773 | |||
774 | pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg); | ||
775 | pss_ctl &= ~__PSS_LMEM_RESET; | ||
776 | pss_ctl |= __PSS_LMEM_INIT_EN; | ||
777 | pss_ctl |= __PSS_I2C_CLK_DIV(3UL); /* i2c workaround 12.5khz clock */ | ||
778 | bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl); | ||
779 | |||
780 | /** | ||
781 | * wait for memory initialization to be complete | ||
782 | */ | ||
783 | i = 0; | ||
784 | do { | ||
785 | pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg); | ||
786 | i++; | ||
787 | } while (!(pss_ctl & __PSS_LMEM_INIT_DONE) && (i < PSS_LMEM_INIT_TIME)); | ||
788 | |||
789 | /** | ||
790 | * If memory initialization is not successful, IOC timeout will catch | ||
791 | * such failures. | ||
792 | */ | ||
793 | bfa_assert(pss_ctl & __PSS_LMEM_INIT_DONE); | ||
794 | bfa_trc(ioc, pss_ctl); | ||
795 | |||
796 | pss_ctl &= ~(__PSS_LMEM_INIT_DONE | __PSS_LMEM_INIT_EN); | ||
797 | bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl); | ||
798 | } | ||
799 | |||
800 | static void | ||
801 | bfa_ioc_lpu_start(struct bfa_ioc_s *ioc) | ||
802 | { | ||
803 | u32 pss_ctl; | ||
804 | |||
805 | /** | ||
806 | * Take processor out of reset. | ||
807 | */ | ||
808 | pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg); | ||
809 | pss_ctl &= ~__PSS_LPU0_RESET; | ||
810 | |||
811 | bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl); | ||
812 | } | ||
813 | |||
814 | static void | ||
815 | bfa_ioc_lpu_stop(struct bfa_ioc_s *ioc) | ||
816 | { | ||
817 | u32 pss_ctl; | ||
818 | |||
819 | /** | ||
820 | * Put processors in reset. | ||
821 | */ | ||
822 | pss_ctl = bfa_reg_read(ioc->ioc_regs.pss_ctl_reg); | ||
823 | pss_ctl |= (__PSS_LPU0_RESET | __PSS_LPU1_RESET); | ||
824 | |||
825 | bfa_reg_write(ioc->ioc_regs.pss_ctl_reg, pss_ctl); | ||
826 | } | ||
827 | |||
828 | /** | ||
829 | * Get driver and firmware versions. | ||
830 | */ | ||
831 | static void | ||
832 | bfa_ioc_fwver_get(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) | ||
833 | { | ||
834 | u32 pgnum, pgoff; | ||
835 | u32 loff = 0; | ||
836 | int i; | ||
837 | u32 *fwsig = (u32 *) fwhdr; | ||
838 | |||
839 | pgnum = bfa_ioc_smem_pgnum(ioc, loff); | ||
840 | pgoff = bfa_ioc_smem_pgoff(ioc, loff); | ||
841 | bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum); | ||
842 | |||
843 | for (i = 0; i < (sizeof(struct bfi_ioc_image_hdr_s) / sizeof(u32)); | ||
844 | i++) { | ||
845 | fwsig[i] = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff); | ||
846 | loff += sizeof(u32); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | static u32 * | ||
851 | bfa_ioc_fwimg_get_chunk(struct bfa_ioc_s *ioc, u32 off) | ||
852 | { | ||
853 | if (ioc->ctdev) | ||
854 | return bfi_image_ct_get_chunk(off); | ||
855 | return bfi_image_cb_get_chunk(off); | ||
856 | } | ||
857 | |||
858 | static u32 | ||
859 | bfa_ioc_fwimg_get_size(struct bfa_ioc_s *ioc) | ||
860 | { | ||
861 | return (ioc->ctdev) ? bfi_image_ct_size : bfi_image_cb_size; | ||
862 | } | ||
863 | |||
864 | /** | ||
865 | * Returns TRUE if same. | ||
866 | */ | ||
867 | static bfa_boolean_t | ||
868 | bfa_ioc_fwver_cmp(struct bfa_ioc_s *ioc, struct bfi_ioc_image_hdr_s *fwhdr) | ||
869 | { | ||
870 | struct bfi_ioc_image_hdr_s *drv_fwhdr; | ||
871 | int i; | ||
872 | |||
873 | drv_fwhdr = | ||
874 | (struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0); | ||
875 | |||
876 | for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { | ||
877 | if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) { | ||
878 | bfa_trc(ioc, i); | ||
879 | bfa_trc(ioc, fwhdr->md5sum[i]); | ||
880 | bfa_trc(ioc, drv_fwhdr->md5sum[i]); | ||
881 | return BFA_FALSE; | ||
882 | } | ||
883 | } | ||
884 | |||
885 | bfa_trc(ioc, fwhdr->md5sum[0]); | ||
886 | return BFA_TRUE; | ||
887 | } | ||
888 | |||
889 | /** | ||
890 | * Return true if current running version is valid. Firmware signature and | ||
891 | * execution context (driver/bios) must match. | ||
892 | */ | ||
893 | static bfa_boolean_t | ||
894 | bfa_ioc_fwver_valid(struct bfa_ioc_s *ioc) | ||
895 | { | ||
896 | struct bfi_ioc_image_hdr_s fwhdr, *drv_fwhdr; | ||
897 | |||
898 | /** | ||
899 | * If bios/efi boot (flash based) -- return true | ||
900 | */ | ||
901 | if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) | ||
902 | return BFA_TRUE; | ||
903 | |||
904 | bfa_ioc_fwver_get(ioc, &fwhdr); | ||
905 | drv_fwhdr = | ||
906 | (struct bfi_ioc_image_hdr_s *)bfa_ioc_fwimg_get_chunk(ioc, 0); | ||
907 | |||
908 | if (fwhdr.signature != drv_fwhdr->signature) { | ||
909 | bfa_trc(ioc, fwhdr.signature); | ||
910 | bfa_trc(ioc, drv_fwhdr->signature); | ||
911 | return BFA_FALSE; | ||
912 | } | ||
913 | |||
914 | if (fwhdr.exec != drv_fwhdr->exec) { | ||
915 | bfa_trc(ioc, fwhdr.exec); | ||
916 | bfa_trc(ioc, drv_fwhdr->exec); | ||
917 | return BFA_FALSE; | ||
918 | } | ||
919 | |||
920 | return bfa_ioc_fwver_cmp(ioc, &fwhdr); | ||
921 | } | ||
922 | |||
923 | /** | ||
924 | * Return true if firmware of current driver matches the running firmware. | ||
925 | */ | ||
926 | static bfa_boolean_t | ||
927 | bfa_ioc_firmware_lock(struct bfa_ioc_s *ioc) | ||
928 | { | ||
929 | enum bfi_ioc_state ioc_fwstate; | ||
930 | u32 usecnt; | ||
931 | struct bfi_ioc_image_hdr_s fwhdr; | ||
932 | |||
933 | /** | ||
934 | * Firmware match check is relevant only for CNA. | ||
935 | */ | ||
936 | if (!ioc->cna) | ||
937 | return BFA_TRUE; | ||
938 | |||
939 | /** | ||
940 | * If bios boot (flash based) -- do not increment usage count | ||
941 | */ | ||
942 | if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) | ||
943 | return BFA_TRUE; | ||
944 | |||
945 | bfa_ioc_usage_sem_get(ioc); | ||
946 | usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg); | ||
947 | |||
948 | /** | ||
949 | * If usage count is 0, always return TRUE. | ||
950 | */ | ||
951 | if (usecnt == 0) { | ||
952 | bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, 1); | ||
953 | bfa_ioc_usage_sem_release(ioc); | ||
954 | bfa_trc(ioc, usecnt); | ||
955 | return BFA_TRUE; | ||
956 | } | ||
957 | |||
958 | ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate); | ||
959 | bfa_trc(ioc, ioc_fwstate); | ||
960 | |||
961 | /** | ||
962 | * Use count cannot be non-zero and chip in uninitialized state. | ||
963 | */ | ||
964 | bfa_assert(ioc_fwstate != BFI_IOC_UNINIT); | ||
965 | |||
966 | /** | ||
967 | * Check if another driver with a different firmware is active | ||
968 | */ | ||
969 | bfa_ioc_fwver_get(ioc, &fwhdr); | ||
970 | if (!bfa_ioc_fwver_cmp(ioc, &fwhdr)) { | ||
971 | bfa_ioc_usage_sem_release(ioc); | ||
972 | bfa_trc(ioc, usecnt); | ||
973 | return BFA_FALSE; | ||
974 | } | ||
975 | |||
976 | /** | ||
977 | * Same firmware version. Increment the reference count. | ||
978 | */ | ||
979 | usecnt++; | ||
980 | bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt); | ||
981 | bfa_ioc_usage_sem_release(ioc); | ||
982 | bfa_trc(ioc, usecnt); | ||
983 | return BFA_TRUE; | ||
984 | } | ||
985 | |||
986 | static void | ||
987 | bfa_ioc_firmware_unlock(struct bfa_ioc_s *ioc) | ||
988 | { | ||
989 | u32 usecnt; | ||
990 | |||
991 | /** | ||
992 | * Firmware lock is relevant only for CNA. | ||
993 | * If bios boot (flash based) -- do not decrement usage count | ||
994 | */ | ||
995 | if (!ioc->cna || (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ)) | ||
996 | return; | ||
997 | |||
998 | /** | ||
999 | * decrement usage count | ||
1000 | */ | ||
1001 | bfa_ioc_usage_sem_get(ioc); | ||
1002 | usecnt = bfa_reg_read(ioc->ioc_regs.ioc_usage_reg); | ||
1003 | bfa_assert(usecnt > 0); | ||
1004 | |||
1005 | usecnt--; | ||
1006 | bfa_reg_write(ioc->ioc_regs.ioc_usage_reg, usecnt); | ||
1007 | bfa_trc(ioc, usecnt); | ||
1008 | |||
1009 | bfa_ioc_usage_sem_release(ioc); | ||
1010 | } | ||
1011 | |||
1012 | /** | ||
1013 | * Conditionally flush any pending message from firmware at start. | ||
1014 | */ | ||
1015 | static void | ||
1016 | bfa_ioc_msgflush(struct bfa_ioc_s *ioc) | ||
1017 | { | ||
1018 | u32 r32; | ||
1019 | |||
1020 | r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd); | ||
1021 | if (r32) | ||
1022 | bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1); | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | static void | ||
1027 | bfa_ioc_hwinit(struct bfa_ioc_s *ioc, bfa_boolean_t force) | ||
1028 | { | ||
1029 | enum bfi_ioc_state ioc_fwstate; | ||
1030 | bfa_boolean_t fwvalid; | ||
1031 | |||
1032 | ioc_fwstate = bfa_reg_read(ioc->ioc_regs.ioc_fwstate); | ||
1033 | |||
1034 | if (force) | ||
1035 | ioc_fwstate = BFI_IOC_UNINIT; | ||
1036 | |||
1037 | bfa_trc(ioc, ioc_fwstate); | ||
1038 | |||
1039 | /** | ||
1040 | * check if firmware is valid | ||
1041 | */ | ||
1042 | fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ? | ||
1043 | BFA_FALSE : bfa_ioc_fwver_valid(ioc); | ||
1044 | |||
1045 | if (!fwvalid) { | ||
1046 | bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id); | ||
1047 | return; | ||
1048 | } | ||
1049 | |||
1050 | /** | ||
1051 | * If hardware initialization is in progress (initialized by other IOC), | ||
1052 | * just wait for an initialization completion interrupt. | ||
1053 | */ | ||
1054 | if (ioc_fwstate == BFI_IOC_INITING) { | ||
1055 | bfa_trc(ioc, ioc_fwstate); | ||
1056 | ioc->cbfn->reset_cbfn(ioc->bfa); | ||
1057 | return; | ||
1058 | } | ||
1059 | |||
1060 | /** | ||
1061 | * If IOC function is disabled and firmware version is same, | ||
1062 | * just re-enable IOC. | ||
1063 | */ | ||
1064 | if (ioc_fwstate == BFI_IOC_DISABLED || ioc_fwstate == BFI_IOC_OP) { | ||
1065 | bfa_trc(ioc, ioc_fwstate); | ||
1066 | |||
1067 | /** | ||
1068 | * When using MSI-X any pending firmware ready event should | ||
1069 | * be flushed. Otherwise MSI-X interrupts are not delivered. | ||
1070 | */ | ||
1071 | bfa_ioc_msgflush(ioc); | ||
1072 | ioc->cbfn->reset_cbfn(ioc->bfa); | ||
1073 | bfa_fsm_send_event(ioc, IOC_E_FWREADY); | ||
1074 | return; | ||
1075 | } | ||
1076 | |||
1077 | /** | ||
1078 | * Initialize the h/w for any other states. | ||
1079 | */ | ||
1080 | bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id); | ||
1081 | } | ||
1082 | |||
1083 | static void | ||
1084 | bfa_ioc_timeout(void *ioc_arg) | ||
1085 | { | ||
1086 | struct bfa_ioc_s *ioc = (struct bfa_ioc_s *)ioc_arg; | ||
1087 | |||
1088 | bfa_trc(ioc, 0); | ||
1089 | bfa_fsm_send_event(ioc, IOC_E_TIMEOUT); | ||
1090 | } | ||
1091 | |||
1092 | void | ||
1093 | bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len) | ||
1094 | { | ||
1095 | u32 *msgp = (u32 *) ioc_msg; | ||
1096 | u32 i; | ||
1097 | |||
1098 | bfa_trc(ioc, msgp[0]); | ||
1099 | bfa_trc(ioc, len); | ||
1100 | |||
1101 | bfa_assert(len <= BFI_IOC_MSGLEN_MAX); | ||
1102 | |||
1103 | /* | ||
1104 | * first write msg to mailbox registers | ||
1105 | */ | ||
1106 | for (i = 0; i < len / sizeof(u32); i++) | ||
1107 | bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32), | ||
1108 | bfa_os_wtole(msgp[i])); | ||
1109 | |||
1110 | for (; i < BFI_IOC_MSGLEN_MAX / sizeof(u32); i++) | ||
1111 | bfa_reg_write(ioc->ioc_regs.hfn_mbox + i * sizeof(u32), 0); | ||
1112 | |||
1113 | /* | ||
1114 | * write 1 to mailbox CMD to trigger LPU event | ||
1115 | */ | ||
1116 | bfa_reg_write(ioc->ioc_regs.hfn_mbox_cmd, 1); | ||
1117 | (void)bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd); | ||
1118 | } | ||
1119 | |||
1120 | static void | ||
1121 | bfa_ioc_send_enable(struct bfa_ioc_s *ioc) | ||
1122 | { | ||
1123 | struct bfi_ioc_ctrl_req_s enable_req; | ||
1124 | |||
1125 | bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ, | ||
1126 | bfa_ioc_portid(ioc)); | ||
1127 | enable_req.ioc_class = ioc->ioc_mc; | ||
1128 | bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req_s)); | ||
1129 | } | ||
1130 | |||
1131 | static void | ||
1132 | bfa_ioc_send_disable(struct bfa_ioc_s *ioc) | ||
1133 | { | ||
1134 | struct bfi_ioc_ctrl_req_s disable_req; | ||
1135 | |||
1136 | bfi_h2i_set(disable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_DISABLE_REQ, | ||
1137 | bfa_ioc_portid(ioc)); | ||
1138 | bfa_ioc_mbox_send(ioc, &disable_req, sizeof(struct bfi_ioc_ctrl_req_s)); | ||
1139 | } | ||
1140 | |||
1141 | static void | ||
1142 | bfa_ioc_send_getattr(struct bfa_ioc_s *ioc) | ||
1143 | { | ||
1144 | struct bfi_ioc_getattr_req_s attr_req; | ||
1145 | |||
1146 | bfi_h2i_set(attr_req.mh, BFI_MC_IOC, BFI_IOC_H2I_GETATTR_REQ, | ||
1147 | bfa_ioc_portid(ioc)); | ||
1148 | bfa_dma_be_addr_set(attr_req.attr_addr, ioc->attr_dma.pa); | ||
1149 | bfa_ioc_mbox_send(ioc, &attr_req, sizeof(attr_req)); | ||
1150 | } | ||
1151 | |||
1152 | static void | ||
1153 | bfa_ioc_hb_check(void *cbarg) | ||
1154 | { | ||
1155 | struct bfa_ioc_s *ioc = cbarg; | ||
1156 | u32 hb_count; | ||
1157 | |||
1158 | hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat); | ||
1159 | if (ioc->hb_count == hb_count) { | ||
1160 | ioc->hb_fail++; | ||
1161 | } else { | ||
1162 | ioc->hb_count = hb_count; | ||
1163 | ioc->hb_fail = 0; | ||
1164 | } | ||
1165 | |||
1166 | if (ioc->hb_fail >= BFA_IOC_HB_FAIL_MAX) { | ||
1167 | bfa_log(ioc->logm, BFA_LOG_HAL_HEARTBEAT_FAILURE, hb_count); | ||
1168 | ioc->hb_fail = 0; | ||
1169 | bfa_ioc_recover(ioc); | ||
1170 | return; | ||
1171 | } | ||
1172 | |||
1173 | bfa_ioc_mbox_poll(ioc); | ||
1174 | bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc, | ||
1175 | BFA_IOC_HB_TOV); | ||
1176 | } | ||
1177 | |||
1178 | static void | ||
1179 | bfa_ioc_hb_monitor(struct bfa_ioc_s *ioc) | ||
1180 | { | ||
1181 | ioc->hb_fail = 0; | ||
1182 | ioc->hb_count = bfa_reg_read(ioc->ioc_regs.heartbeat); | ||
1183 | bfa_timer_begin(ioc->timer_mod, &ioc->ioc_timer, bfa_ioc_hb_check, ioc, | ||
1184 | BFA_IOC_HB_TOV); | ||
1185 | } | ||
1186 | |||
1187 | static void | ||
1188 | bfa_ioc_hb_stop(struct bfa_ioc_s *ioc) | ||
1189 | { | ||
1190 | bfa_timer_stop(&ioc->ioc_timer); | ||
1191 | } | ||
1192 | |||
1193 | /** | ||
1194 | * Host to LPU mailbox message addresses | ||
1195 | */ | ||
1196 | static struct { | ||
1197 | u32 hfn_mbox, lpu_mbox, hfn_pgn; | ||
1198 | } iocreg_fnreg[] = { | ||
1199 | { | ||
1200 | HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0}, { | ||
1201 | HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1}, { | ||
1202 | HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2}, { | ||
1203 | HOSTFN3_LPU_MBOX0_8, LPU_HOSTFN3_MBOX0_8, HOST_PAGE_NUM_FN3} | ||
1204 | }; | ||
1205 | |||
1206 | /** | ||
1207 | * Host <-> LPU mailbox command/status registers - port 0 | ||
1208 | */ | ||
1209 | static struct { | ||
1210 | u32 hfn, lpu; | ||
1211 | } iocreg_mbcmd_p0[] = { | ||
1212 | { | ||
1213 | HOSTFN0_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN0_MBOX0_CMD_STAT}, { | ||
1214 | HOSTFN1_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN1_MBOX0_CMD_STAT}, { | ||
1215 | HOSTFN2_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN2_MBOX0_CMD_STAT}, { | ||
1216 | HOSTFN3_LPU0_MBOX0_CMD_STAT, LPU0_HOSTFN3_MBOX0_CMD_STAT} | ||
1217 | }; | ||
1218 | |||
1219 | /** | ||
1220 | * Host <-> LPU mailbox command/status registers - port 1 | ||
1221 | */ | ||
1222 | static struct { | ||
1223 | u32 hfn, lpu; | ||
1224 | } iocreg_mbcmd_p1[] = { | ||
1225 | { | ||
1226 | HOSTFN0_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN0_MBOX0_CMD_STAT}, { | ||
1227 | HOSTFN1_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN1_MBOX0_CMD_STAT}, { | ||
1228 | HOSTFN2_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN2_MBOX0_CMD_STAT}, { | ||
1229 | HOSTFN3_LPU1_MBOX0_CMD_STAT, LPU1_HOSTFN3_MBOX0_CMD_STAT} | ||
1230 | }; | ||
1231 | |||
1232 | /** | ||
1233 | * Shared IRQ handling in INTX mode | ||
1234 | */ | ||
1235 | static struct { | ||
1236 | u32 isr, msk; | ||
1237 | } iocreg_shirq_next[] = { | ||
1238 | { | ||
1239 | HOSTFN1_INT_STATUS, HOSTFN1_INT_MSK}, { | ||
1240 | HOSTFN2_INT_STATUS, HOSTFN2_INT_MSK}, { | ||
1241 | HOSTFN3_INT_STATUS, HOSTFN3_INT_MSK}, { | ||
1242 | HOSTFN0_INT_STATUS, HOSTFN0_INT_MSK},}; | ||
1243 | |||
1244 | static void | ||
1245 | bfa_ioc_reg_init(struct bfa_ioc_s *ioc) | ||
1246 | { | ||
1247 | bfa_os_addr_t rb; | ||
1248 | int pcifn = bfa_ioc_pcifn(ioc); | ||
1249 | |||
1250 | rb = bfa_ioc_bar0(ioc); | ||
1251 | |||
1252 | ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; | ||
1253 | ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; | ||
1254 | ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; | ||
1255 | |||
1256 | if (ioc->port_id == 0) { | ||
1257 | ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; | ||
1258 | ioc->ioc_regs.ioc_fwstate = rb + BFA_IOC0_STATE_REG; | ||
1259 | ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].hfn; | ||
1260 | ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p0[pcifn].lpu; | ||
1261 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P0; | ||
1262 | } else { | ||
1263 | ioc->ioc_regs.heartbeat = (rb + BFA_IOC1_HBEAT_REG); | ||
1264 | ioc->ioc_regs.ioc_fwstate = (rb + BFA_IOC1_STATE_REG); | ||
1265 | ioc->ioc_regs.hfn_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].hfn; | ||
1266 | ioc->ioc_regs.lpu_mbox_cmd = rb + iocreg_mbcmd_p1[pcifn].lpu; | ||
1267 | ioc->ioc_regs.ll_halt = rb + FW_INIT_HALT_P1; | ||
1268 | } | ||
1269 | |||
1270 | /** | ||
1271 | * Shared IRQ handling in INTX mode | ||
1272 | */ | ||
1273 | ioc->ioc_regs.shirq_isr_next = rb + iocreg_shirq_next[pcifn].isr; | ||
1274 | ioc->ioc_regs.shirq_msk_next = rb + iocreg_shirq_next[pcifn].msk; | ||
1275 | |||
1276 | /* | ||
1277 | * PSS control registers | ||
1278 | */ | ||
1279 | ioc->ioc_regs.pss_ctl_reg = (rb + PSS_CTL_REG); | ||
1280 | ioc->ioc_regs.app_pll_fast_ctl_reg = (rb + APP_PLL_425_CTL_REG); | ||
1281 | ioc->ioc_regs.app_pll_slow_ctl_reg = (rb + APP_PLL_312_CTL_REG); | ||
1282 | |||
1283 | /* | ||
1284 | * IOC semaphore registers and serialization | ||
1285 | */ | ||
1286 | ioc->ioc_regs.ioc_sem_reg = (rb + HOST_SEM0_REG); | ||
1287 | ioc->ioc_regs.ioc_usage_sem_reg = (rb + HOST_SEM1_REG); | ||
1288 | ioc->ioc_regs.ioc_usage_reg = (rb + BFA_FW_USE_COUNT); | ||
1289 | |||
1290 | /** | ||
1291 | * sram memory access | ||
1292 | */ | ||
1293 | ioc->ioc_regs.smem_page_start = (rb + PSS_SMEM_PAGE_START); | ||
1294 | ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CB; | ||
1295 | if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) | ||
1296 | ioc->ioc_regs.smem_pg0 = BFI_IOC_SMEM_PG0_CT; | ||
1297 | } | ||
1298 | |||
1299 | /** | ||
1300 | * Initiate a full firmware download. | ||
1301 | */ | ||
1302 | static void | ||
1303 | bfa_ioc_download_fw(struct bfa_ioc_s *ioc, u32 boot_type, | ||
1304 | u32 boot_param) | ||
1305 | { | ||
1306 | u32 *fwimg; | ||
1307 | u32 pgnum, pgoff; | ||
1308 | u32 loff = 0; | ||
1309 | u32 chunkno = 0; | ||
1310 | u32 i; | ||
1311 | |||
1312 | /** | ||
1313 | * Initialize LMEM first before code download | ||
1314 | */ | ||
1315 | bfa_ioc_lmem_init(ioc); | ||
1316 | |||
1317 | /** | ||
1318 | * Flash based firmware boot | ||
1319 | */ | ||
1320 | bfa_trc(ioc, bfa_ioc_fwimg_get_size(ioc)); | ||
1321 | if (bfa_ioc_fwimg_get_size(ioc) < BFA_IOC_FWIMG_MINSZ) | ||
1322 | boot_type = BFI_BOOT_TYPE_FLASH; | ||
1323 | fwimg = bfa_ioc_fwimg_get_chunk(ioc, chunkno); | ||
1324 | fwimg[BFI_BOOT_TYPE_OFF / sizeof(u32)] = bfa_os_swap32(boot_type); | ||
1325 | fwimg[BFI_BOOT_PARAM_OFF / sizeof(u32)] = | ||
1326 | bfa_os_swap32(boot_param); | ||
1327 | |||
1328 | pgnum = bfa_ioc_smem_pgnum(ioc, loff); | ||
1329 | pgoff = bfa_ioc_smem_pgoff(ioc, loff); | ||
1330 | |||
1331 | bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum); | ||
1332 | |||
1333 | for (i = 0; i < bfa_ioc_fwimg_get_size(ioc); i++) { | ||
1334 | |||
1335 | if (BFA_FLASH_CHUNK_NO(i) != chunkno) { | ||
1336 | chunkno = BFA_FLASH_CHUNK_NO(i); | ||
1337 | fwimg = bfa_ioc_fwimg_get_chunk(ioc, | ||
1338 | BFA_FLASH_CHUNK_ADDR(chunkno)); | ||
1339 | } | ||
1340 | |||
1341 | /** | ||
1342 | * write smem | ||
1343 | */ | ||
1344 | bfa_mem_write(ioc->ioc_regs.smem_page_start, loff, | ||
1345 | fwimg[BFA_FLASH_OFFSET_IN_CHUNK(i)]); | ||
1346 | |||
1347 | loff += sizeof(u32); | ||
1348 | |||
1349 | /** | ||
1350 | * handle page offset wrap around | ||
1351 | */ | ||
1352 | loff = PSS_SMEM_PGOFF(loff); | ||
1353 | if (loff == 0) { | ||
1354 | pgnum++; | ||
1355 | bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum); | ||
1356 | } | ||
1357 | } | ||
1358 | |||
1359 | bfa_reg_write(ioc->ioc_regs.host_page_num_fn, | ||
1360 | bfa_ioc_smem_pgnum(ioc, 0)); | ||
1361 | } | ||
1362 | |||
1363 | static void | ||
1364 | bfa_ioc_reset(struct bfa_ioc_s *ioc, bfa_boolean_t force) | ||
1365 | { | ||
1366 | bfa_ioc_hwinit(ioc, force); | ||
1367 | } | ||
1368 | |||
1369 | /** | ||
1370 | * Update BFA configuration from firmware configuration. | ||
1371 | */ | ||
1372 | static void | ||
1373 | bfa_ioc_getattr_reply(struct bfa_ioc_s *ioc) | ||
1374 | { | ||
1375 | struct bfi_ioc_attr_s *attr = ioc->attr; | ||
1376 | |||
1377 | attr->adapter_prop = bfa_os_ntohl(attr->adapter_prop); | ||
1378 | attr->maxfrsize = bfa_os_ntohs(attr->maxfrsize); | ||
1379 | |||
1380 | bfa_fsm_send_event(ioc, IOC_E_FWRSP_GETATTR); | ||
1381 | } | ||
1382 | |||
1383 | /** | ||
1384 | * Attach time initialization of mbox logic. | ||
1385 | */ | ||
1386 | static void | ||
1387 | bfa_ioc_mbox_attach(struct bfa_ioc_s *ioc) | ||
1388 | { | ||
1389 | struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod; | ||
1390 | int mc; | ||
1391 | |||
1392 | INIT_LIST_HEAD(&mod->cmd_q); | ||
1393 | for (mc = 0; mc < BFI_MC_MAX; mc++) { | ||
1394 | mod->mbhdlr[mc].cbfn = NULL; | ||
1395 | mod->mbhdlr[mc].cbarg = ioc->bfa; | ||
1396 | } | ||
1397 | } | ||
1398 | |||
1399 | /** | ||
1400 | * Mbox poll timer -- restarts any pending mailbox requests. | ||
1401 | */ | ||
1402 | static void | ||
1403 | bfa_ioc_mbox_poll(struct bfa_ioc_s *ioc) | ||
1404 | { | ||
1405 | struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod; | ||
1406 | struct bfa_mbox_cmd_s *cmd; | ||
1407 | u32 stat; | ||
1408 | |||
1409 | /** | ||
1410 | * If no command pending, do nothing | ||
1411 | */ | ||
1412 | if (list_empty(&mod->cmd_q)) | ||
1413 | return; | ||
1414 | |||
1415 | /** | ||
1416 | * If previous command is not yet fetched by firmware, do nothing | ||
1417 | */ | ||
1418 | stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd); | ||
1419 | if (stat) | ||
1420 | return; | ||
1421 | |||
1422 | /** | ||
1423 | * Enqueue command to firmware. | ||
1424 | */ | ||
1425 | bfa_q_deq(&mod->cmd_q, &cmd); | ||
1426 | bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg)); | ||
1427 | } | ||
1428 | |||
1429 | /** | ||
1430 | * Cleanup any pending requests. | ||
1431 | */ | ||
1432 | static void | ||
1433 | bfa_ioc_mbox_hbfail(struct bfa_ioc_s *ioc) | ||
1434 | { | ||
1435 | struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod; | ||
1436 | struct bfa_mbox_cmd_s *cmd; | ||
1437 | |||
1438 | while (!list_empty(&mod->cmd_q)) | ||
1439 | bfa_q_deq(&mod->cmd_q, &cmd); | ||
1440 | } | ||
1441 | |||
1442 | /** | ||
1443 | * Initialize IOC to port mapping. | ||
1444 | */ | ||
1445 | |||
1446 | #define FNC_PERS_FN_SHIFT(__fn) ((__fn) * 8) | ||
1447 | static void | ||
1448 | bfa_ioc_map_port(struct bfa_ioc_s *ioc) | ||
1449 | { | ||
1450 | bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; | ||
1451 | u32 r32; | ||
1452 | |||
1453 | /** | ||
1454 | * For crossbow, port id is same as pci function. | ||
1455 | */ | ||
1456 | if (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT) { | ||
1457 | ioc->port_id = bfa_ioc_pcifn(ioc); | ||
1458 | return; | ||
1459 | } | ||
1460 | |||
1461 | /** | ||
1462 | * For catapult, base port id on personality register and IOC type | ||
1463 | */ | ||
1464 | r32 = bfa_reg_read(rb + FNC_PERS_REG); | ||
1465 | r32 >>= FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc)); | ||
1466 | ioc->port_id = (r32 & __F0_PORT_MAP_MK) >> __F0_PORT_MAP_SH; | ||
1467 | |||
1468 | bfa_trc(ioc, bfa_ioc_pcifn(ioc)); | ||
1469 | bfa_trc(ioc, ioc->port_id); | ||
1470 | } | ||
1471 | |||
1472 | |||
1473 | |||
1474 | /** | ||
1475 | * bfa_ioc_public | ||
1476 | */ | ||
1477 | |||
1478 | /** | ||
1479 | * Set interrupt mode for a function: INTX or MSIX | ||
1480 | */ | ||
1481 | void | ||
1482 | bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t msix) | ||
1483 | { | ||
1484 | bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; | ||
1485 | u32 r32, mode; | ||
1486 | |||
1487 | r32 = bfa_reg_read(rb + FNC_PERS_REG); | ||
1488 | bfa_trc(ioc, r32); | ||
1489 | |||
1490 | mode = (r32 >> FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))) & | ||
1491 | __F0_INTX_STATUS; | ||
1492 | |||
1493 | /** | ||
1494 | * If already in desired mode, do not change anything | ||
1495 | */ | ||
1496 | if (!msix && mode) | ||
1497 | return; | ||
1498 | |||
1499 | if (msix) | ||
1500 | mode = __F0_INTX_STATUS_MSIX; | ||
1501 | else | ||
1502 | mode = __F0_INTX_STATUS_INTA; | ||
1503 | |||
1504 | r32 &= ~(__F0_INTX_STATUS << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); | ||
1505 | r32 |= (mode << FNC_PERS_FN_SHIFT(bfa_ioc_pcifn(ioc))); | ||
1506 | bfa_trc(ioc, r32); | ||
1507 | |||
1508 | bfa_reg_write(rb + FNC_PERS_REG, r32); | ||
1509 | } | ||
1510 | |||
1511 | bfa_status_t | ||
1512 | bfa_ioc_pll_init(struct bfa_ioc_s *ioc) | ||
1513 | { | ||
1514 | bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; | ||
1515 | u32 pll_sclk, pll_fclk, r32; | ||
1516 | |||
1517 | if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) { | ||
1518 | pll_sclk = | ||
1519 | __APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN | | ||
1520 | __APP_PLL_312_RSEL200500 | __APP_PLL_312_P0_1(0U) | | ||
1521 | __APP_PLL_312_JITLMT0_1(3U) | | ||
1522 | __APP_PLL_312_CNTLMT0_1(1U); | ||
1523 | pll_fclk = | ||
1524 | __APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN | | ||
1525 | __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(0U) | | ||
1526 | __APP_PLL_425_JITLMT0_1(3U) | | ||
1527 | __APP_PLL_425_CNTLMT0_1(1U); | ||
1528 | |||
1529 | /** | ||
1530 | * For catapult, choose operational mode FC/FCoE | ||
1531 | */ | ||
1532 | if (ioc->fcmode) { | ||
1533 | bfa_reg_write((rb + OP_MODE), 0); | ||
1534 | bfa_reg_write((rb + ETH_MAC_SER_REG), | ||
1535 | __APP_EMS_CMLCKSEL | __APP_EMS_REFCKBUFEN2 | ||
1536 | | __APP_EMS_CHANNEL_SEL); | ||
1537 | } else { | ||
1538 | ioc->pllinit = BFA_TRUE; | ||
1539 | bfa_reg_write((rb + OP_MODE), __GLOBAL_FCOE_MODE); | ||
1540 | bfa_reg_write((rb + ETH_MAC_SER_REG), | ||
1541 | __APP_EMS_REFCKBUFEN1); | ||
1542 | } | ||
1543 | } else { | ||
1544 | pll_sclk = | ||
1545 | __APP_PLL_312_ENABLE | __APP_PLL_312_LRESETN | | ||
1546 | __APP_PLL_312_P0_1(3U) | __APP_PLL_312_JITLMT0_1(3U) | | ||
1547 | __APP_PLL_312_CNTLMT0_1(3U); | ||
1548 | pll_fclk = | ||
1549 | __APP_PLL_425_ENABLE | __APP_PLL_425_LRESETN | | ||
1550 | __APP_PLL_425_RSEL200500 | __APP_PLL_425_P0_1(3U) | | ||
1551 | __APP_PLL_425_JITLMT0_1(3U) | | ||
1552 | __APP_PLL_425_CNTLMT0_1(3U); | ||
1553 | } | ||
1554 | |||
1555 | bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_UNINIT); | ||
1556 | bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_UNINIT); | ||
1557 | |||
1558 | bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); | ||
1559 | bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); | ||
1560 | bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); | ||
1561 | bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); | ||
1562 | bfa_reg_write((rb + HOSTFN0_INT_MSK), 0xffffffffU); | ||
1563 | bfa_reg_write((rb + HOSTFN1_INT_MSK), 0xffffffffU); | ||
1564 | |||
1565 | bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, | ||
1566 | __APP_PLL_312_LOGIC_SOFT_RESET); | ||
1567 | bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, | ||
1568 | __APP_PLL_312_BYPASS | __APP_PLL_312_LOGIC_SOFT_RESET); | ||
1569 | bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, | ||
1570 | __APP_PLL_425_LOGIC_SOFT_RESET); | ||
1571 | bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, | ||
1572 | __APP_PLL_425_BYPASS | __APP_PLL_425_LOGIC_SOFT_RESET); | ||
1573 | bfa_os_udelay(2); | ||
1574 | bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, | ||
1575 | __APP_PLL_312_LOGIC_SOFT_RESET); | ||
1576 | bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, | ||
1577 | __APP_PLL_425_LOGIC_SOFT_RESET); | ||
1578 | |||
1579 | bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, | ||
1580 | pll_sclk | __APP_PLL_312_LOGIC_SOFT_RESET); | ||
1581 | bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, | ||
1582 | pll_fclk | __APP_PLL_425_LOGIC_SOFT_RESET); | ||
1583 | |||
1584 | /** | ||
1585 | * Wait for PLLs to lock. | ||
1586 | */ | ||
1587 | bfa_os_udelay(2000); | ||
1588 | bfa_reg_write((rb + HOSTFN0_INT_STATUS), 0xffffffffU); | ||
1589 | bfa_reg_write((rb + HOSTFN1_INT_STATUS), 0xffffffffU); | ||
1590 | |||
1591 | bfa_reg_write(ioc->ioc_regs.app_pll_slow_ctl_reg, pll_sclk); | ||
1592 | bfa_reg_write(ioc->ioc_regs.app_pll_fast_ctl_reg, pll_fclk); | ||
1593 | |||
1594 | if (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT) { | ||
1595 | bfa_reg_write((rb + MBIST_CTL_REG), __EDRAM_BISTR_START); | ||
1596 | bfa_os_udelay(1000); | ||
1597 | r32 = bfa_reg_read((rb + MBIST_STAT_REG)); | ||
1598 | bfa_trc(ioc, r32); | ||
1599 | } | ||
1600 | |||
1601 | return BFA_STATUS_OK; | ||
1602 | } | ||
1603 | |||
1604 | /** | ||
1605 | * Interface used by diag module to do firmware boot with memory test | ||
1606 | * as the entry vector. | ||
1607 | */ | ||
1608 | void | ||
1609 | bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param) | ||
1610 | { | ||
1611 | bfa_os_addr_t rb; | ||
1612 | |||
1613 | bfa_ioc_stats(ioc, ioc_boots); | ||
1614 | |||
1615 | if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK) | ||
1616 | return; | ||
1617 | |||
1618 | /** | ||
1619 | * Initialize IOC state of all functions on a chip reset. | ||
1620 | */ | ||
1621 | rb = ioc->pcidev.pci_bar_kva; | ||
1622 | if (boot_param == BFI_BOOT_TYPE_MEMTEST) { | ||
1623 | bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_MEMTEST); | ||
1624 | bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_MEMTEST); | ||
1625 | } else { | ||
1626 | bfa_reg_write((rb + BFA_IOC0_STATE_REG), BFI_IOC_INITING); | ||
1627 | bfa_reg_write((rb + BFA_IOC1_STATE_REG), BFI_IOC_INITING); | ||
1628 | } | ||
1629 | |||
1630 | bfa_ioc_download_fw(ioc, boot_type, boot_param); | ||
1631 | |||
1632 | /** | ||
1633 | * Enable interrupts just before starting LPU | ||
1634 | */ | ||
1635 | ioc->cbfn->reset_cbfn(ioc->bfa); | ||
1636 | bfa_ioc_lpu_start(ioc); | ||
1637 | } | ||
1638 | |||
1639 | /** | ||
1640 | * Enable/disable IOC failure auto recovery. | ||
1641 | */ | ||
1642 | void | ||
1643 | bfa_ioc_auto_recover(bfa_boolean_t auto_recover) | ||
1644 | { | ||
1645 | bfa_auto_recover = BFA_FALSE; | ||
1646 | } | ||
1647 | |||
1648 | |||
1649 | bfa_boolean_t | ||
1650 | bfa_ioc_is_operational(struct bfa_ioc_s *ioc) | ||
1651 | { | ||
1652 | return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op); | ||
1653 | } | ||
1654 | |||
1655 | void | ||
1656 | bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg) | ||
1657 | { | ||
1658 | u32 *msgp = mbmsg; | ||
1659 | u32 r32; | ||
1660 | int i; | ||
1661 | |||
1662 | /** | ||
1663 | * read the MBOX msg | ||
1664 | */ | ||
1665 | for (i = 0; i < (sizeof(union bfi_ioc_i2h_msg_u) / sizeof(u32)); | ||
1666 | i++) { | ||
1667 | r32 = bfa_reg_read(ioc->ioc_regs.lpu_mbox + | ||
1668 | i * sizeof(u32)); | ||
1669 | msgp[i] = bfa_os_htonl(r32); | ||
1670 | } | ||
1671 | |||
1672 | /** | ||
1673 | * turn off mailbox interrupt by clearing mailbox status | ||
1674 | */ | ||
1675 | bfa_reg_write(ioc->ioc_regs.lpu_mbox_cmd, 1); | ||
1676 | bfa_reg_read(ioc->ioc_regs.lpu_mbox_cmd); | ||
1677 | } | ||
1678 | |||
1679 | void | ||
1680 | bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *m) | ||
1681 | { | ||
1682 | union bfi_ioc_i2h_msg_u *msg; | ||
1683 | |||
1684 | msg = (union bfi_ioc_i2h_msg_u *)m; | ||
1685 | |||
1686 | bfa_ioc_stats(ioc, ioc_isrs); | ||
1687 | |||
1688 | switch (msg->mh.msg_id) { | ||
1689 | case BFI_IOC_I2H_HBEAT: | ||
1690 | break; | ||
1691 | |||
1692 | case BFI_IOC_I2H_READY_EVENT: | ||
1693 | bfa_fsm_send_event(ioc, IOC_E_FWREADY); | ||
1694 | break; | ||
1695 | |||
1696 | case BFI_IOC_I2H_ENABLE_REPLY: | ||
1697 | bfa_fsm_send_event(ioc, IOC_E_FWRSP_ENABLE); | ||
1698 | break; | ||
1699 | |||
1700 | case BFI_IOC_I2H_DISABLE_REPLY: | ||
1701 | bfa_fsm_send_event(ioc, IOC_E_FWRSP_DISABLE); | ||
1702 | break; | ||
1703 | |||
1704 | case BFI_IOC_I2H_GETATTR_REPLY: | ||
1705 | bfa_ioc_getattr_reply(ioc); | ||
1706 | break; | ||
1707 | |||
1708 | default: | ||
1709 | bfa_trc(ioc, msg->mh.msg_id); | ||
1710 | bfa_assert(0); | ||
1711 | } | ||
1712 | } | ||
1713 | |||
1714 | /** | ||
1715 | * IOC attach time initialization and setup. | ||
1716 | * | ||
1717 | * @param[in] ioc memory for IOC | ||
1718 | * @param[in] bfa driver instance structure | ||
1719 | * @param[in] trcmod kernel trace module | ||
1720 | * @param[in] aen kernel aen event module | ||
1721 | * @param[in] logm kernel logging module | ||
1722 | */ | ||
1723 | void | ||
1724 | bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, struct bfa_ioc_cbfn_s *cbfn, | ||
1725 | struct bfa_timer_mod_s *timer_mod, struct bfa_trc_mod_s *trcmod, | ||
1726 | struct bfa_aen_s *aen, struct bfa_log_mod_s *logm) | ||
1727 | { | ||
1728 | ioc->bfa = bfa; | ||
1729 | ioc->cbfn = cbfn; | ||
1730 | ioc->timer_mod = timer_mod; | ||
1731 | ioc->trcmod = trcmod; | ||
1732 | ioc->aen = aen; | ||
1733 | ioc->logm = logm; | ||
1734 | ioc->fcmode = BFA_FALSE; | ||
1735 | ioc->pllinit = BFA_FALSE; | ||
1736 | ioc->dbg_fwsave_once = BFA_TRUE; | ||
1737 | |||
1738 | bfa_ioc_mbox_attach(ioc); | ||
1739 | INIT_LIST_HEAD(&ioc->hb_notify_q); | ||
1740 | |||
1741 | bfa_fsm_set_state(ioc, bfa_ioc_sm_reset); | ||
1742 | } | ||
1743 | |||
1744 | /** | ||
1745 | * Driver detach time IOC cleanup. | ||
1746 | */ | ||
1747 | void | ||
1748 | bfa_ioc_detach(struct bfa_ioc_s *ioc) | ||
1749 | { | ||
1750 | bfa_fsm_send_event(ioc, IOC_E_DETACH); | ||
1751 | } | ||
1752 | |||
1753 | /** | ||
1754 | * Setup IOC PCI properties. | ||
1755 | * | ||
1756 | * @param[in] pcidev PCI device information for this IOC | ||
1757 | */ | ||
1758 | void | ||
1759 | bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, | ||
1760 | enum bfi_mclass mc) | ||
1761 | { | ||
1762 | ioc->ioc_mc = mc; | ||
1763 | ioc->pcidev = *pcidev; | ||
1764 | ioc->ctdev = (ioc->pcidev.device_id == BFA_PCI_DEVICE_ID_CT); | ||
1765 | ioc->cna = ioc->ctdev && !ioc->fcmode; | ||
1766 | |||
1767 | bfa_ioc_map_port(ioc); | ||
1768 | bfa_ioc_reg_init(ioc); | ||
1769 | } | ||
1770 | |||
1771 | /** | ||
1772 | * Initialize IOC dma memory | ||
1773 | * | ||
1774 | * @param[in] dm_kva kernel virtual address of IOC dma memory | ||
1775 | * @param[in] dm_pa physical address of IOC dma memory | ||
1776 | */ | ||
1777 | void | ||
1778 | bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa) | ||
1779 | { | ||
1780 | /** | ||
1781 | * dma memory for firmware attribute | ||
1782 | */ | ||
1783 | ioc->attr_dma.kva = dm_kva; | ||
1784 | ioc->attr_dma.pa = dm_pa; | ||
1785 | ioc->attr = (struct bfi_ioc_attr_s *)dm_kva; | ||
1786 | } | ||
1787 | |||
1788 | /** | ||
1789 | * Return size of dma memory required. | ||
1790 | */ | ||
1791 | u32 | ||
1792 | bfa_ioc_meminfo(void) | ||
1793 | { | ||
1794 | return BFA_ROUNDUP(sizeof(struct bfi_ioc_attr_s), BFA_DMA_ALIGN_SZ); | ||
1795 | } | ||
1796 | |||
1797 | void | ||
1798 | bfa_ioc_enable(struct bfa_ioc_s *ioc) | ||
1799 | { | ||
1800 | bfa_ioc_stats(ioc, ioc_enables); | ||
1801 | ioc->dbg_fwsave_once = BFA_TRUE; | ||
1802 | |||
1803 | bfa_fsm_send_event(ioc, IOC_E_ENABLE); | ||
1804 | } | ||
1805 | |||
1806 | void | ||
1807 | bfa_ioc_disable(struct bfa_ioc_s *ioc) | ||
1808 | { | ||
1809 | bfa_ioc_stats(ioc, ioc_disables); | ||
1810 | bfa_fsm_send_event(ioc, IOC_E_DISABLE); | ||
1811 | } | ||
1812 | |||
1813 | /** | ||
1814 | * Returns memory required for saving firmware trace in case of crash. | ||
1815 | * Driver must call this interface to allocate memory required for | ||
1816 | * automatic saving of firmware trace. Driver should call | ||
1817 | * bfa_ioc_debug_memclaim() right after bfa_ioc_attach() to setup this | ||
1818 | * trace memory. | ||
1819 | */ | ||
1820 | int | ||
1821 | bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover) | ||
1822 | { | ||
1823 | return (auto_recover) ? BFA_DBG_FWTRC_LEN : 0; | ||
1824 | } | ||
1825 | |||
1826 | /** | ||
1827 | * Initialize memory for saving firmware trace. Driver must initialize | ||
1828 | * trace memory before call bfa_ioc_enable(). | ||
1829 | */ | ||
1830 | void | ||
1831 | bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave) | ||
1832 | { | ||
1833 | bfa_assert(ioc->auto_recover); | ||
1834 | ioc->dbg_fwsave = dbg_fwsave; | ||
1835 | ioc->dbg_fwsave_len = bfa_ioc_debug_trcsz(ioc->auto_recover); | ||
1836 | } | ||
1837 | |||
1838 | u32 | ||
1839 | bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr) | ||
1840 | { | ||
1841 | return PSS_SMEM_PGNUM(ioc->ioc_regs.smem_pg0, fmaddr); | ||
1842 | } | ||
1843 | |||
1844 | u32 | ||
1845 | bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr) | ||
1846 | { | ||
1847 | return PSS_SMEM_PGOFF(fmaddr); | ||
1848 | } | ||
1849 | |||
1850 | /** | ||
1851 | * Register mailbox message handler functions | ||
1852 | * | ||
1853 | * @param[in] ioc IOC instance | ||
1854 | * @param[in] mcfuncs message class handler functions | ||
1855 | */ | ||
1856 | void | ||
1857 | bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, bfa_ioc_mbox_mcfunc_t *mcfuncs) | ||
1858 | { | ||
1859 | struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod; | ||
1860 | int mc; | ||
1861 | |||
1862 | for (mc = 0; mc < BFI_MC_MAX; mc++) | ||
1863 | mod->mbhdlr[mc].cbfn = mcfuncs[mc]; | ||
1864 | } | ||
1865 | |||
1866 | /** | ||
1867 | * Register mailbox message handler function, to be called by common modules | ||
1868 | */ | ||
1869 | void | ||
1870 | bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc, | ||
1871 | bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg) | ||
1872 | { | ||
1873 | struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod; | ||
1874 | |||
1875 | mod->mbhdlr[mc].cbfn = cbfn; | ||
1876 | mod->mbhdlr[mc].cbarg = cbarg; | ||
1877 | } | ||
1878 | |||
1879 | /** | ||
1880 | * Queue a mailbox command request to firmware. Waits if mailbox is busy. | ||
1881 | * Responsibility of caller to serialize | ||
1882 | * | ||
1883 | * @param[in] ioc IOC instance | ||
1884 | * @param[i] cmd Mailbox command | ||
1885 | */ | ||
1886 | void | ||
1887 | bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd) | ||
1888 | { | ||
1889 | struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod; | ||
1890 | u32 stat; | ||
1891 | |||
1892 | /** | ||
1893 | * If a previous command is pending, queue new command | ||
1894 | */ | ||
1895 | if (!list_empty(&mod->cmd_q)) { | ||
1896 | list_add_tail(&cmd->qe, &mod->cmd_q); | ||
1897 | return; | ||
1898 | } | ||
1899 | |||
1900 | /** | ||
1901 | * If mailbox is busy, queue command for poll timer | ||
1902 | */ | ||
1903 | stat = bfa_reg_read(ioc->ioc_regs.hfn_mbox_cmd); | ||
1904 | if (stat) { | ||
1905 | list_add_tail(&cmd->qe, &mod->cmd_q); | ||
1906 | return; | ||
1907 | } | ||
1908 | |||
1909 | /** | ||
1910 | * mailbox is free -- queue command to firmware | ||
1911 | */ | ||
1912 | bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg)); | ||
1913 | } | ||
1914 | |||
1915 | /** | ||
1916 | * Handle mailbox interrupts | ||
1917 | */ | ||
1918 | void | ||
1919 | bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc) | ||
1920 | { | ||
1921 | struct bfa_ioc_mbox_mod_s *mod = &ioc->mbox_mod; | ||
1922 | struct bfi_mbmsg_s m; | ||
1923 | int mc; | ||
1924 | |||
1925 | bfa_ioc_msgget(ioc, &m); | ||
1926 | |||
1927 | /** | ||
1928 | * Treat IOC message class as special. | ||
1929 | */ | ||
1930 | mc = m.mh.msg_class; | ||
1931 | if (mc == BFI_MC_IOC) { | ||
1932 | bfa_ioc_isr(ioc, &m); | ||
1933 | return; | ||
1934 | } | ||
1935 | |||
1936 | if ((mc > BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL)) | ||
1937 | return; | ||
1938 | |||
1939 | mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m); | ||
1940 | } | ||
1941 | |||
1942 | void | ||
1943 | bfa_ioc_error_isr(struct bfa_ioc_s *ioc) | ||
1944 | { | ||
1945 | bfa_fsm_send_event(ioc, IOC_E_HWERROR); | ||
1946 | } | ||
1947 | |||
1948 | #ifndef BFA_BIOS_BUILD | ||
1949 | |||
1950 | /** | ||
1951 | * return true if IOC is disabled | ||
1952 | */ | ||
1953 | bfa_boolean_t | ||
1954 | bfa_ioc_is_disabled(struct bfa_ioc_s *ioc) | ||
1955 | { | ||
1956 | return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabling) | ||
1957 | || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled)); | ||
1958 | } | ||
1959 | |||
1960 | /** | ||
1961 | * return true if IOC firmware is different. | ||
1962 | */ | ||
1963 | bfa_boolean_t | ||
1964 | bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc) | ||
1965 | { | ||
1966 | return (bfa_fsm_cmp_state(ioc, bfa_ioc_sm_reset) | ||
1967 | || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_fwcheck) | ||
1968 | || bfa_fsm_cmp_state(ioc, bfa_ioc_sm_mismatch)); | ||
1969 | } | ||
1970 | |||
1971 | #define bfa_ioc_state_disabled(__sm) \ | ||
1972 | (((__sm) == BFI_IOC_UNINIT) || \ | ||
1973 | ((__sm) == BFI_IOC_INITING) || \ | ||
1974 | ((__sm) == BFI_IOC_HWINIT) || \ | ||
1975 | ((__sm) == BFI_IOC_DISABLED) || \ | ||
1976 | ((__sm) == BFI_IOC_HBFAIL) || \ | ||
1977 | ((__sm) == BFI_IOC_CFG_DISABLED)) | ||
1978 | |||
1979 | /** | ||
1980 | * Check if adapter is disabled -- both IOCs should be in a disabled | ||
1981 | * state. | ||
1982 | */ | ||
1983 | bfa_boolean_t | ||
1984 | bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc) | ||
1985 | { | ||
1986 | u32 ioc_state; | ||
1987 | bfa_os_addr_t rb = ioc->pcidev.pci_bar_kva; | ||
1988 | |||
1989 | if (!bfa_fsm_cmp_state(ioc, bfa_ioc_sm_disabled)) | ||
1990 | return BFA_FALSE; | ||
1991 | |||
1992 | ioc_state = bfa_reg_read(rb + BFA_IOC0_STATE_REG); | ||
1993 | if (!bfa_ioc_state_disabled(ioc_state)) | ||
1994 | return BFA_FALSE; | ||
1995 | |||
1996 | ioc_state = bfa_reg_read(rb + BFA_IOC1_STATE_REG); | ||
1997 | if (!bfa_ioc_state_disabled(ioc_state)) | ||
1998 | return BFA_FALSE; | ||
1999 | |||
2000 | return BFA_TRUE; | ||
2001 | } | ||
2002 | |||
2003 | /** | ||
2004 | * Add to IOC heartbeat failure notification queue. To be used by common | ||
2005 | * modules such as | ||
2006 | */ | ||
2007 | void | ||
2008 | bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc, | ||
2009 | struct bfa_ioc_hbfail_notify_s *notify) | ||
2010 | { | ||
2011 | list_add_tail(¬ify->qe, &ioc->hb_notify_q); | ||
2012 | } | ||
2013 | |||
2014 | #define BFA_MFG_NAME "Brocade" | ||
2015 | void | ||
2016 | bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, | ||
2017 | struct bfa_adapter_attr_s *ad_attr) | ||
2018 | { | ||
2019 | struct bfi_ioc_attr_s *ioc_attr; | ||
2020 | char model[BFA_ADAPTER_MODEL_NAME_LEN]; | ||
2021 | |||
2022 | ioc_attr = ioc->attr; | ||
2023 | bfa_os_memcpy((void *)&ad_attr->serial_num, | ||
2024 | (void *)ioc_attr->brcd_serialnum, | ||
2025 | BFA_ADAPTER_SERIAL_NUM_LEN); | ||
2026 | |||
2027 | bfa_os_memcpy(&ad_attr->fw_ver, ioc_attr->fw_version, BFA_VERSION_LEN); | ||
2028 | bfa_os_memcpy(&ad_attr->optrom_ver, ioc_attr->optrom_version, | ||
2029 | BFA_VERSION_LEN); | ||
2030 | bfa_os_memcpy(&ad_attr->manufacturer, BFA_MFG_NAME, | ||
2031 | BFA_ADAPTER_MFG_NAME_LEN); | ||
2032 | bfa_os_memcpy(&ad_attr->vpd, &ioc_attr->vpd, | ||
2033 | sizeof(struct bfa_mfg_vpd_s)); | ||
2034 | |||
2035 | ad_attr->nports = BFI_ADAPTER_GETP(NPORTS, ioc_attr->adapter_prop); | ||
2036 | ad_attr->max_speed = BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop); | ||
2037 | |||
2038 | /** | ||
2039 | * model name | ||
2040 | */ | ||
2041 | if (BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop) == 10) { | ||
2042 | strcpy(model, "BR-10?0"); | ||
2043 | model[5] = '0' + ad_attr->nports; | ||
2044 | } else { | ||
2045 | strcpy(model, "Brocade-??5"); | ||
2046 | model[8] = | ||
2047 | '0' + BFI_ADAPTER_GETP(SPEED, ioc_attr->adapter_prop); | ||
2048 | model[9] = '0' + ad_attr->nports; | ||
2049 | } | ||
2050 | |||
2051 | if (BFI_ADAPTER_IS_SPECIAL(ioc_attr->adapter_prop)) | ||
2052 | ad_attr->prototype = 1; | ||
2053 | else | ||
2054 | ad_attr->prototype = 0; | ||
2055 | |||
2056 | bfa_os_memcpy(&ad_attr->model, model, BFA_ADAPTER_MODEL_NAME_LEN); | ||
2057 | bfa_os_memcpy(&ad_attr->model_descr, &ad_attr->model, | ||
2058 | BFA_ADAPTER_MODEL_NAME_LEN); | ||
2059 | |||
2060 | ad_attr->pwwn = bfa_ioc_get_pwwn(ioc); | ||
2061 | ad_attr->mac = bfa_ioc_get_mac(ioc); | ||
2062 | |||
2063 | ad_attr->pcie_gen = ioc_attr->pcie_gen; | ||
2064 | ad_attr->pcie_lanes = ioc_attr->pcie_lanes; | ||
2065 | ad_attr->pcie_lanes_orig = ioc_attr->pcie_lanes_orig; | ||
2066 | ad_attr->asic_rev = ioc_attr->asic_rev; | ||
2067 | ad_attr->hw_ver[0] = 'R'; | ||
2068 | ad_attr->hw_ver[1] = 'e'; | ||
2069 | ad_attr->hw_ver[2] = 'v'; | ||
2070 | ad_attr->hw_ver[3] = '-'; | ||
2071 | ad_attr->hw_ver[4] = ioc_attr->asic_rev; | ||
2072 | ad_attr->hw_ver[5] = '\0'; | ||
2073 | |||
2074 | ad_attr->cna_capable = ioc->cna; | ||
2075 | } | ||
2076 | |||
2077 | void | ||
2078 | bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr) | ||
2079 | { | ||
2080 | bfa_os_memset((void *)ioc_attr, 0, sizeof(struct bfa_ioc_attr_s)); | ||
2081 | |||
2082 | ioc_attr->state = bfa_sm_to_state(ioc_sm_table, ioc->fsm); | ||
2083 | ioc_attr->port_id = ioc->port_id; | ||
2084 | |||
2085 | if (!ioc->ctdev) | ||
2086 | ioc_attr->ioc_type = BFA_IOC_TYPE_FC; | ||
2087 | else if (ioc->ioc_mc == BFI_MC_IOCFC) | ||
2088 | ioc_attr->ioc_type = BFA_IOC_TYPE_FCoE; | ||
2089 | else if (ioc->ioc_mc == BFI_MC_LL) | ||
2090 | ioc_attr->ioc_type = BFA_IOC_TYPE_LL; | ||
2091 | |||
2092 | bfa_ioc_get_adapter_attr(ioc, &ioc_attr->adapter_attr); | ||
2093 | |||
2094 | ioc_attr->pci_attr.device_id = ioc->pcidev.device_id; | ||
2095 | ioc_attr->pci_attr.pcifn = ioc->pcidev.pci_func; | ||
2096 | ioc_attr->pci_attr.chip_rev[0] = 'R'; | ||
2097 | ioc_attr->pci_attr.chip_rev[1] = 'e'; | ||
2098 | ioc_attr->pci_attr.chip_rev[2] = 'v'; | ||
2099 | ioc_attr->pci_attr.chip_rev[3] = '-'; | ||
2100 | ioc_attr->pci_attr.chip_rev[4] = ioc_attr->adapter_attr.asic_rev; | ||
2101 | ioc_attr->pci_attr.chip_rev[5] = '\0'; | ||
2102 | } | ||
2103 | |||
2104 | /** | ||
2105 | * hal_wwn_public | ||
2106 | */ | ||
2107 | wwn_t | ||
2108 | bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc) | ||
2109 | { | ||
2110 | union { | ||
2111 | wwn_t wwn; | ||
2112 | u8 byte[sizeof(wwn_t)]; | ||
2113 | } | ||
2114 | w; | ||
2115 | |||
2116 | w.wwn = ioc->attr->mfg_wwn; | ||
2117 | |||
2118 | if (bfa_ioc_portid(ioc) == 1) | ||
2119 | w.byte[7]++; | ||
2120 | |||
2121 | return w.wwn; | ||
2122 | } | ||
2123 | |||
2124 | wwn_t | ||
2125 | bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc) | ||
2126 | { | ||
2127 | union { | ||
2128 | wwn_t wwn; | ||
2129 | u8 byte[sizeof(wwn_t)]; | ||
2130 | } | ||
2131 | w; | ||
2132 | |||
2133 | w.wwn = ioc->attr->mfg_wwn; | ||
2134 | |||
2135 | if (bfa_ioc_portid(ioc) == 1) | ||
2136 | w.byte[7]++; | ||
2137 | |||
2138 | w.byte[0] = 0x20; | ||
2139 | |||
2140 | return w.wwn; | ||
2141 | } | ||
2142 | |||
2143 | wwn_t | ||
2144 | bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst) | ||
2145 | { | ||
2146 | union { | ||
2147 | wwn_t wwn; | ||
2148 | u8 byte[sizeof(wwn_t)]; | ||
2149 | } | ||
2150 | w , w5; | ||
2151 | |||
2152 | bfa_trc(ioc, inst); | ||
2153 | |||
2154 | w.wwn = ioc->attr->mfg_wwn; | ||
2155 | w5.byte[0] = 0x50 | w.byte[2] >> 4; | ||
2156 | w5.byte[1] = w.byte[2] << 4 | w.byte[3] >> 4; | ||
2157 | w5.byte[2] = w.byte[3] << 4 | w.byte[4] >> 4; | ||
2158 | w5.byte[3] = w.byte[4] << 4 | w.byte[5] >> 4; | ||
2159 | w5.byte[4] = w.byte[5] << 4 | w.byte[6] >> 4; | ||
2160 | w5.byte[5] = w.byte[6] << 4 | w.byte[7] >> 4; | ||
2161 | w5.byte[6] = w.byte[7] << 4 | (inst & 0x0f00) >> 8; | ||
2162 | w5.byte[7] = (inst & 0xff); | ||
2163 | |||
2164 | return w5.wwn; | ||
2165 | } | ||
2166 | |||
2167 | u64 | ||
2168 | bfa_ioc_get_adid(struct bfa_ioc_s *ioc) | ||
2169 | { | ||
2170 | return ioc->attr->mfg_wwn; | ||
2171 | } | ||
2172 | |||
2173 | mac_t | ||
2174 | bfa_ioc_get_mac(struct bfa_ioc_s *ioc) | ||
2175 | { | ||
2176 | mac_t mac; | ||
2177 | |||
2178 | mac = ioc->attr->mfg_mac; | ||
2179 | mac.mac[MAC_ADDRLEN - 1] += bfa_ioc_pcifn(ioc); | ||
2180 | |||
2181 | return mac; | ||
2182 | } | ||
2183 | |||
2184 | void | ||
2185 | bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc) | ||
2186 | { | ||
2187 | ioc->fcmode = BFA_TRUE; | ||
2188 | ioc->port_id = bfa_ioc_pcifn(ioc); | ||
2189 | } | ||
2190 | |||
2191 | bfa_boolean_t | ||
2192 | bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc) | ||
2193 | { | ||
2194 | return ioc->fcmode || (ioc->pcidev.device_id != BFA_PCI_DEVICE_ID_CT); | ||
2195 | } | ||
2196 | |||
2197 | /** | ||
2198 | * Return true if interrupt should be claimed. | ||
2199 | */ | ||
2200 | bfa_boolean_t | ||
2201 | bfa_ioc_intx_claim(struct bfa_ioc_s *ioc) | ||
2202 | { | ||
2203 | u32 isr, msk; | ||
2204 | |||
2205 | /** | ||
2206 | * Always claim if not catapult. | ||
2207 | */ | ||
2208 | if (!ioc->ctdev) | ||
2209 | return BFA_TRUE; | ||
2210 | |||
2211 | /** | ||
2212 | * FALSE if next device is claiming interrupt. | ||
2213 | * TRUE if next device is not interrupting or not present. | ||
2214 | */ | ||
2215 | msk = bfa_reg_read(ioc->ioc_regs.shirq_msk_next); | ||
2216 | isr = bfa_reg_read(ioc->ioc_regs.shirq_isr_next); | ||
2217 | return !(isr & ~msk); | ||
2218 | } | ||
2219 | |||
2220 | /** | ||
2221 | * Send AEN notification | ||
2222 | */ | ||
2223 | static void | ||
2224 | bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event) | ||
2225 | { | ||
2226 | union bfa_aen_data_u aen_data; | ||
2227 | struct bfa_log_mod_s *logmod = ioc->logm; | ||
2228 | s32 inst_num = 0; | ||
2229 | struct bfa_ioc_attr_s ioc_attr; | ||
2230 | |||
2231 | switch (event) { | ||
2232 | case BFA_IOC_AEN_HBGOOD: | ||
2233 | bfa_log(logmod, BFA_AEN_IOC_HBGOOD, inst_num); | ||
2234 | break; | ||
2235 | case BFA_IOC_AEN_HBFAIL: | ||
2236 | bfa_log(logmod, BFA_AEN_IOC_HBFAIL, inst_num); | ||
2237 | break; | ||
2238 | case BFA_IOC_AEN_ENABLE: | ||
2239 | bfa_log(logmod, BFA_AEN_IOC_ENABLE, inst_num); | ||
2240 | break; | ||
2241 | case BFA_IOC_AEN_DISABLE: | ||
2242 | bfa_log(logmod, BFA_AEN_IOC_DISABLE, inst_num); | ||
2243 | break; | ||
2244 | case BFA_IOC_AEN_FWMISMATCH: | ||
2245 | bfa_log(logmod, BFA_AEN_IOC_FWMISMATCH, inst_num); | ||
2246 | break; | ||
2247 | default: | ||
2248 | break; | ||
2249 | } | ||
2250 | |||
2251 | memset(&aen_data.ioc.pwwn, 0, sizeof(aen_data.ioc.pwwn)); | ||
2252 | memset(&aen_data.ioc.mac, 0, sizeof(aen_data.ioc.mac)); | ||
2253 | bfa_ioc_get_attr(ioc, &ioc_attr); | ||
2254 | switch (ioc_attr.ioc_type) { | ||
2255 | case BFA_IOC_TYPE_FC: | ||
2256 | aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc); | ||
2257 | break; | ||
2258 | case BFA_IOC_TYPE_FCoE: | ||
2259 | aen_data.ioc.pwwn = bfa_ioc_get_pwwn(ioc); | ||
2260 | aen_data.ioc.mac = bfa_ioc_get_mac(ioc); | ||
2261 | break; | ||
2262 | case BFA_IOC_TYPE_LL: | ||
2263 | aen_data.ioc.mac = bfa_ioc_get_mac(ioc); | ||
2264 | break; | ||
2265 | default: | ||
2266 | bfa_assert(ioc_attr.ioc_type == BFA_IOC_TYPE_FC); | ||
2267 | break; | ||
2268 | } | ||
2269 | aen_data.ioc.ioc_type = ioc_attr.ioc_type; | ||
2270 | } | ||
2271 | |||
2272 | /** | ||
2273 | * Retrieve saved firmware trace from a prior IOC failure. | ||
2274 | */ | ||
2275 | bfa_status_t | ||
2276 | bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, int *trclen) | ||
2277 | { | ||
2278 | int tlen; | ||
2279 | |||
2280 | if (ioc->dbg_fwsave_len == 0) | ||
2281 | return BFA_STATUS_ENOFSAVE; | ||
2282 | |||
2283 | tlen = *trclen; | ||
2284 | if (tlen > ioc->dbg_fwsave_len) | ||
2285 | tlen = ioc->dbg_fwsave_len; | ||
2286 | |||
2287 | bfa_os_memcpy(trcdata, ioc->dbg_fwsave, tlen); | ||
2288 | *trclen = tlen; | ||
2289 | return BFA_STATUS_OK; | ||
2290 | } | ||
2291 | |||
2292 | /** | ||
2293 | * Retrieve saved firmware trace from a prior IOC failure. | ||
2294 | */ | ||
2295 | bfa_status_t | ||
2296 | bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, int *trclen) | ||
2297 | { | ||
2298 | u32 pgnum; | ||
2299 | u32 loff = BFA_DBG_FWTRC_OFF(bfa_ioc_portid(ioc)); | ||
2300 | int i, tlen; | ||
2301 | u32 *tbuf = trcdata, r32; | ||
2302 | |||
2303 | bfa_trc(ioc, *trclen); | ||
2304 | |||
2305 | pgnum = bfa_ioc_smem_pgnum(ioc, loff); | ||
2306 | loff = bfa_ioc_smem_pgoff(ioc, loff); | ||
2307 | bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum); | ||
2308 | |||
2309 | tlen = *trclen; | ||
2310 | if (tlen > BFA_DBG_FWTRC_LEN) | ||
2311 | tlen = BFA_DBG_FWTRC_LEN; | ||
2312 | tlen /= sizeof(u32); | ||
2313 | |||
2314 | bfa_trc(ioc, tlen); | ||
2315 | |||
2316 | for (i = 0; i < tlen; i++) { | ||
2317 | r32 = bfa_mem_read(ioc->ioc_regs.smem_page_start, loff); | ||
2318 | tbuf[i] = bfa_os_ntohl(r32); | ||
2319 | loff += sizeof(u32); | ||
2320 | |||
2321 | /** | ||
2322 | * handle page offset wrap around | ||
2323 | */ | ||
2324 | loff = PSS_SMEM_PGOFF(loff); | ||
2325 | if (loff == 0) { | ||
2326 | pgnum++; | ||
2327 | bfa_reg_write(ioc->ioc_regs.host_page_num_fn, pgnum); | ||
2328 | } | ||
2329 | } | ||
2330 | bfa_reg_write(ioc->ioc_regs.host_page_num_fn, | ||
2331 | bfa_ioc_smem_pgnum(ioc, 0)); | ||
2332 | bfa_trc(ioc, pgnum); | ||
2333 | |||
2334 | *trclen = tlen * sizeof(u32); | ||
2335 | return BFA_STATUS_OK; | ||
2336 | } | ||
2337 | |||
2338 | /** | ||
2339 | * Save firmware trace if configured. | ||
2340 | */ | ||
2341 | static void | ||
2342 | bfa_ioc_debug_save(struct bfa_ioc_s *ioc) | ||
2343 | { | ||
2344 | int tlen; | ||
2345 | |||
2346 | if (ioc->dbg_fwsave_len) { | ||
2347 | tlen = ioc->dbg_fwsave_len; | ||
2348 | bfa_ioc_debug_fwtrc(ioc, ioc->dbg_fwsave, &tlen); | ||
2349 | } | ||
2350 | } | ||
2351 | |||
2352 | /** | ||
2353 | * Firmware failure detected. Start recovery actions. | ||
2354 | */ | ||
2355 | static void | ||
2356 | bfa_ioc_recover(struct bfa_ioc_s *ioc) | ||
2357 | { | ||
2358 | if (ioc->dbg_fwsave_once) { | ||
2359 | ioc->dbg_fwsave_once = BFA_FALSE; | ||
2360 | bfa_ioc_debug_save(ioc); | ||
2361 | } | ||
2362 | |||
2363 | bfa_ioc_stats(ioc, ioc_hbfails); | ||
2364 | bfa_fsm_send_event(ioc, IOC_E_HBFAIL); | ||
2365 | } | ||
2366 | |||
2367 | #else | ||
2368 | |||
2369 | static void | ||
2370 | bfa_ioc_aen_post(struct bfa_ioc_s *ioc, enum bfa_ioc_aen_event event) | ||
2371 | { | ||
2372 | } | ||
2373 | |||
2374 | static void | ||
2375 | bfa_ioc_recover(struct bfa_ioc_s *ioc) | ||
2376 | { | ||
2377 | bfa_assert(0); | ||
2378 | } | ||
2379 | |||
2380 | #endif | ||
2381 | |||
2382 | |||
diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h new file mode 100644 index 000000000000..58efd4b13143 --- /dev/null +++ b/drivers/scsi/bfa/bfa_ioc.h | |||
@@ -0,0 +1,259 @@ | |||
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 | #ifndef __BFA_IOC_H__ | ||
19 | #define __BFA_IOC_H__ | ||
20 | |||
21 | #include <cs/bfa_sm.h> | ||
22 | #include <bfi/bfi.h> | ||
23 | #include <bfi/bfi_ioc.h> | ||
24 | #include <bfi/bfi_boot.h> | ||
25 | #include <bfa_timer.h> | ||
26 | |||
27 | /** | ||
28 | * PCI device information required by IOC | ||
29 | */ | ||
30 | struct bfa_pcidev_s { | ||
31 | int pci_slot; | ||
32 | u8 pci_func; | ||
33 | u16 device_id; | ||
34 | bfa_os_addr_t pci_bar_kva; | ||
35 | }; | ||
36 | |||
37 | /** | ||
38 | * Structure used to remember the DMA-able memory block's KVA and Physical | ||
39 | * Address | ||
40 | */ | ||
41 | struct bfa_dma_s { | ||
42 | void *kva; /*! Kernel virtual address */ | ||
43 | u64 pa; /*! Physical address */ | ||
44 | }; | ||
45 | |||
46 | #define BFA_DMA_ALIGN_SZ 256 | ||
47 | #define BFA_ROUNDUP(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1)) | ||
48 | |||
49 | |||
50 | |||
51 | #define bfa_dma_addr_set(dma_addr, pa) \ | ||
52 | __bfa_dma_addr_set(&dma_addr, (u64)pa) | ||
53 | |||
54 | static inline void | ||
55 | __bfa_dma_addr_set(union bfi_addr_u *dma_addr, u64 pa) | ||
56 | { | ||
57 | dma_addr->a32.addr_lo = (u32) pa; | ||
58 | dma_addr->a32.addr_hi = (u32) (bfa_os_u32(pa)); | ||
59 | } | ||
60 | |||
61 | |||
62 | #define bfa_dma_be_addr_set(dma_addr, pa) \ | ||
63 | __bfa_dma_be_addr_set(&dma_addr, (u64)pa) | ||
64 | static inline void | ||
65 | __bfa_dma_be_addr_set(union bfi_addr_u *dma_addr, u64 pa) | ||
66 | { | ||
67 | dma_addr->a32.addr_lo = (u32) bfa_os_htonl(pa); | ||
68 | dma_addr->a32.addr_hi = (u32) bfa_os_htonl(bfa_os_u32(pa)); | ||
69 | } | ||
70 | |||
71 | struct bfa_ioc_regs_s { | ||
72 | bfa_os_addr_t hfn_mbox_cmd; | ||
73 | bfa_os_addr_t hfn_mbox; | ||
74 | bfa_os_addr_t lpu_mbox_cmd; | ||
75 | bfa_os_addr_t lpu_mbox; | ||
76 | bfa_os_addr_t pss_ctl_reg; | ||
77 | bfa_os_addr_t app_pll_fast_ctl_reg; | ||
78 | bfa_os_addr_t app_pll_slow_ctl_reg; | ||
79 | bfa_os_addr_t ioc_sem_reg; | ||
80 | bfa_os_addr_t ioc_usage_sem_reg; | ||
81 | bfa_os_addr_t ioc_usage_reg; | ||
82 | bfa_os_addr_t host_page_num_fn; | ||
83 | bfa_os_addr_t heartbeat; | ||
84 | bfa_os_addr_t ioc_fwstate; | ||
85 | bfa_os_addr_t ll_halt; | ||
86 | bfa_os_addr_t shirq_isr_next; | ||
87 | bfa_os_addr_t shirq_msk_next; | ||
88 | bfa_os_addr_t smem_page_start; | ||
89 | u32 smem_pg0; | ||
90 | }; | ||
91 | |||
92 | #define bfa_reg_read(_raddr) bfa_os_reg_read(_raddr) | ||
93 | #define bfa_reg_write(_raddr, _val) bfa_os_reg_write(_raddr, _val) | ||
94 | #define bfa_mem_read(_raddr, _off) bfa_os_mem_read(_raddr, _off) | ||
95 | #define bfa_mem_write(_raddr, _off, _val) \ | ||
96 | bfa_os_mem_write(_raddr, _off, _val) | ||
97 | /** | ||
98 | * IOC Mailbox structures | ||
99 | */ | ||
100 | struct bfa_mbox_cmd_s { | ||
101 | struct list_head qe; | ||
102 | u32 msg[BFI_IOC_MSGSZ]; | ||
103 | }; | ||
104 | |||
105 | /** | ||
106 | * IOC mailbox module | ||
107 | */ | ||
108 | typedef void (*bfa_ioc_mbox_mcfunc_t)(void *cbarg, struct bfi_mbmsg_s *m); | ||
109 | struct bfa_ioc_mbox_mod_s { | ||
110 | struct list_head cmd_q; /* pending mbox queue */ | ||
111 | int nmclass; /* number of handlers */ | ||
112 | struct { | ||
113 | bfa_ioc_mbox_mcfunc_t cbfn; /* message handlers */ | ||
114 | void *cbarg; | ||
115 | } mbhdlr[BFI_MC_MAX]; | ||
116 | }; | ||
117 | |||
118 | /** | ||
119 | * IOC callback function interfaces | ||
120 | */ | ||
121 | typedef void (*bfa_ioc_enable_cbfn_t)(void *bfa, enum bfa_status status); | ||
122 | typedef void (*bfa_ioc_disable_cbfn_t)(void *bfa); | ||
123 | typedef void (*bfa_ioc_hbfail_cbfn_t)(void *bfa); | ||
124 | typedef void (*bfa_ioc_reset_cbfn_t)(void *bfa); | ||
125 | struct bfa_ioc_cbfn_s { | ||
126 | bfa_ioc_enable_cbfn_t enable_cbfn; | ||
127 | bfa_ioc_disable_cbfn_t disable_cbfn; | ||
128 | bfa_ioc_hbfail_cbfn_t hbfail_cbfn; | ||
129 | bfa_ioc_reset_cbfn_t reset_cbfn; | ||
130 | }; | ||
131 | |||
132 | /** | ||
133 | * Heartbeat failure notification queue element. | ||
134 | */ | ||
135 | struct bfa_ioc_hbfail_notify_s { | ||
136 | struct list_head qe; | ||
137 | bfa_ioc_hbfail_cbfn_t cbfn; | ||
138 | void *cbarg; | ||
139 | }; | ||
140 | |||
141 | /** | ||
142 | * Initialize a heartbeat failure notification structure | ||
143 | */ | ||
144 | #define bfa_ioc_hbfail_init(__notify, __cbfn, __cbarg) do { \ | ||
145 | (__notify)->cbfn = (__cbfn); \ | ||
146 | (__notify)->cbarg = (__cbarg); \ | ||
147 | } while (0) | ||
148 | |||
149 | struct bfa_ioc_s { | ||
150 | bfa_fsm_t fsm; | ||
151 | struct bfa_s *bfa; | ||
152 | struct bfa_pcidev_s pcidev; | ||
153 | struct bfa_timer_mod_s *timer_mod; | ||
154 | struct bfa_timer_s ioc_timer; | ||
155 | struct bfa_timer_s sem_timer; | ||
156 | u32 hb_count; | ||
157 | u32 hb_fail; | ||
158 | u32 retry_count; | ||
159 | struct list_head hb_notify_q; | ||
160 | void *dbg_fwsave; | ||
161 | int dbg_fwsave_len; | ||
162 | bfa_boolean_t dbg_fwsave_once; | ||
163 | enum bfi_mclass ioc_mc; | ||
164 | struct bfa_ioc_regs_s ioc_regs; | ||
165 | struct bfa_trc_mod_s *trcmod; | ||
166 | struct bfa_aen_s *aen; | ||
167 | struct bfa_log_mod_s *logm; | ||
168 | struct bfa_ioc_drv_stats_s stats; | ||
169 | bfa_boolean_t auto_recover; | ||
170 | bfa_boolean_t fcmode; | ||
171 | bfa_boolean_t ctdev; | ||
172 | bfa_boolean_t cna; | ||
173 | bfa_boolean_t pllinit; | ||
174 | u8 port_id; | ||
175 | |||
176 | struct bfa_dma_s attr_dma; | ||
177 | struct bfi_ioc_attr_s *attr; | ||
178 | struct bfa_ioc_cbfn_s *cbfn; | ||
179 | struct bfa_ioc_mbox_mod_s mbox_mod; | ||
180 | }; | ||
181 | |||
182 | #define bfa_ioc_pcifn(__ioc) (__ioc)->pcidev.pci_func | ||
183 | #define bfa_ioc_devid(__ioc) (__ioc)->pcidev.device_id | ||
184 | #define bfa_ioc_bar0(__ioc) (__ioc)->pcidev.pci_bar_kva | ||
185 | #define bfa_ioc_portid(__ioc) ((__ioc)->port_id) | ||
186 | #define bfa_ioc_fetch_stats(__ioc, __stats) \ | ||
187 | ((__stats)->drv_stats) = (__ioc)->stats | ||
188 | #define bfa_ioc_clr_stats(__ioc) \ | ||
189 | bfa_os_memset(&(__ioc)->stats, 0, sizeof((__ioc)->stats)) | ||
190 | #define bfa_ioc_maxfrsize(__ioc) (__ioc)->attr->maxfrsize | ||
191 | #define bfa_ioc_rx_bbcredit(__ioc) (__ioc)->attr->rx_bbcredit | ||
192 | #define bfa_ioc_speed_sup(__ioc) \ | ||
193 | BFI_ADAPTER_GETP(SPEED, (__ioc)->attr->adapter_prop) | ||
194 | |||
195 | /** | ||
196 | * IOC mailbox interface | ||
197 | */ | ||
198 | void bfa_ioc_mbox_queue(struct bfa_ioc_s *ioc, struct bfa_mbox_cmd_s *cmd); | ||
199 | void bfa_ioc_mbox_register(struct bfa_ioc_s *ioc, | ||
200 | bfa_ioc_mbox_mcfunc_t *mcfuncs); | ||
201 | void bfa_ioc_mbox_isr(struct bfa_ioc_s *ioc); | ||
202 | void bfa_ioc_mbox_send(struct bfa_ioc_s *ioc, void *ioc_msg, int len); | ||
203 | void bfa_ioc_msgget(struct bfa_ioc_s *ioc, void *mbmsg); | ||
204 | void bfa_ioc_mbox_regisr(struct bfa_ioc_s *ioc, enum bfi_mclass mc, | ||
205 | bfa_ioc_mbox_mcfunc_t cbfn, void *cbarg); | ||
206 | |||
207 | /** | ||
208 | * IOC interfaces | ||
209 | */ | ||
210 | void bfa_ioc_attach(struct bfa_ioc_s *ioc, void *bfa, | ||
211 | struct bfa_ioc_cbfn_s *cbfn, struct bfa_timer_mod_s *timer_mod, | ||
212 | struct bfa_trc_mod_s *trcmod, | ||
213 | struct bfa_aen_s *aen, struct bfa_log_mod_s *logm); | ||
214 | void bfa_ioc_detach(struct bfa_ioc_s *ioc); | ||
215 | void bfa_ioc_pci_init(struct bfa_ioc_s *ioc, struct bfa_pcidev_s *pcidev, | ||
216 | enum bfi_mclass mc); | ||
217 | u32 bfa_ioc_meminfo(void); | ||
218 | void bfa_ioc_mem_claim(struct bfa_ioc_s *ioc, u8 *dm_kva, u64 dm_pa); | ||
219 | void bfa_ioc_enable(struct bfa_ioc_s *ioc); | ||
220 | void bfa_ioc_disable(struct bfa_ioc_s *ioc); | ||
221 | bfa_boolean_t bfa_ioc_intx_claim(struct bfa_ioc_s *ioc); | ||
222 | |||
223 | void bfa_ioc_boot(struct bfa_ioc_s *ioc, u32 boot_type, u32 boot_param); | ||
224 | void bfa_ioc_isr(struct bfa_ioc_s *ioc, struct bfi_mbmsg_s *msg); | ||
225 | void bfa_ioc_error_isr(struct bfa_ioc_s *ioc); | ||
226 | void bfa_ioc_isr_mode_set(struct bfa_ioc_s *ioc, bfa_boolean_t intx); | ||
227 | bfa_status_t bfa_ioc_pll_init(struct bfa_ioc_s *ioc); | ||
228 | bfa_boolean_t bfa_ioc_is_operational(struct bfa_ioc_s *ioc); | ||
229 | bfa_boolean_t bfa_ioc_is_disabled(struct bfa_ioc_s *ioc); | ||
230 | bfa_boolean_t bfa_ioc_fw_mismatch(struct bfa_ioc_s *ioc); | ||
231 | bfa_boolean_t bfa_ioc_adapter_is_disabled(struct bfa_ioc_s *ioc); | ||
232 | void bfa_ioc_cfg_complete(struct bfa_ioc_s *ioc); | ||
233 | void bfa_ioc_get_attr(struct bfa_ioc_s *ioc, struct bfa_ioc_attr_s *ioc_attr); | ||
234 | void bfa_ioc_get_adapter_attr(struct bfa_ioc_s *ioc, | ||
235 | struct bfa_adapter_attr_s *ad_attr); | ||
236 | int bfa_ioc_debug_trcsz(bfa_boolean_t auto_recover); | ||
237 | void bfa_ioc_debug_memclaim(struct bfa_ioc_s *ioc, void *dbg_fwsave); | ||
238 | bfa_status_t bfa_ioc_debug_fwsave(struct bfa_ioc_s *ioc, void *trcdata, | ||
239 | int *trclen); | ||
240 | bfa_status_t bfa_ioc_debug_fwtrc(struct bfa_ioc_s *ioc, void *trcdata, | ||
241 | int *trclen); | ||
242 | u32 bfa_ioc_smem_pgnum(struct bfa_ioc_s *ioc, u32 fmaddr); | ||
243 | u32 bfa_ioc_smem_pgoff(struct bfa_ioc_s *ioc, u32 fmaddr); | ||
244 | void bfa_ioc_set_fcmode(struct bfa_ioc_s *ioc); | ||
245 | bfa_boolean_t bfa_ioc_get_fcmode(struct bfa_ioc_s *ioc); | ||
246 | void bfa_ioc_hbfail_register(struct bfa_ioc_s *ioc, | ||
247 | struct bfa_ioc_hbfail_notify_s *notify); | ||
248 | |||
249 | /* | ||
250 | * bfa mfg wwn API functions | ||
251 | */ | ||
252 | wwn_t bfa_ioc_get_pwwn(struct bfa_ioc_s *ioc); | ||
253 | wwn_t bfa_ioc_get_nwwn(struct bfa_ioc_s *ioc); | ||
254 | wwn_t bfa_ioc_get_wwn_naa5(struct bfa_ioc_s *ioc, u16 inst); | ||
255 | mac_t bfa_ioc_get_mac(struct bfa_ioc_s *ioc); | ||
256 | u64 bfa_ioc_get_adid(struct bfa_ioc_s *ioc); | ||
257 | |||
258 | #endif /* __BFA_IOC_H__ */ | ||
259 | |||
diff --git a/drivers/scsi/bfa/bfa_iocfc.c b/drivers/scsi/bfa/bfa_iocfc.c new file mode 100644 index 000000000000..12350b022d63 --- /dev/null +++ b/drivers/scsi/bfa/bfa_iocfc.c | |||
@@ -0,0 +1,872 @@ | |||
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 | #include <cs/bfa_debug.h> | ||
19 | #include <bfa_priv.h> | ||
20 | #include <log/bfa_log_hal.h> | ||
21 | #include <bfi/bfi_boot.h> | ||
22 | #include <bfi/bfi_cbreg.h> | ||
23 | #include <aen/bfa_aen_ioc.h> | ||
24 | #include <defs/bfa_defs_iocfc.h> | ||
25 | #include <defs/bfa_defs_pci.h> | ||
26 | #include "bfa_callback_priv.h" | ||
27 | #include "bfad_drv.h" | ||
28 | |||
29 | BFA_TRC_FILE(HAL, IOCFC); | ||
30 | |||
31 | /** | ||
32 | * IOC local definitions | ||
33 | */ | ||
34 | #define BFA_IOCFC_TOV 5000 /* msecs */ | ||
35 | |||
36 | enum { | ||
37 | BFA_IOCFC_ACT_NONE = 0, | ||
38 | BFA_IOCFC_ACT_INIT = 1, | ||
39 | BFA_IOCFC_ACT_STOP = 2, | ||
40 | BFA_IOCFC_ACT_DISABLE = 3, | ||
41 | }; | ||
42 | |||
43 | /* | ||
44 | * forward declarations | ||
45 | */ | ||
46 | static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status); | ||
47 | static void bfa_iocfc_disable_cbfn(void *bfa_arg); | ||
48 | static void bfa_iocfc_hbfail_cbfn(void *bfa_arg); | ||
49 | static void bfa_iocfc_reset_cbfn(void *bfa_arg); | ||
50 | static void bfa_iocfc_stats_clear(void *bfa_arg); | ||
51 | static void bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, | ||
52 | struct bfa_fw_stats_s *s); | ||
53 | static void bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete); | ||
54 | static void bfa_iocfc_stats_clr_timeout(void *bfa_arg); | ||
55 | static void bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete); | ||
56 | static void bfa_iocfc_stats_timeout(void *bfa_arg); | ||
57 | |||
58 | static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn; | ||
59 | |||
60 | /** | ||
61 | * bfa_ioc_pvt BFA IOC private functions | ||
62 | */ | ||
63 | |||
64 | static void | ||
65 | bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len) | ||
66 | { | ||
67 | int i, per_reqq_sz, per_rspq_sz; | ||
68 | |||
69 | per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ), | ||
70 | BFA_DMA_ALIGN_SZ); | ||
71 | per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ), | ||
72 | BFA_DMA_ALIGN_SZ); | ||
73 | |||
74 | /* | ||
75 | * Calculate CQ size | ||
76 | */ | ||
77 | for (i = 0; i < cfg->fwcfg.num_cqs; i++) { | ||
78 | *dm_len = *dm_len + per_reqq_sz; | ||
79 | *dm_len = *dm_len + per_rspq_sz; | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Calculate Shadow CI/PI size | ||
84 | */ | ||
85 | for (i = 0; i < cfg->fwcfg.num_cqs; i++) | ||
86 | *dm_len += (2 * BFA_CACHELINE_SZ); | ||
87 | } | ||
88 | |||
89 | static void | ||
90 | bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len) | ||
91 | { | ||
92 | *dm_len += | ||
93 | BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); | ||
94 | *dm_len += | ||
95 | BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), | ||
96 | BFA_CACHELINE_SZ); | ||
97 | *dm_len += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ); | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ | ||
102 | */ | ||
103 | static void | ||
104 | bfa_iocfc_send_cfg(void *bfa_arg) | ||
105 | { | ||
106 | struct bfa_s *bfa = bfa_arg; | ||
107 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
108 | struct bfi_iocfc_cfg_req_s cfg_req; | ||
109 | struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo; | ||
110 | struct bfa_iocfc_cfg_s *cfg = &iocfc->cfg; | ||
111 | int i; | ||
112 | |||
113 | bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS); | ||
114 | bfa_trc(bfa, cfg->fwcfg.num_cqs); | ||
115 | |||
116 | iocfc->cfgdone = BFA_FALSE; | ||
117 | bfa_iocfc_reset_queues(bfa); | ||
118 | |||
119 | /** | ||
120 | * initialize IOC configuration info | ||
121 | */ | ||
122 | cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG; | ||
123 | cfg_info->num_cqs = cfg->fwcfg.num_cqs; | ||
124 | |||
125 | bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa); | ||
126 | bfa_dma_be_addr_set(cfg_info->stats_addr, iocfc->stats_pa); | ||
127 | |||
128 | /** | ||
129 | * dma map REQ and RSP circular queues and shadow pointers | ||
130 | */ | ||
131 | for (i = 0; i < cfg->fwcfg.num_cqs; i++) { | ||
132 | bfa_dma_be_addr_set(cfg_info->req_cq_ba[i], | ||
133 | iocfc->req_cq_ba[i].pa); | ||
134 | bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i], | ||
135 | iocfc->req_cq_shadow_ci[i].pa); | ||
136 | cfg_info->req_cq_elems[i] = | ||
137 | bfa_os_htons(cfg->drvcfg.num_reqq_elems); | ||
138 | |||
139 | bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i], | ||
140 | iocfc->rsp_cq_ba[i].pa); | ||
141 | bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i], | ||
142 | iocfc->rsp_cq_shadow_pi[i].pa); | ||
143 | cfg_info->rsp_cq_elems[i] = | ||
144 | bfa_os_htons(cfg->drvcfg.num_rspq_elems); | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * dma map IOC configuration itself | ||
149 | */ | ||
150 | bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ, | ||
151 | bfa_lpuid(bfa)); | ||
152 | bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa); | ||
153 | |||
154 | bfa_ioc_mbox_send(&bfa->ioc, &cfg_req, | ||
155 | sizeof(struct bfi_iocfc_cfg_req_s)); | ||
156 | } | ||
157 | |||
158 | static void | ||
159 | bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
160 | struct bfa_pcidev_s *pcidev) | ||
161 | { | ||
162 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
163 | |||
164 | bfa->bfad = bfad; | ||
165 | iocfc->bfa = bfa; | ||
166 | iocfc->action = BFA_IOCFC_ACT_NONE; | ||
167 | |||
168 | bfa_os_assign(iocfc->cfg, *cfg); | ||
169 | |||
170 | /** | ||
171 | * Initialize chip specific handlers. | ||
172 | */ | ||
173 | if (bfa_ioc_devid(&bfa->ioc) == BFA_PCI_DEVICE_ID_CT) { | ||
174 | iocfc->hwif.hw_reginit = bfa_hwct_reginit; | ||
175 | iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack; | ||
176 | iocfc->hwif.hw_msix_init = bfa_hwct_msix_init; | ||
177 | iocfc->hwif.hw_msix_install = bfa_hwct_msix_install; | ||
178 | iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall; | ||
179 | iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set; | ||
180 | iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs; | ||
181 | } else { | ||
182 | iocfc->hwif.hw_reginit = bfa_hwcb_reginit; | ||
183 | iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; | ||
184 | iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init; | ||
185 | iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install; | ||
186 | iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall; | ||
187 | iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set; | ||
188 | iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs; | ||
189 | } | ||
190 | |||
191 | iocfc->hwif.hw_reginit(bfa); | ||
192 | bfa->msix.nvecs = 0; | ||
193 | } | ||
194 | |||
195 | static void | ||
196 | bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg, | ||
197 | struct bfa_meminfo_s *meminfo) | ||
198 | { | ||
199 | u8 *dm_kva; | ||
200 | u64 dm_pa; | ||
201 | int i, per_reqq_sz, per_rspq_sz; | ||
202 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
203 | int dbgsz; | ||
204 | |||
205 | dm_kva = bfa_meminfo_dma_virt(meminfo); | ||
206 | dm_pa = bfa_meminfo_dma_phys(meminfo); | ||
207 | |||
208 | /* | ||
209 | * First allocate dma memory for IOC. | ||
210 | */ | ||
211 | bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa); | ||
212 | dm_kva += bfa_ioc_meminfo(); | ||
213 | dm_pa += bfa_ioc_meminfo(); | ||
214 | |||
215 | /* | ||
216 | * Claim DMA-able memory for the request/response queues and for shadow | ||
217 | * ci/pi registers | ||
218 | */ | ||
219 | per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ), | ||
220 | BFA_DMA_ALIGN_SZ); | ||
221 | per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ), | ||
222 | BFA_DMA_ALIGN_SZ); | ||
223 | |||
224 | for (i = 0; i < cfg->fwcfg.num_cqs; i++) { | ||
225 | iocfc->req_cq_ba[i].kva = dm_kva; | ||
226 | iocfc->req_cq_ba[i].pa = dm_pa; | ||
227 | bfa_os_memset(dm_kva, 0, per_reqq_sz); | ||
228 | dm_kva += per_reqq_sz; | ||
229 | dm_pa += per_reqq_sz; | ||
230 | |||
231 | iocfc->rsp_cq_ba[i].kva = dm_kva; | ||
232 | iocfc->rsp_cq_ba[i].pa = dm_pa; | ||
233 | bfa_os_memset(dm_kva, 0, per_rspq_sz); | ||
234 | dm_kva += per_rspq_sz; | ||
235 | dm_pa += per_rspq_sz; | ||
236 | } | ||
237 | |||
238 | for (i = 0; i < cfg->fwcfg.num_cqs; i++) { | ||
239 | iocfc->req_cq_shadow_ci[i].kva = dm_kva; | ||
240 | iocfc->req_cq_shadow_ci[i].pa = dm_pa; | ||
241 | dm_kva += BFA_CACHELINE_SZ; | ||
242 | dm_pa += BFA_CACHELINE_SZ; | ||
243 | |||
244 | iocfc->rsp_cq_shadow_pi[i].kva = dm_kva; | ||
245 | iocfc->rsp_cq_shadow_pi[i].pa = dm_pa; | ||
246 | dm_kva += BFA_CACHELINE_SZ; | ||
247 | dm_pa += BFA_CACHELINE_SZ; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Claim DMA-able memory for the config info page | ||
252 | */ | ||
253 | bfa->iocfc.cfg_info.kva = dm_kva; | ||
254 | bfa->iocfc.cfg_info.pa = dm_pa; | ||
255 | bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva; | ||
256 | dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); | ||
257 | dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); | ||
258 | |||
259 | /* | ||
260 | * Claim DMA-able memory for the config response | ||
261 | */ | ||
262 | bfa->iocfc.cfgrsp_dma.kva = dm_kva; | ||
263 | bfa->iocfc.cfgrsp_dma.pa = dm_pa; | ||
264 | bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva; | ||
265 | |||
266 | dm_kva += | ||
267 | BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), | ||
268 | BFA_CACHELINE_SZ); | ||
269 | dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), | ||
270 | BFA_CACHELINE_SZ); | ||
271 | |||
272 | /* | ||
273 | * Claim DMA-able memory for iocfc stats | ||
274 | */ | ||
275 | bfa->iocfc.stats_kva = dm_kva; | ||
276 | bfa->iocfc.stats_pa = dm_pa; | ||
277 | bfa->iocfc.fw_stats = (struct bfa_fw_stats_s *) dm_kva; | ||
278 | dm_kva += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ); | ||
279 | dm_pa += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ); | ||
280 | |||
281 | bfa_meminfo_dma_virt(meminfo) = dm_kva; | ||
282 | bfa_meminfo_dma_phys(meminfo) = dm_pa; | ||
283 | |||
284 | dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover); | ||
285 | if (dbgsz > 0) { | ||
286 | bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo)); | ||
287 | bfa_meminfo_kva(meminfo) += dbgsz; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * BFA submodules initialization completion notification. | ||
293 | */ | ||
294 | static void | ||
295 | bfa_iocfc_initdone_submod(struct bfa_s *bfa) | ||
296 | { | ||
297 | int i; | ||
298 | |||
299 | for (i = 0; hal_mods[i]; i++) | ||
300 | hal_mods[i]->initdone(bfa); | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * Start BFA submodules. | ||
305 | */ | ||
306 | static void | ||
307 | bfa_iocfc_start_submod(struct bfa_s *bfa) | ||
308 | { | ||
309 | int i; | ||
310 | |||
311 | bfa->rme_process = BFA_TRUE; | ||
312 | |||
313 | for (i = 0; hal_mods[i]; i++) | ||
314 | hal_mods[i]->start(bfa); | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * Disable BFA submodules. | ||
319 | */ | ||
320 | static void | ||
321 | bfa_iocfc_disable_submod(struct bfa_s *bfa) | ||
322 | { | ||
323 | int i; | ||
324 | |||
325 | for (i = 0; hal_mods[i]; i++) | ||
326 | hal_mods[i]->iocdisable(bfa); | ||
327 | } | ||
328 | |||
329 | static void | ||
330 | bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete) | ||
331 | { | ||
332 | struct bfa_s *bfa = bfa_arg; | ||
333 | |||
334 | if (complete) { | ||
335 | if (bfa->iocfc.cfgdone) | ||
336 | bfa_cb_init(bfa->bfad, BFA_STATUS_OK); | ||
337 | else | ||
338 | bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED); | ||
339 | } else | ||
340 | bfa->iocfc.action = BFA_IOCFC_ACT_NONE; | ||
341 | } | ||
342 | |||
343 | static void | ||
344 | bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl) | ||
345 | { | ||
346 | struct bfa_s *bfa = bfa_arg; | ||
347 | struct bfad_s *bfad = bfa->bfad; | ||
348 | |||
349 | if (compl) | ||
350 | complete(&bfad->comp); | ||
351 | |||
352 | else | ||
353 | bfa->iocfc.action = BFA_IOCFC_ACT_NONE; | ||
354 | } | ||
355 | |||
356 | static void | ||
357 | bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl) | ||
358 | { | ||
359 | struct bfa_s *bfa = bfa_arg; | ||
360 | struct bfad_s *bfad = bfa->bfad; | ||
361 | |||
362 | if (compl) | ||
363 | complete(&bfad->disable_comp); | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * Update BFA configuration from firmware configuration. | ||
368 | */ | ||
369 | static void | ||
370 | bfa_iocfc_cfgrsp(struct bfa_s *bfa) | ||
371 | { | ||
372 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
373 | struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; | ||
374 | struct bfa_iocfc_fwcfg_s *fwcfg = &cfgrsp->fwcfg; | ||
375 | struct bfi_iocfc_cfg_s *cfginfo = iocfc->cfginfo; | ||
376 | |||
377 | fwcfg->num_cqs = fwcfg->num_cqs; | ||
378 | fwcfg->num_ioim_reqs = bfa_os_ntohs(fwcfg->num_ioim_reqs); | ||
379 | fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs); | ||
380 | fwcfg->num_fcxp_reqs = bfa_os_ntohs(fwcfg->num_fcxp_reqs); | ||
381 | fwcfg->num_uf_bufs = bfa_os_ntohs(fwcfg->num_uf_bufs); | ||
382 | fwcfg->num_rports = bfa_os_ntohs(fwcfg->num_rports); | ||
383 | |||
384 | cfginfo->intr_attr.coalesce = cfgrsp->intr_attr.coalesce; | ||
385 | cfginfo->intr_attr.delay = bfa_os_ntohs(cfgrsp->intr_attr.delay); | ||
386 | cfginfo->intr_attr.latency = bfa_os_ntohs(cfgrsp->intr_attr.latency); | ||
387 | |||
388 | iocfc->cfgdone = BFA_TRUE; | ||
389 | |||
390 | /** | ||
391 | * Configuration is complete - initialize/start submodules | ||
392 | */ | ||
393 | if (iocfc->action == BFA_IOCFC_ACT_INIT) | ||
394 | bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa); | ||
395 | else | ||
396 | bfa_iocfc_start_submod(bfa); | ||
397 | } | ||
398 | |||
399 | static void | ||
400 | bfa_iocfc_stats_clear(void *bfa_arg) | ||
401 | { | ||
402 | struct bfa_s *bfa = bfa_arg; | ||
403 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
404 | struct bfi_iocfc_stats_req_s stats_req; | ||
405 | |||
406 | bfa_timer_start(bfa, &iocfc->stats_timer, | ||
407 | bfa_iocfc_stats_clr_timeout, bfa, | ||
408 | BFA_IOCFC_TOV); | ||
409 | |||
410 | bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CLEAR_STATS_REQ, | ||
411 | bfa_lpuid(bfa)); | ||
412 | bfa_ioc_mbox_send(&bfa->ioc, &stats_req, | ||
413 | sizeof(struct bfi_iocfc_stats_req_s)); | ||
414 | } | ||
415 | |||
416 | static void | ||
417 | bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, struct bfa_fw_stats_s *s) | ||
418 | { | ||
419 | u32 *dip = (u32 *) d; | ||
420 | u32 *sip = (u32 *) s; | ||
421 | int i; | ||
422 | |||
423 | for (i = 0; i < (sizeof(struct bfa_fw_stats_s) / sizeof(u32)); i++) | ||
424 | dip[i] = bfa_os_ntohl(sip[i]); | ||
425 | } | ||
426 | |||
427 | static void | ||
428 | bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete) | ||
429 | { | ||
430 | struct bfa_s *bfa = bfa_arg; | ||
431 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
432 | |||
433 | if (complete) { | ||
434 | bfa_ioc_clr_stats(&bfa->ioc); | ||
435 | iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status); | ||
436 | } else { | ||
437 | iocfc->stats_busy = BFA_FALSE; | ||
438 | iocfc->stats_status = BFA_STATUS_OK; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | static void | ||
443 | bfa_iocfc_stats_clr_timeout(void *bfa_arg) | ||
444 | { | ||
445 | struct bfa_s *bfa = bfa_arg; | ||
446 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
447 | |||
448 | bfa_trc(bfa, 0); | ||
449 | |||
450 | iocfc->stats_status = BFA_STATUS_ETIMER; | ||
451 | bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_clr_cb, bfa); | ||
452 | } | ||
453 | |||
454 | static void | ||
455 | bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete) | ||
456 | { | ||
457 | struct bfa_s *bfa = bfa_arg; | ||
458 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
459 | |||
460 | if (complete) { | ||
461 | if (iocfc->stats_status == BFA_STATUS_OK) { | ||
462 | bfa_os_memset(iocfc->stats_ret, 0, | ||
463 | sizeof(*iocfc->stats_ret)); | ||
464 | bfa_iocfc_stats_swap(&iocfc->stats_ret->fw_stats, | ||
465 | iocfc->fw_stats); | ||
466 | } | ||
467 | iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status); | ||
468 | } else { | ||
469 | iocfc->stats_busy = BFA_FALSE; | ||
470 | iocfc->stats_status = BFA_STATUS_OK; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | static void | ||
475 | bfa_iocfc_stats_timeout(void *bfa_arg) | ||
476 | { | ||
477 | struct bfa_s *bfa = bfa_arg; | ||
478 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
479 | |||
480 | bfa_trc(bfa, 0); | ||
481 | |||
482 | iocfc->stats_status = BFA_STATUS_ETIMER; | ||
483 | bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, bfa); | ||
484 | } | ||
485 | |||
486 | static void | ||
487 | bfa_iocfc_stats_query(struct bfa_s *bfa) | ||
488 | { | ||
489 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
490 | struct bfi_iocfc_stats_req_s stats_req; | ||
491 | |||
492 | bfa_timer_start(bfa, &iocfc->stats_timer, | ||
493 | bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV); | ||
494 | |||
495 | bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ, | ||
496 | bfa_lpuid(bfa)); | ||
497 | bfa_ioc_mbox_send(&bfa->ioc, &stats_req, | ||
498 | sizeof(struct bfi_iocfc_stats_req_s)); | ||
499 | } | ||
500 | |||
501 | void | ||
502 | bfa_iocfc_reset_queues(struct bfa_s *bfa) | ||
503 | { | ||
504 | int q; | ||
505 | |||
506 | for (q = 0; q < BFI_IOC_MAX_CQS; q++) { | ||
507 | bfa_reqq_ci(bfa, q) = 0; | ||
508 | bfa_reqq_pi(bfa, q) = 0; | ||
509 | bfa_rspq_ci(bfa, q) = 0; | ||
510 | bfa_rspq_pi(bfa, q) = 0; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | /** | ||
515 | * IOC enable request is complete | ||
516 | */ | ||
517 | static void | ||
518 | bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status) | ||
519 | { | ||
520 | struct bfa_s *bfa = bfa_arg; | ||
521 | |||
522 | if (status != BFA_STATUS_OK) { | ||
523 | bfa_isr_disable(bfa); | ||
524 | if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT) | ||
525 | bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, | ||
526 | bfa_iocfc_init_cb, bfa); | ||
527 | return; | ||
528 | } | ||
529 | |||
530 | bfa_iocfc_initdone_submod(bfa); | ||
531 | bfa_iocfc_send_cfg(bfa); | ||
532 | } | ||
533 | |||
534 | /** | ||
535 | * IOC disable request is complete | ||
536 | */ | ||
537 | static void | ||
538 | bfa_iocfc_disable_cbfn(void *bfa_arg) | ||
539 | { | ||
540 | struct bfa_s *bfa = bfa_arg; | ||
541 | |||
542 | bfa_isr_disable(bfa); | ||
543 | bfa_iocfc_disable_submod(bfa); | ||
544 | |||
545 | if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP) | ||
546 | bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb, | ||
547 | bfa); | ||
548 | else { | ||
549 | bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE); | ||
550 | bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb, | ||
551 | bfa); | ||
552 | } | ||
553 | } | ||
554 | |||
555 | /** | ||
556 | * Notify sub-modules of hardware failure. | ||
557 | */ | ||
558 | static void | ||
559 | bfa_iocfc_hbfail_cbfn(void *bfa_arg) | ||
560 | { | ||
561 | struct bfa_s *bfa = bfa_arg; | ||
562 | |||
563 | bfa->rme_process = BFA_FALSE; | ||
564 | |||
565 | bfa_isr_disable(bfa); | ||
566 | bfa_iocfc_disable_submod(bfa); | ||
567 | |||
568 | if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT) | ||
569 | bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb, | ||
570 | bfa); | ||
571 | } | ||
572 | |||
573 | /** | ||
574 | * Actions on chip-reset completion. | ||
575 | */ | ||
576 | static void | ||
577 | bfa_iocfc_reset_cbfn(void *bfa_arg) | ||
578 | { | ||
579 | struct bfa_s *bfa = bfa_arg; | ||
580 | |||
581 | bfa_iocfc_reset_queues(bfa); | ||
582 | bfa_isr_enable(bfa); | ||
583 | } | ||
584 | |||
585 | |||
586 | |||
587 | /** | ||
588 | * bfa_ioc_public | ||
589 | */ | ||
590 | |||
591 | /** | ||
592 | * Query IOC memory requirement information. | ||
593 | */ | ||
594 | void | ||
595 | bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
596 | u32 *dm_len) | ||
597 | { | ||
598 | /* dma memory for IOC */ | ||
599 | *dm_len += bfa_ioc_meminfo(); | ||
600 | |||
601 | bfa_iocfc_fw_cfg_sz(cfg, dm_len); | ||
602 | bfa_iocfc_cqs_sz(cfg, dm_len); | ||
603 | *km_len += bfa_ioc_debug_trcsz(bfa_auto_recover); | ||
604 | } | ||
605 | |||
606 | /** | ||
607 | * Query IOC memory requirement information. | ||
608 | */ | ||
609 | void | ||
610 | bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
611 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
612 | { | ||
613 | int i; | ||
614 | |||
615 | bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn; | ||
616 | bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn; | ||
617 | bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn; | ||
618 | bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn; | ||
619 | |||
620 | bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod, | ||
621 | bfa->trcmod, bfa->aen, bfa->logm); | ||
622 | bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC); | ||
623 | bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs); | ||
624 | |||
625 | /** | ||
626 | * Choose FC (ssid: 0x1C) v/s FCoE (ssid: 0x14) mode. | ||
627 | */ | ||
628 | if (0) | ||
629 | bfa_ioc_set_fcmode(&bfa->ioc); | ||
630 | |||
631 | bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev); | ||
632 | bfa_iocfc_mem_claim(bfa, cfg, meminfo); | ||
633 | bfa_timer_init(&bfa->timer_mod); | ||
634 | |||
635 | INIT_LIST_HEAD(&bfa->comp_q); | ||
636 | for (i = 0; i < BFI_IOC_MAX_CQS; i++) | ||
637 | INIT_LIST_HEAD(&bfa->reqq_waitq[i]); | ||
638 | } | ||
639 | |||
640 | /** | ||
641 | * Query IOC memory requirement information. | ||
642 | */ | ||
643 | void | ||
644 | bfa_iocfc_detach(struct bfa_s *bfa) | ||
645 | { | ||
646 | bfa_ioc_detach(&bfa->ioc); | ||
647 | } | ||
648 | |||
649 | /** | ||
650 | * Query IOC memory requirement information. | ||
651 | */ | ||
652 | void | ||
653 | bfa_iocfc_init(struct bfa_s *bfa) | ||
654 | { | ||
655 | bfa->iocfc.action = BFA_IOCFC_ACT_INIT; | ||
656 | bfa_ioc_enable(&bfa->ioc); | ||
657 | bfa_msix_install(bfa); | ||
658 | } | ||
659 | |||
660 | /** | ||
661 | * IOC start called from bfa_start(). Called to start IOC operations | ||
662 | * at driver instantiation for this instance. | ||
663 | */ | ||
664 | void | ||
665 | bfa_iocfc_start(struct bfa_s *bfa) | ||
666 | { | ||
667 | if (bfa->iocfc.cfgdone) | ||
668 | bfa_iocfc_start_submod(bfa); | ||
669 | } | ||
670 | |||
671 | /** | ||
672 | * IOC stop called from bfa_stop(). Called only when driver is unloaded | ||
673 | * for this instance. | ||
674 | */ | ||
675 | void | ||
676 | bfa_iocfc_stop(struct bfa_s *bfa) | ||
677 | { | ||
678 | bfa->iocfc.action = BFA_IOCFC_ACT_STOP; | ||
679 | |||
680 | bfa->rme_process = BFA_FALSE; | ||
681 | bfa_ioc_disable(&bfa->ioc); | ||
682 | } | ||
683 | |||
684 | void | ||
685 | bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m) | ||
686 | { | ||
687 | struct bfa_s *bfa = bfaarg; | ||
688 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
689 | union bfi_iocfc_i2h_msg_u *msg; | ||
690 | |||
691 | msg = (union bfi_iocfc_i2h_msg_u *) m; | ||
692 | bfa_trc(bfa, msg->mh.msg_id); | ||
693 | |||
694 | switch (msg->mh.msg_id) { | ||
695 | case BFI_IOCFC_I2H_CFG_REPLY: | ||
696 | iocfc->cfg_reply = &msg->cfg_reply; | ||
697 | bfa_iocfc_cfgrsp(bfa); | ||
698 | break; | ||
699 | |||
700 | case BFI_IOCFC_I2H_GET_STATS_RSP: | ||
701 | if (iocfc->stats_busy == BFA_FALSE | ||
702 | || iocfc->stats_status == BFA_STATUS_ETIMER) | ||
703 | break; | ||
704 | |||
705 | bfa_timer_stop(&iocfc->stats_timer); | ||
706 | iocfc->stats_status = BFA_STATUS_OK; | ||
707 | bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, | ||
708 | bfa); | ||
709 | break; | ||
710 | case BFI_IOCFC_I2H_CLEAR_STATS_RSP: | ||
711 | /* | ||
712 | * check for timer pop before processing the rsp | ||
713 | */ | ||
714 | if (iocfc->stats_busy == BFA_FALSE | ||
715 | || iocfc->stats_status == BFA_STATUS_ETIMER) | ||
716 | break; | ||
717 | |||
718 | bfa_timer_stop(&iocfc->stats_timer); | ||
719 | iocfc->stats_status = BFA_STATUS_OK; | ||
720 | bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, | ||
721 | bfa_iocfc_stats_clr_cb, bfa); | ||
722 | break; | ||
723 | case BFI_IOCFC_I2H_UPDATEQ_RSP: | ||
724 | iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK); | ||
725 | break; | ||
726 | default: | ||
727 | bfa_assert(0); | ||
728 | } | ||
729 | } | ||
730 | |||
731 | #ifndef BFA_BIOS_BUILD | ||
732 | void | ||
733 | bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr) | ||
734 | { | ||
735 | bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr); | ||
736 | } | ||
737 | |||
738 | u64 | ||
739 | bfa_adapter_get_id(struct bfa_s *bfa) | ||
740 | { | ||
741 | return bfa_ioc_get_adid(&bfa->ioc); | ||
742 | } | ||
743 | |||
744 | void | ||
745 | bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr) | ||
746 | { | ||
747 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
748 | |||
749 | attr->intr_attr = iocfc->cfginfo->intr_attr; | ||
750 | attr->config = iocfc->cfg; | ||
751 | } | ||
752 | |||
753 | bfa_status_t | ||
754 | bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr) | ||
755 | { | ||
756 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
757 | struct bfi_iocfc_set_intr_req_s *m; | ||
758 | |||
759 | iocfc->cfginfo->intr_attr = *attr; | ||
760 | if (!bfa_iocfc_is_operational(bfa)) | ||
761 | return BFA_STATUS_OK; | ||
762 | |||
763 | m = bfa_reqq_next(bfa, BFA_REQQ_IOC); | ||
764 | if (!m) | ||
765 | return BFA_STATUS_DEVBUSY; | ||
766 | |||
767 | bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ, | ||
768 | bfa_lpuid(bfa)); | ||
769 | m->coalesce = attr->coalesce; | ||
770 | m->delay = bfa_os_htons(attr->delay); | ||
771 | m->latency = bfa_os_htons(attr->latency); | ||
772 | |||
773 | bfa_trc(bfa, attr->delay); | ||
774 | bfa_trc(bfa, attr->latency); | ||
775 | |||
776 | bfa_reqq_produce(bfa, BFA_REQQ_IOC); | ||
777 | return BFA_STATUS_OK; | ||
778 | } | ||
779 | |||
780 | void | ||
781 | bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa) | ||
782 | { | ||
783 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
784 | |||
785 | iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1); | ||
786 | bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa); | ||
787 | } | ||
788 | |||
789 | bfa_status_t | ||
790 | bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats, | ||
791 | bfa_cb_ioc_t cbfn, void *cbarg) | ||
792 | { | ||
793 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
794 | |||
795 | if (iocfc->stats_busy) { | ||
796 | bfa_trc(bfa, iocfc->stats_busy); | ||
797 | return (BFA_STATUS_DEVBUSY); | ||
798 | } | ||
799 | |||
800 | iocfc->stats_busy = BFA_TRUE; | ||
801 | iocfc->stats_ret = stats; | ||
802 | iocfc->stats_cbfn = cbfn; | ||
803 | iocfc->stats_cbarg = cbarg; | ||
804 | |||
805 | bfa_iocfc_stats_query(bfa); | ||
806 | |||
807 | return (BFA_STATUS_OK); | ||
808 | } | ||
809 | |||
810 | bfa_status_t | ||
811 | bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg) | ||
812 | { | ||
813 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
814 | |||
815 | if (iocfc->stats_busy) { | ||
816 | bfa_trc(bfa, iocfc->stats_busy); | ||
817 | return (BFA_STATUS_DEVBUSY); | ||
818 | } | ||
819 | |||
820 | iocfc->stats_busy = BFA_TRUE; | ||
821 | iocfc->stats_cbfn = cbfn; | ||
822 | iocfc->stats_cbarg = cbarg; | ||
823 | |||
824 | bfa_iocfc_stats_clear(bfa); | ||
825 | return (BFA_STATUS_OK); | ||
826 | } | ||
827 | |||
828 | /** | ||
829 | * Enable IOC after it is disabled. | ||
830 | */ | ||
831 | void | ||
832 | bfa_iocfc_enable(struct bfa_s *bfa) | ||
833 | { | ||
834 | bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0, | ||
835 | "IOC Enable"); | ||
836 | bfa_ioc_enable(&bfa->ioc); | ||
837 | } | ||
838 | |||
839 | void | ||
840 | bfa_iocfc_disable(struct bfa_s *bfa) | ||
841 | { | ||
842 | bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0, | ||
843 | "IOC Disable"); | ||
844 | bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE; | ||
845 | |||
846 | bfa->rme_process = BFA_FALSE; | ||
847 | bfa_ioc_disable(&bfa->ioc); | ||
848 | } | ||
849 | |||
850 | |||
851 | bfa_boolean_t | ||
852 | bfa_iocfc_is_operational(struct bfa_s *bfa) | ||
853 | { | ||
854 | return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone; | ||
855 | } | ||
856 | |||
857 | /** | ||
858 | * Return boot target port wwns -- read from boot information in flash. | ||
859 | */ | ||
860 | void | ||
861 | bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns) | ||
862 | { | ||
863 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
864 | struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; | ||
865 | |||
866 | *nwwns = cfgrsp->bootwwns.nwwns; | ||
867 | *wwns = cfgrsp->bootwwns.wwn; | ||
868 | } | ||
869 | |||
870 | #endif | ||
871 | |||
872 | |||
diff --git a/drivers/scsi/bfa/bfa_iocfc.h b/drivers/scsi/bfa/bfa_iocfc.h new file mode 100644 index 000000000000..7ad177ed4cfc --- /dev/null +++ b/drivers/scsi/bfa/bfa_iocfc.h | |||
@@ -0,0 +1,168 @@ | |||
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 | #ifndef __BFA_IOCFC_H__ | ||
19 | #define __BFA_IOCFC_H__ | ||
20 | |||
21 | #include <bfa_ioc.h> | ||
22 | #include <bfa.h> | ||
23 | #include <bfi/bfi_iocfc.h> | ||
24 | #include <bfa_callback_priv.h> | ||
25 | |||
26 | #define BFA_REQQ_NELEMS_MIN (4) | ||
27 | #define BFA_RSPQ_NELEMS_MIN (4) | ||
28 | |||
29 | struct bfa_iocfc_regs_s { | ||
30 | bfa_os_addr_t intr_status; | ||
31 | bfa_os_addr_t intr_mask; | ||
32 | bfa_os_addr_t cpe_q_pi[BFI_IOC_MAX_CQS]; | ||
33 | bfa_os_addr_t cpe_q_ci[BFI_IOC_MAX_CQS]; | ||
34 | bfa_os_addr_t cpe_q_depth[BFI_IOC_MAX_CQS]; | ||
35 | bfa_os_addr_t cpe_q_ctrl[BFI_IOC_MAX_CQS]; | ||
36 | bfa_os_addr_t rme_q_ci[BFI_IOC_MAX_CQS]; | ||
37 | bfa_os_addr_t rme_q_pi[BFI_IOC_MAX_CQS]; | ||
38 | bfa_os_addr_t rme_q_depth[BFI_IOC_MAX_CQS]; | ||
39 | bfa_os_addr_t rme_q_ctrl[BFI_IOC_MAX_CQS]; | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * MSIX vector handlers | ||
44 | */ | ||
45 | #define BFA_MSIX_MAX_VECTORS 22 | ||
46 | typedef void (*bfa_msix_handler_t)(struct bfa_s *bfa, int vec); | ||
47 | struct bfa_msix_s { | ||
48 | int nvecs; | ||
49 | bfa_msix_handler_t handler[BFA_MSIX_MAX_VECTORS]; | ||
50 | }; | ||
51 | |||
52 | /** | ||
53 | * Chip specific interfaces | ||
54 | */ | ||
55 | struct bfa_hwif_s { | ||
56 | void (*hw_reginit)(struct bfa_s *bfa); | ||
57 | void (*hw_rspq_ack)(struct bfa_s *bfa, int rspq); | ||
58 | void (*hw_msix_init)(struct bfa_s *bfa, int nvecs); | ||
59 | void (*hw_msix_install)(struct bfa_s *bfa); | ||
60 | void (*hw_msix_uninstall)(struct bfa_s *bfa); | ||
61 | void (*hw_isr_mode_set)(struct bfa_s *bfa, bfa_boolean_t msix); | ||
62 | void (*hw_msix_getvecs)(struct bfa_s *bfa, u32 *vecmap, | ||
63 | u32 *nvecs, u32 *maxvec); | ||
64 | }; | ||
65 | typedef void (*bfa_cb_iocfc_t) (void *cbarg, enum bfa_status status); | ||
66 | |||
67 | struct bfa_iocfc_s { | ||
68 | struct bfa_s *bfa; | ||
69 | struct bfa_iocfc_cfg_s cfg; | ||
70 | int action; | ||
71 | |||
72 | u32 req_cq_pi[BFI_IOC_MAX_CQS]; | ||
73 | u32 rsp_cq_ci[BFI_IOC_MAX_CQS]; | ||
74 | |||
75 | struct bfa_cb_qe_s init_hcb_qe; | ||
76 | struct bfa_cb_qe_s stop_hcb_qe; | ||
77 | struct bfa_cb_qe_s dis_hcb_qe; | ||
78 | struct bfa_cb_qe_s stats_hcb_qe; | ||
79 | bfa_boolean_t cfgdone; | ||
80 | |||
81 | struct bfa_dma_s cfg_info; | ||
82 | struct bfi_iocfc_cfg_s *cfginfo; | ||
83 | struct bfa_dma_s cfgrsp_dma; | ||
84 | struct bfi_iocfc_cfgrsp_s *cfgrsp; | ||
85 | struct bfi_iocfc_cfg_reply_s *cfg_reply; | ||
86 | |||
87 | u8 *stats_kva; | ||
88 | u64 stats_pa; | ||
89 | struct bfa_fw_stats_s *fw_stats; | ||
90 | struct bfa_timer_s stats_timer; /* timer */ | ||
91 | struct bfa_iocfc_stats_s *stats_ret; /* driver stats location */ | ||
92 | bfa_status_t stats_status; /* stats/statsclr status */ | ||
93 | bfa_boolean_t stats_busy; /* outstanding stats */ | ||
94 | bfa_cb_ioc_t stats_cbfn; /* driver callback function */ | ||
95 | void *stats_cbarg; /* user callback arg */ | ||
96 | |||
97 | struct bfa_dma_s req_cq_ba[BFI_IOC_MAX_CQS]; | ||
98 | struct bfa_dma_s req_cq_shadow_ci[BFI_IOC_MAX_CQS]; | ||
99 | struct bfa_dma_s rsp_cq_ba[BFI_IOC_MAX_CQS]; | ||
100 | struct bfa_dma_s rsp_cq_shadow_pi[BFI_IOC_MAX_CQS]; | ||
101 | struct bfa_iocfc_regs_s bfa_regs; /* BFA device registers */ | ||
102 | struct bfa_hwif_s hwif; | ||
103 | |||
104 | bfa_cb_iocfc_t updateq_cbfn; /* bios callback function */ | ||
105 | void *updateq_cbarg; /* bios callback arg */ | ||
106 | }; | ||
107 | |||
108 | #define bfa_lpuid(__bfa) bfa_ioc_portid(&(__bfa)->ioc) | ||
109 | #define bfa_msix_init(__bfa, __nvecs) \ | ||
110 | (__bfa)->iocfc.hwif.hw_msix_init(__bfa, __nvecs) | ||
111 | #define bfa_msix_install(__bfa) \ | ||
112 | (__bfa)->iocfc.hwif.hw_msix_install(__bfa) | ||
113 | #define bfa_msix_uninstall(__bfa) \ | ||
114 | (__bfa)->iocfc.hwif.hw_msix_uninstall(__bfa) | ||
115 | #define bfa_isr_mode_set(__bfa, __msix) \ | ||
116 | (__bfa)->iocfc.hwif.hw_isr_mode_set(__bfa, __msix) | ||
117 | #define bfa_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) \ | ||
118 | (__bfa)->iocfc.hwif.hw_msix_getvecs(__bfa, __vecmap, __nvecs, __maxvec) | ||
119 | |||
120 | /* | ||
121 | * FC specific IOC functions. | ||
122 | */ | ||
123 | void bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
124 | u32 *dm_len); | ||
125 | void bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, | ||
126 | struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo, | ||
127 | struct bfa_pcidev_s *pcidev); | ||
128 | void bfa_iocfc_detach(struct bfa_s *bfa); | ||
129 | void bfa_iocfc_init(struct bfa_s *bfa); | ||
130 | void bfa_iocfc_start(struct bfa_s *bfa); | ||
131 | void bfa_iocfc_stop(struct bfa_s *bfa); | ||
132 | void bfa_iocfc_isr(void *bfa, struct bfi_mbmsg_s *msg); | ||
133 | void bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa); | ||
134 | bfa_boolean_t bfa_iocfc_is_operational(struct bfa_s *bfa); | ||
135 | void bfa_iocfc_reset_queues(struct bfa_s *bfa); | ||
136 | void bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba, | ||
137 | u32 reqq_sci, u32 rspq_spi, | ||
138 | bfa_cb_iocfc_t cbfn, void *cbarg); | ||
139 | |||
140 | void bfa_msix_all(struct bfa_s *bfa, int vec); | ||
141 | void bfa_msix_reqq(struct bfa_s *bfa, int vec); | ||
142 | void bfa_msix_rspq(struct bfa_s *bfa, int vec); | ||
143 | void bfa_msix_lpu_err(struct bfa_s *bfa, int vec); | ||
144 | |||
145 | void bfa_hwcb_reginit(struct bfa_s *bfa); | ||
146 | void bfa_hwcb_rspq_ack(struct bfa_s *bfa, int rspq); | ||
147 | void bfa_hwcb_msix_init(struct bfa_s *bfa, int nvecs); | ||
148 | void bfa_hwcb_msix_install(struct bfa_s *bfa); | ||
149 | void bfa_hwcb_msix_uninstall(struct bfa_s *bfa); | ||
150 | void bfa_hwcb_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix); | ||
151 | void bfa_hwcb_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, | ||
152 | u32 *nvecs, u32 *maxvec); | ||
153 | void bfa_hwct_reginit(struct bfa_s *bfa); | ||
154 | void bfa_hwct_rspq_ack(struct bfa_s *bfa, int rspq); | ||
155 | void bfa_hwct_msix_init(struct bfa_s *bfa, int nvecs); | ||
156 | void bfa_hwct_msix_install(struct bfa_s *bfa); | ||
157 | void bfa_hwct_msix_uninstall(struct bfa_s *bfa); | ||
158 | void bfa_hwct_isr_mode_set(struct bfa_s *bfa, bfa_boolean_t msix); | ||
159 | void bfa_hwct_msix_getvecs(struct bfa_s *bfa, u32 *vecmap, | ||
160 | u32 *nvecs, u32 *maxvec); | ||
161 | |||
162 | void bfa_com_meminfo(bfa_boolean_t mincfg, u32 *dm_len); | ||
163 | void bfa_com_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi, | ||
164 | bfa_boolean_t mincfg); | ||
165 | void bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t **wwns); | ||
166 | |||
167 | #endif /* __BFA_IOCFC_H__ */ | ||
168 | |||
diff --git a/drivers/scsi/bfa/bfa_iocfc_q.c b/drivers/scsi/bfa/bfa_iocfc_q.c new file mode 100644 index 000000000000..500a17df40b2 --- /dev/null +++ b/drivers/scsi/bfa/bfa_iocfc_q.c | |||
@@ -0,0 +1,44 @@ | |||
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 | #include <bfa.h> | ||
19 | #include "bfa_intr_priv.h" | ||
20 | |||
21 | BFA_TRC_FILE(HAL, IOCFC_Q); | ||
22 | |||
23 | void | ||
24 | bfa_iocfc_updateq(struct bfa_s *bfa, u32 reqq_ba, u32 rspq_ba, | ||
25 | u32 reqq_sci, u32 rspq_spi, bfa_cb_iocfc_t cbfn, | ||
26 | void *cbarg) | ||
27 | { | ||
28 | struct bfa_iocfc_s *iocfc = &bfa->iocfc; | ||
29 | struct bfi_iocfc_updateq_req_s updateq_req; | ||
30 | |||
31 | iocfc->updateq_cbfn = cbfn; | ||
32 | iocfc->updateq_cbarg = cbarg; | ||
33 | |||
34 | bfi_h2i_set(updateq_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_UPDATEQ_REQ, | ||
35 | bfa_lpuid(bfa)); | ||
36 | |||
37 | updateq_req.reqq_ba = bfa_os_htonl(reqq_ba); | ||
38 | updateq_req.rspq_ba = bfa_os_htonl(rspq_ba); | ||
39 | updateq_req.reqq_sci = bfa_os_htonl(reqq_sci); | ||
40 | updateq_req.rspq_spi = bfa_os_htonl(rspq_spi); | ||
41 | |||
42 | bfa_ioc_mbox_send(&bfa->ioc, &updateq_req, | ||
43 | sizeof(struct bfi_iocfc_updateq_req_s)); | ||
44 | } | ||
diff --git a/drivers/scsi/bfa/bfa_ioim.c b/drivers/scsi/bfa/bfa_ioim.c new file mode 100644 index 000000000000..7ae2552e1e14 --- /dev/null +++ b/drivers/scsi/bfa/bfa_ioim.c | |||
@@ -0,0 +1,1311 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <cs/bfa_debug.h> | ||
20 | #include <bfa_cb_ioim_macros.h> | ||
21 | |||
22 | BFA_TRC_FILE(HAL, IOIM); | ||
23 | |||
24 | /* | ||
25 | * forward declarations. | ||
26 | */ | ||
27 | static bfa_boolean_t bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim); | ||
28 | static bfa_boolean_t bfa_ioim_sge_setup(struct bfa_ioim_s *ioim); | ||
29 | static void bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim); | ||
30 | static bfa_boolean_t bfa_ioim_send_abort(struct bfa_ioim_s *ioim); | ||
31 | static void bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim); | ||
32 | static void __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete); | ||
33 | static void __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete); | ||
34 | static void __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete); | ||
35 | static void __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete); | ||
36 | static void __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete); | ||
37 | |||
38 | /** | ||
39 | * bfa_ioim_sm | ||
40 | */ | ||
41 | |||
42 | /** | ||
43 | * IO state machine events | ||
44 | */ | ||
45 | enum bfa_ioim_event { | ||
46 | BFA_IOIM_SM_START = 1, /* io start request from host */ | ||
47 | BFA_IOIM_SM_COMP_GOOD = 2, /* io good comp, resource free */ | ||
48 | BFA_IOIM_SM_COMP = 3, /* io comp, resource is free */ | ||
49 | BFA_IOIM_SM_COMP_UTAG = 4, /* io comp, resource is free */ | ||
50 | BFA_IOIM_SM_DONE = 5, /* io comp, resource not free */ | ||
51 | BFA_IOIM_SM_FREE = 6, /* io resource is freed */ | ||
52 | BFA_IOIM_SM_ABORT = 7, /* abort request from scsi stack */ | ||
53 | BFA_IOIM_SM_ABORT_COMP = 8, /* abort from f/w */ | ||
54 | BFA_IOIM_SM_ABORT_DONE = 9, /* abort completion from f/w */ | ||
55 | BFA_IOIM_SM_QRESUME = 10, /* CQ space available to queue IO */ | ||
56 | BFA_IOIM_SM_SGALLOCED = 11, /* SG page allocation successful */ | ||
57 | BFA_IOIM_SM_SQRETRY = 12, /* sequence recovery retry */ | ||
58 | BFA_IOIM_SM_HCB = 13, /* bfa callback complete */ | ||
59 | BFA_IOIM_SM_CLEANUP = 14, /* IO cleanup from itnim */ | ||
60 | BFA_IOIM_SM_TMSTART = 15, /* IO cleanup from tskim */ | ||
61 | BFA_IOIM_SM_TMDONE = 16, /* IO cleanup from tskim */ | ||
62 | BFA_IOIM_SM_HWFAIL = 17, /* IOC h/w failure event */ | ||
63 | BFA_IOIM_SM_IOTOV = 18, /* ITN offline TOV */ | ||
64 | }; | ||
65 | |||
66 | /* | ||
67 | * forward declaration of IO state machine | ||
68 | */ | ||
69 | static void bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, | ||
70 | enum bfa_ioim_event event); | ||
71 | static void bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, | ||
72 | enum bfa_ioim_event event); | ||
73 | static void bfa_ioim_sm_active(struct bfa_ioim_s *ioim, | ||
74 | enum bfa_ioim_event event); | ||
75 | static void bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, | ||
76 | enum bfa_ioim_event event); | ||
77 | static void bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, | ||
78 | enum bfa_ioim_event event); | ||
79 | static void bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, | ||
80 | enum bfa_ioim_event event); | ||
81 | static void bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, | ||
82 | enum bfa_ioim_event event); | ||
83 | static void bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, | ||
84 | enum bfa_ioim_event event); | ||
85 | static void bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, | ||
86 | enum bfa_ioim_event event); | ||
87 | static void bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, | ||
88 | enum bfa_ioim_event event); | ||
89 | static void bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, | ||
90 | enum bfa_ioim_event event); | ||
91 | |||
92 | /** | ||
93 | * IO is not started (unallocated). | ||
94 | */ | ||
95 | static void | ||
96 | bfa_ioim_sm_uninit(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
97 | { | ||
98 | bfa_trc_fp(ioim->bfa, ioim->iotag); | ||
99 | bfa_trc_fp(ioim->bfa, event); | ||
100 | |||
101 | switch (event) { | ||
102 | case BFA_IOIM_SM_START: | ||
103 | if (!bfa_itnim_is_online(ioim->itnim)) { | ||
104 | if (!bfa_itnim_hold_io(ioim->itnim)) { | ||
105 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
106 | list_del(&ioim->qe); | ||
107 | list_add_tail(&ioim->qe, | ||
108 | &ioim->fcpim->ioim_comp_q); | ||
109 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, | ||
110 | __bfa_cb_ioim_pathtov, ioim); | ||
111 | } else { | ||
112 | list_del(&ioim->qe); | ||
113 | list_add_tail(&ioim->qe, | ||
114 | &ioim->itnim->pending_q); | ||
115 | } | ||
116 | break; | ||
117 | } | ||
118 | |||
119 | if (ioim->nsges > BFI_SGE_INLINE) { | ||
120 | if (!bfa_ioim_sge_setup(ioim)) { | ||
121 | bfa_sm_set_state(ioim, bfa_ioim_sm_sgalloc); | ||
122 | return; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | if (!bfa_ioim_send_ioreq(ioim)) { | ||
127 | bfa_sm_set_state(ioim, bfa_ioim_sm_qfull); | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | bfa_sm_set_state(ioim, bfa_ioim_sm_active); | ||
132 | break; | ||
133 | |||
134 | case BFA_IOIM_SM_IOTOV: | ||
135 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
136 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, | ||
137 | __bfa_cb_ioim_pathtov, ioim); | ||
138 | break; | ||
139 | |||
140 | case BFA_IOIM_SM_ABORT: | ||
141 | /** | ||
142 | * IO in pending queue can get abort requests. Complete abort | ||
143 | * requests immediately. | ||
144 | */ | ||
145 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
146 | bfa_assert(bfa_q_is_on_q(&ioim->itnim->pending_q, ioim)); | ||
147 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
148 | ioim); | ||
149 | break; | ||
150 | |||
151 | default: | ||
152 | bfa_assert(0); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * IO is waiting for SG pages. | ||
158 | */ | ||
159 | static void | ||
160 | bfa_ioim_sm_sgalloc(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
161 | { | ||
162 | bfa_trc(ioim->bfa, ioim->iotag); | ||
163 | bfa_trc(ioim->bfa, event); | ||
164 | |||
165 | switch (event) { | ||
166 | case BFA_IOIM_SM_SGALLOCED: | ||
167 | if (!bfa_ioim_send_ioreq(ioim)) { | ||
168 | bfa_sm_set_state(ioim, bfa_ioim_sm_qfull); | ||
169 | break; | ||
170 | } | ||
171 | bfa_sm_set_state(ioim, bfa_ioim_sm_active); | ||
172 | break; | ||
173 | |||
174 | case BFA_IOIM_SM_CLEANUP: | ||
175 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
176 | bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe); | ||
177 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
178 | ioim); | ||
179 | bfa_ioim_notify_cleanup(ioim); | ||
180 | break; | ||
181 | |||
182 | case BFA_IOIM_SM_ABORT: | ||
183 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
184 | bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe); | ||
185 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
186 | ioim); | ||
187 | break; | ||
188 | |||
189 | case BFA_IOIM_SM_HWFAIL: | ||
190 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
191 | bfa_sgpg_wcancel(ioim->bfa, &ioim->iosp->sgpg_wqe); | ||
192 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
193 | ioim); | ||
194 | break; | ||
195 | |||
196 | default: | ||
197 | bfa_assert(0); | ||
198 | } | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * IO is active. | ||
203 | */ | ||
204 | static void | ||
205 | bfa_ioim_sm_active(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
206 | { | ||
207 | bfa_trc_fp(ioim->bfa, ioim->iotag); | ||
208 | bfa_trc_fp(ioim->bfa, event); | ||
209 | |||
210 | switch (event) { | ||
211 | case BFA_IOIM_SM_COMP_GOOD: | ||
212 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
213 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, | ||
214 | __bfa_cb_ioim_good_comp, ioim); | ||
215 | break; | ||
216 | |||
217 | case BFA_IOIM_SM_COMP: | ||
218 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
219 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp, | ||
220 | ioim); | ||
221 | break; | ||
222 | |||
223 | case BFA_IOIM_SM_DONE: | ||
224 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); | ||
225 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_comp, | ||
226 | ioim); | ||
227 | break; | ||
228 | |||
229 | case BFA_IOIM_SM_ABORT: | ||
230 | ioim->iosp->abort_explicit = BFA_TRUE; | ||
231 | ioim->io_cbfn = __bfa_cb_ioim_abort; | ||
232 | |||
233 | if (bfa_ioim_send_abort(ioim)) | ||
234 | bfa_sm_set_state(ioim, bfa_ioim_sm_abort); | ||
235 | else { | ||
236 | bfa_sm_set_state(ioim, bfa_ioim_sm_abort_qfull); | ||
237 | bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, | ||
238 | &ioim->iosp->reqq_wait); | ||
239 | } | ||
240 | break; | ||
241 | |||
242 | case BFA_IOIM_SM_CLEANUP: | ||
243 | ioim->iosp->abort_explicit = BFA_FALSE; | ||
244 | ioim->io_cbfn = __bfa_cb_ioim_failed; | ||
245 | |||
246 | if (bfa_ioim_send_abort(ioim)) | ||
247 | bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup); | ||
248 | else { | ||
249 | bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull); | ||
250 | bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, | ||
251 | &ioim->iosp->reqq_wait); | ||
252 | } | ||
253 | break; | ||
254 | |||
255 | case BFA_IOIM_SM_HWFAIL: | ||
256 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
257 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
258 | ioim); | ||
259 | break; | ||
260 | |||
261 | default: | ||
262 | bfa_assert(0); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | /** | ||
267 | * IO is being aborted, waiting for completion from firmware. | ||
268 | */ | ||
269 | static void | ||
270 | bfa_ioim_sm_abort(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
271 | { | ||
272 | bfa_trc(ioim->bfa, ioim->iotag); | ||
273 | bfa_trc(ioim->bfa, event); | ||
274 | |||
275 | switch (event) { | ||
276 | case BFA_IOIM_SM_COMP_GOOD: | ||
277 | case BFA_IOIM_SM_COMP: | ||
278 | case BFA_IOIM_SM_DONE: | ||
279 | case BFA_IOIM_SM_FREE: | ||
280 | break; | ||
281 | |||
282 | case BFA_IOIM_SM_ABORT_DONE: | ||
283 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); | ||
284 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
285 | ioim); | ||
286 | break; | ||
287 | |||
288 | case BFA_IOIM_SM_ABORT_COMP: | ||
289 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
290 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
291 | ioim); | ||
292 | break; | ||
293 | |||
294 | case BFA_IOIM_SM_COMP_UTAG: | ||
295 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
296 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
297 | ioim); | ||
298 | break; | ||
299 | |||
300 | case BFA_IOIM_SM_CLEANUP: | ||
301 | bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE); | ||
302 | ioim->iosp->abort_explicit = BFA_FALSE; | ||
303 | |||
304 | if (bfa_ioim_send_abort(ioim)) | ||
305 | bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup); | ||
306 | else { | ||
307 | bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull); | ||
308 | bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, | ||
309 | &ioim->iosp->reqq_wait); | ||
310 | } | ||
311 | break; | ||
312 | |||
313 | case BFA_IOIM_SM_HWFAIL: | ||
314 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
315 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
316 | ioim); | ||
317 | break; | ||
318 | |||
319 | default: | ||
320 | bfa_assert(0); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | /** | ||
325 | * IO is being cleaned up (implicit abort), waiting for completion from | ||
326 | * firmware. | ||
327 | */ | ||
328 | static void | ||
329 | bfa_ioim_sm_cleanup(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
330 | { | ||
331 | bfa_trc(ioim->bfa, ioim->iotag); | ||
332 | bfa_trc(ioim->bfa, event); | ||
333 | |||
334 | switch (event) { | ||
335 | case BFA_IOIM_SM_COMP_GOOD: | ||
336 | case BFA_IOIM_SM_COMP: | ||
337 | case BFA_IOIM_SM_DONE: | ||
338 | case BFA_IOIM_SM_FREE: | ||
339 | break; | ||
340 | |||
341 | case BFA_IOIM_SM_ABORT: | ||
342 | /** | ||
343 | * IO is already being aborted implicitly | ||
344 | */ | ||
345 | ioim->io_cbfn = __bfa_cb_ioim_abort; | ||
346 | break; | ||
347 | |||
348 | case BFA_IOIM_SM_ABORT_DONE: | ||
349 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); | ||
350 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim); | ||
351 | bfa_ioim_notify_cleanup(ioim); | ||
352 | break; | ||
353 | |||
354 | case BFA_IOIM_SM_ABORT_COMP: | ||
355 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
356 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim); | ||
357 | bfa_ioim_notify_cleanup(ioim); | ||
358 | break; | ||
359 | |||
360 | case BFA_IOIM_SM_COMP_UTAG: | ||
361 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
362 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim); | ||
363 | bfa_ioim_notify_cleanup(ioim); | ||
364 | break; | ||
365 | |||
366 | case BFA_IOIM_SM_HWFAIL: | ||
367 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
368 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
369 | ioim); | ||
370 | break; | ||
371 | |||
372 | case BFA_IOIM_SM_CLEANUP: | ||
373 | /** | ||
374 | * IO can be in cleanup state already due to TM command. 2nd cleanup | ||
375 | * request comes from ITN offline event. | ||
376 | */ | ||
377 | break; | ||
378 | |||
379 | default: | ||
380 | bfa_assert(0); | ||
381 | } | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * IO is waiting for room in request CQ | ||
386 | */ | ||
387 | static void | ||
388 | bfa_ioim_sm_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
389 | { | ||
390 | bfa_trc(ioim->bfa, ioim->iotag); | ||
391 | bfa_trc(ioim->bfa, event); | ||
392 | |||
393 | switch (event) { | ||
394 | case BFA_IOIM_SM_QRESUME: | ||
395 | bfa_sm_set_state(ioim, bfa_ioim_sm_active); | ||
396 | bfa_ioim_send_ioreq(ioim); | ||
397 | break; | ||
398 | |||
399 | case BFA_IOIM_SM_ABORT: | ||
400 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
401 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
402 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
403 | ioim); | ||
404 | break; | ||
405 | |||
406 | case BFA_IOIM_SM_CLEANUP: | ||
407 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
408 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
409 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
410 | ioim); | ||
411 | bfa_ioim_notify_cleanup(ioim); | ||
412 | break; | ||
413 | |||
414 | case BFA_IOIM_SM_HWFAIL: | ||
415 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
416 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
417 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
418 | ioim); | ||
419 | break; | ||
420 | |||
421 | default: | ||
422 | bfa_assert(0); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * Active IO is being aborted, waiting for room in request CQ. | ||
428 | */ | ||
429 | static void | ||
430 | bfa_ioim_sm_abort_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
431 | { | ||
432 | bfa_trc(ioim->bfa, ioim->iotag); | ||
433 | bfa_trc(ioim->bfa, event); | ||
434 | |||
435 | switch (event) { | ||
436 | case BFA_IOIM_SM_QRESUME: | ||
437 | bfa_sm_set_state(ioim, bfa_ioim_sm_abort); | ||
438 | bfa_ioim_send_abort(ioim); | ||
439 | break; | ||
440 | |||
441 | case BFA_IOIM_SM_CLEANUP: | ||
442 | bfa_assert(ioim->iosp->abort_explicit == BFA_TRUE); | ||
443 | ioim->iosp->abort_explicit = BFA_FALSE; | ||
444 | bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup_qfull); | ||
445 | break; | ||
446 | |||
447 | case BFA_IOIM_SM_COMP_GOOD: | ||
448 | case BFA_IOIM_SM_COMP: | ||
449 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
450 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
451 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
452 | ioim); | ||
453 | break; | ||
454 | |||
455 | case BFA_IOIM_SM_DONE: | ||
456 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); | ||
457 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
458 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_abort, | ||
459 | ioim); | ||
460 | break; | ||
461 | |||
462 | case BFA_IOIM_SM_HWFAIL: | ||
463 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
464 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
465 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
466 | ioim); | ||
467 | break; | ||
468 | |||
469 | default: | ||
470 | bfa_assert(0); | ||
471 | } | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * Active IO is being cleaned up, waiting for room in request CQ. | ||
476 | */ | ||
477 | static void | ||
478 | bfa_ioim_sm_cleanup_qfull(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
479 | { | ||
480 | bfa_trc(ioim->bfa, ioim->iotag); | ||
481 | bfa_trc(ioim->bfa, event); | ||
482 | |||
483 | switch (event) { | ||
484 | case BFA_IOIM_SM_QRESUME: | ||
485 | bfa_sm_set_state(ioim, bfa_ioim_sm_cleanup); | ||
486 | bfa_ioim_send_abort(ioim); | ||
487 | break; | ||
488 | |||
489 | case BFA_IOIM_SM_ABORT: | ||
490 | /** | ||
491 | * IO is alraedy being cleaned up implicitly | ||
492 | */ | ||
493 | ioim->io_cbfn = __bfa_cb_ioim_abort; | ||
494 | break; | ||
495 | |||
496 | case BFA_IOIM_SM_COMP_GOOD: | ||
497 | case BFA_IOIM_SM_COMP: | ||
498 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
499 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
500 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim); | ||
501 | bfa_ioim_notify_cleanup(ioim); | ||
502 | break; | ||
503 | |||
504 | case BFA_IOIM_SM_DONE: | ||
505 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb_free); | ||
506 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
507 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim); | ||
508 | bfa_ioim_notify_cleanup(ioim); | ||
509 | break; | ||
510 | |||
511 | case BFA_IOIM_SM_HWFAIL: | ||
512 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
513 | bfa_reqq_wcancel(&ioim->iosp->reqq_wait); | ||
514 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, __bfa_cb_ioim_failed, | ||
515 | ioim); | ||
516 | break; | ||
517 | |||
518 | default: | ||
519 | bfa_assert(0); | ||
520 | } | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * IO bfa callback is pending. | ||
525 | */ | ||
526 | static void | ||
527 | bfa_ioim_sm_hcb(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
528 | { | ||
529 | bfa_trc_fp(ioim->bfa, ioim->iotag); | ||
530 | bfa_trc_fp(ioim->bfa, event); | ||
531 | |||
532 | switch (event) { | ||
533 | case BFA_IOIM_SM_HCB: | ||
534 | bfa_sm_set_state(ioim, bfa_ioim_sm_uninit); | ||
535 | bfa_ioim_free(ioim); | ||
536 | bfa_cb_ioim_resfree(ioim->bfa->bfad); | ||
537 | break; | ||
538 | |||
539 | case BFA_IOIM_SM_CLEANUP: | ||
540 | bfa_ioim_notify_cleanup(ioim); | ||
541 | break; | ||
542 | |||
543 | case BFA_IOIM_SM_HWFAIL: | ||
544 | break; | ||
545 | |||
546 | default: | ||
547 | bfa_assert(0); | ||
548 | } | ||
549 | } | ||
550 | |||
551 | /** | ||
552 | * IO bfa callback is pending. IO resource cannot be freed. | ||
553 | */ | ||
554 | static void | ||
555 | bfa_ioim_sm_hcb_free(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
556 | { | ||
557 | bfa_trc(ioim->bfa, ioim->iotag); | ||
558 | bfa_trc(ioim->bfa, event); | ||
559 | |||
560 | switch (event) { | ||
561 | case BFA_IOIM_SM_HCB: | ||
562 | bfa_sm_set_state(ioim, bfa_ioim_sm_resfree); | ||
563 | list_del(&ioim->qe); | ||
564 | list_add_tail(&ioim->qe, &ioim->fcpim->ioim_resfree_q); | ||
565 | break; | ||
566 | |||
567 | case BFA_IOIM_SM_FREE: | ||
568 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
569 | break; | ||
570 | |||
571 | case BFA_IOIM_SM_CLEANUP: | ||
572 | bfa_ioim_notify_cleanup(ioim); | ||
573 | break; | ||
574 | |||
575 | case BFA_IOIM_SM_HWFAIL: | ||
576 | bfa_sm_set_state(ioim, bfa_ioim_sm_hcb); | ||
577 | break; | ||
578 | |||
579 | default: | ||
580 | bfa_assert(0); | ||
581 | } | ||
582 | } | ||
583 | |||
584 | /** | ||
585 | * IO is completed, waiting resource free from firmware. | ||
586 | */ | ||
587 | static void | ||
588 | bfa_ioim_sm_resfree(struct bfa_ioim_s *ioim, enum bfa_ioim_event event) | ||
589 | { | ||
590 | bfa_trc(ioim->bfa, ioim->iotag); | ||
591 | bfa_trc(ioim->bfa, event); | ||
592 | |||
593 | switch (event) { | ||
594 | case BFA_IOIM_SM_FREE: | ||
595 | bfa_sm_set_state(ioim, bfa_ioim_sm_uninit); | ||
596 | bfa_ioim_free(ioim); | ||
597 | bfa_cb_ioim_resfree(ioim->bfa->bfad); | ||
598 | break; | ||
599 | |||
600 | case BFA_IOIM_SM_CLEANUP: | ||
601 | bfa_ioim_notify_cleanup(ioim); | ||
602 | break; | ||
603 | |||
604 | case BFA_IOIM_SM_HWFAIL: | ||
605 | break; | ||
606 | |||
607 | default: | ||
608 | bfa_assert(0); | ||
609 | } | ||
610 | } | ||
611 | |||
612 | |||
613 | |||
614 | /** | ||
615 | * bfa_ioim_private | ||
616 | */ | ||
617 | |||
618 | static void | ||
619 | __bfa_cb_ioim_good_comp(void *cbarg, bfa_boolean_t complete) | ||
620 | { | ||
621 | struct bfa_ioim_s *ioim = cbarg; | ||
622 | |||
623 | if (!complete) { | ||
624 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
625 | return; | ||
626 | } | ||
627 | |||
628 | bfa_cb_ioim_good_comp(ioim->bfa->bfad, ioim->dio); | ||
629 | } | ||
630 | |||
631 | static void | ||
632 | __bfa_cb_ioim_comp(void *cbarg, bfa_boolean_t complete) | ||
633 | { | ||
634 | struct bfa_ioim_s *ioim = cbarg; | ||
635 | struct bfi_ioim_rsp_s *m; | ||
636 | u8 *snsinfo = NULL; | ||
637 | u8 sns_len = 0; | ||
638 | s32 residue = 0; | ||
639 | |||
640 | if (!complete) { | ||
641 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
642 | return; | ||
643 | } | ||
644 | |||
645 | m = (struct bfi_ioim_rsp_s *) &ioim->iosp->comp_rspmsg; | ||
646 | if (m->io_status == BFI_IOIM_STS_OK) { | ||
647 | /** | ||
648 | * setup sense information, if present | ||
649 | */ | ||
650 | if (m->scsi_status == SCSI_STATUS_CHECK_CONDITION | ||
651 | && m->sns_len) { | ||
652 | sns_len = m->sns_len; | ||
653 | snsinfo = ioim->iosp->snsinfo; | ||
654 | } | ||
655 | |||
656 | /** | ||
657 | * setup residue value correctly for normal completions | ||
658 | */ | ||
659 | if (m->resid_flags == FCP_RESID_UNDER) | ||
660 | residue = bfa_os_ntohl(m->residue); | ||
661 | if (m->resid_flags == FCP_RESID_OVER) { | ||
662 | residue = bfa_os_ntohl(m->residue); | ||
663 | residue = -residue; | ||
664 | } | ||
665 | } | ||
666 | |||
667 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, m->io_status, | ||
668 | m->scsi_status, sns_len, snsinfo, residue); | ||
669 | } | ||
670 | |||
671 | static void | ||
672 | __bfa_cb_ioim_failed(void *cbarg, bfa_boolean_t complete) | ||
673 | { | ||
674 | struct bfa_ioim_s *ioim = cbarg; | ||
675 | |||
676 | if (!complete) { | ||
677 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
678 | return; | ||
679 | } | ||
680 | |||
681 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_ABORTED, | ||
682 | 0, 0, NULL, 0); | ||
683 | } | ||
684 | |||
685 | static void | ||
686 | __bfa_cb_ioim_pathtov(void *cbarg, bfa_boolean_t complete) | ||
687 | { | ||
688 | struct bfa_ioim_s *ioim = cbarg; | ||
689 | |||
690 | if (!complete) { | ||
691 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
692 | return; | ||
693 | } | ||
694 | |||
695 | bfa_cb_ioim_done(ioim->bfa->bfad, ioim->dio, BFI_IOIM_STS_PATHTOV, | ||
696 | 0, 0, NULL, 0); | ||
697 | } | ||
698 | |||
699 | static void | ||
700 | __bfa_cb_ioim_abort(void *cbarg, bfa_boolean_t complete) | ||
701 | { | ||
702 | struct bfa_ioim_s *ioim = cbarg; | ||
703 | |||
704 | if (!complete) { | ||
705 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HCB); | ||
706 | return; | ||
707 | } | ||
708 | |||
709 | bfa_cb_ioim_abort(ioim->bfa->bfad, ioim->dio); | ||
710 | } | ||
711 | |||
712 | static void | ||
713 | bfa_ioim_sgpg_alloced(void *cbarg) | ||
714 | { | ||
715 | struct bfa_ioim_s *ioim = cbarg; | ||
716 | |||
717 | ioim->nsgpgs = BFA_SGPG_NPAGE(ioim->nsges); | ||
718 | list_splice_tail_init(&ioim->iosp->sgpg_wqe.sgpg_q, &ioim->sgpg_q); | ||
719 | bfa_ioim_sgpg_setup(ioim); | ||
720 | bfa_sm_send_event(ioim, BFA_IOIM_SM_SGALLOCED); | ||
721 | } | ||
722 | |||
723 | /** | ||
724 | * Send I/O request to firmware. | ||
725 | */ | ||
726 | static bfa_boolean_t | ||
727 | bfa_ioim_send_ioreq(struct bfa_ioim_s *ioim) | ||
728 | { | ||
729 | struct bfa_itnim_s *itnim = ioim->itnim; | ||
730 | struct bfi_ioim_req_s *m; | ||
731 | static struct fcp_cmnd_s cmnd_z0 = { 0 }; | ||
732 | struct bfi_sge_s *sge; | ||
733 | u32 pgdlen = 0; | ||
734 | |||
735 | /** | ||
736 | * check for room in queue to send request now | ||
737 | */ | ||
738 | m = bfa_reqq_next(ioim->bfa, itnim->reqq); | ||
739 | if (!m) { | ||
740 | bfa_reqq_wait(ioim->bfa, ioim->itnim->reqq, | ||
741 | &ioim->iosp->reqq_wait); | ||
742 | return BFA_FALSE; | ||
743 | } | ||
744 | |||
745 | /** | ||
746 | * build i/o request message next | ||
747 | */ | ||
748 | m->io_tag = bfa_os_htons(ioim->iotag); | ||
749 | m->rport_hdl = ioim->itnim->rport->fw_handle; | ||
750 | m->io_timeout = bfa_cb_ioim_get_timeout(ioim->dio); | ||
751 | |||
752 | /** | ||
753 | * build inline IO SG element here | ||
754 | */ | ||
755 | sge = &m->sges[0]; | ||
756 | if (ioim->nsges) { | ||
757 | sge->sga = bfa_cb_ioim_get_sgaddr(ioim->dio, 0); | ||
758 | pgdlen = bfa_cb_ioim_get_sglen(ioim->dio, 0); | ||
759 | sge->sg_len = pgdlen; | ||
760 | sge->flags = (ioim->nsges > BFI_SGE_INLINE) ? | ||
761 | BFI_SGE_DATA_CPL : BFI_SGE_DATA_LAST; | ||
762 | bfa_sge_to_be(sge); | ||
763 | sge++; | ||
764 | } | ||
765 | |||
766 | if (ioim->nsges > BFI_SGE_INLINE) { | ||
767 | sge->sga = ioim->sgpg->sgpg_pa; | ||
768 | } else { | ||
769 | sge->sga.a32.addr_lo = 0; | ||
770 | sge->sga.a32.addr_hi = 0; | ||
771 | } | ||
772 | sge->sg_len = pgdlen; | ||
773 | sge->flags = BFI_SGE_PGDLEN; | ||
774 | bfa_sge_to_be(sge); | ||
775 | |||
776 | /** | ||
777 | * set up I/O command parameters | ||
778 | */ | ||
779 | bfa_os_assign(m->cmnd, cmnd_z0); | ||
780 | m->cmnd.lun = bfa_cb_ioim_get_lun(ioim->dio); | ||
781 | m->cmnd.iodir = bfa_cb_ioim_get_iodir(ioim->dio); | ||
782 | bfa_os_assign(m->cmnd.cdb, | ||
783 | *(struct scsi_cdb_s *)bfa_cb_ioim_get_cdb(ioim->dio)); | ||
784 | m->cmnd.fcp_dl = bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio)); | ||
785 | |||
786 | /** | ||
787 | * set up I/O message header | ||
788 | */ | ||
789 | switch (m->cmnd.iodir) { | ||
790 | case FCP_IODIR_READ: | ||
791 | bfi_h2i_set(m->mh, BFI_MC_IOIM_READ, 0, bfa_lpuid(ioim->bfa)); | ||
792 | bfa_stats(itnim, input_reqs); | ||
793 | break; | ||
794 | case FCP_IODIR_WRITE: | ||
795 | bfi_h2i_set(m->mh, BFI_MC_IOIM_WRITE, 0, bfa_lpuid(ioim->bfa)); | ||
796 | bfa_stats(itnim, output_reqs); | ||
797 | break; | ||
798 | case FCP_IODIR_RW: | ||
799 | bfa_stats(itnim, input_reqs); | ||
800 | bfa_stats(itnim, output_reqs); | ||
801 | default: | ||
802 | bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa)); | ||
803 | } | ||
804 | if (itnim->seq_rec || | ||
805 | (bfa_cb_ioim_get_size(ioim->dio) & (sizeof(u32) - 1))) | ||
806 | bfi_h2i_set(m->mh, BFI_MC_IOIM_IO, 0, bfa_lpuid(ioim->bfa)); | ||
807 | |||
808 | #ifdef IOIM_ADVANCED | ||
809 | m->cmnd.crn = bfa_cb_ioim_get_crn(ioim->dio); | ||
810 | m->cmnd.priority = bfa_cb_ioim_get_priority(ioim->dio); | ||
811 | m->cmnd.taskattr = bfa_cb_ioim_get_taskattr(ioim->dio); | ||
812 | |||
813 | /** | ||
814 | * Handle large CDB (>16 bytes). | ||
815 | */ | ||
816 | m->cmnd.addl_cdb_len = (bfa_cb_ioim_get_cdblen(ioim->dio) - | ||
817 | FCP_CMND_CDB_LEN) / sizeof(u32); | ||
818 | if (m->cmnd.addl_cdb_len) { | ||
819 | bfa_os_memcpy(&m->cmnd.cdb + 1, (struct scsi_cdb_s *) | ||
820 | bfa_cb_ioim_get_cdb(ioim->dio) + 1, | ||
821 | m->cmnd.addl_cdb_len * sizeof(u32)); | ||
822 | fcp_cmnd_fcpdl(&m->cmnd) = | ||
823 | bfa_os_htonl(bfa_cb_ioim_get_size(ioim->dio)); | ||
824 | } | ||
825 | #endif | ||
826 | |||
827 | /** | ||
828 | * queue I/O message to firmware | ||
829 | */ | ||
830 | bfa_reqq_produce(ioim->bfa, itnim->reqq); | ||
831 | return BFA_TRUE; | ||
832 | } | ||
833 | |||
834 | /** | ||
835 | * Setup any additional SG pages needed.Inline SG element is setup | ||
836 | * at queuing time. | ||
837 | */ | ||
838 | static bfa_boolean_t | ||
839 | bfa_ioim_sge_setup(struct bfa_ioim_s *ioim) | ||
840 | { | ||
841 | u16 nsgpgs; | ||
842 | |||
843 | bfa_assert(ioim->nsges > BFI_SGE_INLINE); | ||
844 | |||
845 | /** | ||
846 | * allocate SG pages needed | ||
847 | */ | ||
848 | nsgpgs = BFA_SGPG_NPAGE(ioim->nsges); | ||
849 | if (!nsgpgs) | ||
850 | return BFA_TRUE; | ||
851 | |||
852 | if (bfa_sgpg_malloc(ioim->bfa, &ioim->sgpg_q, nsgpgs) | ||
853 | != BFA_STATUS_OK) { | ||
854 | bfa_sgpg_wait(ioim->bfa, &ioim->iosp->sgpg_wqe, nsgpgs); | ||
855 | return BFA_FALSE; | ||
856 | } | ||
857 | |||
858 | ioim->nsgpgs = nsgpgs; | ||
859 | bfa_ioim_sgpg_setup(ioim); | ||
860 | |||
861 | return BFA_TRUE; | ||
862 | } | ||
863 | |||
864 | static void | ||
865 | bfa_ioim_sgpg_setup(struct bfa_ioim_s *ioim) | ||
866 | { | ||
867 | int sgeid, nsges, i; | ||
868 | struct bfi_sge_s *sge; | ||
869 | struct bfa_sgpg_s *sgpg; | ||
870 | u32 pgcumsz; | ||
871 | |||
872 | sgeid = BFI_SGE_INLINE; | ||
873 | ioim->sgpg = sgpg = bfa_q_first(&ioim->sgpg_q); | ||
874 | |||
875 | do { | ||
876 | sge = sgpg->sgpg->sges; | ||
877 | nsges = ioim->nsges - sgeid; | ||
878 | if (nsges > BFI_SGPG_DATA_SGES) | ||
879 | nsges = BFI_SGPG_DATA_SGES; | ||
880 | |||
881 | pgcumsz = 0; | ||
882 | for (i = 0; i < nsges; i++, sge++, sgeid++) { | ||
883 | sge->sga = bfa_cb_ioim_get_sgaddr(ioim->dio, sgeid); | ||
884 | sge->sg_len = bfa_cb_ioim_get_sglen(ioim->dio, sgeid); | ||
885 | pgcumsz += sge->sg_len; | ||
886 | |||
887 | /** | ||
888 | * set flags | ||
889 | */ | ||
890 | if (i < (nsges - 1)) | ||
891 | sge->flags = BFI_SGE_DATA; | ||
892 | else if (sgeid < (ioim->nsges - 1)) | ||
893 | sge->flags = BFI_SGE_DATA_CPL; | ||
894 | else | ||
895 | sge->flags = BFI_SGE_DATA_LAST; | ||
896 | } | ||
897 | |||
898 | sgpg = (struct bfa_sgpg_s *) bfa_q_next(sgpg); | ||
899 | |||
900 | /** | ||
901 | * set the link element of each page | ||
902 | */ | ||
903 | if (sgeid == ioim->nsges) { | ||
904 | sge->flags = BFI_SGE_PGDLEN; | ||
905 | sge->sga.a32.addr_lo = 0; | ||
906 | sge->sga.a32.addr_hi = 0; | ||
907 | } else { | ||
908 | sge->flags = BFI_SGE_LINK; | ||
909 | sge->sga = sgpg->sgpg_pa; | ||
910 | } | ||
911 | sge->sg_len = pgcumsz; | ||
912 | } while (sgeid < ioim->nsges); | ||
913 | } | ||
914 | |||
915 | /** | ||
916 | * Send I/O abort request to firmware. | ||
917 | */ | ||
918 | static bfa_boolean_t | ||
919 | bfa_ioim_send_abort(struct bfa_ioim_s *ioim) | ||
920 | { | ||
921 | struct bfa_itnim_s *itnim = ioim->itnim; | ||
922 | struct bfi_ioim_abort_req_s *m; | ||
923 | enum bfi_ioim_h2i msgop; | ||
924 | |||
925 | /** | ||
926 | * check for room in queue to send request now | ||
927 | */ | ||
928 | m = bfa_reqq_next(ioim->bfa, itnim->reqq); | ||
929 | if (!m) | ||
930 | return BFA_FALSE; | ||
931 | |||
932 | /** | ||
933 | * build i/o request message next | ||
934 | */ | ||
935 | if (ioim->iosp->abort_explicit) | ||
936 | msgop = BFI_IOIM_H2I_IOABORT_REQ; | ||
937 | else | ||
938 | msgop = BFI_IOIM_H2I_IOCLEANUP_REQ; | ||
939 | |||
940 | bfi_h2i_set(m->mh, BFI_MC_IOIM, msgop, bfa_lpuid(ioim->bfa)); | ||
941 | m->io_tag = bfa_os_htons(ioim->iotag); | ||
942 | m->abort_tag = ++ioim->abort_tag; | ||
943 | |||
944 | /** | ||
945 | * queue I/O message to firmware | ||
946 | */ | ||
947 | bfa_reqq_produce(ioim->bfa, itnim->reqq); | ||
948 | return BFA_TRUE; | ||
949 | } | ||
950 | |||
951 | /** | ||
952 | * Call to resume any I/O requests waiting for room in request queue. | ||
953 | */ | ||
954 | static void | ||
955 | bfa_ioim_qresume(void *cbarg) | ||
956 | { | ||
957 | struct bfa_ioim_s *ioim = cbarg; | ||
958 | |||
959 | bfa_fcpim_stats(ioim->fcpim, qresumes); | ||
960 | bfa_sm_send_event(ioim, BFA_IOIM_SM_QRESUME); | ||
961 | } | ||
962 | |||
963 | |||
964 | static void | ||
965 | bfa_ioim_notify_cleanup(struct bfa_ioim_s *ioim) | ||
966 | { | ||
967 | /** | ||
968 | * Move IO from itnim queue to fcpim global queue since itnim will be | ||
969 | * freed. | ||
970 | */ | ||
971 | list_del(&ioim->qe); | ||
972 | list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); | ||
973 | |||
974 | if (!ioim->iosp->tskim) { | ||
975 | if (ioim->fcpim->delay_comp && ioim->itnim->iotov_active) { | ||
976 | bfa_cb_dequeue(&ioim->hcb_qe); | ||
977 | list_del(&ioim->qe); | ||
978 | list_add_tail(&ioim->qe, &ioim->itnim->delay_comp_q); | ||
979 | } | ||
980 | bfa_itnim_iodone(ioim->itnim); | ||
981 | } else | ||
982 | bfa_tskim_iodone(ioim->iosp->tskim); | ||
983 | } | ||
984 | |||
985 | /** | ||
986 | * or after the link comes back. | ||
987 | */ | ||
988 | void | ||
989 | bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, bfa_boolean_t iotov) | ||
990 | { | ||
991 | /** | ||
992 | * If path tov timer expired, failback with PATHTOV status - these | ||
993 | * IO requests are not normally retried by IO stack. | ||
994 | * | ||
995 | * Otherwise device cameback online and fail it with normal failed | ||
996 | * status so that IO stack retries these failed IO requests. | ||
997 | */ | ||
998 | if (iotov) | ||
999 | ioim->io_cbfn = __bfa_cb_ioim_pathtov; | ||
1000 | else | ||
1001 | ioim->io_cbfn = __bfa_cb_ioim_failed; | ||
1002 | |||
1003 | bfa_cb_queue(ioim->bfa, &ioim->hcb_qe, ioim->io_cbfn, ioim); | ||
1004 | |||
1005 | /** | ||
1006 | * Move IO to fcpim global queue since itnim will be | ||
1007 | * freed. | ||
1008 | */ | ||
1009 | list_del(&ioim->qe); | ||
1010 | list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); | ||
1011 | } | ||
1012 | |||
1013 | |||
1014 | |||
1015 | /** | ||
1016 | * bfa_ioim_friend | ||
1017 | */ | ||
1018 | |||
1019 | /** | ||
1020 | * Memory allocation and initialization. | ||
1021 | */ | ||
1022 | void | ||
1023 | bfa_ioim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) | ||
1024 | { | ||
1025 | struct bfa_ioim_s *ioim; | ||
1026 | struct bfa_ioim_sp_s *iosp; | ||
1027 | u16 i; | ||
1028 | u8 *snsinfo; | ||
1029 | u32 snsbufsz; | ||
1030 | |||
1031 | /** | ||
1032 | * claim memory first | ||
1033 | */ | ||
1034 | ioim = (struct bfa_ioim_s *) bfa_meminfo_kva(minfo); | ||
1035 | fcpim->ioim_arr = ioim; | ||
1036 | bfa_meminfo_kva(minfo) = (u8 *) (ioim + fcpim->num_ioim_reqs); | ||
1037 | |||
1038 | iosp = (struct bfa_ioim_sp_s *) bfa_meminfo_kva(minfo); | ||
1039 | fcpim->ioim_sp_arr = iosp; | ||
1040 | bfa_meminfo_kva(minfo) = (u8 *) (iosp + fcpim->num_ioim_reqs); | ||
1041 | |||
1042 | /** | ||
1043 | * Claim DMA memory for per IO sense data. | ||
1044 | */ | ||
1045 | snsbufsz = fcpim->num_ioim_reqs * BFI_IOIM_SNSLEN; | ||
1046 | fcpim->snsbase.pa = bfa_meminfo_dma_phys(minfo); | ||
1047 | bfa_meminfo_dma_phys(minfo) += snsbufsz; | ||
1048 | |||
1049 | fcpim->snsbase.kva = bfa_meminfo_dma_virt(minfo); | ||
1050 | bfa_meminfo_dma_virt(minfo) += snsbufsz; | ||
1051 | snsinfo = fcpim->snsbase.kva; | ||
1052 | bfa_iocfc_set_snsbase(fcpim->bfa, fcpim->snsbase.pa); | ||
1053 | |||
1054 | /** | ||
1055 | * Initialize ioim free queues | ||
1056 | */ | ||
1057 | INIT_LIST_HEAD(&fcpim->ioim_free_q); | ||
1058 | INIT_LIST_HEAD(&fcpim->ioim_resfree_q); | ||
1059 | INIT_LIST_HEAD(&fcpim->ioim_comp_q); | ||
1060 | |||
1061 | for (i = 0; i < fcpim->num_ioim_reqs; | ||
1062 | i++, ioim++, iosp++, snsinfo += BFI_IOIM_SNSLEN) { | ||
1063 | /* | ||
1064 | * initialize IOIM | ||
1065 | */ | ||
1066 | bfa_os_memset(ioim, 0, sizeof(struct bfa_ioim_s)); | ||
1067 | ioim->iotag = i; | ||
1068 | ioim->bfa = fcpim->bfa; | ||
1069 | ioim->fcpim = fcpim; | ||
1070 | ioim->iosp = iosp; | ||
1071 | iosp->snsinfo = snsinfo; | ||
1072 | INIT_LIST_HEAD(&ioim->sgpg_q); | ||
1073 | bfa_reqq_winit(&ioim->iosp->reqq_wait, | ||
1074 | bfa_ioim_qresume, ioim); | ||
1075 | bfa_sgpg_winit(&ioim->iosp->sgpg_wqe, | ||
1076 | bfa_ioim_sgpg_alloced, ioim); | ||
1077 | bfa_sm_set_state(ioim, bfa_ioim_sm_uninit); | ||
1078 | |||
1079 | list_add_tail(&ioim->qe, &fcpim->ioim_free_q); | ||
1080 | } | ||
1081 | } | ||
1082 | |||
1083 | /** | ||
1084 | * Driver detach time call. | ||
1085 | */ | ||
1086 | void | ||
1087 | bfa_ioim_detach(struct bfa_fcpim_mod_s *fcpim) | ||
1088 | { | ||
1089 | } | ||
1090 | |||
1091 | void | ||
1092 | bfa_ioim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
1093 | { | ||
1094 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
1095 | struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m; | ||
1096 | struct bfa_ioim_s *ioim; | ||
1097 | u16 iotag; | ||
1098 | enum bfa_ioim_event evt = BFA_IOIM_SM_COMP; | ||
1099 | |||
1100 | iotag = bfa_os_ntohs(rsp->io_tag); | ||
1101 | |||
1102 | ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); | ||
1103 | bfa_assert(ioim->iotag == iotag); | ||
1104 | |||
1105 | bfa_trc(ioim->bfa, ioim->iotag); | ||
1106 | bfa_trc(ioim->bfa, rsp->io_status); | ||
1107 | bfa_trc(ioim->bfa, rsp->reuse_io_tag); | ||
1108 | |||
1109 | if (bfa_sm_cmp_state(ioim, bfa_ioim_sm_active)) | ||
1110 | bfa_os_assign(ioim->iosp->comp_rspmsg, *m); | ||
1111 | |||
1112 | switch (rsp->io_status) { | ||
1113 | case BFI_IOIM_STS_OK: | ||
1114 | bfa_fcpim_stats(fcpim, iocomp_ok); | ||
1115 | if (rsp->reuse_io_tag == 0) | ||
1116 | evt = BFA_IOIM_SM_DONE; | ||
1117 | else | ||
1118 | evt = BFA_IOIM_SM_COMP; | ||
1119 | break; | ||
1120 | |||
1121 | case BFI_IOIM_STS_TIMEDOUT: | ||
1122 | case BFI_IOIM_STS_ABORTED: | ||
1123 | rsp->io_status = BFI_IOIM_STS_ABORTED; | ||
1124 | bfa_fcpim_stats(fcpim, iocomp_aborted); | ||
1125 | if (rsp->reuse_io_tag == 0) | ||
1126 | evt = BFA_IOIM_SM_DONE; | ||
1127 | else | ||
1128 | evt = BFA_IOIM_SM_COMP; | ||
1129 | break; | ||
1130 | |||
1131 | case BFI_IOIM_STS_PROTO_ERR: | ||
1132 | bfa_fcpim_stats(fcpim, iocom_proto_err); | ||
1133 | bfa_assert(rsp->reuse_io_tag); | ||
1134 | evt = BFA_IOIM_SM_COMP; | ||
1135 | break; | ||
1136 | |||
1137 | case BFI_IOIM_STS_SQER_NEEDED: | ||
1138 | bfa_fcpim_stats(fcpim, iocom_sqer_needed); | ||
1139 | bfa_assert(rsp->reuse_io_tag == 0); | ||
1140 | evt = BFA_IOIM_SM_SQRETRY; | ||
1141 | break; | ||
1142 | |||
1143 | case BFI_IOIM_STS_RES_FREE: | ||
1144 | bfa_fcpim_stats(fcpim, iocom_res_free); | ||
1145 | evt = BFA_IOIM_SM_FREE; | ||
1146 | break; | ||
1147 | |||
1148 | case BFI_IOIM_STS_HOST_ABORTED: | ||
1149 | bfa_fcpim_stats(fcpim, iocom_hostabrts); | ||
1150 | if (rsp->abort_tag != ioim->abort_tag) { | ||
1151 | bfa_trc(ioim->bfa, rsp->abort_tag); | ||
1152 | bfa_trc(ioim->bfa, ioim->abort_tag); | ||
1153 | return; | ||
1154 | } | ||
1155 | |||
1156 | if (rsp->reuse_io_tag) | ||
1157 | evt = BFA_IOIM_SM_ABORT_COMP; | ||
1158 | else | ||
1159 | evt = BFA_IOIM_SM_ABORT_DONE; | ||
1160 | break; | ||
1161 | |||
1162 | case BFI_IOIM_STS_UTAG: | ||
1163 | bfa_fcpim_stats(fcpim, iocom_utags); | ||
1164 | evt = BFA_IOIM_SM_COMP_UTAG; | ||
1165 | break; | ||
1166 | |||
1167 | default: | ||
1168 | bfa_assert(0); | ||
1169 | } | ||
1170 | |||
1171 | bfa_sm_send_event(ioim, evt); | ||
1172 | } | ||
1173 | |||
1174 | void | ||
1175 | bfa_ioim_good_comp_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
1176 | { | ||
1177 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
1178 | struct bfi_ioim_rsp_s *rsp = (struct bfi_ioim_rsp_s *) m; | ||
1179 | struct bfa_ioim_s *ioim; | ||
1180 | u16 iotag; | ||
1181 | |||
1182 | iotag = bfa_os_ntohs(rsp->io_tag); | ||
1183 | |||
1184 | ioim = BFA_IOIM_FROM_TAG(fcpim, iotag); | ||
1185 | bfa_assert(ioim->iotag == iotag); | ||
1186 | |||
1187 | bfa_trc_fp(ioim->bfa, ioim->iotag); | ||
1188 | bfa_sm_send_event(ioim, BFA_IOIM_SM_COMP_GOOD); | ||
1189 | } | ||
1190 | |||
1191 | /** | ||
1192 | * Called by itnim to clean up IO while going offline. | ||
1193 | */ | ||
1194 | void | ||
1195 | bfa_ioim_cleanup(struct bfa_ioim_s *ioim) | ||
1196 | { | ||
1197 | bfa_trc(ioim->bfa, ioim->iotag); | ||
1198 | bfa_fcpim_stats(ioim->fcpim, io_cleanups); | ||
1199 | |||
1200 | ioim->iosp->tskim = NULL; | ||
1201 | bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP); | ||
1202 | } | ||
1203 | |||
1204 | void | ||
1205 | bfa_ioim_cleanup_tm(struct bfa_ioim_s *ioim, struct bfa_tskim_s *tskim) | ||
1206 | { | ||
1207 | bfa_trc(ioim->bfa, ioim->iotag); | ||
1208 | bfa_fcpim_stats(ioim->fcpim, io_tmaborts); | ||
1209 | |||
1210 | ioim->iosp->tskim = tskim; | ||
1211 | bfa_sm_send_event(ioim, BFA_IOIM_SM_CLEANUP); | ||
1212 | } | ||
1213 | |||
1214 | /** | ||
1215 | * IOC failure handling. | ||
1216 | */ | ||
1217 | void | ||
1218 | bfa_ioim_iocdisable(struct bfa_ioim_s *ioim) | ||
1219 | { | ||
1220 | bfa_sm_send_event(ioim, BFA_IOIM_SM_HWFAIL); | ||
1221 | } | ||
1222 | |||
1223 | /** | ||
1224 | * IO offline TOV popped. Fail the pending IO. | ||
1225 | */ | ||
1226 | void | ||
1227 | bfa_ioim_tov(struct bfa_ioim_s *ioim) | ||
1228 | { | ||
1229 | bfa_sm_send_event(ioim, BFA_IOIM_SM_IOTOV); | ||
1230 | } | ||
1231 | |||
1232 | |||
1233 | |||
1234 | /** | ||
1235 | * bfa_ioim_api | ||
1236 | */ | ||
1237 | |||
1238 | /** | ||
1239 | * Allocate IOIM resource for initiator mode I/O request. | ||
1240 | */ | ||
1241 | struct bfa_ioim_s * | ||
1242 | bfa_ioim_alloc(struct bfa_s *bfa, struct bfad_ioim_s *dio, | ||
1243 | struct bfa_itnim_s *itnim, u16 nsges) | ||
1244 | { | ||
1245 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
1246 | struct bfa_ioim_s *ioim; | ||
1247 | |||
1248 | /** | ||
1249 | * alocate IOIM resource | ||
1250 | */ | ||
1251 | bfa_q_deq(&fcpim->ioim_free_q, &ioim); | ||
1252 | if (!ioim) { | ||
1253 | bfa_fcpim_stats(fcpim, no_iotags); | ||
1254 | return NULL; | ||
1255 | } | ||
1256 | |||
1257 | ioim->dio = dio; | ||
1258 | ioim->itnim = itnim; | ||
1259 | ioim->nsges = nsges; | ||
1260 | ioim->nsgpgs = 0; | ||
1261 | |||
1262 | bfa_stats(fcpim, total_ios); | ||
1263 | bfa_stats(itnim, ios); | ||
1264 | fcpim->ios_active++; | ||
1265 | |||
1266 | list_add_tail(&ioim->qe, &itnim->io_q); | ||
1267 | bfa_trc_fp(ioim->bfa, ioim->iotag); | ||
1268 | |||
1269 | return ioim; | ||
1270 | } | ||
1271 | |||
1272 | void | ||
1273 | bfa_ioim_free(struct bfa_ioim_s *ioim) | ||
1274 | { | ||
1275 | struct bfa_fcpim_mod_s *fcpim = ioim->fcpim; | ||
1276 | |||
1277 | bfa_trc_fp(ioim->bfa, ioim->iotag); | ||
1278 | bfa_assert_fp(bfa_sm_cmp_state(ioim, bfa_ioim_sm_uninit)); | ||
1279 | |||
1280 | bfa_assert_fp(list_empty(&ioim->sgpg_q) | ||
1281 | || (ioim->nsges > BFI_SGE_INLINE)); | ||
1282 | |||
1283 | if (ioim->nsgpgs > 0) | ||
1284 | bfa_sgpg_mfree(ioim->bfa, &ioim->sgpg_q, ioim->nsgpgs); | ||
1285 | |||
1286 | bfa_stats(ioim->itnim, io_comps); | ||
1287 | fcpim->ios_active--; | ||
1288 | |||
1289 | list_del(&ioim->qe); | ||
1290 | list_add_tail(&ioim->qe, &fcpim->ioim_free_q); | ||
1291 | } | ||
1292 | |||
1293 | void | ||
1294 | bfa_ioim_start(struct bfa_ioim_s *ioim) | ||
1295 | { | ||
1296 | bfa_trc_fp(ioim->bfa, ioim->iotag); | ||
1297 | bfa_sm_send_event(ioim, BFA_IOIM_SM_START); | ||
1298 | } | ||
1299 | |||
1300 | /** | ||
1301 | * Driver I/O abort request. | ||
1302 | */ | ||
1303 | void | ||
1304 | bfa_ioim_abort(struct bfa_ioim_s *ioim) | ||
1305 | { | ||
1306 | bfa_trc(ioim->bfa, ioim->iotag); | ||
1307 | bfa_fcpim_stats(ioim->fcpim, io_aborts); | ||
1308 | bfa_sm_send_event(ioim, BFA_IOIM_SM_ABORT); | ||
1309 | } | ||
1310 | |||
1311 | |||
diff --git a/drivers/scsi/bfa/bfa_itnim.c b/drivers/scsi/bfa/bfa_itnim.c new file mode 100644 index 000000000000..4d5c61a4f85c --- /dev/null +++ b/drivers/scsi/bfa/bfa_itnim.c | |||
@@ -0,0 +1,1088 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfa_fcpim.h> | ||
20 | #include "bfa_fcpim_priv.h" | ||
21 | |||
22 | BFA_TRC_FILE(HAL, ITNIM); | ||
23 | |||
24 | #define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \ | ||
25 | ((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))) | ||
26 | |||
27 | #define bfa_fcpim_additn(__itnim) \ | ||
28 | list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q) | ||
29 | #define bfa_fcpim_delitn(__itnim) do { \ | ||
30 | bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \ | ||
31 | list_del(&(__itnim)->qe); \ | ||
32 | bfa_assert(list_empty(&(__itnim)->io_q)); \ | ||
33 | bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \ | ||
34 | bfa_assert(list_empty(&(__itnim)->pending_q)); \ | ||
35 | } while (0) | ||
36 | |||
37 | #define bfa_itnim_online_cb(__itnim) do { \ | ||
38 | if ((__itnim)->bfa->fcs) \ | ||
39 | bfa_cb_itnim_online((__itnim)->ditn); \ | ||
40 | else { \ | ||
41 | bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \ | ||
42 | __bfa_cb_itnim_online, (__itnim)); \ | ||
43 | } \ | ||
44 | } while (0) | ||
45 | |||
46 | #define bfa_itnim_offline_cb(__itnim) do { \ | ||
47 | if ((__itnim)->bfa->fcs) \ | ||
48 | bfa_cb_itnim_offline((__itnim)->ditn); \ | ||
49 | else { \ | ||
50 | bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \ | ||
51 | __bfa_cb_itnim_offline, (__itnim)); \ | ||
52 | } \ | ||
53 | } while (0) | ||
54 | |||
55 | #define bfa_itnim_sler_cb(__itnim) do { \ | ||
56 | if ((__itnim)->bfa->fcs) \ | ||
57 | bfa_cb_itnim_sler((__itnim)->ditn); \ | ||
58 | else { \ | ||
59 | bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \ | ||
60 | __bfa_cb_itnim_sler, (__itnim)); \ | ||
61 | } \ | ||
62 | } while (0) | ||
63 | |||
64 | /* | ||
65 | * forward declarations | ||
66 | */ | ||
67 | static void bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim); | ||
68 | static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim); | ||
69 | static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim); | ||
70 | static void bfa_itnim_cleanp_comp(void *itnim_cbarg); | ||
71 | static void bfa_itnim_cleanup(struct bfa_itnim_s *itnim); | ||
72 | static void __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete); | ||
73 | static void __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete); | ||
74 | static void __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete); | ||
75 | static void bfa_itnim_iotov_online(struct bfa_itnim_s *itnim); | ||
76 | static void bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim); | ||
77 | static void bfa_itnim_iotov(void *itnim_arg); | ||
78 | static void bfa_itnim_iotov_start(struct bfa_itnim_s *itnim); | ||
79 | static void bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim); | ||
80 | static void bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim); | ||
81 | |||
82 | /** | ||
83 | * bfa_itnim_sm BFA itnim state machine | ||
84 | */ | ||
85 | |||
86 | |||
87 | enum bfa_itnim_event { | ||
88 | BFA_ITNIM_SM_CREATE = 1, /* itnim is created */ | ||
89 | BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */ | ||
90 | BFA_ITNIM_SM_OFFLINE = 3, /* itnim is offline */ | ||
91 | BFA_ITNIM_SM_FWRSP = 4, /* firmware response */ | ||
92 | BFA_ITNIM_SM_DELETE = 5, /* deleting an existing itnim */ | ||
93 | BFA_ITNIM_SM_CLEANUP = 6, /* IO cleanup completion */ | ||
94 | BFA_ITNIM_SM_SLER = 7, /* second level error recovery */ | ||
95 | BFA_ITNIM_SM_HWFAIL = 8, /* IOC h/w failure event */ | ||
96 | BFA_ITNIM_SM_QRESUME = 9, /* queue space available */ | ||
97 | }; | ||
98 | |||
99 | static void bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, | ||
100 | enum bfa_itnim_event event); | ||
101 | static void bfa_itnim_sm_created(struct bfa_itnim_s *itnim, | ||
102 | enum bfa_itnim_event event); | ||
103 | static void bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, | ||
104 | enum bfa_itnim_event event); | ||
105 | static void bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim, | ||
106 | enum bfa_itnim_event event); | ||
107 | static void bfa_itnim_sm_online(struct bfa_itnim_s *itnim, | ||
108 | enum bfa_itnim_event event); | ||
109 | static void bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, | ||
110 | enum bfa_itnim_event event); | ||
111 | static void bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim, | ||
112 | enum bfa_itnim_event event); | ||
113 | static void bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim, | ||
114 | enum bfa_itnim_event event); | ||
115 | static void bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, | ||
116 | enum bfa_itnim_event event); | ||
117 | static void bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, | ||
118 | enum bfa_itnim_event event); | ||
119 | static void bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim, | ||
120 | enum bfa_itnim_event event); | ||
121 | static void bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, | ||
122 | enum bfa_itnim_event event); | ||
123 | static void bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim, | ||
124 | enum bfa_itnim_event event); | ||
125 | static void bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim, | ||
126 | enum bfa_itnim_event event); | ||
127 | static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim, | ||
128 | enum bfa_itnim_event event); | ||
129 | |||
130 | /** | ||
131 | * Beginning/unallocated state - no events expected. | ||
132 | */ | ||
133 | static void | ||
134 | bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
135 | { | ||
136 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
137 | bfa_trc(itnim->bfa, event); | ||
138 | |||
139 | switch (event) { | ||
140 | case BFA_ITNIM_SM_CREATE: | ||
141 | bfa_sm_set_state(itnim, bfa_itnim_sm_created); | ||
142 | itnim->is_online = BFA_FALSE; | ||
143 | bfa_fcpim_additn(itnim); | ||
144 | break; | ||
145 | |||
146 | default: | ||
147 | bfa_assert(0); | ||
148 | } | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Beginning state, only online event expected. | ||
153 | */ | ||
154 | static void | ||
155 | bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
156 | { | ||
157 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
158 | bfa_trc(itnim->bfa, event); | ||
159 | |||
160 | switch (event) { | ||
161 | case BFA_ITNIM_SM_ONLINE: | ||
162 | if (bfa_itnim_send_fwcreate(itnim)) | ||
163 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); | ||
164 | else | ||
165 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull); | ||
166 | break; | ||
167 | |||
168 | case BFA_ITNIM_SM_DELETE: | ||
169 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
170 | bfa_fcpim_delitn(itnim); | ||
171 | break; | ||
172 | |||
173 | case BFA_ITNIM_SM_HWFAIL: | ||
174 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
175 | break; | ||
176 | |||
177 | default: | ||
178 | bfa_assert(0); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * Waiting for itnim create response from firmware. | ||
184 | */ | ||
185 | static void | ||
186 | bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
187 | { | ||
188 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
189 | bfa_trc(itnim->bfa, event); | ||
190 | |||
191 | switch (event) { | ||
192 | case BFA_ITNIM_SM_FWRSP: | ||
193 | bfa_sm_set_state(itnim, bfa_itnim_sm_online); | ||
194 | itnim->is_online = BFA_TRUE; | ||
195 | bfa_itnim_iotov_online(itnim); | ||
196 | bfa_itnim_online_cb(itnim); | ||
197 | break; | ||
198 | |||
199 | case BFA_ITNIM_SM_DELETE: | ||
200 | bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending); | ||
201 | break; | ||
202 | |||
203 | case BFA_ITNIM_SM_OFFLINE: | ||
204 | if (bfa_itnim_send_fwdelete(itnim)) | ||
205 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete); | ||
206 | else | ||
207 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull); | ||
208 | break; | ||
209 | |||
210 | case BFA_ITNIM_SM_HWFAIL: | ||
211 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
212 | break; | ||
213 | |||
214 | default: | ||
215 | bfa_assert(0); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static void | ||
220 | bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim, | ||
221 | enum bfa_itnim_event event) | ||
222 | { | ||
223 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
224 | bfa_trc(itnim->bfa, event); | ||
225 | |||
226 | switch (event) { | ||
227 | case BFA_ITNIM_SM_QRESUME: | ||
228 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); | ||
229 | bfa_itnim_send_fwcreate(itnim); | ||
230 | break; | ||
231 | |||
232 | case BFA_ITNIM_SM_DELETE: | ||
233 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
234 | bfa_reqq_wcancel(&itnim->reqq_wait); | ||
235 | bfa_fcpim_delitn(itnim); | ||
236 | break; | ||
237 | |||
238 | case BFA_ITNIM_SM_OFFLINE: | ||
239 | bfa_sm_set_state(itnim, bfa_itnim_sm_offline); | ||
240 | bfa_reqq_wcancel(&itnim->reqq_wait); | ||
241 | bfa_itnim_offline_cb(itnim); | ||
242 | break; | ||
243 | |||
244 | case BFA_ITNIM_SM_HWFAIL: | ||
245 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
246 | bfa_reqq_wcancel(&itnim->reqq_wait); | ||
247 | break; | ||
248 | |||
249 | default: | ||
250 | bfa_assert(0); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * Waiting for itnim create response from firmware, a delete is pending. | ||
256 | */ | ||
257 | static void | ||
258 | bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim, | ||
259 | enum bfa_itnim_event event) | ||
260 | { | ||
261 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
262 | bfa_trc(itnim->bfa, event); | ||
263 | |||
264 | switch (event) { | ||
265 | case BFA_ITNIM_SM_FWRSP: | ||
266 | if (bfa_itnim_send_fwdelete(itnim)) | ||
267 | bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); | ||
268 | else | ||
269 | bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull); | ||
270 | break; | ||
271 | |||
272 | case BFA_ITNIM_SM_HWFAIL: | ||
273 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
274 | bfa_fcpim_delitn(itnim); | ||
275 | break; | ||
276 | |||
277 | default: | ||
278 | bfa_assert(0); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * Online state - normal parking state. | ||
284 | */ | ||
285 | static void | ||
286 | bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
287 | { | ||
288 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
289 | bfa_trc(itnim->bfa, event); | ||
290 | |||
291 | switch (event) { | ||
292 | case BFA_ITNIM_SM_OFFLINE: | ||
293 | bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline); | ||
294 | itnim->is_online = BFA_FALSE; | ||
295 | bfa_itnim_iotov_start(itnim); | ||
296 | bfa_itnim_cleanup(itnim); | ||
297 | break; | ||
298 | |||
299 | case BFA_ITNIM_SM_DELETE: | ||
300 | bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete); | ||
301 | itnim->is_online = BFA_FALSE; | ||
302 | bfa_itnim_cleanup(itnim); | ||
303 | break; | ||
304 | |||
305 | case BFA_ITNIM_SM_SLER: | ||
306 | bfa_sm_set_state(itnim, bfa_itnim_sm_sler); | ||
307 | itnim->is_online = BFA_FALSE; | ||
308 | bfa_itnim_iotov_start(itnim); | ||
309 | bfa_itnim_sler_cb(itnim); | ||
310 | break; | ||
311 | |||
312 | case BFA_ITNIM_SM_HWFAIL: | ||
313 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
314 | itnim->is_online = BFA_FALSE; | ||
315 | bfa_itnim_iotov_start(itnim); | ||
316 | bfa_itnim_iocdisable_cleanup(itnim); | ||
317 | break; | ||
318 | |||
319 | default: | ||
320 | bfa_assert(0); | ||
321 | } | ||
322 | } | ||
323 | |||
324 | /** | ||
325 | * Second level error recovery need. | ||
326 | */ | ||
327 | static void | ||
328 | bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
329 | { | ||
330 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
331 | bfa_trc(itnim->bfa, event); | ||
332 | |||
333 | switch (event) { | ||
334 | case BFA_ITNIM_SM_OFFLINE: | ||
335 | bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline); | ||
336 | bfa_itnim_cleanup(itnim); | ||
337 | break; | ||
338 | |||
339 | case BFA_ITNIM_SM_DELETE: | ||
340 | bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete); | ||
341 | bfa_itnim_cleanup(itnim); | ||
342 | bfa_itnim_iotov_delete(itnim); | ||
343 | break; | ||
344 | |||
345 | case BFA_ITNIM_SM_HWFAIL: | ||
346 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
347 | bfa_itnim_iocdisable_cleanup(itnim); | ||
348 | break; | ||
349 | |||
350 | default: | ||
351 | bfa_assert(0); | ||
352 | } | ||
353 | } | ||
354 | |||
355 | /** | ||
356 | * Going offline. Waiting for active IO cleanup. | ||
357 | */ | ||
358 | static void | ||
359 | bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim, | ||
360 | enum bfa_itnim_event event) | ||
361 | { | ||
362 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
363 | bfa_trc(itnim->bfa, event); | ||
364 | |||
365 | switch (event) { | ||
366 | case BFA_ITNIM_SM_CLEANUP: | ||
367 | if (bfa_itnim_send_fwdelete(itnim)) | ||
368 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete); | ||
369 | else | ||
370 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull); | ||
371 | break; | ||
372 | |||
373 | case BFA_ITNIM_SM_DELETE: | ||
374 | bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete); | ||
375 | bfa_itnim_iotov_delete(itnim); | ||
376 | break; | ||
377 | |||
378 | case BFA_ITNIM_SM_HWFAIL: | ||
379 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
380 | bfa_itnim_iocdisable_cleanup(itnim); | ||
381 | bfa_itnim_offline_cb(itnim); | ||
382 | break; | ||
383 | |||
384 | case BFA_ITNIM_SM_SLER: | ||
385 | break; | ||
386 | |||
387 | default: | ||
388 | bfa_assert(0); | ||
389 | } | ||
390 | } | ||
391 | |||
392 | /** | ||
393 | * Deleting itnim. Waiting for active IO cleanup. | ||
394 | */ | ||
395 | static void | ||
396 | bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim, | ||
397 | enum bfa_itnim_event event) | ||
398 | { | ||
399 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
400 | bfa_trc(itnim->bfa, event); | ||
401 | |||
402 | switch (event) { | ||
403 | case BFA_ITNIM_SM_CLEANUP: | ||
404 | if (bfa_itnim_send_fwdelete(itnim)) | ||
405 | bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); | ||
406 | else | ||
407 | bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull); | ||
408 | break; | ||
409 | |||
410 | case BFA_ITNIM_SM_HWFAIL: | ||
411 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
412 | bfa_itnim_iocdisable_cleanup(itnim); | ||
413 | break; | ||
414 | |||
415 | default: | ||
416 | bfa_assert(0); | ||
417 | } | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * Rport offline. Fimrware itnim is being deleted - awaiting f/w response. | ||
422 | */ | ||
423 | static void | ||
424 | bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
425 | { | ||
426 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
427 | bfa_trc(itnim->bfa, event); | ||
428 | |||
429 | switch (event) { | ||
430 | case BFA_ITNIM_SM_FWRSP: | ||
431 | bfa_sm_set_state(itnim, bfa_itnim_sm_offline); | ||
432 | bfa_itnim_offline_cb(itnim); | ||
433 | break; | ||
434 | |||
435 | case BFA_ITNIM_SM_DELETE: | ||
436 | bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); | ||
437 | break; | ||
438 | |||
439 | case BFA_ITNIM_SM_HWFAIL: | ||
440 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
441 | bfa_itnim_offline_cb(itnim); | ||
442 | break; | ||
443 | |||
444 | default: | ||
445 | bfa_assert(0); | ||
446 | } | ||
447 | } | ||
448 | |||
449 | static void | ||
450 | bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim, | ||
451 | enum bfa_itnim_event event) | ||
452 | { | ||
453 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
454 | bfa_trc(itnim->bfa, event); | ||
455 | |||
456 | switch (event) { | ||
457 | case BFA_ITNIM_SM_QRESUME: | ||
458 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete); | ||
459 | bfa_itnim_send_fwdelete(itnim); | ||
460 | break; | ||
461 | |||
462 | case BFA_ITNIM_SM_DELETE: | ||
463 | bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull); | ||
464 | break; | ||
465 | |||
466 | case BFA_ITNIM_SM_HWFAIL: | ||
467 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
468 | bfa_reqq_wcancel(&itnim->reqq_wait); | ||
469 | bfa_itnim_offline_cb(itnim); | ||
470 | break; | ||
471 | |||
472 | default: | ||
473 | bfa_assert(0); | ||
474 | } | ||
475 | } | ||
476 | |||
477 | /** | ||
478 | * Offline state. | ||
479 | */ | ||
480 | static void | ||
481 | bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
482 | { | ||
483 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
484 | bfa_trc(itnim->bfa, event); | ||
485 | |||
486 | switch (event) { | ||
487 | case BFA_ITNIM_SM_DELETE: | ||
488 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
489 | bfa_itnim_iotov_delete(itnim); | ||
490 | bfa_fcpim_delitn(itnim); | ||
491 | break; | ||
492 | |||
493 | case BFA_ITNIM_SM_ONLINE: | ||
494 | if (bfa_itnim_send_fwcreate(itnim)) | ||
495 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); | ||
496 | else | ||
497 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull); | ||
498 | break; | ||
499 | |||
500 | case BFA_ITNIM_SM_HWFAIL: | ||
501 | bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); | ||
502 | break; | ||
503 | |||
504 | default: | ||
505 | bfa_assert(0); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | /** | ||
510 | * IOC h/w failed state. | ||
511 | */ | ||
512 | static void | ||
513 | bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim, | ||
514 | enum bfa_itnim_event event) | ||
515 | { | ||
516 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
517 | bfa_trc(itnim->bfa, event); | ||
518 | |||
519 | switch (event) { | ||
520 | case BFA_ITNIM_SM_DELETE: | ||
521 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
522 | bfa_itnim_iotov_delete(itnim); | ||
523 | bfa_fcpim_delitn(itnim); | ||
524 | break; | ||
525 | |||
526 | case BFA_ITNIM_SM_OFFLINE: | ||
527 | bfa_itnim_offline_cb(itnim); | ||
528 | break; | ||
529 | |||
530 | case BFA_ITNIM_SM_ONLINE: | ||
531 | if (bfa_itnim_send_fwcreate(itnim)) | ||
532 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); | ||
533 | else | ||
534 | bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull); | ||
535 | break; | ||
536 | |||
537 | case BFA_ITNIM_SM_HWFAIL: | ||
538 | break; | ||
539 | |||
540 | default: | ||
541 | bfa_assert(0); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * Itnim is deleted, waiting for firmware response to delete. | ||
547 | */ | ||
548 | static void | ||
549 | bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) | ||
550 | { | ||
551 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
552 | bfa_trc(itnim->bfa, event); | ||
553 | |||
554 | switch (event) { | ||
555 | case BFA_ITNIM_SM_FWRSP: | ||
556 | case BFA_ITNIM_SM_HWFAIL: | ||
557 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
558 | bfa_fcpim_delitn(itnim); | ||
559 | break; | ||
560 | |||
561 | default: | ||
562 | bfa_assert(0); | ||
563 | } | ||
564 | } | ||
565 | |||
566 | static void | ||
567 | bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim, | ||
568 | enum bfa_itnim_event event) | ||
569 | { | ||
570 | bfa_trc(itnim->bfa, itnim->rport->rport_tag); | ||
571 | bfa_trc(itnim->bfa, event); | ||
572 | |||
573 | switch (event) { | ||
574 | case BFA_ITNIM_SM_QRESUME: | ||
575 | bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); | ||
576 | bfa_itnim_send_fwdelete(itnim); | ||
577 | break; | ||
578 | |||
579 | case BFA_ITNIM_SM_HWFAIL: | ||
580 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
581 | bfa_reqq_wcancel(&itnim->reqq_wait); | ||
582 | bfa_fcpim_delitn(itnim); | ||
583 | break; | ||
584 | |||
585 | default: | ||
586 | bfa_assert(0); | ||
587 | } | ||
588 | } | ||
589 | |||
590 | |||
591 | |||
592 | /** | ||
593 | * bfa_itnim_private | ||
594 | */ | ||
595 | |||
596 | /** | ||
597 | * Initiate cleanup of all IOs on an IOC failure. | ||
598 | */ | ||
599 | static void | ||
600 | bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim) | ||
601 | { | ||
602 | struct bfa_tskim_s *tskim; | ||
603 | struct bfa_ioim_s *ioim; | ||
604 | struct list_head *qe, *qen; | ||
605 | |||
606 | list_for_each_safe(qe, qen, &itnim->tsk_q) { | ||
607 | tskim = (struct bfa_tskim_s *) qe; | ||
608 | bfa_tskim_iocdisable(tskim); | ||
609 | } | ||
610 | |||
611 | list_for_each_safe(qe, qen, &itnim->io_q) { | ||
612 | ioim = (struct bfa_ioim_s *) qe; | ||
613 | bfa_ioim_iocdisable(ioim); | ||
614 | } | ||
615 | |||
616 | /** | ||
617 | * For IO request in pending queue, we pretend an early timeout. | ||
618 | */ | ||
619 | list_for_each_safe(qe, qen, &itnim->pending_q) { | ||
620 | ioim = (struct bfa_ioim_s *) qe; | ||
621 | bfa_ioim_tov(ioim); | ||
622 | } | ||
623 | |||
624 | list_for_each_safe(qe, qen, &itnim->io_cleanup_q) { | ||
625 | ioim = (struct bfa_ioim_s *) qe; | ||
626 | bfa_ioim_iocdisable(ioim); | ||
627 | } | ||
628 | } | ||
629 | |||
630 | /** | ||
631 | * IO cleanup completion | ||
632 | */ | ||
633 | static void | ||
634 | bfa_itnim_cleanp_comp(void *itnim_cbarg) | ||
635 | { | ||
636 | struct bfa_itnim_s *itnim = itnim_cbarg; | ||
637 | |||
638 | bfa_stats(itnim, cleanup_comps); | ||
639 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP); | ||
640 | } | ||
641 | |||
642 | /** | ||
643 | * Initiate cleanup of all IOs. | ||
644 | */ | ||
645 | static void | ||
646 | bfa_itnim_cleanup(struct bfa_itnim_s *itnim) | ||
647 | { | ||
648 | struct bfa_ioim_s *ioim; | ||
649 | struct bfa_tskim_s *tskim; | ||
650 | struct list_head *qe, *qen; | ||
651 | |||
652 | bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim); | ||
653 | |||
654 | list_for_each_safe(qe, qen, &itnim->io_q) { | ||
655 | ioim = (struct bfa_ioim_s *) qe; | ||
656 | |||
657 | /** | ||
658 | * Move IO to a cleanup queue from active queue so that a later | ||
659 | * TM will not pickup this IO. | ||
660 | */ | ||
661 | list_del(&ioim->qe); | ||
662 | list_add_tail(&ioim->qe, &itnim->io_cleanup_q); | ||
663 | |||
664 | bfa_wc_up(&itnim->wc); | ||
665 | bfa_ioim_cleanup(ioim); | ||
666 | } | ||
667 | |||
668 | list_for_each_safe(qe, qen, &itnim->tsk_q) { | ||
669 | tskim = (struct bfa_tskim_s *) qe; | ||
670 | bfa_wc_up(&itnim->wc); | ||
671 | bfa_tskim_cleanup(tskim); | ||
672 | } | ||
673 | |||
674 | bfa_wc_wait(&itnim->wc); | ||
675 | } | ||
676 | |||
677 | static void | ||
678 | __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete) | ||
679 | { | ||
680 | struct bfa_itnim_s *itnim = cbarg; | ||
681 | |||
682 | if (complete) | ||
683 | bfa_cb_itnim_online(itnim->ditn); | ||
684 | } | ||
685 | |||
686 | static void | ||
687 | __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete) | ||
688 | { | ||
689 | struct bfa_itnim_s *itnim = cbarg; | ||
690 | |||
691 | if (complete) | ||
692 | bfa_cb_itnim_offline(itnim->ditn); | ||
693 | } | ||
694 | |||
695 | static void | ||
696 | __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete) | ||
697 | { | ||
698 | struct bfa_itnim_s *itnim = cbarg; | ||
699 | |||
700 | if (complete) | ||
701 | bfa_cb_itnim_sler(itnim->ditn); | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * Call to resume any I/O requests waiting for room in request queue. | ||
706 | */ | ||
707 | static void | ||
708 | bfa_itnim_qresume(void *cbarg) | ||
709 | { | ||
710 | struct bfa_itnim_s *itnim = cbarg; | ||
711 | |||
712 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME); | ||
713 | } | ||
714 | |||
715 | |||
716 | |||
717 | |||
718 | /** | ||
719 | * bfa_itnim_public | ||
720 | */ | ||
721 | |||
722 | void | ||
723 | bfa_itnim_iodone(struct bfa_itnim_s *itnim) | ||
724 | { | ||
725 | bfa_wc_down(&itnim->wc); | ||
726 | } | ||
727 | |||
728 | void | ||
729 | bfa_itnim_tskdone(struct bfa_itnim_s *itnim) | ||
730 | { | ||
731 | bfa_wc_down(&itnim->wc); | ||
732 | } | ||
733 | |||
734 | void | ||
735 | bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
736 | u32 *dm_len) | ||
737 | { | ||
738 | /** | ||
739 | * ITN memory | ||
740 | */ | ||
741 | *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s); | ||
742 | } | ||
743 | |||
744 | void | ||
745 | bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) | ||
746 | { | ||
747 | struct bfa_s *bfa = fcpim->bfa; | ||
748 | struct bfa_itnim_s *itnim; | ||
749 | int i; | ||
750 | |||
751 | INIT_LIST_HEAD(&fcpim->itnim_q); | ||
752 | |||
753 | itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo); | ||
754 | fcpim->itnim_arr = itnim; | ||
755 | |||
756 | for (i = 0; i < fcpim->num_itnims; i++, itnim++) { | ||
757 | bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s)); | ||
758 | itnim->bfa = bfa; | ||
759 | itnim->fcpim = fcpim; | ||
760 | itnim->reqq = BFA_REQQ_QOS_LO; | ||
761 | itnim->rport = BFA_RPORT_FROM_TAG(bfa, i); | ||
762 | itnim->iotov_active = BFA_FALSE; | ||
763 | bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim); | ||
764 | |||
765 | INIT_LIST_HEAD(&itnim->io_q); | ||
766 | INIT_LIST_HEAD(&itnim->io_cleanup_q); | ||
767 | INIT_LIST_HEAD(&itnim->pending_q); | ||
768 | INIT_LIST_HEAD(&itnim->tsk_q); | ||
769 | INIT_LIST_HEAD(&itnim->delay_comp_q); | ||
770 | bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); | ||
771 | } | ||
772 | |||
773 | bfa_meminfo_kva(minfo) = (u8 *) itnim; | ||
774 | } | ||
775 | |||
776 | void | ||
777 | bfa_itnim_iocdisable(struct bfa_itnim_s *itnim) | ||
778 | { | ||
779 | bfa_stats(itnim, ioc_disabled); | ||
780 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL); | ||
781 | } | ||
782 | |||
783 | static bfa_boolean_t | ||
784 | bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim) | ||
785 | { | ||
786 | struct bfi_itnim_create_req_s *m; | ||
787 | |||
788 | itnim->msg_no++; | ||
789 | |||
790 | /** | ||
791 | * check for room in queue to send request now | ||
792 | */ | ||
793 | m = bfa_reqq_next(itnim->bfa, itnim->reqq); | ||
794 | if (!m) { | ||
795 | bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait); | ||
796 | return BFA_FALSE; | ||
797 | } | ||
798 | |||
799 | bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ, | ||
800 | bfa_lpuid(itnim->bfa)); | ||
801 | m->fw_handle = itnim->rport->fw_handle; | ||
802 | m->class = FC_CLASS_3; | ||
803 | m->seq_rec = itnim->seq_rec; | ||
804 | m->msg_no = itnim->msg_no; | ||
805 | |||
806 | /** | ||
807 | * queue I/O message to firmware | ||
808 | */ | ||
809 | bfa_reqq_produce(itnim->bfa, itnim->reqq); | ||
810 | return BFA_TRUE; | ||
811 | } | ||
812 | |||
813 | static bfa_boolean_t | ||
814 | bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim) | ||
815 | { | ||
816 | struct bfi_itnim_delete_req_s *m; | ||
817 | |||
818 | /** | ||
819 | * check for room in queue to send request now | ||
820 | */ | ||
821 | m = bfa_reqq_next(itnim->bfa, itnim->reqq); | ||
822 | if (!m) { | ||
823 | bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait); | ||
824 | return BFA_FALSE; | ||
825 | } | ||
826 | |||
827 | bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ, | ||
828 | bfa_lpuid(itnim->bfa)); | ||
829 | m->fw_handle = itnim->rport->fw_handle; | ||
830 | |||
831 | /** | ||
832 | * queue I/O message to firmware | ||
833 | */ | ||
834 | bfa_reqq_produce(itnim->bfa, itnim->reqq); | ||
835 | return BFA_TRUE; | ||
836 | } | ||
837 | |||
838 | /** | ||
839 | * Cleanup all pending failed inflight requests. | ||
840 | */ | ||
841 | static void | ||
842 | bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov) | ||
843 | { | ||
844 | struct bfa_ioim_s *ioim; | ||
845 | struct list_head *qe, *qen; | ||
846 | |||
847 | list_for_each_safe(qe, qen, &itnim->delay_comp_q) { | ||
848 | ioim = (struct bfa_ioim_s *)qe; | ||
849 | bfa_ioim_delayed_comp(ioim, iotov); | ||
850 | } | ||
851 | } | ||
852 | |||
853 | /** | ||
854 | * Start all pending IO requests. | ||
855 | */ | ||
856 | static void | ||
857 | bfa_itnim_iotov_online(struct bfa_itnim_s *itnim) | ||
858 | { | ||
859 | struct bfa_ioim_s *ioim; | ||
860 | |||
861 | bfa_itnim_iotov_stop(itnim); | ||
862 | |||
863 | /** | ||
864 | * Abort all inflight IO requests in the queue | ||
865 | */ | ||
866 | bfa_itnim_delayed_comp(itnim, BFA_FALSE); | ||
867 | |||
868 | /** | ||
869 | * Start all pending IO requests. | ||
870 | */ | ||
871 | while (!list_empty(&itnim->pending_q)) { | ||
872 | bfa_q_deq(&itnim->pending_q, &ioim); | ||
873 | list_add_tail(&ioim->qe, &itnim->io_q); | ||
874 | bfa_ioim_start(ioim); | ||
875 | } | ||
876 | } | ||
877 | |||
878 | /** | ||
879 | * Fail all pending IO requests | ||
880 | */ | ||
881 | static void | ||
882 | bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim) | ||
883 | { | ||
884 | struct bfa_ioim_s *ioim; | ||
885 | |||
886 | /** | ||
887 | * Fail all inflight IO requests in the queue | ||
888 | */ | ||
889 | bfa_itnim_delayed_comp(itnim, BFA_TRUE); | ||
890 | |||
891 | /** | ||
892 | * Fail any pending IO requests. | ||
893 | */ | ||
894 | while (!list_empty(&itnim->pending_q)) { | ||
895 | bfa_q_deq(&itnim->pending_q, &ioim); | ||
896 | list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); | ||
897 | bfa_ioim_tov(ioim); | ||
898 | } | ||
899 | } | ||
900 | |||
901 | /** | ||
902 | * IO TOV timer callback. Fail any pending IO requests. | ||
903 | */ | ||
904 | static void | ||
905 | bfa_itnim_iotov(void *itnim_arg) | ||
906 | { | ||
907 | struct bfa_itnim_s *itnim = itnim_arg; | ||
908 | |||
909 | itnim->iotov_active = BFA_FALSE; | ||
910 | |||
911 | bfa_cb_itnim_tov_begin(itnim->ditn); | ||
912 | bfa_itnim_iotov_cleanup(itnim); | ||
913 | bfa_cb_itnim_tov(itnim->ditn); | ||
914 | } | ||
915 | |||
916 | /** | ||
917 | * Start IO TOV timer for failing back pending IO requests in offline state. | ||
918 | */ | ||
919 | static void | ||
920 | bfa_itnim_iotov_start(struct bfa_itnim_s *itnim) | ||
921 | { | ||
922 | if (itnim->fcpim->path_tov > 0) { | ||
923 | |||
924 | itnim->iotov_active = BFA_TRUE; | ||
925 | bfa_assert(bfa_itnim_hold_io(itnim)); | ||
926 | bfa_timer_start(itnim->bfa, &itnim->timer, | ||
927 | bfa_itnim_iotov, itnim, itnim->fcpim->path_tov); | ||
928 | } | ||
929 | } | ||
930 | |||
931 | /** | ||
932 | * Stop IO TOV timer. | ||
933 | */ | ||
934 | static void | ||
935 | bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim) | ||
936 | { | ||
937 | if (itnim->iotov_active) { | ||
938 | itnim->iotov_active = BFA_FALSE; | ||
939 | bfa_timer_stop(&itnim->timer); | ||
940 | } | ||
941 | } | ||
942 | |||
943 | /** | ||
944 | * Stop IO TOV timer. | ||
945 | */ | ||
946 | static void | ||
947 | bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim) | ||
948 | { | ||
949 | bfa_boolean_t pathtov_active = BFA_FALSE; | ||
950 | |||
951 | if (itnim->iotov_active) | ||
952 | pathtov_active = BFA_TRUE; | ||
953 | |||
954 | bfa_itnim_iotov_stop(itnim); | ||
955 | if (pathtov_active) | ||
956 | bfa_cb_itnim_tov_begin(itnim->ditn); | ||
957 | bfa_itnim_iotov_cleanup(itnim); | ||
958 | if (pathtov_active) | ||
959 | bfa_cb_itnim_tov(itnim->ditn); | ||
960 | } | ||
961 | |||
962 | |||
963 | |||
964 | /** | ||
965 | * bfa_itnim_public | ||
966 | */ | ||
967 | |||
968 | /** | ||
969 | * Itnim interrupt processing. | ||
970 | */ | ||
971 | void | ||
972 | bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
973 | { | ||
974 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
975 | union bfi_itnim_i2h_msg_u msg; | ||
976 | struct bfa_itnim_s *itnim; | ||
977 | |||
978 | bfa_trc(bfa, m->mhdr.msg_id); | ||
979 | |||
980 | msg.msg = m; | ||
981 | |||
982 | switch (m->mhdr.msg_id) { | ||
983 | case BFI_ITNIM_I2H_CREATE_RSP: | ||
984 | itnim = BFA_ITNIM_FROM_TAG(fcpim, | ||
985 | msg.create_rsp->bfa_handle); | ||
986 | bfa_assert(msg.create_rsp->status == BFA_STATUS_OK); | ||
987 | bfa_stats(itnim, create_comps); | ||
988 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP); | ||
989 | break; | ||
990 | |||
991 | case BFI_ITNIM_I2H_DELETE_RSP: | ||
992 | itnim = BFA_ITNIM_FROM_TAG(fcpim, | ||
993 | msg.delete_rsp->bfa_handle); | ||
994 | bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK); | ||
995 | bfa_stats(itnim, delete_comps); | ||
996 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP); | ||
997 | break; | ||
998 | |||
999 | case BFI_ITNIM_I2H_SLER_EVENT: | ||
1000 | itnim = BFA_ITNIM_FROM_TAG(fcpim, | ||
1001 | msg.sler_event->bfa_handle); | ||
1002 | bfa_stats(itnim, sler_events); | ||
1003 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER); | ||
1004 | break; | ||
1005 | |||
1006 | default: | ||
1007 | bfa_trc(bfa, m->mhdr.msg_id); | ||
1008 | bfa_assert(0); | ||
1009 | } | ||
1010 | } | ||
1011 | |||
1012 | |||
1013 | |||
1014 | /** | ||
1015 | * bfa_itnim_api | ||
1016 | */ | ||
1017 | |||
1018 | struct bfa_itnim_s * | ||
1019 | bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn) | ||
1020 | { | ||
1021 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
1022 | struct bfa_itnim_s *itnim; | ||
1023 | |||
1024 | itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag); | ||
1025 | bfa_assert(itnim->rport == rport); | ||
1026 | |||
1027 | itnim->ditn = ditn; | ||
1028 | |||
1029 | bfa_stats(itnim, creates); | ||
1030 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE); | ||
1031 | |||
1032 | return (itnim); | ||
1033 | } | ||
1034 | |||
1035 | void | ||
1036 | bfa_itnim_delete(struct bfa_itnim_s *itnim) | ||
1037 | { | ||
1038 | bfa_stats(itnim, deletes); | ||
1039 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE); | ||
1040 | } | ||
1041 | |||
1042 | void | ||
1043 | bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec) | ||
1044 | { | ||
1045 | itnim->seq_rec = seq_rec; | ||
1046 | bfa_stats(itnim, onlines); | ||
1047 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE); | ||
1048 | } | ||
1049 | |||
1050 | void | ||
1051 | bfa_itnim_offline(struct bfa_itnim_s *itnim) | ||
1052 | { | ||
1053 | bfa_stats(itnim, offlines); | ||
1054 | bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE); | ||
1055 | } | ||
1056 | |||
1057 | /** | ||
1058 | * Return true if itnim is considered offline for holding off IO request. | ||
1059 | * IO is not held if itnim is being deleted. | ||
1060 | */ | ||
1061 | bfa_boolean_t | ||
1062 | bfa_itnim_hold_io(struct bfa_itnim_s *itnim) | ||
1063 | { | ||
1064 | return ( | ||
1065 | itnim->fcpim->path_tov && itnim->iotov_active && | ||
1066 | (bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) || | ||
1067 | bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) || | ||
1068 | bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) || | ||
1069 | bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) || | ||
1070 | bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) || | ||
1071 | bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable)) | ||
1072 | ); | ||
1073 | } | ||
1074 | |||
1075 | void | ||
1076 | bfa_itnim_get_stats(struct bfa_itnim_s *itnim, | ||
1077 | struct bfa_itnim_hal_stats_s *stats) | ||
1078 | { | ||
1079 | *stats = itnim->stats; | ||
1080 | } | ||
1081 | |||
1082 | void | ||
1083 | bfa_itnim_clear_stats(struct bfa_itnim_s *itnim) | ||
1084 | { | ||
1085 | bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats)); | ||
1086 | } | ||
1087 | |||
1088 | |||
diff --git a/drivers/scsi/bfa/bfa_log.c b/drivers/scsi/bfa/bfa_log.c new file mode 100644 index 000000000000..c2735e55cf03 --- /dev/null +++ b/drivers/scsi/bfa/bfa_log.c | |||
@@ -0,0 +1,346 @@ | |||
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 | * bfa_log.c BFA log library | ||
20 | */ | ||
21 | |||
22 | #include <bfa_os_inc.h> | ||
23 | #include <cs/bfa_log.h> | ||
24 | |||
25 | /* | ||
26 | * global log info structure | ||
27 | */ | ||
28 | struct bfa_log_info_s { | ||
29 | u32 start_idx; /* start index for a module */ | ||
30 | u32 total_count; /* total count for a module */ | ||
31 | enum bfa_log_severity level; /* global log level */ | ||
32 | bfa_log_cb_t cbfn; /* callback function */ | ||
33 | }; | ||
34 | |||
35 | static struct bfa_log_info_s bfa_log_info[BFA_LOG_MODULE_ID_MAX + 1]; | ||
36 | static u32 bfa_log_msg_total_count; | ||
37 | static int bfa_log_initialized; | ||
38 | |||
39 | static char *bfa_log_severity[] = | ||
40 | { "[none]", "[critical]", "[error]", "[warn]", "[info]", "" }; | ||
41 | |||
42 | /** | ||
43 | * BFA log library initialization | ||
44 | * | ||
45 | * The log library initialization includes the following, | ||
46 | * - set log instance name and callback function | ||
47 | * - read the message array generated from xml files | ||
48 | * - calculate start index for each module | ||
49 | * - calculate message count for each module | ||
50 | * - perform error checking | ||
51 | * | ||
52 | * @param[in] log_mod - log module info | ||
53 | * @param[in] instance_name - instance name | ||
54 | * @param[in] cbfn - callback function | ||
55 | * | ||
56 | * It return 0 on success, or -1 on failure | ||
57 | */ | ||
58 | int | ||
59 | bfa_log_init(struct bfa_log_mod_s *log_mod, char *instance_name, | ||
60 | bfa_log_cb_t cbfn) | ||
61 | { | ||
62 | struct bfa_log_msgdef_s *msg; | ||
63 | u32 pre_mod_id = 0; | ||
64 | u32 cur_mod_id = 0; | ||
65 | u32 i, pre_idx, idx, msg_id; | ||
66 | |||
67 | /* | ||
68 | * set instance name | ||
69 | */ | ||
70 | if (log_mod) { | ||
71 | strncpy(log_mod->instance_info, instance_name, | ||
72 | sizeof(log_mod->instance_info)); | ||
73 | log_mod->cbfn = cbfn; | ||
74 | for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++) | ||
75 | log_mod->log_level[i] = BFA_LOG_WARNING; | ||
76 | } | ||
77 | |||
78 | if (bfa_log_initialized) | ||
79 | return 0; | ||
80 | |||
81 | for (i = 0; i <= BFA_LOG_MODULE_ID_MAX; i++) { | ||
82 | bfa_log_info[i].start_idx = 0; | ||
83 | bfa_log_info[i].total_count = 0; | ||
84 | bfa_log_info[i].level = BFA_LOG_WARNING; | ||
85 | bfa_log_info[i].cbfn = cbfn; | ||
86 | } | ||
87 | |||
88 | pre_idx = 0; | ||
89 | idx = 0; | ||
90 | msg = bfa_log_msg_array; | ||
91 | msg_id = BFA_LOG_GET_MSG_ID(msg); | ||
92 | pre_mod_id = BFA_LOG_GET_MOD_ID(msg_id); | ||
93 | while (msg_id != 0) { | ||
94 | cur_mod_id = BFA_LOG_GET_MOD_ID(msg_id); | ||
95 | |||
96 | if (cur_mod_id > BFA_LOG_MODULE_ID_MAX) { | ||
97 | cbfn(log_mod, msg_id, | ||
98 | "%s%s log: module id %u out of range\n", | ||
99 | BFA_LOG_CAT_NAME, | ||
100 | bfa_log_severity[BFA_LOG_ERROR], | ||
101 | cur_mod_id); | ||
102 | return -1; | ||
103 | } | ||
104 | |||
105 | if (pre_mod_id > BFA_LOG_MODULE_ID_MAX) { | ||
106 | cbfn(log_mod, msg_id, | ||
107 | "%s%s log: module id %u out of range\n", | ||
108 | BFA_LOG_CAT_NAME, | ||
109 | bfa_log_severity[BFA_LOG_ERROR], | ||
110 | pre_mod_id); | ||
111 | return -1; | ||
112 | } | ||
113 | |||
114 | if (cur_mod_id != pre_mod_id) { | ||
115 | bfa_log_info[pre_mod_id].start_idx = pre_idx; | ||
116 | bfa_log_info[pre_mod_id].total_count = idx - pre_idx; | ||
117 | pre_mod_id = cur_mod_id; | ||
118 | pre_idx = idx; | ||
119 | } | ||
120 | |||
121 | idx++; | ||
122 | msg++; | ||
123 | msg_id = BFA_LOG_GET_MSG_ID(msg); | ||
124 | } | ||
125 | |||
126 | bfa_log_info[cur_mod_id].start_idx = pre_idx; | ||
127 | bfa_log_info[cur_mod_id].total_count = idx - pre_idx; | ||
128 | bfa_log_msg_total_count = idx; | ||
129 | |||
130 | cbfn(log_mod, msg_id, "%s%s log: init OK, msg total count %u\n", | ||
131 | BFA_LOG_CAT_NAME, | ||
132 | bfa_log_severity[BFA_LOG_INFO], bfa_log_msg_total_count); | ||
133 | |||
134 | bfa_log_initialized = 1; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * BFA log set log level for a module | ||
141 | * | ||
142 | * @param[in] log_mod - log module info | ||
143 | * @param[in] mod_id - module id | ||
144 | * @param[in] log_level - log severity level | ||
145 | * | ||
146 | * It return BFA_STATUS_OK on success, or > 0 on failure | ||
147 | */ | ||
148 | bfa_status_t | ||
149 | bfa_log_set_level(struct bfa_log_mod_s *log_mod, int mod_id, | ||
150 | enum bfa_log_severity log_level) | ||
151 | { | ||
152 | if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX) | ||
153 | return BFA_STATUS_EINVAL; | ||
154 | |||
155 | if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX) | ||
156 | return BFA_STATUS_EINVAL; | ||
157 | |||
158 | if (log_mod) | ||
159 | log_mod->log_level[mod_id] = log_level; | ||
160 | else | ||
161 | bfa_log_info[mod_id].level = log_level; | ||
162 | |||
163 | return BFA_STATUS_OK; | ||
164 | } | ||
165 | |||
166 | /** | ||
167 | * BFA log set log level for all modules | ||
168 | * | ||
169 | * @param[in] log_mod - log module info | ||
170 | * @param[in] log_level - log severity level | ||
171 | * | ||
172 | * It return BFA_STATUS_OK on success, or > 0 on failure | ||
173 | */ | ||
174 | bfa_status_t | ||
175 | bfa_log_set_level_all(struct bfa_log_mod_s *log_mod, | ||
176 | enum bfa_log_severity log_level) | ||
177 | { | ||
178 | int mod_id = BFA_LOG_UNUSED_ID + 1; | ||
179 | |||
180 | if (log_level <= BFA_LOG_INVALID || log_level > BFA_LOG_LEVEL_MAX) | ||
181 | return BFA_STATUS_EINVAL; | ||
182 | |||
183 | if (log_mod) { | ||
184 | for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++) | ||
185 | log_mod->log_level[mod_id] = log_level; | ||
186 | } else { | ||
187 | for (; mod_id <= BFA_LOG_MODULE_ID_MAX; mod_id++) | ||
188 | bfa_log_info[mod_id].level = log_level; | ||
189 | } | ||
190 | |||
191 | return BFA_STATUS_OK; | ||
192 | } | ||
193 | |||
194 | /** | ||
195 | * BFA log set log level for all aen sub-modules | ||
196 | * | ||
197 | * @param[in] log_mod - log module info | ||
198 | * @param[in] log_level - log severity level | ||
199 | * | ||
200 | * It return BFA_STATUS_OK on success, or > 0 on failure | ||
201 | */ | ||
202 | bfa_status_t | ||
203 | bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod, | ||
204 | enum bfa_log_severity log_level) | ||
205 | { | ||
206 | int mod_id = BFA_LOG_AEN_MIN + 1; | ||
207 | |||
208 | if (log_mod) { | ||
209 | for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++) | ||
210 | log_mod->log_level[mod_id] = log_level; | ||
211 | } else { | ||
212 | for (; mod_id <= BFA_LOG_AEN_MAX; mod_id++) | ||
213 | bfa_log_info[mod_id].level = log_level; | ||
214 | } | ||
215 | |||
216 | return BFA_STATUS_OK; | ||
217 | } | ||
218 | |||
219 | /** | ||
220 | * BFA log get log level for a module | ||
221 | * | ||
222 | * @param[in] log_mod - log module info | ||
223 | * @param[in] mod_id - module id | ||
224 | * | ||
225 | * It returns log level or -1 on error | ||
226 | */ | ||
227 | enum bfa_log_severity | ||
228 | bfa_log_get_level(struct bfa_log_mod_s *log_mod, int mod_id) | ||
229 | { | ||
230 | if (mod_id <= BFA_LOG_UNUSED_ID || mod_id > BFA_LOG_MODULE_ID_MAX) | ||
231 | return BFA_LOG_INVALID; | ||
232 | |||
233 | if (log_mod) | ||
234 | return (log_mod->log_level[mod_id]); | ||
235 | else | ||
236 | return (bfa_log_info[mod_id].level); | ||
237 | } | ||
238 | |||
239 | enum bfa_log_severity | ||
240 | bfa_log_get_msg_level(struct bfa_log_mod_s *log_mod, u32 msg_id) | ||
241 | { | ||
242 | struct bfa_log_msgdef_s *msg; | ||
243 | u32 mod = BFA_LOG_GET_MOD_ID(msg_id); | ||
244 | u32 idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1; | ||
245 | |||
246 | if (!bfa_log_initialized) | ||
247 | return BFA_LOG_INVALID; | ||
248 | |||
249 | if (mod > BFA_LOG_MODULE_ID_MAX) | ||
250 | return BFA_LOG_INVALID; | ||
251 | |||
252 | if (idx >= bfa_log_info[mod].total_count) { | ||
253 | bfa_log_info[mod].cbfn(log_mod, msg_id, | ||
254 | "%s%s log: inconsistent idx %u vs. total count %u\n", | ||
255 | BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx, | ||
256 | bfa_log_info[mod].total_count); | ||
257 | return BFA_LOG_INVALID; | ||
258 | } | ||
259 | |||
260 | msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx; | ||
261 | if (msg_id != BFA_LOG_GET_MSG_ID(msg)) { | ||
262 | bfa_log_info[mod].cbfn(log_mod, msg_id, | ||
263 | "%s%s log: inconsistent msg id %u array msg id %u\n", | ||
264 | BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], | ||
265 | msg_id, BFA_LOG_GET_MSG_ID(msg)); | ||
266 | return BFA_LOG_INVALID; | ||
267 | } | ||
268 | |||
269 | return BFA_LOG_GET_SEVERITY(msg); | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * BFA log message handling | ||
274 | * | ||
275 | * BFA log message handling finds the message based on message id and prints | ||
276 | * out the message based on its format and arguments. It also does prefix | ||
277 | * the severity etc. | ||
278 | * | ||
279 | * @param[in] log_mod - log module info | ||
280 | * @param[in] msg_id - message id | ||
281 | * @param[in] ... - message arguments | ||
282 | * | ||
283 | * It return 0 on success, or -1 on errors | ||
284 | */ | ||
285 | int | ||
286 | bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...) | ||
287 | { | ||
288 | va_list ap; | ||
289 | char buf[256]; | ||
290 | struct bfa_log_msgdef_s *msg; | ||
291 | int log_level; | ||
292 | u32 mod = BFA_LOG_GET_MOD_ID(msg_id); | ||
293 | u32 idx = BFA_LOG_GET_MSG_IDX(msg_id) - 1; | ||
294 | |||
295 | if (!bfa_log_initialized) | ||
296 | return -1; | ||
297 | |||
298 | if (mod > BFA_LOG_MODULE_ID_MAX) | ||
299 | return -1; | ||
300 | |||
301 | if (idx >= bfa_log_info[mod].total_count) { | ||
302 | bfa_log_info[mod]. | ||
303 | cbfn | ||
304 | (log_mod, msg_id, | ||
305 | "%s%s log: inconsistent idx %u vs. total count %u\n", | ||
306 | BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], idx, | ||
307 | bfa_log_info[mod].total_count); | ||
308 | return -1; | ||
309 | } | ||
310 | |||
311 | msg = bfa_log_msg_array + bfa_log_info[mod].start_idx + idx; | ||
312 | if (msg_id != BFA_LOG_GET_MSG_ID(msg)) { | ||
313 | bfa_log_info[mod]. | ||
314 | cbfn | ||
315 | (log_mod, msg_id, | ||
316 | "%s%s log: inconsistent msg id %u array msg id %u\n", | ||
317 | BFA_LOG_CAT_NAME, bfa_log_severity[BFA_LOG_ERROR], | ||
318 | msg_id, BFA_LOG_GET_MSG_ID(msg)); | ||
319 | return -1; | ||
320 | } | ||
321 | |||
322 | log_level = log_mod ? log_mod->log_level[mod] : bfa_log_info[mod].level; | ||
323 | if ((BFA_LOG_GET_SEVERITY(msg) > log_level) && | ||
324 | (msg->attributes != BFA_LOG_ATTR_NONE)) | ||
325 | return 0; | ||
326 | |||
327 | va_start(ap, msg_id); | ||
328 | bfa_os_vsprintf(buf, BFA_LOG_GET_MSG_FMT_STRING(msg), ap); | ||
329 | va_end(ap); | ||
330 | |||
331 | if (log_mod) | ||
332 | log_mod->cbfn(log_mod, msg_id, "%s[%s]%s%s %s: %s\n", | ||
333 | BFA_LOG_CAT_NAME, log_mod->instance_info, | ||
334 | bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)], | ||
335 | (msg->attributes & BFA_LOG_ATTR_AUDIT) | ||
336 | ? " (audit) " : "", msg->msg_value, buf); | ||
337 | else | ||
338 | bfa_log_info[mod].cbfn(log_mod, msg_id, "%s%s%s %s: %s\n", | ||
339 | BFA_LOG_CAT_NAME, | ||
340 | bfa_log_severity[BFA_LOG_GET_SEVERITY(msg)], | ||
341 | (msg->attributes & BFA_LOG_ATTR_AUDIT) ? | ||
342 | " (audit) " : "", msg->msg_value, buf); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
diff --git a/drivers/scsi/bfa/bfa_log_module.c b/drivers/scsi/bfa/bfa_log_module.c new file mode 100644 index 000000000000..5c154d341d69 --- /dev/null +++ b/drivers/scsi/bfa/bfa_log_module.c | |||
@@ -0,0 +1,451 @@ | |||
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 | #include <cs/bfa_log.h> | ||
19 | #include <aen/bfa_aen_adapter.h> | ||
20 | #include <aen/bfa_aen_audit.h> | ||
21 | #include <aen/bfa_aen_ethport.h> | ||
22 | #include <aen/bfa_aen_ioc.h> | ||
23 | #include <aen/bfa_aen_itnim.h> | ||
24 | #include <aen/bfa_aen_lport.h> | ||
25 | #include <aen/bfa_aen_port.h> | ||
26 | #include <aen/bfa_aen_rport.h> | ||
27 | #include <log/bfa_log_fcs.h> | ||
28 | #include <log/bfa_log_hal.h> | ||
29 | #include <log/bfa_log_linux.h> | ||
30 | #include <log/bfa_log_wdrv.h> | ||
31 | |||
32 | struct bfa_log_msgdef_s bfa_log_msg_array[] = { | ||
33 | |||
34 | |||
35 | /* messages define for BFA_AEN_CAT_ADAPTER Module */ | ||
36 | {BFA_AEN_ADAPTER_ADD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
37 | "BFA_AEN_ADAPTER_ADD", | ||
38 | "New adapter found: SN = %s, base port WWN = %s.", | ||
39 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
40 | |||
41 | {BFA_AEN_ADAPTER_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
42 | BFA_LOG_WARNING, "BFA_AEN_ADAPTER_REMOVE", | ||
43 | "Adapter removed: SN = %s.", | ||
44 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
45 | |||
46 | |||
47 | |||
48 | |||
49 | /* messages define for BFA_AEN_CAT_AUDIT Module */ | ||
50 | {BFA_AEN_AUDIT_AUTH_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
51 | BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_ENABLE", | ||
52 | "Authentication enabled for base port: WWN = %s.", | ||
53 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
54 | |||
55 | {BFA_AEN_AUDIT_AUTH_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
56 | BFA_LOG_INFO, "BFA_AEN_AUDIT_AUTH_DISABLE", | ||
57 | "Authentication disabled for base port: WWN = %s.", | ||
58 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
59 | |||
60 | |||
61 | |||
62 | |||
63 | /* messages define for BFA_AEN_CAT_ETHPORT Module */ | ||
64 | {BFA_AEN_ETHPORT_LINKUP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
65 | "BFA_AEN_ETHPORT_LINKUP", | ||
66 | "Base port ethernet linkup: mac = %s.", | ||
67 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
68 | |||
69 | {BFA_AEN_ETHPORT_LINKDOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
70 | "BFA_AEN_ETHPORT_LINKDOWN", | ||
71 | "Base port ethernet linkdown: mac = %s.", | ||
72 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
73 | |||
74 | {BFA_AEN_ETHPORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
75 | "BFA_AEN_ETHPORT_ENABLE", | ||
76 | "Base port ethernet interface enabled: mac = %s.", | ||
77 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
78 | |||
79 | {BFA_AEN_ETHPORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
80 | "BFA_AEN_ETHPORT_DISABLE", | ||
81 | "Base port ethernet interface disabled: mac = %s.", | ||
82 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
83 | |||
84 | |||
85 | |||
86 | |||
87 | /* messages define for BFA_AEN_CAT_IOC Module */ | ||
88 | {BFA_AEN_IOC_HBGOOD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
89 | "BFA_AEN_IOC_HBGOOD", | ||
90 | "Heart Beat of IOC %d is good.", | ||
91 | ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1}, | ||
92 | |||
93 | {BFA_AEN_IOC_HBFAIL, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_CRITICAL, | ||
94 | "BFA_AEN_IOC_HBFAIL", | ||
95 | "Heart Beat of IOC %d has failed.", | ||
96 | ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1}, | ||
97 | |||
98 | {BFA_AEN_IOC_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
99 | "BFA_AEN_IOC_ENABLE", | ||
100 | "IOC %d is enabled.", | ||
101 | ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1}, | ||
102 | |||
103 | {BFA_AEN_IOC_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
104 | "BFA_AEN_IOC_DISABLE", | ||
105 | "IOC %d is disabled.", | ||
106 | ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1}, | ||
107 | |||
108 | {BFA_AEN_IOC_FWMISMATCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
109 | BFA_LOG_CRITICAL, "BFA_AEN_IOC_FWMISMATCH", | ||
110 | "Running firmware version is incompatible with the driver version.", | ||
111 | (0), 0}, | ||
112 | |||
113 | |||
114 | |||
115 | |||
116 | /* messages define for BFA_AEN_CAT_ITNIM Module */ | ||
117 | {BFA_AEN_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
118 | "BFA_AEN_ITNIM_ONLINE", | ||
119 | "Target (WWN = %s) is online for initiator (WWN = %s).", | ||
120 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
121 | |||
122 | {BFA_AEN_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
123 | "BFA_AEN_ITNIM_OFFLINE", | ||
124 | "Target (WWN = %s) offlined by initiator (WWN = %s).", | ||
125 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
126 | |||
127 | {BFA_AEN_ITNIM_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
128 | BFA_LOG_ERROR, "BFA_AEN_ITNIM_DISCONNECT", | ||
129 | "Target (WWN = %s) connectivity lost for initiator (WWN = %s).", | ||
130 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
131 | |||
132 | |||
133 | |||
134 | |||
135 | /* messages define for BFA_AEN_CAT_LPORT Module */ | ||
136 | {BFA_AEN_LPORT_NEW, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
137 | "BFA_AEN_LPORT_NEW", | ||
138 | "New logical port created: WWN = %s, Role = %s.", | ||
139 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
140 | |||
141 | {BFA_AEN_LPORT_DELETE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
142 | "BFA_AEN_LPORT_DELETE", | ||
143 | "Logical port deleted: WWN = %s, Role = %s.", | ||
144 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
145 | |||
146 | {BFA_AEN_LPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
147 | "BFA_AEN_LPORT_ONLINE", | ||
148 | "Logical port online: WWN = %s, Role = %s.", | ||
149 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
150 | |||
151 | {BFA_AEN_LPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
152 | "BFA_AEN_LPORT_OFFLINE", | ||
153 | "Logical port taken offline: WWN = %s, Role = %s.", | ||
154 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
155 | |||
156 | {BFA_AEN_LPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
157 | BFA_LOG_ERROR, "BFA_AEN_LPORT_DISCONNECT", | ||
158 | "Logical port lost fabric connectivity: WWN = %s, Role = %s.", | ||
159 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
160 | |||
161 | {BFA_AEN_LPORT_NEW_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
162 | "BFA_AEN_LPORT_NEW_PROP", | ||
163 | "New virtual port created using proprietary interface: WWN = %s, Role = %s.", | ||
164 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
165 | |||
166 | {BFA_AEN_LPORT_DELETE_PROP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
167 | BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_PROP", | ||
168 | "Virtual port deleted using proprietary interface: WWN = %s, Role = %s.", | ||
169 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
170 | |||
171 | {BFA_AEN_LPORT_NEW_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
172 | BFA_LOG_INFO, "BFA_AEN_LPORT_NEW_STANDARD", | ||
173 | "New virtual port created using standard interface: WWN = %s, Role = %s.", | ||
174 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
175 | |||
176 | {BFA_AEN_LPORT_DELETE_STANDARD, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
177 | BFA_LOG_INFO, "BFA_AEN_LPORT_DELETE_STANDARD", | ||
178 | "Virtual port deleted using standard interface: WWN = %s, Role = %s.", | ||
179 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
180 | |||
181 | {BFA_AEN_LPORT_NPIV_DUP_WWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
182 | BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_DUP_WWN", | ||
183 | "Virtual port login failed. Duplicate WWN = %s reported by fabric.", | ||
184 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
185 | |||
186 | {BFA_AEN_LPORT_NPIV_FABRIC_MAX, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
187 | BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_FABRIC_MAX", | ||
188 | "Virtual port (WWN = %s) login failed. Max NPIV ports already exist in" | ||
189 | " fabric/fport.", | ||
190 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
191 | |||
192 | {BFA_AEN_LPORT_NPIV_UNKNOWN, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
193 | BFA_LOG_WARNING, "BFA_AEN_LPORT_NPIV_UNKNOWN", | ||
194 | "Virtual port (WWN = %s) login failed.", | ||
195 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
196 | |||
197 | |||
198 | |||
199 | |||
200 | /* messages define for BFA_AEN_CAT_PORT Module */ | ||
201 | {BFA_AEN_PORT_ONLINE, BFA_LOG_ATTR_NONE, BFA_LOG_INFO, "BFA_AEN_PORT_ONLINE", | ||
202 | "Base port online: WWN = %s.", | ||
203 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
204 | |||
205 | {BFA_AEN_PORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING, | ||
206 | "BFA_AEN_PORT_OFFLINE", | ||
207 | "Base port offline: WWN = %s.", | ||
208 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
209 | |||
210 | {BFA_AEN_PORT_RLIR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
211 | "BFA_AEN_PORT_RLIR", | ||
212 | "RLIR event not supported.", | ||
213 | (0), 0}, | ||
214 | |||
215 | {BFA_AEN_PORT_SFP_INSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
216 | "BFA_AEN_PORT_SFP_INSERT", | ||
217 | "New SFP found: WWN/MAC = %s.", | ||
218 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
219 | |||
220 | {BFA_AEN_PORT_SFP_REMOVE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
221 | BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_REMOVE", | ||
222 | "SFP removed: WWN/MAC = %s.", | ||
223 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
224 | |||
225 | {BFA_AEN_PORT_SFP_POM, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING, | ||
226 | "BFA_AEN_PORT_SFP_POM", | ||
227 | "SFP POM level to %s: WWN/MAC = %s.", | ||
228 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
229 | |||
230 | {BFA_AEN_PORT_ENABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
231 | "BFA_AEN_PORT_ENABLE", | ||
232 | "Base port enabled: WWN = %s.", | ||
233 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
234 | |||
235 | {BFA_AEN_PORT_DISABLE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
236 | "BFA_AEN_PORT_DISABLE", | ||
237 | "Base port disabled: WWN = %s.", | ||
238 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
239 | |||
240 | {BFA_AEN_PORT_AUTH_ON, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
241 | "BFA_AEN_PORT_AUTH_ON", | ||
242 | "Authentication successful for base port: WWN = %s.", | ||
243 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
244 | |||
245 | {BFA_AEN_PORT_AUTH_OFF, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR, | ||
246 | "BFA_AEN_PORT_AUTH_OFF", | ||
247 | "Authentication unsuccessful for base port: WWN = %s.", | ||
248 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
249 | |||
250 | {BFA_AEN_PORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR, | ||
251 | "BFA_AEN_PORT_DISCONNECT", | ||
252 | "Base port (WWN = %s) lost fabric connectivity.", | ||
253 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
254 | |||
255 | {BFA_AEN_PORT_QOS_NEG, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_WARNING, | ||
256 | "BFA_AEN_PORT_QOS_NEG", | ||
257 | "QOS negotiation failed for base port: WWN = %s.", | ||
258 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
259 | |||
260 | {BFA_AEN_PORT_FABRIC_NAME_CHANGE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
261 | BFA_LOG_WARNING, "BFA_AEN_PORT_FABRIC_NAME_CHANGE", | ||
262 | "Base port WWN = %s, Fabric WWN = %s.", | ||
263 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
264 | |||
265 | {BFA_AEN_PORT_SFP_ACCESS_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
266 | BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_ACCESS_ERROR", | ||
267 | "SFP access error: WWN/MAC = %s.", | ||
268 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
269 | |||
270 | {BFA_AEN_PORT_SFP_UNSUPPORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
271 | BFA_LOG_WARNING, "BFA_AEN_PORT_SFP_UNSUPPORT", | ||
272 | "Unsupported SFP found: WWN/MAC = %s.", | ||
273 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
274 | |||
275 | |||
276 | |||
277 | |||
278 | /* messages define for BFA_AEN_CAT_RPORT Module */ | ||
279 | {BFA_AEN_RPORT_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
280 | "BFA_AEN_RPORT_ONLINE", | ||
281 | "Remote port (WWN = %s) online for logical port (WWN = %s).", | ||
282 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
283 | |||
284 | {BFA_AEN_RPORT_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
285 | "BFA_AEN_RPORT_OFFLINE", | ||
286 | "Remote port (WWN = %s) offlined by logical port (WWN = %s).", | ||
287 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
288 | |||
289 | {BFA_AEN_RPORT_DISCONNECT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
290 | BFA_LOG_ERROR, "BFA_AEN_RPORT_DISCONNECT", | ||
291 | "Remote port (WWN = %s) connectivity lost for logical port (WWN = %s).", | ||
292 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | 0), 2}, | ||
293 | |||
294 | {BFA_AEN_RPORT_QOS_PRIO, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
295 | "BFA_AEN_RPORT_QOS_PRIO", | ||
296 | "QOS priority changed to %s: RPWWN = %s and LPWWN = %s.", | ||
297 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | | ||
298 | (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3}, | ||
299 | |||
300 | {BFA_AEN_RPORT_QOS_FLOWID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
301 | "BFA_AEN_RPORT_QOS_FLOWID", | ||
302 | "QOS flow ID changed to %d: RPWWN = %s and LPWWN = %s.", | ||
303 | ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | | ||
304 | (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3}, | ||
305 | |||
306 | |||
307 | |||
308 | |||
309 | /* messages define for FCS Module */ | ||
310 | {BFA_LOG_FCS_FABRIC_NOSWITCH, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
311 | BFA_LOG_INFO, "FCS_FABRIC_NOSWITCH", | ||
312 | "No switched fabric presence is detected.", | ||
313 | (0), 0}, | ||
314 | |||
315 | {BFA_LOG_FCS_FABRIC_ISOLATED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
316 | BFA_LOG_INFO, "FCS_FABRIC_ISOLATED", | ||
317 | "Port is isolated due to VF_ID mismatch. PWWN: %s, Port VF_ID: %04x and" | ||
318 | " switch port VF_ID: %04x.", | ||
319 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_X << BFA_LOG_ARG1) | | ||
320 | (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3}, | ||
321 | |||
322 | |||
323 | |||
324 | |||
325 | /* messages define for HAL Module */ | ||
326 | {BFA_LOG_HAL_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR, | ||
327 | "HAL_ASSERT", | ||
328 | "Assertion failure: %s:%d: %s", | ||
329 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) | | ||
330 | (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3}, | ||
331 | |||
332 | {BFA_LOG_HAL_HEARTBEAT_FAILURE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
333 | BFA_LOG_CRITICAL, "HAL_HEARTBEAT_FAILURE", | ||
334 | "Firmware heartbeat failure at %d", | ||
335 | ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1}, | ||
336 | |||
337 | {BFA_LOG_HAL_FCPIM_PARM_INVALID, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
338 | BFA_LOG_INFO, "HAL_FCPIM_PARM_INVALID", | ||
339 | "Driver configuration %s value %d is invalid. Value should be within" | ||
340 | " %d and %d.", | ||
341 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) | | ||
342 | (BFA_LOG_D << BFA_LOG_ARG2) | (BFA_LOG_D << BFA_LOG_ARG3) | 0), 4}, | ||
343 | |||
344 | {BFA_LOG_HAL_SM_ASSERT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_ERROR, | ||
345 | "HAL_SM_ASSERT", | ||
346 | "SM Assertion failure: %s:%d: event = %d", | ||
347 | ((BFA_LOG_S << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) | | ||
348 | (BFA_LOG_D << BFA_LOG_ARG2) | 0), 3}, | ||
349 | |||
350 | |||
351 | |||
352 | |||
353 | /* messages define for LINUX Module */ | ||
354 | {BFA_LOG_LINUX_DEVICE_CLAIMED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
355 | BFA_LOG_INFO, "LINUX_DEVICE_CLAIMED", | ||
356 | "bfa device at %s claimed.", | ||
357 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
358 | |||
359 | {BFA_LOG_LINUX_HASH_INIT_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
360 | BFA_LOG_INFO, "LINUX_HASH_INIT_FAILED", | ||
361 | "Hash table initialization failure for the port %s.", | ||
362 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
363 | |||
364 | {BFA_LOG_LINUX_SYSFS_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
365 | BFA_LOG_INFO, "LINUX_SYSFS_FAILED", | ||
366 | "sysfs file creation failure for the port %s.", | ||
367 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
368 | |||
369 | {BFA_LOG_LINUX_MEM_ALLOC_FAILED, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
370 | BFA_LOG_INFO, "LINUX_MEM_ALLOC_FAILED", | ||
371 | "Memory allocation failed: %s. ", | ||
372 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
373 | |||
374 | {BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED, | ||
375 | BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
376 | "LINUX_DRIVER_REGISTRATION_FAILED", | ||
377 | "%s. ", | ||
378 | ((BFA_LOG_S << BFA_LOG_ARG0) | 0), 1}, | ||
379 | |||
380 | {BFA_LOG_LINUX_ITNIM_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
381 | "LINUX_ITNIM_FREE", | ||
382 | "scsi%d: FCID: %s WWPN: %s", | ||
383 | ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_S << BFA_LOG_ARG1) | | ||
384 | (BFA_LOG_S << BFA_LOG_ARG2) | 0), 3}, | ||
385 | |||
386 | {BFA_LOG_LINUX_ITNIM_ONLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
387 | BFA_LOG_INFO, "LINUX_ITNIM_ONLINE", | ||
388 | "Target: %d:0:%d FCID: %s WWPN: %s", | ||
389 | ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) | | ||
390 | (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4}, | ||
391 | |||
392 | {BFA_LOG_LINUX_ITNIM_OFFLINE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
393 | BFA_LOG_INFO, "LINUX_ITNIM_OFFLINE", | ||
394 | "Target: %d:0:%d FCID: %s WWPN: %s", | ||
395 | ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_D << BFA_LOG_ARG1) | | ||
396 | (BFA_LOG_S << BFA_LOG_ARG2) | (BFA_LOG_S << BFA_LOG_ARG3) | 0), 4}, | ||
397 | |||
398 | {BFA_LOG_LINUX_SCSI_HOST_FREE, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
399 | BFA_LOG_INFO, "LINUX_SCSI_HOST_FREE", | ||
400 | "Free scsi%d", | ||
401 | ((BFA_LOG_D << BFA_LOG_ARG0) | 0), 1}, | ||
402 | |||
403 | {BFA_LOG_LINUX_SCSI_ABORT, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, BFA_LOG_INFO, | ||
404 | "LINUX_SCSI_ABORT", | ||
405 | "scsi%d: abort cmnd %p, iotag %x", | ||
406 | ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) | | ||
407 | (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3}, | ||
408 | |||
409 | {BFA_LOG_LINUX_SCSI_ABORT_COMP, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
410 | BFA_LOG_INFO, "LINUX_SCSI_ABORT_COMP", | ||
411 | "scsi%d: complete abort 0x%p, iotag 0x%x", | ||
412 | ((BFA_LOG_D << BFA_LOG_ARG0) | (BFA_LOG_P << BFA_LOG_ARG1) | | ||
413 | (BFA_LOG_X << BFA_LOG_ARG2) | 0), 3}, | ||
414 | |||
415 | |||
416 | |||
417 | |||
418 | /* messages define for WDRV Module */ | ||
419 | {BFA_LOG_WDRV_IOC_INIT_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
420 | BFA_LOG_INFO, "WDRV_IOC_INIT_ERROR", | ||
421 | "IOC initialization has failed.", | ||
422 | (0), 0}, | ||
423 | |||
424 | {BFA_LOG_WDRV_IOC_INTERNAL_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
425 | BFA_LOG_INFO, "WDRV_IOC_INTERNAL_ERROR", | ||
426 | "IOC internal error. ", | ||
427 | (0), 0}, | ||
428 | |||
429 | {BFA_LOG_WDRV_IOC_START_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
430 | BFA_LOG_INFO, "WDRV_IOC_START_ERROR", | ||
431 | "IOC could not be started. ", | ||
432 | (0), 0}, | ||
433 | |||
434 | {BFA_LOG_WDRV_IOC_STOP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
435 | BFA_LOG_INFO, "WDRV_IOC_STOP_ERROR", | ||
436 | "IOC could not be stopped. ", | ||
437 | (0), 0}, | ||
438 | |||
439 | {BFA_LOG_WDRV_INSUFFICIENT_RESOURCES, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
440 | BFA_LOG_INFO, "WDRV_INSUFFICIENT_RESOURCES", | ||
441 | "Insufficient memory. ", | ||
442 | (0), 0}, | ||
443 | |||
444 | {BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR, BFA_LOG_ATTR_NONE | BFA_LOG_ATTR_LOG, | ||
445 | BFA_LOG_INFO, "WDRV_BASE_ADDRESS_MAP_ERROR", | ||
446 | "Unable to map the IOC onto the system address space. ", | ||
447 | (0), 0}, | ||
448 | |||
449 | |||
450 | {0, 0, 0, "", "", 0, 0}, | ||
451 | }; | ||
diff --git a/drivers/scsi/bfa/bfa_lps.c b/drivers/scsi/bfa/bfa_lps.c new file mode 100644 index 000000000000..9844b45412b6 --- /dev/null +++ b/drivers/scsi/bfa/bfa_lps.c | |||
@@ -0,0 +1,782 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfi/bfi_lps.h> | ||
20 | #include <cs/bfa_debug.h> | ||
21 | |||
22 | BFA_TRC_FILE(HAL, LPS); | ||
23 | BFA_MODULE(lps); | ||
24 | |||
25 | #define BFA_LPS_MIN_LPORTS (1) | ||
26 | #define BFA_LPS_MAX_LPORTS (256) | ||
27 | |||
28 | /** | ||
29 | * forward declarations | ||
30 | */ | ||
31 | static void bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, | ||
32 | u32 *dm_len); | ||
33 | static void bfa_lps_attach(struct bfa_s *bfa, void *bfad, | ||
34 | struct bfa_iocfc_cfg_s *cfg, | ||
35 | struct bfa_meminfo_s *meminfo, | ||
36 | struct bfa_pcidev_s *pcidev); | ||
37 | static void bfa_lps_initdone(struct bfa_s *bfa); | ||
38 | static void bfa_lps_detach(struct bfa_s *bfa); | ||
39 | static void bfa_lps_start(struct bfa_s *bfa); | ||
40 | static void bfa_lps_stop(struct bfa_s *bfa); | ||
41 | static void bfa_lps_iocdisable(struct bfa_s *bfa); | ||
42 | static void bfa_lps_login_rsp(struct bfa_s *bfa, | ||
43 | struct bfi_lps_login_rsp_s *rsp); | ||
44 | static void bfa_lps_logout_rsp(struct bfa_s *bfa, | ||
45 | struct bfi_lps_logout_rsp_s *rsp); | ||
46 | static void bfa_lps_reqq_resume(void *lps_arg); | ||
47 | static void bfa_lps_free(struct bfa_lps_s *lps); | ||
48 | static void bfa_lps_send_login(struct bfa_lps_s *lps); | ||
49 | static void bfa_lps_send_logout(struct bfa_lps_s *lps); | ||
50 | static void bfa_lps_login_comp(struct bfa_lps_s *lps); | ||
51 | static void bfa_lps_logout_comp(struct bfa_lps_s *lps); | ||
52 | |||
53 | |||
54 | /** | ||
55 | * lps_pvt BFA LPS private functions | ||
56 | */ | ||
57 | |||
58 | enum bfa_lps_event { | ||
59 | BFA_LPS_SM_LOGIN = 1, /* login request from user */ | ||
60 | BFA_LPS_SM_LOGOUT = 2, /* logout request from user */ | ||
61 | BFA_LPS_SM_FWRSP = 3, /* f/w response to login/logout */ | ||
62 | BFA_LPS_SM_RESUME = 4, /* space present in reqq queue */ | ||
63 | BFA_LPS_SM_DELETE = 5, /* lps delete from user */ | ||
64 | BFA_LPS_SM_OFFLINE = 6, /* Link is offline */ | ||
65 | }; | ||
66 | |||
67 | static void bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
68 | static void bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
69 | static void bfa_lps_sm_loginwait(struct bfa_lps_s *lps, | ||
70 | enum bfa_lps_event event); | ||
71 | static void bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
72 | static void bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event); | ||
73 | static void bfa_lps_sm_logowait(struct bfa_lps_s *lps, | ||
74 | enum bfa_lps_event event); | ||
75 | |||
76 | /** | ||
77 | * Init state -- no login | ||
78 | */ | ||
79 | static void | ||
80 | bfa_lps_sm_init(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
81 | { | ||
82 | bfa_trc(lps->bfa, lps->lp_tag); | ||
83 | bfa_trc(lps->bfa, event); | ||
84 | |||
85 | switch (event) { | ||
86 | case BFA_LPS_SM_LOGIN: | ||
87 | if (bfa_reqq_full(lps->bfa, lps->reqq)) { | ||
88 | bfa_sm_set_state(lps, bfa_lps_sm_loginwait); | ||
89 | bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe); | ||
90 | } else { | ||
91 | bfa_sm_set_state(lps, bfa_lps_sm_login); | ||
92 | bfa_lps_send_login(lps); | ||
93 | } | ||
94 | break; | ||
95 | |||
96 | case BFA_LPS_SM_LOGOUT: | ||
97 | bfa_lps_logout_comp(lps); | ||
98 | break; | ||
99 | |||
100 | case BFA_LPS_SM_DELETE: | ||
101 | bfa_lps_free(lps); | ||
102 | break; | ||
103 | |||
104 | case BFA_LPS_SM_OFFLINE: | ||
105 | break; | ||
106 | |||
107 | case BFA_LPS_SM_FWRSP: | ||
108 | /* Could happen when fabric detects loopback and discards | ||
109 | * the lps request. Fw will eventually sent out the timeout | ||
110 | * Just ignore | ||
111 | */ | ||
112 | break; | ||
113 | |||
114 | default: | ||
115 | bfa_assert(0); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * login is in progress -- awaiting response from firmware | ||
121 | */ | ||
122 | static void | ||
123 | bfa_lps_sm_login(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
124 | { | ||
125 | bfa_trc(lps->bfa, lps->lp_tag); | ||
126 | bfa_trc(lps->bfa, event); | ||
127 | |||
128 | switch (event) { | ||
129 | case BFA_LPS_SM_FWRSP: | ||
130 | if (lps->status == BFA_STATUS_OK) | ||
131 | bfa_sm_set_state(lps, bfa_lps_sm_online); | ||
132 | else | ||
133 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
134 | bfa_lps_login_comp(lps); | ||
135 | break; | ||
136 | |||
137 | case BFA_LPS_SM_OFFLINE: | ||
138 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
139 | break; | ||
140 | |||
141 | default: | ||
142 | bfa_assert(0); | ||
143 | } | ||
144 | } | ||
145 | |||
146 | /** | ||
147 | * login pending - awaiting space in request queue | ||
148 | */ | ||
149 | static void | ||
150 | bfa_lps_sm_loginwait(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
151 | { | ||
152 | bfa_trc(lps->bfa, lps->lp_tag); | ||
153 | bfa_trc(lps->bfa, event); | ||
154 | |||
155 | switch (event) { | ||
156 | case BFA_LPS_SM_RESUME: | ||
157 | bfa_sm_set_state(lps, bfa_lps_sm_login); | ||
158 | break; | ||
159 | |||
160 | case BFA_LPS_SM_OFFLINE: | ||
161 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
162 | bfa_reqq_wcancel(&lps->wqe); | ||
163 | break; | ||
164 | |||
165 | default: | ||
166 | bfa_assert(0); | ||
167 | } | ||
168 | } | ||
169 | |||
170 | /** | ||
171 | * login complete | ||
172 | */ | ||
173 | static void | ||
174 | bfa_lps_sm_online(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
175 | { | ||
176 | bfa_trc(lps->bfa, lps->lp_tag); | ||
177 | bfa_trc(lps->bfa, event); | ||
178 | |||
179 | switch (event) { | ||
180 | case BFA_LPS_SM_LOGOUT: | ||
181 | if (bfa_reqq_full(lps->bfa, lps->reqq)) { | ||
182 | bfa_sm_set_state(lps, bfa_lps_sm_logowait); | ||
183 | bfa_reqq_wait(lps->bfa, lps->reqq, &lps->wqe); | ||
184 | } else { | ||
185 | bfa_sm_set_state(lps, bfa_lps_sm_logout); | ||
186 | bfa_lps_send_logout(lps); | ||
187 | } | ||
188 | break; | ||
189 | |||
190 | case BFA_LPS_SM_OFFLINE: | ||
191 | case BFA_LPS_SM_DELETE: | ||
192 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
193 | break; | ||
194 | |||
195 | default: | ||
196 | bfa_assert(0); | ||
197 | } | ||
198 | } | ||
199 | |||
200 | /** | ||
201 | * logout in progress - awaiting firmware response | ||
202 | */ | ||
203 | static void | ||
204 | bfa_lps_sm_logout(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
205 | { | ||
206 | bfa_trc(lps->bfa, lps->lp_tag); | ||
207 | bfa_trc(lps->bfa, event); | ||
208 | |||
209 | switch (event) { | ||
210 | case BFA_LPS_SM_FWRSP: | ||
211 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
212 | bfa_lps_logout_comp(lps); | ||
213 | break; | ||
214 | |||
215 | case BFA_LPS_SM_OFFLINE: | ||
216 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
217 | break; | ||
218 | |||
219 | default: | ||
220 | bfa_assert(0); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | /** | ||
225 | * logout pending -- awaiting space in request queue | ||
226 | */ | ||
227 | static void | ||
228 | bfa_lps_sm_logowait(struct bfa_lps_s *lps, enum bfa_lps_event event) | ||
229 | { | ||
230 | bfa_trc(lps->bfa, lps->lp_tag); | ||
231 | bfa_trc(lps->bfa, event); | ||
232 | |||
233 | switch (event) { | ||
234 | case BFA_LPS_SM_RESUME: | ||
235 | bfa_sm_set_state(lps, bfa_lps_sm_logout); | ||
236 | bfa_lps_send_logout(lps); | ||
237 | break; | ||
238 | |||
239 | case BFA_LPS_SM_OFFLINE: | ||
240 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
241 | bfa_reqq_wcancel(&lps->wqe); | ||
242 | break; | ||
243 | |||
244 | default: | ||
245 | bfa_assert(0); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | |||
250 | |||
251 | /** | ||
252 | * lps_pvt BFA LPS private functions | ||
253 | */ | ||
254 | |||
255 | /** | ||
256 | * return memory requirement | ||
257 | */ | ||
258 | static void | ||
259 | bfa_lps_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len) | ||
260 | { | ||
261 | if (cfg->drvcfg.min_cfg) | ||
262 | *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MIN_LPORTS; | ||
263 | else | ||
264 | *ndm_len += sizeof(struct bfa_lps_s) * BFA_LPS_MAX_LPORTS; | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * bfa module attach at initialization time | ||
269 | */ | ||
270 | static void | ||
271 | bfa_lps_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
272 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
273 | { | ||
274 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
275 | struct bfa_lps_s *lps; | ||
276 | int i; | ||
277 | |||
278 | bfa_os_memset(mod, 0, sizeof(struct bfa_lps_mod_s)); | ||
279 | mod->num_lps = BFA_LPS_MAX_LPORTS; | ||
280 | if (cfg->drvcfg.min_cfg) | ||
281 | mod->num_lps = BFA_LPS_MIN_LPORTS; | ||
282 | else | ||
283 | mod->num_lps = BFA_LPS_MAX_LPORTS; | ||
284 | mod->lps_arr = lps = (struct bfa_lps_s *) bfa_meminfo_kva(meminfo); | ||
285 | |||
286 | bfa_meminfo_kva(meminfo) += mod->num_lps * sizeof(struct bfa_lps_s); | ||
287 | |||
288 | INIT_LIST_HEAD(&mod->lps_free_q); | ||
289 | INIT_LIST_HEAD(&mod->lps_active_q); | ||
290 | |||
291 | for (i = 0; i < mod->num_lps; i++, lps++) { | ||
292 | lps->bfa = bfa; | ||
293 | lps->lp_tag = (u8) i; | ||
294 | lps->reqq = BFA_REQQ_LPS; | ||
295 | bfa_reqq_winit(&lps->wqe, bfa_lps_reqq_resume, lps); | ||
296 | list_add_tail(&lps->qe, &mod->lps_free_q); | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static void | ||
301 | bfa_lps_initdone(struct bfa_s *bfa) | ||
302 | { | ||
303 | } | ||
304 | |||
305 | static void | ||
306 | bfa_lps_detach(struct bfa_s *bfa) | ||
307 | { | ||
308 | } | ||
309 | |||
310 | static void | ||
311 | bfa_lps_start(struct bfa_s *bfa) | ||
312 | { | ||
313 | } | ||
314 | |||
315 | static void | ||
316 | bfa_lps_stop(struct bfa_s *bfa) | ||
317 | { | ||
318 | } | ||
319 | |||
320 | /** | ||
321 | * IOC in disabled state -- consider all lps offline | ||
322 | */ | ||
323 | static void | ||
324 | bfa_lps_iocdisable(struct bfa_s *bfa) | ||
325 | { | ||
326 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
327 | struct bfa_lps_s *lps; | ||
328 | struct list_head *qe, *qen; | ||
329 | |||
330 | list_for_each_safe(qe, qen, &mod->lps_active_q) { | ||
331 | lps = (struct bfa_lps_s *) qe; | ||
332 | bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * Firmware login response | ||
338 | */ | ||
339 | static void | ||
340 | bfa_lps_login_rsp(struct bfa_s *bfa, struct bfi_lps_login_rsp_s *rsp) | ||
341 | { | ||
342 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
343 | struct bfa_lps_s *lps; | ||
344 | |||
345 | bfa_assert(rsp->lp_tag < mod->num_lps); | ||
346 | lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); | ||
347 | |||
348 | lps->status = rsp->status; | ||
349 | switch (rsp->status) { | ||
350 | case BFA_STATUS_OK: | ||
351 | lps->fport = rsp->f_port; | ||
352 | lps->npiv_en = rsp->npiv_en; | ||
353 | lps->lp_pid = rsp->lp_pid; | ||
354 | lps->pr_bbcred = bfa_os_ntohs(rsp->bb_credit); | ||
355 | lps->pr_pwwn = rsp->port_name; | ||
356 | lps->pr_nwwn = rsp->node_name; | ||
357 | lps->auth_req = rsp->auth_req; | ||
358 | lps->lp_mac = rsp->lp_mac; | ||
359 | lps->brcd_switch = rsp->brcd_switch; | ||
360 | lps->fcf_mac = rsp->fcf_mac; | ||
361 | |||
362 | break; | ||
363 | |||
364 | case BFA_STATUS_FABRIC_RJT: | ||
365 | lps->lsrjt_rsn = rsp->lsrjt_rsn; | ||
366 | lps->lsrjt_expl = rsp->lsrjt_expl; | ||
367 | |||
368 | break; | ||
369 | |||
370 | case BFA_STATUS_EPROTOCOL: | ||
371 | lps->ext_status = rsp->ext_status; | ||
372 | |||
373 | break; | ||
374 | |||
375 | default: | ||
376 | /* Nothing to do with other status */ | ||
377 | break; | ||
378 | } | ||
379 | |||
380 | bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP); | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * Firmware logout response | ||
385 | */ | ||
386 | static void | ||
387 | bfa_lps_logout_rsp(struct bfa_s *bfa, struct bfi_lps_logout_rsp_s *rsp) | ||
388 | { | ||
389 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
390 | struct bfa_lps_s *lps; | ||
391 | |||
392 | bfa_assert(rsp->lp_tag < mod->num_lps); | ||
393 | lps = BFA_LPS_FROM_TAG(mod, rsp->lp_tag); | ||
394 | |||
395 | bfa_sm_send_event(lps, BFA_LPS_SM_FWRSP); | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * Space is available in request queue, resume queueing request to firmware. | ||
400 | */ | ||
401 | static void | ||
402 | bfa_lps_reqq_resume(void *lps_arg) | ||
403 | { | ||
404 | struct bfa_lps_s *lps = lps_arg; | ||
405 | |||
406 | bfa_sm_send_event(lps, BFA_LPS_SM_RESUME); | ||
407 | } | ||
408 | |||
409 | /** | ||
410 | * lps is freed -- triggered by vport delete | ||
411 | */ | ||
412 | static void | ||
413 | bfa_lps_free(struct bfa_lps_s *lps) | ||
414 | { | ||
415 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(lps->bfa); | ||
416 | |||
417 | list_del(&lps->qe); | ||
418 | list_add_tail(&lps->qe, &mod->lps_free_q); | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * send login request to firmware | ||
423 | */ | ||
424 | static void | ||
425 | bfa_lps_send_login(struct bfa_lps_s *lps) | ||
426 | { | ||
427 | struct bfi_lps_login_req_s *m; | ||
428 | |||
429 | m = bfa_reqq_next(lps->bfa, lps->reqq); | ||
430 | bfa_assert(m); | ||
431 | |||
432 | bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGIN_REQ, | ||
433 | bfa_lpuid(lps->bfa)); | ||
434 | |||
435 | m->lp_tag = lps->lp_tag; | ||
436 | m->alpa = lps->alpa; | ||
437 | m->pdu_size = bfa_os_htons(lps->pdusz); | ||
438 | m->pwwn = lps->pwwn; | ||
439 | m->nwwn = lps->nwwn; | ||
440 | m->fdisc = lps->fdisc; | ||
441 | m->auth_en = lps->auth_en; | ||
442 | |||
443 | bfa_reqq_produce(lps->bfa, lps->reqq); | ||
444 | } | ||
445 | |||
446 | /** | ||
447 | * send logout request to firmware | ||
448 | */ | ||
449 | static void | ||
450 | bfa_lps_send_logout(struct bfa_lps_s *lps) | ||
451 | { | ||
452 | struct bfi_lps_logout_req_s *m; | ||
453 | |||
454 | m = bfa_reqq_next(lps->bfa, lps->reqq); | ||
455 | bfa_assert(m); | ||
456 | |||
457 | bfi_h2i_set(m->mh, BFI_MC_LPS, BFI_LPS_H2I_LOGOUT_REQ, | ||
458 | bfa_lpuid(lps->bfa)); | ||
459 | |||
460 | m->lp_tag = lps->lp_tag; | ||
461 | m->port_name = lps->pwwn; | ||
462 | bfa_reqq_produce(lps->bfa, lps->reqq); | ||
463 | } | ||
464 | |||
465 | /** | ||
466 | * Indirect login completion handler for non-fcs | ||
467 | */ | ||
468 | static void | ||
469 | bfa_lps_login_comp_cb(void *arg, bfa_boolean_t complete) | ||
470 | { | ||
471 | struct bfa_lps_s *lps = arg; | ||
472 | |||
473 | if (!complete) | ||
474 | return; | ||
475 | |||
476 | if (lps->fdisc) | ||
477 | bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
478 | else | ||
479 | bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * Login completion handler -- direct call for fcs, queue for others | ||
484 | */ | ||
485 | static void | ||
486 | bfa_lps_login_comp(struct bfa_lps_s *lps) | ||
487 | { | ||
488 | if (!lps->bfa->fcs) { | ||
489 | bfa_cb_queue(lps->bfa, &lps->hcb_qe, | ||
490 | bfa_lps_login_comp_cb, lps); | ||
491 | return; | ||
492 | } | ||
493 | |||
494 | if (lps->fdisc) | ||
495 | bfa_cb_lps_fdisc_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
496 | else | ||
497 | bfa_cb_lps_flogi_comp(lps->bfa->bfad, lps->uarg, lps->status); | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * Indirect logout completion handler for non-fcs | ||
502 | */ | ||
503 | static void | ||
504 | bfa_lps_logout_comp_cb(void *arg, bfa_boolean_t complete) | ||
505 | { | ||
506 | struct bfa_lps_s *lps = arg; | ||
507 | |||
508 | if (!complete) | ||
509 | return; | ||
510 | |||
511 | if (lps->fdisc) | ||
512 | bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg); | ||
513 | else | ||
514 | bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg); | ||
515 | } | ||
516 | |||
517 | /** | ||
518 | * Logout completion handler -- direct call for fcs, queue for others | ||
519 | */ | ||
520 | static void | ||
521 | bfa_lps_logout_comp(struct bfa_lps_s *lps) | ||
522 | { | ||
523 | if (!lps->bfa->fcs) { | ||
524 | bfa_cb_queue(lps->bfa, &lps->hcb_qe, | ||
525 | bfa_lps_logout_comp_cb, lps); | ||
526 | return; | ||
527 | } | ||
528 | if (lps->fdisc) | ||
529 | bfa_cb_lps_fdisclogo_comp(lps->bfa->bfad, lps->uarg); | ||
530 | else | ||
531 | bfa_cb_lps_flogo_comp(lps->bfa->bfad, lps->uarg); | ||
532 | } | ||
533 | |||
534 | |||
535 | |||
536 | /** | ||
537 | * lps_public BFA LPS public functions | ||
538 | */ | ||
539 | |||
540 | /** | ||
541 | * Allocate a lport srvice tag. | ||
542 | */ | ||
543 | struct bfa_lps_s * | ||
544 | bfa_lps_alloc(struct bfa_s *bfa) | ||
545 | { | ||
546 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
547 | struct bfa_lps_s *lps = NULL; | ||
548 | |||
549 | bfa_q_deq(&mod->lps_free_q, &lps); | ||
550 | |||
551 | if (lps == NULL) | ||
552 | return NULL; | ||
553 | |||
554 | list_add_tail(&lps->qe, &mod->lps_active_q); | ||
555 | |||
556 | bfa_sm_set_state(lps, bfa_lps_sm_init); | ||
557 | return lps; | ||
558 | } | ||
559 | |||
560 | /** | ||
561 | * Free lport service tag. This can be called anytime after an alloc. | ||
562 | * No need to wait for any pending login/logout completions. | ||
563 | */ | ||
564 | void | ||
565 | bfa_lps_delete(struct bfa_lps_s *lps) | ||
566 | { | ||
567 | bfa_sm_send_event(lps, BFA_LPS_SM_DELETE); | ||
568 | } | ||
569 | |||
570 | /** | ||
571 | * Initiate a lport login. | ||
572 | */ | ||
573 | void | ||
574 | bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, | ||
575 | wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en) | ||
576 | { | ||
577 | lps->uarg = uarg; | ||
578 | lps->alpa = alpa; | ||
579 | lps->pdusz = pdusz; | ||
580 | lps->pwwn = pwwn; | ||
581 | lps->nwwn = nwwn; | ||
582 | lps->fdisc = BFA_FALSE; | ||
583 | lps->auth_en = auth_en; | ||
584 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN); | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * Initiate a lport fdisc login. | ||
589 | */ | ||
590 | void | ||
591 | bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, | ||
592 | wwn_t nwwn) | ||
593 | { | ||
594 | lps->uarg = uarg; | ||
595 | lps->alpa = 0; | ||
596 | lps->pdusz = pdusz; | ||
597 | lps->pwwn = pwwn; | ||
598 | lps->nwwn = nwwn; | ||
599 | lps->fdisc = BFA_TRUE; | ||
600 | lps->auth_en = BFA_FALSE; | ||
601 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGIN); | ||
602 | } | ||
603 | |||
604 | /** | ||
605 | * Initiate a lport logout (flogi). | ||
606 | */ | ||
607 | void | ||
608 | bfa_lps_flogo(struct bfa_lps_s *lps) | ||
609 | { | ||
610 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT); | ||
611 | } | ||
612 | |||
613 | /** | ||
614 | * Initiate a lport FDSIC logout. | ||
615 | */ | ||
616 | void | ||
617 | bfa_lps_fdisclogo(struct bfa_lps_s *lps) | ||
618 | { | ||
619 | bfa_sm_send_event(lps, BFA_LPS_SM_LOGOUT); | ||
620 | } | ||
621 | |||
622 | /** | ||
623 | * Discard a pending login request -- should be called only for | ||
624 | * link down handling. | ||
625 | */ | ||
626 | void | ||
627 | bfa_lps_discard(struct bfa_lps_s *lps) | ||
628 | { | ||
629 | bfa_sm_send_event(lps, BFA_LPS_SM_OFFLINE); | ||
630 | } | ||
631 | |||
632 | /** | ||
633 | * Return lport services tag | ||
634 | */ | ||
635 | u8 | ||
636 | bfa_lps_get_tag(struct bfa_lps_s *lps) | ||
637 | { | ||
638 | return lps->lp_tag; | ||
639 | } | ||
640 | |||
641 | /** | ||
642 | * Return lport services tag given the pid | ||
643 | */ | ||
644 | u8 | ||
645 | bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid) | ||
646 | { | ||
647 | struct bfa_lps_mod_s *mod = BFA_LPS_MOD(bfa); | ||
648 | struct bfa_lps_s *lps; | ||
649 | int i; | ||
650 | |||
651 | for (i = 0, lps = mod->lps_arr; i < mod->num_lps; i++, lps++) { | ||
652 | if (lps->lp_pid == pid) | ||
653 | return lps->lp_tag; | ||
654 | } | ||
655 | |||
656 | /* Return base port tag anyway */ | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | /** | ||
661 | * return if fabric login indicates support for NPIV | ||
662 | */ | ||
663 | bfa_boolean_t | ||
664 | bfa_lps_is_npiv_en(struct bfa_lps_s *lps) | ||
665 | { | ||
666 | return lps->npiv_en; | ||
667 | } | ||
668 | |||
669 | /** | ||
670 | * Return TRUE if attached to F-Port, else return FALSE | ||
671 | */ | ||
672 | bfa_boolean_t | ||
673 | bfa_lps_is_fport(struct bfa_lps_s *lps) | ||
674 | { | ||
675 | return lps->fport; | ||
676 | } | ||
677 | |||
678 | /** | ||
679 | * Return TRUE if attached to a Brocade Fabric | ||
680 | */ | ||
681 | bfa_boolean_t | ||
682 | bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps) | ||
683 | { | ||
684 | return lps->brcd_switch; | ||
685 | } | ||
686 | /** | ||
687 | * return TRUE if authentication is required | ||
688 | */ | ||
689 | bfa_boolean_t | ||
690 | bfa_lps_is_authreq(struct bfa_lps_s *lps) | ||
691 | { | ||
692 | return lps->auth_req; | ||
693 | } | ||
694 | |||
695 | bfa_eproto_status_t | ||
696 | bfa_lps_get_extstatus(struct bfa_lps_s *lps) | ||
697 | { | ||
698 | return lps->ext_status; | ||
699 | } | ||
700 | |||
701 | /** | ||
702 | * return port id assigned to the lport | ||
703 | */ | ||
704 | u32 | ||
705 | bfa_lps_get_pid(struct bfa_lps_s *lps) | ||
706 | { | ||
707 | return lps->lp_pid; | ||
708 | } | ||
709 | |||
710 | /** | ||
711 | * Return bb_credit assigned in FLOGI response | ||
712 | */ | ||
713 | u16 | ||
714 | bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps) | ||
715 | { | ||
716 | return lps->pr_bbcred; | ||
717 | } | ||
718 | |||
719 | /** | ||
720 | * Return peer port name | ||
721 | */ | ||
722 | wwn_t | ||
723 | bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps) | ||
724 | { | ||
725 | return lps->pr_pwwn; | ||
726 | } | ||
727 | |||
728 | /** | ||
729 | * Return peer node name | ||
730 | */ | ||
731 | wwn_t | ||
732 | bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps) | ||
733 | { | ||
734 | return lps->pr_nwwn; | ||
735 | } | ||
736 | |||
737 | /** | ||
738 | * return reason code if login request is rejected | ||
739 | */ | ||
740 | u8 | ||
741 | bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps) | ||
742 | { | ||
743 | return lps->lsrjt_rsn; | ||
744 | } | ||
745 | |||
746 | /** | ||
747 | * return explanation code if login request is rejected | ||
748 | */ | ||
749 | u8 | ||
750 | bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps) | ||
751 | { | ||
752 | return lps->lsrjt_expl; | ||
753 | } | ||
754 | |||
755 | |||
756 | /** | ||
757 | * LPS firmware message class handler. | ||
758 | */ | ||
759 | void | ||
760 | bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
761 | { | ||
762 | union bfi_lps_i2h_msg_u msg; | ||
763 | |||
764 | bfa_trc(bfa, m->mhdr.msg_id); | ||
765 | msg.msg = m; | ||
766 | |||
767 | switch (m->mhdr.msg_id) { | ||
768 | case BFI_LPS_H2I_LOGIN_RSP: | ||
769 | bfa_lps_login_rsp(bfa, msg.login_rsp); | ||
770 | break; | ||
771 | |||
772 | case BFI_LPS_H2I_LOGOUT_RSP: | ||
773 | bfa_lps_logout_rsp(bfa, msg.logout_rsp); | ||
774 | break; | ||
775 | |||
776 | default: | ||
777 | bfa_trc(bfa, m->mhdr.msg_id); | ||
778 | bfa_assert(0); | ||
779 | } | ||
780 | } | ||
781 | |||
782 | |||
diff --git a/drivers/scsi/bfa/bfa_lps_priv.h b/drivers/scsi/bfa/bfa_lps_priv.h new file mode 100644 index 000000000000..d16c6ce995df --- /dev/null +++ b/drivers/scsi/bfa/bfa_lps_priv.h | |||
@@ -0,0 +1,38 @@ | |||
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 | #ifndef __BFA_LPS_PRIV_H__ | ||
19 | #define __BFA_LPS_PRIV_H__ | ||
20 | |||
21 | #include <bfa_svc.h> | ||
22 | |||
23 | struct bfa_lps_mod_s { | ||
24 | struct list_head lps_free_q; | ||
25 | struct list_head lps_active_q; | ||
26 | struct bfa_lps_s *lps_arr; | ||
27 | int num_lps; | ||
28 | }; | ||
29 | |||
30 | #define BFA_LPS_MOD(__bfa) (&(__bfa)->modules.lps_mod) | ||
31 | #define BFA_LPS_FROM_TAG(__mod, __tag) (&(__mod)->lps_arr[__tag]) | ||
32 | |||
33 | /* | ||
34 | * external functions | ||
35 | */ | ||
36 | void bfa_lps_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
37 | |||
38 | #endif /* __BFA_LPS_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_module.c b/drivers/scsi/bfa/bfa_module.c new file mode 100644 index 000000000000..32eda8e1ec65 --- /dev/null +++ b/drivers/scsi/bfa/bfa_module.c | |||
@@ -0,0 +1,90 @@ | |||
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 | #include <bfa.h> | ||
18 | #include <defs/bfa_defs_pci.h> | ||
19 | #include <cs/bfa_debug.h> | ||
20 | #include <bfa_iocfc.h> | ||
21 | |||
22 | /** | ||
23 | * BFA module list terminated by NULL | ||
24 | */ | ||
25 | struct bfa_module_s *hal_mods[] = { | ||
26 | &hal_mod_sgpg, | ||
27 | &hal_mod_pport, | ||
28 | &hal_mod_fcxp, | ||
29 | &hal_mod_lps, | ||
30 | &hal_mod_uf, | ||
31 | &hal_mod_rport, | ||
32 | &hal_mod_fcpim, | ||
33 | #ifdef BFA_CFG_PBIND | ||
34 | &hal_mod_pbind, | ||
35 | #endif | ||
36 | NULL | ||
37 | }; | ||
38 | |||
39 | /** | ||
40 | * Message handlers for various modules. | ||
41 | */ | ||
42 | bfa_isr_func_t bfa_isrs[BFI_MC_MAX] = { | ||
43 | bfa_isr_unhandled, /* NONE */ | ||
44 | bfa_isr_unhandled, /* BFI_MC_IOC */ | ||
45 | bfa_isr_unhandled, /* BFI_MC_DIAG */ | ||
46 | bfa_isr_unhandled, /* BFI_MC_FLASH */ | ||
47 | bfa_isr_unhandled, /* BFI_MC_CEE */ | ||
48 | bfa_pport_isr, /* BFI_MC_PORT */ | ||
49 | bfa_isr_unhandled, /* BFI_MC_IOCFC */ | ||
50 | bfa_isr_unhandled, /* BFI_MC_LL */ | ||
51 | bfa_uf_isr, /* BFI_MC_UF */ | ||
52 | bfa_fcxp_isr, /* BFI_MC_FCXP */ | ||
53 | bfa_lps_isr, /* BFI_MC_LPS */ | ||
54 | bfa_rport_isr, /* BFI_MC_RPORT */ | ||
55 | bfa_itnim_isr, /* BFI_MC_ITNIM */ | ||
56 | bfa_isr_unhandled, /* BFI_MC_IOIM_READ */ | ||
57 | bfa_isr_unhandled, /* BFI_MC_IOIM_WRITE */ | ||
58 | bfa_isr_unhandled, /* BFI_MC_IOIM_IO */ | ||
59 | bfa_ioim_isr, /* BFI_MC_IOIM */ | ||
60 | bfa_ioim_good_comp_isr, /* BFI_MC_IOIM_IOCOM */ | ||
61 | bfa_tskim_isr, /* BFI_MC_TSKIM */ | ||
62 | bfa_isr_unhandled, /* BFI_MC_SBOOT */ | ||
63 | bfa_isr_unhandled, /* BFI_MC_IPFC */ | ||
64 | bfa_isr_unhandled, /* BFI_MC_PORT */ | ||
65 | bfa_isr_unhandled, /* --------- */ | ||
66 | bfa_isr_unhandled, /* --------- */ | ||
67 | bfa_isr_unhandled, /* --------- */ | ||
68 | bfa_isr_unhandled, /* --------- */ | ||
69 | bfa_isr_unhandled, /* --------- */ | ||
70 | bfa_isr_unhandled, /* --------- */ | ||
71 | bfa_isr_unhandled, /* --------- */ | ||
72 | bfa_isr_unhandled, /* --------- */ | ||
73 | bfa_isr_unhandled, /* --------- */ | ||
74 | bfa_isr_unhandled, /* --------- */ | ||
75 | }; | ||
76 | |||
77 | /** | ||
78 | * Message handlers for mailbox command classes | ||
79 | */ | ||
80 | bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[BFI_MC_MAX] = { | ||
81 | NULL, | ||
82 | NULL, /* BFI_MC_IOC */ | ||
83 | NULL, /* BFI_MC_DIAG */ | ||
84 | NULL, /* BFI_MC_FLASH */ | ||
85 | NULL, /* BFI_MC_CEE */ | ||
86 | NULL, /* BFI_MC_PORT */ | ||
87 | bfa_iocfc_isr, /* BFI_MC_IOCFC */ | ||
88 | NULL, | ||
89 | }; | ||
90 | |||
diff --git a/drivers/scsi/bfa/bfa_modules_priv.h b/drivers/scsi/bfa/bfa_modules_priv.h new file mode 100644 index 000000000000..96f70534593c --- /dev/null +++ b/drivers/scsi/bfa/bfa_modules_priv.h | |||
@@ -0,0 +1,43 @@ | |||
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 | #ifndef __BFA_MODULES_PRIV_H__ | ||
19 | #define __BFA_MODULES_PRIV_H__ | ||
20 | |||
21 | #include "bfa_uf_priv.h" | ||
22 | #include "bfa_port_priv.h" | ||
23 | #include "bfa_rport_priv.h" | ||
24 | #include "bfa_fcxp_priv.h" | ||
25 | #include "bfa_lps_priv.h" | ||
26 | #include "bfa_fcpim_priv.h" | ||
27 | #include <cee/bfa_cee.h> | ||
28 | #include <port/bfa_port.h> | ||
29 | |||
30 | |||
31 | struct bfa_modules_s { | ||
32 | struct bfa_pport_s pport; /* physical port module */ | ||
33 | struct bfa_fcxp_mod_s fcxp_mod; /* fcxp module */ | ||
34 | struct bfa_lps_mod_s lps_mod; /* fcxp module */ | ||
35 | struct bfa_uf_mod_s uf_mod; /* unsolicited frame module */ | ||
36 | struct bfa_rport_mod_s rport_mod; /* remote port module */ | ||
37 | struct bfa_fcpim_mod_s fcpim_mod; /* FCP initiator module */ | ||
38 | struct bfa_sgpg_mod_s sgpg_mod; /* SG page module */ | ||
39 | struct bfa_cee_s cee; /* CEE Module */ | ||
40 | struct bfa_port_s port; /* Physical port module */ | ||
41 | }; | ||
42 | |||
43 | #endif /* __BFA_MODULES_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_os_inc.h b/drivers/scsi/bfa/bfa_os_inc.h new file mode 100644 index 000000000000..10a89f75fa94 --- /dev/null +++ b/drivers/scsi/bfa/bfa_os_inc.h | |||
@@ -0,0 +1,222 @@ | |||
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 | * Contains declarations all OS Specific files needed for BFA layer | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_OS_INC_H__ | ||
23 | #define __BFA_OS_INC_H__ | ||
24 | |||
25 | #ifndef __KERNEL__ | ||
26 | #include <stdint.h> | ||
27 | #else | ||
28 | #include <linux/types.h> | ||
29 | |||
30 | #include <linux/version.h> | ||
31 | #include <linux/pci.h> | ||
32 | |||
33 | #include <linux/dma-mapping.h> | ||
34 | #define SET_MODULE_VERSION(VER) | ||
35 | |||
36 | #include <linux/idr.h> | ||
37 | |||
38 | #include <linux/interrupt.h> | ||
39 | #include <linux/cdev.h> | ||
40 | #include <linux/fs.h> | ||
41 | #include <linux/delay.h> | ||
42 | #include <linux/vmalloc.h> | ||
43 | |||
44 | #include <linux/workqueue.h> | ||
45 | |||
46 | #include <scsi/scsi.h> | ||
47 | #include <scsi/scsi_host.h> | ||
48 | |||
49 | #include <scsi/scsi_tcq.h> | ||
50 | #include <scsi/scsi_transport_fc.h> | ||
51 | #include <scsi/scsi_transport.h> | ||
52 | |||
53 | #define BFA_ERR KERN_ERR | ||
54 | #define BFA_WARNING KERN_WARNING | ||
55 | #define BFA_NOTICE KERN_NOTICE | ||
56 | #define BFA_INFO KERN_INFO | ||
57 | #define BFA_DEBUG KERN_DEBUG | ||
58 | |||
59 | #define LOG_BFAD_INIT 0x00000001 | ||
60 | #define LOG_FCP_IO 0x00000002 | ||
61 | |||
62 | #ifdef DEBUG | ||
63 | #define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...) \ | ||
64 | BFA_LOG(bfad, level, mask, fmt, ## arg) | ||
65 | #define BFA_DEV_TRACE(bfad, level, fmt, arg...) \ | ||
66 | BFA_DEV_PRINTF(bfad, level, fmt, ## arg) | ||
67 | #define BFA_TRACE(level, fmt, arg...) \ | ||
68 | BFA_PRINTF(level, fmt, ## arg) | ||
69 | #else | ||
70 | #define BFA_LOG_TRACE(bfad, level, mask, fmt, arg...) | ||
71 | #define BFA_DEV_TRACE(bfad, level, fmt, arg...) | ||
72 | #define BFA_TRACE(level, fmt, arg...) | ||
73 | #endif | ||
74 | |||
75 | #define BFA_ASSERT(p) do { \ | ||
76 | if (!(p)) { \ | ||
77 | printk(KERN_ERR "assert(%s) failed at %s:%d\n", \ | ||
78 | #p, __FILE__, __LINE__); \ | ||
79 | BUG(); \ | ||
80 | } \ | ||
81 | } while (0) | ||
82 | |||
83 | |||
84 | #define BFA_LOG(bfad, level, mask, fmt, arg...) \ | ||
85 | do { \ | ||
86 | if (((mask) & (((struct bfad_s *)(bfad))-> \ | ||
87 | cfg_data[cfg_log_mask])) || (level[1] <= '3')) \ | ||
88 | dev_printk(level, &(((struct bfad_s *) \ | ||
89 | (bfad))->pcidev->dev), fmt, ##arg); \ | ||
90 | } while (0) | ||
91 | |||
92 | #ifndef BFA_DEV_PRINTF | ||
93 | #define BFA_DEV_PRINTF(bfad, level, fmt, arg...) \ | ||
94 | dev_printk(level, &(((struct bfad_s *) \ | ||
95 | (bfad))->pcidev->dev), fmt, ##arg); | ||
96 | #endif | ||
97 | |||
98 | #define BFA_PRINTF(level, fmt, arg...) \ | ||
99 | printk(level fmt, ##arg); | ||
100 | |||
101 | int bfa_os_MWB(void *); | ||
102 | |||
103 | #define bfa_os_mmiowb() mmiowb() | ||
104 | |||
105 | #define bfa_swap_3b(_x) \ | ||
106 | ((((_x) & 0xff) << 16) | \ | ||
107 | ((_x) & 0x00ff00) | \ | ||
108 | (((_x) & 0xff0000) >> 16)) | ||
109 | |||
110 | #define bfa_swap_8b(_x) \ | ||
111 | ((((_x) & 0xff00000000000000ull) >> 56) \ | ||
112 | | (((_x) & 0x00ff000000000000ull) >> 40) \ | ||
113 | | (((_x) & 0x0000ff0000000000ull) >> 24) \ | ||
114 | | (((_x) & 0x000000ff00000000ull) >> 8) \ | ||
115 | | (((_x) & 0x00000000ff000000ull) << 8) \ | ||
116 | | (((_x) & 0x0000000000ff0000ull) << 24) \ | ||
117 | | (((_x) & 0x000000000000ff00ull) << 40) \ | ||
118 | | (((_x) & 0x00000000000000ffull) << 56)) | ||
119 | |||
120 | #define bfa_os_swap32(_x) \ | ||
121 | ((((_x) & 0xff) << 24) | \ | ||
122 | (((_x) & 0x0000ff00) << 8) | \ | ||
123 | (((_x) & 0x00ff0000) >> 8) | \ | ||
124 | (((_x) & 0xff000000) >> 24)) | ||
125 | |||
126 | |||
127 | #ifndef __BIGENDIAN | ||
128 | #define bfa_os_htons(_x) ((u16)((((_x) & 0xff00) >> 8) | \ | ||
129 | (((_x) & 0x00ff) << 8))) | ||
130 | |||
131 | #define bfa_os_htonl(_x) bfa_os_swap32(_x) | ||
132 | #define bfa_os_htonll(_x) bfa_swap_8b(_x) | ||
133 | #define bfa_os_hton3b(_x) bfa_swap_3b(_x) | ||
134 | |||
135 | #define bfa_os_wtole(_x) (_x) | ||
136 | |||
137 | #else | ||
138 | |||
139 | #define bfa_os_htons(_x) (_x) | ||
140 | #define bfa_os_htonl(_x) (_x) | ||
141 | #define bfa_os_hton3b(_x) (_x) | ||
142 | #define bfa_os_htonll(_x) (_x) | ||
143 | #define bfa_os_wtole(_x) bfa_os_swap32(_x) | ||
144 | |||
145 | #endif | ||
146 | |||
147 | #define bfa_os_ntohs(_x) bfa_os_htons(_x) | ||
148 | #define bfa_os_ntohl(_x) bfa_os_htonl(_x) | ||
149 | #define bfa_os_ntohll(_x) bfa_os_htonll(_x) | ||
150 | #define bfa_os_ntoh3b(_x) bfa_os_hton3b(_x) | ||
151 | |||
152 | #define bfa_os_u32(__pa64) ((__pa64) >> 32) | ||
153 | |||
154 | #define bfa_os_memset memset | ||
155 | #define bfa_os_memcpy memcpy | ||
156 | #define bfa_os_udelay udelay | ||
157 | #define bfa_os_vsprintf vsprintf | ||
158 | |||
159 | #define bfa_os_assign(__t, __s) __t = __s | ||
160 | |||
161 | #define bfa_os_addr_t char __iomem * | ||
162 | #define bfa_os_panic() | ||
163 | |||
164 | #define bfa_os_reg_read(_raddr) bfa_os_wtole(readl(_raddr)) | ||
165 | #define bfa_os_reg_write(_raddr, _val) writel(bfa_os_wtole((_val)), (_raddr)) | ||
166 | #define bfa_os_mem_read(_raddr, _off) \ | ||
167 | bfa_os_ntohl(readl(((_raddr) + (_off)))) | ||
168 | #define bfa_os_mem_write(_raddr, _off, _val) \ | ||
169 | writel(bfa_os_htonl((_val)), ((_raddr) + (_off))) | ||
170 | |||
171 | #define BFA_TRC_TS(_trcm) \ | ||
172 | ({ \ | ||
173 | struct timeval tv; \ | ||
174 | \ | ||
175 | do_gettimeofday(&tv); \ | ||
176 | (tv.tv_sec*1000000+tv.tv_usec); \ | ||
177 | }) | ||
178 | |||
179 | struct bfa_log_mod_s; | ||
180 | void bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id, | ||
181 | const char *fmt, ...); | ||
182 | #endif | ||
183 | |||
184 | #define boolean_t int | ||
185 | |||
186 | /** | ||
187 | * For current time stamp, OS API will fill-in | ||
188 | */ | ||
189 | struct bfa_timeval_s { | ||
190 | u32 tv_sec; /* seconds */ | ||
191 | u32 tv_usec; /* microseconds */ | ||
192 | }; | ||
193 | |||
194 | void bfa_os_gettimeofday(struct bfa_timeval_s *tv); | ||
195 | |||
196 | static inline void | ||
197 | wwn2str(char *wwn_str, u64 wwn) | ||
198 | { | ||
199 | union { | ||
200 | u64 wwn; | ||
201 | u8 byte[8]; | ||
202 | } w; | ||
203 | |||
204 | w.wwn = wwn; | ||
205 | sprintf(wwn_str, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", w.byte[0], | ||
206 | w.byte[1], w.byte[2], w.byte[3], w.byte[4], w.byte[5], | ||
207 | w.byte[6], w.byte[7]); | ||
208 | } | ||
209 | |||
210 | static inline void | ||
211 | fcid2str(char *fcid_str, u32 fcid) | ||
212 | { | ||
213 | union { | ||
214 | u32 fcid; | ||
215 | u8 byte[4]; | ||
216 | } f; | ||
217 | |||
218 | f.fcid = fcid; | ||
219 | sprintf(fcid_str, "%02x:%02x:%02x", f.byte[1], f.byte[2], f.byte[3]); | ||
220 | } | ||
221 | |||
222 | #endif /* __BFA_OS_INC_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_port.c b/drivers/scsi/bfa/bfa_port.c new file mode 100644 index 000000000000..cab19028361a --- /dev/null +++ b/drivers/scsi/bfa/bfa_port.c | |||
@@ -0,0 +1,460 @@ | |||
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 | #include <defs/bfa_defs_port.h> | ||
19 | #include <cs/bfa_trc.h> | ||
20 | #include <cs/bfa_log.h> | ||
21 | #include <cs/bfa_debug.h> | ||
22 | #include <port/bfa_port.h> | ||
23 | #include <bfi/bfi.h> | ||
24 | #include <bfi/bfi_port.h> | ||
25 | #include <bfa_ioc.h> | ||
26 | #include <cna/bfa_cna_trcmod.h> | ||
27 | |||
28 | BFA_TRC_FILE(CNA, PORT); | ||
29 | |||
30 | #define bfa_ioc_portid(__ioc) ((__ioc)->port_id) | ||
31 | #define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc) | ||
32 | |||
33 | static void | ||
34 | bfa_port_stats_swap(struct bfa_port_s *port, union bfa_pport_stats_u *stats) | ||
35 | { | ||
36 | u32 *dip = (u32 *) stats; | ||
37 | u32 t0, t1; | ||
38 | int i; | ||
39 | |||
40 | for (i = 0; i < sizeof(union bfa_pport_stats_u) / sizeof(u32); | ||
41 | i += 2) { | ||
42 | t0 = dip[i]; | ||
43 | t1 = dip[i + 1]; | ||
44 | #ifdef __BIGENDIAN | ||
45 | dip[i] = bfa_os_ntohl(t0); | ||
46 | dip[i + 1] = bfa_os_ntohl(t1); | ||
47 | #else | ||
48 | dip[i] = bfa_os_ntohl(t1); | ||
49 | dip[i + 1] = bfa_os_ntohl(t0); | ||
50 | #endif | ||
51 | } | ||
52 | |||
53 | /** todo | ||
54 | * QoS stats r also swapped as 64bit; that structure also | ||
55 | * has to use 64 bit counters | ||
56 | */ | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * bfa_port_enable_isr() | ||
61 | * | ||
62 | * | ||
63 | * @param[in] port - Pointer to the port module | ||
64 | * status - Return status from the f/w | ||
65 | * | ||
66 | * @return void | ||
67 | */ | ||
68 | static void | ||
69 | bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status) | ||
70 | { | ||
71 | bfa_assert(0); | ||
72 | } | ||
73 | |||
74 | /** | ||
75 | * bfa_port_disable_isr() | ||
76 | * | ||
77 | * | ||
78 | * @param[in] port - Pointer to the port module | ||
79 | * status - Return status from the f/w | ||
80 | * | ||
81 | * @return void | ||
82 | */ | ||
83 | static void | ||
84 | bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status) | ||
85 | { | ||
86 | bfa_assert(0); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * bfa_port_get_stats_isr() | ||
91 | * | ||
92 | * | ||
93 | * @param[in] port - Pointer to the Port module | ||
94 | * status - Return status from the f/w | ||
95 | * | ||
96 | * @return void | ||
97 | */ | ||
98 | static void | ||
99 | bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status) | ||
100 | { | ||
101 | port->stats_status = status; | ||
102 | port->stats_busy = BFA_FALSE; | ||
103 | |||
104 | if (status == BFA_STATUS_OK) { | ||
105 | memcpy(port->stats, port->stats_dma.kva, | ||
106 | sizeof(union bfa_pport_stats_u)); | ||
107 | bfa_port_stats_swap(port, port->stats); | ||
108 | } | ||
109 | |||
110 | if (port->stats_cbfn) { | ||
111 | port->stats_cbfn(port->stats_cbarg, status); | ||
112 | port->stats_cbfn = NULL; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * bfa_port_clear_stats_isr() | ||
118 | * | ||
119 | * | ||
120 | * @param[in] port - Pointer to the Port module | ||
121 | * status - Return status from the f/w | ||
122 | * | ||
123 | * @return void | ||
124 | */ | ||
125 | static void | ||
126 | bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status) | ||
127 | { | ||
128 | port->stats_status = status; | ||
129 | port->stats_busy = BFA_FALSE; | ||
130 | |||
131 | if (port->stats_cbfn) { | ||
132 | port->stats_cbfn(port->stats_cbarg, status); | ||
133 | port->stats_cbfn = NULL; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /** | ||
138 | * bfa_port_isr() | ||
139 | * | ||
140 | * | ||
141 | * @param[in] Pointer to the Port module data structure. | ||
142 | * | ||
143 | * @return void | ||
144 | */ | ||
145 | static void | ||
146 | bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m) | ||
147 | { | ||
148 | struct bfa_port_s *port = (struct bfa_port_s *)cbarg; | ||
149 | union bfi_port_i2h_msg_u *i2hmsg; | ||
150 | |||
151 | i2hmsg = (union bfi_port_i2h_msg_u *)m; | ||
152 | bfa_trc(port, m->mh.msg_id); | ||
153 | |||
154 | switch (m->mh.msg_id) { | ||
155 | case BFI_PORT_I2H_ENABLE_RSP: | ||
156 | if (port->endis_pending == BFA_FALSE) | ||
157 | break; | ||
158 | bfa_port_enable_isr(port, i2hmsg->enable_rsp.status); | ||
159 | break; | ||
160 | |||
161 | case BFI_PORT_I2H_DISABLE_RSP: | ||
162 | if (port->endis_pending == BFA_FALSE) | ||
163 | break; | ||
164 | bfa_port_disable_isr(port, i2hmsg->disable_rsp.status); | ||
165 | break; | ||
166 | |||
167 | case BFI_PORT_I2H_GET_STATS_RSP: | ||
168 | /* | ||
169 | * Stats busy flag is still set? (may be cmd timed out) | ||
170 | */ | ||
171 | if (port->stats_busy == BFA_FALSE) | ||
172 | break; | ||
173 | bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status); | ||
174 | break; | ||
175 | |||
176 | case BFI_PORT_I2H_CLEAR_STATS_RSP: | ||
177 | if (port->stats_busy == BFA_FALSE) | ||
178 | break; | ||
179 | bfa_port_clear_stats_isr(port, i2hmsg->clearstats_rsp.status); | ||
180 | break; | ||
181 | |||
182 | default: | ||
183 | bfa_assert(0); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /** | ||
188 | * bfa_port_meminfo() | ||
189 | * | ||
190 | * | ||
191 | * @param[in] void | ||
192 | * | ||
193 | * @return Size of DMA region | ||
194 | */ | ||
195 | u32 | ||
196 | bfa_port_meminfo(void) | ||
197 | { | ||
198 | return BFA_ROUNDUP(sizeof(union bfa_pport_stats_u), BFA_DMA_ALIGN_SZ); | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * bfa_port_mem_claim() | ||
203 | * | ||
204 | * | ||
205 | * @param[in] port Port module pointer | ||
206 | * dma_kva Kernel Virtual Address of Port DMA Memory | ||
207 | * dma_pa Physical Address of Port DMA Memory | ||
208 | * | ||
209 | * @return void | ||
210 | */ | ||
211 | void | ||
212 | bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa) | ||
213 | { | ||
214 | port->stats_dma.kva = dma_kva; | ||
215 | port->stats_dma.pa = dma_pa; | ||
216 | } | ||
217 | |||
218 | /** | ||
219 | * bfa_port_enable() | ||
220 | * | ||
221 | * Send the Port enable request to the f/w | ||
222 | * | ||
223 | * @param[in] Pointer to the Port module data structure. | ||
224 | * | ||
225 | * @return Status | ||
226 | */ | ||
227 | bfa_status_t | ||
228 | bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn, | ||
229 | void *cbarg) | ||
230 | { | ||
231 | struct bfi_port_generic_req_s *m; | ||
232 | |||
233 | /** todo Not implemented */ | ||
234 | bfa_assert(0); | ||
235 | |||
236 | if (!bfa_ioc_is_operational(port->ioc)) { | ||
237 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | ||
238 | return BFA_STATUS_IOC_FAILURE; | ||
239 | } | ||
240 | |||
241 | if (port->endis_pending) { | ||
242 | bfa_trc(port, BFA_STATUS_DEVBUSY); | ||
243 | return BFA_STATUS_DEVBUSY; | ||
244 | } | ||
245 | |||
246 | m = (struct bfi_port_generic_req_s *)port->endis_mb.msg; | ||
247 | |||
248 | port->msgtag++; | ||
249 | port->endis_cbfn = cbfn; | ||
250 | port->endis_cbarg = cbarg; | ||
251 | port->endis_pending = BFA_TRUE; | ||
252 | |||
253 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ, | ||
254 | bfa_ioc_portid(port->ioc)); | ||
255 | bfa_ioc_mbox_queue(port->ioc, &port->endis_mb); | ||
256 | |||
257 | return BFA_STATUS_OK; | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * bfa_port_disable() | ||
262 | * | ||
263 | * Send the Port disable request to the f/w | ||
264 | * | ||
265 | * @param[in] Pointer to the Port module data structure. | ||
266 | * | ||
267 | * @return Status | ||
268 | */ | ||
269 | bfa_status_t | ||
270 | bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn, | ||
271 | void *cbarg) | ||
272 | { | ||
273 | struct bfi_port_generic_req_s *m; | ||
274 | |||
275 | /** todo Not implemented */ | ||
276 | bfa_assert(0); | ||
277 | |||
278 | if (!bfa_ioc_is_operational(port->ioc)) { | ||
279 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | ||
280 | return BFA_STATUS_IOC_FAILURE; | ||
281 | } | ||
282 | |||
283 | if (port->endis_pending) { | ||
284 | bfa_trc(port, BFA_STATUS_DEVBUSY); | ||
285 | return BFA_STATUS_DEVBUSY; | ||
286 | } | ||
287 | |||
288 | m = (struct bfi_port_generic_req_s *)port->endis_mb.msg; | ||
289 | |||
290 | port->msgtag++; | ||
291 | port->endis_cbfn = cbfn; | ||
292 | port->endis_cbarg = cbarg; | ||
293 | port->endis_pending = BFA_TRUE; | ||
294 | |||
295 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ, | ||
296 | bfa_ioc_portid(port->ioc)); | ||
297 | bfa_ioc_mbox_queue(port->ioc, &port->endis_mb); | ||
298 | |||
299 | return BFA_STATUS_OK; | ||
300 | } | ||
301 | |||
302 | /** | ||
303 | * bfa_port_get_stats() | ||
304 | * | ||
305 | * Send the request to the f/w to fetch Port statistics. | ||
306 | * | ||
307 | * @param[in] Pointer to the Port module data structure. | ||
308 | * | ||
309 | * @return Status | ||
310 | */ | ||
311 | bfa_status_t | ||
312 | bfa_port_get_stats(struct bfa_port_s *port, union bfa_pport_stats_u *stats, | ||
313 | bfa_port_stats_cbfn_t cbfn, void *cbarg) | ||
314 | { | ||
315 | struct bfi_port_get_stats_req_s *m; | ||
316 | |||
317 | if (!bfa_ioc_is_operational(port->ioc)) { | ||
318 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | ||
319 | return BFA_STATUS_IOC_FAILURE; | ||
320 | } | ||
321 | |||
322 | if (port->stats_busy) { | ||
323 | bfa_trc(port, BFA_STATUS_DEVBUSY); | ||
324 | return BFA_STATUS_DEVBUSY; | ||
325 | } | ||
326 | |||
327 | m = (struct bfi_port_get_stats_req_s *)port->stats_mb.msg; | ||
328 | |||
329 | port->stats = stats; | ||
330 | port->stats_cbfn = cbfn; | ||
331 | port->stats_cbarg = cbarg; | ||
332 | port->stats_busy = BFA_TRUE; | ||
333 | bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa); | ||
334 | |||
335 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ, | ||
336 | bfa_ioc_portid(port->ioc)); | ||
337 | bfa_ioc_mbox_queue(port->ioc, &port->stats_mb); | ||
338 | |||
339 | return BFA_STATUS_OK; | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * bfa_port_clear_stats() | ||
344 | * | ||
345 | * | ||
346 | * @param[in] Pointer to the Port module data structure. | ||
347 | * | ||
348 | * @return Status | ||
349 | */ | ||
350 | bfa_status_t | ||
351 | bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn, | ||
352 | void *cbarg) | ||
353 | { | ||
354 | struct bfi_port_generic_req_s *m; | ||
355 | |||
356 | if (!bfa_ioc_is_operational(port->ioc)) { | ||
357 | bfa_trc(port, BFA_STATUS_IOC_FAILURE); | ||
358 | return BFA_STATUS_IOC_FAILURE; | ||
359 | } | ||
360 | |||
361 | if (port->stats_busy) { | ||
362 | bfa_trc(port, BFA_STATUS_DEVBUSY); | ||
363 | return BFA_STATUS_DEVBUSY; | ||
364 | } | ||
365 | |||
366 | m = (struct bfi_port_generic_req_s *)port->stats_mb.msg; | ||
367 | |||
368 | port->stats_cbfn = cbfn; | ||
369 | port->stats_cbarg = cbarg; | ||
370 | port->stats_busy = BFA_TRUE; | ||
371 | |||
372 | bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ, | ||
373 | bfa_ioc_portid(port->ioc)); | ||
374 | bfa_ioc_mbox_queue(port->ioc, &port->stats_mb); | ||
375 | |||
376 | return BFA_STATUS_OK; | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * bfa_port_hbfail() | ||
381 | * | ||
382 | * | ||
383 | * @param[in] Pointer to the Port module data structure. | ||
384 | * | ||
385 | * @return void | ||
386 | */ | ||
387 | void | ||
388 | bfa_port_hbfail(void *arg) | ||
389 | { | ||
390 | struct bfa_port_s *port = (struct bfa_port_s *)arg; | ||
391 | |||
392 | /* | ||
393 | * Fail any pending get_stats/clear_stats requests | ||
394 | */ | ||
395 | if (port->stats_busy) { | ||
396 | if (port->stats_cbfn) | ||
397 | port->stats_cbfn(port->dev, BFA_STATUS_FAILED); | ||
398 | port->stats_cbfn = NULL; | ||
399 | port->stats_busy = BFA_FALSE; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * Clear any enable/disable is pending | ||
404 | */ | ||
405 | if (port->endis_pending) { | ||
406 | if (port->endis_cbfn) | ||
407 | port->endis_cbfn(port->dev, BFA_STATUS_FAILED); | ||
408 | port->endis_cbfn = NULL; | ||
409 | port->endis_pending = BFA_FALSE; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * bfa_port_attach() | ||
415 | * | ||
416 | * | ||
417 | * @param[in] port - Pointer to the Port module data structure | ||
418 | * ioc - Pointer to the ioc module data structure | ||
419 | * dev - Pointer to the device driver module data structure | ||
420 | * The device driver specific mbox ISR functions have | ||
421 | * this pointer as one of the parameters. | ||
422 | * trcmod - | ||
423 | * logmod - | ||
424 | * | ||
425 | * @return void | ||
426 | */ | ||
427 | void | ||
428 | bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, void *dev, | ||
429 | struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod) | ||
430 | { | ||
431 | bfa_assert(port); | ||
432 | |||
433 | port->dev = dev; | ||
434 | port->ioc = ioc; | ||
435 | port->trcmod = trcmod; | ||
436 | port->logmod = logmod; | ||
437 | |||
438 | port->stats_busy = port->endis_pending = BFA_FALSE; | ||
439 | port->stats_cbfn = port->endis_cbfn = NULL; | ||
440 | |||
441 | bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port); | ||
442 | bfa_ioc_hbfail_init(&port->hbfail, bfa_port_hbfail, port); | ||
443 | bfa_ioc_hbfail_register(port->ioc, &port->hbfail); | ||
444 | |||
445 | bfa_trc(port, 0); | ||
446 | } | ||
447 | |||
448 | /** | ||
449 | * bfa_port_detach() | ||
450 | * | ||
451 | * | ||
452 | * @param[in] port - Pointer to the Port module data structure | ||
453 | * | ||
454 | * @return void | ||
455 | */ | ||
456 | void | ||
457 | bfa_port_detach(struct bfa_port_s *port) | ||
458 | { | ||
459 | bfa_trc(port, 0); | ||
460 | } | ||
diff --git a/drivers/scsi/bfa/bfa_port_priv.h b/drivers/scsi/bfa/bfa_port_priv.h new file mode 100644 index 000000000000..4b97e2759908 --- /dev/null +++ b/drivers/scsi/bfa/bfa_port_priv.h | |||
@@ -0,0 +1,90 @@ | |||
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 | #ifndef __BFA_PORT_PRIV_H__ | ||
19 | #define __BFA_PORT_PRIV_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_pport.h> | ||
22 | #include <bfi/bfi_pport.h> | ||
23 | #include "bfa_intr_priv.h" | ||
24 | |||
25 | /** | ||
26 | * BFA physical port data structure | ||
27 | */ | ||
28 | struct bfa_pport_s { | ||
29 | struct bfa_s *bfa; /* parent BFA instance */ | ||
30 | bfa_sm_t sm; /* port state machine */ | ||
31 | wwn_t nwwn; /* node wwn of physical port */ | ||
32 | wwn_t pwwn; /* port wwn of physical oprt */ | ||
33 | enum bfa_pport_speed speed_sup; | ||
34 | /* supported speeds */ | ||
35 | enum bfa_pport_speed speed; /* current speed */ | ||
36 | enum bfa_pport_topology topology; /* current topology */ | ||
37 | u8 myalpa; /* my ALPA in LOOP topology */ | ||
38 | u8 rsvd[3]; | ||
39 | struct bfa_pport_cfg_s cfg; /* current port configuration */ | ||
40 | struct bfa_qos_attr_s qos_attr; /* QoS Attributes */ | ||
41 | struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */ | ||
42 | struct bfa_reqq_wait_s reqq_wait; | ||
43 | /* to wait for room in reqq */ | ||
44 | struct bfa_reqq_wait_s svcreq_wait; | ||
45 | /* to wait for room in reqq */ | ||
46 | struct bfa_reqq_wait_s stats_reqq_wait; | ||
47 | /* to wait for room in reqq (stats) */ | ||
48 | void *event_cbarg; | ||
49 | void (*event_cbfn) (void *cbarg, | ||
50 | bfa_pport_event_t event); | ||
51 | union { | ||
52 | union bfi_pport_i2h_msg_u i2hmsg; | ||
53 | } event_arg; | ||
54 | void *bfad; /* BFA driver handle */ | ||
55 | struct bfa_cb_qe_s hcb_qe; /* BFA callback queue elem */ | ||
56 | enum bfa_pport_linkstate hcb_event; | ||
57 | /* link event for callback */ | ||
58 | u32 msgtag; /* fimrware msg tag for reply */ | ||
59 | u8 *stats_kva; | ||
60 | u64 stats_pa; | ||
61 | union bfa_pport_stats_u *stats; /* pport stats */ | ||
62 | u32 mypid : 24; | ||
63 | u32 rsvd_b : 8; | ||
64 | struct bfa_timer_s timer; /* timer */ | ||
65 | union bfa_pport_stats_u *stats_ret; | ||
66 | /* driver stats location */ | ||
67 | bfa_status_t stats_status; | ||
68 | /* stats/statsclr status */ | ||
69 | bfa_boolean_t stats_busy; | ||
70 | /* outstanding stats/statsclr */ | ||
71 | bfa_boolean_t stats_qfull; | ||
72 | bfa_boolean_t diag_busy; | ||
73 | /* diag busy status */ | ||
74 | bfa_boolean_t beacon; | ||
75 | /* port beacon status */ | ||
76 | bfa_boolean_t link_e2e_beacon; | ||
77 | /* link beacon status */ | ||
78 | bfa_cb_pport_t stats_cbfn; | ||
79 | /* driver callback function */ | ||
80 | void *stats_cbarg; | ||
81 | /* *!< user callback arg */ | ||
82 | }; | ||
83 | |||
84 | #define BFA_PORT_MOD(__bfa) (&(__bfa)->modules.pport) | ||
85 | |||
86 | /* | ||
87 | * public functions | ||
88 | */ | ||
89 | void bfa_pport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
90 | #endif /* __BFA_PORT_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_priv.h b/drivers/scsi/bfa/bfa_priv.h new file mode 100644 index 000000000000..0747a6b26f7b --- /dev/null +++ b/drivers/scsi/bfa/bfa_priv.h | |||
@@ -0,0 +1,113 @@ | |||
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 | #ifndef __BFA_PRIV_H__ | ||
19 | #define __BFA_PRIV_H__ | ||
20 | |||
21 | #include "bfa_iocfc.h" | ||
22 | #include "bfa_intr_priv.h" | ||
23 | #include "bfa_trcmod_priv.h" | ||
24 | #include "bfa_modules_priv.h" | ||
25 | #include "bfa_fwimg_priv.h" | ||
26 | #include <cs/bfa_log.h> | ||
27 | #include <bfa_timer.h> | ||
28 | |||
29 | /** | ||
30 | * Macro to define a new BFA module | ||
31 | */ | ||
32 | #define BFA_MODULE(__mod) \ | ||
33 | static void bfa_ ## __mod ## _meminfo( \ | ||
34 | struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, \ | ||
35 | u32 *dm_len); \ | ||
36 | static void bfa_ ## __mod ## _attach(struct bfa_s *bfa, \ | ||
37 | void *bfad, struct bfa_iocfc_cfg_s *cfg, \ | ||
38 | struct bfa_meminfo_s *meminfo, \ | ||
39 | struct bfa_pcidev_s *pcidev); \ | ||
40 | static void bfa_ ## __mod ## _initdone(struct bfa_s *bfa); \ | ||
41 | static void bfa_ ## __mod ## _detach(struct bfa_s *bfa); \ | ||
42 | static void bfa_ ## __mod ## _start(struct bfa_s *bfa); \ | ||
43 | static void bfa_ ## __mod ## _stop(struct bfa_s *bfa); \ | ||
44 | static void bfa_ ## __mod ## _iocdisable(struct bfa_s *bfa); \ | ||
45 | \ | ||
46 | extern struct bfa_module_s hal_mod_ ## __mod; \ | ||
47 | struct bfa_module_s hal_mod_ ## __mod = { \ | ||
48 | bfa_ ## __mod ## _meminfo, \ | ||
49 | bfa_ ## __mod ## _attach, \ | ||
50 | bfa_ ## __mod ## _initdone, \ | ||
51 | bfa_ ## __mod ## _detach, \ | ||
52 | bfa_ ## __mod ## _start, \ | ||
53 | bfa_ ## __mod ## _stop, \ | ||
54 | bfa_ ## __mod ## _iocdisable, \ | ||
55 | } | ||
56 | |||
57 | #define BFA_CACHELINE_SZ (256) | ||
58 | |||
59 | /** | ||
60 | * Structure used to interact between different BFA sub modules | ||
61 | * | ||
62 | * Each sub module needs to implement only the entry points relevant to it (and | ||
63 | * can leave entry points as NULL) | ||
64 | */ | ||
65 | struct bfa_module_s { | ||
66 | void (*meminfo) (struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
67 | u32 *dm_len); | ||
68 | void (*attach) (struct bfa_s *bfa, void *bfad, | ||
69 | struct bfa_iocfc_cfg_s *cfg, | ||
70 | struct bfa_meminfo_s *meminfo, | ||
71 | struct bfa_pcidev_s *pcidev); | ||
72 | void (*initdone) (struct bfa_s *bfa); | ||
73 | void (*detach) (struct bfa_s *bfa); | ||
74 | void (*start) (struct bfa_s *bfa); | ||
75 | void (*stop) (struct bfa_s *bfa); | ||
76 | void (*iocdisable) (struct bfa_s *bfa); | ||
77 | }; | ||
78 | |||
79 | extern struct bfa_module_s *hal_mods[]; | ||
80 | |||
81 | struct bfa_s { | ||
82 | void *bfad; /* BFA driver instance */ | ||
83 | struct bfa_aen_s *aen; /* AEN module */ | ||
84 | struct bfa_plog_s *plog; /* portlog buffer */ | ||
85 | struct bfa_log_mod_s *logm; /* driver logging modulen */ | ||
86 | struct bfa_trc_mod_s *trcmod; /* driver tracing */ | ||
87 | struct bfa_ioc_s ioc; /* IOC module */ | ||
88 | struct bfa_iocfc_s iocfc; /* IOCFC module */ | ||
89 | struct bfa_timer_mod_s timer_mod; /* timer module */ | ||
90 | struct bfa_modules_s modules; /* BFA modules */ | ||
91 | struct list_head comp_q; /* pending completions */ | ||
92 | bfa_boolean_t rme_process; /* RME processing enabled */ | ||
93 | struct list_head reqq_waitq[BFI_IOC_MAX_CQS]; | ||
94 | bfa_boolean_t fcs; /* FCS is attached to BFA */ | ||
95 | struct bfa_msix_s msix; | ||
96 | }; | ||
97 | |||
98 | extern bfa_isr_func_t bfa_isrs[BFI_MC_MAX]; | ||
99 | extern bfa_ioc_mbox_mcfunc_t bfa_mbox_isrs[]; | ||
100 | extern bfa_boolean_t bfa_auto_recover; | ||
101 | extern struct bfa_module_s hal_mod_flash; | ||
102 | extern struct bfa_module_s hal_mod_fcdiag; | ||
103 | extern struct bfa_module_s hal_mod_sgpg; | ||
104 | extern struct bfa_module_s hal_mod_pport; | ||
105 | extern struct bfa_module_s hal_mod_fcxp; | ||
106 | extern struct bfa_module_s hal_mod_lps; | ||
107 | extern struct bfa_module_s hal_mod_uf; | ||
108 | extern struct bfa_module_s hal_mod_rport; | ||
109 | extern struct bfa_module_s hal_mod_fcpim; | ||
110 | extern struct bfa_module_s hal_mod_pbind; | ||
111 | |||
112 | #endif /* __BFA_PRIV_H__ */ | ||
113 | |||
diff --git a/drivers/scsi/bfa/bfa_rport.c b/drivers/scsi/bfa/bfa_rport.c new file mode 100644 index 000000000000..16da77a8db28 --- /dev/null +++ b/drivers/scsi/bfa/bfa_rport.c | |||
@@ -0,0 +1,911 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfa_svc.h> | ||
20 | #include <cs/bfa_debug.h> | ||
21 | #include <bfi/bfi_rport.h> | ||
22 | #include "bfa_intr_priv.h" | ||
23 | |||
24 | BFA_TRC_FILE(HAL, RPORT); | ||
25 | BFA_MODULE(rport); | ||
26 | |||
27 | #define bfa_rport_offline_cb(__rp) do { \ | ||
28 | if ((__rp)->bfa->fcs) \ | ||
29 | bfa_cb_rport_offline((__rp)->rport_drv); \ | ||
30 | else { \ | ||
31 | bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \ | ||
32 | __bfa_cb_rport_offline, (__rp)); \ | ||
33 | } \ | ||
34 | } while (0) | ||
35 | |||
36 | #define bfa_rport_online_cb(__rp) do { \ | ||
37 | if ((__rp)->bfa->fcs) \ | ||
38 | bfa_cb_rport_online((__rp)->rport_drv); \ | ||
39 | else { \ | ||
40 | bfa_cb_queue((__rp)->bfa, &(__rp)->hcb_qe, \ | ||
41 | __bfa_cb_rport_online, (__rp)); \ | ||
42 | } \ | ||
43 | } while (0) | ||
44 | |||
45 | /* | ||
46 | * forward declarations | ||
47 | */ | ||
48 | static struct bfa_rport_s *bfa_rport_alloc(struct bfa_rport_mod_s *rp_mod); | ||
49 | static void bfa_rport_free(struct bfa_rport_s *rport); | ||
50 | static bfa_boolean_t bfa_rport_send_fwcreate(struct bfa_rport_s *rp); | ||
51 | static bfa_boolean_t bfa_rport_send_fwdelete(struct bfa_rport_s *rp); | ||
52 | static bfa_boolean_t bfa_rport_send_fwspeed(struct bfa_rport_s *rp); | ||
53 | static void __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete); | ||
54 | static void __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete); | ||
55 | |||
56 | /** | ||
57 | * bfa_rport_sm BFA rport state machine | ||
58 | */ | ||
59 | |||
60 | |||
61 | enum bfa_rport_event { | ||
62 | BFA_RPORT_SM_CREATE = 1, /* rport create event */ | ||
63 | BFA_RPORT_SM_DELETE = 2, /* deleting an existing rport */ | ||
64 | BFA_RPORT_SM_ONLINE = 3, /* rport is online */ | ||
65 | BFA_RPORT_SM_OFFLINE = 4, /* rport is offline */ | ||
66 | BFA_RPORT_SM_FWRSP = 5, /* firmware response */ | ||
67 | BFA_RPORT_SM_HWFAIL = 6, /* IOC h/w failure */ | ||
68 | BFA_RPORT_SM_QOS_SCN = 7, /* QoS SCN from firmware */ | ||
69 | BFA_RPORT_SM_SET_SPEED = 8, /* Set Rport Speed */ | ||
70 | BFA_RPORT_SM_QRESUME = 9, /* space in requeue queue */ | ||
71 | }; | ||
72 | |||
73 | static void bfa_rport_sm_uninit(struct bfa_rport_s *rp, | ||
74 | enum bfa_rport_event event); | ||
75 | static void bfa_rport_sm_created(struct bfa_rport_s *rp, | ||
76 | enum bfa_rport_event event); | ||
77 | static void bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, | ||
78 | enum bfa_rport_event event); | ||
79 | static void bfa_rport_sm_online(struct bfa_rport_s *rp, | ||
80 | enum bfa_rport_event event); | ||
81 | static void bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, | ||
82 | enum bfa_rport_event event); | ||
83 | static void bfa_rport_sm_offline(struct bfa_rport_s *rp, | ||
84 | enum bfa_rport_event event); | ||
85 | static void bfa_rport_sm_deleting(struct bfa_rport_s *rp, | ||
86 | enum bfa_rport_event event); | ||
87 | static void bfa_rport_sm_offline_pending(struct bfa_rport_s *rp, | ||
88 | enum bfa_rport_event event); | ||
89 | static void bfa_rport_sm_delete_pending(struct bfa_rport_s *rp, | ||
90 | enum bfa_rport_event event); | ||
91 | static void bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, | ||
92 | enum bfa_rport_event event); | ||
93 | static void bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, | ||
94 | enum bfa_rport_event event); | ||
95 | static void bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, | ||
96 | enum bfa_rport_event event); | ||
97 | static void bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, | ||
98 | enum bfa_rport_event event); | ||
99 | |||
100 | /** | ||
101 | * Beginning state, only online event expected. | ||
102 | */ | ||
103 | static void | ||
104 | bfa_rport_sm_uninit(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
105 | { | ||
106 | bfa_trc(rp->bfa, rp->rport_tag); | ||
107 | bfa_trc(rp->bfa, event); | ||
108 | |||
109 | switch (event) { | ||
110 | case BFA_RPORT_SM_CREATE: | ||
111 | bfa_stats(rp, sm_un_cr); | ||
112 | bfa_sm_set_state(rp, bfa_rport_sm_created); | ||
113 | break; | ||
114 | |||
115 | default: | ||
116 | bfa_stats(rp, sm_un_unexp); | ||
117 | bfa_assert(0); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | static void | ||
122 | bfa_rport_sm_created(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
123 | { | ||
124 | bfa_trc(rp->bfa, rp->rport_tag); | ||
125 | bfa_trc(rp->bfa, event); | ||
126 | |||
127 | switch (event) { | ||
128 | case BFA_RPORT_SM_ONLINE: | ||
129 | bfa_stats(rp, sm_cr_on); | ||
130 | if (bfa_rport_send_fwcreate(rp)) | ||
131 | bfa_sm_set_state(rp, bfa_rport_sm_fwcreate); | ||
132 | else | ||
133 | bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull); | ||
134 | break; | ||
135 | |||
136 | case BFA_RPORT_SM_DELETE: | ||
137 | bfa_stats(rp, sm_cr_del); | ||
138 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
139 | bfa_rport_free(rp); | ||
140 | break; | ||
141 | |||
142 | case BFA_RPORT_SM_HWFAIL: | ||
143 | bfa_stats(rp, sm_cr_hwf); | ||
144 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
145 | break; | ||
146 | |||
147 | default: | ||
148 | bfa_stats(rp, sm_cr_unexp); | ||
149 | bfa_assert(0); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Waiting for rport create response from firmware. | ||
155 | */ | ||
156 | static void | ||
157 | bfa_rport_sm_fwcreate(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
158 | { | ||
159 | bfa_trc(rp->bfa, rp->rport_tag); | ||
160 | bfa_trc(rp->bfa, event); | ||
161 | |||
162 | switch (event) { | ||
163 | case BFA_RPORT_SM_FWRSP: | ||
164 | bfa_stats(rp, sm_fwc_rsp); | ||
165 | bfa_sm_set_state(rp, bfa_rport_sm_online); | ||
166 | bfa_rport_online_cb(rp); | ||
167 | break; | ||
168 | |||
169 | case BFA_RPORT_SM_DELETE: | ||
170 | bfa_stats(rp, sm_fwc_del); | ||
171 | bfa_sm_set_state(rp, bfa_rport_sm_delete_pending); | ||
172 | break; | ||
173 | |||
174 | case BFA_RPORT_SM_OFFLINE: | ||
175 | bfa_stats(rp, sm_fwc_off); | ||
176 | bfa_sm_set_state(rp, bfa_rport_sm_offline_pending); | ||
177 | break; | ||
178 | |||
179 | case BFA_RPORT_SM_HWFAIL: | ||
180 | bfa_stats(rp, sm_fwc_hwf); | ||
181 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
182 | break; | ||
183 | |||
184 | default: | ||
185 | bfa_stats(rp, sm_fwc_unexp); | ||
186 | bfa_assert(0); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Request queue is full, awaiting queue resume to send create request. | ||
192 | */ | ||
193 | static void | ||
194 | bfa_rport_sm_fwcreate_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
195 | { | ||
196 | bfa_trc(rp->bfa, rp->rport_tag); | ||
197 | bfa_trc(rp->bfa, event); | ||
198 | |||
199 | switch (event) { | ||
200 | case BFA_RPORT_SM_QRESUME: | ||
201 | bfa_sm_set_state(rp, bfa_rport_sm_fwcreate); | ||
202 | bfa_rport_send_fwcreate(rp); | ||
203 | break; | ||
204 | |||
205 | case BFA_RPORT_SM_DELETE: | ||
206 | bfa_stats(rp, sm_fwc_del); | ||
207 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
208 | bfa_reqq_wcancel(&rp->reqq_wait); | ||
209 | bfa_rport_free(rp); | ||
210 | break; | ||
211 | |||
212 | case BFA_RPORT_SM_OFFLINE: | ||
213 | bfa_stats(rp, sm_fwc_off); | ||
214 | bfa_sm_set_state(rp, bfa_rport_sm_offline); | ||
215 | bfa_reqq_wcancel(&rp->reqq_wait); | ||
216 | bfa_rport_offline_cb(rp); | ||
217 | break; | ||
218 | |||
219 | case BFA_RPORT_SM_HWFAIL: | ||
220 | bfa_stats(rp, sm_fwc_hwf); | ||
221 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
222 | bfa_reqq_wcancel(&rp->reqq_wait); | ||
223 | break; | ||
224 | |||
225 | default: | ||
226 | bfa_stats(rp, sm_fwc_unexp); | ||
227 | bfa_assert(0); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * Online state - normal parking state. | ||
233 | */ | ||
234 | static void | ||
235 | bfa_rport_sm_online(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
236 | { | ||
237 | struct bfi_rport_qos_scn_s *qos_scn; | ||
238 | |||
239 | bfa_trc(rp->bfa, rp->rport_tag); | ||
240 | bfa_trc(rp->bfa, event); | ||
241 | |||
242 | switch (event) { | ||
243 | case BFA_RPORT_SM_OFFLINE: | ||
244 | bfa_stats(rp, sm_on_off); | ||
245 | if (bfa_rport_send_fwdelete(rp)) | ||
246 | bfa_sm_set_state(rp, bfa_rport_sm_fwdelete); | ||
247 | else | ||
248 | bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull); | ||
249 | break; | ||
250 | |||
251 | case BFA_RPORT_SM_DELETE: | ||
252 | bfa_stats(rp, sm_on_del); | ||
253 | if (bfa_rport_send_fwdelete(rp)) | ||
254 | bfa_sm_set_state(rp, bfa_rport_sm_deleting); | ||
255 | else | ||
256 | bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull); | ||
257 | break; | ||
258 | |||
259 | case BFA_RPORT_SM_HWFAIL: | ||
260 | bfa_stats(rp, sm_on_hwf); | ||
261 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
262 | break; | ||
263 | |||
264 | case BFA_RPORT_SM_SET_SPEED: | ||
265 | bfa_rport_send_fwspeed(rp); | ||
266 | break; | ||
267 | |||
268 | case BFA_RPORT_SM_QOS_SCN: | ||
269 | qos_scn = (struct bfi_rport_qos_scn_s *) rp->event_arg.fw_msg; | ||
270 | rp->qos_attr = qos_scn->new_qos_attr; | ||
271 | bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_flow_id); | ||
272 | bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_flow_id); | ||
273 | bfa_trc(rp->bfa, qos_scn->old_qos_attr.qos_priority); | ||
274 | bfa_trc(rp->bfa, qos_scn->new_qos_attr.qos_priority); | ||
275 | |||
276 | qos_scn->old_qos_attr.qos_flow_id = | ||
277 | bfa_os_ntohl(qos_scn->old_qos_attr.qos_flow_id); | ||
278 | qos_scn->new_qos_attr.qos_flow_id = | ||
279 | bfa_os_ntohl(qos_scn->new_qos_attr.qos_flow_id); | ||
280 | qos_scn->old_qos_attr.qos_priority = | ||
281 | bfa_os_ntohl(qos_scn->old_qos_attr.qos_priority); | ||
282 | qos_scn->new_qos_attr.qos_priority = | ||
283 | bfa_os_ntohl(qos_scn->new_qos_attr.qos_priority); | ||
284 | |||
285 | if (qos_scn->old_qos_attr.qos_flow_id != | ||
286 | qos_scn->new_qos_attr.qos_flow_id) | ||
287 | bfa_cb_rport_qos_scn_flowid(rp->rport_drv, | ||
288 | qos_scn->old_qos_attr, | ||
289 | qos_scn->new_qos_attr); | ||
290 | if (qos_scn->old_qos_attr.qos_priority != | ||
291 | qos_scn->new_qos_attr.qos_priority) | ||
292 | bfa_cb_rport_qos_scn_prio(rp->rport_drv, | ||
293 | qos_scn->old_qos_attr, | ||
294 | qos_scn->new_qos_attr); | ||
295 | break; | ||
296 | |||
297 | default: | ||
298 | bfa_stats(rp, sm_on_unexp); | ||
299 | bfa_assert(0); | ||
300 | } | ||
301 | } | ||
302 | |||
303 | /** | ||
304 | * Firmware rport is being deleted - awaiting f/w response. | ||
305 | */ | ||
306 | static void | ||
307 | bfa_rport_sm_fwdelete(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
308 | { | ||
309 | bfa_trc(rp->bfa, rp->rport_tag); | ||
310 | bfa_trc(rp->bfa, event); | ||
311 | |||
312 | switch (event) { | ||
313 | case BFA_RPORT_SM_FWRSP: | ||
314 | bfa_stats(rp, sm_fwd_rsp); | ||
315 | bfa_sm_set_state(rp, bfa_rport_sm_offline); | ||
316 | bfa_rport_offline_cb(rp); | ||
317 | break; | ||
318 | |||
319 | case BFA_RPORT_SM_DELETE: | ||
320 | bfa_stats(rp, sm_fwd_del); | ||
321 | bfa_sm_set_state(rp, bfa_rport_sm_deleting); | ||
322 | break; | ||
323 | |||
324 | case BFA_RPORT_SM_HWFAIL: | ||
325 | bfa_stats(rp, sm_fwd_hwf); | ||
326 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
327 | bfa_rport_offline_cb(rp); | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | bfa_stats(rp, sm_fwd_unexp); | ||
332 | bfa_assert(0); | ||
333 | } | ||
334 | } | ||
335 | |||
336 | static void | ||
337 | bfa_rport_sm_fwdelete_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
338 | { | ||
339 | bfa_trc(rp->bfa, rp->rport_tag); | ||
340 | bfa_trc(rp->bfa, event); | ||
341 | |||
342 | switch (event) { | ||
343 | case BFA_RPORT_SM_QRESUME: | ||
344 | bfa_sm_set_state(rp, bfa_rport_sm_fwdelete); | ||
345 | bfa_rport_send_fwdelete(rp); | ||
346 | break; | ||
347 | |||
348 | case BFA_RPORT_SM_DELETE: | ||
349 | bfa_stats(rp, sm_fwd_del); | ||
350 | bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull); | ||
351 | break; | ||
352 | |||
353 | case BFA_RPORT_SM_HWFAIL: | ||
354 | bfa_stats(rp, sm_fwd_hwf); | ||
355 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
356 | bfa_reqq_wcancel(&rp->reqq_wait); | ||
357 | bfa_rport_offline_cb(rp); | ||
358 | break; | ||
359 | |||
360 | default: | ||
361 | bfa_stats(rp, sm_fwd_unexp); | ||
362 | bfa_assert(0); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /** | ||
367 | * Offline state. | ||
368 | */ | ||
369 | static void | ||
370 | bfa_rport_sm_offline(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
371 | { | ||
372 | bfa_trc(rp->bfa, rp->rport_tag); | ||
373 | bfa_trc(rp->bfa, event); | ||
374 | |||
375 | switch (event) { | ||
376 | case BFA_RPORT_SM_DELETE: | ||
377 | bfa_stats(rp, sm_off_del); | ||
378 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
379 | bfa_rport_free(rp); | ||
380 | break; | ||
381 | |||
382 | case BFA_RPORT_SM_ONLINE: | ||
383 | bfa_stats(rp, sm_off_on); | ||
384 | if (bfa_rport_send_fwcreate(rp)) | ||
385 | bfa_sm_set_state(rp, bfa_rport_sm_fwcreate); | ||
386 | else | ||
387 | bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull); | ||
388 | break; | ||
389 | |||
390 | case BFA_RPORT_SM_HWFAIL: | ||
391 | bfa_stats(rp, sm_off_hwf); | ||
392 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
393 | break; | ||
394 | |||
395 | default: | ||
396 | bfa_stats(rp, sm_off_unexp); | ||
397 | bfa_assert(0); | ||
398 | } | ||
399 | } | ||
400 | |||
401 | /** | ||
402 | * Rport is deleted, waiting for firmware response to delete. | ||
403 | */ | ||
404 | static void | ||
405 | bfa_rport_sm_deleting(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
406 | { | ||
407 | bfa_trc(rp->bfa, rp->rport_tag); | ||
408 | bfa_trc(rp->bfa, event); | ||
409 | |||
410 | switch (event) { | ||
411 | case BFA_RPORT_SM_FWRSP: | ||
412 | bfa_stats(rp, sm_del_fwrsp); | ||
413 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
414 | bfa_rport_free(rp); | ||
415 | break; | ||
416 | |||
417 | case BFA_RPORT_SM_HWFAIL: | ||
418 | bfa_stats(rp, sm_del_hwf); | ||
419 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
420 | bfa_rport_free(rp); | ||
421 | break; | ||
422 | |||
423 | default: | ||
424 | bfa_assert(0); | ||
425 | } | ||
426 | } | ||
427 | |||
428 | static void | ||
429 | bfa_rport_sm_deleting_qfull(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
430 | { | ||
431 | bfa_trc(rp->bfa, rp->rport_tag); | ||
432 | bfa_trc(rp->bfa, event); | ||
433 | |||
434 | switch (event) { | ||
435 | case BFA_RPORT_SM_QRESUME: | ||
436 | bfa_stats(rp, sm_del_fwrsp); | ||
437 | bfa_sm_set_state(rp, bfa_rport_sm_deleting); | ||
438 | bfa_rport_send_fwdelete(rp); | ||
439 | break; | ||
440 | |||
441 | case BFA_RPORT_SM_HWFAIL: | ||
442 | bfa_stats(rp, sm_del_hwf); | ||
443 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
444 | bfa_reqq_wcancel(&rp->reqq_wait); | ||
445 | bfa_rport_free(rp); | ||
446 | break; | ||
447 | |||
448 | default: | ||
449 | bfa_assert(0); | ||
450 | } | ||
451 | } | ||
452 | |||
453 | /** | ||
454 | * Waiting for rport create response from firmware. A delete is pending. | ||
455 | */ | ||
456 | static void | ||
457 | bfa_rport_sm_delete_pending(struct bfa_rport_s *rp, | ||
458 | enum bfa_rport_event event) | ||
459 | { | ||
460 | bfa_trc(rp->bfa, rp->rport_tag); | ||
461 | bfa_trc(rp->bfa, event); | ||
462 | |||
463 | switch (event) { | ||
464 | case BFA_RPORT_SM_FWRSP: | ||
465 | bfa_stats(rp, sm_delp_fwrsp); | ||
466 | if (bfa_rport_send_fwdelete(rp)) | ||
467 | bfa_sm_set_state(rp, bfa_rport_sm_deleting); | ||
468 | else | ||
469 | bfa_sm_set_state(rp, bfa_rport_sm_deleting_qfull); | ||
470 | break; | ||
471 | |||
472 | case BFA_RPORT_SM_HWFAIL: | ||
473 | bfa_stats(rp, sm_delp_hwf); | ||
474 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
475 | bfa_rport_free(rp); | ||
476 | break; | ||
477 | |||
478 | default: | ||
479 | bfa_stats(rp, sm_delp_unexp); | ||
480 | bfa_assert(0); | ||
481 | } | ||
482 | } | ||
483 | |||
484 | /** | ||
485 | * Waiting for rport create response from firmware. Rport offline is pending. | ||
486 | */ | ||
487 | static void | ||
488 | bfa_rport_sm_offline_pending(struct bfa_rport_s *rp, | ||
489 | enum bfa_rport_event event) | ||
490 | { | ||
491 | bfa_trc(rp->bfa, rp->rport_tag); | ||
492 | bfa_trc(rp->bfa, event); | ||
493 | |||
494 | switch (event) { | ||
495 | case BFA_RPORT_SM_FWRSP: | ||
496 | bfa_stats(rp, sm_offp_fwrsp); | ||
497 | if (bfa_rport_send_fwdelete(rp)) | ||
498 | bfa_sm_set_state(rp, bfa_rport_sm_fwdelete); | ||
499 | else | ||
500 | bfa_sm_set_state(rp, bfa_rport_sm_fwdelete_qfull); | ||
501 | break; | ||
502 | |||
503 | case BFA_RPORT_SM_DELETE: | ||
504 | bfa_stats(rp, sm_offp_del); | ||
505 | bfa_sm_set_state(rp, bfa_rport_sm_delete_pending); | ||
506 | break; | ||
507 | |||
508 | case BFA_RPORT_SM_HWFAIL: | ||
509 | bfa_stats(rp, sm_offp_hwf); | ||
510 | bfa_sm_set_state(rp, bfa_rport_sm_iocdisable); | ||
511 | break; | ||
512 | |||
513 | default: | ||
514 | bfa_stats(rp, sm_offp_unexp); | ||
515 | bfa_assert(0); | ||
516 | } | ||
517 | } | ||
518 | |||
519 | /** | ||
520 | * IOC h/w failed. | ||
521 | */ | ||
522 | static void | ||
523 | bfa_rport_sm_iocdisable(struct bfa_rport_s *rp, enum bfa_rport_event event) | ||
524 | { | ||
525 | bfa_trc(rp->bfa, rp->rport_tag); | ||
526 | bfa_trc(rp->bfa, event); | ||
527 | |||
528 | switch (event) { | ||
529 | case BFA_RPORT_SM_OFFLINE: | ||
530 | bfa_stats(rp, sm_iocd_off); | ||
531 | bfa_rport_offline_cb(rp); | ||
532 | break; | ||
533 | |||
534 | case BFA_RPORT_SM_DELETE: | ||
535 | bfa_stats(rp, sm_iocd_del); | ||
536 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
537 | bfa_rport_free(rp); | ||
538 | break; | ||
539 | |||
540 | case BFA_RPORT_SM_ONLINE: | ||
541 | bfa_stats(rp, sm_iocd_on); | ||
542 | if (bfa_rport_send_fwcreate(rp)) | ||
543 | bfa_sm_set_state(rp, bfa_rport_sm_fwcreate); | ||
544 | else | ||
545 | bfa_sm_set_state(rp, bfa_rport_sm_fwcreate_qfull); | ||
546 | break; | ||
547 | |||
548 | case BFA_RPORT_SM_HWFAIL: | ||
549 | break; | ||
550 | |||
551 | default: | ||
552 | bfa_stats(rp, sm_iocd_unexp); | ||
553 | bfa_assert(0); | ||
554 | } | ||
555 | } | ||
556 | |||
557 | |||
558 | |||
559 | /** | ||
560 | * bfa_rport_private BFA rport private functions | ||
561 | */ | ||
562 | |||
563 | static void | ||
564 | __bfa_cb_rport_online(void *cbarg, bfa_boolean_t complete) | ||
565 | { | ||
566 | struct bfa_rport_s *rp = cbarg; | ||
567 | |||
568 | if (complete) | ||
569 | bfa_cb_rport_online(rp->rport_drv); | ||
570 | } | ||
571 | |||
572 | static void | ||
573 | __bfa_cb_rport_offline(void *cbarg, bfa_boolean_t complete) | ||
574 | { | ||
575 | struct bfa_rport_s *rp = cbarg; | ||
576 | |||
577 | if (complete) | ||
578 | bfa_cb_rport_offline(rp->rport_drv); | ||
579 | } | ||
580 | |||
581 | static void | ||
582 | bfa_rport_qresume(void *cbarg) | ||
583 | { | ||
584 | struct bfa_rport_s *rp = cbarg; | ||
585 | |||
586 | bfa_sm_send_event(rp, BFA_RPORT_SM_QRESUME); | ||
587 | } | ||
588 | |||
589 | static void | ||
590 | bfa_rport_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
591 | u32 *dm_len) | ||
592 | { | ||
593 | if (cfg->fwcfg.num_rports < BFA_RPORT_MIN) | ||
594 | cfg->fwcfg.num_rports = BFA_RPORT_MIN; | ||
595 | |||
596 | *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_rport_s); | ||
597 | } | ||
598 | |||
599 | static void | ||
600 | bfa_rport_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
601 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
602 | { | ||
603 | struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa); | ||
604 | struct bfa_rport_s *rp; | ||
605 | u16 i; | ||
606 | |||
607 | INIT_LIST_HEAD(&mod->rp_free_q); | ||
608 | INIT_LIST_HEAD(&mod->rp_active_q); | ||
609 | |||
610 | rp = (struct bfa_rport_s *) bfa_meminfo_kva(meminfo); | ||
611 | mod->rps_list = rp; | ||
612 | mod->num_rports = cfg->fwcfg.num_rports; | ||
613 | |||
614 | bfa_assert(mod->num_rports | ||
615 | && !(mod->num_rports & (mod->num_rports - 1))); | ||
616 | |||
617 | for (i = 0; i < mod->num_rports; i++, rp++) { | ||
618 | bfa_os_memset(rp, 0, sizeof(struct bfa_rport_s)); | ||
619 | rp->bfa = bfa; | ||
620 | rp->rport_tag = i; | ||
621 | bfa_sm_set_state(rp, bfa_rport_sm_uninit); | ||
622 | |||
623 | /** | ||
624 | * - is unused | ||
625 | */ | ||
626 | if (i) | ||
627 | list_add_tail(&rp->qe, &mod->rp_free_q); | ||
628 | |||
629 | bfa_reqq_winit(&rp->reqq_wait, bfa_rport_qresume, rp); | ||
630 | } | ||
631 | |||
632 | /** | ||
633 | * consume memory | ||
634 | */ | ||
635 | bfa_meminfo_kva(meminfo) = (u8 *) rp; | ||
636 | } | ||
637 | |||
638 | static void | ||
639 | bfa_rport_initdone(struct bfa_s *bfa) | ||
640 | { | ||
641 | } | ||
642 | |||
643 | static void | ||
644 | bfa_rport_detach(struct bfa_s *bfa) | ||
645 | { | ||
646 | } | ||
647 | |||
648 | static void | ||
649 | bfa_rport_start(struct bfa_s *bfa) | ||
650 | { | ||
651 | } | ||
652 | |||
653 | static void | ||
654 | bfa_rport_stop(struct bfa_s *bfa) | ||
655 | { | ||
656 | } | ||
657 | |||
658 | static void | ||
659 | bfa_rport_iocdisable(struct bfa_s *bfa) | ||
660 | { | ||
661 | struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(bfa); | ||
662 | struct bfa_rport_s *rport; | ||
663 | struct list_head *qe, *qen; | ||
664 | |||
665 | list_for_each_safe(qe, qen, &mod->rp_active_q) { | ||
666 | rport = (struct bfa_rport_s *) qe; | ||
667 | bfa_sm_send_event(rport, BFA_RPORT_SM_HWFAIL); | ||
668 | } | ||
669 | } | ||
670 | |||
671 | static struct bfa_rport_s * | ||
672 | bfa_rport_alloc(struct bfa_rport_mod_s *mod) | ||
673 | { | ||
674 | struct bfa_rport_s *rport; | ||
675 | |||
676 | bfa_q_deq(&mod->rp_free_q, &rport); | ||
677 | if (rport) | ||
678 | list_add_tail(&rport->qe, &mod->rp_active_q); | ||
679 | |||
680 | return (rport); | ||
681 | } | ||
682 | |||
683 | static void | ||
684 | bfa_rport_free(struct bfa_rport_s *rport) | ||
685 | { | ||
686 | struct bfa_rport_mod_s *mod = BFA_RPORT_MOD(rport->bfa); | ||
687 | |||
688 | bfa_assert(bfa_q_is_on_q(&mod->rp_active_q, rport)); | ||
689 | list_del(&rport->qe); | ||
690 | list_add_tail(&rport->qe, &mod->rp_free_q); | ||
691 | } | ||
692 | |||
693 | static bfa_boolean_t | ||
694 | bfa_rport_send_fwcreate(struct bfa_rport_s *rp) | ||
695 | { | ||
696 | struct bfi_rport_create_req_s *m; | ||
697 | |||
698 | /** | ||
699 | * check for room in queue to send request now | ||
700 | */ | ||
701 | m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT); | ||
702 | if (!m) { | ||
703 | bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait); | ||
704 | return BFA_FALSE; | ||
705 | } | ||
706 | |||
707 | bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_CREATE_REQ, | ||
708 | bfa_lpuid(rp->bfa)); | ||
709 | m->bfa_handle = rp->rport_tag; | ||
710 | m->max_frmsz = bfa_os_htons(rp->rport_info.max_frmsz); | ||
711 | m->pid = rp->rport_info.pid; | ||
712 | m->lp_tag = rp->rport_info.lp_tag; | ||
713 | m->local_pid = rp->rport_info.local_pid; | ||
714 | m->fc_class = rp->rport_info.fc_class; | ||
715 | m->vf_en = rp->rport_info.vf_en; | ||
716 | m->vf_id = rp->rport_info.vf_id; | ||
717 | m->cisc = rp->rport_info.cisc; | ||
718 | |||
719 | /** | ||
720 | * queue I/O message to firmware | ||
721 | */ | ||
722 | bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT); | ||
723 | return BFA_TRUE; | ||
724 | } | ||
725 | |||
726 | static bfa_boolean_t | ||
727 | bfa_rport_send_fwdelete(struct bfa_rport_s *rp) | ||
728 | { | ||
729 | struct bfi_rport_delete_req_s *m; | ||
730 | |||
731 | /** | ||
732 | * check for room in queue to send request now | ||
733 | */ | ||
734 | m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT); | ||
735 | if (!m) { | ||
736 | bfa_reqq_wait(rp->bfa, BFA_REQQ_RPORT, &rp->reqq_wait); | ||
737 | return BFA_FALSE; | ||
738 | } | ||
739 | |||
740 | bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_DELETE_REQ, | ||
741 | bfa_lpuid(rp->bfa)); | ||
742 | m->fw_handle = rp->fw_handle; | ||
743 | |||
744 | /** | ||
745 | * queue I/O message to firmware | ||
746 | */ | ||
747 | bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT); | ||
748 | return BFA_TRUE; | ||
749 | } | ||
750 | |||
751 | static bfa_boolean_t | ||
752 | bfa_rport_send_fwspeed(struct bfa_rport_s *rp) | ||
753 | { | ||
754 | struct bfa_rport_speed_req_s *m; | ||
755 | |||
756 | /** | ||
757 | * check for room in queue to send request now | ||
758 | */ | ||
759 | m = bfa_reqq_next(rp->bfa, BFA_REQQ_RPORT); | ||
760 | if (!m) { | ||
761 | bfa_trc(rp->bfa, rp->rport_info.speed); | ||
762 | return BFA_FALSE; | ||
763 | } | ||
764 | |||
765 | bfi_h2i_set(m->mh, BFI_MC_RPORT, BFI_RPORT_H2I_SET_SPEED_REQ, | ||
766 | bfa_lpuid(rp->bfa)); | ||
767 | m->fw_handle = rp->fw_handle; | ||
768 | m->speed = (u8)rp->rport_info.speed; | ||
769 | |||
770 | /** | ||
771 | * queue I/O message to firmware | ||
772 | */ | ||
773 | bfa_reqq_produce(rp->bfa, BFA_REQQ_RPORT); | ||
774 | return BFA_TRUE; | ||
775 | } | ||
776 | |||
777 | |||
778 | |||
779 | /** | ||
780 | * bfa_rport_public | ||
781 | */ | ||
782 | |||
783 | /** | ||
784 | * Rport interrupt processing. | ||
785 | */ | ||
786 | void | ||
787 | bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
788 | { | ||
789 | union bfi_rport_i2h_msg_u msg; | ||
790 | struct bfa_rport_s *rp; | ||
791 | |||
792 | bfa_trc(bfa, m->mhdr.msg_id); | ||
793 | |||
794 | msg.msg = m; | ||
795 | |||
796 | switch (m->mhdr.msg_id) { | ||
797 | case BFI_RPORT_I2H_CREATE_RSP: | ||
798 | rp = BFA_RPORT_FROM_TAG(bfa, msg.create_rsp->bfa_handle); | ||
799 | rp->fw_handle = msg.create_rsp->fw_handle; | ||
800 | rp->qos_attr = msg.create_rsp->qos_attr; | ||
801 | bfa_assert(msg.create_rsp->status == BFA_STATUS_OK); | ||
802 | bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); | ||
803 | break; | ||
804 | |||
805 | case BFI_RPORT_I2H_DELETE_RSP: | ||
806 | rp = BFA_RPORT_FROM_TAG(bfa, msg.delete_rsp->bfa_handle); | ||
807 | bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK); | ||
808 | bfa_sm_send_event(rp, BFA_RPORT_SM_FWRSP); | ||
809 | break; | ||
810 | |||
811 | case BFI_RPORT_I2H_QOS_SCN: | ||
812 | rp = BFA_RPORT_FROM_TAG(bfa, msg.qos_scn_evt->bfa_handle); | ||
813 | rp->event_arg.fw_msg = msg.qos_scn_evt; | ||
814 | bfa_sm_send_event(rp, BFA_RPORT_SM_QOS_SCN); | ||
815 | break; | ||
816 | |||
817 | default: | ||
818 | bfa_trc(bfa, m->mhdr.msg_id); | ||
819 | bfa_assert(0); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | |||
824 | |||
825 | /** | ||
826 | * bfa_rport_api | ||
827 | */ | ||
828 | |||
829 | struct bfa_rport_s * | ||
830 | bfa_rport_create(struct bfa_s *bfa, void *rport_drv) | ||
831 | { | ||
832 | struct bfa_rport_s *rp; | ||
833 | |||
834 | rp = bfa_rport_alloc(BFA_RPORT_MOD(bfa)); | ||
835 | |||
836 | if (rp == NULL) | ||
837 | return (NULL); | ||
838 | |||
839 | rp->bfa = bfa; | ||
840 | rp->rport_drv = rport_drv; | ||
841 | bfa_rport_clear_stats(rp); | ||
842 | |||
843 | bfa_assert(bfa_sm_cmp_state(rp, bfa_rport_sm_uninit)); | ||
844 | bfa_sm_send_event(rp, BFA_RPORT_SM_CREATE); | ||
845 | |||
846 | return (rp); | ||
847 | } | ||
848 | |||
849 | void | ||
850 | bfa_rport_delete(struct bfa_rport_s *rport) | ||
851 | { | ||
852 | bfa_sm_send_event(rport, BFA_RPORT_SM_DELETE); | ||
853 | } | ||
854 | |||
855 | void | ||
856 | bfa_rport_online(struct bfa_rport_s *rport, struct bfa_rport_info_s *rport_info) | ||
857 | { | ||
858 | bfa_assert(rport_info->max_frmsz != 0); | ||
859 | |||
860 | /** | ||
861 | * Some JBODs are seen to be not setting PDU size correctly in PLOGI | ||
862 | * responses. Default to minimum size. | ||
863 | */ | ||
864 | if (rport_info->max_frmsz == 0) { | ||
865 | bfa_trc(rport->bfa, rport->rport_tag); | ||
866 | rport_info->max_frmsz = FC_MIN_PDUSZ; | ||
867 | } | ||
868 | |||
869 | bfa_os_assign(rport->rport_info, *rport_info); | ||
870 | bfa_sm_send_event(rport, BFA_RPORT_SM_ONLINE); | ||
871 | } | ||
872 | |||
873 | void | ||
874 | bfa_rport_offline(struct bfa_rport_s *rport) | ||
875 | { | ||
876 | bfa_sm_send_event(rport, BFA_RPORT_SM_OFFLINE); | ||
877 | } | ||
878 | |||
879 | void | ||
880 | bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed) | ||
881 | { | ||
882 | bfa_assert(speed != 0); | ||
883 | bfa_assert(speed != BFA_PPORT_SPEED_AUTO); | ||
884 | |||
885 | rport->rport_info.speed = speed; | ||
886 | bfa_sm_send_event(rport, BFA_RPORT_SM_SET_SPEED); | ||
887 | } | ||
888 | |||
889 | void | ||
890 | bfa_rport_get_stats(struct bfa_rport_s *rport, | ||
891 | struct bfa_rport_hal_stats_s *stats) | ||
892 | { | ||
893 | *stats = rport->stats; | ||
894 | } | ||
895 | |||
896 | void | ||
897 | bfa_rport_get_qos_attr(struct bfa_rport_s *rport, | ||
898 | struct bfa_rport_qos_attr_s *qos_attr) | ||
899 | { | ||
900 | qos_attr->qos_priority = bfa_os_ntohl(rport->qos_attr.qos_priority); | ||
901 | qos_attr->qos_flow_id = bfa_os_ntohl(rport->qos_attr.qos_flow_id); | ||
902 | |||
903 | } | ||
904 | |||
905 | void | ||
906 | bfa_rport_clear_stats(struct bfa_rport_s *rport) | ||
907 | { | ||
908 | bfa_os_memset(&rport->stats, 0, sizeof(rport->stats)); | ||
909 | } | ||
910 | |||
911 | |||
diff --git a/drivers/scsi/bfa/bfa_rport_priv.h b/drivers/scsi/bfa/bfa_rport_priv.h new file mode 100644 index 000000000000..6490ce2e990d --- /dev/null +++ b/drivers/scsi/bfa/bfa_rport_priv.h | |||
@@ -0,0 +1,45 @@ | |||
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 | #ifndef __BFA_RPORT_PRIV_H__ | ||
19 | #define __BFA_RPORT_PRIV_H__ | ||
20 | |||
21 | #include <bfa_svc.h> | ||
22 | |||
23 | #define BFA_RPORT_MIN 4 | ||
24 | |||
25 | struct bfa_rport_mod_s { | ||
26 | struct bfa_rport_s *rps_list; /* list of rports */ | ||
27 | struct list_head rp_free_q; /* free bfa_rports */ | ||
28 | struct list_head rp_active_q; /* free bfa_rports */ | ||
29 | u16 num_rports; /* number of rports */ | ||
30 | }; | ||
31 | |||
32 | #define BFA_RPORT_MOD(__bfa) (&(__bfa)->modules.rport_mod) | ||
33 | |||
34 | /** | ||
35 | * Convert rport tag to RPORT | ||
36 | */ | ||
37 | #define BFA_RPORT_FROM_TAG(__bfa, _tag) \ | ||
38 | (BFA_RPORT_MOD(__bfa)->rps_list + \ | ||
39 | ((_tag) & (BFA_RPORT_MOD(__bfa)->num_rports - 1))) | ||
40 | |||
41 | /* | ||
42 | * external functions | ||
43 | */ | ||
44 | void bfa_rport_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
45 | #endif /* __BFA_RPORT_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_sgpg.c b/drivers/scsi/bfa/bfa_sgpg.c new file mode 100644 index 000000000000..279d8f9b8907 --- /dev/null +++ b/drivers/scsi/bfa/bfa_sgpg.c | |||
@@ -0,0 +1,231 @@ | |||
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 | #include <bfa.h> | ||
19 | |||
20 | BFA_TRC_FILE(HAL, SGPG); | ||
21 | BFA_MODULE(sgpg); | ||
22 | |||
23 | /** | ||
24 | * bfa_sgpg_mod BFA SGPG Mode module | ||
25 | */ | ||
26 | |||
27 | /** | ||
28 | * Compute and return memory needed by FCP(im) module. | ||
29 | */ | ||
30 | static void | ||
31 | bfa_sgpg_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, | ||
32 | u32 *dm_len) | ||
33 | { | ||
34 | if (cfg->drvcfg.num_sgpgs < BFA_SGPG_MIN) | ||
35 | cfg->drvcfg.num_sgpgs = BFA_SGPG_MIN; | ||
36 | |||
37 | *km_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfa_sgpg_s); | ||
38 | *dm_len += (cfg->drvcfg.num_sgpgs + 1) * sizeof(struct bfi_sgpg_s); | ||
39 | } | ||
40 | |||
41 | |||
42 | static void | ||
43 | bfa_sgpg_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
44 | struct bfa_meminfo_s *minfo, struct bfa_pcidev_s *pcidev) | ||
45 | { | ||
46 | struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); | ||
47 | int i; | ||
48 | struct bfa_sgpg_s *hsgpg; | ||
49 | struct bfi_sgpg_s *sgpg; | ||
50 | u64 align_len; | ||
51 | |||
52 | union { | ||
53 | u64 pa; | ||
54 | union bfi_addr_u addr; | ||
55 | } sgpg_pa; | ||
56 | |||
57 | INIT_LIST_HEAD(&mod->sgpg_q); | ||
58 | INIT_LIST_HEAD(&mod->sgpg_wait_q); | ||
59 | |||
60 | bfa_trc(bfa, cfg->drvcfg.num_sgpgs); | ||
61 | |||
62 | mod->num_sgpgs = cfg->drvcfg.num_sgpgs; | ||
63 | mod->sgpg_arr_pa = bfa_meminfo_dma_phys(minfo); | ||
64 | align_len = (BFA_SGPG_ROUNDUP(mod->sgpg_arr_pa) - mod->sgpg_arr_pa); | ||
65 | mod->sgpg_arr_pa += align_len; | ||
66 | mod->hsgpg_arr = (struct bfa_sgpg_s *) (bfa_meminfo_kva(minfo) + | ||
67 | align_len); | ||
68 | mod->sgpg_arr = (struct bfi_sgpg_s *) (bfa_meminfo_dma_virt(minfo) + | ||
69 | align_len); | ||
70 | |||
71 | hsgpg = mod->hsgpg_arr; | ||
72 | sgpg = mod->sgpg_arr; | ||
73 | sgpg_pa.pa = mod->sgpg_arr_pa; | ||
74 | mod->free_sgpgs = mod->num_sgpgs; | ||
75 | |||
76 | bfa_assert(!(sgpg_pa.pa & (sizeof(struct bfi_sgpg_s) - 1))); | ||
77 | |||
78 | for (i = 0; i < mod->num_sgpgs; i++) { | ||
79 | bfa_os_memset(hsgpg, 0, sizeof(*hsgpg)); | ||
80 | bfa_os_memset(sgpg, 0, sizeof(*sgpg)); | ||
81 | |||
82 | hsgpg->sgpg = sgpg; | ||
83 | hsgpg->sgpg_pa = sgpg_pa.addr; | ||
84 | list_add_tail(&hsgpg->qe, &mod->sgpg_q); | ||
85 | |||
86 | hsgpg++; | ||
87 | sgpg++; | ||
88 | sgpg_pa.pa += sizeof(struct bfi_sgpg_s); | ||
89 | } | ||
90 | |||
91 | bfa_meminfo_kva(minfo) = (u8 *) hsgpg; | ||
92 | bfa_meminfo_dma_virt(minfo) = (u8 *) sgpg; | ||
93 | bfa_meminfo_dma_phys(minfo) = sgpg_pa.pa; | ||
94 | } | ||
95 | |||
96 | static void | ||
97 | bfa_sgpg_initdone(struct bfa_s *bfa) | ||
98 | { | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | bfa_sgpg_detach(struct bfa_s *bfa) | ||
103 | { | ||
104 | } | ||
105 | |||
106 | static void | ||
107 | bfa_sgpg_start(struct bfa_s *bfa) | ||
108 | { | ||
109 | } | ||
110 | |||
111 | static void | ||
112 | bfa_sgpg_stop(struct bfa_s *bfa) | ||
113 | { | ||
114 | } | ||
115 | |||
116 | static void | ||
117 | bfa_sgpg_iocdisable(struct bfa_s *bfa) | ||
118 | { | ||
119 | } | ||
120 | |||
121 | |||
122 | |||
123 | /** | ||
124 | * bfa_sgpg_public BFA SGPG public functions | ||
125 | */ | ||
126 | |||
127 | bfa_status_t | ||
128 | bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpgs) | ||
129 | { | ||
130 | struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); | ||
131 | struct bfa_sgpg_s *hsgpg; | ||
132 | int i; | ||
133 | |||
134 | bfa_trc_fp(bfa, nsgpgs); | ||
135 | |||
136 | if (mod->free_sgpgs < nsgpgs) | ||
137 | return BFA_STATUS_ENOMEM; | ||
138 | |||
139 | for (i = 0; i < nsgpgs; i++) { | ||
140 | bfa_q_deq(&mod->sgpg_q, &hsgpg); | ||
141 | bfa_assert(hsgpg); | ||
142 | list_add_tail(&hsgpg->qe, sgpg_q); | ||
143 | } | ||
144 | |||
145 | mod->free_sgpgs -= nsgpgs; | ||
146 | return BFA_STATUS_OK; | ||
147 | } | ||
148 | |||
149 | void | ||
150 | bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, int nsgpg) | ||
151 | { | ||
152 | struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); | ||
153 | struct bfa_sgpg_wqe_s *wqe; | ||
154 | |||
155 | bfa_trc_fp(bfa, nsgpg); | ||
156 | |||
157 | mod->free_sgpgs += nsgpg; | ||
158 | bfa_assert(mod->free_sgpgs <= mod->num_sgpgs); | ||
159 | |||
160 | list_splice_tail_init(sgpg_q, &mod->sgpg_q); | ||
161 | |||
162 | if (list_empty(&mod->sgpg_wait_q)) | ||
163 | return; | ||
164 | |||
165 | /** | ||
166 | * satisfy as many waiting requests as possible | ||
167 | */ | ||
168 | do { | ||
169 | wqe = bfa_q_first(&mod->sgpg_wait_q); | ||
170 | if (mod->free_sgpgs < wqe->nsgpg) | ||
171 | nsgpg = mod->free_sgpgs; | ||
172 | else | ||
173 | nsgpg = wqe->nsgpg; | ||
174 | bfa_sgpg_malloc(bfa, &wqe->sgpg_q, nsgpg); | ||
175 | wqe->nsgpg -= nsgpg; | ||
176 | if (wqe->nsgpg == 0) { | ||
177 | list_del(&wqe->qe); | ||
178 | wqe->cbfn(wqe->cbarg); | ||
179 | } | ||
180 | } while (mod->free_sgpgs && !list_empty(&mod->sgpg_wait_q)); | ||
181 | } | ||
182 | |||
183 | void | ||
184 | bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, int nsgpg) | ||
185 | { | ||
186 | struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); | ||
187 | |||
188 | bfa_assert(nsgpg > 0); | ||
189 | bfa_assert(nsgpg > mod->free_sgpgs); | ||
190 | |||
191 | wqe->nsgpg_total = wqe->nsgpg = nsgpg; | ||
192 | |||
193 | /** | ||
194 | * allocate any left to this one first | ||
195 | */ | ||
196 | if (mod->free_sgpgs) { | ||
197 | /** | ||
198 | * no one else is waiting for SGPG | ||
199 | */ | ||
200 | bfa_assert(list_empty(&mod->sgpg_wait_q)); | ||
201 | list_splice_tail_init(&mod->sgpg_q, &wqe->sgpg_q); | ||
202 | wqe->nsgpg -= mod->free_sgpgs; | ||
203 | mod->free_sgpgs = 0; | ||
204 | } | ||
205 | |||
206 | list_add_tail(&wqe->qe, &mod->sgpg_wait_q); | ||
207 | } | ||
208 | |||
209 | void | ||
210 | bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe) | ||
211 | { | ||
212 | struct bfa_sgpg_mod_s *mod = BFA_SGPG_MOD(bfa); | ||
213 | |||
214 | bfa_assert(bfa_q_is_on_q(&mod->sgpg_wait_q, wqe)); | ||
215 | list_del(&wqe->qe); | ||
216 | |||
217 | if (wqe->nsgpg_total != wqe->nsgpg) | ||
218 | bfa_sgpg_mfree(bfa, &wqe->sgpg_q, | ||
219 | wqe->nsgpg_total - wqe->nsgpg); | ||
220 | } | ||
221 | |||
222 | void | ||
223 | bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, void (*cbfn) (void *cbarg), | ||
224 | void *cbarg) | ||
225 | { | ||
226 | INIT_LIST_HEAD(&wqe->sgpg_q); | ||
227 | wqe->cbfn = cbfn; | ||
228 | wqe->cbarg = cbarg; | ||
229 | } | ||
230 | |||
231 | |||
diff --git a/drivers/scsi/bfa/bfa_sgpg_priv.h b/drivers/scsi/bfa/bfa_sgpg_priv.h new file mode 100644 index 000000000000..9c2a8cbe7522 --- /dev/null +++ b/drivers/scsi/bfa/bfa_sgpg_priv.h | |||
@@ -0,0 +1,79 @@ | |||
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 | * hal_sgpg.h BFA SG page module | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_SGPG_PRIV_H__ | ||
23 | #define __BFA_SGPG_PRIV_H__ | ||
24 | |||
25 | #include <cs/bfa_q.h> | ||
26 | |||
27 | #define BFA_SGPG_MIN (16) | ||
28 | |||
29 | /** | ||
30 | * Alignment macro for SG page allocation | ||
31 | */ | ||
32 | #define BFA_SGPG_ROUNDUP(_l) (((_l) + (sizeof(struct bfi_sgpg_s) - 1)) \ | ||
33 | & ~(sizeof(struct bfi_sgpg_s) - 1)) | ||
34 | |||
35 | struct bfa_sgpg_wqe_s { | ||
36 | struct list_head qe; /* queue sg page element */ | ||
37 | int nsgpg; /* pages to be allocated */ | ||
38 | int nsgpg_total; /* total pages required */ | ||
39 | void (*cbfn) (void *cbarg); | ||
40 | /* callback function */ | ||
41 | void *cbarg; /* callback arg */ | ||
42 | struct list_head sgpg_q; /* queue of alloced sgpgs */ | ||
43 | }; | ||
44 | |||
45 | struct bfa_sgpg_s { | ||
46 | struct list_head qe; /* queue sg page element */ | ||
47 | struct bfi_sgpg_s *sgpg; /* va of SG page */ | ||
48 | union bfi_addr_u sgpg_pa;/* pa of SG page */ | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * Given number of SG elements, BFA_SGPG_NPAGE() returns the number of | ||
53 | * SG pages required. | ||
54 | */ | ||
55 | #define BFA_SGPG_NPAGE(_nsges) (((_nsges) / BFI_SGPG_DATA_SGES) + 1) | ||
56 | |||
57 | struct bfa_sgpg_mod_s { | ||
58 | struct bfa_s *bfa; | ||
59 | int num_sgpgs; /* number of SG pages */ | ||
60 | int free_sgpgs; /* number of free SG pages */ | ||
61 | struct bfa_sgpg_s *hsgpg_arr; /* BFA SG page array */ | ||
62 | struct bfi_sgpg_s *sgpg_arr; /* actual SG page array */ | ||
63 | u64 sgpg_arr_pa; /* SG page array DMA addr */ | ||
64 | struct list_head sgpg_q; /* queue of free SG pages */ | ||
65 | struct list_head sgpg_wait_q; /* wait queue for SG pages */ | ||
66 | }; | ||
67 | #define BFA_SGPG_MOD(__bfa) (&(__bfa)->modules.sgpg_mod) | ||
68 | |||
69 | bfa_status_t bfa_sgpg_malloc(struct bfa_s *bfa, struct list_head *sgpg_q, | ||
70 | int nsgpgs); | ||
71 | void bfa_sgpg_mfree(struct bfa_s *bfa, struct list_head *sgpg_q, | ||
72 | int nsgpgs); | ||
73 | void bfa_sgpg_winit(struct bfa_sgpg_wqe_s *wqe, | ||
74 | void (*cbfn) (void *cbarg), void *cbarg); | ||
75 | void bfa_sgpg_wait(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe, | ||
76 | int nsgpgs); | ||
77 | void bfa_sgpg_wcancel(struct bfa_s *bfa, struct bfa_sgpg_wqe_s *wqe); | ||
78 | |||
79 | #endif /* __BFA_SGPG_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_sm.c b/drivers/scsi/bfa/bfa_sm.c new file mode 100644 index 000000000000..5420f4f45e58 --- /dev/null +++ b/drivers/scsi/bfa/bfa_sm.c | |||
@@ -0,0 +1,38 @@ | |||
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 | * bfasm.c BFA State machine utility functions | ||
20 | */ | ||
21 | |||
22 | #include <cs/bfa_sm.h> | ||
23 | |||
24 | /** | ||
25 | * cs_sm_api | ||
26 | */ | ||
27 | |||
28 | int | ||
29 | bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm) | ||
30 | { | ||
31 | int i = 0; | ||
32 | |||
33 | while (smt[i].sm && smt[i].sm != sm) | ||
34 | i++; | ||
35 | return smt[i].state; | ||
36 | } | ||
37 | |||
38 | |||
diff --git a/drivers/scsi/bfa/bfa_timer.c b/drivers/scsi/bfa/bfa_timer.c new file mode 100644 index 000000000000..cb76481f5cb1 --- /dev/null +++ b/drivers/scsi/bfa/bfa_timer.c | |||
@@ -0,0 +1,90 @@ | |||
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 | #include <bfa_timer.h> | ||
19 | #include <cs/bfa_debug.h> | ||
20 | |||
21 | void | ||
22 | bfa_timer_init(struct bfa_timer_mod_s *mod) | ||
23 | { | ||
24 | INIT_LIST_HEAD(&mod->timer_q); | ||
25 | } | ||
26 | |||
27 | void | ||
28 | bfa_timer_beat(struct bfa_timer_mod_s *mod) | ||
29 | { | ||
30 | struct list_head *qh = &mod->timer_q; | ||
31 | struct list_head *qe, *qe_next; | ||
32 | struct bfa_timer_s *elem; | ||
33 | struct list_head timedout_q; | ||
34 | |||
35 | INIT_LIST_HEAD(&timedout_q); | ||
36 | |||
37 | qe = bfa_q_next(qh); | ||
38 | |||
39 | while (qe != qh) { | ||
40 | qe_next = bfa_q_next(qe); | ||
41 | |||
42 | elem = (struct bfa_timer_s *) qe; | ||
43 | if (elem->timeout <= BFA_TIMER_FREQ) { | ||
44 | elem->timeout = 0; | ||
45 | list_del(&elem->qe); | ||
46 | list_add_tail(&elem->qe, &timedout_q); | ||
47 | } else { | ||
48 | elem->timeout -= BFA_TIMER_FREQ; | ||
49 | } | ||
50 | |||
51 | qe = qe_next; /* go to next elem */ | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Pop all the timeout entries | ||
56 | */ | ||
57 | while (!list_empty(&timedout_q)) { | ||
58 | bfa_q_deq(&timedout_q, &elem); | ||
59 | elem->timercb(elem->arg); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * Should be called with lock protection | ||
65 | */ | ||
66 | void | ||
67 | bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer, | ||
68 | void (*timercb) (void *), void *arg, unsigned int timeout) | ||
69 | { | ||
70 | |||
71 | bfa_assert(timercb != NULL); | ||
72 | bfa_assert(!bfa_q_is_on_q(&mod->timer_q, timer)); | ||
73 | |||
74 | timer->timeout = timeout; | ||
75 | timer->timercb = timercb; | ||
76 | timer->arg = arg; | ||
77 | |||
78 | list_add_tail(&timer->qe, &mod->timer_q); | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * Should be called with lock protection | ||
83 | */ | ||
84 | void | ||
85 | bfa_timer_stop(struct bfa_timer_s *timer) | ||
86 | { | ||
87 | bfa_assert(!list_empty(&timer->qe)); | ||
88 | |||
89 | list_del(&timer->qe); | ||
90 | } | ||
diff --git a/drivers/scsi/bfa/bfa_trcmod_priv.h b/drivers/scsi/bfa/bfa_trcmod_priv.h new file mode 100644 index 000000000000..b3562dce7e9f --- /dev/null +++ b/drivers/scsi/bfa/bfa_trcmod_priv.h | |||
@@ -0,0 +1,66 @@ | |||
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 | * hal_trcmod.h BFA trace modules | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_TRCMOD_PRIV_H__ | ||
23 | #define __BFA_TRCMOD_PRIV_H__ | ||
24 | |||
25 | #include <cs/bfa_trc.h> | ||
26 | |||
27 | /* | ||
28 | * !!! Only append to the enums defined here to avoid any versioning | ||
29 | * !!! needed between trace utility and driver version | ||
30 | */ | ||
31 | enum { | ||
32 | BFA_TRC_HAL_IOC = 1, | ||
33 | BFA_TRC_HAL_INTR = 2, | ||
34 | BFA_TRC_HAL_FCXP = 3, | ||
35 | BFA_TRC_HAL_UF = 4, | ||
36 | BFA_TRC_HAL_DIAG = 5, | ||
37 | BFA_TRC_HAL_RPORT = 6, | ||
38 | BFA_TRC_HAL_FCPIM = 7, | ||
39 | BFA_TRC_HAL_IOIM = 8, | ||
40 | BFA_TRC_HAL_TSKIM = 9, | ||
41 | BFA_TRC_HAL_ITNIM = 10, | ||
42 | BFA_TRC_HAL_PPORT = 11, | ||
43 | BFA_TRC_HAL_SGPG = 12, | ||
44 | BFA_TRC_HAL_FLASH = 13, | ||
45 | BFA_TRC_HAL_DEBUG = 14, | ||
46 | BFA_TRC_HAL_WWN = 15, | ||
47 | BFA_TRC_HAL_FLASH_RAW = 16, | ||
48 | BFA_TRC_HAL_SBOOT = 17, | ||
49 | BFA_TRC_HAL_SBOOT_IO = 18, | ||
50 | BFA_TRC_HAL_SBOOT_INTR = 19, | ||
51 | BFA_TRC_HAL_SBTEST = 20, | ||
52 | BFA_TRC_HAL_IPFC = 21, | ||
53 | BFA_TRC_HAL_IOCFC = 22, | ||
54 | BFA_TRC_HAL_FCPTM = 23, | ||
55 | BFA_TRC_HAL_IOTM = 24, | ||
56 | BFA_TRC_HAL_TSKTM = 25, | ||
57 | BFA_TRC_HAL_TIN = 26, | ||
58 | BFA_TRC_HAL_LPS = 27, | ||
59 | BFA_TRC_HAL_FCDIAG = 28, | ||
60 | BFA_TRC_HAL_PBIND = 29, | ||
61 | BFA_TRC_HAL_IOCFC_CT = 30, | ||
62 | BFA_TRC_HAL_IOCFC_CB = 31, | ||
63 | BFA_TRC_HAL_IOCFC_Q = 32, | ||
64 | }; | ||
65 | |||
66 | #endif /* __BFA_TRCMOD_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfa_tskim.c b/drivers/scsi/bfa/bfa_tskim.c new file mode 100644 index 000000000000..010d40d1e5d3 --- /dev/null +++ b/drivers/scsi/bfa/bfa_tskim.c | |||
@@ -0,0 +1,689 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfa_cb_ioim_macros.h> | ||
20 | |||
21 | BFA_TRC_FILE(HAL, TSKIM); | ||
22 | |||
23 | /** | ||
24 | * task management completion handling | ||
25 | */ | ||
26 | #define bfa_tskim_qcomp(__tskim, __cbfn) do { \ | ||
27 | bfa_cb_queue((__tskim)->bfa, &(__tskim)->hcb_qe, __cbfn, (__tskim)); \ | ||
28 | bfa_tskim_notify_comp(__tskim); \ | ||
29 | } while (0) | ||
30 | |||
31 | #define bfa_tskim_notify_comp(__tskim) do { \ | ||
32 | if ((__tskim)->notify) \ | ||
33 | bfa_itnim_tskdone((__tskim)->itnim); \ | ||
34 | } while (0) | ||
35 | |||
36 | /* | ||
37 | * forward declarations | ||
38 | */ | ||
39 | static void __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete); | ||
40 | static void __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete); | ||
41 | static bfa_boolean_t bfa_tskim_match_scope(struct bfa_tskim_s *tskim, | ||
42 | lun_t lun); | ||
43 | static void bfa_tskim_gather_ios(struct bfa_tskim_s *tskim); | ||
44 | static void bfa_tskim_cleanp_comp(void *tskim_cbarg); | ||
45 | static void bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim); | ||
46 | static bfa_boolean_t bfa_tskim_send(struct bfa_tskim_s *tskim); | ||
47 | static bfa_boolean_t bfa_tskim_send_abort(struct bfa_tskim_s *tskim); | ||
48 | static void bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim); | ||
49 | |||
50 | /** | ||
51 | * bfa_tskim_sm | ||
52 | */ | ||
53 | |||
54 | enum bfa_tskim_event { | ||
55 | BFA_TSKIM_SM_START = 1, /* TM command start */ | ||
56 | BFA_TSKIM_SM_DONE = 2, /* TM completion */ | ||
57 | BFA_TSKIM_SM_QRESUME = 3, /* resume after qfull */ | ||
58 | BFA_TSKIM_SM_HWFAIL = 5, /* IOC h/w failure event */ | ||
59 | BFA_TSKIM_SM_HCB = 6, /* BFA callback completion */ | ||
60 | BFA_TSKIM_SM_IOS_DONE = 7, /* IO and sub TM completions */ | ||
61 | BFA_TSKIM_SM_CLEANUP = 8, /* TM cleanup on ITN offline */ | ||
62 | BFA_TSKIM_SM_CLEANUP_DONE = 9, /* TM abort completion */ | ||
63 | }; | ||
64 | |||
65 | static void bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, | ||
66 | enum bfa_tskim_event event); | ||
67 | static void bfa_tskim_sm_active(struct bfa_tskim_s *tskim, | ||
68 | enum bfa_tskim_event event); | ||
69 | static void bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, | ||
70 | enum bfa_tskim_event event); | ||
71 | static void bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, | ||
72 | enum bfa_tskim_event event); | ||
73 | static void bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, | ||
74 | enum bfa_tskim_event event); | ||
75 | static void bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim, | ||
76 | enum bfa_tskim_event event); | ||
77 | static void bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, | ||
78 | enum bfa_tskim_event event); | ||
79 | |||
80 | /** | ||
81 | * Task management command beginning state. | ||
82 | */ | ||
83 | static void | ||
84 | bfa_tskim_sm_uninit(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) | ||
85 | { | ||
86 | bfa_trc(tskim->bfa, event); | ||
87 | |||
88 | switch (event) { | ||
89 | case BFA_TSKIM_SM_START: | ||
90 | bfa_sm_set_state(tskim, bfa_tskim_sm_active); | ||
91 | bfa_tskim_gather_ios(tskim); | ||
92 | |||
93 | /** | ||
94 | * If device is offline, do not send TM on wire. Just cleanup | ||
95 | * any pending IO requests and complete TM request. | ||
96 | */ | ||
97 | if (!bfa_itnim_is_online(tskim->itnim)) { | ||
98 | bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup); | ||
99 | tskim->tsk_status = BFI_TSKIM_STS_OK; | ||
100 | bfa_tskim_cleanup_ios(tskim); | ||
101 | return; | ||
102 | } | ||
103 | |||
104 | if (!bfa_tskim_send(tskim)) { | ||
105 | bfa_sm_set_state(tskim, bfa_tskim_sm_qfull); | ||
106 | bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq, | ||
107 | &tskim->reqq_wait); | ||
108 | } | ||
109 | break; | ||
110 | |||
111 | default: | ||
112 | bfa_assert(0); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * brief | ||
118 | * TM command is active, awaiting completion from firmware to | ||
119 | * cleanup IO requests in TM scope. | ||
120 | */ | ||
121 | static void | ||
122 | bfa_tskim_sm_active(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) | ||
123 | { | ||
124 | bfa_trc(tskim->bfa, event); | ||
125 | |||
126 | switch (event) { | ||
127 | case BFA_TSKIM_SM_DONE: | ||
128 | bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup); | ||
129 | bfa_tskim_cleanup_ios(tskim); | ||
130 | break; | ||
131 | |||
132 | case BFA_TSKIM_SM_CLEANUP: | ||
133 | bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup); | ||
134 | if (!bfa_tskim_send_abort(tskim)) { | ||
135 | bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup_qfull); | ||
136 | bfa_reqq_wait(tskim->bfa, tskim->itnim->reqq, | ||
137 | &tskim->reqq_wait); | ||
138 | } | ||
139 | break; | ||
140 | |||
141 | case BFA_TSKIM_SM_HWFAIL: | ||
142 | bfa_sm_set_state(tskim, bfa_tskim_sm_hcb); | ||
143 | bfa_tskim_iocdisable_ios(tskim); | ||
144 | bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed); | ||
145 | break; | ||
146 | |||
147 | default: | ||
148 | bfa_assert(0); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * An active TM is being cleaned up since ITN is offline. Awaiting cleanup | ||
154 | * completion event from firmware. | ||
155 | */ | ||
156 | static void | ||
157 | bfa_tskim_sm_cleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) | ||
158 | { | ||
159 | bfa_trc(tskim->bfa, event); | ||
160 | |||
161 | switch (event) { | ||
162 | case BFA_TSKIM_SM_DONE: | ||
163 | /** | ||
164 | * Ignore and wait for ABORT completion from firmware. | ||
165 | */ | ||
166 | break; | ||
167 | |||
168 | case BFA_TSKIM_SM_CLEANUP_DONE: | ||
169 | bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup); | ||
170 | bfa_tskim_cleanup_ios(tskim); | ||
171 | break; | ||
172 | |||
173 | case BFA_TSKIM_SM_HWFAIL: | ||
174 | bfa_sm_set_state(tskim, bfa_tskim_sm_hcb); | ||
175 | bfa_tskim_iocdisable_ios(tskim); | ||
176 | bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed); | ||
177 | break; | ||
178 | |||
179 | default: | ||
180 | bfa_assert(0); | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void | ||
185 | bfa_tskim_sm_iocleanup(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) | ||
186 | { | ||
187 | bfa_trc(tskim->bfa, event); | ||
188 | |||
189 | switch (event) { | ||
190 | case BFA_TSKIM_SM_IOS_DONE: | ||
191 | bfa_sm_set_state(tskim, bfa_tskim_sm_hcb); | ||
192 | bfa_tskim_qcomp(tskim, __bfa_cb_tskim_done); | ||
193 | break; | ||
194 | |||
195 | case BFA_TSKIM_SM_CLEANUP: | ||
196 | /** | ||
197 | * Ignore, TM command completed on wire. | ||
198 | * Notify TM conmpletion on IO cleanup completion. | ||
199 | */ | ||
200 | break; | ||
201 | |||
202 | case BFA_TSKIM_SM_HWFAIL: | ||
203 | bfa_sm_set_state(tskim, bfa_tskim_sm_hcb); | ||
204 | bfa_tskim_iocdisable_ios(tskim); | ||
205 | bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed); | ||
206 | break; | ||
207 | |||
208 | default: | ||
209 | bfa_assert(0); | ||
210 | } | ||
211 | } | ||
212 | |||
213 | /** | ||
214 | * Task management command is waiting for room in request CQ | ||
215 | */ | ||
216 | static void | ||
217 | bfa_tskim_sm_qfull(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) | ||
218 | { | ||
219 | bfa_trc(tskim->bfa, event); | ||
220 | |||
221 | switch (event) { | ||
222 | case BFA_TSKIM_SM_QRESUME: | ||
223 | bfa_sm_set_state(tskim, bfa_tskim_sm_active); | ||
224 | bfa_tskim_send(tskim); | ||
225 | break; | ||
226 | |||
227 | case BFA_TSKIM_SM_CLEANUP: | ||
228 | /** | ||
229 | * No need to send TM on wire since ITN is offline. | ||
230 | */ | ||
231 | bfa_sm_set_state(tskim, bfa_tskim_sm_iocleanup); | ||
232 | bfa_reqq_wcancel(&tskim->reqq_wait); | ||
233 | bfa_tskim_cleanup_ios(tskim); | ||
234 | break; | ||
235 | |||
236 | case BFA_TSKIM_SM_HWFAIL: | ||
237 | bfa_sm_set_state(tskim, bfa_tskim_sm_hcb); | ||
238 | bfa_reqq_wcancel(&tskim->reqq_wait); | ||
239 | bfa_tskim_iocdisable_ios(tskim); | ||
240 | bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed); | ||
241 | break; | ||
242 | |||
243 | default: | ||
244 | bfa_assert(0); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * Task management command is active, awaiting for room in request CQ | ||
250 | * to send clean up request. | ||
251 | */ | ||
252 | static void | ||
253 | bfa_tskim_sm_cleanup_qfull(struct bfa_tskim_s *tskim, | ||
254 | enum bfa_tskim_event event) | ||
255 | { | ||
256 | bfa_trc(tskim->bfa, event); | ||
257 | |||
258 | switch (event) { | ||
259 | case BFA_TSKIM_SM_DONE: | ||
260 | bfa_reqq_wcancel(&tskim->reqq_wait); | ||
261 | /** | ||
262 | * | ||
263 | * Fall through !!! | ||
264 | */ | ||
265 | |||
266 | case BFA_TSKIM_SM_QRESUME: | ||
267 | bfa_sm_set_state(tskim, bfa_tskim_sm_cleanup); | ||
268 | bfa_tskim_send_abort(tskim); | ||
269 | break; | ||
270 | |||
271 | case BFA_TSKIM_SM_HWFAIL: | ||
272 | bfa_sm_set_state(tskim, bfa_tskim_sm_hcb); | ||
273 | bfa_reqq_wcancel(&tskim->reqq_wait); | ||
274 | bfa_tskim_iocdisable_ios(tskim); | ||
275 | bfa_tskim_qcomp(tskim, __bfa_cb_tskim_failed); | ||
276 | break; | ||
277 | |||
278 | default: | ||
279 | bfa_assert(0); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * BFA callback is pending | ||
285 | */ | ||
286 | static void | ||
287 | bfa_tskim_sm_hcb(struct bfa_tskim_s *tskim, enum bfa_tskim_event event) | ||
288 | { | ||
289 | bfa_trc(tskim->bfa, event); | ||
290 | |||
291 | switch (event) { | ||
292 | case BFA_TSKIM_SM_HCB: | ||
293 | bfa_sm_set_state(tskim, bfa_tskim_sm_uninit); | ||
294 | bfa_tskim_free(tskim); | ||
295 | break; | ||
296 | |||
297 | case BFA_TSKIM_SM_CLEANUP: | ||
298 | bfa_tskim_notify_comp(tskim); | ||
299 | break; | ||
300 | |||
301 | case BFA_TSKIM_SM_HWFAIL: | ||
302 | break; | ||
303 | |||
304 | default: | ||
305 | bfa_assert(0); | ||
306 | } | ||
307 | } | ||
308 | |||
309 | |||
310 | |||
311 | /** | ||
312 | * bfa_tskim_private | ||
313 | */ | ||
314 | |||
315 | static void | ||
316 | __bfa_cb_tskim_done(void *cbarg, bfa_boolean_t complete) | ||
317 | { | ||
318 | struct bfa_tskim_s *tskim = cbarg; | ||
319 | |||
320 | if (!complete) { | ||
321 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB); | ||
322 | return; | ||
323 | } | ||
324 | |||
325 | bfa_stats(tskim->itnim, tm_success); | ||
326 | bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, tskim->tsk_status); | ||
327 | } | ||
328 | |||
329 | static void | ||
330 | __bfa_cb_tskim_failed(void *cbarg, bfa_boolean_t complete) | ||
331 | { | ||
332 | struct bfa_tskim_s *tskim = cbarg; | ||
333 | |||
334 | if (!complete) { | ||
335 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_HCB); | ||
336 | return; | ||
337 | } | ||
338 | |||
339 | bfa_stats(tskim->itnim, tm_failures); | ||
340 | bfa_cb_tskim_done(tskim->bfa->bfad, tskim->dtsk, | ||
341 | BFI_TSKIM_STS_FAILED); | ||
342 | } | ||
343 | |||
344 | static bfa_boolean_t | ||
345 | bfa_tskim_match_scope(struct bfa_tskim_s *tskim, lun_t lun) | ||
346 | { | ||
347 | switch (tskim->tm_cmnd) { | ||
348 | case FCP_TM_TARGET_RESET: | ||
349 | return BFA_TRUE; | ||
350 | |||
351 | case FCP_TM_ABORT_TASK_SET: | ||
352 | case FCP_TM_CLEAR_TASK_SET: | ||
353 | case FCP_TM_LUN_RESET: | ||
354 | case FCP_TM_CLEAR_ACA: | ||
355 | return (tskim->lun == lun); | ||
356 | |||
357 | default: | ||
358 | bfa_assert(0); | ||
359 | } | ||
360 | |||
361 | return BFA_FALSE; | ||
362 | } | ||
363 | |||
364 | /** | ||
365 | * Gather affected IO requests and task management commands. | ||
366 | */ | ||
367 | static void | ||
368 | bfa_tskim_gather_ios(struct bfa_tskim_s *tskim) | ||
369 | { | ||
370 | struct bfa_itnim_s *itnim = tskim->itnim; | ||
371 | struct bfa_ioim_s *ioim; | ||
372 | struct list_head *qe, *qen; | ||
373 | |||
374 | INIT_LIST_HEAD(&tskim->io_q); | ||
375 | |||
376 | /** | ||
377 | * Gather any active IO requests first. | ||
378 | */ | ||
379 | list_for_each_safe(qe, qen, &itnim->io_q) { | ||
380 | ioim = (struct bfa_ioim_s *) qe; | ||
381 | if (bfa_tskim_match_scope | ||
382 | (tskim, bfa_cb_ioim_get_lun(ioim->dio))) { | ||
383 | list_del(&ioim->qe); | ||
384 | list_add_tail(&ioim->qe, &tskim->io_q); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | /** | ||
389 | * Failback any pending IO requests immediately. | ||
390 | */ | ||
391 | list_for_each_safe(qe, qen, &itnim->pending_q) { | ||
392 | ioim = (struct bfa_ioim_s *) qe; | ||
393 | if (bfa_tskim_match_scope | ||
394 | (tskim, bfa_cb_ioim_get_lun(ioim->dio))) { | ||
395 | list_del(&ioim->qe); | ||
396 | list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); | ||
397 | bfa_ioim_tov(ioim); | ||
398 | } | ||
399 | } | ||
400 | } | ||
401 | |||
402 | /** | ||
403 | * IO cleanup completion | ||
404 | */ | ||
405 | static void | ||
406 | bfa_tskim_cleanp_comp(void *tskim_cbarg) | ||
407 | { | ||
408 | struct bfa_tskim_s *tskim = tskim_cbarg; | ||
409 | |||
410 | bfa_stats(tskim->itnim, tm_io_comps); | ||
411 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_IOS_DONE); | ||
412 | } | ||
413 | |||
414 | /** | ||
415 | * Gather affected IO requests and task management commands. | ||
416 | */ | ||
417 | static void | ||
418 | bfa_tskim_cleanup_ios(struct bfa_tskim_s *tskim) | ||
419 | { | ||
420 | struct bfa_ioim_s *ioim; | ||
421 | struct list_head *qe, *qen; | ||
422 | |||
423 | bfa_wc_init(&tskim->wc, bfa_tskim_cleanp_comp, tskim); | ||
424 | |||
425 | list_for_each_safe(qe, qen, &tskim->io_q) { | ||
426 | ioim = (struct bfa_ioim_s *) qe; | ||
427 | bfa_wc_up(&tskim->wc); | ||
428 | bfa_ioim_cleanup_tm(ioim, tskim); | ||
429 | } | ||
430 | |||
431 | bfa_wc_wait(&tskim->wc); | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * Send task management request to firmware. | ||
436 | */ | ||
437 | static bfa_boolean_t | ||
438 | bfa_tskim_send(struct bfa_tskim_s *tskim) | ||
439 | { | ||
440 | struct bfa_itnim_s *itnim = tskim->itnim; | ||
441 | struct bfi_tskim_req_s *m; | ||
442 | |||
443 | /** | ||
444 | * check for room in queue to send request now | ||
445 | */ | ||
446 | m = bfa_reqq_next(tskim->bfa, itnim->reqq); | ||
447 | if (!m) | ||
448 | return BFA_FALSE; | ||
449 | |||
450 | /** | ||
451 | * build i/o request message next | ||
452 | */ | ||
453 | bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_TM_REQ, | ||
454 | bfa_lpuid(tskim->bfa)); | ||
455 | |||
456 | m->tsk_tag = bfa_os_htons(tskim->tsk_tag); | ||
457 | m->itn_fhdl = tskim->itnim->rport->fw_handle; | ||
458 | m->t_secs = tskim->tsecs; | ||
459 | m->lun = tskim->lun; | ||
460 | m->tm_flags = tskim->tm_cmnd; | ||
461 | |||
462 | /** | ||
463 | * queue I/O message to firmware | ||
464 | */ | ||
465 | bfa_reqq_produce(tskim->bfa, itnim->reqq); | ||
466 | return BFA_TRUE; | ||
467 | } | ||
468 | |||
469 | /** | ||
470 | * Send abort request to cleanup an active TM to firmware. | ||
471 | */ | ||
472 | static bfa_boolean_t | ||
473 | bfa_tskim_send_abort(struct bfa_tskim_s *tskim) | ||
474 | { | ||
475 | struct bfa_itnim_s *itnim = tskim->itnim; | ||
476 | struct bfi_tskim_abortreq_s *m; | ||
477 | |||
478 | /** | ||
479 | * check for room in queue to send request now | ||
480 | */ | ||
481 | m = bfa_reqq_next(tskim->bfa, itnim->reqq); | ||
482 | if (!m) | ||
483 | return BFA_FALSE; | ||
484 | |||
485 | /** | ||
486 | * build i/o request message next | ||
487 | */ | ||
488 | bfi_h2i_set(m->mh, BFI_MC_TSKIM, BFI_TSKIM_H2I_ABORT_REQ, | ||
489 | bfa_lpuid(tskim->bfa)); | ||
490 | |||
491 | m->tsk_tag = bfa_os_htons(tskim->tsk_tag); | ||
492 | |||
493 | /** | ||
494 | * queue I/O message to firmware | ||
495 | */ | ||
496 | bfa_reqq_produce(tskim->bfa, itnim->reqq); | ||
497 | return BFA_TRUE; | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * Call to resume task management cmnd waiting for room in request queue. | ||
502 | */ | ||
503 | static void | ||
504 | bfa_tskim_qresume(void *cbarg) | ||
505 | { | ||
506 | struct bfa_tskim_s *tskim = cbarg; | ||
507 | |||
508 | bfa_fcpim_stats(tskim->fcpim, qresumes); | ||
509 | bfa_stats(tskim->itnim, tm_qresumes); | ||
510 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_QRESUME); | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * Cleanup IOs associated with a task mangement command on IOC failures. | ||
515 | */ | ||
516 | static void | ||
517 | bfa_tskim_iocdisable_ios(struct bfa_tskim_s *tskim) | ||
518 | { | ||
519 | struct bfa_ioim_s *ioim; | ||
520 | struct list_head *qe, *qen; | ||
521 | |||
522 | list_for_each_safe(qe, qen, &tskim->io_q) { | ||
523 | ioim = (struct bfa_ioim_s *) qe; | ||
524 | bfa_ioim_iocdisable(ioim); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | |||
529 | |||
530 | /** | ||
531 | * bfa_tskim_friend | ||
532 | */ | ||
533 | |||
534 | /** | ||
535 | * Notification on completions from related ioim. | ||
536 | */ | ||
537 | void | ||
538 | bfa_tskim_iodone(struct bfa_tskim_s *tskim) | ||
539 | { | ||
540 | bfa_wc_down(&tskim->wc); | ||
541 | } | ||
542 | |||
543 | /** | ||
544 | * Handle IOC h/w failure notification from itnim. | ||
545 | */ | ||
546 | void | ||
547 | bfa_tskim_iocdisable(struct bfa_tskim_s *tskim) | ||
548 | { | ||
549 | tskim->notify = BFA_FALSE; | ||
550 | bfa_stats(tskim->itnim, tm_iocdowns); | ||
551 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_HWFAIL); | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * Cleanup TM command and associated IOs as part of ITNIM offline. | ||
556 | */ | ||
557 | void | ||
558 | bfa_tskim_cleanup(struct bfa_tskim_s *tskim) | ||
559 | { | ||
560 | tskim->notify = BFA_TRUE; | ||
561 | bfa_stats(tskim->itnim, tm_cleanups); | ||
562 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP); | ||
563 | } | ||
564 | |||
565 | /** | ||
566 | * Memory allocation and initialization. | ||
567 | */ | ||
568 | void | ||
569 | bfa_tskim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) | ||
570 | { | ||
571 | struct bfa_tskim_s *tskim; | ||
572 | u16 i; | ||
573 | |||
574 | INIT_LIST_HEAD(&fcpim->tskim_free_q); | ||
575 | |||
576 | tskim = (struct bfa_tskim_s *) bfa_meminfo_kva(minfo); | ||
577 | fcpim->tskim_arr = tskim; | ||
578 | |||
579 | for (i = 0; i < fcpim->num_tskim_reqs; i++, tskim++) { | ||
580 | /* | ||
581 | * initialize TSKIM | ||
582 | */ | ||
583 | bfa_os_memset(tskim, 0, sizeof(struct bfa_tskim_s)); | ||
584 | tskim->tsk_tag = i; | ||
585 | tskim->bfa = fcpim->bfa; | ||
586 | tskim->fcpim = fcpim; | ||
587 | tskim->notify = BFA_FALSE; | ||
588 | bfa_reqq_winit(&tskim->reqq_wait, bfa_tskim_qresume, | ||
589 | tskim); | ||
590 | bfa_sm_set_state(tskim, bfa_tskim_sm_uninit); | ||
591 | |||
592 | list_add_tail(&tskim->qe, &fcpim->tskim_free_q); | ||
593 | } | ||
594 | |||
595 | bfa_meminfo_kva(minfo) = (u8 *) tskim; | ||
596 | } | ||
597 | |||
598 | void | ||
599 | bfa_tskim_detach(struct bfa_fcpim_mod_s *fcpim) | ||
600 | { | ||
601 | /** | ||
602 | * @todo | ||
603 | */ | ||
604 | } | ||
605 | |||
606 | void | ||
607 | bfa_tskim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) | ||
608 | { | ||
609 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
610 | struct bfi_tskim_rsp_s *rsp = (struct bfi_tskim_rsp_s *) m; | ||
611 | struct bfa_tskim_s *tskim; | ||
612 | u16 tsk_tag = bfa_os_ntohs(rsp->tsk_tag); | ||
613 | |||
614 | tskim = BFA_TSKIM_FROM_TAG(fcpim, tsk_tag); | ||
615 | bfa_assert(tskim->tsk_tag == tsk_tag); | ||
616 | |||
617 | tskim->tsk_status = rsp->tsk_status; | ||
618 | |||
619 | /** | ||
620 | * Firmware sends BFI_TSKIM_STS_ABORTED status for abort | ||
621 | * requests. All other statuses are for normal completions. | ||
622 | */ | ||
623 | if (rsp->tsk_status == BFI_TSKIM_STS_ABORTED) { | ||
624 | bfa_stats(tskim->itnim, tm_cleanup_comps); | ||
625 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_CLEANUP_DONE); | ||
626 | } else { | ||
627 | bfa_stats(tskim->itnim, tm_fw_rsps); | ||
628 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_DONE); | ||
629 | } | ||
630 | } | ||
631 | |||
632 | |||
633 | |||
634 | /** | ||
635 | * bfa_tskim_api | ||
636 | */ | ||
637 | |||
638 | |||
639 | struct bfa_tskim_s * | ||
640 | bfa_tskim_alloc(struct bfa_s *bfa, struct bfad_tskim_s *dtsk) | ||
641 | { | ||
642 | struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); | ||
643 | struct bfa_tskim_s *tskim; | ||
644 | |||
645 | bfa_q_deq(&fcpim->tskim_free_q, &tskim); | ||
646 | |||
647 | if (!tskim) | ||
648 | bfa_fcpim_stats(fcpim, no_tskims); | ||
649 | else | ||
650 | tskim->dtsk = dtsk; | ||
651 | |||
652 | return tskim; | ||
653 | } | ||
654 | |||
655 | void | ||
656 | bfa_tskim_free(struct bfa_tskim_s *tskim) | ||
657 | { | ||
658 | bfa_assert(bfa_q_is_on_q_func(&tskim->itnim->tsk_q, &tskim->qe)); | ||
659 | list_del(&tskim->qe); | ||
660 | list_add_tail(&tskim->qe, &tskim->fcpim->tskim_free_q); | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * Start a task management command. | ||
665 | * | ||
666 | * @param[in] tskim BFA task management command instance | ||
667 | * @param[in] itnim i-t nexus for the task management command | ||
668 | * @param[in] lun lun, if applicable | ||
669 | * @param[in] tm_cmnd Task management command code. | ||
670 | * @param[in] t_secs Timeout in seconds | ||
671 | * | ||
672 | * @return None. | ||
673 | */ | ||
674 | void | ||
675 | bfa_tskim_start(struct bfa_tskim_s *tskim, struct bfa_itnim_s *itnim, lun_t lun, | ||
676 | enum fcp_tm_cmnd tm_cmnd, u8 tsecs) | ||
677 | { | ||
678 | tskim->itnim = itnim; | ||
679 | tskim->lun = lun; | ||
680 | tskim->tm_cmnd = tm_cmnd; | ||
681 | tskim->tsecs = tsecs; | ||
682 | tskim->notify = BFA_FALSE; | ||
683 | bfa_stats(itnim, tm_cmnds); | ||
684 | |||
685 | list_add_tail(&tskim->qe, &itnim->tsk_q); | ||
686 | bfa_sm_send_event(tskim, BFA_TSKIM_SM_START); | ||
687 | } | ||
688 | |||
689 | |||
diff --git a/drivers/scsi/bfa/bfa_uf.c b/drivers/scsi/bfa/bfa_uf.c new file mode 100644 index 000000000000..ff5f9deb1b22 --- /dev/null +++ b/drivers/scsi/bfa/bfa_uf.c | |||
@@ -0,0 +1,345 @@ | |||
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 | * bfa_uf.c BFA unsolicited frame receive implementation | ||
20 | */ | ||
21 | |||
22 | #include <bfa.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include <bfi/bfi_uf.h> | ||
25 | #include <cs/bfa_debug.h> | ||
26 | |||
27 | BFA_TRC_FILE(HAL, UF); | ||
28 | BFA_MODULE(uf); | ||
29 | |||
30 | /* | ||
31 | ***************************************************************************** | ||
32 | * Internal functions | ||
33 | ***************************************************************************** | ||
34 | */ | ||
35 | static void | ||
36 | __bfa_cb_uf_recv(void *cbarg, bfa_boolean_t complete) | ||
37 | { | ||
38 | struct bfa_uf_s *uf = cbarg; | ||
39 | struct bfa_uf_mod_s *ufm = BFA_UF_MOD(uf->bfa); | ||
40 | |||
41 | if (complete) | ||
42 | ufm->ufrecv(ufm->cbarg, uf); | ||
43 | } | ||
44 | |||
45 | static void | ||
46 | claim_uf_pbs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) | ||
47 | { | ||
48 | u32 uf_pb_tot_sz; | ||
49 | |||
50 | ufm->uf_pbs_kva = (struct bfa_uf_buf_s *) bfa_meminfo_dma_virt(mi); | ||
51 | ufm->uf_pbs_pa = bfa_meminfo_dma_phys(mi); | ||
52 | uf_pb_tot_sz = BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * ufm->num_ufs), | ||
53 | BFA_DMA_ALIGN_SZ); | ||
54 | |||
55 | bfa_meminfo_dma_virt(mi) += uf_pb_tot_sz; | ||
56 | bfa_meminfo_dma_phys(mi) += uf_pb_tot_sz; | ||
57 | |||
58 | bfa_os_memset((void *)ufm->uf_pbs_kva, 0, uf_pb_tot_sz); | ||
59 | } | ||
60 | |||
61 | static void | ||
62 | claim_uf_post_msgs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) | ||
63 | { | ||
64 | struct bfi_uf_buf_post_s *uf_bp_msg; | ||
65 | struct bfi_sge_s *sge; | ||
66 | union bfi_addr_u sga_zero = { {0} }; | ||
67 | u16 i; | ||
68 | u16 buf_len; | ||
69 | |||
70 | ufm->uf_buf_posts = (struct bfi_uf_buf_post_s *) bfa_meminfo_kva(mi); | ||
71 | uf_bp_msg = ufm->uf_buf_posts; | ||
72 | |||
73 | for (i = 0, uf_bp_msg = ufm->uf_buf_posts; i < ufm->num_ufs; | ||
74 | i++, uf_bp_msg++) { | ||
75 | bfa_os_memset(uf_bp_msg, 0, sizeof(struct bfi_uf_buf_post_s)); | ||
76 | |||
77 | uf_bp_msg->buf_tag = i; | ||
78 | buf_len = sizeof(struct bfa_uf_buf_s); | ||
79 | uf_bp_msg->buf_len = bfa_os_htons(buf_len); | ||
80 | bfi_h2i_set(uf_bp_msg->mh, BFI_MC_UF, BFI_UF_H2I_BUF_POST, | ||
81 | bfa_lpuid(ufm->bfa)); | ||
82 | |||
83 | sge = uf_bp_msg->sge; | ||
84 | sge[0].sg_len = buf_len; | ||
85 | sge[0].flags = BFI_SGE_DATA_LAST; | ||
86 | bfa_dma_addr_set(sge[0].sga, ufm_pbs_pa(ufm, i)); | ||
87 | bfa_sge_to_be(sge); | ||
88 | |||
89 | sge[1].sg_len = buf_len; | ||
90 | sge[1].flags = BFI_SGE_PGDLEN; | ||
91 | sge[1].sga = sga_zero; | ||
92 | bfa_sge_to_be(&sge[1]); | ||
93 | } | ||
94 | |||
95 | /** | ||
96 | * advance pointer beyond consumed memory | ||
97 | */ | ||
98 | bfa_meminfo_kva(mi) = (u8 *) uf_bp_msg; | ||
99 | } | ||
100 | |||
101 | static void | ||
102 | claim_ufs(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) | ||
103 | { | ||
104 | u16 i; | ||
105 | struct bfa_uf_s *uf; | ||
106 | |||
107 | /* | ||
108 | * Claim block of memory for UF list | ||
109 | */ | ||
110 | ufm->uf_list = (struct bfa_uf_s *) bfa_meminfo_kva(mi); | ||
111 | |||
112 | /* | ||
113 | * Initialize UFs and queue it in UF free queue | ||
114 | */ | ||
115 | for (i = 0, uf = ufm->uf_list; i < ufm->num_ufs; i++, uf++) { | ||
116 | bfa_os_memset(uf, 0, sizeof(struct bfa_uf_s)); | ||
117 | uf->bfa = ufm->bfa; | ||
118 | uf->uf_tag = i; | ||
119 | uf->pb_len = sizeof(struct bfa_uf_buf_s); | ||
120 | uf->buf_kva = (void *)&ufm->uf_pbs_kva[i]; | ||
121 | uf->buf_pa = ufm_pbs_pa(ufm, i); | ||
122 | list_add_tail(&uf->qe, &ufm->uf_free_q); | ||
123 | } | ||
124 | |||
125 | /** | ||
126 | * advance memory pointer | ||
127 | */ | ||
128 | bfa_meminfo_kva(mi) = (u8 *) uf; | ||
129 | } | ||
130 | |||
131 | static void | ||
132 | uf_mem_claim(struct bfa_uf_mod_s *ufm, struct bfa_meminfo_s *mi) | ||
133 | { | ||
134 | claim_uf_pbs(ufm, mi); | ||
135 | claim_ufs(ufm, mi); | ||
136 | claim_uf_post_msgs(ufm, mi); | ||
137 | } | ||
138 | |||
139 | static void | ||
140 | bfa_uf_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *ndm_len, u32 *dm_len) | ||
141 | { | ||
142 | u32 num_ufs = cfg->fwcfg.num_uf_bufs; | ||
143 | |||
144 | /* | ||
145 | * dma-able memory for UF posted bufs | ||
146 | */ | ||
147 | *dm_len += BFA_ROUNDUP((sizeof(struct bfa_uf_buf_s) * num_ufs), | ||
148 | BFA_DMA_ALIGN_SZ); | ||
149 | |||
150 | /* | ||
151 | * kernel Virtual memory for UFs and UF buf post msg copies | ||
152 | */ | ||
153 | *ndm_len += sizeof(struct bfa_uf_s) * num_ufs; | ||
154 | *ndm_len += sizeof(struct bfi_uf_buf_post_s) * num_ufs; | ||
155 | } | ||
156 | |||
157 | static void | ||
158 | bfa_uf_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
159 | struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) | ||
160 | { | ||
161 | struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa); | ||
162 | |||
163 | bfa_os_memset(ufm, 0, sizeof(struct bfa_uf_mod_s)); | ||
164 | ufm->bfa = bfa; | ||
165 | ufm->num_ufs = cfg->fwcfg.num_uf_bufs; | ||
166 | INIT_LIST_HEAD(&ufm->uf_free_q); | ||
167 | INIT_LIST_HEAD(&ufm->uf_posted_q); | ||
168 | |||
169 | uf_mem_claim(ufm, meminfo); | ||
170 | } | ||
171 | |||
172 | static void | ||
173 | bfa_uf_initdone(struct bfa_s *bfa) | ||
174 | { | ||
175 | } | ||
176 | |||
177 | static void | ||
178 | bfa_uf_detach(struct bfa_s *bfa) | ||
179 | { | ||
180 | } | ||
181 | |||
182 | static struct bfa_uf_s * | ||
183 | bfa_uf_get(struct bfa_uf_mod_s *uf_mod) | ||
184 | { | ||
185 | struct bfa_uf_s *uf; | ||
186 | |||
187 | bfa_q_deq(&uf_mod->uf_free_q, &uf); | ||
188 | return (uf); | ||
189 | } | ||
190 | |||
191 | static void | ||
192 | bfa_uf_put(struct bfa_uf_mod_s *uf_mod, struct bfa_uf_s *uf) | ||
193 | { | ||
194 | list_add_tail(&uf->qe, &uf_mod->uf_free_q); | ||
195 | } | ||
196 | |||
197 | static bfa_status_t | ||
198 | bfa_uf_post(struct bfa_uf_mod_s *ufm, struct bfa_uf_s *uf) | ||
199 | { | ||
200 | struct bfi_uf_buf_post_s *uf_post_msg; | ||
201 | |||
202 | uf_post_msg = bfa_reqq_next(ufm->bfa, BFA_REQQ_FCXP); | ||
203 | if (!uf_post_msg) | ||
204 | return BFA_STATUS_FAILED; | ||
205 | |||
206 | bfa_os_memcpy(uf_post_msg, &ufm->uf_buf_posts[uf->uf_tag], | ||
207 | sizeof(struct bfi_uf_buf_post_s)); | ||
208 | bfa_reqq_produce(ufm->bfa, BFA_REQQ_FCXP); | ||
209 | |||
210 | bfa_trc(ufm->bfa, uf->uf_tag); | ||
211 | |||
212 | list_add_tail(&uf->qe, &ufm->uf_posted_q); | ||
213 | return BFA_STATUS_OK; | ||
214 | } | ||
215 | |||
216 | static void | ||
217 | bfa_uf_post_all(struct bfa_uf_mod_s *uf_mod) | ||
218 | { | ||
219 | struct bfa_uf_s *uf; | ||
220 | |||
221 | while ((uf = bfa_uf_get(uf_mod)) != NULL) { | ||
222 | if (bfa_uf_post(uf_mod, uf) != BFA_STATUS_OK) | ||
223 | break; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | static void | ||
228 | uf_recv(struct bfa_s *bfa, struct bfi_uf_frm_rcvd_s *m) | ||
229 | { | ||
230 | struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa); | ||
231 | u16 uf_tag = m->buf_tag; | ||
232 | struct bfa_uf_buf_s *uf_buf = &ufm->uf_pbs_kva[uf_tag]; | ||
233 | struct bfa_uf_s *uf = &ufm->uf_list[uf_tag]; | ||
234 | u8 *buf = &uf_buf->d[0]; | ||
235 | struct fchs_s *fchs; | ||
236 | |||
237 | m->frm_len = bfa_os_ntohs(m->frm_len); | ||
238 | m->xfr_len = bfa_os_ntohs(m->xfr_len); | ||
239 | |||
240 | fchs = (struct fchs_s *) uf_buf; | ||
241 | |||
242 | list_del(&uf->qe); /* dequeue from posted queue */ | ||
243 | |||
244 | uf->data_ptr = buf; | ||
245 | uf->data_len = m->xfr_len; | ||
246 | |||
247 | bfa_assert(uf->data_len >= sizeof(struct fchs_s)); | ||
248 | |||
249 | if (uf->data_len == sizeof(struct fchs_s)) { | ||
250 | bfa_plog_fchdr(bfa->plog, BFA_PL_MID_HAL_UF, BFA_PL_EID_RX, | ||
251 | uf->data_len, (struct fchs_s *) buf); | ||
252 | } else { | ||
253 | u32 pld_w0 = *((u32 *) (buf + sizeof(struct fchs_s))); | ||
254 | bfa_plog_fchdr_and_pl(bfa->plog, BFA_PL_MID_HAL_UF, | ||
255 | BFA_PL_EID_RX, uf->data_len, | ||
256 | (struct fchs_s *) buf, pld_w0); | ||
257 | } | ||
258 | |||
259 | bfa_cb_queue(bfa, &uf->hcb_qe, __bfa_cb_uf_recv, uf); | ||
260 | } | ||
261 | |||
262 | static void | ||
263 | bfa_uf_stop(struct bfa_s *bfa) | ||
264 | { | ||
265 | } | ||
266 | |||
267 | static void | ||
268 | bfa_uf_iocdisable(struct bfa_s *bfa) | ||
269 | { | ||
270 | struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa); | ||
271 | struct bfa_uf_s *uf; | ||
272 | struct list_head *qe, *qen; | ||
273 | |||
274 | list_for_each_safe(qe, qen, &ufm->uf_posted_q) { | ||
275 | uf = (struct bfa_uf_s *) qe; | ||
276 | list_del(&uf->qe); | ||
277 | bfa_uf_put(ufm, uf); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | static void | ||
282 | bfa_uf_start(struct bfa_s *bfa) | ||
283 | { | ||
284 | bfa_uf_post_all(BFA_UF_MOD(bfa)); | ||
285 | } | ||
286 | |||
287 | |||
288 | |||
289 | /** | ||
290 | * bfa_uf_api | ||
291 | */ | ||
292 | |||
293 | /** | ||
294 | * Register handler for all unsolicted recieve frames. | ||
295 | * | ||
296 | * @param[in] bfa BFA instance | ||
297 | * @param[in] ufrecv receive handler function | ||
298 | * @param[in] cbarg receive handler arg | ||
299 | */ | ||
300 | void | ||
301 | bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, void *cbarg) | ||
302 | { | ||
303 | struct bfa_uf_mod_s *ufm = BFA_UF_MOD(bfa); | ||
304 | |||
305 | ufm->ufrecv = ufrecv; | ||
306 | ufm->cbarg = cbarg; | ||
307 | } | ||
308 | |||
309 | /** | ||
310 | * Free an unsolicited frame back to BFA. | ||
311 | * | ||
312 | * @param[in] uf unsolicited frame to be freed | ||
313 | * | ||
314 | * @return None | ||
315 | */ | ||
316 | void | ||
317 | bfa_uf_free(struct bfa_uf_s *uf) | ||
318 | { | ||
319 | bfa_uf_put(BFA_UF_MOD(uf->bfa), uf); | ||
320 | bfa_uf_post_all(BFA_UF_MOD(uf->bfa)); | ||
321 | } | ||
322 | |||
323 | |||
324 | |||
325 | /** | ||
326 | * uf_pub BFA uf module public functions | ||
327 | */ | ||
328 | |||
329 | void | ||
330 | bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg) | ||
331 | { | ||
332 | bfa_trc(bfa, msg->mhdr.msg_id); | ||
333 | |||
334 | switch (msg->mhdr.msg_id) { | ||
335 | case BFI_UF_I2H_FRM_RCVD: | ||
336 | uf_recv(bfa, (struct bfi_uf_frm_rcvd_s *) msg); | ||
337 | break; | ||
338 | |||
339 | default: | ||
340 | bfa_trc(bfa, msg->mhdr.msg_id); | ||
341 | bfa_assert(0); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | |||
diff --git a/drivers/scsi/bfa/bfa_uf_priv.h b/drivers/scsi/bfa/bfa_uf_priv.h new file mode 100644 index 000000000000..bcb490f834f3 --- /dev/null +++ b/drivers/scsi/bfa/bfa_uf_priv.h | |||
@@ -0,0 +1,47 @@ | |||
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 | #ifndef __BFA_UF_PRIV_H__ | ||
18 | #define __BFA_UF_PRIV_H__ | ||
19 | |||
20 | #include <cs/bfa_sm.h> | ||
21 | #include <bfa_svc.h> | ||
22 | #include <bfi/bfi_uf.h> | ||
23 | |||
24 | #define BFA_UF_MIN (4) | ||
25 | |||
26 | struct bfa_uf_mod_s { | ||
27 | struct bfa_s *bfa; /* back pointer to BFA */ | ||
28 | struct bfa_uf_s *uf_list; /* array of UFs */ | ||
29 | u16 num_ufs; /* num unsolicited rx frames */ | ||
30 | struct list_head uf_free_q; /* free UFs */ | ||
31 | struct list_head uf_posted_q; /* UFs posted to IOC */ | ||
32 | struct bfa_uf_buf_s *uf_pbs_kva; /* list UF bufs request pld */ | ||
33 | u64 uf_pbs_pa; /* phy addr for UF bufs */ | ||
34 | struct bfi_uf_buf_post_s *uf_buf_posts; | ||
35 | /* pre-built UF post msgs */ | ||
36 | bfa_cb_uf_recv_t ufrecv; /* uf recv handler function */ | ||
37 | void *cbarg; /* uf receive handler arg */ | ||
38 | }; | ||
39 | |||
40 | #define BFA_UF_MOD(__bfa) (&(__bfa)->modules.uf_mod) | ||
41 | |||
42 | #define ufm_pbs_pa(_ufmod, _uftag) \ | ||
43 | ((_ufmod)->uf_pbs_pa + sizeof(struct bfa_uf_buf_s) * (_uftag)) | ||
44 | |||
45 | void bfa_uf_isr(struct bfa_s *bfa, struct bfi_msg_s *msg); | ||
46 | |||
47 | #endif /* __BFA_UF_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c new file mode 100644 index 000000000000..6f2be5abf561 --- /dev/null +++ b/drivers/scsi/bfa/bfad.c | |||
@@ -0,0 +1,1182 @@ | |||
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 | * bfad.c Linux driver PCI interface module. | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include "bfad_drv.h" | ||
24 | #include "bfad_im.h" | ||
25 | #include "bfad_tm.h" | ||
26 | #include "bfad_ipfc.h" | ||
27 | #include "bfad_trcmod.h" | ||
28 | #include <fcb/bfa_fcb_vf.h> | ||
29 | #include <fcb/bfa_fcb_rport.h> | ||
30 | #include <fcb/bfa_fcb_port.h> | ||
31 | #include <fcb/bfa_fcb.h> | ||
32 | |||
33 | BFA_TRC_FILE(LDRV, BFAD); | ||
34 | static DEFINE_MUTEX(bfad_mutex); | ||
35 | LIST_HEAD(bfad_list); | ||
36 | static int bfad_inst; | ||
37 | int bfad_supported_fc4s; | ||
38 | |||
39 | static char *host_name; | ||
40 | static char *os_name; | ||
41 | static char *os_patch; | ||
42 | static int num_rports; | ||
43 | static int num_ios; | ||
44 | static int num_tms; | ||
45 | static int num_fcxps; | ||
46 | static int num_ufbufs; | ||
47 | static int reqq_size; | ||
48 | static int rspq_size; | ||
49 | static int num_sgpgs; | ||
50 | static int rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT; | ||
51 | static int bfa_io_max_sge = BFAD_IO_MAX_SGE; | ||
52 | static int log_level = BFA_LOG_WARNING; | ||
53 | static int ioc_auto_recover = BFA_TRUE; | ||
54 | static int ipfc_enable = BFA_FALSE; | ||
55 | static int ipfc_mtu = -1; | ||
56 | int bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH; | ||
57 | int bfa_linkup_delay = -1; | ||
58 | |||
59 | module_param(os_name, charp, S_IRUGO | S_IWUSR); | ||
60 | module_param(os_patch, charp, S_IRUGO | S_IWUSR); | ||
61 | module_param(host_name, charp, S_IRUGO | S_IWUSR); | ||
62 | module_param(num_rports, int, S_IRUGO | S_IWUSR); | ||
63 | module_param(num_ios, int, S_IRUGO | S_IWUSR); | ||
64 | module_param(num_tms, int, S_IRUGO | S_IWUSR); | ||
65 | module_param(num_fcxps, int, S_IRUGO | S_IWUSR); | ||
66 | module_param(num_ufbufs, int, S_IRUGO | S_IWUSR); | ||
67 | module_param(reqq_size, int, S_IRUGO | S_IWUSR); | ||
68 | module_param(rspq_size, int, S_IRUGO | S_IWUSR); | ||
69 | module_param(num_sgpgs, int, S_IRUGO | S_IWUSR); | ||
70 | module_param(rport_del_timeout, int, S_IRUGO | S_IWUSR); | ||
71 | module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR); | ||
72 | module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR); | ||
73 | module_param(log_level, int, S_IRUGO | S_IWUSR); | ||
74 | module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR); | ||
75 | module_param(ipfc_enable, int, S_IRUGO | S_IWUSR); | ||
76 | module_param(ipfc_mtu, int, S_IRUGO | S_IWUSR); | ||
77 | module_param(bfa_linkup_delay, int, S_IRUGO | S_IWUSR); | ||
78 | |||
79 | /* | ||
80 | * Stores the module parm num_sgpgs value; | ||
81 | * used to reset for bfad next instance. | ||
82 | */ | ||
83 | static int num_sgpgs_parm; | ||
84 | |||
85 | static bfa_status_t | ||
86 | bfad_fc4_probe(struct bfad_s *bfad) | ||
87 | { | ||
88 | int rc; | ||
89 | |||
90 | rc = bfad_im_probe(bfad); | ||
91 | if (rc != BFA_STATUS_OK) | ||
92 | goto ext; | ||
93 | |||
94 | bfad_tm_probe(bfad); | ||
95 | |||
96 | if (ipfc_enable) | ||
97 | bfad_ipfc_probe(bfad); | ||
98 | ext: | ||
99 | return rc; | ||
100 | } | ||
101 | |||
102 | static void | ||
103 | bfad_fc4_probe_undo(struct bfad_s *bfad) | ||
104 | { | ||
105 | bfad_im_probe_undo(bfad); | ||
106 | bfad_tm_probe_undo(bfad); | ||
107 | if (ipfc_enable) | ||
108 | bfad_ipfc_probe_undo(bfad); | ||
109 | } | ||
110 | |||
111 | static void | ||
112 | bfad_fc4_probe_post(struct bfad_s *bfad) | ||
113 | { | ||
114 | if (bfad->im) | ||
115 | bfad_im_probe_post(bfad->im); | ||
116 | |||
117 | bfad_tm_probe_post(bfad); | ||
118 | if (ipfc_enable) | ||
119 | bfad_ipfc_probe_post(bfad); | ||
120 | } | ||
121 | |||
122 | static bfa_status_t | ||
123 | bfad_fc4_port_new(struct bfad_s *bfad, struct bfad_port_s *port, int roles) | ||
124 | { | ||
125 | int rc = BFA_STATUS_FAILED; | ||
126 | |||
127 | if (roles & BFA_PORT_ROLE_FCP_IM) | ||
128 | rc = bfad_im_port_new(bfad, port); | ||
129 | if (rc != BFA_STATUS_OK) | ||
130 | goto ext; | ||
131 | |||
132 | if (roles & BFA_PORT_ROLE_FCP_TM) | ||
133 | rc = bfad_tm_port_new(bfad, port); | ||
134 | if (rc != BFA_STATUS_OK) | ||
135 | goto ext; | ||
136 | |||
137 | if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) | ||
138 | rc = bfad_ipfc_port_new(bfad, port, port->pvb_type); | ||
139 | ext: | ||
140 | return rc; | ||
141 | } | ||
142 | |||
143 | static void | ||
144 | bfad_fc4_port_delete(struct bfad_s *bfad, struct bfad_port_s *port, int roles) | ||
145 | { | ||
146 | if (roles & BFA_PORT_ROLE_FCP_IM) | ||
147 | bfad_im_port_delete(bfad, port); | ||
148 | |||
149 | if (roles & BFA_PORT_ROLE_FCP_TM) | ||
150 | bfad_tm_port_delete(bfad, port); | ||
151 | |||
152 | if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) | ||
153 | bfad_ipfc_port_delete(bfad, port); | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * BFA callbacks | ||
158 | */ | ||
159 | void | ||
160 | bfad_hcb_comp(void *arg, bfa_status_t status) | ||
161 | { | ||
162 | struct bfad_hal_comp *fcomp = (struct bfad_hal_comp *)arg; | ||
163 | |||
164 | fcomp->status = status; | ||
165 | complete(&fcomp->comp); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * bfa_init callback | ||
170 | */ | ||
171 | void | ||
172 | bfa_cb_init(void *drv, bfa_status_t init_status) | ||
173 | { | ||
174 | struct bfad_s *bfad = drv; | ||
175 | |||
176 | if (init_status == BFA_STATUS_OK) | ||
177 | bfad->bfad_flags |= BFAD_HAL_INIT_DONE; | ||
178 | |||
179 | complete(&bfad->comp); | ||
180 | } | ||
181 | |||
182 | |||
183 | |||
184 | /** | ||
185 | * BFA_FCS callbacks | ||
186 | */ | ||
187 | static struct bfad_port_s * | ||
188 | bfad_get_drv_port(struct bfad_s *bfad, struct bfad_vf_s *vf_drv, | ||
189 | struct bfad_vport_s *vp_drv) | ||
190 | { | ||
191 | return ((vp_drv) ? (&(vp_drv)->drv_port) | ||
192 | : ((vf_drv) ? (&(vf_drv)->base_port) : (&(bfad)->pport))); | ||
193 | } | ||
194 | |||
195 | struct bfad_port_s * | ||
196 | bfa_fcb_port_new(struct bfad_s *bfad, struct bfa_fcs_port_s *port, | ||
197 | enum bfa_port_role roles, struct bfad_vf_s *vf_drv, | ||
198 | struct bfad_vport_s *vp_drv) | ||
199 | { | ||
200 | bfa_status_t rc; | ||
201 | struct bfad_port_s *port_drv; | ||
202 | |||
203 | if (!vp_drv && !vf_drv) { | ||
204 | port_drv = &bfad->pport; | ||
205 | port_drv->pvb_type = BFAD_PORT_PHYS_BASE; | ||
206 | } else if (!vp_drv && vf_drv) { | ||
207 | port_drv = &vf_drv->base_port; | ||
208 | port_drv->pvb_type = BFAD_PORT_VF_BASE; | ||
209 | } else if (vp_drv && !vf_drv) { | ||
210 | port_drv = &vp_drv->drv_port; | ||
211 | port_drv->pvb_type = BFAD_PORT_PHYS_VPORT; | ||
212 | } else { | ||
213 | port_drv = &vp_drv->drv_port; | ||
214 | port_drv->pvb_type = BFAD_PORT_VF_VPORT; | ||
215 | } | ||
216 | |||
217 | port_drv->fcs_port = port; | ||
218 | port_drv->roles = roles; | ||
219 | rc = bfad_fc4_port_new(bfad, port_drv, roles); | ||
220 | if (rc != BFA_STATUS_OK) { | ||
221 | bfad_fc4_port_delete(bfad, port_drv, roles); | ||
222 | port_drv = NULL; | ||
223 | } | ||
224 | |||
225 | return port_drv; | ||
226 | } | ||
227 | |||
228 | void | ||
229 | bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles, | ||
230 | struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv) | ||
231 | { | ||
232 | struct bfad_port_s *port_drv; | ||
233 | |||
234 | /* | ||
235 | * this will be only called from rmmod context | ||
236 | */ | ||
237 | if (vp_drv && !vp_drv->comp_del) { | ||
238 | port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv); | ||
239 | bfa_trc(bfad, roles); | ||
240 | bfad_fc4_port_delete(bfad, port_drv, roles); | ||
241 | } | ||
242 | } | ||
243 | |||
244 | void | ||
245 | bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles, | ||
246 | struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv) | ||
247 | { | ||
248 | struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv); | ||
249 | |||
250 | if (roles & BFA_PORT_ROLE_FCP_IM) | ||
251 | bfad_im_port_online(bfad, port_drv); | ||
252 | |||
253 | if (roles & BFA_PORT_ROLE_FCP_TM) | ||
254 | bfad_tm_port_online(bfad, port_drv); | ||
255 | |||
256 | if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) | ||
257 | bfad_ipfc_port_online(bfad, port_drv); | ||
258 | |||
259 | bfad->bfad_flags |= BFAD_PORT_ONLINE; | ||
260 | } | ||
261 | |||
262 | void | ||
263 | bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles, | ||
264 | struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv) | ||
265 | { | ||
266 | struct bfad_port_s *port_drv = bfad_get_drv_port(bfad, vf_drv, vp_drv); | ||
267 | |||
268 | if (roles & BFA_PORT_ROLE_FCP_IM) | ||
269 | bfad_im_port_offline(bfad, port_drv); | ||
270 | |||
271 | if (roles & BFA_PORT_ROLE_FCP_TM) | ||
272 | bfad_tm_port_offline(bfad, port_drv); | ||
273 | |||
274 | if ((roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) | ||
275 | bfad_ipfc_port_offline(bfad, port_drv); | ||
276 | } | ||
277 | |||
278 | void | ||
279 | bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv) | ||
280 | { | ||
281 | if (vport_drv->comp_del) { | ||
282 | complete(vport_drv->comp_del); | ||
283 | return; | ||
284 | } | ||
285 | |||
286 | kfree(vport_drv); | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * FCS RPORT alloc callback, after successful PLOGI by FCS | ||
291 | */ | ||
292 | bfa_status_t | ||
293 | bfa_fcb_rport_alloc(struct bfad_s *bfad, struct bfa_fcs_rport_s **rport, | ||
294 | struct bfad_rport_s **rport_drv) | ||
295 | { | ||
296 | bfa_status_t rc = BFA_STATUS_OK; | ||
297 | |||
298 | *rport_drv = kzalloc(sizeof(struct bfad_rport_s), GFP_ATOMIC); | ||
299 | if (*rport_drv == NULL) { | ||
300 | rc = BFA_STATUS_ENOMEM; | ||
301 | goto ext; | ||
302 | } | ||
303 | |||
304 | *rport = &(*rport_drv)->fcs_rport; | ||
305 | |||
306 | ext: | ||
307 | return rc; | ||
308 | } | ||
309 | |||
310 | |||
311 | |||
312 | void | ||
313 | bfad_hal_mem_release(struct bfad_s *bfad) | ||
314 | { | ||
315 | int i; | ||
316 | struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo; | ||
317 | struct bfa_mem_elem_s *meminfo_elem; | ||
318 | |||
319 | for (i = 0; i < BFA_MEM_TYPE_MAX; i++) { | ||
320 | meminfo_elem = &hal_meminfo->meminfo[i]; | ||
321 | if (meminfo_elem->kva != NULL) { | ||
322 | switch (meminfo_elem->mem_type) { | ||
323 | case BFA_MEM_TYPE_KVA: | ||
324 | vfree(meminfo_elem->kva); | ||
325 | break; | ||
326 | case BFA_MEM_TYPE_DMA: | ||
327 | dma_free_coherent(&bfad->pcidev->dev, | ||
328 | meminfo_elem->mem_len, | ||
329 | meminfo_elem->kva, | ||
330 | (dma_addr_t) meminfo_elem->dma); | ||
331 | break; | ||
332 | default: | ||
333 | bfa_assert(0); | ||
334 | break; | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | memset(hal_meminfo, 0, sizeof(struct bfa_meminfo_s)); | ||
340 | } | ||
341 | |||
342 | void | ||
343 | bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg) | ||
344 | { | ||
345 | if (num_rports > 0) | ||
346 | bfa_cfg->fwcfg.num_rports = num_rports; | ||
347 | if (num_ios > 0) | ||
348 | bfa_cfg->fwcfg.num_ioim_reqs = num_ios; | ||
349 | if (num_tms > 0) | ||
350 | bfa_cfg->fwcfg.num_tskim_reqs = num_tms; | ||
351 | if (num_fcxps > 0) | ||
352 | bfa_cfg->fwcfg.num_fcxp_reqs = num_fcxps; | ||
353 | if (num_ufbufs > 0) | ||
354 | bfa_cfg->fwcfg.num_uf_bufs = num_ufbufs; | ||
355 | if (reqq_size > 0) | ||
356 | bfa_cfg->drvcfg.num_reqq_elems = reqq_size; | ||
357 | if (rspq_size > 0) | ||
358 | bfa_cfg->drvcfg.num_rspq_elems = rspq_size; | ||
359 | if (num_sgpgs > 0) | ||
360 | bfa_cfg->drvcfg.num_sgpgs = num_sgpgs; | ||
361 | |||
362 | /* | ||
363 | * populate the hal values back to the driver for sysfs use. | ||
364 | * otherwise, the default values will be shown as 0 in sysfs | ||
365 | */ | ||
366 | num_rports = bfa_cfg->fwcfg.num_rports; | ||
367 | num_ios = bfa_cfg->fwcfg.num_ioim_reqs; | ||
368 | num_tms = bfa_cfg->fwcfg.num_tskim_reqs; | ||
369 | num_fcxps = bfa_cfg->fwcfg.num_fcxp_reqs; | ||
370 | num_ufbufs = bfa_cfg->fwcfg.num_uf_bufs; | ||
371 | reqq_size = bfa_cfg->drvcfg.num_reqq_elems; | ||
372 | rspq_size = bfa_cfg->drvcfg.num_rspq_elems; | ||
373 | num_sgpgs = bfa_cfg->drvcfg.num_sgpgs; | ||
374 | } | ||
375 | |||
376 | bfa_status_t | ||
377 | bfad_hal_mem_alloc(struct bfad_s *bfad) | ||
378 | { | ||
379 | struct bfa_meminfo_s *hal_meminfo = &bfad->meminfo; | ||
380 | struct bfa_mem_elem_s *meminfo_elem; | ||
381 | bfa_status_t rc = BFA_STATUS_OK; | ||
382 | dma_addr_t phys_addr; | ||
383 | int retry_count = 0; | ||
384 | int reset_value = 1; | ||
385 | int min_num_sgpgs = 512; | ||
386 | void *kva; | ||
387 | int i; | ||
388 | |||
389 | bfa_cfg_get_default(&bfad->ioc_cfg); | ||
390 | |||
391 | retry: | ||
392 | bfad_update_hal_cfg(&bfad->ioc_cfg); | ||
393 | bfad->cfg_data.ioc_queue_depth = bfad->ioc_cfg.fwcfg.num_ioim_reqs; | ||
394 | bfa_cfg_get_meminfo(&bfad->ioc_cfg, hal_meminfo); | ||
395 | |||
396 | for (i = 0; i < BFA_MEM_TYPE_MAX; i++) { | ||
397 | meminfo_elem = &hal_meminfo->meminfo[i]; | ||
398 | switch (meminfo_elem->mem_type) { | ||
399 | case BFA_MEM_TYPE_KVA: | ||
400 | kva = vmalloc(meminfo_elem->mem_len); | ||
401 | if (kva == NULL) { | ||
402 | bfad_hal_mem_release(bfad); | ||
403 | rc = BFA_STATUS_ENOMEM; | ||
404 | goto ext; | ||
405 | } | ||
406 | memset(kva, 0, meminfo_elem->mem_len); | ||
407 | meminfo_elem->kva = kva; | ||
408 | break; | ||
409 | case BFA_MEM_TYPE_DMA: | ||
410 | kva = dma_alloc_coherent(&bfad->pcidev->dev, | ||
411 | meminfo_elem->mem_len, | ||
412 | &phys_addr, GFP_KERNEL); | ||
413 | if (kva == NULL) { | ||
414 | bfad_hal_mem_release(bfad); | ||
415 | /* | ||
416 | * If we cannot allocate with default | ||
417 | * num_sgpages try with half the value. | ||
418 | */ | ||
419 | if (num_sgpgs > min_num_sgpgs) { | ||
420 | printk(KERN_INFO "bfad[%d]: memory" | ||
421 | " allocation failed with" | ||
422 | " num_sgpgs: %d\n", | ||
423 | bfad->inst_no, num_sgpgs); | ||
424 | nextLowerInt(&num_sgpgs); | ||
425 | printk(KERN_INFO "bfad[%d]: trying to" | ||
426 | " allocate memory with" | ||
427 | " num_sgpgs: %d\n", | ||
428 | bfad->inst_no, num_sgpgs); | ||
429 | retry_count++; | ||
430 | goto retry; | ||
431 | } else { | ||
432 | if (num_sgpgs_parm > 0) | ||
433 | num_sgpgs = num_sgpgs_parm; | ||
434 | else { | ||
435 | reset_value = | ||
436 | (1 << retry_count); | ||
437 | num_sgpgs *= reset_value; | ||
438 | } | ||
439 | rc = BFA_STATUS_ENOMEM; | ||
440 | goto ext; | ||
441 | } | ||
442 | } | ||
443 | |||
444 | if (num_sgpgs_parm > 0) | ||
445 | num_sgpgs = num_sgpgs_parm; | ||
446 | else { | ||
447 | reset_value = (1 << retry_count); | ||
448 | num_sgpgs *= reset_value; | ||
449 | } | ||
450 | |||
451 | memset(kva, 0, meminfo_elem->mem_len); | ||
452 | meminfo_elem->kva = kva; | ||
453 | meminfo_elem->dma = phys_addr; | ||
454 | break; | ||
455 | default: | ||
456 | break; | ||
457 | |||
458 | } | ||
459 | } | ||
460 | ext: | ||
461 | return rc; | ||
462 | } | ||
463 | |||
464 | /** | ||
465 | * Create a vport under a vf. | ||
466 | */ | ||
467 | bfa_status_t | ||
468 | bfad_vport_create(struct bfad_s *bfad, u16 vf_id, | ||
469 | struct bfa_port_cfg_s *port_cfg) | ||
470 | { | ||
471 | struct bfad_vport_s *vport; | ||
472 | int rc = BFA_STATUS_OK; | ||
473 | unsigned long flags; | ||
474 | struct completion fcomp; | ||
475 | |||
476 | vport = kzalloc(sizeof(struct bfad_vport_s), GFP_KERNEL); | ||
477 | if (!vport) { | ||
478 | rc = BFA_STATUS_ENOMEM; | ||
479 | goto ext; | ||
480 | } | ||
481 | |||
482 | vport->drv_port.bfad = bfad; | ||
483 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
484 | rc = bfa_fcs_vport_create(&vport->fcs_vport, &bfad->bfa_fcs, vf_id, | ||
485 | port_cfg, vport); | ||
486 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
487 | |||
488 | if (rc != BFA_STATUS_OK) | ||
489 | goto ext_free_vport; | ||
490 | |||
491 | if (port_cfg->roles & BFA_PORT_ROLE_FCP_IM) { | ||
492 | rc = bfad_im_scsi_host_alloc(bfad, vport->drv_port.im_port); | ||
493 | if (rc != BFA_STATUS_OK) | ||
494 | goto ext_free_fcs_vport; | ||
495 | } | ||
496 | |||
497 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
498 | bfa_fcs_vport_start(&vport->fcs_vport); | ||
499 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
500 | |||
501 | return BFA_STATUS_OK; | ||
502 | |||
503 | ext_free_fcs_vport: | ||
504 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
505 | vport->comp_del = &fcomp; | ||
506 | init_completion(vport->comp_del); | ||
507 | bfa_fcs_vport_delete(&vport->fcs_vport); | ||
508 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
509 | wait_for_completion(vport->comp_del); | ||
510 | ext_free_vport: | ||
511 | kfree(vport); | ||
512 | ext: | ||
513 | return rc; | ||
514 | } | ||
515 | |||
516 | /** | ||
517 | * Create a vf and its base vport implicitely. | ||
518 | */ | ||
519 | bfa_status_t | ||
520 | bfad_vf_create(struct bfad_s *bfad, u16 vf_id, | ||
521 | struct bfa_port_cfg_s *port_cfg) | ||
522 | { | ||
523 | struct bfad_vf_s *vf; | ||
524 | int rc = BFA_STATUS_OK; | ||
525 | |||
526 | vf = kzalloc(sizeof(struct bfad_vf_s), GFP_KERNEL); | ||
527 | if (!vf) { | ||
528 | rc = BFA_STATUS_FAILED; | ||
529 | goto ext; | ||
530 | } | ||
531 | |||
532 | rc = bfa_fcs_vf_create(&vf->fcs_vf, &bfad->bfa_fcs, vf_id, port_cfg, | ||
533 | vf); | ||
534 | if (rc != BFA_STATUS_OK) | ||
535 | kfree(vf); | ||
536 | ext: | ||
537 | return rc; | ||
538 | } | ||
539 | |||
540 | void | ||
541 | bfad_bfa_tmo(unsigned long data) | ||
542 | { | ||
543 | struct bfad_s *bfad = (struct bfad_s *)data; | ||
544 | unsigned long flags; | ||
545 | struct list_head doneq; | ||
546 | |||
547 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
548 | |||
549 | bfa_timer_tick(&bfad->bfa); | ||
550 | |||
551 | bfa_comp_deq(&bfad->bfa, &doneq); | ||
552 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
553 | |||
554 | if (!list_empty(&doneq)) { | ||
555 | bfa_comp_process(&bfad->bfa, &doneq); | ||
556 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
557 | bfa_comp_free(&bfad->bfa, &doneq); | ||
558 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
559 | } | ||
560 | |||
561 | mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ)); | ||
562 | } | ||
563 | |||
564 | void | ||
565 | bfad_init_timer(struct bfad_s *bfad) | ||
566 | { | ||
567 | init_timer(&bfad->hal_tmo); | ||
568 | bfad->hal_tmo.function = bfad_bfa_tmo; | ||
569 | bfad->hal_tmo.data = (unsigned long)bfad; | ||
570 | |||
571 | mod_timer(&bfad->hal_tmo, jiffies + msecs_to_jiffies(BFA_TIMER_FREQ)); | ||
572 | } | ||
573 | |||
574 | int | ||
575 | bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad) | ||
576 | { | ||
577 | unsigned long bar0_len; | ||
578 | int rc = -ENODEV; | ||
579 | |||
580 | if (pci_enable_device(pdev)) { | ||
581 | BFA_PRINTF(BFA_ERR, "pci_enable_device fail %p\n", pdev); | ||
582 | goto out; | ||
583 | } | ||
584 | |||
585 | if (pci_request_regions(pdev, BFAD_DRIVER_NAME)) | ||
586 | goto out_disable_device; | ||
587 | |||
588 | pci_set_master(pdev); | ||
589 | |||
590 | |||
591 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) | ||
592 | if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) { | ||
593 | BFA_PRINTF(BFA_ERR, "pci_set_dma_mask fail %p\n", pdev); | ||
594 | goto out_release_region; | ||
595 | } | ||
596 | |||
597 | bfad->pci_bar0_map = pci_resource_start(pdev, 0); | ||
598 | bar0_len = pci_resource_len(pdev, 0); | ||
599 | bfad->pci_bar0_kva = ioremap(bfad->pci_bar0_map, bar0_len); | ||
600 | |||
601 | if (bfad->pci_bar0_kva == NULL) { | ||
602 | BFA_PRINTF(BFA_ERR, "Fail to map bar0\n"); | ||
603 | goto out_release_region; | ||
604 | } | ||
605 | |||
606 | bfad->hal_pcidev.pci_slot = PCI_SLOT(pdev->devfn); | ||
607 | bfad->hal_pcidev.pci_func = PCI_FUNC(pdev->devfn); | ||
608 | bfad->hal_pcidev.pci_bar_kva = bfad->pci_bar0_kva; | ||
609 | bfad->hal_pcidev.device_id = pdev->device; | ||
610 | bfad->pci_name = pci_name(pdev); | ||
611 | |||
612 | bfad->pci_attr.vendor_id = pdev->vendor; | ||
613 | bfad->pci_attr.device_id = pdev->device; | ||
614 | bfad->pci_attr.ssid = pdev->subsystem_device; | ||
615 | bfad->pci_attr.ssvid = pdev->subsystem_vendor; | ||
616 | bfad->pci_attr.pcifn = PCI_FUNC(pdev->devfn); | ||
617 | |||
618 | bfad->pcidev = pdev; | ||
619 | return 0; | ||
620 | |||
621 | out_release_region: | ||
622 | pci_release_regions(pdev); | ||
623 | out_disable_device: | ||
624 | pci_disable_device(pdev); | ||
625 | out: | ||
626 | return rc; | ||
627 | } | ||
628 | |||
629 | void | ||
630 | bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad) | ||
631 | { | ||
632 | #if defined(__ia64__) | ||
633 | pci_iounmap(pdev, bfad->pci_bar0_kva); | ||
634 | #else | ||
635 | iounmap(bfad->pci_bar0_kva); | ||
636 | #endif | ||
637 | pci_release_regions(pdev); | ||
638 | pci_disable_device(pdev); | ||
639 | pci_set_drvdata(pdev, NULL); | ||
640 | } | ||
641 | |||
642 | void | ||
643 | bfad_fcs_port_cfg(struct bfad_s *bfad) | ||
644 | { | ||
645 | struct bfa_port_cfg_s port_cfg; | ||
646 | struct bfa_pport_attr_s attr; | ||
647 | char symname[BFA_SYMNAME_MAXLEN]; | ||
648 | |||
649 | sprintf(symname, "%s-%d", BFAD_DRIVER_NAME, bfad->inst_no); | ||
650 | memcpy(port_cfg.sym_name.symname, symname, strlen(symname)); | ||
651 | bfa_pport_get_attr(&bfad->bfa, &attr); | ||
652 | port_cfg.nwwn = attr.nwwn; | ||
653 | port_cfg.pwwn = attr.pwwn; | ||
654 | |||
655 | bfa_fcs_cfg_base_port(&bfad->bfa_fcs, &port_cfg); | ||
656 | } | ||
657 | |||
658 | bfa_status_t | ||
659 | bfad_drv_init(struct bfad_s *bfad) | ||
660 | { | ||
661 | bfa_status_t rc; | ||
662 | unsigned long flags; | ||
663 | struct bfa_fcs_driver_info_s driver_info; | ||
664 | int i; | ||
665 | |||
666 | bfad->cfg_data.rport_del_timeout = rport_del_timeout; | ||
667 | bfad->cfg_data.lun_queue_depth = bfa_lun_queue_depth; | ||
668 | bfad->cfg_data.io_max_sge = bfa_io_max_sge; | ||
669 | bfad->cfg_data.binding_method = FCP_PWWN_BINDING; | ||
670 | |||
671 | rc = bfad_hal_mem_alloc(bfad); | ||
672 | if (rc != BFA_STATUS_OK) { | ||
673 | printk(KERN_WARNING "bfad%d bfad_hal_mem_alloc failure\n", | ||
674 | bfad->inst_no); | ||
675 | printk(KERN_WARNING | ||
676 | "Not enough memory to attach all Brocade HBA ports," | ||
677 | " System may need more memory.\n"); | ||
678 | goto out_hal_mem_alloc_failure; | ||
679 | } | ||
680 | |||
681 | bfa_init_log(&bfad->bfa, bfad->logmod); | ||
682 | bfa_init_trc(&bfad->bfa, bfad->trcmod); | ||
683 | bfa_init_aen(&bfad->bfa, bfad->aen); | ||
684 | INIT_LIST_HEAD(&bfad->file_q); | ||
685 | INIT_LIST_HEAD(&bfad->file_free_q); | ||
686 | for (i = 0; i < BFAD_AEN_MAX_APPS; i++) { | ||
687 | bfa_q_qe_init(&bfad->file_buf[i].qe); | ||
688 | list_add_tail(&bfad->file_buf[i].qe, &bfad->file_free_q); | ||
689 | } | ||
690 | bfa_init_plog(&bfad->bfa, &bfad->plog_buf); | ||
691 | bfa_plog_init(&bfad->plog_buf); | ||
692 | bfa_plog_str(&bfad->plog_buf, BFA_PL_MID_DRVR, BFA_PL_EID_DRIVER_START, | ||
693 | 0, "Driver Attach"); | ||
694 | |||
695 | bfa_attach(&bfad->bfa, bfad, &bfad->ioc_cfg, &bfad->meminfo, | ||
696 | &bfad->hal_pcidev); | ||
697 | |||
698 | init_completion(&bfad->comp); | ||
699 | |||
700 | /* | ||
701 | * Enable Interrupt and wait bfa_init completion | ||
702 | */ | ||
703 | if (bfad_setup_intr(bfad)) { | ||
704 | printk(KERN_WARNING "bfad%d: bfad_setup_intr failed\n", | ||
705 | bfad->inst_no); | ||
706 | goto out_setup_intr_failure; | ||
707 | } | ||
708 | |||
709 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
710 | bfa_init(&bfad->bfa); | ||
711 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
712 | |||
713 | /* | ||
714 | * Set up interrupt handler for each vectors | ||
715 | */ | ||
716 | if ((bfad->bfad_flags & BFAD_MSIX_ON) | ||
717 | && bfad_install_msix_handler(bfad)) { | ||
718 | printk(KERN_WARNING "%s: install_msix failed, bfad%d\n", | ||
719 | __FUNCTION__, bfad->inst_no); | ||
720 | } | ||
721 | |||
722 | bfad_init_timer(bfad); | ||
723 | |||
724 | wait_for_completion(&bfad->comp); | ||
725 | |||
726 | memset(&driver_info, 0, sizeof(driver_info)); | ||
727 | strncpy(driver_info.version, BFAD_DRIVER_VERSION, | ||
728 | sizeof(driver_info.version) - 1); | ||
729 | if (host_name) | ||
730 | strncpy(driver_info.host_machine_name, host_name, | ||
731 | sizeof(driver_info.host_machine_name) - 1); | ||
732 | if (os_name) | ||
733 | strncpy(driver_info.host_os_name, os_name, | ||
734 | sizeof(driver_info.host_os_name) - 1); | ||
735 | if (os_patch) | ||
736 | strncpy(driver_info.host_os_patch, os_patch, | ||
737 | sizeof(driver_info.host_os_patch) - 1); | ||
738 | |||
739 | strncpy(driver_info.os_device_name, bfad->pci_name, | ||
740 | sizeof(driver_info.os_device_name - 1)); | ||
741 | |||
742 | /* | ||
743 | * FCS INIT | ||
744 | */ | ||
745 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
746 | bfa_fcs_log_init(&bfad->bfa_fcs, bfad->logmod); | ||
747 | bfa_fcs_trc_init(&bfad->bfa_fcs, bfad->trcmod); | ||
748 | bfa_fcs_aen_init(&bfad->bfa_fcs, bfad->aen); | ||
749 | bfa_fcs_init(&bfad->bfa_fcs, &bfad->bfa, bfad, BFA_FALSE); | ||
750 | bfa_fcs_driver_info_init(&bfad->bfa_fcs, &driver_info); | ||
751 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
752 | |||
753 | bfad->bfad_flags |= BFAD_DRV_INIT_DONE; | ||
754 | return BFA_STATUS_OK; | ||
755 | |||
756 | out_setup_intr_failure: | ||
757 | bfa_detach(&bfad->bfa); | ||
758 | bfad_hal_mem_release(bfad); | ||
759 | out_hal_mem_alloc_failure: | ||
760 | return BFA_STATUS_FAILED; | ||
761 | } | ||
762 | |||
763 | void | ||
764 | bfad_drv_uninit(struct bfad_s *bfad) | ||
765 | { | ||
766 | del_timer_sync(&bfad->hal_tmo); | ||
767 | bfa_isr_disable(&bfad->bfa); | ||
768 | bfa_detach(&bfad->bfa); | ||
769 | bfad_remove_intr(bfad); | ||
770 | bfa_assert(list_empty(&bfad->file_q)); | ||
771 | bfad_hal_mem_release(bfad); | ||
772 | } | ||
773 | |||
774 | void | ||
775 | bfad_drv_start(struct bfad_s *bfad) | ||
776 | { | ||
777 | unsigned long flags; | ||
778 | |||
779 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
780 | bfa_start(&bfad->bfa); | ||
781 | bfa_fcs_start(&bfad->bfa_fcs); | ||
782 | bfad->bfad_flags |= BFAD_HAL_START_DONE; | ||
783 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
784 | |||
785 | bfad_fc4_probe_post(bfad); | ||
786 | } | ||
787 | |||
788 | void | ||
789 | bfad_drv_stop(struct bfad_s *bfad) | ||
790 | { | ||
791 | unsigned long flags; | ||
792 | |||
793 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
794 | init_completion(&bfad->comp); | ||
795 | bfad->pport.flags |= BFAD_PORT_DELETE; | ||
796 | bfa_fcs_exit(&bfad->bfa_fcs); | ||
797 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
798 | wait_for_completion(&bfad->comp); | ||
799 | |||
800 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
801 | init_completion(&bfad->comp); | ||
802 | bfa_stop(&bfad->bfa); | ||
803 | bfad->bfad_flags &= ~BFAD_HAL_START_DONE; | ||
804 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
805 | wait_for_completion(&bfad->comp); | ||
806 | } | ||
807 | |||
808 | bfa_status_t | ||
809 | bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role) | ||
810 | { | ||
811 | int rc = BFA_STATUS_OK; | ||
812 | |||
813 | /* | ||
814 | * Allocate scsi_host for the physical port | ||
815 | */ | ||
816 | if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM) | ||
817 | && (role & BFA_PORT_ROLE_FCP_IM)) { | ||
818 | if (bfad->pport.im_port == NULL) { | ||
819 | rc = BFA_STATUS_FAILED; | ||
820 | goto out; | ||
821 | } | ||
822 | |||
823 | rc = bfad_im_scsi_host_alloc(bfad, bfad->pport.im_port); | ||
824 | if (rc != BFA_STATUS_OK) | ||
825 | goto out; | ||
826 | |||
827 | bfad->pport.roles |= BFA_PORT_ROLE_FCP_IM; | ||
828 | } | ||
829 | |||
830 | bfad->bfad_flags |= BFAD_CFG_PPORT_DONE; | ||
831 | |||
832 | out: | ||
833 | return rc; | ||
834 | } | ||
835 | |||
836 | void | ||
837 | bfad_uncfg_pport(struct bfad_s *bfad) | ||
838 | { | ||
839 | if ((bfad->pport.roles & BFA_PORT_ROLE_FCP_IPFC) && ipfc_enable) { | ||
840 | bfad_ipfc_port_delete(bfad, &bfad->pport); | ||
841 | bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IPFC; | ||
842 | } | ||
843 | |||
844 | if ((bfad_supported_fc4s & BFA_PORT_ROLE_FCP_IM) | ||
845 | && (bfad->pport.roles & BFA_PORT_ROLE_FCP_IM)) { | ||
846 | bfad_im_scsi_host_free(bfad, bfad->pport.im_port); | ||
847 | bfad_im_port_clean(bfad->pport.im_port); | ||
848 | kfree(bfad->pport.im_port); | ||
849 | bfad->pport.roles &= ~BFA_PORT_ROLE_FCP_IM; | ||
850 | } | ||
851 | |||
852 | bfad->bfad_flags &= ~BFAD_CFG_PPORT_DONE; | ||
853 | } | ||
854 | |||
855 | void | ||
856 | bfad_drv_log_level_set(struct bfad_s *bfad) | ||
857 | { | ||
858 | if (log_level > BFA_LOG_INVALID && log_level <= BFA_LOG_LEVEL_MAX) | ||
859 | bfa_log_set_level_all(&bfad->log_data, log_level); | ||
860 | } | ||
861 | |||
862 | /* | ||
863 | * PCI_entry PCI driver entries * { | ||
864 | */ | ||
865 | |||
866 | /** | ||
867 | * PCI probe entry. | ||
868 | */ | ||
869 | int | ||
870 | bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid) | ||
871 | { | ||
872 | struct bfad_s *bfad; | ||
873 | int error = -ENODEV, retval; | ||
874 | char buf[16]; | ||
875 | |||
876 | /* | ||
877 | * For single port cards - only claim function 0 | ||
878 | */ | ||
879 | if ((pdev->device == BFA_PCI_DEVICE_ID_FC_8G1P) | ||
880 | && (PCI_FUNC(pdev->devfn) != 0)) | ||
881 | return -ENODEV; | ||
882 | |||
883 | BFA_TRACE(BFA_INFO, "bfad_pci_probe entry"); | ||
884 | |||
885 | bfad = kzalloc(sizeof(struct bfad_s), GFP_KERNEL); | ||
886 | if (!bfad) { | ||
887 | error = -ENOMEM; | ||
888 | goto out; | ||
889 | } | ||
890 | |||
891 | bfad->trcmod = kzalloc(sizeof(struct bfa_trc_mod_s), GFP_KERNEL); | ||
892 | if (!bfad->trcmod) { | ||
893 | printk(KERN_WARNING "Error alloc trace buffer!\n"); | ||
894 | error = -ENOMEM; | ||
895 | goto out_alloc_trace_failure; | ||
896 | } | ||
897 | |||
898 | /* | ||
899 | * LOG/TRACE INIT | ||
900 | */ | ||
901 | bfa_trc_init(bfad->trcmod); | ||
902 | bfa_trc(bfad, bfad_inst); | ||
903 | |||
904 | bfad->logmod = &bfad->log_data; | ||
905 | sprintf(buf, "%d", bfad_inst); | ||
906 | bfa_log_init(bfad->logmod, buf, bfa_os_printf); | ||
907 | |||
908 | bfad_drv_log_level_set(bfad); | ||
909 | |||
910 | bfad->aen = &bfad->aen_buf; | ||
911 | |||
912 | if (!(bfad_load_fwimg(pdev))) { | ||
913 | printk(KERN_WARNING "bfad_load_fwimg failure!\n"); | ||
914 | kfree(bfad->trcmod); | ||
915 | goto out_alloc_trace_failure; | ||
916 | } | ||
917 | |||
918 | retval = bfad_pci_init(pdev, bfad); | ||
919 | if (retval) { | ||
920 | printk(KERN_WARNING "bfad_pci_init failure!\n"); | ||
921 | error = retval; | ||
922 | goto out_pci_init_failure; | ||
923 | } | ||
924 | |||
925 | mutex_lock(&bfad_mutex); | ||
926 | bfad->inst_no = bfad_inst++; | ||
927 | list_add_tail(&bfad->list_entry, &bfad_list); | ||
928 | mutex_unlock(&bfad_mutex); | ||
929 | |||
930 | spin_lock_init(&bfad->bfad_lock); | ||
931 | pci_set_drvdata(pdev, bfad); | ||
932 | |||
933 | bfad->ref_count = 0; | ||
934 | bfad->pport.bfad = bfad; | ||
935 | |||
936 | retval = bfad_drv_init(bfad); | ||
937 | if (retval != BFA_STATUS_OK) | ||
938 | goto out_drv_init_failure; | ||
939 | if (!(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | ||
940 | printk(KERN_WARNING "bfad%d: hal init failed\n", bfad->inst_no); | ||
941 | goto ok; | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * PPORT FCS config | ||
946 | */ | ||
947 | bfad_fcs_port_cfg(bfad); | ||
948 | |||
949 | retval = bfad_cfg_pport(bfad, BFA_PORT_ROLE_FCP_IM); | ||
950 | if (retval != BFA_STATUS_OK) | ||
951 | goto out_cfg_pport_failure; | ||
952 | |||
953 | /* | ||
954 | * BFAD level FC4 (IM/TM/IPFC) specific resource allocation | ||
955 | */ | ||
956 | retval = bfad_fc4_probe(bfad); | ||
957 | if (retval != BFA_STATUS_OK) { | ||
958 | printk(KERN_WARNING "bfad_fc4_probe failed\n"); | ||
959 | goto out_fc4_probe_failure; | ||
960 | } | ||
961 | |||
962 | bfad_drv_start(bfad); | ||
963 | |||
964 | /* | ||
965 | * If bfa_linkup_delay is set to -1 default; try to retrive the | ||
966 | * value using the bfad_os_get_linkup_delay(); else use the | ||
967 | * passed in module param value as the bfa_linkup_delay. | ||
968 | */ | ||
969 | if (bfa_linkup_delay < 0) { | ||
970 | bfa_linkup_delay = bfad_os_get_linkup_delay(bfad); | ||
971 | bfad_os_rport_online_wait(bfad); | ||
972 | bfa_linkup_delay = -1; | ||
973 | } else { | ||
974 | bfad_os_rport_online_wait(bfad); | ||
975 | } | ||
976 | |||
977 | bfa_log(bfad->logmod, BFA_LOG_LINUX_DEVICE_CLAIMED, bfad->pci_name); | ||
978 | ok: | ||
979 | return 0; | ||
980 | |||
981 | out_fc4_probe_failure: | ||
982 | bfad_fc4_probe_undo(bfad); | ||
983 | bfad_uncfg_pport(bfad); | ||
984 | out_cfg_pport_failure: | ||
985 | bfad_drv_uninit(bfad); | ||
986 | out_drv_init_failure: | ||
987 | mutex_lock(&bfad_mutex); | ||
988 | bfad_inst--; | ||
989 | list_del(&bfad->list_entry); | ||
990 | mutex_unlock(&bfad_mutex); | ||
991 | bfad_pci_uninit(pdev, bfad); | ||
992 | out_pci_init_failure: | ||
993 | kfree(bfad->trcmod); | ||
994 | out_alloc_trace_failure: | ||
995 | kfree(bfad); | ||
996 | out: | ||
997 | return error; | ||
998 | } | ||
999 | |||
1000 | /** | ||
1001 | * PCI remove entry. | ||
1002 | */ | ||
1003 | void | ||
1004 | bfad_pci_remove(struct pci_dev *pdev) | ||
1005 | { | ||
1006 | struct bfad_s *bfad = pci_get_drvdata(pdev); | ||
1007 | unsigned long flags; | ||
1008 | |||
1009 | bfa_trc(bfad, bfad->inst_no); | ||
1010 | |||
1011 | if ((bfad->bfad_flags & BFAD_DRV_INIT_DONE) | ||
1012 | && !(bfad->bfad_flags & BFAD_HAL_INIT_DONE)) { | ||
1013 | |||
1014 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1015 | init_completion(&bfad->comp); | ||
1016 | bfa_stop(&bfad->bfa); | ||
1017 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1018 | wait_for_completion(&bfad->comp); | ||
1019 | |||
1020 | bfad_remove_intr(bfad); | ||
1021 | del_timer_sync(&bfad->hal_tmo); | ||
1022 | goto hal_detach; | ||
1023 | } else if (!(bfad->bfad_flags & BFAD_DRV_INIT_DONE)) { | ||
1024 | goto remove_sysfs; | ||
1025 | } | ||
1026 | |||
1027 | if (bfad->bfad_flags & BFAD_HAL_START_DONE) | ||
1028 | bfad_drv_stop(bfad); | ||
1029 | |||
1030 | bfad_remove_intr(bfad); | ||
1031 | |||
1032 | del_timer_sync(&bfad->hal_tmo); | ||
1033 | bfad_fc4_probe_undo(bfad); | ||
1034 | |||
1035 | if (bfad->bfad_flags & BFAD_CFG_PPORT_DONE) | ||
1036 | bfad_uncfg_pport(bfad); | ||
1037 | |||
1038 | hal_detach: | ||
1039 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1040 | bfa_detach(&bfad->bfa); | ||
1041 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1042 | bfad_hal_mem_release(bfad); | ||
1043 | remove_sysfs: | ||
1044 | |||
1045 | mutex_lock(&bfad_mutex); | ||
1046 | bfad_inst--; | ||
1047 | list_del(&bfad->list_entry); | ||
1048 | mutex_unlock(&bfad_mutex); | ||
1049 | bfad_pci_uninit(pdev, bfad); | ||
1050 | |||
1051 | kfree(bfad->trcmod); | ||
1052 | kfree(bfad); | ||
1053 | } | ||
1054 | |||
1055 | |||
1056 | static struct pci_device_id bfad_id_table[] = { | ||
1057 | { | ||
1058 | .vendor = BFA_PCI_VENDOR_ID_BROCADE, | ||
1059 | .device = BFA_PCI_DEVICE_ID_FC_8G2P, | ||
1060 | .subvendor = PCI_ANY_ID, | ||
1061 | .subdevice = PCI_ANY_ID, | ||
1062 | }, | ||
1063 | { | ||
1064 | .vendor = BFA_PCI_VENDOR_ID_BROCADE, | ||
1065 | .device = BFA_PCI_DEVICE_ID_FC_8G1P, | ||
1066 | .subvendor = PCI_ANY_ID, | ||
1067 | .subdevice = PCI_ANY_ID, | ||
1068 | }, | ||
1069 | { | ||
1070 | .vendor = BFA_PCI_VENDOR_ID_BROCADE, | ||
1071 | .device = BFA_PCI_DEVICE_ID_CT, | ||
1072 | .subvendor = PCI_ANY_ID, | ||
1073 | .subdevice = PCI_ANY_ID, | ||
1074 | .class = (PCI_CLASS_SERIAL_FIBER << 8), | ||
1075 | .class_mask = ~0, | ||
1076 | }, | ||
1077 | |||
1078 | {0, 0}, | ||
1079 | }; | ||
1080 | |||
1081 | MODULE_DEVICE_TABLE(pci, bfad_id_table); | ||
1082 | |||
1083 | static struct pci_driver bfad_pci_driver = { | ||
1084 | .name = BFAD_DRIVER_NAME, | ||
1085 | .id_table = bfad_id_table, | ||
1086 | .probe = bfad_pci_probe, | ||
1087 | .remove = __devexit_p(bfad_pci_remove), | ||
1088 | }; | ||
1089 | |||
1090 | /** | ||
1091 | * Linux driver module functions | ||
1092 | */ | ||
1093 | bfa_status_t | ||
1094 | bfad_fc4_module_init(void) | ||
1095 | { | ||
1096 | int rc; | ||
1097 | |||
1098 | rc = bfad_im_module_init(); | ||
1099 | if (rc != BFA_STATUS_OK) | ||
1100 | goto ext; | ||
1101 | |||
1102 | bfad_tm_module_init(); | ||
1103 | if (ipfc_enable) | ||
1104 | bfad_ipfc_module_init(); | ||
1105 | ext: | ||
1106 | return rc; | ||
1107 | } | ||
1108 | |||
1109 | void | ||
1110 | bfad_fc4_module_exit(void) | ||
1111 | { | ||
1112 | if (ipfc_enable) | ||
1113 | bfad_ipfc_module_exit(); | ||
1114 | bfad_tm_module_exit(); | ||
1115 | bfad_im_module_exit(); | ||
1116 | } | ||
1117 | |||
1118 | /** | ||
1119 | * Driver module init. | ||
1120 | */ | ||
1121 | static int __init | ||
1122 | bfad_init(void) | ||
1123 | { | ||
1124 | int error = 0; | ||
1125 | |||
1126 | printk(KERN_INFO "Brocade BFA FC/FCOE SCSI driver - version: %s\n", | ||
1127 | BFAD_DRIVER_VERSION); | ||
1128 | |||
1129 | if (num_sgpgs > 0) | ||
1130 | num_sgpgs_parm = num_sgpgs; | ||
1131 | |||
1132 | error = bfad_fc4_module_init(); | ||
1133 | if (error) { | ||
1134 | error = -ENOMEM; | ||
1135 | printk(KERN_WARNING "bfad_fc4_module_init failure\n"); | ||
1136 | goto ext; | ||
1137 | } | ||
1138 | |||
1139 | if (!strcmp(FCPI_NAME, " fcpim")) | ||
1140 | bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IM; | ||
1141 | if (!strcmp(FCPT_NAME, " fcptm")) | ||
1142 | bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_TM; | ||
1143 | if (!strcmp(IPFC_NAME, " ipfc")) | ||
1144 | bfad_supported_fc4s |= BFA_PORT_ROLE_FCP_IPFC; | ||
1145 | |||
1146 | bfa_ioc_auto_recover(ioc_auto_recover); | ||
1147 | bfa_fcs_rport_set_del_timeout(rport_del_timeout); | ||
1148 | error = pci_register_driver(&bfad_pci_driver); | ||
1149 | |||
1150 | if (error) { | ||
1151 | printk(KERN_WARNING "bfad pci_register_driver failure\n"); | ||
1152 | goto ext; | ||
1153 | } | ||
1154 | |||
1155 | return 0; | ||
1156 | |||
1157 | ext: | ||
1158 | bfad_fc4_module_exit(); | ||
1159 | return error; | ||
1160 | } | ||
1161 | |||
1162 | /** | ||
1163 | * Driver module exit. | ||
1164 | */ | ||
1165 | static void __exit | ||
1166 | bfad_exit(void) | ||
1167 | { | ||
1168 | pci_unregister_driver(&bfad_pci_driver); | ||
1169 | bfad_fc4_module_exit(); | ||
1170 | bfad_free_fwimg(); | ||
1171 | } | ||
1172 | |||
1173 | #define BFAD_PROTO_NAME FCPI_NAME FCPT_NAME IPFC_NAME | ||
1174 | |||
1175 | module_init(bfad_init); | ||
1176 | module_exit(bfad_exit); | ||
1177 | MODULE_LICENSE("GPL"); | ||
1178 | MODULE_DESCRIPTION("Brocade Fibre Channel HBA Driver" BFAD_PROTO_NAME); | ||
1179 | MODULE_AUTHOR("Brocade Communications Systems, Inc."); | ||
1180 | MODULE_VERSION(BFAD_DRIVER_VERSION); | ||
1181 | |||
1182 | |||
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c new file mode 100644 index 000000000000..9129ae3040ff --- /dev/null +++ b/drivers/scsi/bfa/bfad_attr.c | |||
@@ -0,0 +1,649 @@ | |||
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 | * bfa_attr.c Linux driver configuration interface module. | ||
20 | */ | ||
21 | |||
22 | #include "bfad_drv.h" | ||
23 | #include "bfad_im.h" | ||
24 | #include "bfad_trcmod.h" | ||
25 | #include "bfad_attr.h" | ||
26 | |||
27 | /** | ||
28 | * FC_transport_template FC transport template | ||
29 | */ | ||
30 | |||
31 | /** | ||
32 | * FC transport template entry, get SCSI target port ID. | ||
33 | */ | ||
34 | void | ||
35 | bfad_im_get_starget_port_id(struct scsi_target *starget) | ||
36 | { | ||
37 | struct Scsi_Host *shost; | ||
38 | struct bfad_im_port_s *im_port; | ||
39 | struct bfad_s *bfad; | ||
40 | struct bfad_itnim_s *itnim = NULL; | ||
41 | u32 fc_id = -1; | ||
42 | unsigned long flags; | ||
43 | |||
44 | shost = bfad_os_starget_to_shost(starget); | ||
45 | im_port = (struct bfad_im_port_s *) shost->hostdata[0]; | ||
46 | bfad = im_port->bfad; | ||
47 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
48 | |||
49 | itnim = bfad_os_get_itnim(im_port, starget->id); | ||
50 | if (itnim) | ||
51 | fc_id = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); | ||
52 | |||
53 | fc_starget_port_id(starget) = fc_id; | ||
54 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
55 | } | ||
56 | |||
57 | /** | ||
58 | * FC transport template entry, get SCSI target nwwn. | ||
59 | */ | ||
60 | void | ||
61 | bfad_im_get_starget_node_name(struct scsi_target *starget) | ||
62 | { | ||
63 | struct Scsi_Host *shost; | ||
64 | struct bfad_im_port_s *im_port; | ||
65 | struct bfad_s *bfad; | ||
66 | struct bfad_itnim_s *itnim = NULL; | ||
67 | u64 node_name = 0; | ||
68 | unsigned long flags; | ||
69 | |||
70 | shost = bfad_os_starget_to_shost(starget); | ||
71 | im_port = (struct bfad_im_port_s *) shost->hostdata[0]; | ||
72 | bfad = im_port->bfad; | ||
73 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
74 | |||
75 | itnim = bfad_os_get_itnim(im_port, starget->id); | ||
76 | if (itnim) | ||
77 | node_name = bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim); | ||
78 | |||
79 | fc_starget_node_name(starget) = bfa_os_htonll(node_name); | ||
80 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * FC transport template entry, get SCSI target pwwn. | ||
85 | */ | ||
86 | void | ||
87 | bfad_im_get_starget_port_name(struct scsi_target *starget) | ||
88 | { | ||
89 | struct Scsi_Host *shost; | ||
90 | struct bfad_im_port_s *im_port; | ||
91 | struct bfad_s *bfad; | ||
92 | struct bfad_itnim_s *itnim = NULL; | ||
93 | u64 port_name = 0; | ||
94 | unsigned long flags; | ||
95 | |||
96 | shost = bfad_os_starget_to_shost(starget); | ||
97 | im_port = (struct bfad_im_port_s *) shost->hostdata[0]; | ||
98 | bfad = im_port->bfad; | ||
99 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
100 | |||
101 | itnim = bfad_os_get_itnim(im_port, starget->id); | ||
102 | if (itnim) | ||
103 | port_name = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); | ||
104 | |||
105 | fc_starget_port_name(starget) = bfa_os_htonll(port_name); | ||
106 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * FC transport template entry, get SCSI host port ID. | ||
111 | */ | ||
112 | void | ||
113 | bfad_im_get_host_port_id(struct Scsi_Host *shost) | ||
114 | { | ||
115 | struct bfad_im_port_s *im_port = | ||
116 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
117 | struct bfad_port_s *port = im_port->port; | ||
118 | |||
119 | fc_host_port_id(shost) = | ||
120 | bfa_os_hton3b(bfa_fcs_port_get_fcid(port->fcs_port)); | ||
121 | } | ||
122 | |||
123 | |||
124 | |||
125 | |||
126 | |||
127 | struct Scsi_Host * | ||
128 | bfad_os_starget_to_shost(struct scsi_target *starget) | ||
129 | { | ||
130 | return dev_to_shost(starget->dev.parent); | ||
131 | } | ||
132 | |||
133 | /** | ||
134 | * FC transport template entry, get SCSI host port type. | ||
135 | */ | ||
136 | static void | ||
137 | bfad_im_get_host_port_type(struct Scsi_Host *shost) | ||
138 | { | ||
139 | struct bfad_im_port_s *im_port = | ||
140 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
141 | struct bfad_s *bfad = im_port->bfad; | ||
142 | struct bfa_pport_attr_s attr; | ||
143 | |||
144 | bfa_pport_get_attr(&bfad->bfa, &attr); | ||
145 | |||
146 | switch (attr.port_type) { | ||
147 | case BFA_PPORT_TYPE_NPORT: | ||
148 | fc_host_port_type(shost) = FC_PORTTYPE_NPORT; | ||
149 | break; | ||
150 | case BFA_PPORT_TYPE_NLPORT: | ||
151 | fc_host_port_type(shost) = FC_PORTTYPE_NLPORT; | ||
152 | break; | ||
153 | case BFA_PPORT_TYPE_P2P: | ||
154 | fc_host_port_type(shost) = FC_PORTTYPE_PTP; | ||
155 | break; | ||
156 | case BFA_PPORT_TYPE_LPORT: | ||
157 | fc_host_port_type(shost) = FC_PORTTYPE_LPORT; | ||
158 | break; | ||
159 | default: | ||
160 | fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; | ||
161 | break; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | /** | ||
166 | * FC transport template entry, get SCSI host port state. | ||
167 | */ | ||
168 | static void | ||
169 | bfad_im_get_host_port_state(struct Scsi_Host *shost) | ||
170 | { | ||
171 | struct bfad_im_port_s *im_port = | ||
172 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
173 | struct bfad_s *bfad = im_port->bfad; | ||
174 | struct bfa_pport_attr_s attr; | ||
175 | |||
176 | bfa_pport_get_attr(&bfad->bfa, &attr); | ||
177 | |||
178 | switch (attr.port_state) { | ||
179 | case BFA_PPORT_ST_LINKDOWN: | ||
180 | fc_host_port_state(shost) = FC_PORTSTATE_LINKDOWN; | ||
181 | break; | ||
182 | case BFA_PPORT_ST_LINKUP: | ||
183 | fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; | ||
184 | break; | ||
185 | case BFA_PPORT_ST_UNINIT: | ||
186 | case BFA_PPORT_ST_ENABLING_QWAIT: | ||
187 | case BFA_PPORT_ST_ENABLING: | ||
188 | case BFA_PPORT_ST_DISABLING_QWAIT: | ||
189 | case BFA_PPORT_ST_DISABLING: | ||
190 | case BFA_PPORT_ST_DISABLED: | ||
191 | case BFA_PPORT_ST_STOPPED: | ||
192 | case BFA_PPORT_ST_IOCDOWN: | ||
193 | default: | ||
194 | fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN; | ||
195 | break; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * FC transport template entry, get SCSI host active fc4s. | ||
201 | */ | ||
202 | static void | ||
203 | bfad_im_get_host_active_fc4s(struct Scsi_Host *shost) | ||
204 | { | ||
205 | struct bfad_im_port_s *im_port = | ||
206 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
207 | struct bfad_port_s *port = im_port->port; | ||
208 | |||
209 | memset(fc_host_active_fc4s(shost), 0, | ||
210 | sizeof(fc_host_active_fc4s(shost))); | ||
211 | |||
212 | if (port->supported_fc4s & | ||
213 | (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM)) | ||
214 | fc_host_active_fc4s(shost)[2] = 1; | ||
215 | |||
216 | if (port->supported_fc4s & BFA_PORT_ROLE_FCP_IPFC) | ||
217 | fc_host_active_fc4s(shost)[3] = 0x20; | ||
218 | |||
219 | fc_host_active_fc4s(shost)[7] = 1; | ||
220 | } | ||
221 | |||
222 | /** | ||
223 | * FC transport template entry, get SCSI host link speed. | ||
224 | */ | ||
225 | static void | ||
226 | bfad_im_get_host_speed(struct Scsi_Host *shost) | ||
227 | { | ||
228 | struct bfad_im_port_s *im_port = | ||
229 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
230 | struct bfad_s *bfad = im_port->bfad; | ||
231 | struct bfa_pport_attr_s attr; | ||
232 | |||
233 | bfa_pport_get_attr(&bfad->bfa, &attr); | ||
234 | switch (attr.speed) { | ||
235 | case BFA_PPORT_SPEED_8GBPS: | ||
236 | fc_host_speed(shost) = FC_PORTSPEED_8GBIT; | ||
237 | break; | ||
238 | case BFA_PPORT_SPEED_4GBPS: | ||
239 | fc_host_speed(shost) = FC_PORTSPEED_4GBIT; | ||
240 | break; | ||
241 | case BFA_PPORT_SPEED_2GBPS: | ||
242 | fc_host_speed(shost) = FC_PORTSPEED_2GBIT; | ||
243 | break; | ||
244 | case BFA_PPORT_SPEED_1GBPS: | ||
245 | fc_host_speed(shost) = FC_PORTSPEED_1GBIT; | ||
246 | break; | ||
247 | default: | ||
248 | fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; | ||
249 | break; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /** | ||
254 | * FC transport template entry, get SCSI host port type. | ||
255 | */ | ||
256 | static void | ||
257 | bfad_im_get_host_fabric_name(struct Scsi_Host *shost) | ||
258 | { | ||
259 | struct bfad_im_port_s *im_port = | ||
260 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
261 | struct bfad_port_s *port = im_port->port; | ||
262 | wwn_t fabric_nwwn = 0; | ||
263 | |||
264 | fabric_nwwn = bfa_fcs_port_get_fabric_name(port->fcs_port); | ||
265 | |||
266 | fc_host_fabric_name(shost) = bfa_os_htonll(fabric_nwwn); | ||
267 | |||
268 | } | ||
269 | |||
270 | /** | ||
271 | * FC transport template entry, get BFAD statistics. | ||
272 | */ | ||
273 | static struct fc_host_statistics * | ||
274 | bfad_im_get_stats(struct Scsi_Host *shost) | ||
275 | { | ||
276 | struct bfad_im_port_s *im_port = | ||
277 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
278 | struct bfad_s *bfad = im_port->bfad; | ||
279 | struct bfad_hal_comp fcomp; | ||
280 | struct fc_host_statistics *hstats; | ||
281 | bfa_status_t rc; | ||
282 | unsigned long flags; | ||
283 | |||
284 | hstats = &bfad->link_stats; | ||
285 | init_completion(&fcomp.comp); | ||
286 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
287 | memset(hstats, 0, sizeof(struct fc_host_statistics)); | ||
288 | rc = bfa_pport_get_stats(&bfad->bfa, | ||
289 | (union bfa_pport_stats_u *) hstats, | ||
290 | bfad_hcb_comp, &fcomp); | ||
291 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
292 | if (rc != BFA_STATUS_OK) | ||
293 | return NULL; | ||
294 | |||
295 | wait_for_completion(&fcomp.comp); | ||
296 | |||
297 | return hstats; | ||
298 | } | ||
299 | |||
300 | /** | ||
301 | * FC transport template entry, reset BFAD statistics. | ||
302 | */ | ||
303 | static void | ||
304 | bfad_im_reset_stats(struct Scsi_Host *shost) | ||
305 | { | ||
306 | struct bfad_im_port_s *im_port = | ||
307 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
308 | struct bfad_s *bfad = im_port->bfad; | ||
309 | struct bfad_hal_comp fcomp; | ||
310 | unsigned long flags; | ||
311 | bfa_status_t rc; | ||
312 | |||
313 | init_completion(&fcomp.comp); | ||
314 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
315 | rc = bfa_pport_clear_stats(&bfad->bfa, bfad_hcb_comp, &fcomp); | ||
316 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
317 | |||
318 | if (rc != BFA_STATUS_OK) | ||
319 | return; | ||
320 | |||
321 | wait_for_completion(&fcomp.comp); | ||
322 | |||
323 | return; | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * FC transport template entry, get rport loss timeout. | ||
328 | */ | ||
329 | static void | ||
330 | bfad_im_get_rport_loss_tmo(struct fc_rport *rport) | ||
331 | { | ||
332 | struct bfad_itnim_data_s *itnim_data = rport->dd_data; | ||
333 | struct bfad_itnim_s *itnim = itnim_data->itnim; | ||
334 | struct bfad_s *bfad = itnim->im->bfad; | ||
335 | unsigned long flags; | ||
336 | |||
337 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
338 | rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); | ||
339 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
340 | } | ||
341 | |||
342 | /** | ||
343 | * FC transport template entry, set rport loss timeout. | ||
344 | */ | ||
345 | static void | ||
346 | bfad_im_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) | ||
347 | { | ||
348 | struct bfad_itnim_data_s *itnim_data = rport->dd_data; | ||
349 | struct bfad_itnim_s *itnim = itnim_data->itnim; | ||
350 | struct bfad_s *bfad = itnim->im->bfad; | ||
351 | unsigned long flags; | ||
352 | |||
353 | if (timeout > 0) { | ||
354 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
355 | bfa_fcpim_path_tov_set(&bfad->bfa, timeout); | ||
356 | rport->dev_loss_tmo = bfa_fcpim_path_tov_get(&bfad->bfa); | ||
357 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
358 | } | ||
359 | |||
360 | } | ||
361 | |||
362 | struct fc_function_template bfad_im_fc_function_template = { | ||
363 | |||
364 | /* Target dynamic attributes */ | ||
365 | .get_starget_port_id = bfad_im_get_starget_port_id, | ||
366 | .show_starget_port_id = 1, | ||
367 | .get_starget_node_name = bfad_im_get_starget_node_name, | ||
368 | .show_starget_node_name = 1, | ||
369 | .get_starget_port_name = bfad_im_get_starget_port_name, | ||
370 | .show_starget_port_name = 1, | ||
371 | |||
372 | /* Host dynamic attribute */ | ||
373 | .get_host_port_id = bfad_im_get_host_port_id, | ||
374 | .show_host_port_id = 1, | ||
375 | |||
376 | /* Host fixed attributes */ | ||
377 | .show_host_node_name = 1, | ||
378 | .show_host_port_name = 1, | ||
379 | .show_host_supported_classes = 1, | ||
380 | .show_host_supported_fc4s = 1, | ||
381 | .show_host_supported_speeds = 1, | ||
382 | .show_host_maxframe_size = 1, | ||
383 | |||
384 | /* More host dynamic attributes */ | ||
385 | .show_host_port_type = 1, | ||
386 | .get_host_port_type = bfad_im_get_host_port_type, | ||
387 | .show_host_port_state = 1, | ||
388 | .get_host_port_state = bfad_im_get_host_port_state, | ||
389 | .show_host_active_fc4s = 1, | ||
390 | .get_host_active_fc4s = bfad_im_get_host_active_fc4s, | ||
391 | .show_host_speed = 1, | ||
392 | .get_host_speed = bfad_im_get_host_speed, | ||
393 | .show_host_fabric_name = 1, | ||
394 | .get_host_fabric_name = bfad_im_get_host_fabric_name, | ||
395 | |||
396 | .show_host_symbolic_name = 1, | ||
397 | |||
398 | /* Statistics */ | ||
399 | .get_fc_host_stats = bfad_im_get_stats, | ||
400 | .reset_fc_host_stats = bfad_im_reset_stats, | ||
401 | |||
402 | /* Allocation length for host specific data */ | ||
403 | .dd_fcrport_size = sizeof(struct bfad_itnim_data_s *), | ||
404 | |||
405 | /* Remote port fixed attributes */ | ||
406 | .show_rport_maxframe_size = 1, | ||
407 | .show_rport_supported_classes = 1, | ||
408 | .show_rport_dev_loss_tmo = 1, | ||
409 | .get_rport_dev_loss_tmo = bfad_im_get_rport_loss_tmo, | ||
410 | .set_rport_dev_loss_tmo = bfad_im_set_rport_loss_tmo, | ||
411 | }; | ||
412 | |||
413 | /** | ||
414 | * Scsi_Host_attrs SCSI host attributes | ||
415 | */ | ||
416 | static ssize_t | ||
417 | bfad_im_serial_num_show(struct device *dev, struct device_attribute *attr, | ||
418 | char *buf) | ||
419 | { | ||
420 | struct Scsi_Host *shost = class_to_shost(dev); | ||
421 | struct bfad_im_port_s *im_port = | ||
422 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
423 | struct bfad_s *bfad = im_port->bfad; | ||
424 | struct bfa_ioc_attr_s ioc_attr; | ||
425 | |||
426 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
427 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
428 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
429 | ioc_attr.adapter_attr.serial_num); | ||
430 | } | ||
431 | |||
432 | static ssize_t | ||
433 | bfad_im_model_show(struct device *dev, struct device_attribute *attr, | ||
434 | char *buf) | ||
435 | { | ||
436 | struct Scsi_Host *shost = class_to_shost(dev); | ||
437 | struct bfad_im_port_s *im_port = | ||
438 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
439 | struct bfad_s *bfad = im_port->bfad; | ||
440 | struct bfa_ioc_attr_s ioc_attr; | ||
441 | |||
442 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
443 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
444 | return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.model); | ||
445 | } | ||
446 | |||
447 | static ssize_t | ||
448 | bfad_im_model_desc_show(struct device *dev, struct device_attribute *attr, | ||
449 | char *buf) | ||
450 | { | ||
451 | struct Scsi_Host *shost = class_to_shost(dev); | ||
452 | struct bfad_im_port_s *im_port = | ||
453 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
454 | struct bfad_s *bfad = im_port->bfad; | ||
455 | struct bfa_ioc_attr_s ioc_attr; | ||
456 | |||
457 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
458 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
459 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
460 | ioc_attr.adapter_attr.model_descr); | ||
461 | } | ||
462 | |||
463 | static ssize_t | ||
464 | bfad_im_node_name_show(struct device *dev, struct device_attribute *attr, | ||
465 | char *buf) | ||
466 | { | ||
467 | struct Scsi_Host *shost = class_to_shost(dev); | ||
468 | struct bfad_im_port_s *im_port = | ||
469 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
470 | struct bfad_port_s *port = im_port->port; | ||
471 | u64 nwwn; | ||
472 | |||
473 | nwwn = bfa_fcs_port_get_nwwn(port->fcs_port); | ||
474 | return snprintf(buf, PAGE_SIZE, "0x%llx\n", bfa_os_htonll(nwwn)); | ||
475 | } | ||
476 | |||
477 | static ssize_t | ||
478 | bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr, | ||
479 | char *buf) | ||
480 | { | ||
481 | struct Scsi_Host *shost = class_to_shost(dev); | ||
482 | struct bfad_im_port_s *im_port = | ||
483 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
484 | struct bfad_s *bfad = im_port->bfad; | ||
485 | struct bfa_ioc_attr_s ioc_attr; | ||
486 | |||
487 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
488 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
489 | |||
490 | return snprintf(buf, PAGE_SIZE, "Brocade %s FV%s DV%s\n", | ||
491 | ioc_attr.adapter_attr.model, | ||
492 | ioc_attr.adapter_attr.fw_ver, BFAD_DRIVER_VERSION); | ||
493 | } | ||
494 | |||
495 | static ssize_t | ||
496 | bfad_im_hw_version_show(struct device *dev, struct device_attribute *attr, | ||
497 | char *buf) | ||
498 | { | ||
499 | struct Scsi_Host *shost = class_to_shost(dev); | ||
500 | struct bfad_im_port_s *im_port = | ||
501 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
502 | struct bfad_s *bfad = im_port->bfad; | ||
503 | struct bfa_ioc_attr_s ioc_attr; | ||
504 | |||
505 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
506 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
507 | return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.hw_ver); | ||
508 | } | ||
509 | |||
510 | static ssize_t | ||
511 | bfad_im_drv_version_show(struct device *dev, struct device_attribute *attr, | ||
512 | char *buf) | ||
513 | { | ||
514 | return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_VERSION); | ||
515 | } | ||
516 | |||
517 | static ssize_t | ||
518 | bfad_im_optionrom_version_show(struct device *dev, | ||
519 | struct device_attribute *attr, char *buf) | ||
520 | { | ||
521 | struct Scsi_Host *shost = class_to_shost(dev); | ||
522 | struct bfad_im_port_s *im_port = | ||
523 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
524 | struct bfad_s *bfad = im_port->bfad; | ||
525 | struct bfa_ioc_attr_s ioc_attr; | ||
526 | |||
527 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
528 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
529 | return snprintf(buf, PAGE_SIZE, "%s\n", | ||
530 | ioc_attr.adapter_attr.optrom_ver); | ||
531 | } | ||
532 | |||
533 | static ssize_t | ||
534 | bfad_im_fw_version_show(struct device *dev, struct device_attribute *attr, | ||
535 | char *buf) | ||
536 | { | ||
537 | struct Scsi_Host *shost = class_to_shost(dev); | ||
538 | struct bfad_im_port_s *im_port = | ||
539 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
540 | struct bfad_s *bfad = im_port->bfad; | ||
541 | struct bfa_ioc_attr_s ioc_attr; | ||
542 | |||
543 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
544 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
545 | return snprintf(buf, PAGE_SIZE, "%s\n", ioc_attr.adapter_attr.fw_ver); | ||
546 | } | ||
547 | |||
548 | static ssize_t | ||
549 | bfad_im_num_of_ports_show(struct device *dev, struct device_attribute *attr, | ||
550 | char *buf) | ||
551 | { | ||
552 | struct Scsi_Host *shost = class_to_shost(dev); | ||
553 | struct bfad_im_port_s *im_port = | ||
554 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
555 | struct bfad_s *bfad = im_port->bfad; | ||
556 | struct bfa_ioc_attr_s ioc_attr; | ||
557 | |||
558 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
559 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
560 | return snprintf(buf, PAGE_SIZE, "%d\n", ioc_attr.adapter_attr.nports); | ||
561 | } | ||
562 | |||
563 | static ssize_t | ||
564 | bfad_im_drv_name_show(struct device *dev, struct device_attribute *attr, | ||
565 | char *buf) | ||
566 | { | ||
567 | return snprintf(buf, PAGE_SIZE, "%s\n", BFAD_DRIVER_NAME); | ||
568 | } | ||
569 | |||
570 | static ssize_t | ||
571 | bfad_im_num_of_discovered_ports_show(struct device *dev, | ||
572 | struct device_attribute *attr, char *buf) | ||
573 | { | ||
574 | struct Scsi_Host *shost = class_to_shost(dev); | ||
575 | struct bfad_im_port_s *im_port = | ||
576 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
577 | struct bfad_port_s *port = im_port->port; | ||
578 | struct bfad_s *bfad = im_port->bfad; | ||
579 | int nrports = 2048; | ||
580 | wwn_t *rports = NULL; | ||
581 | unsigned long flags; | ||
582 | |||
583 | rports = kzalloc(sizeof(wwn_t) * nrports , GFP_ATOMIC); | ||
584 | if (rports == NULL) | ||
585 | return -ENOMEM; | ||
586 | |||
587 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
588 | bfa_fcs_port_get_rports(port->fcs_port, rports, &nrports); | ||
589 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
590 | kfree(rports); | ||
591 | |||
592 | return snprintf(buf, PAGE_SIZE, "%d\n", nrports); | ||
593 | } | ||
594 | |||
595 | static DEVICE_ATTR(serial_number, S_IRUGO, | ||
596 | bfad_im_serial_num_show, NULL); | ||
597 | static DEVICE_ATTR(model, S_IRUGO, bfad_im_model_show, NULL); | ||
598 | static DEVICE_ATTR(model_description, S_IRUGO, | ||
599 | bfad_im_model_desc_show, NULL); | ||
600 | static DEVICE_ATTR(node_name, S_IRUGO, bfad_im_node_name_show, NULL); | ||
601 | static DEVICE_ATTR(symbolic_name, S_IRUGO, | ||
602 | bfad_im_symbolic_name_show, NULL); | ||
603 | static DEVICE_ATTR(hardware_version, S_IRUGO, | ||
604 | bfad_im_hw_version_show, NULL); | ||
605 | static DEVICE_ATTR(driver_version, S_IRUGO, | ||
606 | bfad_im_drv_version_show, NULL); | ||
607 | static DEVICE_ATTR(option_rom_version, S_IRUGO, | ||
608 | bfad_im_optionrom_version_show, NULL); | ||
609 | static DEVICE_ATTR(firmware_version, S_IRUGO, | ||
610 | bfad_im_fw_version_show, NULL); | ||
611 | static DEVICE_ATTR(number_of_ports, S_IRUGO, | ||
612 | bfad_im_num_of_ports_show, NULL); | ||
613 | static DEVICE_ATTR(driver_name, S_IRUGO, bfad_im_drv_name_show, NULL); | ||
614 | static DEVICE_ATTR(number_of_discovered_ports, S_IRUGO, | ||
615 | bfad_im_num_of_discovered_ports_show, NULL); | ||
616 | |||
617 | struct device_attribute *bfad_im_host_attrs[] = { | ||
618 | &dev_attr_serial_number, | ||
619 | &dev_attr_model, | ||
620 | &dev_attr_model_description, | ||
621 | &dev_attr_node_name, | ||
622 | &dev_attr_symbolic_name, | ||
623 | &dev_attr_hardware_version, | ||
624 | &dev_attr_driver_version, | ||
625 | &dev_attr_option_rom_version, | ||
626 | &dev_attr_firmware_version, | ||
627 | &dev_attr_number_of_ports, | ||
628 | &dev_attr_driver_name, | ||
629 | &dev_attr_number_of_discovered_ports, | ||
630 | NULL, | ||
631 | }; | ||
632 | |||
633 | struct device_attribute *bfad_im_vport_attrs[] = { | ||
634 | &dev_attr_serial_number, | ||
635 | &dev_attr_model, | ||
636 | &dev_attr_model_description, | ||
637 | &dev_attr_node_name, | ||
638 | &dev_attr_symbolic_name, | ||
639 | &dev_attr_hardware_version, | ||
640 | &dev_attr_driver_version, | ||
641 | &dev_attr_option_rom_version, | ||
642 | &dev_attr_firmware_version, | ||
643 | &dev_attr_number_of_ports, | ||
644 | &dev_attr_driver_name, | ||
645 | &dev_attr_number_of_discovered_ports, | ||
646 | NULL, | ||
647 | }; | ||
648 | |||
649 | |||
diff --git a/drivers/scsi/bfa/bfad_attr.h b/drivers/scsi/bfa/bfad_attr.h new file mode 100644 index 000000000000..4d3312da6a81 --- /dev/null +++ b/drivers/scsi/bfa/bfad_attr.h | |||
@@ -0,0 +1,65 @@ | |||
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 | #ifndef __BFAD_ATTR_H__ | ||
19 | #define __BFAD_ATTR_H__ | ||
20 | /** | ||
21 | * bfad_attr.h VMware driver configuration interface module. | ||
22 | */ | ||
23 | |||
24 | /** | ||
25 | * FC_transport_template FC transport template | ||
26 | */ | ||
27 | |||
28 | struct Scsi_Host* | ||
29 | bfad_os_dev_to_shost(struct scsi_target *starget); | ||
30 | |||
31 | /** | ||
32 | * FC transport template entry, get SCSI target port ID. | ||
33 | */ | ||
34 | void | ||
35 | bfad_im_get_starget_port_id(struct scsi_target *starget); | ||
36 | |||
37 | /** | ||
38 | * FC transport template entry, get SCSI target nwwn. | ||
39 | */ | ||
40 | void | ||
41 | bfad_im_get_starget_node_name(struct scsi_target *starget); | ||
42 | |||
43 | /** | ||
44 | * FC transport template entry, get SCSI target pwwn. | ||
45 | */ | ||
46 | void | ||
47 | bfad_im_get_starget_port_name(struct scsi_target *starget); | ||
48 | |||
49 | /** | ||
50 | * FC transport template entry, get SCSI host port ID. | ||
51 | */ | ||
52 | void | ||
53 | bfad_im_get_host_port_id(struct Scsi_Host *shost); | ||
54 | |||
55 | /** | ||
56 | * FC transport template entry, issue a LIP. | ||
57 | */ | ||
58 | int | ||
59 | bfad_im_issue_fc_host_lip(struct Scsi_Host *shost); | ||
60 | |||
61 | struct Scsi_Host* | ||
62 | bfad_os_starget_to_shost(struct scsi_target *starget); | ||
63 | |||
64 | |||
65 | #endif /* __BFAD_ATTR_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfad_drv.h b/drivers/scsi/bfa/bfad_drv.h new file mode 100644 index 000000000000..172c81e25c1c --- /dev/null +++ b/drivers/scsi/bfa/bfad_drv.h | |||
@@ -0,0 +1,295 @@ | |||
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 | * Contains base driver definitions. | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * bfa_drv.h Linux driver data structures. | ||
24 | */ | ||
25 | |||
26 | #ifndef __BFAD_DRV_H__ | ||
27 | #define __BFAD_DRV_H__ | ||
28 | |||
29 | #include "bfa_os_inc.h" | ||
30 | |||
31 | #include <bfa.h> | ||
32 | #include <bfa_svc.h> | ||
33 | #include <fcs/bfa_fcs.h> | ||
34 | #include <defs/bfa_defs_pci.h> | ||
35 | #include <defs/bfa_defs_port.h> | ||
36 | #include <defs/bfa_defs_rport.h> | ||
37 | #include <fcs/bfa_fcs_rport.h> | ||
38 | #include <defs/bfa_defs_vport.h> | ||
39 | #include <fcs/bfa_fcs_vport.h> | ||
40 | |||
41 | #include <cs/bfa_plog.h> | ||
42 | #include "aen/bfa_aen.h" | ||
43 | #include <log/bfa_log_linux.h> | ||
44 | |||
45 | #define BFAD_DRIVER_NAME "bfa" | ||
46 | #ifdef BFA_DRIVER_VERSION | ||
47 | #define BFAD_DRIVER_VERSION BFA_DRIVER_VERSION | ||
48 | #else | ||
49 | #define BFAD_DRIVER_VERSION "2.0.0.0" | ||
50 | #endif | ||
51 | |||
52 | |||
53 | #define BFAD_IRQ_FLAGS IRQF_SHARED | ||
54 | |||
55 | /* | ||
56 | * BFAD flags | ||
57 | */ | ||
58 | #define BFAD_MSIX_ON 0x00000001 | ||
59 | #define BFAD_HAL_INIT_DONE 0x00000002 | ||
60 | #define BFAD_DRV_INIT_DONE 0x00000004 | ||
61 | #define BFAD_CFG_PPORT_DONE 0x00000008 | ||
62 | #define BFAD_HAL_START_DONE 0x00000010 | ||
63 | #define BFAD_PORT_ONLINE 0x00000020 | ||
64 | #define BFAD_RPORT_ONLINE 0x00000040 | ||
65 | |||
66 | #define BFAD_PORT_DELETE 0x00000001 | ||
67 | |||
68 | /* | ||
69 | * BFAD related definition | ||
70 | */ | ||
71 | #define SCSI_SCAN_DELAY HZ | ||
72 | #define BFAD_STOP_TIMEOUT 30 | ||
73 | #define BFAD_SUSPEND_TIMEOUT BFAD_STOP_TIMEOUT | ||
74 | |||
75 | /* | ||
76 | * BFAD configuration parameter default values | ||
77 | */ | ||
78 | #define BFAD_LUN_QUEUE_DEPTH 32 | ||
79 | #define BFAD_IO_MAX_SGE SG_ALL | ||
80 | |||
81 | #define bfad_isr_t irq_handler_t | ||
82 | |||
83 | #define MAX_MSIX_ENTRY 22 | ||
84 | |||
85 | struct bfad_msix_s { | ||
86 | struct bfad_s *bfad; | ||
87 | struct msix_entry msix; | ||
88 | }; | ||
89 | |||
90 | enum bfad_port_pvb_type { | ||
91 | BFAD_PORT_PHYS_BASE = 0, | ||
92 | BFAD_PORT_PHYS_VPORT = 1, | ||
93 | BFAD_PORT_VF_BASE = 2, | ||
94 | BFAD_PORT_VF_VPORT = 3, | ||
95 | }; | ||
96 | |||
97 | /* | ||
98 | * PORT data structure | ||
99 | */ | ||
100 | struct bfad_port_s { | ||
101 | struct list_head list_entry; | ||
102 | struct bfad_s *bfad; | ||
103 | struct bfa_fcs_port_s *fcs_port; | ||
104 | u32 roles; | ||
105 | s32 flags; | ||
106 | u32 supported_fc4s; | ||
107 | u8 ipfc_flags; | ||
108 | enum bfad_port_pvb_type pvb_type; | ||
109 | struct bfad_im_port_s *im_port; /* IM specific data */ | ||
110 | struct bfad_tm_port_s *tm_port; /* TM specific data */ | ||
111 | struct bfad_ipfc_port_s *ipfc_port; /* IPFC specific data */ | ||
112 | }; | ||
113 | |||
114 | /* | ||
115 | * VPORT data structure | ||
116 | */ | ||
117 | struct bfad_vport_s { | ||
118 | struct bfad_port_s drv_port; | ||
119 | struct bfa_fcs_vport_s fcs_vport; | ||
120 | struct completion *comp_del; | ||
121 | }; | ||
122 | |||
123 | /* | ||
124 | * VF data structure | ||
125 | */ | ||
126 | struct bfad_vf_s { | ||
127 | bfa_fcs_vf_t fcs_vf; | ||
128 | struct bfad_port_s base_port; /* base port for vf */ | ||
129 | struct bfad_s *bfad; | ||
130 | }; | ||
131 | |||
132 | struct bfad_cfg_param_s { | ||
133 | u32 rport_del_timeout; | ||
134 | u32 ioc_queue_depth; | ||
135 | u32 lun_queue_depth; | ||
136 | u32 io_max_sge; | ||
137 | u32 binding_method; | ||
138 | }; | ||
139 | |||
140 | #define BFAD_AEN_MAX_APPS 8 | ||
141 | struct bfad_aen_file_s { | ||
142 | struct list_head qe; | ||
143 | struct bfad_s *bfad; | ||
144 | s32 ri; | ||
145 | s32 app_id; | ||
146 | }; | ||
147 | |||
148 | /* | ||
149 | * BFAD (PCI function) data structure | ||
150 | */ | ||
151 | struct bfad_s { | ||
152 | struct list_head list_entry; | ||
153 | struct bfa_s bfa; | ||
154 | struct bfa_fcs_s bfa_fcs; | ||
155 | struct pci_dev *pcidev; | ||
156 | const char *pci_name; | ||
157 | struct bfa_pcidev_s hal_pcidev; | ||
158 | struct bfa_ioc_pci_attr_s pci_attr; | ||
159 | unsigned long pci_bar0_map; | ||
160 | void __iomem *pci_bar0_kva; | ||
161 | struct completion comp; | ||
162 | struct completion suspend; | ||
163 | struct completion disable_comp; | ||
164 | bfa_boolean_t disable_active; | ||
165 | struct bfad_port_s pport; /* physical port of the BFAD */ | ||
166 | struct bfa_meminfo_s meminfo; | ||
167 | struct bfa_iocfc_cfg_s ioc_cfg; | ||
168 | u32 inst_no; /* BFAD instance number */ | ||
169 | u32 bfad_flags; | ||
170 | spinlock_t bfad_lock; | ||
171 | struct bfad_cfg_param_s cfg_data; | ||
172 | struct bfad_msix_s msix_tab[MAX_MSIX_ENTRY]; | ||
173 | int nvec; | ||
174 | char adapter_name[BFA_ADAPTER_SYM_NAME_LEN]; | ||
175 | char port_name[BFA_ADAPTER_SYM_NAME_LEN]; | ||
176 | struct timer_list hal_tmo; | ||
177 | unsigned long hs_start; | ||
178 | struct bfad_im_s *im; /* IM specific data */ | ||
179 | struct bfad_tm_s *tm; /* TM specific data */ | ||
180 | struct bfad_ipfc_s *ipfc; /* IPFC specific data */ | ||
181 | struct bfa_log_mod_s log_data; | ||
182 | struct bfa_trc_mod_s *trcmod; | ||
183 | struct bfa_log_mod_s *logmod; | ||
184 | struct bfa_aen_s *aen; | ||
185 | struct bfa_aen_s aen_buf; | ||
186 | struct bfad_aen_file_s file_buf[BFAD_AEN_MAX_APPS]; | ||
187 | struct list_head file_q; | ||
188 | struct list_head file_free_q; | ||
189 | struct bfa_plog_s plog_buf; | ||
190 | int ref_count; | ||
191 | bfa_boolean_t ipfc_enabled; | ||
192 | struct fc_host_statistics link_stats; | ||
193 | |||
194 | struct kobject *bfa_kobj; | ||
195 | struct kobject *ioc_kobj; | ||
196 | struct kobject *pport_kobj; | ||
197 | struct kobject *lport_kobj; | ||
198 | }; | ||
199 | |||
200 | /* | ||
201 | * RPORT data structure | ||
202 | */ | ||
203 | struct bfad_rport_s { | ||
204 | struct bfa_fcs_rport_s fcs_rport; | ||
205 | }; | ||
206 | |||
207 | struct bfad_buf_info { | ||
208 | void *virt; | ||
209 | dma_addr_t phys; | ||
210 | u32 size; | ||
211 | }; | ||
212 | |||
213 | struct bfad_fcxp { | ||
214 | struct bfad_port_s *port; | ||
215 | struct bfa_rport_s *bfa_rport; | ||
216 | bfa_status_t req_status; | ||
217 | u16 tag; | ||
218 | u16 rsp_len; | ||
219 | u16 rsp_maxlen; | ||
220 | u8 use_ireqbuf; | ||
221 | u8 use_irspbuf; | ||
222 | u32 num_req_sgles; | ||
223 | u32 num_rsp_sgles; | ||
224 | struct fchs_s fchs; | ||
225 | void *reqbuf_info; | ||
226 | void *rspbuf_info; | ||
227 | struct bfa_sge_s *req_sge; | ||
228 | struct bfa_sge_s *rsp_sge; | ||
229 | fcxp_send_cb_t send_cbfn; | ||
230 | void *send_cbarg; | ||
231 | void *bfa_fcxp; | ||
232 | struct completion comp; | ||
233 | }; | ||
234 | |||
235 | struct bfad_hal_comp { | ||
236 | bfa_status_t status; | ||
237 | struct completion comp; | ||
238 | }; | ||
239 | |||
240 | /* | ||
241 | * Macro to obtain the immediate lower power | ||
242 | * of two for the integer. | ||
243 | */ | ||
244 | #define nextLowerInt(x) \ | ||
245 | do { \ | ||
246 | int j; \ | ||
247 | (*x)--; \ | ||
248 | for (j = 1; j < (sizeof(int) * 8); j <<= 1) \ | ||
249 | (*x) = (*x) | (*x) >> j; \ | ||
250 | (*x)++; \ | ||
251 | (*x) = (*x) >> 1; \ | ||
252 | } while (0) | ||
253 | |||
254 | |||
255 | bfa_status_t bfad_vport_create(struct bfad_s *bfad, u16 vf_id, | ||
256 | struct bfa_port_cfg_s *port_cfg); | ||
257 | bfa_status_t bfad_vf_create(struct bfad_s *bfad, u16 vf_id, | ||
258 | struct bfa_port_cfg_s *port_cfg); | ||
259 | bfa_status_t bfad_cfg_pport(struct bfad_s *bfad, enum bfa_port_role role); | ||
260 | bfa_status_t bfad_drv_init(struct bfad_s *bfad); | ||
261 | void bfad_drv_start(struct bfad_s *bfad); | ||
262 | void bfad_uncfg_pport(struct bfad_s *bfad); | ||
263 | void bfad_drv_stop(struct bfad_s *bfad); | ||
264 | void bfad_remove_intr(struct bfad_s *bfad); | ||
265 | void bfad_hal_mem_release(struct bfad_s *bfad); | ||
266 | void bfad_hcb_comp(void *arg, bfa_status_t status); | ||
267 | |||
268 | int bfad_setup_intr(struct bfad_s *bfad); | ||
269 | void bfad_remove_intr(struct bfad_s *bfad); | ||
270 | |||
271 | void bfad_update_hal_cfg(struct bfa_iocfc_cfg_s *bfa_cfg); | ||
272 | bfa_status_t bfad_hal_mem_alloc(struct bfad_s *bfad); | ||
273 | void bfad_bfa_tmo(unsigned long data); | ||
274 | void bfad_init_timer(struct bfad_s *bfad); | ||
275 | int bfad_pci_init(struct pci_dev *pdev, struct bfad_s *bfad); | ||
276 | void bfad_pci_uninit(struct pci_dev *pdev, struct bfad_s *bfad); | ||
277 | void bfad_fcs_port_cfg(struct bfad_s *bfad); | ||
278 | void bfad_drv_uninit(struct bfad_s *bfad); | ||
279 | void bfad_drv_log_level_set(struct bfad_s *bfad); | ||
280 | bfa_status_t bfad_fc4_module_init(void); | ||
281 | void bfad_fc4_module_exit(void); | ||
282 | |||
283 | void bfad_pci_remove(struct pci_dev *pdev); | ||
284 | int bfad_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid); | ||
285 | void bfad_os_rport_online_wait(struct bfad_s *bfad); | ||
286 | int bfad_os_get_linkup_delay(struct bfad_s *bfad); | ||
287 | int bfad_install_msix_handler(struct bfad_s *bfad); | ||
288 | |||
289 | extern struct idr bfad_im_port_index; | ||
290 | extern struct list_head bfad_list; | ||
291 | extern int bfa_lun_queue_depth; | ||
292 | extern int bfad_supported_fc4s; | ||
293 | extern int bfa_linkup_delay; | ||
294 | |||
295 | #endif /* __BFAD_DRV_H__ */ | ||
diff --git a/drivers/scsi/bfa/bfad_fwimg.c b/drivers/scsi/bfa/bfad_fwimg.c new file mode 100644 index 000000000000..b2f6949bc8d3 --- /dev/null +++ b/drivers/scsi/bfa/bfad_fwimg.c | |||
@@ -0,0 +1,95 @@ | |||
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 | * bfad_fwimg.c Linux driver PCI interface module. | ||
20 | */ | ||
21 | #include <bfa_os_inc.h> | ||
22 | #include <bfad_drv.h> | ||
23 | #include <bfad_im_compat.h> | ||
24 | #include <defs/bfa_defs_version.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/sched.h> | ||
27 | #include <linux/init.h> | ||
28 | #include <linux/fs.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/fcntl.h> | ||
31 | #include <linux/pci.h> | ||
32 | #include <linux/firmware.h> | ||
33 | #include <bfa_fwimg_priv.h> | ||
34 | #include <bfa.h> | ||
35 | |||
36 | u32 bfi_image_ct_size; | ||
37 | u32 bfi_image_cb_size; | ||
38 | u32 *bfi_image_ct; | ||
39 | u32 *bfi_image_cb; | ||
40 | |||
41 | |||
42 | #define BFAD_FW_FILE_CT "ctfw.bin" | ||
43 | #define BFAD_FW_FILE_CB "cbfw.bin" | ||
44 | |||
45 | u32 * | ||
46 | bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image, | ||
47 | u32 *bfi_image_size, char *fw_name) | ||
48 | { | ||
49 | const struct firmware *fw; | ||
50 | |||
51 | if (request_firmware(&fw, fw_name, &pdev->dev)) { | ||
52 | printk(KERN_ALERT "Can't locate firmware %s\n", fw_name); | ||
53 | goto error; | ||
54 | } | ||
55 | |||
56 | *bfi_image = vmalloc(fw->size); | ||
57 | if (NULL == *bfi_image) { | ||
58 | printk(KERN_ALERT "Fail to allocate buffer for fw image " | ||
59 | "size=%x!\n", (u32) fw->size); | ||
60 | goto error; | ||
61 | } | ||
62 | |||
63 | memcpy(*bfi_image, fw->data, fw->size); | ||
64 | *bfi_image_size = fw->size/sizeof(u32); | ||
65 | |||
66 | return(*bfi_image); | ||
67 | |||
68 | error: | ||
69 | return(NULL); | ||
70 | } | ||
71 | |||
72 | u32 * | ||
73 | bfad_get_firmware_buf(struct pci_dev *pdev) | ||
74 | { | ||
75 | if (pdev->device == BFA_PCI_DEVICE_ID_CT) { | ||
76 | if (bfi_image_ct_size == 0) | ||
77 | bfad_read_firmware(pdev, &bfi_image_ct, | ||
78 | &bfi_image_ct_size, BFAD_FW_FILE_CT); | ||
79 | return(bfi_image_ct); | ||
80 | } else { | ||
81 | if (bfi_image_cb_size == 0) | ||
82 | bfad_read_firmware(pdev, &bfi_image_cb, | ||
83 | &bfi_image_cb_size, BFAD_FW_FILE_CB); | ||
84 | return(bfi_image_cb); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | u32 * | ||
89 | bfi_image_ct_get_chunk(u32 off) | ||
90 | { return (u32 *)(bfi_image_ct + off); } | ||
91 | |||
92 | u32 * | ||
93 | bfi_image_cb_get_chunk(u32 off) | ||
94 | { return (u32 *)(bfi_image_cb + off); } | ||
95 | |||
diff --git a/drivers/scsi/bfa/bfad_im.c b/drivers/scsi/bfa/bfad_im.c new file mode 100644 index 000000000000..158c99243c08 --- /dev/null +++ b/drivers/scsi/bfa/bfad_im.c | |||
@@ -0,0 +1,1230 @@ | |||
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 | * bfad_im.c Linux driver IM module. | ||
20 | */ | ||
21 | |||
22 | #include "bfad_drv.h" | ||
23 | #include "bfad_im.h" | ||
24 | #include "bfad_trcmod.h" | ||
25 | #include "bfa_cb_ioim_macros.h" | ||
26 | #include <fcb/bfa_fcb_fcpim.h> | ||
27 | |||
28 | BFA_TRC_FILE(LDRV, IM); | ||
29 | |||
30 | DEFINE_IDR(bfad_im_port_index); | ||
31 | struct scsi_transport_template *bfad_im_scsi_transport_template; | ||
32 | static void bfad_im_itnim_work_handler(struct work_struct *work); | ||
33 | static int bfad_im_queuecommand(struct scsi_cmnd *cmnd, | ||
34 | void (*done)(struct scsi_cmnd *)); | ||
35 | static int bfad_im_slave_alloc(struct scsi_device *sdev); | ||
36 | |||
37 | void | ||
38 | bfa_cb_ioim_done(void *drv, struct bfad_ioim_s *dio, | ||
39 | enum bfi_ioim_status io_status, u8 scsi_status, | ||
40 | int sns_len, u8 *sns_info, s32 residue) | ||
41 | { | ||
42 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
43 | struct bfad_s *bfad = drv; | ||
44 | struct bfad_itnim_data_s *itnim_data; | ||
45 | struct bfad_itnim_s *itnim; | ||
46 | |||
47 | switch (io_status) { | ||
48 | case BFI_IOIM_STS_OK: | ||
49 | bfa_trc(bfad, scsi_status); | ||
50 | cmnd->result = ScsiResult(DID_OK, scsi_status); | ||
51 | scsi_set_resid(cmnd, 0); | ||
52 | |||
53 | if (sns_len > 0) { | ||
54 | bfa_trc(bfad, sns_len); | ||
55 | if (sns_len > SCSI_SENSE_BUFFERSIZE) | ||
56 | sns_len = SCSI_SENSE_BUFFERSIZE; | ||
57 | memcpy(cmnd->sense_buffer, sns_info, sns_len); | ||
58 | } | ||
59 | if (residue > 0) | ||
60 | scsi_set_resid(cmnd, residue); | ||
61 | break; | ||
62 | |||
63 | case BFI_IOIM_STS_ABORTED: | ||
64 | case BFI_IOIM_STS_TIMEDOUT: | ||
65 | case BFI_IOIM_STS_PATHTOV: | ||
66 | default: | ||
67 | cmnd->result = ScsiResult(DID_ERROR, 0); | ||
68 | } | ||
69 | |||
70 | /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */ | ||
71 | if (cmnd->device->host != NULL) | ||
72 | scsi_dma_unmap(cmnd); | ||
73 | |||
74 | cmnd->host_scribble = NULL; | ||
75 | bfa_trc(bfad, cmnd->result); | ||
76 | |||
77 | itnim_data = cmnd->device->hostdata; | ||
78 | if (itnim_data) { | ||
79 | itnim = itnim_data->itnim; | ||
80 | if (!cmnd->result && itnim && | ||
81 | (bfa_lun_queue_depth > cmnd->device->queue_depth)) { | ||
82 | /* Queue depth adjustment for good status completion */ | ||
83 | bfad_os_ramp_up_qdepth(itnim, cmnd->device); | ||
84 | } else if (cmnd->result == SAM_STAT_TASK_SET_FULL && itnim) { | ||
85 | /* qfull handling */ | ||
86 | bfad_os_handle_qfull(itnim, cmnd->device); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | cmnd->scsi_done(cmnd); | ||
91 | } | ||
92 | |||
93 | void | ||
94 | bfa_cb_ioim_good_comp(void *drv, struct bfad_ioim_s *dio) | ||
95 | { | ||
96 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
97 | struct bfad_itnim_data_s *itnim_data; | ||
98 | struct bfad_itnim_s *itnim; | ||
99 | |||
100 | cmnd->result = ScsiResult(DID_OK, SCSI_STATUS_GOOD); | ||
101 | |||
102 | /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */ | ||
103 | if (cmnd->device->host != NULL) | ||
104 | scsi_dma_unmap(cmnd); | ||
105 | |||
106 | cmnd->host_scribble = NULL; | ||
107 | |||
108 | /* Queue depth adjustment */ | ||
109 | if (bfa_lun_queue_depth > cmnd->device->queue_depth) { | ||
110 | itnim_data = cmnd->device->hostdata; | ||
111 | if (itnim_data) { | ||
112 | itnim = itnim_data->itnim; | ||
113 | if (itnim) | ||
114 | bfad_os_ramp_up_qdepth(itnim, cmnd->device); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | cmnd->scsi_done(cmnd); | ||
119 | } | ||
120 | |||
121 | void | ||
122 | bfa_cb_ioim_abort(void *drv, struct bfad_ioim_s *dio) | ||
123 | { | ||
124 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dio; | ||
125 | struct bfad_s *bfad = drv; | ||
126 | |||
127 | cmnd->result = ScsiResult(DID_ERROR, 0); | ||
128 | |||
129 | /* Unmap DMA, if host is NULL, it means a scsi passthru cmd */ | ||
130 | if (cmnd->device->host != NULL) | ||
131 | scsi_dma_unmap(cmnd); | ||
132 | |||
133 | bfa_trc(bfad, cmnd->result); | ||
134 | cmnd->host_scribble = NULL; | ||
135 | } | ||
136 | |||
137 | void | ||
138 | bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, | ||
139 | enum bfi_tskim_status tsk_status) | ||
140 | { | ||
141 | struct scsi_cmnd *cmnd = (struct scsi_cmnd *)dtsk; | ||
142 | wait_queue_head_t *wq; | ||
143 | |||
144 | cmnd->SCp.Status |= tsk_status << 1; | ||
145 | set_bit(IO_DONE_BIT, (unsigned long *)&cmnd->SCp.Status); | ||
146 | wq = (wait_queue_head_t *) cmnd->SCp.ptr; | ||
147 | cmnd->SCp.ptr = NULL; | ||
148 | |||
149 | if (wq) | ||
150 | wake_up(wq); | ||
151 | } | ||
152 | |||
153 | void | ||
154 | bfa_cb_ioim_resfree(void *drv) | ||
155 | { | ||
156 | } | ||
157 | |||
158 | /** | ||
159 | * Scsi_Host_template SCSI host template | ||
160 | */ | ||
161 | /** | ||
162 | * Scsi_Host template entry, returns BFAD PCI info. | ||
163 | */ | ||
164 | static const char * | ||
165 | bfad_im_info(struct Scsi_Host *shost) | ||
166 | { | ||
167 | static char bfa_buf[256]; | ||
168 | struct bfad_im_port_s *im_port = | ||
169 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
170 | struct bfa_ioc_attr_s ioc_attr; | ||
171 | struct bfad_s *bfad = im_port->bfad; | ||
172 | |||
173 | memset(&ioc_attr, 0, sizeof(ioc_attr)); | ||
174 | bfa_get_attr(&bfad->bfa, &ioc_attr); | ||
175 | |||
176 | memset(bfa_buf, 0, sizeof(bfa_buf)); | ||
177 | snprintf(bfa_buf, sizeof(bfa_buf), | ||
178 | "Brocade FC/FCOE Adapter, " "model: %s hwpath: %s driver: %s", | ||
179 | ioc_attr.adapter_attr.model, bfad->pci_name, | ||
180 | BFAD_DRIVER_VERSION); | ||
181 | return bfa_buf; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Scsi_Host template entry, aborts the specified SCSI command. | ||
186 | * | ||
187 | * Returns: SUCCESS or FAILED. | ||
188 | */ | ||
189 | static int | ||
190 | bfad_im_abort_handler(struct scsi_cmnd *cmnd) | ||
191 | { | ||
192 | struct Scsi_Host *shost = cmnd->device->host; | ||
193 | struct bfad_im_port_s *im_port = | ||
194 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
195 | struct bfad_s *bfad = im_port->bfad; | ||
196 | struct bfa_ioim_s *hal_io; | ||
197 | unsigned long flags; | ||
198 | u32 timeout; | ||
199 | int rc = FAILED; | ||
200 | |||
201 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
202 | hal_io = (struct bfa_ioim_s *) cmnd->host_scribble; | ||
203 | if (!hal_io) { | ||
204 | /* IO has been completed, retrun success */ | ||
205 | rc = SUCCESS; | ||
206 | goto out; | ||
207 | } | ||
208 | if (hal_io->dio != (struct bfad_ioim_s *) cmnd) { | ||
209 | rc = FAILED; | ||
210 | goto out; | ||
211 | } | ||
212 | |||
213 | bfa_trc(bfad, hal_io->iotag); | ||
214 | bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT, | ||
215 | im_port->shost->host_no, cmnd, hal_io->iotag); | ||
216 | bfa_ioim_abort(hal_io); | ||
217 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
218 | |||
219 | /* Need to wait until the command get aborted */ | ||
220 | timeout = 10; | ||
221 | while ((struct bfa_ioim_s *) cmnd->host_scribble == hal_io) { | ||
222 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
223 | schedule_timeout(timeout); | ||
224 | if (timeout < 4 * HZ) | ||
225 | timeout *= 2; | ||
226 | } | ||
227 | |||
228 | cmnd->scsi_done(cmnd); | ||
229 | bfa_trc(bfad, hal_io->iotag); | ||
230 | bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_ABORT_COMP, | ||
231 | im_port->shost->host_no, cmnd, hal_io->iotag); | ||
232 | return SUCCESS; | ||
233 | out: | ||
234 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
235 | return rc; | ||
236 | } | ||
237 | |||
238 | static bfa_status_t | ||
239 | bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd, | ||
240 | struct bfad_itnim_s *itnim) | ||
241 | { | ||
242 | struct bfa_tskim_s *tskim; | ||
243 | struct bfa_itnim_s *bfa_itnim; | ||
244 | bfa_status_t rc = BFA_STATUS_OK; | ||
245 | |||
246 | bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); | ||
247 | tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd); | ||
248 | if (!tskim) { | ||
249 | BFA_DEV_PRINTF(bfad, BFA_ERR, | ||
250 | "target reset, fail to allocate tskim\n"); | ||
251 | rc = BFA_STATUS_FAILED; | ||
252 | goto out; | ||
253 | } | ||
254 | |||
255 | /* | ||
256 | * Set host_scribble to NULL to avoid aborting a task command if | ||
257 | * happens. | ||
258 | */ | ||
259 | cmnd->host_scribble = NULL; | ||
260 | cmnd->SCp.Status = 0; | ||
261 | bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); | ||
262 | bfa_tskim_start(tskim, bfa_itnim, (lun_t)0, | ||
263 | FCP_TM_TARGET_RESET, BFAD_TARGET_RESET_TMO); | ||
264 | out: | ||
265 | return rc; | ||
266 | } | ||
267 | |||
268 | /** | ||
269 | * Scsi_Host template entry, resets a LUN and abort its all commands. | ||
270 | * | ||
271 | * Returns: SUCCESS or FAILED. | ||
272 | * | ||
273 | */ | ||
274 | static int | ||
275 | bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd) | ||
276 | { | ||
277 | struct Scsi_Host *shost = cmnd->device->host; | ||
278 | struct bfad_im_port_s *im_port = | ||
279 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
280 | struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata; | ||
281 | struct bfad_s *bfad = im_port->bfad; | ||
282 | struct bfa_tskim_s *tskim; | ||
283 | struct bfad_itnim_s *itnim; | ||
284 | struct bfa_itnim_s *bfa_itnim; | ||
285 | DECLARE_WAIT_QUEUE_HEAD(wq); | ||
286 | int rc = SUCCESS; | ||
287 | unsigned long flags; | ||
288 | enum bfi_tskim_status task_status; | ||
289 | |||
290 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
291 | itnim = itnim_data->itnim; | ||
292 | if (!itnim) { | ||
293 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
294 | rc = FAILED; | ||
295 | goto out; | ||
296 | } | ||
297 | |||
298 | tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd); | ||
299 | if (!tskim) { | ||
300 | BFA_DEV_PRINTF(bfad, BFA_ERR, | ||
301 | "LUN reset, fail to allocate tskim"); | ||
302 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
303 | rc = FAILED; | ||
304 | goto out; | ||
305 | } | ||
306 | |||
307 | /** | ||
308 | * Set host_scribble to NULL to avoid aborting a task command | ||
309 | * if happens. | ||
310 | */ | ||
311 | cmnd->host_scribble = NULL; | ||
312 | cmnd->SCp.ptr = (char *)&wq; | ||
313 | cmnd->SCp.Status = 0; | ||
314 | bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim->fcs_itnim); | ||
315 | bfa_tskim_start(tskim, bfa_itnim, | ||
316 | bfad_int_to_lun(cmnd->device->lun), | ||
317 | FCP_TM_LUN_RESET, BFAD_LUN_RESET_TMO); | ||
318 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
319 | |||
320 | wait_event(wq, test_bit(IO_DONE_BIT, | ||
321 | (unsigned long *)&cmnd->SCp.Status)); | ||
322 | |||
323 | task_status = cmnd->SCp.Status >> 1; | ||
324 | if (task_status != BFI_TSKIM_STS_OK) { | ||
325 | BFA_DEV_PRINTF(bfad, BFA_ERR, "LUN reset failure, status: %d\n", | ||
326 | task_status); | ||
327 | rc = FAILED; | ||
328 | } | ||
329 | |||
330 | out: | ||
331 | return rc; | ||
332 | } | ||
333 | |||
334 | /** | ||
335 | * Scsi_Host template entry, resets the bus and abort all commands. | ||
336 | */ | ||
337 | static int | ||
338 | bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd) | ||
339 | { | ||
340 | struct Scsi_Host *shost = cmnd->device->host; | ||
341 | struct bfad_im_port_s *im_port = | ||
342 | (struct bfad_im_port_s *) shost->hostdata[0]; | ||
343 | struct bfad_s *bfad = im_port->bfad; | ||
344 | struct bfad_itnim_s *itnim; | ||
345 | unsigned long flags; | ||
346 | u32 i, rc, err_cnt = 0; | ||
347 | DECLARE_WAIT_QUEUE_HEAD(wq); | ||
348 | enum bfi_tskim_status task_status; | ||
349 | |||
350 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
351 | for (i = 0; i < MAX_FCP_TARGET; i++) { | ||
352 | itnim = bfad_os_get_itnim(im_port, i); | ||
353 | if (itnim) { | ||
354 | cmnd->SCp.ptr = (char *)&wq; | ||
355 | rc = bfad_im_target_reset_send(bfad, cmnd, itnim); | ||
356 | if (rc != BFA_STATUS_OK) { | ||
357 | err_cnt++; | ||
358 | continue; | ||
359 | } | ||
360 | |||
361 | /* wait target reset to complete */ | ||
362 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
363 | wait_event(wq, test_bit(IO_DONE_BIT, | ||
364 | (unsigned long *)&cmnd->SCp.Status)); | ||
365 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
366 | |||
367 | task_status = cmnd->SCp.Status >> 1; | ||
368 | if (task_status != BFI_TSKIM_STS_OK) { | ||
369 | BFA_DEV_PRINTF(bfad, BFA_ERR, | ||
370 | "target reset failure," | ||
371 | " status: %d\n", task_status); | ||
372 | err_cnt++; | ||
373 | } | ||
374 | } | ||
375 | } | ||
376 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
377 | |||
378 | if (err_cnt) | ||
379 | return FAILED; | ||
380 | |||
381 | return SUCCESS; | ||
382 | } | ||
383 | |||
384 | /** | ||
385 | * Scsi_Host template entry slave_destroy. | ||
386 | */ | ||
387 | static void | ||
388 | bfad_im_slave_destroy(struct scsi_device *sdev) | ||
389 | { | ||
390 | sdev->hostdata = NULL; | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * BFA FCS itnim callbacks | ||
396 | */ | ||
397 | |||
398 | /** | ||
399 | * BFA FCS itnim alloc callback, after successful PRLI | ||
400 | * Context: Interrupt | ||
401 | */ | ||
402 | void | ||
403 | bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim, | ||
404 | struct bfad_itnim_s **itnim_drv) | ||
405 | { | ||
406 | *itnim_drv = kzalloc(sizeof(struct bfad_itnim_s), GFP_ATOMIC); | ||
407 | if (*itnim_drv == NULL) | ||
408 | return; | ||
409 | |||
410 | (*itnim_drv)->im = bfad->im; | ||
411 | *itnim = &(*itnim_drv)->fcs_itnim; | ||
412 | (*itnim_drv)->state = ITNIM_STATE_NONE; | ||
413 | |||
414 | /* | ||
415 | * Initiaze the itnim_work | ||
416 | */ | ||
417 | INIT_WORK(&(*itnim_drv)->itnim_work, bfad_im_itnim_work_handler); | ||
418 | bfad->bfad_flags |= BFAD_RPORT_ONLINE; | ||
419 | } | ||
420 | |||
421 | /** | ||
422 | * BFA FCS itnim free callback. | ||
423 | * Context: Interrupt. bfad_lock is held | ||
424 | */ | ||
425 | void | ||
426 | bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv) | ||
427 | { | ||
428 | struct bfad_port_s *port; | ||
429 | wwn_t wwpn; | ||
430 | u32 fcid; | ||
431 | char wwpn_str[32], fcid_str[16]; | ||
432 | |||
433 | /* online to free state transtion should not happen */ | ||
434 | bfa_assert(itnim_drv->state != ITNIM_STATE_ONLINE); | ||
435 | |||
436 | itnim_drv->queue_work = 1; | ||
437 | /* offline request is not yet done, use the same request to free */ | ||
438 | if (itnim_drv->state == ITNIM_STATE_OFFLINE_PENDING) | ||
439 | itnim_drv->queue_work = 0; | ||
440 | |||
441 | itnim_drv->state = ITNIM_STATE_FREE; | ||
442 | port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim); | ||
443 | itnim_drv->im_port = port->im_port; | ||
444 | wwpn = bfa_fcs_itnim_get_pwwn(&itnim_drv->fcs_itnim); | ||
445 | fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim); | ||
446 | wwn2str(wwpn_str, wwpn); | ||
447 | fcid2str(fcid_str, fcid); | ||
448 | bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_FREE, | ||
449 | port->im_port->shost->host_no, | ||
450 | fcid_str, wwpn_str); | ||
451 | bfad_os_itnim_process(itnim_drv); | ||
452 | } | ||
453 | |||
454 | /** | ||
455 | * BFA FCS itnim online callback. | ||
456 | * Context: Interrupt. bfad_lock is held | ||
457 | */ | ||
458 | void | ||
459 | bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv) | ||
460 | { | ||
461 | struct bfad_port_s *port; | ||
462 | |||
463 | itnim_drv->bfa_itnim = bfa_fcs_itnim_get_halitn(&itnim_drv->fcs_itnim); | ||
464 | port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim); | ||
465 | itnim_drv->state = ITNIM_STATE_ONLINE; | ||
466 | itnim_drv->queue_work = 1; | ||
467 | itnim_drv->im_port = port->im_port; | ||
468 | bfad_os_itnim_process(itnim_drv); | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * BFA FCS itnim offline callback. | ||
473 | * Context: Interrupt. bfad_lock is held | ||
474 | */ | ||
475 | void | ||
476 | bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv) | ||
477 | { | ||
478 | struct bfad_port_s *port; | ||
479 | struct bfad_s *bfad; | ||
480 | |||
481 | port = bfa_fcs_itnim_get_drvport(&itnim_drv->fcs_itnim); | ||
482 | bfad = port->bfad; | ||
483 | if ((bfad->pport.flags & BFAD_PORT_DELETE) || | ||
484 | (port->flags & BFAD_PORT_DELETE)) { | ||
485 | itnim_drv->state = ITNIM_STATE_OFFLINE; | ||
486 | return; | ||
487 | } | ||
488 | itnim_drv->im_port = port->im_port; | ||
489 | itnim_drv->state = ITNIM_STATE_OFFLINE_PENDING; | ||
490 | itnim_drv->queue_work = 1; | ||
491 | bfad_os_itnim_process(itnim_drv); | ||
492 | } | ||
493 | |||
494 | /** | ||
495 | * BFA FCS itnim timeout callback. | ||
496 | * Context: Interrupt. bfad_lock is held | ||
497 | */ | ||
498 | void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim) | ||
499 | { | ||
500 | itnim->state = ITNIM_STATE_TIMEOUT; | ||
501 | } | ||
502 | |||
503 | /** | ||
504 | * Path TOV processing begin notification -- dummy for linux | ||
505 | */ | ||
506 | void | ||
507 | bfa_fcb_itnim_tov_begin(struct bfad_itnim_s *itnim) | ||
508 | { | ||
509 | } | ||
510 | |||
511 | |||
512 | |||
513 | /** | ||
514 | * Allocate a Scsi_Host for a port. | ||
515 | */ | ||
516 | int | ||
517 | bfad_im_scsi_host_alloc(struct bfad_s *bfad, struct bfad_im_port_s *im_port) | ||
518 | { | ||
519 | int error = 1; | ||
520 | |||
521 | if (!idr_pre_get(&bfad_im_port_index, GFP_KERNEL)) { | ||
522 | printk(KERN_WARNING "idr_pre_get failure\n"); | ||
523 | goto out; | ||
524 | } | ||
525 | |||
526 | error = idr_get_new(&bfad_im_port_index, im_port, | ||
527 | &im_port->idr_id); | ||
528 | if (error) { | ||
529 | printk(KERN_WARNING "idr_get_new failure\n"); | ||
530 | goto out; | ||
531 | } | ||
532 | |||
533 | im_port->shost = bfad_os_scsi_host_alloc(im_port, bfad); | ||
534 | if (!im_port->shost) { | ||
535 | error = 1; | ||
536 | goto out_free_idr; | ||
537 | } | ||
538 | |||
539 | im_port->shost->hostdata[0] = (unsigned long)im_port; | ||
540 | im_port->shost->unique_id = im_port->idr_id; | ||
541 | im_port->shost->this_id = -1; | ||
542 | im_port->shost->max_id = MAX_FCP_TARGET; | ||
543 | im_port->shost->max_lun = MAX_FCP_LUN; | ||
544 | im_port->shost->max_cmd_len = 16; | ||
545 | im_port->shost->can_queue = bfad->cfg_data.ioc_queue_depth; | ||
546 | im_port->shost->transportt = bfad_im_scsi_transport_template; | ||
547 | |||
548 | error = bfad_os_scsi_add_host(im_port->shost, im_port, bfad); | ||
549 | if (error) { | ||
550 | printk(KERN_WARNING "bfad_os_scsi_add_host failure %d\n", | ||
551 | error); | ||
552 | goto out_fc_rel; | ||
553 | } | ||
554 | |||
555 | /* setup host fixed attribute if the lk supports */ | ||
556 | bfad_os_fc_host_init(im_port); | ||
557 | |||
558 | return 0; | ||
559 | |||
560 | out_fc_rel: | ||
561 | scsi_host_put(im_port->shost); | ||
562 | out_free_idr: | ||
563 | idr_remove(&bfad_im_port_index, im_port->idr_id); | ||
564 | out: | ||
565 | return error; | ||
566 | } | ||
567 | |||
568 | void | ||
569 | bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) | ||
570 | { | ||
571 | unsigned long flags; | ||
572 | |||
573 | bfa_trc(bfad, bfad->inst_no); | ||
574 | bfa_log(bfad->logmod, BFA_LOG_LINUX_SCSI_HOST_FREE, | ||
575 | im_port->shost->host_no); | ||
576 | |||
577 | fc_remove_host(im_port->shost); | ||
578 | |||
579 | scsi_remove_host(im_port->shost); | ||
580 | scsi_host_put(im_port->shost); | ||
581 | |||
582 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
583 | idr_remove(&bfad_im_port_index, im_port->idr_id); | ||
584 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
585 | } | ||
586 | |||
587 | static void | ||
588 | bfad_im_port_delete_handler(struct work_struct *work) | ||
589 | { | ||
590 | struct bfad_im_port_s *im_port = | ||
591 | container_of(work, struct bfad_im_port_s, port_delete_work); | ||
592 | |||
593 | bfad_im_scsi_host_free(im_port->bfad, im_port); | ||
594 | bfad_im_port_clean(im_port); | ||
595 | kfree(im_port); | ||
596 | } | ||
597 | |||
598 | bfa_status_t | ||
599 | bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port) | ||
600 | { | ||
601 | int rc = BFA_STATUS_OK; | ||
602 | struct bfad_im_port_s *im_port; | ||
603 | |||
604 | im_port = kzalloc(sizeof(struct bfad_im_port_s), GFP_ATOMIC); | ||
605 | if (im_port == NULL) { | ||
606 | rc = BFA_STATUS_ENOMEM; | ||
607 | goto ext; | ||
608 | } | ||
609 | port->im_port = im_port; | ||
610 | im_port->port = port; | ||
611 | im_port->bfad = bfad; | ||
612 | |||
613 | INIT_WORK(&im_port->port_delete_work, bfad_im_port_delete_handler); | ||
614 | INIT_LIST_HEAD(&im_port->itnim_mapped_list); | ||
615 | INIT_LIST_HEAD(&im_port->binding_list); | ||
616 | |||
617 | ext: | ||
618 | return rc; | ||
619 | } | ||
620 | |||
621 | void | ||
622 | bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port) | ||
623 | { | ||
624 | struct bfad_im_port_s *im_port = port->im_port; | ||
625 | |||
626 | queue_work(bfad->im->drv_workq, | ||
627 | &im_port->port_delete_work); | ||
628 | } | ||
629 | |||
630 | void | ||
631 | bfad_im_port_clean(struct bfad_im_port_s *im_port) | ||
632 | { | ||
633 | struct bfad_fcp_binding *bp, *bp_new; | ||
634 | unsigned long flags; | ||
635 | struct bfad_s *bfad = im_port->bfad; | ||
636 | |||
637 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
638 | list_for_each_entry_safe(bp, bp_new, &im_port->binding_list, | ||
639 | list_entry) { | ||
640 | list_del(&bp->list_entry); | ||
641 | kfree(bp); | ||
642 | } | ||
643 | |||
644 | /* the itnim_mapped_list must be empty at this time */ | ||
645 | bfa_assert(list_empty(&im_port->itnim_mapped_list)); | ||
646 | |||
647 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
648 | } | ||
649 | |||
650 | void | ||
651 | bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port) | ||
652 | { | ||
653 | } | ||
654 | |||
655 | void | ||
656 | bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port) | ||
657 | { | ||
658 | } | ||
659 | |||
660 | bfa_status_t | ||
661 | bfad_im_probe(struct bfad_s *bfad) | ||
662 | { | ||
663 | struct bfad_im_s *im; | ||
664 | bfa_status_t rc = BFA_STATUS_OK; | ||
665 | |||
666 | im = kzalloc(sizeof(struct bfad_im_s), GFP_KERNEL); | ||
667 | if (im == NULL) { | ||
668 | rc = BFA_STATUS_ENOMEM; | ||
669 | goto ext; | ||
670 | } | ||
671 | |||
672 | bfad->im = im; | ||
673 | im->bfad = bfad; | ||
674 | |||
675 | if (bfad_os_thread_workq(bfad) != BFA_STATUS_OK) { | ||
676 | kfree(im); | ||
677 | rc = BFA_STATUS_FAILED; | ||
678 | } | ||
679 | |||
680 | ext: | ||
681 | return rc; | ||
682 | } | ||
683 | |||
684 | void | ||
685 | bfad_im_probe_undo(struct bfad_s *bfad) | ||
686 | { | ||
687 | if (bfad->im) { | ||
688 | bfad_os_destroy_workq(bfad->im); | ||
689 | kfree(bfad->im); | ||
690 | bfad->im = NULL; | ||
691 | } | ||
692 | } | ||
693 | |||
694 | |||
695 | |||
696 | |||
697 | int | ||
698 | bfad_os_scsi_add_host(struct Scsi_Host *shost, struct bfad_im_port_s *im_port, | ||
699 | struct bfad_s *bfad) | ||
700 | { | ||
701 | struct device *dev; | ||
702 | |||
703 | if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE) | ||
704 | dev = &bfad->pcidev->dev; | ||
705 | else | ||
706 | dev = &bfad->pport.im_port->shost->shost_gendev; | ||
707 | |||
708 | return scsi_add_host(shost, dev); | ||
709 | } | ||
710 | |||
711 | struct Scsi_Host * | ||
712 | bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, struct bfad_s *bfad) | ||
713 | { | ||
714 | struct scsi_host_template *sht; | ||
715 | |||
716 | if (im_port->port->pvb_type == BFAD_PORT_PHYS_BASE) | ||
717 | sht = &bfad_im_scsi_host_template; | ||
718 | else | ||
719 | sht = &bfad_im_vport_template; | ||
720 | |||
721 | sht->sg_tablesize = bfad->cfg_data.io_max_sge; | ||
722 | |||
723 | return scsi_host_alloc(sht, sizeof(unsigned long)); | ||
724 | } | ||
725 | |||
726 | void | ||
727 | bfad_os_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port) | ||
728 | { | ||
729 | flush_workqueue(bfad->im->drv_workq); | ||
730 | bfad_im_scsi_host_free(im_port->bfad, im_port); | ||
731 | bfad_im_port_clean(im_port); | ||
732 | kfree(im_port); | ||
733 | } | ||
734 | |||
735 | void | ||
736 | bfad_os_destroy_workq(struct bfad_im_s *im) | ||
737 | { | ||
738 | if (im && im->drv_workq) { | ||
739 | destroy_workqueue(im->drv_workq); | ||
740 | im->drv_workq = NULL; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | bfa_status_t | ||
745 | bfad_os_thread_workq(struct bfad_s *bfad) | ||
746 | { | ||
747 | struct bfad_im_s *im = bfad->im; | ||
748 | |||
749 | bfa_trc(bfad, 0); | ||
750 | snprintf(im->drv_workq_name, BFAD_KOBJ_NAME_LEN, "bfad_wq_%d", | ||
751 | bfad->inst_no); | ||
752 | im->drv_workq = create_singlethread_workqueue(im->drv_workq_name); | ||
753 | if (!im->drv_workq) | ||
754 | return BFA_STATUS_FAILED; | ||
755 | |||
756 | return BFA_STATUS_OK; | ||
757 | } | ||
758 | |||
759 | /** | ||
760 | * Scsi_Host template entry. | ||
761 | * | ||
762 | * Description: | ||
763 | * OS entry point to adjust the queue_depths on a per-device basis. | ||
764 | * Called once per device during the bus scan. | ||
765 | * Return non-zero if fails. | ||
766 | */ | ||
767 | static int | ||
768 | bfad_im_slave_configure(struct scsi_device *sdev) | ||
769 | { | ||
770 | if (sdev->tagged_supported) | ||
771 | scsi_activate_tcq(sdev, bfa_lun_queue_depth); | ||
772 | else | ||
773 | scsi_deactivate_tcq(sdev, bfa_lun_queue_depth); | ||
774 | |||
775 | return 0; | ||
776 | } | ||
777 | |||
778 | struct scsi_host_template bfad_im_scsi_host_template = { | ||
779 | .module = THIS_MODULE, | ||
780 | .name = BFAD_DRIVER_NAME, | ||
781 | .info = bfad_im_info, | ||
782 | .queuecommand = bfad_im_queuecommand, | ||
783 | .eh_abort_handler = bfad_im_abort_handler, | ||
784 | .eh_device_reset_handler = bfad_im_reset_lun_handler, | ||
785 | .eh_bus_reset_handler = bfad_im_reset_bus_handler, | ||
786 | |||
787 | .slave_alloc = bfad_im_slave_alloc, | ||
788 | .slave_configure = bfad_im_slave_configure, | ||
789 | .slave_destroy = bfad_im_slave_destroy, | ||
790 | |||
791 | .this_id = -1, | ||
792 | .sg_tablesize = BFAD_IO_MAX_SGE, | ||
793 | .cmd_per_lun = 3, | ||
794 | .use_clustering = ENABLE_CLUSTERING, | ||
795 | .shost_attrs = bfad_im_host_attrs, | ||
796 | .max_sectors = 0xFFFF, | ||
797 | }; | ||
798 | |||
799 | struct scsi_host_template bfad_im_vport_template = { | ||
800 | .module = THIS_MODULE, | ||
801 | .name = BFAD_DRIVER_NAME, | ||
802 | .info = bfad_im_info, | ||
803 | .queuecommand = bfad_im_queuecommand, | ||
804 | .eh_abort_handler = bfad_im_abort_handler, | ||
805 | .eh_device_reset_handler = bfad_im_reset_lun_handler, | ||
806 | .eh_bus_reset_handler = bfad_im_reset_bus_handler, | ||
807 | |||
808 | .slave_alloc = bfad_im_slave_alloc, | ||
809 | .slave_configure = bfad_im_slave_configure, | ||
810 | .slave_destroy = bfad_im_slave_destroy, | ||
811 | |||
812 | .this_id = -1, | ||
813 | .sg_tablesize = BFAD_IO_MAX_SGE, | ||
814 | .cmd_per_lun = 3, | ||
815 | .use_clustering = ENABLE_CLUSTERING, | ||
816 | .shost_attrs = bfad_im_vport_attrs, | ||
817 | .max_sectors = 0xFFFF, | ||
818 | }; | ||
819 | |||
820 | void | ||
821 | bfad_im_probe_post(struct bfad_im_s *im) | ||
822 | { | ||
823 | flush_workqueue(im->drv_workq); | ||
824 | } | ||
825 | |||
826 | bfa_status_t | ||
827 | bfad_im_module_init(void) | ||
828 | { | ||
829 | bfad_im_scsi_transport_template = | ||
830 | fc_attach_transport(&bfad_im_fc_function_template); | ||
831 | if (!bfad_im_scsi_transport_template) | ||
832 | return BFA_STATUS_ENOMEM; | ||
833 | |||
834 | return BFA_STATUS_OK; | ||
835 | } | ||
836 | |||
837 | void | ||
838 | bfad_im_module_exit(void) | ||
839 | { | ||
840 | if (bfad_im_scsi_transport_template) | ||
841 | fc_release_transport(bfad_im_scsi_transport_template); | ||
842 | } | ||
843 | |||
844 | void | ||
845 | bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv) | ||
846 | { | ||
847 | struct bfad_im_s *im = itnim_drv->im; | ||
848 | |||
849 | if (itnim_drv->queue_work) | ||
850 | queue_work(im->drv_workq, &itnim_drv->itnim_work); | ||
851 | } | ||
852 | |||
853 | void | ||
854 | bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, struct scsi_device *sdev) | ||
855 | { | ||
856 | struct scsi_device *tmp_sdev; | ||
857 | |||
858 | if (((jiffies - itnim->last_ramp_up_time) > | ||
859 | BFA_QUEUE_FULL_RAMP_UP_TIME * HZ) && | ||
860 | ((jiffies - itnim->last_queue_full_time) > | ||
861 | BFA_QUEUE_FULL_RAMP_UP_TIME * HZ)) { | ||
862 | shost_for_each_device(tmp_sdev, sdev->host) { | ||
863 | if (bfa_lun_queue_depth > tmp_sdev->queue_depth) { | ||
864 | if (tmp_sdev->id != sdev->id) | ||
865 | continue; | ||
866 | if (tmp_sdev->ordered_tags) | ||
867 | scsi_adjust_queue_depth(tmp_sdev, | ||
868 | MSG_ORDERED_TAG, | ||
869 | tmp_sdev->queue_depth + 1); | ||
870 | else | ||
871 | scsi_adjust_queue_depth(tmp_sdev, | ||
872 | MSG_SIMPLE_TAG, | ||
873 | tmp_sdev->queue_depth + 1); | ||
874 | |||
875 | itnim->last_ramp_up_time = jiffies; | ||
876 | } | ||
877 | } | ||
878 | } | ||
879 | } | ||
880 | |||
881 | void | ||
882 | bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev) | ||
883 | { | ||
884 | struct scsi_device *tmp_sdev; | ||
885 | |||
886 | itnim->last_queue_full_time = jiffies; | ||
887 | |||
888 | shost_for_each_device(tmp_sdev, sdev->host) { | ||
889 | if (tmp_sdev->id != sdev->id) | ||
890 | continue; | ||
891 | scsi_track_queue_full(tmp_sdev, tmp_sdev->queue_depth - 1); | ||
892 | } | ||
893 | } | ||
894 | |||
895 | |||
896 | |||
897 | |||
898 | struct bfad_itnim_s * | ||
899 | bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id) | ||
900 | { | ||
901 | struct bfad_itnim_s *itnim = NULL; | ||
902 | |||
903 | /* Search the mapped list for this target ID */ | ||
904 | list_for_each_entry(itnim, &im_port->itnim_mapped_list, list_entry) { | ||
905 | if (id == itnim->scsi_tgt_id) | ||
906 | return itnim; | ||
907 | } | ||
908 | |||
909 | return NULL; | ||
910 | } | ||
911 | |||
912 | /** | ||
913 | * Scsi_Host template entry slave_alloc | ||
914 | */ | ||
915 | static int | ||
916 | bfad_im_slave_alloc(struct scsi_device *sdev) | ||
917 | { | ||
918 | struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); | ||
919 | |||
920 | if (!rport || fc_remote_port_chkready(rport)) | ||
921 | return -ENXIO; | ||
922 | |||
923 | sdev->hostdata = rport->dd_data; | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | void | ||
929 | bfad_os_fc_host_init(struct bfad_im_port_s *im_port) | ||
930 | { | ||
931 | struct Scsi_Host *host = im_port->shost; | ||
932 | struct bfad_s *bfad = im_port->bfad; | ||
933 | struct bfad_port_s *port = im_port->port; | ||
934 | union attr { | ||
935 | struct bfa_pport_attr_s pattr; | ||
936 | struct bfa_ioc_attr_s ioc_attr; | ||
937 | } attr; | ||
938 | |||
939 | fc_host_node_name(host) = | ||
940 | bfa_os_htonll((bfa_fcs_port_get_nwwn(port->fcs_port))); | ||
941 | fc_host_port_name(host) = | ||
942 | bfa_os_htonll((bfa_fcs_port_get_pwwn(port->fcs_port))); | ||
943 | |||
944 | fc_host_supported_classes(host) = FC_COS_CLASS3; | ||
945 | |||
946 | memset(fc_host_supported_fc4s(host), 0, | ||
947 | sizeof(fc_host_supported_fc4s(host))); | ||
948 | if (bfad_supported_fc4s & (BFA_PORT_ROLE_FCP_IM | BFA_PORT_ROLE_FCP_TM)) | ||
949 | /* For FCP type 0x08 */ | ||
950 | fc_host_supported_fc4s(host)[2] = 1; | ||
951 | if (bfad_supported_fc4s | BFA_PORT_ROLE_FCP_IPFC) | ||
952 | /* For LLC/SNAP type 0x05 */ | ||
953 | fc_host_supported_fc4s(host)[3] = 0x20; | ||
954 | /* For fibre channel services type 0x20 */ | ||
955 | fc_host_supported_fc4s(host)[7] = 1; | ||
956 | |||
957 | memset(&attr.ioc_attr, 0, sizeof(attr.ioc_attr)); | ||
958 | bfa_get_attr(&bfad->bfa, &attr.ioc_attr); | ||
959 | sprintf(fc_host_symbolic_name(host), "Brocade %s FV%s DV%s", | ||
960 | attr.ioc_attr.adapter_attr.model, | ||
961 | attr.ioc_attr.adapter_attr.fw_ver, BFAD_DRIVER_VERSION); | ||
962 | |||
963 | fc_host_supported_speeds(host) = 0; | ||
964 | fc_host_supported_speeds(host) |= | ||
965 | FC_PORTSPEED_8GBIT | FC_PORTSPEED_4GBIT | FC_PORTSPEED_2GBIT | | ||
966 | FC_PORTSPEED_1GBIT; | ||
967 | |||
968 | memset(&attr.pattr, 0, sizeof(attr.pattr)); | ||
969 | bfa_pport_get_attr(&bfad->bfa, &attr.pattr); | ||
970 | fc_host_maxframe_size(host) = attr.pattr.pport_cfg.maxfrsize; | ||
971 | } | ||
972 | |||
973 | static void | ||
974 | bfad_im_fc_rport_add(struct bfad_im_port_s *im_port, struct bfad_itnim_s *itnim) | ||
975 | { | ||
976 | struct fc_rport_identifiers rport_ids; | ||
977 | struct fc_rport *fc_rport; | ||
978 | struct bfad_itnim_data_s *itnim_data; | ||
979 | |||
980 | rport_ids.node_name = | ||
981 | bfa_os_htonll(bfa_fcs_itnim_get_nwwn(&itnim->fcs_itnim)); | ||
982 | rport_ids.port_name = | ||
983 | bfa_os_htonll(bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim)); | ||
984 | rport_ids.port_id = | ||
985 | bfa_os_hton3b(bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim)); | ||
986 | rport_ids.roles = FC_RPORT_ROLE_UNKNOWN; | ||
987 | |||
988 | itnim->fc_rport = fc_rport = | ||
989 | fc_remote_port_add(im_port->shost, 0, &rport_ids); | ||
990 | |||
991 | if (!fc_rport) | ||
992 | return; | ||
993 | |||
994 | fc_rport->maxframe_size = | ||
995 | bfa_fcs_itnim_get_maxfrsize(&itnim->fcs_itnim); | ||
996 | fc_rport->supported_classes = bfa_fcs_itnim_get_cos(&itnim->fcs_itnim); | ||
997 | |||
998 | itnim_data = fc_rport->dd_data; | ||
999 | itnim_data->itnim = itnim; | ||
1000 | |||
1001 | rport_ids.roles |= FC_RPORT_ROLE_FCP_TARGET; | ||
1002 | |||
1003 | if (rport_ids.roles != FC_RPORT_ROLE_UNKNOWN) | ||
1004 | fc_remote_port_rolechg(fc_rport, rport_ids.roles); | ||
1005 | |||
1006 | if ((fc_rport->scsi_target_id != -1) | ||
1007 | && (fc_rport->scsi_target_id < MAX_FCP_TARGET)) | ||
1008 | itnim->scsi_tgt_id = fc_rport->scsi_target_id; | ||
1009 | |||
1010 | return; | ||
1011 | } | ||
1012 | |||
1013 | /** | ||
1014 | * Work queue handler using FC transport service | ||
1015 | * Context: kernel | ||
1016 | */ | ||
1017 | static void | ||
1018 | bfad_im_itnim_work_handler(struct work_struct *work) | ||
1019 | { | ||
1020 | struct bfad_itnim_s *itnim = container_of(work, struct bfad_itnim_s, | ||
1021 | itnim_work); | ||
1022 | struct bfad_im_s *im = itnim->im; | ||
1023 | struct bfad_s *bfad = im->bfad; | ||
1024 | struct bfad_im_port_s *im_port; | ||
1025 | unsigned long flags; | ||
1026 | struct fc_rport *fc_rport; | ||
1027 | wwn_t wwpn; | ||
1028 | u32 fcid; | ||
1029 | char wwpn_str[32], fcid_str[16]; | ||
1030 | |||
1031 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1032 | im_port = itnim->im_port; | ||
1033 | bfa_trc(bfad, itnim->state); | ||
1034 | switch (itnim->state) { | ||
1035 | case ITNIM_STATE_ONLINE: | ||
1036 | if (!itnim->fc_rport) { | ||
1037 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1038 | bfad_im_fc_rport_add(im_port, itnim); | ||
1039 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1040 | wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); | ||
1041 | fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); | ||
1042 | wwn2str(wwpn_str, wwpn); | ||
1043 | fcid2str(fcid_str, fcid); | ||
1044 | list_add_tail(&itnim->list_entry, | ||
1045 | &im_port->itnim_mapped_list); | ||
1046 | bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_ONLINE, | ||
1047 | im_port->shost->host_no, | ||
1048 | itnim->scsi_tgt_id, | ||
1049 | fcid_str, wwpn_str); | ||
1050 | } else { | ||
1051 | printk(KERN_WARNING | ||
1052 | "%s: itnim %llx is already in online state\n", | ||
1053 | __FUNCTION__, | ||
1054 | bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim)); | ||
1055 | } | ||
1056 | |||
1057 | break; | ||
1058 | case ITNIM_STATE_OFFLINE_PENDING: | ||
1059 | itnim->state = ITNIM_STATE_OFFLINE; | ||
1060 | if (itnim->fc_rport) { | ||
1061 | fc_rport = itnim->fc_rport; | ||
1062 | ((struct bfad_itnim_data_s *) | ||
1063 | fc_rport->dd_data)->itnim = NULL; | ||
1064 | itnim->fc_rport = NULL; | ||
1065 | if (!(im_port->port->flags & BFAD_PORT_DELETE)) { | ||
1066 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1067 | fc_rport->dev_loss_tmo = | ||
1068 | bfa_fcpim_path_tov_get(&bfad->bfa) + 1; | ||
1069 | fc_remote_port_delete(fc_rport); | ||
1070 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1071 | } | ||
1072 | wwpn = bfa_fcs_itnim_get_pwwn(&itnim->fcs_itnim); | ||
1073 | fcid = bfa_fcs_itnim_get_fcid(&itnim->fcs_itnim); | ||
1074 | wwn2str(wwpn_str, wwpn); | ||
1075 | fcid2str(fcid_str, fcid); | ||
1076 | list_del(&itnim->list_entry); | ||
1077 | bfa_log(bfad->logmod, BFA_LOG_LINUX_ITNIM_OFFLINE, | ||
1078 | im_port->shost->host_no, | ||
1079 | itnim->scsi_tgt_id, | ||
1080 | fcid_str, wwpn_str); | ||
1081 | } | ||
1082 | break; | ||
1083 | case ITNIM_STATE_FREE: | ||
1084 | if (itnim->fc_rport) { | ||
1085 | fc_rport = itnim->fc_rport; | ||
1086 | ((struct bfad_itnim_data_s *) | ||
1087 | fc_rport->dd_data)->itnim = NULL; | ||
1088 | itnim->fc_rport = NULL; | ||
1089 | if (!(im_port->port->flags & BFAD_PORT_DELETE)) { | ||
1090 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1091 | fc_rport->dev_loss_tmo = | ||
1092 | bfa_fcpim_path_tov_get(&bfad->bfa) + 1; | ||
1093 | fc_remote_port_delete(fc_rport); | ||
1094 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1095 | } | ||
1096 | list_del(&itnim->list_entry); | ||
1097 | } | ||
1098 | |||
1099 | kfree(itnim); | ||
1100 | break; | ||
1101 | default: | ||
1102 | bfa_assert(0); | ||
1103 | break; | ||
1104 | } | ||
1105 | |||
1106 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1107 | } | ||
1108 | |||
1109 | /** | ||
1110 | * Scsi_Host template entry, queue a SCSI command to the BFAD. | ||
1111 | */ | ||
1112 | static int | ||
1113 | bfad_im_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | ||
1114 | { | ||
1115 | struct bfad_im_port_s *im_port = | ||
1116 | (struct bfad_im_port_s *) cmnd->device->host->hostdata[0]; | ||
1117 | struct bfad_s *bfad = im_port->bfad; | ||
1118 | struct bfad_itnim_data_s *itnim_data = cmnd->device->hostdata; | ||
1119 | struct bfad_itnim_s *itnim; | ||
1120 | struct bfa_ioim_s *hal_io; | ||
1121 | unsigned long flags; | ||
1122 | int rc; | ||
1123 | s16 sg_cnt = 0; | ||
1124 | struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); | ||
1125 | |||
1126 | rc = fc_remote_port_chkready(rport); | ||
1127 | if (rc) { | ||
1128 | cmnd->result = rc; | ||
1129 | done(cmnd); | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | sg_cnt = scsi_dma_map(cmnd); | ||
1134 | |||
1135 | if (sg_cnt < 0) | ||
1136 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1137 | |||
1138 | cmnd->scsi_done = done; | ||
1139 | |||
1140 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
1141 | if (!(bfad->bfad_flags & BFAD_HAL_START_DONE)) { | ||
1142 | printk(KERN_WARNING | ||
1143 | "bfad%d, queuecommand %p %x failed, BFA stopped\n", | ||
1144 | bfad->inst_no, cmnd, cmnd->cmnd[0]); | ||
1145 | cmnd->result = ScsiResult(DID_NO_CONNECT, 0); | ||
1146 | goto out_fail_cmd; | ||
1147 | } | ||
1148 | |||
1149 | itnim = itnim_data->itnim; | ||
1150 | if (!itnim) { | ||
1151 | cmnd->result = ScsiResult(DID_IMM_RETRY, 0); | ||
1152 | goto out_fail_cmd; | ||
1153 | } | ||
1154 | |||
1155 | hal_io = bfa_ioim_alloc(&bfad->bfa, (struct bfad_ioim_s *) cmnd, | ||
1156 | itnim->bfa_itnim, sg_cnt); | ||
1157 | if (!hal_io) { | ||
1158 | printk(KERN_WARNING "hal_io failure\n"); | ||
1159 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1160 | scsi_dma_unmap(cmnd); | ||
1161 | return SCSI_MLQUEUE_HOST_BUSY; | ||
1162 | } | ||
1163 | |||
1164 | cmnd->host_scribble = (char *)hal_io; | ||
1165 | bfa_trc_fp(bfad, hal_io->iotag); | ||
1166 | bfa_ioim_start(hal_io); | ||
1167 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1168 | |||
1169 | return 0; | ||
1170 | |||
1171 | out_fail_cmd: | ||
1172 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
1173 | scsi_dma_unmap(cmnd); | ||
1174 | if (done) | ||
1175 | done(cmnd); | ||
1176 | |||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | void | ||
1181 | bfad_os_rport_online_wait(struct bfad_s *bfad) | ||
1182 | { | ||
1183 | int i; | ||
1184 | int rport_delay = 10; | ||
1185 | |||
1186 | for (i = 0; !(bfad->bfad_flags & BFAD_PORT_ONLINE) | ||
1187 | && i < bfa_linkup_delay; i++) | ||
1188 | schedule_timeout_uninterruptible(HZ); | ||
1189 | |||
1190 | if (bfad->bfad_flags & BFAD_PORT_ONLINE) { | ||
1191 | rport_delay = rport_delay < bfa_linkup_delay ? | ||
1192 | rport_delay : bfa_linkup_delay; | ||
1193 | for (i = 0; !(bfad->bfad_flags & BFAD_RPORT_ONLINE) | ||
1194 | && i < rport_delay; i++) | ||
1195 | schedule_timeout_uninterruptible(HZ); | ||
1196 | |||
1197 | if (rport_delay > 0 && (bfad->bfad_flags & BFAD_RPORT_ONLINE)) | ||
1198 | schedule_timeout_uninterruptible(rport_delay * HZ); | ||
1199 | } | ||
1200 | } | ||
1201 | |||
1202 | int | ||
1203 | bfad_os_get_linkup_delay(struct bfad_s *bfad) | ||
1204 | { | ||
1205 | |||
1206 | u8 nwwns = 0; | ||
1207 | wwn_t *wwns; | ||
1208 | int ldelay; | ||
1209 | |||
1210 | /* | ||
1211 | * Querying for the boot target port wwns | ||
1212 | * -- read from boot information in flash. | ||
1213 | * If nwwns > 0 => boot over SAN and set bfa_linkup_delay = 30 | ||
1214 | * else => local boot machine set bfa_linkup_delay = 10 | ||
1215 | */ | ||
1216 | |||
1217 | bfa_iocfc_get_bootwwns(&bfad->bfa, &nwwns, &wwns); | ||
1218 | |||
1219 | if (nwwns > 0) { | ||
1220 | /* If boot over SAN; linkup_delay = 30sec */ | ||
1221 | ldelay = 30; | ||
1222 | } else { | ||
1223 | /* If local boot; linkup_delay = 10sec */ | ||
1224 | ldelay = 0; | ||
1225 | } | ||
1226 | |||
1227 | return ldelay; | ||
1228 | } | ||
1229 | |||
1230 | |||
diff --git a/drivers/scsi/bfa/bfad_im.h b/drivers/scsi/bfa/bfad_im.h new file mode 100644 index 000000000000..189a5b29e21a --- /dev/null +++ b/drivers/scsi/bfa/bfad_im.h | |||
@@ -0,0 +1,150 @@ | |||
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 | #ifndef __BFAD_IM_H__ | ||
19 | #define __BFAD_IM_H__ | ||
20 | |||
21 | #include "fcs/bfa_fcs_fcpim.h" | ||
22 | #include "bfad_im_compat.h" | ||
23 | |||
24 | #define FCPI_NAME " fcpim" | ||
25 | |||
26 | void bfad_flags_set(struct bfad_s *bfad, u32 flags); | ||
27 | bfa_status_t bfad_im_module_init(void); | ||
28 | void bfad_im_module_exit(void); | ||
29 | bfa_status_t bfad_im_probe(struct bfad_s *bfad); | ||
30 | void bfad_im_probe_undo(struct bfad_s *bfad); | ||
31 | void bfad_im_probe_post(struct bfad_im_s *im); | ||
32 | bfa_status_t bfad_im_port_new(struct bfad_s *bfad, struct bfad_port_s *port); | ||
33 | void bfad_im_port_delete(struct bfad_s *bfad, struct bfad_port_s *port); | ||
34 | void bfad_im_port_online(struct bfad_s *bfad, struct bfad_port_s *port); | ||
35 | void bfad_im_port_offline(struct bfad_s *bfad, struct bfad_port_s *port); | ||
36 | void bfad_im_port_clean(struct bfad_im_port_s *im_port); | ||
37 | int bfad_im_scsi_host_alloc(struct bfad_s *bfad, | ||
38 | struct bfad_im_port_s *im_port); | ||
39 | void bfad_im_scsi_host_free(struct bfad_s *bfad, | ||
40 | struct bfad_im_port_s *im_port); | ||
41 | |||
42 | #define MAX_FCP_TARGET 1024 | ||
43 | #define MAX_FCP_LUN 16384 | ||
44 | #define BFAD_TARGET_RESET_TMO 60 | ||
45 | #define BFAD_LUN_RESET_TMO 60 | ||
46 | #define ScsiResult(host_code, scsi_code) (((host_code) << 16) | scsi_code) | ||
47 | #define BFA_QUEUE_FULL_RAMP_UP_TIME 120 | ||
48 | #define BFAD_KOBJ_NAME_LEN 20 | ||
49 | |||
50 | /* | ||
51 | * itnim flags | ||
52 | */ | ||
53 | #define ITNIM_MAPPED 0x00000001 | ||
54 | |||
55 | #define SCSI_TASK_MGMT 0x00000001 | ||
56 | #define IO_DONE_BIT 0 | ||
57 | |||
58 | struct bfad_itnim_data_s { | ||
59 | struct bfad_itnim_s *itnim; | ||
60 | }; | ||
61 | |||
62 | struct bfad_im_port_s { | ||
63 | struct bfad_s *bfad; | ||
64 | struct bfad_port_s *port; | ||
65 | struct work_struct port_delete_work; | ||
66 | int idr_id; | ||
67 | u16 cur_scsi_id; | ||
68 | struct list_head binding_list; | ||
69 | struct Scsi_Host *shost; | ||
70 | struct list_head itnim_mapped_list; | ||
71 | }; | ||
72 | |||
73 | enum bfad_itnim_state { | ||
74 | ITNIM_STATE_NONE, | ||
75 | ITNIM_STATE_ONLINE, | ||
76 | ITNIM_STATE_OFFLINE_PENDING, | ||
77 | ITNIM_STATE_OFFLINE, | ||
78 | ITNIM_STATE_TIMEOUT, | ||
79 | ITNIM_STATE_FREE, | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * Per itnim data structure | ||
84 | */ | ||
85 | struct bfad_itnim_s { | ||
86 | struct list_head list_entry; | ||
87 | struct bfa_fcs_itnim_s fcs_itnim; | ||
88 | struct work_struct itnim_work; | ||
89 | u32 flags; | ||
90 | enum bfad_itnim_state state; | ||
91 | struct bfad_im_s *im; | ||
92 | struct bfad_im_port_s *im_port; | ||
93 | struct bfad_rport_s *drv_rport; | ||
94 | struct fc_rport *fc_rport; | ||
95 | struct bfa_itnim_s *bfa_itnim; | ||
96 | u16 scsi_tgt_id; | ||
97 | u16 queue_work; | ||
98 | unsigned long last_ramp_up_time; | ||
99 | unsigned long last_queue_full_time; | ||
100 | }; | ||
101 | |||
102 | enum bfad_binding_type { | ||
103 | FCP_PWWN_BINDING = 0x1, | ||
104 | FCP_NWWN_BINDING = 0x2, | ||
105 | FCP_FCID_BINDING = 0x3, | ||
106 | }; | ||
107 | |||
108 | struct bfad_fcp_binding { | ||
109 | struct list_head list_entry; | ||
110 | enum bfad_binding_type binding_type; | ||
111 | u16 scsi_target_id; | ||
112 | u32 fc_id; | ||
113 | wwn_t nwwn; | ||
114 | wwn_t pwwn; | ||
115 | }; | ||
116 | |||
117 | struct bfad_im_s { | ||
118 | struct bfad_s *bfad; | ||
119 | struct workqueue_struct *drv_workq; | ||
120 | char drv_workq_name[BFAD_KOBJ_NAME_LEN]; | ||
121 | }; | ||
122 | |||
123 | struct Scsi_Host *bfad_os_scsi_host_alloc(struct bfad_im_port_s *im_port, | ||
124 | struct bfad_s *); | ||
125 | bfa_status_t bfad_os_thread_workq(struct bfad_s *bfad); | ||
126 | void bfad_os_destroy_workq(struct bfad_im_s *im); | ||
127 | void bfad_os_itnim_process(struct bfad_itnim_s *itnim_drv); | ||
128 | void bfad_os_fc_host_init(struct bfad_im_port_s *im_port); | ||
129 | void bfad_os_init_work(struct bfad_im_port_s *im_port); | ||
130 | void bfad_os_scsi_host_free(struct bfad_s *bfad, | ||
131 | struct bfad_im_port_s *im_port); | ||
132 | void bfad_os_ramp_up_qdepth(struct bfad_itnim_s *itnim, | ||
133 | struct scsi_device *sdev); | ||
134 | void bfad_os_handle_qfull(struct bfad_itnim_s *itnim, struct scsi_device *sdev); | ||
135 | struct bfad_itnim_s *bfad_os_get_itnim(struct bfad_im_port_s *im_port, int id); | ||
136 | int bfad_os_scsi_add_host(struct Scsi_Host *shost, | ||
137 | struct bfad_im_port_s *im_port, struct bfad_s *bfad); | ||
138 | |||
139 | /* | ||
140 | * scsi_host_template entries | ||
141 | */ | ||
142 | void bfad_im_itnim_unmap(struct bfad_im_port_s *im_port, | ||
143 | struct bfad_itnim_s *itnim); | ||
144 | |||
145 | extern struct scsi_host_template bfad_im_scsi_host_template; | ||
146 | extern struct scsi_host_template bfad_im_vport_template; | ||
147 | extern struct fc_function_template bfad_im_fc_function_template; | ||
148 | extern struct scsi_transport_template *bfad_im_scsi_transport_template; | ||
149 | |||
150 | #endif | ||
diff --git a/drivers/scsi/bfa/bfad_im_compat.h b/drivers/scsi/bfa/bfad_im_compat.h new file mode 100644 index 000000000000..1d3e74ec338c --- /dev/null +++ b/drivers/scsi/bfa/bfad_im_compat.h | |||
@@ -0,0 +1,46 @@ | |||
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 | #ifndef __BFAD_IM_COMPAT_H__ | ||
19 | #define __BFAD_IM_COMPAT_H__ | ||
20 | |||
21 | extern u32 *bfi_image_buf; | ||
22 | extern u32 bfi_image_size; | ||
23 | |||
24 | extern struct device_attribute *bfad_im_host_attrs[]; | ||
25 | extern struct device_attribute *bfad_im_vport_attrs[]; | ||
26 | |||
27 | u32 *bfad_get_firmware_buf(struct pci_dev *pdev); | ||
28 | u32 *bfad_read_firmware(struct pci_dev *pdev, u32 **bfi_image, | ||
29 | u32 *bfi_image_size, char *fw_name); | ||
30 | |||
31 | static inline u32 * | ||
32 | bfad_load_fwimg(struct pci_dev *pdev) | ||
33 | { | ||
34 | return(bfad_get_firmware_buf(pdev)); | ||
35 | } | ||
36 | |||
37 | static inline void | ||
38 | bfad_free_fwimg(void) | ||
39 | { | ||
40 | if (bfi_image_ct_size && bfi_image_ct) | ||
41 | vfree(bfi_image_ct); | ||
42 | if (bfi_image_cb_size && bfi_image_cb) | ||
43 | vfree(bfi_image_cb); | ||
44 | } | ||
45 | |||
46 | #endif | ||
diff --git a/drivers/scsi/bfa/bfad_intr.c b/drivers/scsi/bfa/bfad_intr.c new file mode 100644 index 000000000000..f104e029cac9 --- /dev/null +++ b/drivers/scsi/bfa/bfad_intr.c | |||
@@ -0,0 +1,214 @@ | |||
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 | #include "bfad_drv.h" | ||
19 | #include "bfad_trcmod.h" | ||
20 | |||
21 | BFA_TRC_FILE(LDRV, INTR); | ||
22 | |||
23 | /** | ||
24 | * bfa_isr BFA driver interrupt functions | ||
25 | */ | ||
26 | irqreturn_t bfad_intx(int irq, void *dev_id); | ||
27 | static int msix_disable; | ||
28 | module_param(msix_disable, int, S_IRUGO | S_IWUSR); | ||
29 | /** | ||
30 | * Line based interrupt handler. | ||
31 | */ | ||
32 | irqreturn_t | ||
33 | bfad_intx(int irq, void *dev_id) | ||
34 | { | ||
35 | struct bfad_s *bfad = dev_id; | ||
36 | struct list_head doneq; | ||
37 | unsigned long flags; | ||
38 | bfa_boolean_t rc; | ||
39 | |||
40 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
41 | rc = bfa_intx(&bfad->bfa); | ||
42 | if (!rc) { | ||
43 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
44 | return IRQ_NONE; | ||
45 | } | ||
46 | |||
47 | bfa_comp_deq(&bfad->bfa, &doneq); | ||
48 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
49 | |||
50 | if (!list_empty(&doneq)) { | ||
51 | bfa_comp_process(&bfad->bfa, &doneq); | ||
52 | |||
53 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
54 | bfa_comp_free(&bfad->bfa, &doneq); | ||
55 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
56 | bfa_trc_fp(bfad, irq); | ||
57 | } | ||
58 | |||
59 | return IRQ_HANDLED; | ||
60 | |||
61 | } | ||
62 | |||
63 | static irqreturn_t | ||
64 | bfad_msix(int irq, void *dev_id) | ||
65 | { | ||
66 | struct bfad_msix_s *vec = dev_id; | ||
67 | struct bfad_s *bfad = vec->bfad; | ||
68 | struct list_head doneq; | ||
69 | unsigned long flags; | ||
70 | |||
71 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
72 | |||
73 | bfa_msix(&bfad->bfa, vec->msix.entry); | ||
74 | bfa_comp_deq(&bfad->bfa, &doneq); | ||
75 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
76 | |||
77 | if (!list_empty(&doneq)) { | ||
78 | bfa_comp_process(&bfad->bfa, &doneq); | ||
79 | |||
80 | spin_lock_irqsave(&bfad->bfad_lock, flags); | ||
81 | bfa_comp_free(&bfad->bfa, &doneq); | ||
82 | spin_unlock_irqrestore(&bfad->bfad_lock, flags); | ||
83 | } | ||
84 | |||
85 | return IRQ_HANDLED; | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * Initialize the MSIX entry table. | ||
90 | */ | ||
91 | static void | ||
92 | bfad_init_msix_entry(struct bfad_s *bfad, struct msix_entry *msix_entries, | ||
93 | int mask, int max_bit) | ||
94 | { | ||
95 | int i; | ||
96 | int match = 0x00000001; | ||
97 | |||
98 | for (i = 0, bfad->nvec = 0; i < MAX_MSIX_ENTRY; i++) { | ||
99 | if (mask & match) { | ||
100 | bfad->msix_tab[bfad->nvec].msix.entry = i; | ||
101 | bfad->msix_tab[bfad->nvec].bfad = bfad; | ||
102 | msix_entries[bfad->nvec].entry = i; | ||
103 | bfad->nvec++; | ||
104 | } | ||
105 | |||
106 | match <<= 1; | ||
107 | } | ||
108 | |||
109 | } | ||
110 | |||
111 | int | ||
112 | bfad_install_msix_handler(struct bfad_s *bfad) | ||
113 | { | ||
114 | int i, error = 0; | ||
115 | |||
116 | for (i = 0; i < bfad->nvec; i++) { | ||
117 | error = request_irq(bfad->msix_tab[i].msix.vector, | ||
118 | (irq_handler_t) bfad_msix, 0, | ||
119 | BFAD_DRIVER_NAME, &bfad->msix_tab[i]); | ||
120 | bfa_trc(bfad, i); | ||
121 | bfa_trc(bfad, bfad->msix_tab[i].msix.vector); | ||
122 | if (error) { | ||
123 | int j; | ||
124 | |||
125 | for (j = 0; j < i; j++) | ||
126 | free_irq(bfad->msix_tab[j].msix.vector, | ||
127 | &bfad->msix_tab[j]); | ||
128 | |||
129 | return 1; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * Setup MSIX based interrupt. | ||
138 | */ | ||
139 | int | ||
140 | bfad_setup_intr(struct bfad_s *bfad) | ||
141 | { | ||
142 | int error = 0; | ||
143 | u32 mask = 0, i, num_bit = 0, max_bit = 0; | ||
144 | struct msix_entry msix_entries[MAX_MSIX_ENTRY]; | ||
145 | |||
146 | /* Call BFA to get the msix map for this PCI function. */ | ||
147 | bfa_msix_getvecs(&bfad->bfa, &mask, &num_bit, &max_bit); | ||
148 | |||
149 | /* Set up the msix entry table */ | ||
150 | bfad_init_msix_entry(bfad, msix_entries, mask, max_bit); | ||
151 | |||
152 | if (!msix_disable) { | ||
153 | error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec); | ||
154 | if (error) { | ||
155 | /* | ||
156 | * Only error number of vector is available. | ||
157 | * We don't have a mechanism to map multiple | ||
158 | * interrupts into one vector, so even if we | ||
159 | * can try to request less vectors, we don't | ||
160 | * know how to associate interrupt events to | ||
161 | * vectors. Linux doesn't dupicate vectors | ||
162 | * in the MSIX table for this case. | ||
163 | */ | ||
164 | |||
165 | printk(KERN_WARNING "bfad%d: " | ||
166 | "pci_enable_msix failed (%d)," | ||
167 | " use line based.\n", bfad->inst_no, error); | ||
168 | |||
169 | goto line_based; | ||
170 | } | ||
171 | |||
172 | /* Save the vectors */ | ||
173 | for (i = 0; i < bfad->nvec; i++) { | ||
174 | bfa_trc(bfad, msix_entries[i].vector); | ||
175 | bfad->msix_tab[i].msix.vector = msix_entries[i].vector; | ||
176 | } | ||
177 | |||
178 | bfa_msix_init(&bfad->bfa, bfad->nvec); | ||
179 | |||
180 | bfad->bfad_flags |= BFAD_MSIX_ON; | ||
181 | |||
182 | return error; | ||
183 | } | ||
184 | |||
185 | line_based: | ||
186 | error = 0; | ||
187 | if (request_irq | ||
188 | (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS, | ||
189 | BFAD_DRIVER_NAME, bfad) != 0) { | ||
190 | /* Enable interrupt handler failed */ | ||
191 | return 1; | ||
192 | } | ||
193 | |||
194 | return error; | ||
195 | } | ||
196 | |||
197 | void | ||
198 | bfad_remove_intr(struct bfad_s *bfad) | ||
199 | { | ||
200 | int i; | ||
201 | |||
202 | if (bfad->bfad_flags & BFAD_MSIX_ON) { | ||
203 | for (i = 0; i < bfad->nvec; i++) | ||
204 | free_irq(bfad->msix_tab[i].msix.vector, | ||
205 | &bfad->msix_tab[i]); | ||
206 | |||
207 | pci_disable_msix(bfad->pcidev); | ||
208 | bfad->bfad_flags &= ~BFAD_MSIX_ON; | ||
209 | } else { | ||
210 | free_irq(bfad->pcidev->irq, bfad); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | |||
diff --git a/drivers/scsi/bfa/bfad_ipfc.h b/drivers/scsi/bfa/bfad_ipfc.h new file mode 100644 index 000000000000..718bc5227671 --- /dev/null +++ b/drivers/scsi/bfa/bfad_ipfc.h | |||
@@ -0,0 +1,42 @@ | |||
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 | #ifndef __BFA_DRV_IPFC_H__ | ||
18 | #define __BFA_DRV_IPFC_H__ | ||
19 | |||
20 | |||
21 | #define IPFC_NAME "" | ||
22 | |||
23 | #define bfad_ipfc_module_init(x) do {} while (0) | ||
24 | #define bfad_ipfc_module_exit(x) do {} while (0) | ||
25 | #define bfad_ipfc_probe(x) do {} while (0) | ||
26 | #define bfad_ipfc_probe_undo(x) do {} while (0) | ||
27 | #define bfad_ipfc_port_config(x, y) BFA_STATUS_OK | ||
28 | #define bfad_ipfc_port_unconfig(x, y) do {} while (0) | ||
29 | |||
30 | #define bfad_ipfc_probe_post(x) do {} while (0) | ||
31 | #define bfad_ipfc_port_new(x, y, z) BFA_STATUS_OK | ||
32 | #define bfad_ipfc_port_delete(x, y) do {} while (0) | ||
33 | #define bfad_ipfc_port_online(x, y) do {} while (0) | ||
34 | #define bfad_ipfc_port_offline(x, y) do {} while (0) | ||
35 | |||
36 | #define bfad_ip_get_attr(x) BFA_STATUS_FAILED | ||
37 | #define bfad_ip_reset_drv_stats(x) BFA_STATUS_FAILED | ||
38 | #define bfad_ip_get_drv_stats(x, y) BFA_STATUS_FAILED | ||
39 | #define bfad_ip_enable_ipfc(x, y, z) BFA_STATUS_FAILED | ||
40 | |||
41 | |||
42 | #endif | ||
diff --git a/drivers/scsi/bfa/bfad_os.c b/drivers/scsi/bfa/bfad_os.c new file mode 100644 index 000000000000..faf47b4f1a38 --- /dev/null +++ b/drivers/scsi/bfa/bfad_os.c | |||
@@ -0,0 +1,50 @@ | |||
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 | * bfad_os.c Linux driver OS specific calls. | ||
20 | */ | ||
21 | |||
22 | #include "bfa_os_inc.h" | ||
23 | #include "bfad_drv.h" | ||
24 | |||
25 | void | ||
26 | bfa_os_gettimeofday(struct bfa_timeval_s *tv) | ||
27 | { | ||
28 | struct timeval tmp_tv; | ||
29 | |||
30 | do_gettimeofday(&tmp_tv); | ||
31 | tv->tv_sec = (u32) tmp_tv.tv_sec; | ||
32 | tv->tv_usec = (u32) tmp_tv.tv_usec; | ||
33 | } | ||
34 | |||
35 | void | ||
36 | bfa_os_printf(struct bfa_log_mod_s *log_mod, u32 msg_id, | ||
37 | const char *fmt, ...) | ||
38 | { | ||
39 | va_list ap; | ||
40 | #define BFA_STRING_256 256 | ||
41 | char tmp[BFA_STRING_256]; | ||
42 | |||
43 | va_start(ap, fmt); | ||
44 | vsprintf(tmp, fmt, ap); | ||
45 | va_end(ap); | ||
46 | |||
47 | printk(tmp); | ||
48 | } | ||
49 | |||
50 | |||
diff --git a/drivers/scsi/bfa/bfad_tm.h b/drivers/scsi/bfa/bfad_tm.h new file mode 100644 index 000000000000..4901b1b7df02 --- /dev/null +++ b/drivers/scsi/bfa/bfad_tm.h | |||
@@ -0,0 +1,59 @@ | |||
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 | * Brocade Fibre Channel HBA Linux Target Mode Driver | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * tm/dummy/bfad_tm.h BFA callback dummy header file for BFA Linux target mode PCI interface module. | ||
24 | */ | ||
25 | |||
26 | #ifndef __BFAD_TM_H__ | ||
27 | #define __BFAD_TM_H__ | ||
28 | |||
29 | #include <defs/bfa_defs_status.h> | ||
30 | |||
31 | #define FCPT_NAME "" | ||
32 | |||
33 | /* | ||
34 | * Called from base Linux driver on (De)Init events | ||
35 | */ | ||
36 | |||
37 | /* attach tgt template with scst */ | ||
38 | #define bfad_tm_module_init() do {} while (0) | ||
39 | |||
40 | /* detach/release tgt template */ | ||
41 | #define bfad_tm_module_exit() do {} while (0) | ||
42 | |||
43 | #define bfad_tm_probe(x) do {} while (0) | ||
44 | #define bfad_tm_probe_undo(x) do {} while (0) | ||
45 | #define bfad_tm_probe_post(x) do {} while (0) | ||
46 | |||
47 | /* | ||
48 | * Called by base Linux driver but triggered by BFA FCS on config events | ||
49 | */ | ||
50 | #define bfad_tm_port_new(x, y) BFA_STATUS_OK | ||
51 | #define bfad_tm_port_delete(x, y) do {} while (0) | ||
52 | |||
53 | /* | ||
54 | * Called by base Linux driver but triggered by BFA FCS on PLOGI/O events | ||
55 | */ | ||
56 | #define bfad_tm_port_online(x, y) do {} while (0) | ||
57 | #define bfad_tm_port_offline(x, y) do {} while (0) | ||
58 | |||
59 | #endif | ||
diff --git a/drivers/scsi/bfa/bfad_trcmod.h b/drivers/scsi/bfa/bfad_trcmod.h new file mode 100644 index 000000000000..2827b2acd041 --- /dev/null +++ b/drivers/scsi/bfa/bfad_trcmod.h | |||
@@ -0,0 +1,52 @@ | |||
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 | * bfad_trcmod.h Linux driver trace modules | ||
20 | */ | ||
21 | |||
22 | |||
23 | #ifndef __BFAD_TRCMOD_H__ | ||
24 | #define __BFAD_TRCMOD_H__ | ||
25 | |||
26 | #include <cs/bfa_trc.h> | ||
27 | |||
28 | /* | ||
29 | * !!! Only append to the enums defined here to avoid any versioning | ||
30 | * !!! needed between trace utility and driver version | ||
31 | */ | ||
32 | enum { | ||
33 | /* 2.6 Driver */ | ||
34 | BFA_TRC_LDRV_BFAD = 1, | ||
35 | BFA_TRC_LDRV_BFAD_2_6 = 2, | ||
36 | BFA_TRC_LDRV_BFAD_2_6_9 = 3, | ||
37 | BFA_TRC_LDRV_BFAD_2_6_10 = 4, | ||
38 | BFA_TRC_LDRV_INTR = 5, | ||
39 | BFA_TRC_LDRV_IOCTL = 6, | ||
40 | BFA_TRC_LDRV_OS = 7, | ||
41 | BFA_TRC_LDRV_IM = 8, | ||
42 | BFA_TRC_LDRV_IM_2_6 = 9, | ||
43 | BFA_TRC_LDRV_IM_2_6_9 = 10, | ||
44 | BFA_TRC_LDRV_IM_2_6_10 = 11, | ||
45 | BFA_TRC_LDRV_TM = 12, | ||
46 | BFA_TRC_LDRV_IPFC = 13, | ||
47 | BFA_TRC_LDRV_IM_2_4 = 14, | ||
48 | BFA_TRC_LDRV_IM_VMW = 15, | ||
49 | BFA_TRC_LDRV_IM_LT_2_6_10 = 16, | ||
50 | }; | ||
51 | |||
52 | #endif /* __BFAD_TRCMOD_H__ */ | ||
diff --git a/drivers/scsi/bfa/fab.c b/drivers/scsi/bfa/fab.c new file mode 100644 index 000000000000..7e3a4d5d7bb4 --- /dev/null +++ b/drivers/scsi/bfa/fab.c | |||
@@ -0,0 +1,62 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfa_svc.h> | ||
20 | #include "fcs_lport.h" | ||
21 | #include "fcs_rport.h" | ||
22 | #include "lport_priv.h" | ||
23 | |||
24 | /** | ||
25 | * fab.c port fab implementation. | ||
26 | */ | ||
27 | |||
28 | /** | ||
29 | * bfa_fcs_port_fab_public port fab public functions | ||
30 | */ | ||
31 | |||
32 | /** | ||
33 | * Called by port to initialize fabric services of the base port. | ||
34 | */ | ||
35 | void | ||
36 | bfa_fcs_port_fab_init(struct bfa_fcs_port_s *port) | ||
37 | { | ||
38 | bfa_fcs_port_ns_init(port); | ||
39 | bfa_fcs_port_scn_init(port); | ||
40 | bfa_fcs_port_ms_init(port); | ||
41 | } | ||
42 | |||
43 | /** | ||
44 | * Called by port to notify transition to online state. | ||
45 | */ | ||
46 | void | ||
47 | bfa_fcs_port_fab_online(struct bfa_fcs_port_s *port) | ||
48 | { | ||
49 | bfa_fcs_port_ns_online(port); | ||
50 | bfa_fcs_port_scn_online(port); | ||
51 | } | ||
52 | |||
53 | /** | ||
54 | * Called by port to notify transition to offline state. | ||
55 | */ | ||
56 | void | ||
57 | bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *port) | ||
58 | { | ||
59 | bfa_fcs_port_ns_offline(port); | ||
60 | bfa_fcs_port_scn_offline(port); | ||
61 | bfa_fcs_port_ms_offline(port); | ||
62 | } | ||
diff --git a/drivers/scsi/bfa/fabric.c b/drivers/scsi/bfa/fabric.c new file mode 100644 index 000000000000..a8b14c47b009 --- /dev/null +++ b/drivers/scsi/bfa/fabric.c | |||
@@ -0,0 +1,1278 @@ | |||
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 | * fabric.c Fabric module implementation. | ||
20 | */ | ||
21 | |||
22 | #include "fcs_fabric.h" | ||
23 | #include "fcs_lport.h" | ||
24 | #include "fcs_vport.h" | ||
25 | #include "fcs_trcmod.h" | ||
26 | #include "fcs_fcxp.h" | ||
27 | #include "fcs_auth.h" | ||
28 | #include "fcs.h" | ||
29 | #include "fcbuild.h" | ||
30 | #include <log/bfa_log_fcs.h> | ||
31 | #include <aen/bfa_aen_port.h> | ||
32 | #include <bfa_svc.h> | ||
33 | |||
34 | BFA_TRC_FILE(FCS, FABRIC); | ||
35 | |||
36 | #define BFA_FCS_FABRIC_RETRY_DELAY (2000) /* Milliseconds */ | ||
37 | #define BFA_FCS_FABRIC_CLEANUP_DELAY (10000) /* Milliseconds */ | ||
38 | |||
39 | #define bfa_fcs_fabric_set_opertype(__fabric) do { \ | ||
40 | if (bfa_pport_get_topology((__fabric)->fcs->bfa) \ | ||
41 | == BFA_PPORT_TOPOLOGY_P2P) \ | ||
42 | (__fabric)->oper_type = BFA_PPORT_TYPE_NPORT; \ | ||
43 | else \ | ||
44 | (__fabric)->oper_type = BFA_PPORT_TYPE_NLPORT; \ | ||
45 | } while (0) | ||
46 | |||
47 | /* | ||
48 | * forward declarations | ||
49 | */ | ||
50 | static void bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric); | ||
51 | static void bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric); | ||
52 | static void bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric); | ||
53 | static void bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric); | ||
54 | static void bfa_fcs_fabric_delay(void *cbarg); | ||
55 | static void bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric); | ||
56 | static void bfa_fcs_fabric_delete_comp(void *cbarg); | ||
57 | static void bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, | ||
58 | struct fchs_s *fchs, u16 len); | ||
59 | static void bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, | ||
60 | struct fchs_s *fchs, u16 len); | ||
61 | static void bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric); | ||
62 | static void bfa_fcs_fabric_flogiacc_comp(void *fcsarg, | ||
63 | struct bfa_fcxp_s *fcxp, | ||
64 | void *cbarg, bfa_status_t status, | ||
65 | u32 rsp_len, | ||
66 | u32 resid_len, | ||
67 | struct fchs_s *rspfchs); | ||
68 | /** | ||
69 | * fcs_fabric_sm fabric state machine functions | ||
70 | */ | ||
71 | |||
72 | /** | ||
73 | * Fabric state machine events | ||
74 | */ | ||
75 | enum bfa_fcs_fabric_event { | ||
76 | BFA_FCS_FABRIC_SM_CREATE = 1, /* fabric create from driver */ | ||
77 | BFA_FCS_FABRIC_SM_DELETE = 2, /* fabric delete from driver */ | ||
78 | BFA_FCS_FABRIC_SM_LINK_DOWN = 3, /* link down from port */ | ||
79 | BFA_FCS_FABRIC_SM_LINK_UP = 4, /* link up from port */ | ||
80 | BFA_FCS_FABRIC_SM_CONT_OP = 5, /* continue op from flogi/auth */ | ||
81 | BFA_FCS_FABRIC_SM_RETRY_OP = 6, /* continue op from flogi/auth */ | ||
82 | BFA_FCS_FABRIC_SM_NO_FABRIC = 7, /* no fabric from flogi/auth | ||
83 | */ | ||
84 | BFA_FCS_FABRIC_SM_PERF_EVFP = 8, /* perform EVFP from | ||
85 | *flogi/auth */ | ||
86 | BFA_FCS_FABRIC_SM_ISOLATE = 9, /* isolate from EVFP processing */ | ||
87 | BFA_FCS_FABRIC_SM_NO_TAGGING = 10,/* no VFT tagging from EVFP */ | ||
88 | BFA_FCS_FABRIC_SM_DELAYED = 11, /* timeout delay event */ | ||
89 | BFA_FCS_FABRIC_SM_AUTH_FAILED = 12, /* authentication failed */ | ||
90 | BFA_FCS_FABRIC_SM_AUTH_SUCCESS = 13, /* authentication successful | ||
91 | */ | ||
92 | BFA_FCS_FABRIC_SM_DELCOMP = 14, /* all vports deleted event */ | ||
93 | BFA_FCS_FABRIC_SM_LOOPBACK = 15, /* Received our own FLOGI */ | ||
94 | BFA_FCS_FABRIC_SM_START = 16, /* fabric delete from driver */ | ||
95 | }; | ||
96 | |||
97 | static void bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, | ||
98 | enum bfa_fcs_fabric_event event); | ||
99 | static void bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, | ||
100 | enum bfa_fcs_fabric_event event); | ||
101 | static void bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric, | ||
102 | enum bfa_fcs_fabric_event event); | ||
103 | static void bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, | ||
104 | enum bfa_fcs_fabric_event event); | ||
105 | static void bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, | ||
106 | enum bfa_fcs_fabric_event event); | ||
107 | static void bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, | ||
108 | enum bfa_fcs_fabric_event event); | ||
109 | static void bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, | ||
110 | enum bfa_fcs_fabric_event event); | ||
111 | static void bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, | ||
112 | enum bfa_fcs_fabric_event event); | ||
113 | static void bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, | ||
114 | enum bfa_fcs_fabric_event event); | ||
115 | static void bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, | ||
116 | enum bfa_fcs_fabric_event event); | ||
117 | static void bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, | ||
118 | enum bfa_fcs_fabric_event event); | ||
119 | static void bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, | ||
120 | enum bfa_fcs_fabric_event event); | ||
121 | static void bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric, | ||
122 | enum bfa_fcs_fabric_event event); | ||
123 | static void bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, | ||
124 | enum bfa_fcs_fabric_event event); | ||
125 | /** | ||
126 | * Beginning state before fabric creation. | ||
127 | */ | ||
128 | static void | ||
129 | bfa_fcs_fabric_sm_uninit(struct bfa_fcs_fabric_s *fabric, | ||
130 | enum bfa_fcs_fabric_event event) | ||
131 | { | ||
132 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
133 | bfa_trc(fabric->fcs, event); | ||
134 | |||
135 | switch (event) { | ||
136 | case BFA_FCS_FABRIC_SM_CREATE: | ||
137 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_created); | ||
138 | bfa_fcs_fabric_init(fabric); | ||
139 | bfa_fcs_lport_init(&fabric->bport, fabric->fcs, FC_VF_ID_NULL, | ||
140 | &fabric->bport.port_cfg, NULL); | ||
141 | break; | ||
142 | |||
143 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
144 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
145 | break; | ||
146 | |||
147 | default: | ||
148 | bfa_sm_fault(fabric->fcs, event); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * Beginning state before fabric creation. | ||
154 | */ | ||
155 | static void | ||
156 | bfa_fcs_fabric_sm_created(struct bfa_fcs_fabric_s *fabric, | ||
157 | enum bfa_fcs_fabric_event event) | ||
158 | { | ||
159 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
160 | bfa_trc(fabric->fcs, event); | ||
161 | |||
162 | switch (event) { | ||
163 | case BFA_FCS_FABRIC_SM_START: | ||
164 | if (bfa_pport_is_linkup(fabric->fcs->bfa)) { | ||
165 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | ||
166 | bfa_fcs_fabric_login(fabric); | ||
167 | } else | ||
168 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
169 | break; | ||
170 | |||
171 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
172 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
173 | break; | ||
174 | |||
175 | case BFA_FCS_FABRIC_SM_DELETE: | ||
176 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | ||
177 | bfa_fcs_modexit_comp(fabric->fcs); | ||
178 | break; | ||
179 | |||
180 | default: | ||
181 | bfa_sm_fault(fabric->fcs, event); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | /** | ||
186 | * Link is down, awaiting LINK UP event from port. This is also the | ||
187 | * first state at fabric creation. | ||
188 | */ | ||
189 | static void | ||
190 | bfa_fcs_fabric_sm_linkdown(struct bfa_fcs_fabric_s *fabric, | ||
191 | enum bfa_fcs_fabric_event event) | ||
192 | { | ||
193 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
194 | bfa_trc(fabric->fcs, event); | ||
195 | |||
196 | switch (event) { | ||
197 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
198 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | ||
199 | bfa_fcs_fabric_login(fabric); | ||
200 | break; | ||
201 | |||
202 | case BFA_FCS_FABRIC_SM_RETRY_OP: | ||
203 | break; | ||
204 | |||
205 | case BFA_FCS_FABRIC_SM_DELETE: | ||
206 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
207 | bfa_fcs_fabric_delete(fabric); | ||
208 | break; | ||
209 | |||
210 | default: | ||
211 | bfa_sm_fault(fabric->fcs, event); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * FLOGI is in progress, awaiting FLOGI reply. | ||
217 | */ | ||
218 | static void | ||
219 | bfa_fcs_fabric_sm_flogi(struct bfa_fcs_fabric_s *fabric, | ||
220 | enum bfa_fcs_fabric_event event) | ||
221 | { | ||
222 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
223 | bfa_trc(fabric->fcs, event); | ||
224 | |||
225 | switch (event) { | ||
226 | case BFA_FCS_FABRIC_SM_CONT_OP: | ||
227 | |||
228 | bfa_pport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit); | ||
229 | fabric->fab_type = BFA_FCS_FABRIC_SWITCHED; | ||
230 | |||
231 | if (fabric->auth_reqd && fabric->is_auth) { | ||
232 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth); | ||
233 | bfa_trc(fabric->fcs, event); | ||
234 | } else { | ||
235 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online); | ||
236 | bfa_fcs_fabric_notify_online(fabric); | ||
237 | } | ||
238 | break; | ||
239 | |||
240 | case BFA_FCS_FABRIC_SM_RETRY_OP: | ||
241 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi_retry); | ||
242 | bfa_timer_start(fabric->fcs->bfa, &fabric->delay_timer, | ||
243 | bfa_fcs_fabric_delay, fabric, | ||
244 | BFA_FCS_FABRIC_RETRY_DELAY); | ||
245 | break; | ||
246 | |||
247 | case BFA_FCS_FABRIC_SM_LOOPBACK: | ||
248 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_loopback); | ||
249 | bfa_lps_discard(fabric->lps); | ||
250 | bfa_fcs_fabric_set_opertype(fabric); | ||
251 | break; | ||
252 | |||
253 | case BFA_FCS_FABRIC_SM_NO_FABRIC: | ||
254 | fabric->fab_type = BFA_FCS_FABRIC_N2N; | ||
255 | bfa_pport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit); | ||
256 | bfa_fcs_fabric_notify_online(fabric); | ||
257 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_nofabric); | ||
258 | break; | ||
259 | |||
260 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
261 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
262 | bfa_lps_discard(fabric->lps); | ||
263 | break; | ||
264 | |||
265 | case BFA_FCS_FABRIC_SM_DELETE: | ||
266 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
267 | bfa_lps_discard(fabric->lps); | ||
268 | bfa_fcs_fabric_delete(fabric); | ||
269 | break; | ||
270 | |||
271 | default: | ||
272 | bfa_sm_fault(fabric->fcs, event); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | |||
277 | static void | ||
278 | bfa_fcs_fabric_sm_flogi_retry(struct bfa_fcs_fabric_s *fabric, | ||
279 | enum bfa_fcs_fabric_event event) | ||
280 | { | ||
281 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
282 | bfa_trc(fabric->fcs, event); | ||
283 | |||
284 | switch (event) { | ||
285 | case BFA_FCS_FABRIC_SM_DELAYED: | ||
286 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_flogi); | ||
287 | bfa_fcs_fabric_login(fabric); | ||
288 | break; | ||
289 | |||
290 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
291 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
292 | bfa_timer_stop(&fabric->delay_timer); | ||
293 | break; | ||
294 | |||
295 | case BFA_FCS_FABRIC_SM_DELETE: | ||
296 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
297 | bfa_timer_stop(&fabric->delay_timer); | ||
298 | bfa_fcs_fabric_delete(fabric); | ||
299 | break; | ||
300 | |||
301 | default: | ||
302 | bfa_sm_fault(fabric->fcs, event); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * Authentication is in progress, awaiting authentication results. | ||
308 | */ | ||
309 | static void | ||
310 | bfa_fcs_fabric_sm_auth(struct bfa_fcs_fabric_s *fabric, | ||
311 | enum bfa_fcs_fabric_event event) | ||
312 | { | ||
313 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
314 | bfa_trc(fabric->fcs, event); | ||
315 | |||
316 | switch (event) { | ||
317 | case BFA_FCS_FABRIC_SM_AUTH_FAILED: | ||
318 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); | ||
319 | bfa_lps_discard(fabric->lps); | ||
320 | break; | ||
321 | |||
322 | case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: | ||
323 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_online); | ||
324 | bfa_fcs_fabric_notify_online(fabric); | ||
325 | break; | ||
326 | |||
327 | case BFA_FCS_FABRIC_SM_PERF_EVFP: | ||
328 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp); | ||
329 | break; | ||
330 | |||
331 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
332 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
333 | bfa_lps_discard(fabric->lps); | ||
334 | break; | ||
335 | |||
336 | case BFA_FCS_FABRIC_SM_DELETE: | ||
337 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
338 | bfa_fcs_fabric_delete(fabric); | ||
339 | break; | ||
340 | |||
341 | default: | ||
342 | bfa_sm_fault(fabric->fcs, event); | ||
343 | } | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * Authentication failed | ||
348 | */ | ||
349 | static void | ||
350 | bfa_fcs_fabric_sm_auth_failed(struct bfa_fcs_fabric_s *fabric, | ||
351 | enum bfa_fcs_fabric_event event) | ||
352 | { | ||
353 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
354 | bfa_trc(fabric->fcs, event); | ||
355 | |||
356 | switch (event) { | ||
357 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
358 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
359 | bfa_fcs_fabric_notify_offline(fabric); | ||
360 | break; | ||
361 | |||
362 | case BFA_FCS_FABRIC_SM_DELETE: | ||
363 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
364 | bfa_fcs_fabric_delete(fabric); | ||
365 | break; | ||
366 | |||
367 | default: | ||
368 | bfa_sm_fault(fabric->fcs, event); | ||
369 | } | ||
370 | } | ||
371 | |||
372 | /** | ||
373 | * Port is in loopback mode. | ||
374 | */ | ||
375 | static void | ||
376 | bfa_fcs_fabric_sm_loopback(struct bfa_fcs_fabric_s *fabric, | ||
377 | enum bfa_fcs_fabric_event event) | ||
378 | { | ||
379 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
380 | bfa_trc(fabric->fcs, event); | ||
381 | |||
382 | switch (event) { | ||
383 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
384 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
385 | bfa_fcs_fabric_notify_offline(fabric); | ||
386 | break; | ||
387 | |||
388 | case BFA_FCS_FABRIC_SM_DELETE: | ||
389 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
390 | bfa_fcs_fabric_delete(fabric); | ||
391 | break; | ||
392 | |||
393 | default: | ||
394 | bfa_sm_fault(fabric->fcs, event); | ||
395 | } | ||
396 | } | ||
397 | |||
398 | /** | ||
399 | * There is no attached fabric - private loop or NPort-to-NPort topology. | ||
400 | */ | ||
401 | static void | ||
402 | bfa_fcs_fabric_sm_nofabric(struct bfa_fcs_fabric_s *fabric, | ||
403 | enum bfa_fcs_fabric_event event) | ||
404 | { | ||
405 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
406 | bfa_trc(fabric->fcs, event); | ||
407 | |||
408 | switch (event) { | ||
409 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
410 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
411 | bfa_lps_discard(fabric->lps); | ||
412 | bfa_fcs_fabric_notify_offline(fabric); | ||
413 | break; | ||
414 | |||
415 | case BFA_FCS_FABRIC_SM_DELETE: | ||
416 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
417 | bfa_fcs_fabric_delete(fabric); | ||
418 | break; | ||
419 | |||
420 | case BFA_FCS_FABRIC_SM_NO_FABRIC: | ||
421 | bfa_trc(fabric->fcs, fabric->bb_credit); | ||
422 | bfa_pport_set_tx_bbcredit(fabric->fcs->bfa, fabric->bb_credit); | ||
423 | break; | ||
424 | |||
425 | default: | ||
426 | bfa_sm_fault(fabric->fcs, event); | ||
427 | } | ||
428 | } | ||
429 | |||
430 | /** | ||
431 | * Fabric is online - normal operating state. | ||
432 | */ | ||
433 | static void | ||
434 | bfa_fcs_fabric_sm_online(struct bfa_fcs_fabric_s *fabric, | ||
435 | enum bfa_fcs_fabric_event event) | ||
436 | { | ||
437 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
438 | bfa_trc(fabric->fcs, event); | ||
439 | |||
440 | switch (event) { | ||
441 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
442 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_linkdown); | ||
443 | bfa_lps_discard(fabric->lps); | ||
444 | bfa_fcs_fabric_notify_offline(fabric); | ||
445 | break; | ||
446 | |||
447 | case BFA_FCS_FABRIC_SM_DELETE: | ||
448 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_deleting); | ||
449 | bfa_fcs_fabric_delete(fabric); | ||
450 | break; | ||
451 | |||
452 | case BFA_FCS_FABRIC_SM_AUTH_FAILED: | ||
453 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_auth_failed); | ||
454 | bfa_lps_discard(fabric->lps); | ||
455 | break; | ||
456 | |||
457 | case BFA_FCS_FABRIC_SM_AUTH_SUCCESS: | ||
458 | break; | ||
459 | |||
460 | default: | ||
461 | bfa_sm_fault(fabric->fcs, event); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | /** | ||
466 | * Exchanging virtual fabric parameters. | ||
467 | */ | ||
468 | static void | ||
469 | bfa_fcs_fabric_sm_evfp(struct bfa_fcs_fabric_s *fabric, | ||
470 | enum bfa_fcs_fabric_event event) | ||
471 | { | ||
472 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
473 | bfa_trc(fabric->fcs, event); | ||
474 | |||
475 | switch (event) { | ||
476 | case BFA_FCS_FABRIC_SM_CONT_OP: | ||
477 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_evfp_done); | ||
478 | break; | ||
479 | |||
480 | case BFA_FCS_FABRIC_SM_ISOLATE: | ||
481 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_isolated); | ||
482 | break; | ||
483 | |||
484 | default: | ||
485 | bfa_sm_fault(fabric->fcs, event); | ||
486 | } | ||
487 | } | ||
488 | |||
489 | /** | ||
490 | * EVFP exchange complete and VFT tagging is enabled. | ||
491 | */ | ||
492 | static void | ||
493 | bfa_fcs_fabric_sm_evfp_done(struct bfa_fcs_fabric_s *fabric, | ||
494 | enum bfa_fcs_fabric_event event) | ||
495 | { | ||
496 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
497 | bfa_trc(fabric->fcs, event); | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * Port is isolated after EVFP exchange due to VF_ID mismatch (N and F). | ||
502 | */ | ||
503 | static void | ||
504 | bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric, | ||
505 | enum bfa_fcs_fabric_event event) | ||
506 | { | ||
507 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
508 | bfa_trc(fabric->fcs, event); | ||
509 | |||
510 | bfa_log(fabric->fcs->logm, BFA_LOG_FCS_FABRIC_ISOLATED, | ||
511 | fabric->bport.port_cfg.pwwn, fabric->fcs->port_vfid, | ||
512 | fabric->event_arg.swp_vfid); | ||
513 | } | ||
514 | |||
515 | /** | ||
516 | * Fabric is being deleted, awaiting vport delete completions. | ||
517 | */ | ||
518 | static void | ||
519 | bfa_fcs_fabric_sm_deleting(struct bfa_fcs_fabric_s *fabric, | ||
520 | enum bfa_fcs_fabric_event event) | ||
521 | { | ||
522 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
523 | bfa_trc(fabric->fcs, event); | ||
524 | |||
525 | switch (event) { | ||
526 | case BFA_FCS_FABRIC_SM_DELCOMP: | ||
527 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | ||
528 | bfa_fcs_modexit_comp(fabric->fcs); | ||
529 | break; | ||
530 | |||
531 | case BFA_FCS_FABRIC_SM_LINK_UP: | ||
532 | break; | ||
533 | |||
534 | case BFA_FCS_FABRIC_SM_LINK_DOWN: | ||
535 | bfa_fcs_fabric_notify_offline(fabric); | ||
536 | break; | ||
537 | |||
538 | default: | ||
539 | bfa_sm_fault(fabric->fcs, event); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | |||
544 | |||
545 | /** | ||
546 | * fcs_fabric_private fabric private functions | ||
547 | */ | ||
548 | |||
549 | static void | ||
550 | bfa_fcs_fabric_init(struct bfa_fcs_fabric_s *fabric) | ||
551 | { | ||
552 | struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg; | ||
553 | |||
554 | port_cfg->roles = BFA_PORT_ROLE_FCP_IM; | ||
555 | port_cfg->nwwn = bfa_ioc_get_nwwn(&fabric->fcs->bfa->ioc); | ||
556 | port_cfg->pwwn = bfa_ioc_get_pwwn(&fabric->fcs->bfa->ioc); | ||
557 | } | ||
558 | |||
559 | /** | ||
560 | * Port Symbolic Name Creation for base port. | ||
561 | */ | ||
562 | void | ||
563 | bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric) | ||
564 | { | ||
565 | struct bfa_port_cfg_s *port_cfg = &fabric->bport.port_cfg; | ||
566 | struct bfa_adapter_attr_s adapter_attr; | ||
567 | struct bfa_fcs_driver_info_s *driver_info = &fabric->fcs->driver_info; | ||
568 | |||
569 | bfa_os_memset((void *)&adapter_attr, 0, | ||
570 | sizeof(struct bfa_adapter_attr_s)); | ||
571 | bfa_ioc_get_adapter_attr(&fabric->fcs->bfa->ioc, &adapter_attr); | ||
572 | |||
573 | /* | ||
574 | * Model name/number | ||
575 | */ | ||
576 | strncpy((char *)&port_cfg->sym_name, adapter_attr.model, | ||
577 | BFA_FCS_PORT_SYMBNAME_MODEL_SZ); | ||
578 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
579 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
580 | |||
581 | /* | ||
582 | * Driver Version | ||
583 | */ | ||
584 | strncat((char *)&port_cfg->sym_name, (char *)driver_info->version, | ||
585 | BFA_FCS_PORT_SYMBNAME_VERSION_SZ); | ||
586 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
587 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
588 | |||
589 | /* | ||
590 | * Host machine name | ||
591 | */ | ||
592 | strncat((char *)&port_cfg->sym_name, | ||
593 | (char *)driver_info->host_machine_name, | ||
594 | BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ); | ||
595 | strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
596 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
597 | |||
598 | /* | ||
599 | * Host OS Info : | ||
600 | * If OS Patch Info is not there, do not truncate any bytes from the | ||
601 | * OS name string and instead copy the entire OS info string (64 bytes). | ||
602 | */ | ||
603 | if (driver_info->host_os_patch[0] == '\0') { | ||
604 | strncat((char *)&port_cfg->sym_name, | ||
605 | (char *)driver_info->host_os_name, BFA_FCS_OS_STR_LEN); | ||
606 | strncat((char *)&port_cfg->sym_name, | ||
607 | BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
608 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
609 | } else { | ||
610 | strncat((char *)&port_cfg->sym_name, | ||
611 | (char *)driver_info->host_os_name, | ||
612 | BFA_FCS_PORT_SYMBNAME_OSINFO_SZ); | ||
613 | strncat((char *)&port_cfg->sym_name, | ||
614 | BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
615 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
616 | |||
617 | /* | ||
618 | * Append host OS Patch Info | ||
619 | */ | ||
620 | strncat((char *)&port_cfg->sym_name, | ||
621 | (char *)driver_info->host_os_patch, | ||
622 | BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ); | ||
623 | } | ||
624 | |||
625 | /* | ||
626 | * null terminate | ||
627 | */ | ||
628 | port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0; | ||
629 | } | ||
630 | |||
631 | /** | ||
632 | * bfa lps login completion callback | ||
633 | */ | ||
634 | void | ||
635 | bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status) | ||
636 | { | ||
637 | struct bfa_fcs_fabric_s *fabric = uarg; | ||
638 | |||
639 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
640 | bfa_trc(fabric->fcs, status); | ||
641 | |||
642 | switch (status) { | ||
643 | case BFA_STATUS_OK: | ||
644 | fabric->stats.flogi_accepts++; | ||
645 | break; | ||
646 | |||
647 | case BFA_STATUS_INVALID_MAC: | ||
648 | /* | ||
649 | * Only for CNA | ||
650 | */ | ||
651 | fabric->stats.flogi_acc_err++; | ||
652 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
653 | |||
654 | return; | ||
655 | |||
656 | case BFA_STATUS_EPROTOCOL: | ||
657 | switch (bfa_lps_get_extstatus(fabric->lps)) { | ||
658 | case BFA_EPROTO_BAD_ACCEPT: | ||
659 | fabric->stats.flogi_acc_err++; | ||
660 | break; | ||
661 | |||
662 | case BFA_EPROTO_UNKNOWN_RSP: | ||
663 | fabric->stats.flogi_unknown_rsp++; | ||
664 | break; | ||
665 | |||
666 | default: | ||
667 | break; | ||
668 | } | ||
669 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
670 | |||
671 | return; | ||
672 | |||
673 | case BFA_STATUS_FABRIC_RJT: | ||
674 | fabric->stats.flogi_rejects++; | ||
675 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
676 | return; | ||
677 | |||
678 | default: | ||
679 | fabric->stats.flogi_rsp_err++; | ||
680 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_RETRY_OP); | ||
681 | return; | ||
682 | } | ||
683 | |||
684 | fabric->bb_credit = bfa_lps_get_peer_bbcredit(fabric->lps); | ||
685 | bfa_trc(fabric->fcs, fabric->bb_credit); | ||
686 | |||
687 | if (!bfa_lps_is_brcd_fabric(fabric->lps)) | ||
688 | fabric->fabric_name = bfa_lps_get_peer_nwwn(fabric->lps); | ||
689 | |||
690 | /* | ||
691 | * Check port type. It should be 1 = F-port. | ||
692 | */ | ||
693 | if (bfa_lps_is_fport(fabric->lps)) { | ||
694 | fabric->bport.pid = bfa_lps_get_pid(fabric->lps); | ||
695 | fabric->is_npiv = bfa_lps_is_npiv_en(fabric->lps); | ||
696 | fabric->is_auth = bfa_lps_is_authreq(fabric->lps); | ||
697 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CONT_OP); | ||
698 | } else { | ||
699 | /* | ||
700 | * Nport-2-Nport direct attached | ||
701 | */ | ||
702 | fabric->bport.port_topo.pn2n.rem_port_wwn = | ||
703 | bfa_lps_get_peer_pwwn(fabric->lps); | ||
704 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC); | ||
705 | } | ||
706 | |||
707 | bfa_trc(fabric->fcs, fabric->bport.pid); | ||
708 | bfa_trc(fabric->fcs, fabric->is_npiv); | ||
709 | bfa_trc(fabric->fcs, fabric->is_auth); | ||
710 | } | ||
711 | |||
712 | /** | ||
713 | * Allocate and send FLOGI. | ||
714 | */ | ||
715 | static void | ||
716 | bfa_fcs_fabric_login(struct bfa_fcs_fabric_s *fabric) | ||
717 | { | ||
718 | struct bfa_s *bfa = fabric->fcs->bfa; | ||
719 | struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg; | ||
720 | u8 alpa = 0; | ||
721 | |||
722 | if (bfa_pport_get_topology(bfa) == BFA_PPORT_TOPOLOGY_LOOP) | ||
723 | alpa = bfa_pport_get_myalpa(bfa); | ||
724 | |||
725 | bfa_lps_flogi(fabric->lps, fabric, alpa, bfa_pport_get_maxfrsize(bfa), | ||
726 | pcfg->pwwn, pcfg->nwwn, fabric->auth_reqd); | ||
727 | |||
728 | fabric->stats.flogi_sent++; | ||
729 | } | ||
730 | |||
731 | static void | ||
732 | bfa_fcs_fabric_notify_online(struct bfa_fcs_fabric_s *fabric) | ||
733 | { | ||
734 | struct bfa_fcs_vport_s *vport; | ||
735 | struct list_head *qe, *qen; | ||
736 | |||
737 | bfa_trc(fabric->fcs, fabric->fabric_name); | ||
738 | |||
739 | bfa_fcs_fabric_set_opertype(fabric); | ||
740 | fabric->stats.fabric_onlines++; | ||
741 | |||
742 | /** | ||
743 | * notify online event to base and then virtual ports | ||
744 | */ | ||
745 | bfa_fcs_port_online(&fabric->bport); | ||
746 | |||
747 | list_for_each_safe(qe, qen, &fabric->vport_q) { | ||
748 | vport = (struct bfa_fcs_vport_s *)qe; | ||
749 | bfa_fcs_vport_online(vport); | ||
750 | } | ||
751 | } | ||
752 | |||
753 | static void | ||
754 | bfa_fcs_fabric_notify_offline(struct bfa_fcs_fabric_s *fabric) | ||
755 | { | ||
756 | struct bfa_fcs_vport_s *vport; | ||
757 | struct list_head *qe, *qen; | ||
758 | |||
759 | bfa_trc(fabric->fcs, fabric->fabric_name); | ||
760 | fabric->stats.fabric_offlines++; | ||
761 | |||
762 | /** | ||
763 | * notify offline event first to vports and then base port. | ||
764 | */ | ||
765 | list_for_each_safe(qe, qen, &fabric->vport_q) { | ||
766 | vport = (struct bfa_fcs_vport_s *)qe; | ||
767 | bfa_fcs_vport_offline(vport); | ||
768 | } | ||
769 | |||
770 | bfa_fcs_port_offline(&fabric->bport); | ||
771 | |||
772 | fabric->fabric_name = 0; | ||
773 | fabric->fabric_ip_addr[0] = 0; | ||
774 | } | ||
775 | |||
776 | static void | ||
777 | bfa_fcs_fabric_delay(void *cbarg) | ||
778 | { | ||
779 | struct bfa_fcs_fabric_s *fabric = cbarg; | ||
780 | |||
781 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELAYED); | ||
782 | } | ||
783 | |||
784 | /** | ||
785 | * Delete all vports and wait for vport delete completions. | ||
786 | */ | ||
787 | static void | ||
788 | bfa_fcs_fabric_delete(struct bfa_fcs_fabric_s *fabric) | ||
789 | { | ||
790 | struct bfa_fcs_vport_s *vport; | ||
791 | struct list_head *qe, *qen; | ||
792 | |||
793 | list_for_each_safe(qe, qen, &fabric->vport_q) { | ||
794 | vport = (struct bfa_fcs_vport_s *)qe; | ||
795 | bfa_fcs_vport_delete(vport); | ||
796 | } | ||
797 | |||
798 | bfa_fcs_port_delete(&fabric->bport); | ||
799 | bfa_wc_wait(&fabric->wc); | ||
800 | } | ||
801 | |||
802 | static void | ||
803 | bfa_fcs_fabric_delete_comp(void *cbarg) | ||
804 | { | ||
805 | struct bfa_fcs_fabric_s *fabric = cbarg; | ||
806 | |||
807 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELCOMP); | ||
808 | } | ||
809 | |||
810 | |||
811 | |||
812 | /** | ||
813 | * fcs_fabric_public fabric public functions | ||
814 | */ | ||
815 | |||
816 | /** | ||
817 | * Module initialization | ||
818 | */ | ||
819 | void | ||
820 | bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs) | ||
821 | { | ||
822 | struct bfa_fcs_fabric_s *fabric; | ||
823 | |||
824 | fabric = &fcs->fabric; | ||
825 | bfa_os_memset(fabric, 0, sizeof(struct bfa_fcs_fabric_s)); | ||
826 | |||
827 | /** | ||
828 | * Initialize base fabric. | ||
829 | */ | ||
830 | fabric->fcs = fcs; | ||
831 | INIT_LIST_HEAD(&fabric->vport_q); | ||
832 | INIT_LIST_HEAD(&fabric->vf_q); | ||
833 | fabric->lps = bfa_lps_alloc(fcs->bfa); | ||
834 | bfa_assert(fabric->lps); | ||
835 | |||
836 | /** | ||
837 | * Initialize fabric delete completion handler. Fabric deletion is complete | ||
838 | * when the last vport delete is complete. | ||
839 | */ | ||
840 | bfa_wc_init(&fabric->wc, bfa_fcs_fabric_delete_comp, fabric); | ||
841 | bfa_wc_up(&fabric->wc); /* For the base port */ | ||
842 | |||
843 | bfa_sm_set_state(fabric, bfa_fcs_fabric_sm_uninit); | ||
844 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_CREATE); | ||
845 | bfa_trc(fcs, 0); | ||
846 | } | ||
847 | |||
848 | /** | ||
849 | * Module cleanup | ||
850 | */ | ||
851 | void | ||
852 | bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs) | ||
853 | { | ||
854 | struct bfa_fcs_fabric_s *fabric; | ||
855 | |||
856 | bfa_trc(fcs, 0); | ||
857 | |||
858 | /** | ||
859 | * Cleanup base fabric. | ||
860 | */ | ||
861 | fabric = &fcs->fabric; | ||
862 | bfa_lps_delete(fabric->lps); | ||
863 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_DELETE); | ||
864 | } | ||
865 | |||
866 | /** | ||
867 | * Fabric module start -- kick starts FCS actions | ||
868 | */ | ||
869 | void | ||
870 | bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs) | ||
871 | { | ||
872 | struct bfa_fcs_fabric_s *fabric; | ||
873 | |||
874 | bfa_trc(fcs, 0); | ||
875 | fabric = &fcs->fabric; | ||
876 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_START); | ||
877 | } | ||
878 | |||
879 | /** | ||
880 | * Suspend fabric activity as part of driver suspend. | ||
881 | */ | ||
882 | void | ||
883 | bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs) | ||
884 | { | ||
885 | } | ||
886 | |||
887 | bfa_boolean_t | ||
888 | bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric) | ||
889 | { | ||
890 | return (bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_loopback)); | ||
891 | } | ||
892 | |||
893 | enum bfa_pport_type | ||
894 | bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric) | ||
895 | { | ||
896 | return fabric->oper_type; | ||
897 | } | ||
898 | |||
899 | /** | ||
900 | * Link up notification from BFA physical port module. | ||
901 | */ | ||
902 | void | ||
903 | bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric) | ||
904 | { | ||
905 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
906 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_UP); | ||
907 | } | ||
908 | |||
909 | /** | ||
910 | * Link down notification from BFA physical port module. | ||
911 | */ | ||
912 | void | ||
913 | bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric) | ||
914 | { | ||
915 | bfa_trc(fabric->fcs, fabric->bport.port_cfg.pwwn); | ||
916 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LINK_DOWN); | ||
917 | } | ||
918 | |||
919 | /** | ||
920 | * A child vport is being created in the fabric. | ||
921 | * | ||
922 | * Call from vport module at vport creation. A list of base port and vports | ||
923 | * belonging to a fabric is maintained to propagate link events. | ||
924 | * | ||
925 | * param[in] fabric - Fabric instance. This can be a base fabric or vf. | ||
926 | * param[in] vport - Vport being created. | ||
927 | * | ||
928 | * @return None (always succeeds) | ||
929 | */ | ||
930 | void | ||
931 | bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, | ||
932 | struct bfa_fcs_vport_s *vport) | ||
933 | { | ||
934 | /** | ||
935 | * - add vport to fabric's vport_q | ||
936 | */ | ||
937 | bfa_trc(fabric->fcs, fabric->vf_id); | ||
938 | |||
939 | list_add_tail(&vport->qe, &fabric->vport_q); | ||
940 | fabric->num_vports++; | ||
941 | bfa_wc_up(&fabric->wc); | ||
942 | } | ||
943 | |||
944 | /** | ||
945 | * A child vport is being deleted from fabric. | ||
946 | * | ||
947 | * Vport is being deleted. | ||
948 | */ | ||
949 | void | ||
950 | bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric, | ||
951 | struct bfa_fcs_vport_s *vport) | ||
952 | { | ||
953 | list_del(&vport->qe); | ||
954 | fabric->num_vports--; | ||
955 | bfa_wc_down(&fabric->wc); | ||
956 | } | ||
957 | |||
958 | /** | ||
959 | * Base port is deleted. | ||
960 | */ | ||
961 | void | ||
962 | bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric) | ||
963 | { | ||
964 | bfa_wc_down(&fabric->wc); | ||
965 | } | ||
966 | |||
967 | /** | ||
968 | * Check if fabric is online. | ||
969 | * | ||
970 | * param[in] fabric - Fabric instance. This can be a base fabric or vf. | ||
971 | * | ||
972 | * @return TRUE/FALSE | ||
973 | */ | ||
974 | int | ||
975 | bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric) | ||
976 | { | ||
977 | return (bfa_sm_cmp_state(fabric, bfa_fcs_fabric_sm_online)); | ||
978 | } | ||
979 | |||
980 | |||
981 | bfa_status_t | ||
982 | bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, struct bfa_fcs_s *fcs, | ||
983 | struct bfa_port_cfg_s *port_cfg, | ||
984 | struct bfad_vf_s *vf_drv) | ||
985 | { | ||
986 | bfa_sm_set_state(vf, bfa_fcs_fabric_sm_uninit); | ||
987 | return BFA_STATUS_OK; | ||
988 | } | ||
989 | |||
990 | /** | ||
991 | * Lookup for a vport withing a fabric given its pwwn | ||
992 | */ | ||
993 | struct bfa_fcs_vport_s * | ||
994 | bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn) | ||
995 | { | ||
996 | struct bfa_fcs_vport_s *vport; | ||
997 | struct list_head *qe; | ||
998 | |||
999 | list_for_each(qe, &fabric->vport_q) { | ||
1000 | vport = (struct bfa_fcs_vport_s *)qe; | ||
1001 | if (bfa_fcs_port_get_pwwn(&vport->lport) == pwwn) | ||
1002 | return vport; | ||
1003 | } | ||
1004 | |||
1005 | return NULL; | ||
1006 | } | ||
1007 | |||
1008 | /** | ||
1009 | * In a given fabric, return the number of lports. | ||
1010 | * | ||
1011 | * param[in] fabric - Fabric instance. This can be a base fabric or vf. | ||
1012 | * | ||
1013 | * @return : 1 or more. | ||
1014 | */ | ||
1015 | u16 | ||
1016 | bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric) | ||
1017 | { | ||
1018 | return (fabric->num_vports); | ||
1019 | } | ||
1020 | |||
1021 | /** | ||
1022 | * Unsolicited frame receive handling. | ||
1023 | */ | ||
1024 | void | ||
1025 | bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, | ||
1026 | u16 len) | ||
1027 | { | ||
1028 | u32 pid = fchs->d_id; | ||
1029 | struct bfa_fcs_vport_s *vport; | ||
1030 | struct list_head *qe; | ||
1031 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
1032 | struct fc_logi_s *flogi = (struct fc_logi_s *) els_cmd; | ||
1033 | |||
1034 | bfa_trc(fabric->fcs, len); | ||
1035 | bfa_trc(fabric->fcs, pid); | ||
1036 | |||
1037 | /** | ||
1038 | * Look for our own FLOGI frames being looped back. This means an | ||
1039 | * external loopback cable is in place. Our own FLOGI frames are | ||
1040 | * sometimes looped back when switch port gets temporarily bypassed. | ||
1041 | */ | ||
1042 | if ((pid == bfa_os_ntoh3b(FC_FABRIC_PORT)) | ||
1043 | && (els_cmd->els_code == FC_ELS_FLOGI) | ||
1044 | && (flogi->port_name == bfa_fcs_port_get_pwwn(&fabric->bport))) { | ||
1045 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_LOOPBACK); | ||
1046 | return; | ||
1047 | } | ||
1048 | |||
1049 | /** | ||
1050 | * FLOGI/EVFP exchanges should be consumed by base fabric. | ||
1051 | */ | ||
1052 | if (fchs->d_id == bfa_os_hton3b(FC_FABRIC_PORT)) { | ||
1053 | bfa_trc(fabric->fcs, pid); | ||
1054 | bfa_fcs_fabric_process_uf(fabric, fchs, len); | ||
1055 | return; | ||
1056 | } | ||
1057 | |||
1058 | if (fabric->bport.pid == pid) { | ||
1059 | /** | ||
1060 | * All authentication frames should be routed to auth | ||
1061 | */ | ||
1062 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1063 | if (els_cmd->els_code == FC_ELS_AUTH) { | ||
1064 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1065 | fabric->auth.response = (u8 *) els_cmd; | ||
1066 | return; | ||
1067 | } | ||
1068 | |||
1069 | bfa_trc(fabric->fcs, *(u8 *) ((u8 *) fchs)); | ||
1070 | bfa_fcs_port_uf_recv(&fabric->bport, fchs, len); | ||
1071 | return; | ||
1072 | } | ||
1073 | |||
1074 | /** | ||
1075 | * look for a matching local port ID | ||
1076 | */ | ||
1077 | list_for_each(qe, &fabric->vport_q) { | ||
1078 | vport = (struct bfa_fcs_vport_s *)qe; | ||
1079 | if (vport->lport.pid == pid) { | ||
1080 | bfa_fcs_port_uf_recv(&vport->lport, fchs, len); | ||
1081 | return; | ||
1082 | } | ||
1083 | } | ||
1084 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1085 | bfa_fcs_port_uf_recv(&fabric->bport, fchs, len); | ||
1086 | } | ||
1087 | |||
1088 | /** | ||
1089 | * Unsolicited frames to be processed by fabric. | ||
1090 | */ | ||
1091 | static void | ||
1092 | bfa_fcs_fabric_process_uf(struct bfa_fcs_fabric_s *fabric, struct fchs_s *fchs, | ||
1093 | u16 len) | ||
1094 | { | ||
1095 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
1096 | |||
1097 | bfa_trc(fabric->fcs, els_cmd->els_code); | ||
1098 | |||
1099 | switch (els_cmd->els_code) { | ||
1100 | case FC_ELS_FLOGI: | ||
1101 | bfa_fcs_fabric_process_flogi(fabric, fchs, len); | ||
1102 | break; | ||
1103 | |||
1104 | default: | ||
1105 | /* | ||
1106 | * need to generate a LS_RJT | ||
1107 | */ | ||
1108 | break; | ||
1109 | } | ||
1110 | } | ||
1111 | |||
1112 | /** | ||
1113 | * Process incoming FLOGI | ||
1114 | */ | ||
1115 | static void | ||
1116 | bfa_fcs_fabric_process_flogi(struct bfa_fcs_fabric_s *fabric, | ||
1117 | struct fchs_s *fchs, u16 len) | ||
1118 | { | ||
1119 | struct fc_logi_s *flogi = (struct fc_logi_s *) (fchs + 1); | ||
1120 | struct bfa_fcs_port_s *bport = &fabric->bport; | ||
1121 | |||
1122 | bfa_trc(fabric->fcs, fchs->s_id); | ||
1123 | |||
1124 | fabric->stats.flogi_rcvd++; | ||
1125 | /* | ||
1126 | * Check port type. It should be 0 = n-port. | ||
1127 | */ | ||
1128 | if (flogi->csp.port_type) { | ||
1129 | /* | ||
1130 | * @todo: may need to send a LS_RJT | ||
1131 | */ | ||
1132 | bfa_trc(fabric->fcs, flogi->port_name); | ||
1133 | fabric->stats.flogi_rejected++; | ||
1134 | return; | ||
1135 | } | ||
1136 | |||
1137 | fabric->bb_credit = bfa_os_ntohs(flogi->csp.bbcred); | ||
1138 | bport->port_topo.pn2n.rem_port_wwn = flogi->port_name; | ||
1139 | bport->port_topo.pn2n.reply_oxid = fchs->ox_id; | ||
1140 | |||
1141 | /* | ||
1142 | * Send a Flogi Acc | ||
1143 | */ | ||
1144 | bfa_fcs_fabric_send_flogi_acc(fabric); | ||
1145 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_NO_FABRIC); | ||
1146 | } | ||
1147 | |||
1148 | static void | ||
1149 | bfa_fcs_fabric_send_flogi_acc(struct bfa_fcs_fabric_s *fabric) | ||
1150 | { | ||
1151 | struct bfa_port_cfg_s *pcfg = &fabric->bport.port_cfg; | ||
1152 | struct bfa_fcs_port_n2n_s *n2n_port = &fabric->bport.port_topo.pn2n; | ||
1153 | struct bfa_s *bfa = fabric->fcs->bfa; | ||
1154 | struct bfa_fcxp_s *fcxp; | ||
1155 | u16 reqlen; | ||
1156 | struct fchs_s fchs; | ||
1157 | |||
1158 | fcxp = bfa_fcs_fcxp_alloc(fabric->fcs); | ||
1159 | /** | ||
1160 | * Do not expect this failure -- expect remote node to retry | ||
1161 | */ | ||
1162 | if (!fcxp) | ||
1163 | return; | ||
1164 | |||
1165 | reqlen = fc_flogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
1166 | bfa_os_hton3b(FC_FABRIC_PORT), | ||
1167 | n2n_port->reply_oxid, pcfg->pwwn, | ||
1168 | pcfg->nwwn, bfa_pport_get_maxfrsize(bfa), | ||
1169 | bfa_pport_get_rx_bbcredit(bfa)); | ||
1170 | |||
1171 | bfa_fcxp_send(fcxp, NULL, fabric->vf_id, bfa_lps_get_tag(fabric->lps), | ||
1172 | BFA_FALSE, FC_CLASS_3, reqlen, &fchs, | ||
1173 | bfa_fcs_fabric_flogiacc_comp, fabric, | ||
1174 | FC_MAX_PDUSZ, 0); /* Timeout 0 indicates no | ||
1175 | * response expected | ||
1176 | */ | ||
1177 | } | ||
1178 | |||
1179 | /** | ||
1180 | * Flogi Acc completion callback. | ||
1181 | */ | ||
1182 | static void | ||
1183 | bfa_fcs_fabric_flogiacc_comp(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
1184 | bfa_status_t status, u32 rsp_len, | ||
1185 | u32 resid_len, struct fchs_s *rspfchs) | ||
1186 | { | ||
1187 | struct bfa_fcs_fabric_s *fabric = cbarg; | ||
1188 | |||
1189 | bfa_trc(fabric->fcs, status); | ||
1190 | } | ||
1191 | |||
1192 | /* | ||
1193 | * | ||
1194 | * @param[in] fabric - fabric | ||
1195 | * @param[in] result - 1 | ||
1196 | * | ||
1197 | * @return - none | ||
1198 | */ | ||
1199 | void | ||
1200 | bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, enum auth_status status) | ||
1201 | { | ||
1202 | bfa_trc(fabric->fcs, status); | ||
1203 | |||
1204 | if (status == FC_AUTH_STATE_SUCCESS) | ||
1205 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_SUCCESS); | ||
1206 | else | ||
1207 | bfa_sm_send_event(fabric, BFA_FCS_FABRIC_SM_AUTH_FAILED); | ||
1208 | } | ||
1209 | |||
1210 | /** | ||
1211 | * Send AEN notification | ||
1212 | */ | ||
1213 | static void | ||
1214 | bfa_fcs_fabric_aen_post(struct bfa_fcs_port_s *port, | ||
1215 | enum bfa_port_aen_event event) | ||
1216 | { | ||
1217 | union bfa_aen_data_u aen_data; | ||
1218 | struct bfa_log_mod_s *logmod = port->fcs->logm; | ||
1219 | wwn_t pwwn = bfa_fcs_port_get_pwwn(port); | ||
1220 | wwn_t fwwn = bfa_fcs_port_get_fabric_name(port); | ||
1221 | char pwwn_ptr[BFA_STRING_32]; | ||
1222 | char fwwn_ptr[BFA_STRING_32]; | ||
1223 | |||
1224 | wwn2str(pwwn_ptr, pwwn); | ||
1225 | wwn2str(fwwn_ptr, fwwn); | ||
1226 | |||
1227 | switch (event) { | ||
1228 | case BFA_PORT_AEN_FABRIC_NAME_CHANGE: | ||
1229 | bfa_log(logmod, BFA_AEN_PORT_FABRIC_NAME_CHANGE, pwwn_ptr, | ||
1230 | fwwn_ptr); | ||
1231 | break; | ||
1232 | default: | ||
1233 | break; | ||
1234 | } | ||
1235 | |||
1236 | aen_data.port.pwwn = pwwn; | ||
1237 | aen_data.port.fwwn = fwwn; | ||
1238 | } | ||
1239 | |||
1240 | /* | ||
1241 | * | ||
1242 | * @param[in] fabric - fabric | ||
1243 | * @param[in] wwn_t - new fabric name | ||
1244 | * | ||
1245 | * @return - none | ||
1246 | */ | ||
1247 | void | ||
1248 | bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, | ||
1249 | wwn_t fabric_name) | ||
1250 | { | ||
1251 | bfa_trc(fabric->fcs, fabric_name); | ||
1252 | |||
1253 | if (fabric->fabric_name == 0) { | ||
1254 | /* | ||
1255 | * With BRCD switches, we don't get Fabric Name in FLOGI. | ||
1256 | * Don't generate a fabric name change event in this case. | ||
1257 | */ | ||
1258 | fabric->fabric_name = fabric_name; | ||
1259 | } else { | ||
1260 | fabric->fabric_name = fabric_name; | ||
1261 | /* | ||
1262 | * Generate a Event | ||
1263 | */ | ||
1264 | bfa_fcs_fabric_aen_post(&fabric->bport, | ||
1265 | BFA_PORT_AEN_FABRIC_NAME_CHANGE); | ||
1266 | } | ||
1267 | |||
1268 | } | ||
1269 | |||
1270 | /** | ||
1271 | * Not used by FCS. | ||
1272 | */ | ||
1273 | void | ||
1274 | bfa_cb_lps_flogo_comp(void *bfad, void *uarg) | ||
1275 | { | ||
1276 | } | ||
1277 | |||
1278 | |||
diff --git a/drivers/scsi/bfa/fcbuild.c b/drivers/scsi/bfa/fcbuild.c new file mode 100644 index 000000000000..d174706b9caa --- /dev/null +++ b/drivers/scsi/bfa/fcbuild.c | |||
@@ -0,0 +1,1449 @@ | |||
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 | * fcbuild.c - FC link service frame building and parsing routines | ||
19 | */ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include "fcbuild.h" | ||
23 | |||
24 | /* | ||
25 | * static build functions | ||
26 | */ | ||
27 | static void fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
28 | u16 ox_id); | ||
29 | static void fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
30 | u16 ox_id); | ||
31 | static struct fchs_s fc_els_req_tmpl; | ||
32 | static struct fchs_s fc_els_rsp_tmpl; | ||
33 | static struct fchs_s fc_bls_req_tmpl; | ||
34 | static struct fchs_s fc_bls_rsp_tmpl; | ||
35 | static struct fc_ba_acc_s ba_acc_tmpl; | ||
36 | static struct fc_logi_s plogi_tmpl; | ||
37 | static struct fc_prli_s prli_tmpl; | ||
38 | static struct fc_rrq_s rrq_tmpl; | ||
39 | static struct fchs_s fcp_fchs_tmpl; | ||
40 | |||
41 | void | ||
42 | fcbuild_init(void) | ||
43 | { | ||
44 | /* | ||
45 | * fc_els_req_tmpl | ||
46 | */ | ||
47 | fc_els_req_tmpl.routing = FC_RTG_EXT_LINK; | ||
48 | fc_els_req_tmpl.cat_info = FC_CAT_LD_REQUEST; | ||
49 | fc_els_req_tmpl.type = FC_TYPE_ELS; | ||
50 | fc_els_req_tmpl.f_ctl = | ||
51 | bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | | ||
52 | FCTL_SI_XFER); | ||
53 | fc_els_req_tmpl.rx_id = FC_RXID_ANY; | ||
54 | |||
55 | /* | ||
56 | * fc_els_rsp_tmpl | ||
57 | */ | ||
58 | fc_els_rsp_tmpl.routing = FC_RTG_EXT_LINK; | ||
59 | fc_els_rsp_tmpl.cat_info = FC_CAT_LD_REPLY; | ||
60 | fc_els_rsp_tmpl.type = FC_TYPE_ELS; | ||
61 | fc_els_rsp_tmpl.f_ctl = | ||
62 | bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | | ||
63 | FCTL_END_SEQ | FCTL_SI_XFER); | ||
64 | fc_els_rsp_tmpl.rx_id = FC_RXID_ANY; | ||
65 | |||
66 | /* | ||
67 | * fc_bls_req_tmpl | ||
68 | */ | ||
69 | fc_bls_req_tmpl.routing = FC_RTG_BASIC_LINK; | ||
70 | fc_bls_req_tmpl.type = FC_TYPE_BLS; | ||
71 | fc_bls_req_tmpl.f_ctl = bfa_os_hton3b(FCTL_END_SEQ | FCTL_SI_XFER); | ||
72 | fc_bls_req_tmpl.rx_id = FC_RXID_ANY; | ||
73 | |||
74 | /* | ||
75 | * fc_bls_rsp_tmpl | ||
76 | */ | ||
77 | fc_bls_rsp_tmpl.routing = FC_RTG_BASIC_LINK; | ||
78 | fc_bls_rsp_tmpl.cat_info = FC_CAT_BA_ACC; | ||
79 | fc_bls_rsp_tmpl.type = FC_TYPE_BLS; | ||
80 | fc_bls_rsp_tmpl.f_ctl = | ||
81 | bfa_os_hton3b(FCTL_EC_RESP | FCTL_SEQ_INI | FCTL_LS_EXCH | | ||
82 | FCTL_END_SEQ | FCTL_SI_XFER); | ||
83 | fc_bls_rsp_tmpl.rx_id = FC_RXID_ANY; | ||
84 | |||
85 | /* | ||
86 | * ba_acc_tmpl | ||
87 | */ | ||
88 | ba_acc_tmpl.seq_id_valid = 0; | ||
89 | ba_acc_tmpl.low_seq_cnt = 0; | ||
90 | ba_acc_tmpl.high_seq_cnt = 0xFFFF; | ||
91 | |||
92 | /* | ||
93 | * plogi_tmpl | ||
94 | */ | ||
95 | plogi_tmpl.csp.verhi = FC_PH_VER_PH_3; | ||
96 | plogi_tmpl.csp.verlo = FC_PH_VER_4_3; | ||
97 | plogi_tmpl.csp.bbcred = bfa_os_htons(0x0004); | ||
98 | plogi_tmpl.csp.ciro = 0x1; | ||
99 | plogi_tmpl.csp.cisc = 0x0; | ||
100 | plogi_tmpl.csp.altbbcred = 0x0; | ||
101 | plogi_tmpl.csp.conseq = bfa_os_htons(0x00FF); | ||
102 | plogi_tmpl.csp.ro_bitmap = bfa_os_htons(0x0002); | ||
103 | plogi_tmpl.csp.e_d_tov = bfa_os_htonl(2000); | ||
104 | |||
105 | plogi_tmpl.class3.class_valid = 1; | ||
106 | plogi_tmpl.class3.sequential = 1; | ||
107 | plogi_tmpl.class3.conseq = 0xFF; | ||
108 | plogi_tmpl.class3.ospx = 1; | ||
109 | |||
110 | /* | ||
111 | * prli_tmpl | ||
112 | */ | ||
113 | prli_tmpl.command = FC_ELS_PRLI; | ||
114 | prli_tmpl.pglen = 0x10; | ||
115 | prli_tmpl.pagebytes = bfa_os_htons(0x0014); | ||
116 | prli_tmpl.parampage.type = FC_TYPE_FCP; | ||
117 | prli_tmpl.parampage.imagepair = 1; | ||
118 | prli_tmpl.parampage.servparams.rxrdisab = 1; | ||
119 | |||
120 | /* | ||
121 | * rrq_tmpl | ||
122 | */ | ||
123 | rrq_tmpl.els_cmd.els_code = FC_ELS_RRQ; | ||
124 | |||
125 | /* | ||
126 | * fcp_fchs_tmpl | ||
127 | */ | ||
128 | fcp_fchs_tmpl.routing = FC_RTG_FC4_DEV_DATA; | ||
129 | fcp_fchs_tmpl.cat_info = FC_CAT_UNSOLICIT_CMD; | ||
130 | fcp_fchs_tmpl.type = FC_TYPE_FCP; | ||
131 | fcp_fchs_tmpl.f_ctl = | ||
132 | bfa_os_hton3b(FCTL_FS_EXCH | FCTL_END_SEQ | FCTL_SI_XFER); | ||
133 | fcp_fchs_tmpl.seq_id = 1; | ||
134 | fcp_fchs_tmpl.rx_id = FC_RXID_ANY; | ||
135 | } | ||
136 | |||
137 | static void | ||
138 | fc_gs_fchdr_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
139 | u32 ox_id) | ||
140 | { | ||
141 | bfa_os_memset(fchs, 0, sizeof(struct fchs_s)); | ||
142 | |||
143 | fchs->routing = FC_RTG_FC4_DEV_DATA; | ||
144 | fchs->cat_info = FC_CAT_UNSOLICIT_CTRL; | ||
145 | fchs->type = FC_TYPE_SERVICES; | ||
146 | fchs->f_ctl = | ||
147 | bfa_os_hton3b(FCTL_SEQ_INI | FCTL_FS_EXCH | FCTL_END_SEQ | | ||
148 | FCTL_SI_XFER); | ||
149 | fchs->rx_id = FC_RXID_ANY; | ||
150 | fchs->d_id = (d_id); | ||
151 | fchs->s_id = (s_id); | ||
152 | fchs->ox_id = bfa_os_htons(ox_id); | ||
153 | |||
154 | /** | ||
155 | * @todo no need to set ox_id for request | ||
156 | * no need to set rx_id for response | ||
157 | */ | ||
158 | } | ||
159 | |||
160 | void | ||
161 | fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
162 | u16 ox_id) | ||
163 | { | ||
164 | bfa_os_memcpy(fchs, &fc_els_req_tmpl, sizeof(struct fchs_s)); | ||
165 | fchs->d_id = (d_id); | ||
166 | fchs->s_id = (s_id); | ||
167 | fchs->ox_id = bfa_os_htons(ox_id); | ||
168 | } | ||
169 | |||
170 | static void | ||
171 | fc_els_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
172 | u16 ox_id) | ||
173 | { | ||
174 | bfa_os_memcpy(fchs, &fc_els_rsp_tmpl, sizeof(struct fchs_s)); | ||
175 | fchs->d_id = d_id; | ||
176 | fchs->s_id = s_id; | ||
177 | fchs->ox_id = ox_id; | ||
178 | } | ||
179 | |||
180 | enum fc_parse_status | ||
181 | fc_els_rsp_parse(struct fchs_s *fchs, int len) | ||
182 | { | ||
183 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
184 | struct fc_ls_rjt_s *ls_rjt = (struct fc_ls_rjt_s *) els_cmd; | ||
185 | |||
186 | len = len; | ||
187 | |||
188 | switch (els_cmd->els_code) { | ||
189 | case FC_ELS_LS_RJT: | ||
190 | if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY) | ||
191 | return (FC_PARSE_BUSY); | ||
192 | else | ||
193 | return (FC_PARSE_FAILURE); | ||
194 | |||
195 | case FC_ELS_ACC: | ||
196 | return (FC_PARSE_OK); | ||
197 | } | ||
198 | return (FC_PARSE_OK); | ||
199 | } | ||
200 | |||
201 | static void | ||
202 | fc_bls_rsp_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
203 | u16 ox_id) | ||
204 | { | ||
205 | bfa_os_memcpy(fchs, &fc_bls_rsp_tmpl, sizeof(struct fchs_s)); | ||
206 | fchs->d_id = d_id; | ||
207 | fchs->s_id = s_id; | ||
208 | fchs->ox_id = ox_id; | ||
209 | } | ||
210 | |||
211 | static u16 | ||
212 | fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
213 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
214 | u16 pdu_size, u8 els_code) | ||
215 | { | ||
216 | struct fc_logi_s *plogi = (struct fc_logi_s *) (pld); | ||
217 | |||
218 | bfa_os_memcpy(plogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
219 | |||
220 | plogi->els_cmd.els_code = els_code; | ||
221 | if (els_code == FC_ELS_PLOGI) | ||
222 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
223 | else | ||
224 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
225 | |||
226 | plogi->csp.rxsz = plogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
227 | |||
228 | bfa_os_memcpy(&plogi->port_name, &port_name, sizeof(wwn_t)); | ||
229 | bfa_os_memcpy(&plogi->node_name, &node_name, sizeof(wwn_t)); | ||
230 | |||
231 | return (sizeof(struct fc_logi_s)); | ||
232 | } | ||
233 | |||
234 | u16 | ||
235 | fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, | ||
236 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
237 | u16 pdu_size, u8 set_npiv, u8 set_auth, | ||
238 | u16 local_bb_credits) | ||
239 | { | ||
240 | u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT); | ||
241 | u32 *vvl_info; | ||
242 | |||
243 | bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
244 | |||
245 | flogi->els_cmd.els_code = FC_ELS_FLOGI; | ||
246 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
247 | |||
248 | flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
249 | flogi->port_name = port_name; | ||
250 | flogi->node_name = node_name; | ||
251 | |||
252 | /* | ||
253 | * Set the NPIV Capability Bit ( word 1, bit 31) of Common | ||
254 | * Service Parameters. | ||
255 | */ | ||
256 | flogi->csp.ciro = set_npiv; | ||
257 | |||
258 | /* set AUTH capability */ | ||
259 | flogi->csp.security = set_auth; | ||
260 | |||
261 | flogi->csp.bbcred = bfa_os_htons(local_bb_credits); | ||
262 | |||
263 | /* Set brcd token in VVL */ | ||
264 | vvl_info = (u32 *)&flogi->vvl[0]; | ||
265 | |||
266 | /* set the flag to indicate the presence of VVL */ | ||
267 | flogi->csp.npiv_supp = 1; /* @todo. field name is not correct */ | ||
268 | vvl_info[0] = bfa_os_htonl(FLOGI_VVL_BRCD); | ||
269 | |||
270 | return (sizeof(struct fc_logi_s)); | ||
271 | } | ||
272 | |||
273 | u16 | ||
274 | fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, | ||
275 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
276 | u16 pdu_size, u16 local_bb_credits) | ||
277 | { | ||
278 | u32 d_id = 0; | ||
279 | |||
280 | bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
281 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
282 | |||
283 | flogi->els_cmd.els_code = FC_ELS_ACC; | ||
284 | flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
285 | flogi->port_name = port_name; | ||
286 | flogi->node_name = node_name; | ||
287 | |||
288 | flogi->csp.bbcred = bfa_os_htons(local_bb_credits); | ||
289 | |||
290 | return (sizeof(struct fc_logi_s)); | ||
291 | } | ||
292 | |||
293 | u16 | ||
294 | fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id, | ||
295 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
296 | u16 pdu_size) | ||
297 | { | ||
298 | u32 d_id = bfa_os_hton3b(FC_FABRIC_PORT); | ||
299 | |||
300 | bfa_os_memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
301 | |||
302 | flogi->els_cmd.els_code = FC_ELS_FDISC; | ||
303 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
304 | |||
305 | flogi->csp.rxsz = flogi->class3.rxsz = bfa_os_htons(pdu_size); | ||
306 | flogi->port_name = port_name; | ||
307 | flogi->node_name = node_name; | ||
308 | |||
309 | return (sizeof(struct fc_logi_s)); | ||
310 | } | ||
311 | |||
312 | u16 | ||
313 | fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
314 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
315 | u16 pdu_size) | ||
316 | { | ||
317 | return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, | ||
318 | node_name, pdu_size, FC_ELS_PLOGI); | ||
319 | } | ||
320 | |||
321 | u16 | ||
322 | fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
323 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
324 | u16 pdu_size) | ||
325 | { | ||
326 | return fc_plogi_x_build(fchs, pld, d_id, s_id, ox_id, port_name, | ||
327 | node_name, pdu_size, FC_ELS_ACC); | ||
328 | } | ||
329 | |||
330 | enum fc_parse_status | ||
331 | fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name) | ||
332 | { | ||
333 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
334 | struct fc_logi_s *plogi; | ||
335 | struct fc_ls_rjt_s *ls_rjt; | ||
336 | |||
337 | switch (els_cmd->els_code) { | ||
338 | case FC_ELS_LS_RJT: | ||
339 | ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1); | ||
340 | if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY) | ||
341 | return (FC_PARSE_BUSY); | ||
342 | else | ||
343 | return (FC_PARSE_FAILURE); | ||
344 | case FC_ELS_ACC: | ||
345 | plogi = (struct fc_logi_s *) (fchs + 1); | ||
346 | if (len < sizeof(struct fc_logi_s)) | ||
347 | return (FC_PARSE_FAILURE); | ||
348 | |||
349 | if (!wwn_is_equal(plogi->port_name, port_name)) | ||
350 | return (FC_PARSE_FAILURE); | ||
351 | |||
352 | if (!plogi->class3.class_valid) | ||
353 | return (FC_PARSE_FAILURE); | ||
354 | |||
355 | if (bfa_os_ntohs(plogi->class3.rxsz) < (FC_MIN_PDUSZ)) | ||
356 | return (FC_PARSE_FAILURE); | ||
357 | |||
358 | return (FC_PARSE_OK); | ||
359 | default: | ||
360 | return (FC_PARSE_FAILURE); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | enum fc_parse_status | ||
365 | fc_plogi_parse(struct fchs_s *fchs) | ||
366 | { | ||
367 | struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1); | ||
368 | |||
369 | if (plogi->class3.class_valid != 1) | ||
370 | return FC_PARSE_FAILURE; | ||
371 | |||
372 | if ((bfa_os_ntohs(plogi->class3.rxsz) < FC_MIN_PDUSZ) | ||
373 | || (bfa_os_ntohs(plogi->class3.rxsz) > FC_MAX_PDUSZ) | ||
374 | || (plogi->class3.rxsz == 0)) | ||
375 | return (FC_PARSE_FAILURE); | ||
376 | |||
377 | return FC_PARSE_OK; | ||
378 | } | ||
379 | |||
380 | u16 | ||
381 | fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
382 | u16 ox_id) | ||
383 | { | ||
384 | struct fc_prli_s *prli = (struct fc_prli_s *) (pld); | ||
385 | |||
386 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
387 | bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); | ||
388 | |||
389 | prli->command = FC_ELS_PRLI; | ||
390 | prli->parampage.servparams.initiator = 1; | ||
391 | prli->parampage.servparams.retry = 1; | ||
392 | prli->parampage.servparams.rec_support = 1; | ||
393 | prli->parampage.servparams.task_retry_id = 0; | ||
394 | prli->parampage.servparams.confirm = 1; | ||
395 | |||
396 | return (sizeof(struct fc_prli_s)); | ||
397 | } | ||
398 | |||
399 | u16 | ||
400 | fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
401 | u16 ox_id, enum bfa_port_role role) | ||
402 | { | ||
403 | struct fc_prli_s *prli = (struct fc_prli_s *) (pld); | ||
404 | |||
405 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
406 | bfa_os_memcpy(prli, &prli_tmpl, sizeof(struct fc_prli_s)); | ||
407 | |||
408 | prli->command = FC_ELS_ACC; | ||
409 | |||
410 | if ((role & BFA_PORT_ROLE_FCP_TM) == BFA_PORT_ROLE_FCP_TM) | ||
411 | prli->parampage.servparams.target = 1; | ||
412 | else | ||
413 | prli->parampage.servparams.initiator = 1; | ||
414 | |||
415 | prli->parampage.rspcode = FC_PRLI_ACC_XQTD; | ||
416 | |||
417 | return (sizeof(struct fc_prli_s)); | ||
418 | } | ||
419 | |||
420 | enum fc_parse_status | ||
421 | fc_prli_rsp_parse(struct fc_prli_s *prli, int len) | ||
422 | { | ||
423 | if (len < sizeof(struct fc_prli_s)) | ||
424 | return (FC_PARSE_FAILURE); | ||
425 | |||
426 | if (prli->command != FC_ELS_ACC) | ||
427 | return (FC_PARSE_FAILURE); | ||
428 | |||
429 | if ((prli->parampage.rspcode != FC_PRLI_ACC_XQTD) | ||
430 | && (prli->parampage.rspcode != FC_PRLI_ACC_PREDEF_IMG)) | ||
431 | return (FC_PARSE_FAILURE); | ||
432 | |||
433 | if (prli->parampage.servparams.target != 1) | ||
434 | return (FC_PARSE_FAILURE); | ||
435 | |||
436 | return (FC_PARSE_OK); | ||
437 | } | ||
438 | |||
439 | enum fc_parse_status | ||
440 | fc_prli_parse(struct fc_prli_s *prli) | ||
441 | { | ||
442 | if (prli->parampage.type != FC_TYPE_FCP) | ||
443 | return (FC_PARSE_FAILURE); | ||
444 | |||
445 | if (!prli->parampage.imagepair) | ||
446 | return (FC_PARSE_FAILURE); | ||
447 | |||
448 | if (!prli->parampage.servparams.initiator) | ||
449 | return (FC_PARSE_FAILURE); | ||
450 | |||
451 | return (FC_PARSE_OK); | ||
452 | } | ||
453 | |||
454 | u16 | ||
455 | fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, | ||
456 | u32 s_id, u16 ox_id, wwn_t port_name) | ||
457 | { | ||
458 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
459 | |||
460 | memset(logo, '\0', sizeof(struct fc_logo_s)); | ||
461 | logo->els_cmd.els_code = FC_ELS_LOGO; | ||
462 | logo->nport_id = (s_id); | ||
463 | logo->orig_port_name = port_name; | ||
464 | |||
465 | return (sizeof(struct fc_logo_s)); | ||
466 | } | ||
467 | |||
468 | static u16 | ||
469 | fc_adisc_x_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, | ||
470 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
471 | wwn_t node_name, u8 els_code) | ||
472 | { | ||
473 | memset(adisc, '\0', sizeof(struct fc_adisc_s)); | ||
474 | |||
475 | adisc->els_cmd.els_code = els_code; | ||
476 | |||
477 | if (els_code == FC_ELS_ADISC) | ||
478 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
479 | else | ||
480 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
481 | |||
482 | adisc->orig_HA = 0; | ||
483 | adisc->orig_port_name = port_name; | ||
484 | adisc->orig_node_name = node_name; | ||
485 | adisc->nport_id = (s_id); | ||
486 | |||
487 | return (sizeof(struct fc_adisc_s)); | ||
488 | } | ||
489 | |||
490 | u16 | ||
491 | fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, | ||
492 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
493 | wwn_t node_name) | ||
494 | { | ||
495 | return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, | ||
496 | node_name, FC_ELS_ADISC); | ||
497 | } | ||
498 | |||
499 | u16 | ||
500 | fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, u32 d_id, | ||
501 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
502 | wwn_t node_name) | ||
503 | { | ||
504 | return fc_adisc_x_build(fchs, adisc, d_id, s_id, ox_id, port_name, | ||
505 | node_name, FC_ELS_ACC); | ||
506 | } | ||
507 | |||
508 | enum fc_parse_status | ||
509 | fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name, | ||
510 | wwn_t node_name) | ||
511 | { | ||
512 | |||
513 | if (len < sizeof(struct fc_adisc_s)) | ||
514 | return (FC_PARSE_FAILURE); | ||
515 | |||
516 | if (adisc->els_cmd.els_code != FC_ELS_ACC) | ||
517 | return (FC_PARSE_FAILURE); | ||
518 | |||
519 | if (!wwn_is_equal(adisc->orig_port_name, port_name)) | ||
520 | return (FC_PARSE_FAILURE); | ||
521 | |||
522 | return (FC_PARSE_OK); | ||
523 | } | ||
524 | |||
525 | enum fc_parse_status | ||
526 | fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, | ||
527 | wwn_t node_name, wwn_t port_name) | ||
528 | { | ||
529 | struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld; | ||
530 | |||
531 | if (adisc->els_cmd.els_code != FC_ELS_ACC) | ||
532 | return (FC_PARSE_FAILURE); | ||
533 | |||
534 | if ((adisc->nport_id == (host_dap)) | ||
535 | && wwn_is_equal(adisc->orig_port_name, port_name) | ||
536 | && wwn_is_equal(adisc->orig_node_name, node_name)) | ||
537 | return (FC_PARSE_OK); | ||
538 | |||
539 | return (FC_PARSE_FAILURE); | ||
540 | } | ||
541 | |||
542 | enum fc_parse_status | ||
543 | fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name) | ||
544 | { | ||
545 | struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); | ||
546 | |||
547 | if (pdisc->class3.class_valid != 1) | ||
548 | return FC_PARSE_FAILURE; | ||
549 | |||
550 | if ((bfa_os_ntohs(pdisc->class3.rxsz) < | ||
551 | (FC_MIN_PDUSZ - sizeof(struct fchs_s))) | ||
552 | || (pdisc->class3.rxsz == 0)) | ||
553 | return (FC_PARSE_FAILURE); | ||
554 | |||
555 | if (!wwn_is_equal(pdisc->port_name, port_name)) | ||
556 | return (FC_PARSE_FAILURE); | ||
557 | |||
558 | if (!wwn_is_equal(pdisc->node_name, node_name)) | ||
559 | return (FC_PARSE_FAILURE); | ||
560 | |||
561 | return FC_PARSE_OK; | ||
562 | } | ||
563 | |||
564 | u16 | ||
565 | fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id) | ||
566 | { | ||
567 | bfa_os_memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s)); | ||
568 | fchs->cat_info = FC_CAT_ABTS; | ||
569 | fchs->d_id = (d_id); | ||
570 | fchs->s_id = (s_id); | ||
571 | fchs->ox_id = bfa_os_htons(ox_id); | ||
572 | |||
573 | return (sizeof(struct fchs_s)); | ||
574 | } | ||
575 | |||
576 | enum fc_parse_status | ||
577 | fc_abts_rsp_parse(struct fchs_s *fchs, int len) | ||
578 | { | ||
579 | if ((fchs->cat_info == FC_CAT_BA_ACC) | ||
580 | || (fchs->cat_info == FC_CAT_BA_RJT)) | ||
581 | return (FC_PARSE_OK); | ||
582 | |||
583 | return (FC_PARSE_FAILURE); | ||
584 | } | ||
585 | |||
586 | u16 | ||
587 | fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, | ||
588 | u32 s_id, u16 ox_id, u16 rrq_oxid) | ||
589 | { | ||
590 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
591 | |||
592 | /* | ||
593 | * build rrq payload | ||
594 | */ | ||
595 | bfa_os_memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s)); | ||
596 | rrq->s_id = (s_id); | ||
597 | rrq->ox_id = bfa_os_htons(rrq_oxid); | ||
598 | rrq->rx_id = FC_RXID_ANY; | ||
599 | |||
600 | return (sizeof(struct fc_rrq_s)); | ||
601 | } | ||
602 | |||
603 | u16 | ||
604 | fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id, | ||
605 | u16 ox_id) | ||
606 | { | ||
607 | struct fc_els_cmd_s *acc = pld; | ||
608 | |||
609 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
610 | |||
611 | memset(acc, 0, sizeof(struct fc_els_cmd_s)); | ||
612 | acc->els_code = FC_ELS_ACC; | ||
613 | |||
614 | return (sizeof(struct fc_els_cmd_s)); | ||
615 | } | ||
616 | |||
617 | u16 | ||
618 | fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, u32 d_id, | ||
619 | u32 s_id, u16 ox_id, u8 reason_code, | ||
620 | u8 reason_code_expl) | ||
621 | { | ||
622 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
623 | memset(ls_rjt, 0, sizeof(struct fc_ls_rjt_s)); | ||
624 | |||
625 | ls_rjt->els_cmd.els_code = FC_ELS_LS_RJT; | ||
626 | ls_rjt->reason_code = reason_code; | ||
627 | ls_rjt->reason_code_expl = reason_code_expl; | ||
628 | ls_rjt->vendor_unique = 0x00; | ||
629 | |||
630 | return (sizeof(struct fc_ls_rjt_s)); | ||
631 | } | ||
632 | |||
633 | u16 | ||
634 | fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id, | ||
635 | u32 s_id, u16 ox_id, u16 rx_id) | ||
636 | { | ||
637 | fc_bls_rsp_build(fchs, d_id, s_id, ox_id); | ||
638 | |||
639 | bfa_os_memcpy(ba_acc, &ba_acc_tmpl, sizeof(struct fc_ba_acc_s)); | ||
640 | |||
641 | fchs->rx_id = rx_id; | ||
642 | |||
643 | ba_acc->ox_id = fchs->ox_id; | ||
644 | ba_acc->rx_id = fchs->rx_id; | ||
645 | |||
646 | return (sizeof(struct fc_ba_acc_s)); | ||
647 | } | ||
648 | |||
649 | u16 | ||
650 | fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, | ||
651 | u32 d_id, u32 s_id, u16 ox_id) | ||
652 | { | ||
653 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
654 | memset(els_cmd, 0, sizeof(struct fc_els_cmd_s)); | ||
655 | els_cmd->els_code = FC_ELS_ACC; | ||
656 | |||
657 | return (sizeof(struct fc_els_cmd_s)); | ||
658 | } | ||
659 | |||
660 | int | ||
661 | fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code) | ||
662 | { | ||
663 | int num_pages = 0; | ||
664 | struct fc_prlo_s *prlo; | ||
665 | struct fc_tprlo_s *tprlo; | ||
666 | |||
667 | if (els_code == FC_ELS_PRLO) { | ||
668 | prlo = (struct fc_prlo_s *) (fc_frame + 1); | ||
669 | num_pages = (bfa_os_ntohs(prlo->payload_len) - 4) / 16; | ||
670 | } else { | ||
671 | tprlo = (struct fc_tprlo_s *) (fc_frame + 1); | ||
672 | num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16; | ||
673 | } | ||
674 | return num_pages; | ||
675 | } | ||
676 | |||
677 | u16 | ||
678 | fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc, | ||
679 | u32 d_id, u32 s_id, u16 ox_id, | ||
680 | int num_pages) | ||
681 | { | ||
682 | int page; | ||
683 | |||
684 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
685 | |||
686 | memset(tprlo_acc, 0, (num_pages * 16) + 4); | ||
687 | tprlo_acc->command = FC_ELS_ACC; | ||
688 | |||
689 | tprlo_acc->page_len = 0x10; | ||
690 | tprlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
691 | |||
692 | for (page = 0; page < num_pages; page++) { | ||
693 | tprlo_acc->tprlo_acc_params[page].opa_valid = 0; | ||
694 | tprlo_acc->tprlo_acc_params[page].rpa_valid = 0; | ||
695 | tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP; | ||
696 | tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0; | ||
697 | tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0; | ||
698 | } | ||
699 | return (bfa_os_ntohs(tprlo_acc->payload_len)); | ||
700 | } | ||
701 | |||
702 | u16 | ||
703 | fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, | ||
704 | u32 d_id, u32 s_id, u16 ox_id, | ||
705 | int num_pages) | ||
706 | { | ||
707 | int page; | ||
708 | |||
709 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
710 | |||
711 | memset(prlo_acc, 0, (num_pages * 16) + 4); | ||
712 | prlo_acc->command = FC_ELS_ACC; | ||
713 | prlo_acc->page_len = 0x10; | ||
714 | prlo_acc->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
715 | |||
716 | for (page = 0; page < num_pages; page++) { | ||
717 | prlo_acc->prlo_acc_params[page].opa_valid = 0; | ||
718 | prlo_acc->prlo_acc_params[page].rpa_valid = 0; | ||
719 | prlo_acc->prlo_acc_params[page].fc4type_csp = FC_TYPE_FCP; | ||
720 | prlo_acc->prlo_acc_params[page].orig_process_assc = 0; | ||
721 | prlo_acc->prlo_acc_params[page].resp_process_assc = 0; | ||
722 | } | ||
723 | |||
724 | return (bfa_os_ntohs(prlo_acc->payload_len)); | ||
725 | } | ||
726 | |||
727 | u16 | ||
728 | fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id, | ||
729 | u32 s_id, u16 ox_id, u32 data_format) | ||
730 | { | ||
731 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
732 | |||
733 | memset(rnid, 0, sizeof(struct fc_rnid_cmd_s)); | ||
734 | |||
735 | rnid->els_cmd.els_code = FC_ELS_RNID; | ||
736 | rnid->node_id_data_format = data_format; | ||
737 | |||
738 | return (sizeof(struct fc_rnid_cmd_s)); | ||
739 | } | ||
740 | |||
741 | u16 | ||
742 | fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, | ||
743 | u32 d_id, u32 s_id, u16 ox_id, | ||
744 | u32 data_format, | ||
745 | struct fc_rnid_common_id_data_s *common_id_data, | ||
746 | struct fc_rnid_general_topology_data_s *gen_topo_data) | ||
747 | { | ||
748 | memset(rnid_acc, 0, sizeof(struct fc_rnid_acc_s)); | ||
749 | |||
750 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
751 | |||
752 | rnid_acc->els_cmd.els_code = FC_ELS_ACC; | ||
753 | rnid_acc->node_id_data_format = data_format; | ||
754 | rnid_acc->common_id_data_length = | ||
755 | sizeof(struct fc_rnid_common_id_data_s); | ||
756 | rnid_acc->common_id_data = *common_id_data; | ||
757 | |||
758 | if (data_format == RNID_NODEID_DATA_FORMAT_DISCOVERY) { | ||
759 | rnid_acc->specific_id_data_length = | ||
760 | sizeof(struct fc_rnid_general_topology_data_s); | ||
761 | bfa_os_assign(rnid_acc->gen_topology_data, *gen_topo_data); | ||
762 | return (sizeof(struct fc_rnid_acc_s)); | ||
763 | } else { | ||
764 | return (sizeof(struct fc_rnid_acc_s) - | ||
765 | sizeof(struct fc_rnid_general_topology_data_s)); | ||
766 | } | ||
767 | |||
768 | } | ||
769 | |||
770 | u16 | ||
771 | fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id, | ||
772 | u32 s_id, u16 ox_id) | ||
773 | { | ||
774 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
775 | |||
776 | memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s)); | ||
777 | |||
778 | rpsc->els_cmd.els_code = FC_ELS_RPSC; | ||
779 | return (sizeof(struct fc_rpsc_cmd_s)); | ||
780 | } | ||
781 | |||
782 | u16 | ||
783 | fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, | ||
784 | u32 d_id, u32 s_id, u32 *pid_list, | ||
785 | u16 npids) | ||
786 | { | ||
787 | u32 dctlr_id = FC_DOMAIN_CTRLR(bfa_os_hton3b(d_id)); | ||
788 | int i = 0; | ||
789 | |||
790 | fc_els_req_build(fchs, bfa_os_hton3b(dctlr_id), s_id, 0); | ||
791 | |||
792 | memset(rpsc2, 0, sizeof(struct fc_rpsc2_cmd_s)); | ||
793 | |||
794 | rpsc2->els_cmd.els_code = FC_ELS_RPSC; | ||
795 | rpsc2->token = bfa_os_htonl(FC_BRCD_TOKEN); | ||
796 | rpsc2->num_pids = bfa_os_htons(npids); | ||
797 | for (i = 0; i < npids; i++) | ||
798 | rpsc2->pid_list[i].pid = pid_list[i]; | ||
799 | |||
800 | return (sizeof(struct fc_rpsc2_cmd_s) + ((npids - 1) * | ||
801 | (sizeof(u32)))); | ||
802 | } | ||
803 | |||
804 | u16 | ||
805 | fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, | ||
806 | u32 d_id, u32 s_id, u16 ox_id, | ||
807 | struct fc_rpsc_speed_info_s *oper_speed) | ||
808 | { | ||
809 | memset(rpsc_acc, 0, sizeof(struct fc_rpsc_acc_s)); | ||
810 | |||
811 | fc_els_rsp_build(fchs, d_id, s_id, ox_id); | ||
812 | |||
813 | rpsc_acc->command = FC_ELS_ACC; | ||
814 | rpsc_acc->num_entries = bfa_os_htons(1); | ||
815 | |||
816 | rpsc_acc->speed_info[0].port_speed_cap = | ||
817 | bfa_os_htons(oper_speed->port_speed_cap); | ||
818 | |||
819 | rpsc_acc->speed_info[0].port_op_speed = | ||
820 | bfa_os_htons(oper_speed->port_op_speed); | ||
821 | |||
822 | return (sizeof(struct fc_rpsc_acc_s)); | ||
823 | |||
824 | } | ||
825 | |||
826 | /* | ||
827 | * TBD - | ||
828 | * . get rid of unnecessary memsets | ||
829 | */ | ||
830 | |||
831 | u16 | ||
832 | fc_logo_rsp_parse(struct fchs_s *fchs, int len) | ||
833 | { | ||
834 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
835 | |||
836 | len = len; | ||
837 | if (els_cmd->els_code != FC_ELS_ACC) | ||
838 | return FC_PARSE_FAILURE; | ||
839 | |||
840 | return FC_PARSE_OK; | ||
841 | } | ||
842 | |||
843 | u16 | ||
844 | fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
845 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
846 | u16 pdu_size) | ||
847 | { | ||
848 | struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); | ||
849 | |||
850 | bfa_os_memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s)); | ||
851 | |||
852 | pdisc->els_cmd.els_code = FC_ELS_PDISC; | ||
853 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
854 | |||
855 | pdisc->csp.rxsz = pdisc->class3.rxsz = bfa_os_htons(pdu_size); | ||
856 | pdisc->port_name = port_name; | ||
857 | pdisc->node_name = node_name; | ||
858 | |||
859 | return (sizeof(struct fc_logi_s)); | ||
860 | } | ||
861 | |||
862 | u16 | ||
863 | fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name) | ||
864 | { | ||
865 | struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1); | ||
866 | |||
867 | if (len < sizeof(struct fc_logi_s)) | ||
868 | return (FC_PARSE_LEN_INVAL); | ||
869 | |||
870 | if (pdisc->els_cmd.els_code != FC_ELS_ACC) | ||
871 | return (FC_PARSE_ACC_INVAL); | ||
872 | |||
873 | if (!wwn_is_equal(pdisc->port_name, port_name)) | ||
874 | return (FC_PARSE_PWWN_NOT_EQUAL); | ||
875 | |||
876 | if (!pdisc->class3.class_valid) | ||
877 | return (FC_PARSE_NWWN_NOT_EQUAL); | ||
878 | |||
879 | if (bfa_os_ntohs(pdisc->class3.rxsz) < (FC_MIN_PDUSZ)) | ||
880 | return (FC_PARSE_RXSZ_INVAL); | ||
881 | |||
882 | return (FC_PARSE_OK); | ||
883 | } | ||
884 | |||
885 | u16 | ||
886 | fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id, | ||
887 | int num_pages) | ||
888 | { | ||
889 | struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1); | ||
890 | int page; | ||
891 | |||
892 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
893 | memset(prlo, 0, (num_pages * 16) + 4); | ||
894 | prlo->command = FC_ELS_PRLO; | ||
895 | prlo->page_len = 0x10; | ||
896 | prlo->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
897 | |||
898 | for (page = 0; page < num_pages; page++) { | ||
899 | prlo->prlo_params[page].type = FC_TYPE_FCP; | ||
900 | prlo->prlo_params[page].opa_valid = 0; | ||
901 | prlo->prlo_params[page].rpa_valid = 0; | ||
902 | prlo->prlo_params[page].orig_process_assc = 0; | ||
903 | prlo->prlo_params[page].resp_process_assc = 0; | ||
904 | } | ||
905 | |||
906 | return (bfa_os_ntohs(prlo->payload_len)); | ||
907 | } | ||
908 | |||
909 | u16 | ||
910 | fc_prlo_rsp_parse(struct fchs_s *fchs, int len) | ||
911 | { | ||
912 | struct fc_prlo_acc_s *prlo = (struct fc_prlo_acc_s *) (fchs + 1); | ||
913 | int num_pages = 0; | ||
914 | int page = 0; | ||
915 | |||
916 | len = len; | ||
917 | |||
918 | if (prlo->command != FC_ELS_ACC) | ||
919 | return (FC_PARSE_FAILURE); | ||
920 | |||
921 | num_pages = ((bfa_os_ntohs(prlo->payload_len)) - 4) / 16; | ||
922 | |||
923 | for (page = 0; page < num_pages; page++) { | ||
924 | if (prlo->prlo_acc_params[page].type != FC_TYPE_FCP) | ||
925 | return FC_PARSE_FAILURE; | ||
926 | |||
927 | if (prlo->prlo_acc_params[page].opa_valid != 0) | ||
928 | return FC_PARSE_FAILURE; | ||
929 | |||
930 | if (prlo->prlo_acc_params[page].rpa_valid != 0) | ||
931 | return FC_PARSE_FAILURE; | ||
932 | |||
933 | if (prlo->prlo_acc_params[page].orig_process_assc != 0) | ||
934 | return FC_PARSE_FAILURE; | ||
935 | |||
936 | if (prlo->prlo_acc_params[page].resp_process_assc != 0) | ||
937 | return FC_PARSE_FAILURE; | ||
938 | } | ||
939 | return (FC_PARSE_OK); | ||
940 | |||
941 | } | ||
942 | |||
943 | u16 | ||
944 | fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
945 | u16 ox_id, int num_pages, | ||
946 | enum fc_tprlo_type tprlo_type, u32 tpr_id) | ||
947 | { | ||
948 | struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1); | ||
949 | int page; | ||
950 | |||
951 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
952 | memset(tprlo, 0, (num_pages * 16) + 4); | ||
953 | tprlo->command = FC_ELS_TPRLO; | ||
954 | tprlo->page_len = 0x10; | ||
955 | tprlo->payload_len = bfa_os_htons((num_pages * 16) + 4); | ||
956 | |||
957 | for (page = 0; page < num_pages; page++) { | ||
958 | tprlo->tprlo_params[page].type = FC_TYPE_FCP; | ||
959 | tprlo->tprlo_params[page].opa_valid = 0; | ||
960 | tprlo->tprlo_params[page].rpa_valid = 0; | ||
961 | tprlo->tprlo_params[page].orig_process_assc = 0; | ||
962 | tprlo->tprlo_params[page].resp_process_assc = 0; | ||
963 | if (tprlo_type == FC_GLOBAL_LOGO) { | ||
964 | tprlo->tprlo_params[page].global_process_logout = 1; | ||
965 | } else if (tprlo_type == FC_TPR_LOGO) { | ||
966 | tprlo->tprlo_params[page].tpo_nport_valid = 1; | ||
967 | tprlo->tprlo_params[page].tpo_nport_id = (tpr_id); | ||
968 | } | ||
969 | } | ||
970 | |||
971 | return (bfa_os_ntohs(tprlo->payload_len)); | ||
972 | } | ||
973 | |||
974 | u16 | ||
975 | fc_tprlo_rsp_parse(struct fchs_s *fchs, int len) | ||
976 | { | ||
977 | struct fc_tprlo_acc_s *tprlo = (struct fc_tprlo_acc_s *) (fchs + 1); | ||
978 | int num_pages = 0; | ||
979 | int page = 0; | ||
980 | |||
981 | len = len; | ||
982 | |||
983 | if (tprlo->command != FC_ELS_ACC) | ||
984 | return (FC_PARSE_ACC_INVAL); | ||
985 | |||
986 | num_pages = (bfa_os_ntohs(tprlo->payload_len) - 4) / 16; | ||
987 | |||
988 | for (page = 0; page < num_pages; page++) { | ||
989 | if (tprlo->tprlo_acc_params[page].type != FC_TYPE_FCP) | ||
990 | return (FC_PARSE_NOT_FCP); | ||
991 | if (tprlo->tprlo_acc_params[page].opa_valid != 0) | ||
992 | return (FC_PARSE_OPAFLAG_INVAL); | ||
993 | if (tprlo->tprlo_acc_params[page].rpa_valid != 0) | ||
994 | return (FC_PARSE_RPAFLAG_INVAL); | ||
995 | if (tprlo->tprlo_acc_params[page].orig_process_assc != 0) | ||
996 | return (FC_PARSE_OPA_INVAL); | ||
997 | if (tprlo->tprlo_acc_params[page].resp_process_assc != 0) | ||
998 | return (FC_PARSE_RPA_INVAL); | ||
999 | } | ||
1000 | return (FC_PARSE_OK); | ||
1001 | } | ||
1002 | |||
1003 | enum fc_parse_status | ||
1004 | fc_rrq_rsp_parse(struct fchs_s *fchs, int len) | ||
1005 | { | ||
1006 | struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
1007 | |||
1008 | len = len; | ||
1009 | if (els_cmd->els_code != FC_ELS_ACC) | ||
1010 | return FC_PARSE_FAILURE; | ||
1011 | |||
1012 | return FC_PARSE_OK; | ||
1013 | } | ||
1014 | |||
1015 | u16 | ||
1016 | fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
1017 | u16 ox_id, u32 reason_code, | ||
1018 | u32 reason_expl) | ||
1019 | { | ||
1020 | struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1); | ||
1021 | |||
1022 | fc_bls_rsp_build(fchs, d_id, s_id, ox_id); | ||
1023 | |||
1024 | fchs->cat_info = FC_CAT_BA_RJT; | ||
1025 | ba_rjt->reason_code = reason_code; | ||
1026 | ba_rjt->reason_expl = reason_expl; | ||
1027 | return (sizeof(struct fc_ba_rjt_s)); | ||
1028 | } | ||
1029 | |||
1030 | static void | ||
1031 | fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) | ||
1032 | { | ||
1033 | bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s)); | ||
1034 | cthdr->rev_id = CT_GS3_REVISION; | ||
1035 | cthdr->gs_type = CT_GSTYPE_DIRSERVICE; | ||
1036 | cthdr->gs_sub_type = CT_GSSUBTYPE_NAMESERVER; | ||
1037 | cthdr->cmd_rsp_code = bfa_os_htons(cmd_code); | ||
1038 | } | ||
1039 | |||
1040 | static void | ||
1041 | fc_gs_fdmi_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code) | ||
1042 | { | ||
1043 | bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s)); | ||
1044 | cthdr->rev_id = CT_GS3_REVISION; | ||
1045 | cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; | ||
1046 | cthdr->gs_sub_type = CT_GSSUBTYPE_HBA_MGMTSERVER; | ||
1047 | cthdr->cmd_rsp_code = bfa_os_htons(cmd_code); | ||
1048 | } | ||
1049 | |||
1050 | static void | ||
1051 | fc_gs_ms_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code, | ||
1052 | u8 sub_type) | ||
1053 | { | ||
1054 | bfa_os_memset(cthdr, 0, sizeof(struct ct_hdr_s)); | ||
1055 | cthdr->rev_id = CT_GS3_REVISION; | ||
1056 | cthdr->gs_type = CT_GSTYPE_MGMTSERVICE; | ||
1057 | cthdr->gs_sub_type = sub_type; | ||
1058 | cthdr->cmd_rsp_code = bfa_os_htons(cmd_code); | ||
1059 | } | ||
1060 | |||
1061 | u16 | ||
1062 | fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1063 | wwn_t port_name) | ||
1064 | { | ||
1065 | |||
1066 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1067 | struct fcgs_gidpn_req_s *gidpn = | ||
1068 | (struct fcgs_gidpn_req_s *) (cthdr + 1); | ||
1069 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1070 | |||
1071 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1072 | fc_gs_cthdr_build(cthdr, s_id, GS_GID_PN); | ||
1073 | |||
1074 | bfa_os_memset(gidpn, 0, sizeof(struct fcgs_gidpn_req_s)); | ||
1075 | gidpn->port_name = port_name; | ||
1076 | return (sizeof(struct fcgs_gidpn_req_s) + sizeof(struct ct_hdr_s)); | ||
1077 | } | ||
1078 | |||
1079 | u16 | ||
1080 | fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1081 | u32 port_id) | ||
1082 | { | ||
1083 | |||
1084 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1085 | fcgs_gpnid_req_t *gpnid = (fcgs_gpnid_req_t *) (cthdr + 1); | ||
1086 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1087 | |||
1088 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1089 | fc_gs_cthdr_build(cthdr, s_id, GS_GPN_ID); | ||
1090 | |||
1091 | bfa_os_memset(gpnid, 0, sizeof(fcgs_gpnid_req_t)); | ||
1092 | gpnid->dap = port_id; | ||
1093 | return (sizeof(fcgs_gpnid_req_t) + sizeof(struct ct_hdr_s)); | ||
1094 | } | ||
1095 | |||
1096 | u16 | ||
1097 | fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1098 | u32 port_id) | ||
1099 | { | ||
1100 | |||
1101 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1102 | fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1); | ||
1103 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1104 | |||
1105 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1106 | fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID); | ||
1107 | |||
1108 | bfa_os_memset(gnnid, 0, sizeof(fcgs_gnnid_req_t)); | ||
1109 | gnnid->dap = port_id; | ||
1110 | return (sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s)); | ||
1111 | } | ||
1112 | |||
1113 | u16 | ||
1114 | fc_ct_rsp_parse(struct ct_hdr_s *cthdr) | ||
1115 | { | ||
1116 | if (bfa_os_ntohs(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) { | ||
1117 | if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY) | ||
1118 | return FC_PARSE_BUSY; | ||
1119 | else | ||
1120 | return FC_PARSE_FAILURE; | ||
1121 | } | ||
1122 | |||
1123 | return FC_PARSE_OK; | ||
1124 | } | ||
1125 | |||
1126 | u16 | ||
1127 | fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, u8 set_br_reg, | ||
1128 | u32 s_id, u16 ox_id) | ||
1129 | { | ||
1130 | u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); | ||
1131 | |||
1132 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
1133 | |||
1134 | bfa_os_memset(scr, 0, sizeof(struct fc_scr_s)); | ||
1135 | scr->command = FC_ELS_SCR; | ||
1136 | scr->reg_func = FC_SCR_REG_FUNC_FULL; | ||
1137 | if (set_br_reg) | ||
1138 | scr->vu_reg_func = FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE; | ||
1139 | |||
1140 | return (sizeof(struct fc_scr_s)); | ||
1141 | } | ||
1142 | |||
1143 | u16 | ||
1144 | fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id, | ||
1145 | u16 ox_id) | ||
1146 | { | ||
1147 | u32 d_id = bfa_os_hton3b(FC_FABRIC_CONTROLLER); | ||
1148 | u16 payldlen; | ||
1149 | |||
1150 | fc_els_req_build(fchs, d_id, s_id, ox_id); | ||
1151 | rscn->command = FC_ELS_RSCN; | ||
1152 | rscn->pagelen = sizeof(rscn->event[0]); | ||
1153 | |||
1154 | payldlen = sizeof(u32) + rscn->pagelen; | ||
1155 | rscn->payldlen = bfa_os_htons(payldlen); | ||
1156 | |||
1157 | rscn->event[0].format = FC_RSCN_FORMAT_PORTID; | ||
1158 | rscn->event[0].portid = s_id; | ||
1159 | |||
1160 | return (sizeof(struct fc_rscn_pl_s)); | ||
1161 | } | ||
1162 | |||
1163 | u16 | ||
1164 | fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1165 | enum bfa_port_role roles) | ||
1166 | { | ||
1167 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1168 | struct fcgs_rftid_req_s *rftid = | ||
1169 | (struct fcgs_rftid_req_s *) (cthdr + 1); | ||
1170 | u32 type_value, d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1171 | u8 index; | ||
1172 | |||
1173 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1174 | fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); | ||
1175 | |||
1176 | bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s)); | ||
1177 | |||
1178 | rftid->dap = s_id; | ||
1179 | |||
1180 | /* By default, FCP FC4 Type is registered */ | ||
1181 | index = FC_TYPE_FCP >> 5; | ||
1182 | type_value = 1 << (FC_TYPE_FCP % 32); | ||
1183 | rftid->fc4_type[index] = bfa_os_htonl(type_value); | ||
1184 | |||
1185 | if (roles & BFA_PORT_ROLE_FCP_IPFC) { | ||
1186 | index = FC_TYPE_IP >> 5; | ||
1187 | type_value = 1 << (FC_TYPE_IP % 32); | ||
1188 | rftid->fc4_type[index] |= bfa_os_htonl(type_value); | ||
1189 | } | ||
1190 | |||
1191 | return (sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s)); | ||
1192 | } | ||
1193 | |||
1194 | u16 | ||
1195 | fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
1196 | u16 ox_id, u8 *fc4_bitmap, | ||
1197 | u32 bitmap_size) | ||
1198 | { | ||
1199 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1200 | struct fcgs_rftid_req_s *rftid = | ||
1201 | (struct fcgs_rftid_req_s *) (cthdr + 1); | ||
1202 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1203 | |||
1204 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1205 | fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID); | ||
1206 | |||
1207 | bfa_os_memset(rftid, 0, sizeof(struct fcgs_rftid_req_s)); | ||
1208 | |||
1209 | rftid->dap = s_id; | ||
1210 | bfa_os_memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap, | ||
1211 | (bitmap_size < 32 ? bitmap_size : 32)); | ||
1212 | |||
1213 | return (sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s)); | ||
1214 | } | ||
1215 | |||
1216 | u16 | ||
1217 | fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1218 | u8 fc4_type, u8 fc4_ftrs) | ||
1219 | { | ||
1220 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1221 | struct fcgs_rffid_req_s *rffid = | ||
1222 | (struct fcgs_rffid_req_s *) (cthdr + 1); | ||
1223 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1224 | |||
1225 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1226 | fc_gs_cthdr_build(cthdr, s_id, GS_RFF_ID); | ||
1227 | |||
1228 | bfa_os_memset(rffid, 0, sizeof(struct fcgs_rffid_req_s)); | ||
1229 | |||
1230 | rffid->dap = s_id; | ||
1231 | rffid->fc4ftr_bits = fc4_ftrs; | ||
1232 | rffid->fc4_type = fc4_type; | ||
1233 | |||
1234 | return (sizeof(struct fcgs_rffid_req_s) + sizeof(struct ct_hdr_s)); | ||
1235 | } | ||
1236 | |||
1237 | u16 | ||
1238 | fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, | ||
1239 | u8 *name) | ||
1240 | { | ||
1241 | |||
1242 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1243 | struct fcgs_rspnid_req_s *rspnid = | ||
1244 | (struct fcgs_rspnid_req_s *) (cthdr + 1); | ||
1245 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1246 | |||
1247 | fc_gs_fchdr_build(fchs, d_id, s_id, ox_id); | ||
1248 | fc_gs_cthdr_build(cthdr, s_id, GS_RSPN_ID); | ||
1249 | |||
1250 | bfa_os_memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s)); | ||
1251 | |||
1252 | rspnid->dap = s_id; | ||
1253 | rspnid->spn_len = (u8) strlen((char *)name); | ||
1254 | strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len); | ||
1255 | |||
1256 | return (sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s)); | ||
1257 | } | ||
1258 | |||
1259 | u16 | ||
1260 | fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
1261 | u8 fc4_type) | ||
1262 | { | ||
1263 | |||
1264 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1265 | struct fcgs_gidft_req_s *gidft = | ||
1266 | (struct fcgs_gidft_req_s *) (cthdr + 1); | ||
1267 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1268 | |||
1269 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1270 | |||
1271 | fc_gs_cthdr_build(cthdr, s_id, GS_GID_FT); | ||
1272 | |||
1273 | bfa_os_memset(gidft, 0, sizeof(struct fcgs_gidft_req_s)); | ||
1274 | gidft->fc4_type = fc4_type; | ||
1275 | gidft->domain_id = 0; | ||
1276 | gidft->area_id = 0; | ||
1277 | |||
1278 | return (sizeof(struct fcgs_gidft_req_s) + sizeof(struct ct_hdr_s)); | ||
1279 | } | ||
1280 | |||
1281 | u16 | ||
1282 | fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1283 | wwn_t port_name) | ||
1284 | { | ||
1285 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1286 | struct fcgs_rpnid_req_s *rpnid = | ||
1287 | (struct fcgs_rpnid_req_s *) (cthdr + 1); | ||
1288 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1289 | |||
1290 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1291 | fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID); | ||
1292 | |||
1293 | bfa_os_memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s)); | ||
1294 | rpnid->port_id = port_id; | ||
1295 | rpnid->port_name = port_name; | ||
1296 | |||
1297 | return (sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s)); | ||
1298 | } | ||
1299 | |||
1300 | u16 | ||
1301 | fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1302 | wwn_t node_name) | ||
1303 | { | ||
1304 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1305 | struct fcgs_rnnid_req_s *rnnid = | ||
1306 | (struct fcgs_rnnid_req_s *) (cthdr + 1); | ||
1307 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1308 | |||
1309 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1310 | fc_gs_cthdr_build(cthdr, s_id, GS_RNN_ID); | ||
1311 | |||
1312 | bfa_os_memset(rnnid, 0, sizeof(struct fcgs_rnnid_req_s)); | ||
1313 | rnnid->port_id = port_id; | ||
1314 | rnnid->node_name = node_name; | ||
1315 | |||
1316 | return (sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s)); | ||
1317 | } | ||
1318 | |||
1319 | u16 | ||
1320 | fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1321 | u32 cos) | ||
1322 | { | ||
1323 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1324 | struct fcgs_rcsid_req_s *rcsid = | ||
1325 | (struct fcgs_rcsid_req_s *) (cthdr + 1); | ||
1326 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1327 | |||
1328 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1329 | fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID); | ||
1330 | |||
1331 | bfa_os_memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s)); | ||
1332 | rcsid->port_id = port_id; | ||
1333 | rcsid->cos = cos; | ||
1334 | |||
1335 | return (sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s)); | ||
1336 | } | ||
1337 | |||
1338 | u16 | ||
1339 | fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id, | ||
1340 | u8 port_type) | ||
1341 | { | ||
1342 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1343 | struct fcgs_rptid_req_s *rptid = | ||
1344 | (struct fcgs_rptid_req_s *) (cthdr + 1); | ||
1345 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1346 | |||
1347 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1348 | fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID); | ||
1349 | |||
1350 | bfa_os_memset(rptid, 0, sizeof(struct fcgs_rptid_req_s)); | ||
1351 | rptid->port_id = port_id; | ||
1352 | rptid->port_type = port_type; | ||
1353 | |||
1354 | return (sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s)); | ||
1355 | } | ||
1356 | |||
1357 | u16 | ||
1358 | fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id) | ||
1359 | { | ||
1360 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1361 | struct fcgs_ganxt_req_s *ganxt = | ||
1362 | (struct fcgs_ganxt_req_s *) (cthdr + 1); | ||
1363 | u32 d_id = bfa_os_hton3b(FC_NAME_SERVER); | ||
1364 | |||
1365 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1366 | fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT); | ||
1367 | |||
1368 | bfa_os_memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s)); | ||
1369 | ganxt->port_id = port_id; | ||
1370 | |||
1371 | return (sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s)); | ||
1372 | } | ||
1373 | |||
1374 | /* | ||
1375 | * Builds fc hdr and ct hdr for FDMI requests. | ||
1376 | */ | ||
1377 | u16 | ||
1378 | fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
1379 | u16 cmd_code) | ||
1380 | { | ||
1381 | |||
1382 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1383 | u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); | ||
1384 | |||
1385 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1386 | fc_gs_fdmi_cthdr_build(cthdr, s_id, cmd_code); | ||
1387 | |||
1388 | return (sizeof(struct ct_hdr_s)); | ||
1389 | } | ||
1390 | |||
1391 | /* | ||
1392 | * Given a FC4 Type, this function returns a fc4 type bitmask | ||
1393 | */ | ||
1394 | void | ||
1395 | fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask) | ||
1396 | { | ||
1397 | u8 index; | ||
1398 | u32 *ptr = (u32 *) bit_mask; | ||
1399 | u32 type_value; | ||
1400 | |||
1401 | /* | ||
1402 | * @todo : Check for bitmask size | ||
1403 | */ | ||
1404 | |||
1405 | index = fc4_type >> 5; | ||
1406 | type_value = 1 << (fc4_type % 32); | ||
1407 | ptr[index] = bfa_os_htonl(type_value); | ||
1408 | |||
1409 | } | ||
1410 | |||
1411 | /* | ||
1412 | * GMAL Request | ||
1413 | */ | ||
1414 | u16 | ||
1415 | fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) | ||
1416 | { | ||
1417 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1418 | fcgs_gmal_req_t *gmal = (fcgs_gmal_req_t *) (cthdr + 1); | ||
1419 | u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); | ||
1420 | |||
1421 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1422 | fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GMAL_CMD, | ||
1423 | CT_GSSUBTYPE_CFGSERVER); | ||
1424 | |||
1425 | bfa_os_memset(gmal, 0, sizeof(fcgs_gmal_req_t)); | ||
1426 | gmal->wwn = wwn; | ||
1427 | |||
1428 | return (sizeof(struct ct_hdr_s) + sizeof(fcgs_gmal_req_t)); | ||
1429 | } | ||
1430 | |||
1431 | /* | ||
1432 | * GFN (Get Fabric Name) Request | ||
1433 | */ | ||
1434 | u16 | ||
1435 | fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, wwn_t wwn) | ||
1436 | { | ||
1437 | struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld; | ||
1438 | fcgs_gfn_req_t *gfn = (fcgs_gfn_req_t *) (cthdr + 1); | ||
1439 | u32 d_id = bfa_os_hton3b(FC_MGMT_SERVER); | ||
1440 | |||
1441 | fc_gs_fchdr_build(fchs, d_id, s_id, 0); | ||
1442 | fc_gs_ms_cthdr_build(cthdr, s_id, GS_FC_GFN_CMD, | ||
1443 | CT_GSSUBTYPE_CFGSERVER); | ||
1444 | |||
1445 | bfa_os_memset(gfn, 0, sizeof(fcgs_gfn_req_t)); | ||
1446 | gfn->wwn = wwn; | ||
1447 | |||
1448 | return (sizeof(struct ct_hdr_s) + sizeof(fcgs_gfn_req_t)); | ||
1449 | } | ||
diff --git a/drivers/scsi/bfa/fcbuild.h b/drivers/scsi/bfa/fcbuild.h new file mode 100644 index 000000000000..4d248424f7b3 --- /dev/null +++ b/drivers/scsi/bfa/fcbuild.h | |||
@@ -0,0 +1,273 @@ | |||
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 | * fcbuild.h - FC link service frame building and parsing routines | ||
19 | */ | ||
20 | |||
21 | #ifndef __FCBUILD_H__ | ||
22 | #define __FCBUILD_H__ | ||
23 | |||
24 | #include <bfa_os_inc.h> | ||
25 | #include <protocol/fc.h> | ||
26 | #include <protocol/fcp.h> | ||
27 | #include <protocol/ct.h> | ||
28 | #include <defs/bfa_defs_port.h> | ||
29 | #include <defs/bfa_defs_pport.h> | ||
30 | |||
31 | /* | ||
32 | * Utility Macros/functions | ||
33 | */ | ||
34 | |||
35 | #define fcif_sof_set(_ifhdr, _sof) (_ifhdr)->sof = FC_ ## _sof | ||
36 | #define fcif_eof_set(_ifhdr, _eof) (_ifhdr)->eof = FC_ ## _eof | ||
37 | |||
38 | #define wwn_is_equal(_wwn1, _wwn2) \ | ||
39 | (memcmp(&(_wwn1), &(_wwn2), sizeof(wwn_t)) == 0) | ||
40 | |||
41 | #define fc_roundup(_l, _s) (((_l) + ((_s) - 1)) & ~((_s) - 1)) | ||
42 | |||
43 | /* | ||
44 | * Given the fc response length, this routine will return | ||
45 | * the length of the actual payload bytes following the CT header. | ||
46 | * | ||
47 | * Assumes the input response length does not include the crc, eof, etc. | ||
48 | */ | ||
49 | static inline u32 | ||
50 | fc_get_ctresp_pyld_len(u32 resp_len) | ||
51 | { | ||
52 | return (resp_len - sizeof(struct ct_hdr_s)); | ||
53 | } | ||
54 | |||
55 | /* | ||
56 | * Convert bfa speed to rpsc speed value. | ||
57 | */ | ||
58 | static inline enum bfa_pport_speed | ||
59 | fc_rpsc_operspeed_to_bfa_speed(enum fc_rpsc_op_speed_s speed) | ||
60 | { | ||
61 | switch (speed) { | ||
62 | |||
63 | case RPSC_OP_SPEED_1G: | ||
64 | return BFA_PPORT_SPEED_1GBPS; | ||
65 | |||
66 | case RPSC_OP_SPEED_2G: | ||
67 | return BFA_PPORT_SPEED_2GBPS; | ||
68 | |||
69 | case RPSC_OP_SPEED_4G: | ||
70 | return BFA_PPORT_SPEED_4GBPS; | ||
71 | |||
72 | case RPSC_OP_SPEED_8G: | ||
73 | return BFA_PPORT_SPEED_8GBPS; | ||
74 | |||
75 | default: | ||
76 | return BFA_PPORT_SPEED_UNKNOWN; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Convert RPSC speed to bfa speed value. | ||
82 | */ | ||
83 | static inline enum fc_rpsc_op_speed_s | ||
84 | fc_bfa_speed_to_rpsc_operspeed(enum bfa_pport_speed op_speed) | ||
85 | { | ||
86 | switch (op_speed) { | ||
87 | |||
88 | case BFA_PPORT_SPEED_1GBPS: | ||
89 | return RPSC_OP_SPEED_1G; | ||
90 | |||
91 | case BFA_PPORT_SPEED_2GBPS: | ||
92 | return RPSC_OP_SPEED_2G; | ||
93 | |||
94 | case BFA_PPORT_SPEED_4GBPS: | ||
95 | return RPSC_OP_SPEED_4G; | ||
96 | |||
97 | case BFA_PPORT_SPEED_8GBPS: | ||
98 | return RPSC_OP_SPEED_8G; | ||
99 | |||
100 | default: | ||
101 | return RPSC_OP_SPEED_NOT_EST; | ||
102 | } | ||
103 | } | ||
104 | enum fc_parse_status { | ||
105 | FC_PARSE_OK = 0, | ||
106 | FC_PARSE_FAILURE = 1, | ||
107 | FC_PARSE_BUSY = 2, | ||
108 | FC_PARSE_LEN_INVAL, | ||
109 | FC_PARSE_ACC_INVAL, | ||
110 | FC_PARSE_PWWN_NOT_EQUAL, | ||
111 | FC_PARSE_NWWN_NOT_EQUAL, | ||
112 | FC_PARSE_RXSZ_INVAL, | ||
113 | FC_PARSE_NOT_FCP, | ||
114 | FC_PARSE_OPAFLAG_INVAL, | ||
115 | FC_PARSE_RPAFLAG_INVAL, | ||
116 | FC_PARSE_OPA_INVAL, | ||
117 | FC_PARSE_RPA_INVAL, | ||
118 | |||
119 | }; | ||
120 | |||
121 | struct fc_templates_s { | ||
122 | struct fchs_s fc_els_req; | ||
123 | struct fchs_s fc_bls_req; | ||
124 | struct fc_logi_s plogi; | ||
125 | struct fc_rrq_s rrq; | ||
126 | }; | ||
127 | |||
128 | void fcbuild_init(void); | ||
129 | |||
130 | u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, | ||
131 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
132 | wwn_t node_name, u16 pdu_size, u8 set_npiv, | ||
133 | u8 set_auth, u16 local_bb_credits); | ||
134 | u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, | ||
135 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
136 | wwn_t node_name, u16 pdu_size); | ||
137 | u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, | ||
138 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
139 | wwn_t node_name, u16 pdu_size, | ||
140 | u16 local_bb_credits); | ||
141 | u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, | ||
142 | u32 s_id, u16 ox_id, wwn_t port_name, | ||
143 | wwn_t node_name, u16 pdu_size); | ||
144 | enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs); | ||
145 | u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id, | ||
146 | u16 ox_id); | ||
147 | enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len); | ||
148 | u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id, | ||
149 | u32 s_id, u16 ox_id, u16 rrq_oxid); | ||
150 | enum fc_parse_status fc_rrq_rsp_parse(struct fchs_s *buf, int len); | ||
151 | u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id, | ||
152 | u16 ox_id, u8 *name); | ||
153 | u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id, | ||
154 | u16 ox_id, enum bfa_port_role role); | ||
155 | u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
156 | u16 ox_id, u8 *fc4_bitmap, | ||
157 | u32 bitmap_size); | ||
158 | u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
159 | u16 ox_id, u8 fc4_type, u8 fc4_ftrs); | ||
160 | u16 fc_gidpn_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
161 | u16 ox_id, wwn_t port_name); | ||
162 | u16 fc_gpnid_build(struct fchs_s *fchs, void *pld, u32 s_id, | ||
163 | u16 ox_id, u32 port_id); | ||
164 | u16 fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr, | ||
165 | u8 set_br_reg, u32 s_id, u16 ox_id); | ||
166 | u16 fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, | ||
167 | u32 s_id, u16 ox_id, | ||
168 | wwn_t port_name, wwn_t node_name, u16 pdu_size); | ||
169 | |||
170 | u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, | ||
171 | u32 d_id, u32 s_id, u16 ox_id, | ||
172 | wwn_t port_name, wwn_t node_name); | ||
173 | enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld, | ||
174 | u32 host_dap, | ||
175 | wwn_t node_name, wwn_t port_name); | ||
176 | enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, | ||
177 | wwn_t port_name, wwn_t node_name); | ||
178 | u16 fc_adisc_acc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc, | ||
179 | u32 d_id, u32 s_id, u16 ox_id, | ||
180 | wwn_t port_name, wwn_t node_name); | ||
181 | u16 fc_ls_rjt_build(struct fchs_s *fchs, struct fc_ls_rjt_s *ls_rjt, | ||
182 | u32 d_id, u32 s_id, u16 ox_id, | ||
183 | u8 reason_code, u8 reason_code_expl); | ||
184 | u16 fc_ls_acc_build(struct fchs_s *fchs, struct fc_els_cmd_s *els_cmd, | ||
185 | u32 d_id, u32 s_id, u16 ox_id); | ||
186 | u16 fc_prli_build(struct fchs_s *fchs, void *pld, u32 d_id, | ||
187 | u32 s_id, u16 ox_id); | ||
188 | enum fc_parse_status fc_prli_rsp_parse(struct fc_prli_s *prli, int len); | ||
189 | |||
190 | u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, | ||
191 | u32 s_id, u16 ox_id, | ||
192 | enum bfa_port_role role); | ||
193 | u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, | ||
194 | u32 d_id, u32 s_id, u16 ox_id, | ||
195 | u32 data_format); | ||
196 | u16 fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, | ||
197 | u32 d_id, u32 s_id, u16 ox_id, | ||
198 | u32 data_format, | ||
199 | struct fc_rnid_common_id_data_s *common_id_data, | ||
200 | struct fc_rnid_general_topology_data_s * | ||
201 | gen_topo_data); | ||
202 | u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c, | ||
203 | u32 d_id, u32 s_id, | ||
204 | u32 *pid_list, u16 npids); | ||
205 | u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, | ||
206 | u32 d_id, u32 s_id, u16 ox_id); | ||
207 | u16 fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc, | ||
208 | u32 d_id, u32 s_id, u16 ox_id, | ||
209 | struct fc_rpsc_speed_info_s *oper_speed); | ||
210 | u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id, | ||
211 | u8 fc4_type); | ||
212 | u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
213 | u32 port_id, wwn_t port_name); | ||
214 | u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
215 | u32 port_id, wwn_t node_name); | ||
216 | u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
217 | u32 port_id, u32 cos); | ||
218 | u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
219 | u32 port_id, u8 port_type); | ||
220 | u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
221 | u32 port_id); | ||
222 | u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, | ||
223 | u32 d_id, u32 s_id, u16 ox_id, | ||
224 | wwn_t port_name); | ||
225 | u16 fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, | ||
226 | u32 s_id, u16 ox_id); | ||
227 | u16 fc_fdmi_reqhdr_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
228 | u16 cmd_code); | ||
229 | u16 fc_gmal_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
230 | wwn_t wwn); | ||
231 | u16 fc_gfn_req_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
232 | wwn_t wwn); | ||
233 | void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask); | ||
234 | void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
235 | u16 ox_id); | ||
236 | enum fc_parse_status fc_els_rsp_parse(struct fchs_s *fchs, int len); | ||
237 | enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len, | ||
238 | wwn_t port_name); | ||
239 | enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli); | ||
240 | enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, | ||
241 | wwn_t port_name); | ||
242 | u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, | ||
243 | u32 d_id, u32 s_id, u16 ox_id, | ||
244 | u16 rx_id); | ||
245 | int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code); | ||
246 | u16 fc_tprlo_acc_build(struct fchs_s *fchs, | ||
247 | struct fc_tprlo_acc_s *tprlo_acc, | ||
248 | u32 d_id, u32 s_id, u16 ox_id, | ||
249 | int num_pages); | ||
250 | u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, | ||
251 | u32 d_id, u32 s_id, u16 ox_id, | ||
252 | int num_pages); | ||
253 | u16 fc_logo_rsp_parse(struct fchs_s *fchs, int len); | ||
254 | u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
255 | u16 ox_id, wwn_t port_name, wwn_t node_name, | ||
256 | u16 pdu_size); | ||
257 | u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name); | ||
258 | u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
259 | u16 ox_id, int num_pages); | ||
260 | u16 fc_prlo_rsp_parse(struct fchs_s *fchs, int len); | ||
261 | u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
262 | u16 ox_id, int num_pages, | ||
263 | enum fc_tprlo_type tprlo_type, u32 tpr_id); | ||
264 | u16 fc_tprlo_rsp_parse(struct fchs_s *fchs, int len); | ||
265 | u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, | ||
266 | u16 ox_id, u32 reason_code, | ||
267 | u32 reason_expl); | ||
268 | u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, | ||
269 | u16 ox_id, u32 port_id); | ||
270 | u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr); | ||
271 | u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, | ||
272 | u32 s_id, u16 ox_id); | ||
273 | #endif | ||
diff --git a/drivers/scsi/bfa/fcpim.c b/drivers/scsi/bfa/fcpim.c new file mode 100644 index 000000000000..8ce5d8934677 --- /dev/null +++ b/drivers/scsi/bfa/fcpim.c | |||
@@ -0,0 +1,844 @@ | |||
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 | * fcpim.c - FCP initiator mode i-t nexus state machine | ||
20 | */ | ||
21 | |||
22 | #include <bfa.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include "fcs_fcpim.h" | ||
25 | #include "fcs_rport.h" | ||
26 | #include "fcs_lport.h" | ||
27 | #include "fcs_trcmod.h" | ||
28 | #include "fcs_fcxp.h" | ||
29 | #include "fcs.h" | ||
30 | #include <fcs/bfa_fcs_fcpim.h> | ||
31 | #include <fcb/bfa_fcb_fcpim.h> | ||
32 | #include <aen/bfa_aen_itnim.h> | ||
33 | |||
34 | BFA_TRC_FILE(FCS, FCPIM); | ||
35 | |||
36 | /* | ||
37 | * forward declarations | ||
38 | */ | ||
39 | static void bfa_fcs_itnim_timeout(void *arg); | ||
40 | static void bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim); | ||
41 | static void bfa_fcs_itnim_send_prli(void *itnim_cbarg, | ||
42 | struct bfa_fcxp_s *fcxp_alloced); | ||
43 | static void bfa_fcs_itnim_prli_response(void *fcsarg, | ||
44 | struct bfa_fcxp_s *fcxp, | ||
45 | void *cbarg, | ||
46 | bfa_status_t req_status, | ||
47 | u32 rsp_len, | ||
48 | u32 resid_len, | ||
49 | struct fchs_s *rsp_fchs); | ||
50 | static void bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim, | ||
51 | enum bfa_itnim_aen_event event); | ||
52 | |||
53 | /** | ||
54 | * fcs_itnim_sm FCS itnim state machine events | ||
55 | */ | ||
56 | |||
57 | enum bfa_fcs_itnim_event { | ||
58 | BFA_FCS_ITNIM_SM_ONLINE = 1, /* rport online event */ | ||
59 | BFA_FCS_ITNIM_SM_OFFLINE = 2, /* rport offline */ | ||
60 | BFA_FCS_ITNIM_SM_FRMSENT = 3, /* prli frame is sent */ | ||
61 | BFA_FCS_ITNIM_SM_RSP_OK = 4, /* good response */ | ||
62 | BFA_FCS_ITNIM_SM_RSP_ERROR = 5, /* error response */ | ||
63 | BFA_FCS_ITNIM_SM_TIMEOUT = 6, /* delay timeout */ | ||
64 | BFA_FCS_ITNIM_SM_HCB_OFFLINE = 7, /* BFA online callback */ | ||
65 | BFA_FCS_ITNIM_SM_HCB_ONLINE = 8, /* BFA offline callback */ | ||
66 | BFA_FCS_ITNIM_SM_INITIATOR = 9, /* rport is initiator */ | ||
67 | BFA_FCS_ITNIM_SM_DELETE = 10, /* delete event from rport */ | ||
68 | BFA_FCS_ITNIM_SM_PRLO = 11, /* delete event from rport */ | ||
69 | }; | ||
70 | |||
71 | static void bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim, | ||
72 | enum bfa_fcs_itnim_event event); | ||
73 | static void bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim, | ||
74 | enum bfa_fcs_itnim_event event); | ||
75 | static void bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim, | ||
76 | enum bfa_fcs_itnim_event event); | ||
77 | static void bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim, | ||
78 | enum bfa_fcs_itnim_event event); | ||
79 | static void bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim, | ||
80 | enum bfa_fcs_itnim_event event); | ||
81 | static void bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim, | ||
82 | enum bfa_fcs_itnim_event event); | ||
83 | static void bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim, | ||
84 | enum bfa_fcs_itnim_event event); | ||
85 | static void bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim, | ||
86 | enum bfa_fcs_itnim_event event); | ||
87 | |||
88 | static struct bfa_sm_table_s itnim_sm_table[] = { | ||
89 | {BFA_SM(bfa_fcs_itnim_sm_offline), BFA_ITNIM_OFFLINE}, | ||
90 | {BFA_SM(bfa_fcs_itnim_sm_prli_send), BFA_ITNIM_PRLI_SEND}, | ||
91 | {BFA_SM(bfa_fcs_itnim_sm_prli), BFA_ITNIM_PRLI_SENT}, | ||
92 | {BFA_SM(bfa_fcs_itnim_sm_prli_retry), BFA_ITNIM_PRLI_RETRY}, | ||
93 | {BFA_SM(bfa_fcs_itnim_sm_hcb_online), BFA_ITNIM_HCB_ONLINE}, | ||
94 | {BFA_SM(bfa_fcs_itnim_sm_online), BFA_ITNIM_ONLINE}, | ||
95 | {BFA_SM(bfa_fcs_itnim_sm_hcb_offline), BFA_ITNIM_HCB_OFFLINE}, | ||
96 | {BFA_SM(bfa_fcs_itnim_sm_initiator), BFA_ITNIM_INITIATIOR}, | ||
97 | }; | ||
98 | |||
99 | /** | ||
100 | * fcs_itnim_sm FCS itnim state machine | ||
101 | */ | ||
102 | |||
103 | static void | ||
104 | bfa_fcs_itnim_sm_offline(struct bfa_fcs_itnim_s *itnim, | ||
105 | enum bfa_fcs_itnim_event event) | ||
106 | { | ||
107 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
108 | bfa_trc(itnim->fcs, event); | ||
109 | |||
110 | switch (event) { | ||
111 | case BFA_FCS_ITNIM_SM_ONLINE: | ||
112 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send); | ||
113 | bfa_fcs_itnim_send_prli(itnim, NULL); | ||
114 | break; | ||
115 | |||
116 | case BFA_FCS_ITNIM_SM_OFFLINE: | ||
117 | bfa_fcs_rport_itnim_ack(itnim->rport); | ||
118 | break; | ||
119 | |||
120 | case BFA_FCS_ITNIM_SM_INITIATOR: | ||
121 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); | ||
122 | break; | ||
123 | |||
124 | case BFA_FCS_ITNIM_SM_DELETE: | ||
125 | bfa_fcs_itnim_free(itnim); | ||
126 | break; | ||
127 | |||
128 | default: | ||
129 | bfa_assert(0); | ||
130 | } | ||
131 | |||
132 | } | ||
133 | |||
134 | static void | ||
135 | bfa_fcs_itnim_sm_prli_send(struct bfa_fcs_itnim_s *itnim, | ||
136 | enum bfa_fcs_itnim_event event) | ||
137 | { | ||
138 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
139 | bfa_trc(itnim->fcs, event); | ||
140 | |||
141 | switch (event) { | ||
142 | case BFA_FCS_ITNIM_SM_FRMSENT: | ||
143 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli); | ||
144 | break; | ||
145 | |||
146 | case BFA_FCS_ITNIM_SM_INITIATOR: | ||
147 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); | ||
148 | bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe); | ||
149 | break; | ||
150 | |||
151 | case BFA_FCS_ITNIM_SM_OFFLINE: | ||
152 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
153 | bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe); | ||
154 | bfa_fcs_rport_itnim_ack(itnim->rport); | ||
155 | break; | ||
156 | |||
157 | case BFA_FCS_ITNIM_SM_DELETE: | ||
158 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
159 | bfa_fcxp_walloc_cancel(itnim->fcs->bfa, &itnim->fcxp_wqe); | ||
160 | bfa_fcs_itnim_free(itnim); | ||
161 | break; | ||
162 | |||
163 | default: | ||
164 | bfa_assert(0); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static void | ||
169 | bfa_fcs_itnim_sm_prli(struct bfa_fcs_itnim_s *itnim, | ||
170 | enum bfa_fcs_itnim_event event) | ||
171 | { | ||
172 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
173 | bfa_trc(itnim->fcs, event); | ||
174 | |||
175 | switch (event) { | ||
176 | case BFA_FCS_ITNIM_SM_RSP_OK: | ||
177 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_online); | ||
178 | bfa_itnim_online(itnim->bfa_itnim, itnim->seq_rec); | ||
179 | break; | ||
180 | |||
181 | case BFA_FCS_ITNIM_SM_RSP_ERROR: | ||
182 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_retry); | ||
183 | bfa_timer_start(itnim->fcs->bfa, &itnim->timer, | ||
184 | bfa_fcs_itnim_timeout, itnim, | ||
185 | BFA_FCS_RETRY_TIMEOUT); | ||
186 | break; | ||
187 | |||
188 | case BFA_FCS_ITNIM_SM_OFFLINE: | ||
189 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
190 | bfa_fcxp_discard(itnim->fcxp); | ||
191 | bfa_fcs_rport_itnim_ack(itnim->rport); | ||
192 | break; | ||
193 | |||
194 | case BFA_FCS_ITNIM_SM_INITIATOR: | ||
195 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); | ||
196 | /* | ||
197 | * dont discard fcxp. accept will reach same state | ||
198 | */ | ||
199 | break; | ||
200 | |||
201 | case BFA_FCS_ITNIM_SM_DELETE: | ||
202 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
203 | bfa_fcxp_discard(itnim->fcxp); | ||
204 | bfa_fcs_itnim_free(itnim); | ||
205 | break; | ||
206 | |||
207 | default: | ||
208 | bfa_assert(0); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | static void | ||
213 | bfa_fcs_itnim_sm_prli_retry(struct bfa_fcs_itnim_s *itnim, | ||
214 | enum bfa_fcs_itnim_event event) | ||
215 | { | ||
216 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
217 | bfa_trc(itnim->fcs, event); | ||
218 | |||
219 | switch (event) { | ||
220 | case BFA_FCS_ITNIM_SM_TIMEOUT: | ||
221 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_prli_send); | ||
222 | bfa_fcs_itnim_send_prli(itnim, NULL); | ||
223 | break; | ||
224 | |||
225 | case BFA_FCS_ITNIM_SM_OFFLINE: | ||
226 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
227 | bfa_timer_stop(&itnim->timer); | ||
228 | bfa_fcs_rport_itnim_ack(itnim->rport); | ||
229 | break; | ||
230 | |||
231 | case BFA_FCS_ITNIM_SM_INITIATOR: | ||
232 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_initiator); | ||
233 | bfa_timer_stop(&itnim->timer); | ||
234 | break; | ||
235 | |||
236 | case BFA_FCS_ITNIM_SM_DELETE: | ||
237 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
238 | bfa_timer_stop(&itnim->timer); | ||
239 | bfa_fcs_itnim_free(itnim); | ||
240 | break; | ||
241 | |||
242 | default: | ||
243 | bfa_assert(0); | ||
244 | } | ||
245 | } | ||
246 | |||
247 | static void | ||
248 | bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim, | ||
249 | enum bfa_fcs_itnim_event event) | ||
250 | { | ||
251 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
252 | bfa_trc(itnim->fcs, event); | ||
253 | |||
254 | switch (event) { | ||
255 | case BFA_FCS_ITNIM_SM_HCB_ONLINE: | ||
256 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_online); | ||
257 | bfa_fcb_itnim_online(itnim->itnim_drv); | ||
258 | bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_ONLINE); | ||
259 | break; | ||
260 | |||
261 | case BFA_FCS_ITNIM_SM_OFFLINE: | ||
262 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
263 | bfa_itnim_offline(itnim->bfa_itnim); | ||
264 | bfa_fcs_rport_itnim_ack(itnim->rport); | ||
265 | break; | ||
266 | |||
267 | case BFA_FCS_ITNIM_SM_DELETE: | ||
268 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
269 | bfa_fcs_itnim_free(itnim); | ||
270 | break; | ||
271 | |||
272 | default: | ||
273 | bfa_assert(0); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | static void | ||
278 | bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim, | ||
279 | enum bfa_fcs_itnim_event event) | ||
280 | { | ||
281 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
282 | bfa_trc(itnim->fcs, event); | ||
283 | |||
284 | switch (event) { | ||
285 | case BFA_FCS_ITNIM_SM_OFFLINE: | ||
286 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_hcb_offline); | ||
287 | bfa_fcb_itnim_offline(itnim->itnim_drv); | ||
288 | bfa_itnim_offline(itnim->bfa_itnim); | ||
289 | if (bfa_fcs_port_is_online(itnim->rport->port) == BFA_TRUE) { | ||
290 | bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_DISCONNECT); | ||
291 | } else { | ||
292 | bfa_fcs_itnim_aen_post(itnim, BFA_ITNIM_AEN_OFFLINE); | ||
293 | } | ||
294 | break; | ||
295 | |||
296 | case BFA_FCS_ITNIM_SM_DELETE: | ||
297 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
298 | bfa_fcs_itnim_free(itnim); | ||
299 | break; | ||
300 | |||
301 | default: | ||
302 | bfa_assert(0); | ||
303 | } | ||
304 | } | ||
305 | |||
306 | static void | ||
307 | bfa_fcs_itnim_sm_hcb_offline(struct bfa_fcs_itnim_s *itnim, | ||
308 | enum bfa_fcs_itnim_event event) | ||
309 | { | ||
310 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
311 | bfa_trc(itnim->fcs, event); | ||
312 | |||
313 | switch (event) { | ||
314 | case BFA_FCS_ITNIM_SM_HCB_OFFLINE: | ||
315 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
316 | bfa_fcs_rport_itnim_ack(itnim->rport); | ||
317 | break; | ||
318 | |||
319 | case BFA_FCS_ITNIM_SM_DELETE: | ||
320 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
321 | bfa_fcs_itnim_free(itnim); | ||
322 | break; | ||
323 | |||
324 | default: | ||
325 | bfa_assert(0); | ||
326 | } | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * This state is set when a discovered rport is also in intiator mode. | ||
331 | * This ITN is marked as no_op and is not active and will not be truned into | ||
332 | * online state. | ||
333 | */ | ||
334 | static void | ||
335 | bfa_fcs_itnim_sm_initiator(struct bfa_fcs_itnim_s *itnim, | ||
336 | enum bfa_fcs_itnim_event event) | ||
337 | { | ||
338 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
339 | bfa_trc(itnim->fcs, event); | ||
340 | |||
341 | switch (event) { | ||
342 | case BFA_FCS_ITNIM_SM_OFFLINE: | ||
343 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
344 | bfa_fcs_rport_itnim_ack(itnim->rport); | ||
345 | break; | ||
346 | |||
347 | case BFA_FCS_ITNIM_SM_RSP_ERROR: | ||
348 | case BFA_FCS_ITNIM_SM_ONLINE: | ||
349 | case BFA_FCS_ITNIM_SM_INITIATOR: | ||
350 | break; | ||
351 | |||
352 | case BFA_FCS_ITNIM_SM_DELETE: | ||
353 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
354 | bfa_fcs_itnim_free(itnim); | ||
355 | break; | ||
356 | |||
357 | default: | ||
358 | bfa_assert(0); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | |||
363 | |||
364 | /** | ||
365 | * itnim_private FCS ITNIM private interfaces | ||
366 | */ | ||
367 | |||
368 | static void | ||
369 | bfa_fcs_itnim_aen_post(struct bfa_fcs_itnim_s *itnim, | ||
370 | enum bfa_itnim_aen_event event) | ||
371 | { | ||
372 | struct bfa_fcs_rport_s *rport = itnim->rport; | ||
373 | union bfa_aen_data_u aen_data; | ||
374 | struct bfa_log_mod_s *logmod = rport->fcs->logm; | ||
375 | wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port); | ||
376 | wwn_t rpwwn = rport->pwwn; | ||
377 | char lpwwn_ptr[BFA_STRING_32]; | ||
378 | char rpwwn_ptr[BFA_STRING_32]; | ||
379 | |||
380 | /* | ||
381 | * Don't post events for well known addresses | ||
382 | */ | ||
383 | if (BFA_FCS_PID_IS_WKA(rport->pid)) | ||
384 | return; | ||
385 | |||
386 | wwn2str(lpwwn_ptr, lpwwn); | ||
387 | wwn2str(rpwwn_ptr, rpwwn); | ||
388 | |||
389 | switch (event) { | ||
390 | case BFA_ITNIM_AEN_ONLINE: | ||
391 | bfa_log(logmod, BFA_AEN_ITNIM_ONLINE, rpwwn_ptr, lpwwn_ptr); | ||
392 | break; | ||
393 | case BFA_ITNIM_AEN_OFFLINE: | ||
394 | bfa_log(logmod, BFA_AEN_ITNIM_OFFLINE, rpwwn_ptr, lpwwn_ptr); | ||
395 | break; | ||
396 | case BFA_ITNIM_AEN_DISCONNECT: | ||
397 | bfa_log(logmod, BFA_AEN_ITNIM_DISCONNECT, rpwwn_ptr, lpwwn_ptr); | ||
398 | break; | ||
399 | default: | ||
400 | break; | ||
401 | } | ||
402 | |||
403 | aen_data.itnim.vf_id = rport->port->fabric->vf_id; | ||
404 | aen_data.itnim.ppwwn = | ||
405 | bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(itnim->fcs)); | ||
406 | aen_data.itnim.lpwwn = lpwwn; | ||
407 | aen_data.itnim.rpwwn = rpwwn; | ||
408 | } | ||
409 | |||
410 | static void | ||
411 | bfa_fcs_itnim_send_prli(void *itnim_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
412 | { | ||
413 | struct bfa_fcs_itnim_s *itnim = itnim_cbarg; | ||
414 | struct bfa_fcs_rport_s *rport = itnim->rport; | ||
415 | struct bfa_fcs_port_s *port = rport->port; | ||
416 | struct fchs_s fchs; | ||
417 | struct bfa_fcxp_s *fcxp; | ||
418 | int len; | ||
419 | |||
420 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
421 | |||
422 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
423 | if (!fcxp) { | ||
424 | itnim->stats.fcxp_alloc_wait++; | ||
425 | bfa_fcxp_alloc_wait(port->fcs->bfa, &itnim->fcxp_wqe, | ||
426 | bfa_fcs_itnim_send_prli, itnim); | ||
427 | return; | ||
428 | } | ||
429 | itnim->fcxp = fcxp; | ||
430 | |||
431 | len = fc_prli_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), itnim->rport->pid, | ||
432 | bfa_fcs_port_get_fcid(port), 0); | ||
433 | |||
434 | bfa_fcxp_send(fcxp, rport->bfa_rport, port->fabric->vf_id, port->lp_tag, | ||
435 | BFA_FALSE, FC_CLASS_3, len, &fchs, | ||
436 | bfa_fcs_itnim_prli_response, (void *)itnim, FC_MAX_PDUSZ, | ||
437 | FC_RA_TOV); | ||
438 | |||
439 | itnim->stats.prli_sent++; | ||
440 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_FRMSENT); | ||
441 | } | ||
442 | |||
443 | static void | ||
444 | bfa_fcs_itnim_prli_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
445 | bfa_status_t req_status, u32 rsp_len, | ||
446 | u32 resid_len, struct fchs_s *rsp_fchs) | ||
447 | { | ||
448 | struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg; | ||
449 | struct fc_els_cmd_s *els_cmd; | ||
450 | struct fc_prli_s *prli_resp; | ||
451 | struct fc_ls_rjt_s *ls_rjt; | ||
452 | struct fc_prli_params_s *sparams; | ||
453 | |||
454 | bfa_trc(itnim->fcs, req_status); | ||
455 | |||
456 | /* | ||
457 | * Sanity Checks | ||
458 | */ | ||
459 | if (req_status != BFA_STATUS_OK) { | ||
460 | itnim->stats.prli_rsp_err++; | ||
461 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR); | ||
462 | return; | ||
463 | } | ||
464 | |||
465 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
466 | |||
467 | if (els_cmd->els_code == FC_ELS_ACC) { | ||
468 | prli_resp = (struct fc_prli_s *) els_cmd; | ||
469 | |||
470 | if (fc_prli_rsp_parse(prli_resp, rsp_len) != FC_PARSE_OK) { | ||
471 | bfa_trc(itnim->fcs, rsp_len); | ||
472 | /* | ||
473 | * Check if this r-port is also in Initiator mode. | ||
474 | * If so, we need to set this ITN as a no-op. | ||
475 | */ | ||
476 | if (prli_resp->parampage.servparams.initiator) { | ||
477 | bfa_trc(itnim->fcs, prli_resp->parampage.type); | ||
478 | itnim->rport->scsi_function = | ||
479 | BFA_RPORT_INITIATOR; | ||
480 | itnim->stats.prli_rsp_acc++; | ||
481 | bfa_sm_send_event(itnim, | ||
482 | BFA_FCS_ITNIM_SM_INITIATOR); | ||
483 | return; | ||
484 | } | ||
485 | |||
486 | itnim->stats.prli_rsp_parse_err++; | ||
487 | return; | ||
488 | } | ||
489 | itnim->rport->scsi_function = BFA_RPORT_TARGET; | ||
490 | |||
491 | sparams = &prli_resp->parampage.servparams; | ||
492 | itnim->seq_rec = sparams->retry; | ||
493 | itnim->rec_support = sparams->rec_support; | ||
494 | itnim->task_retry_id = sparams->task_retry_id; | ||
495 | itnim->conf_comp = sparams->confirm; | ||
496 | |||
497 | itnim->stats.prli_rsp_acc++; | ||
498 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_OK); | ||
499 | } else { | ||
500 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
501 | |||
502 | bfa_trc(itnim->fcs, ls_rjt->reason_code); | ||
503 | bfa_trc(itnim->fcs, ls_rjt->reason_code_expl); | ||
504 | |||
505 | itnim->stats.prli_rsp_rjt++; | ||
506 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_RSP_ERROR); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | static void | ||
511 | bfa_fcs_itnim_timeout(void *arg) | ||
512 | { | ||
513 | struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)arg; | ||
514 | |||
515 | itnim->stats.timeout++; | ||
516 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_TIMEOUT); | ||
517 | } | ||
518 | |||
519 | static void | ||
520 | bfa_fcs_itnim_free(struct bfa_fcs_itnim_s *itnim) | ||
521 | { | ||
522 | bfa_itnim_delete(itnim->bfa_itnim); | ||
523 | bfa_fcb_itnim_free(itnim->fcs->bfad, itnim->itnim_drv); | ||
524 | } | ||
525 | |||
526 | |||
527 | |||
528 | /** | ||
529 | * itnim_public FCS ITNIM public interfaces | ||
530 | */ | ||
531 | |||
532 | /** | ||
533 | * Called by rport when a new rport is created. | ||
534 | * | ||
535 | * @param[in] rport - remote port. | ||
536 | */ | ||
537 | struct bfa_fcs_itnim_s * | ||
538 | bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport) | ||
539 | { | ||
540 | struct bfa_fcs_port_s *port = rport->port; | ||
541 | struct bfa_fcs_itnim_s *itnim; | ||
542 | struct bfad_itnim_s *itnim_drv; | ||
543 | struct bfa_itnim_s *bfa_itnim; | ||
544 | |||
545 | /* | ||
546 | * call bfad to allocate the itnim | ||
547 | */ | ||
548 | bfa_fcb_itnim_alloc(port->fcs->bfad, &itnim, &itnim_drv); | ||
549 | if (itnim == NULL) { | ||
550 | bfa_trc(port->fcs, rport->pwwn); | ||
551 | return NULL; | ||
552 | } | ||
553 | |||
554 | /* | ||
555 | * Initialize itnim | ||
556 | */ | ||
557 | itnim->rport = rport; | ||
558 | itnim->fcs = rport->fcs; | ||
559 | itnim->itnim_drv = itnim_drv; | ||
560 | |||
561 | /* | ||
562 | * call BFA to create the itnim | ||
563 | */ | ||
564 | bfa_itnim = bfa_itnim_create(port->fcs->bfa, rport->bfa_rport, itnim); | ||
565 | |||
566 | if (bfa_itnim == NULL) { | ||
567 | bfa_trc(port->fcs, rport->pwwn); | ||
568 | bfa_fcb_itnim_free(port->fcs->bfad, itnim_drv); | ||
569 | bfa_assert(0); | ||
570 | return NULL; | ||
571 | } | ||
572 | |||
573 | itnim->bfa_itnim = bfa_itnim; | ||
574 | itnim->seq_rec = BFA_FALSE; | ||
575 | itnim->rec_support = BFA_FALSE; | ||
576 | itnim->conf_comp = BFA_FALSE; | ||
577 | itnim->task_retry_id = BFA_FALSE; | ||
578 | |||
579 | /* | ||
580 | * Set State machine | ||
581 | */ | ||
582 | bfa_sm_set_state(itnim, bfa_fcs_itnim_sm_offline); | ||
583 | |||
584 | return itnim; | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * Called by rport to delete the instance of FCPIM. | ||
589 | * | ||
590 | * @param[in] rport - remote port. | ||
591 | */ | ||
592 | void | ||
593 | bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim) | ||
594 | { | ||
595 | bfa_trc(itnim->fcs, itnim->rport->pid); | ||
596 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_DELETE); | ||
597 | } | ||
598 | |||
599 | /** | ||
600 | * Notification from rport that PLOGI is complete to initiate FC-4 session. | ||
601 | */ | ||
602 | void | ||
603 | bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim) | ||
604 | { | ||
605 | itnim->stats.onlines++; | ||
606 | |||
607 | if (!BFA_FCS_PID_IS_WKA(itnim->rport->pid)) { | ||
608 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_ONLINE); | ||
609 | } else { | ||
610 | /* | ||
611 | * For well known addresses, we set the itnim to initiator | ||
612 | * state | ||
613 | */ | ||
614 | itnim->stats.initiator++; | ||
615 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * Called by rport to handle a remote device offline. | ||
621 | */ | ||
622 | void | ||
623 | bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim) | ||
624 | { | ||
625 | itnim->stats.offlines++; | ||
626 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_OFFLINE); | ||
627 | } | ||
628 | |||
629 | /** | ||
630 | * Called by rport when remote port is known to be an initiator from | ||
631 | * PRLI received. | ||
632 | */ | ||
633 | void | ||
634 | bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim) | ||
635 | { | ||
636 | bfa_trc(itnim->fcs, itnim->rport->pid); | ||
637 | itnim->stats.initiator++; | ||
638 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_INITIATOR); | ||
639 | } | ||
640 | |||
641 | /** | ||
642 | * Called by rport to check if the itnim is online. | ||
643 | */ | ||
644 | bfa_status_t | ||
645 | bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim) | ||
646 | { | ||
647 | bfa_trc(itnim->fcs, itnim->rport->pid); | ||
648 | switch (bfa_sm_to_state(itnim_sm_table, itnim->sm)) { | ||
649 | case BFA_ITNIM_ONLINE: | ||
650 | case BFA_ITNIM_INITIATIOR: | ||
651 | return BFA_STATUS_OK; | ||
652 | |||
653 | default: | ||
654 | return BFA_STATUS_NO_FCPIM_NEXUS; | ||
655 | |||
656 | } | ||
657 | } | ||
658 | |||
659 | /** | ||
660 | * BFA completion callback for bfa_itnim_online(). | ||
661 | */ | ||
662 | void | ||
663 | bfa_cb_itnim_online(void *cbarg) | ||
664 | { | ||
665 | struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cbarg; | ||
666 | |||
667 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
668 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_ONLINE); | ||
669 | } | ||
670 | |||
671 | /** | ||
672 | * BFA completion callback for bfa_itnim_offline(). | ||
673 | */ | ||
674 | void | ||
675 | bfa_cb_itnim_offline(void *cb_arg) | ||
676 | { | ||
677 | struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg; | ||
678 | |||
679 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
680 | bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_HCB_OFFLINE); | ||
681 | } | ||
682 | |||
683 | /** | ||
684 | * Mark the beginning of PATH TOV handling. IO completion callbacks | ||
685 | * are still pending. | ||
686 | */ | ||
687 | void | ||
688 | bfa_cb_itnim_tov_begin(void *cb_arg) | ||
689 | { | ||
690 | struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg; | ||
691 | |||
692 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
693 | bfa_fcb_itnim_tov_begin(itnim->itnim_drv); | ||
694 | } | ||
695 | |||
696 | /** | ||
697 | * Mark the end of PATH TOV handling. All pending IOs are already cleaned up. | ||
698 | */ | ||
699 | void | ||
700 | bfa_cb_itnim_tov(void *cb_arg) | ||
701 | { | ||
702 | struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg; | ||
703 | |||
704 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
705 | bfa_fcb_itnim_tov(itnim->itnim_drv); | ||
706 | } | ||
707 | |||
708 | /** | ||
709 | * BFA notification to FCS/driver for second level error recovery. | ||
710 | * | ||
711 | * Atleast one I/O request has timedout and target is unresponsive to | ||
712 | * repeated abort requests. Second level error recovery should be initiated | ||
713 | * by starting implicit logout and recovery procedures. | ||
714 | */ | ||
715 | void | ||
716 | bfa_cb_itnim_sler(void *cb_arg) | ||
717 | { | ||
718 | struct bfa_fcs_itnim_s *itnim = (struct bfa_fcs_itnim_s *)cb_arg; | ||
719 | |||
720 | itnim->stats.sler++; | ||
721 | bfa_trc(itnim->fcs, itnim->rport->pwwn); | ||
722 | bfa_fcs_rport_logo_imp(itnim->rport); | ||
723 | } | ||
724 | |||
725 | struct bfa_fcs_itnim_s * | ||
726 | bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn) | ||
727 | { | ||
728 | struct bfa_fcs_rport_s *rport; | ||
729 | rport = bfa_fcs_rport_lookup(port, rpwwn); | ||
730 | |||
731 | if (!rport) | ||
732 | return NULL; | ||
733 | |||
734 | bfa_assert(rport->itnim != NULL); | ||
735 | return (rport->itnim); | ||
736 | } | ||
737 | |||
738 | bfa_status_t | ||
739 | bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn, | ||
740 | struct bfa_itnim_attr_s *attr) | ||
741 | { | ||
742 | struct bfa_fcs_itnim_s *itnim = NULL; | ||
743 | |||
744 | itnim = bfa_fcs_itnim_lookup(port, rpwwn); | ||
745 | |||
746 | if (itnim == NULL) | ||
747 | return BFA_STATUS_NO_FCPIM_NEXUS; | ||
748 | |||
749 | attr->state = bfa_sm_to_state(itnim_sm_table, itnim->sm); | ||
750 | attr->retry = itnim->seq_rec; | ||
751 | attr->rec_support = itnim->rec_support; | ||
752 | attr->conf_comp = itnim->conf_comp; | ||
753 | attr->task_retry_id = itnim->task_retry_id; | ||
754 | |||
755 | return BFA_STATUS_OK; | ||
756 | } | ||
757 | |||
758 | bfa_status_t | ||
759 | bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn, | ||
760 | struct bfa_itnim_stats_s *stats) | ||
761 | { | ||
762 | struct bfa_fcs_itnim_s *itnim = NULL; | ||
763 | |||
764 | bfa_assert(port != NULL); | ||
765 | |||
766 | itnim = bfa_fcs_itnim_lookup(port, rpwwn); | ||
767 | |||
768 | if (itnim == NULL) | ||
769 | return BFA_STATUS_NO_FCPIM_NEXUS; | ||
770 | |||
771 | bfa_os_memcpy(stats, &itnim->stats, sizeof(struct bfa_itnim_stats_s)); | ||
772 | |||
773 | return BFA_STATUS_OK; | ||
774 | } | ||
775 | |||
776 | bfa_status_t | ||
777 | bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, wwn_t rpwwn) | ||
778 | { | ||
779 | struct bfa_fcs_itnim_s *itnim = NULL; | ||
780 | |||
781 | bfa_assert(port != NULL); | ||
782 | |||
783 | itnim = bfa_fcs_itnim_lookup(port, rpwwn); | ||
784 | |||
785 | if (itnim == NULL) | ||
786 | return BFA_STATUS_NO_FCPIM_NEXUS; | ||
787 | |||
788 | bfa_os_memset(&itnim->stats, 0, sizeof(struct bfa_itnim_stats_s)); | ||
789 | return BFA_STATUS_OK; | ||
790 | } | ||
791 | |||
792 | void | ||
793 | bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs, | ||
794 | u16 len) | ||
795 | { | ||
796 | struct fc_els_cmd_s *els_cmd; | ||
797 | |||
798 | bfa_trc(itnim->fcs, fchs->type); | ||
799 | |||
800 | if (fchs->type != FC_TYPE_ELS) | ||
801 | return; | ||
802 | |||
803 | els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
804 | |||
805 | bfa_trc(itnim->fcs, els_cmd->els_code); | ||
806 | |||
807 | switch (els_cmd->els_code) { | ||
808 | case FC_ELS_PRLO: | ||
809 | /* bfa_sm_send_event(itnim, BFA_FCS_ITNIM_SM_PRLO); */ | ||
810 | break; | ||
811 | |||
812 | default: | ||
813 | bfa_assert(0); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | void | ||
818 | bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim) | ||
819 | { | ||
820 | } | ||
821 | |||
822 | void | ||
823 | bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim) | ||
824 | { | ||
825 | } | ||
826 | |||
827 | /** | ||
828 | * Module initialization | ||
829 | */ | ||
830 | void | ||
831 | bfa_fcs_fcpim_modinit(struct bfa_fcs_s *fcs) | ||
832 | { | ||
833 | } | ||
834 | |||
835 | /** | ||
836 | * Module cleanup | ||
837 | */ | ||
838 | void | ||
839 | bfa_fcs_fcpim_modexit(struct bfa_fcs_s *fcs) | ||
840 | { | ||
841 | bfa_fcs_modexit_comp(fcs); | ||
842 | } | ||
843 | |||
844 | |||
diff --git a/drivers/scsi/bfa/fcptm.c b/drivers/scsi/bfa/fcptm.c new file mode 100644 index 000000000000..8c8b08c72e7a --- /dev/null +++ b/drivers/scsi/bfa/fcptm.c | |||
@@ -0,0 +1,68 @@ | |||
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 | * This file contains dummy FCPTM routines to aid in Initiator Mode only | ||
20 | * compilation of OS driver. | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include "bfa_os_inc.h" | ||
25 | #include "fcs_rport.h" | ||
26 | #include "fcs_fcptm.h" | ||
27 | #include "fcs/bfa_fcs_rport.h" | ||
28 | |||
29 | struct bfa_fcs_tin_s * | ||
30 | bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport) | ||
31 | { | ||
32 | return NULL; | ||
33 | } | ||
34 | |||
35 | void | ||
36 | bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin) | ||
37 | { | ||
38 | } | ||
39 | |||
40 | void | ||
41 | bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin) | ||
42 | { | ||
43 | } | ||
44 | |||
45 | void | ||
46 | bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | void | ||
51 | bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len) | ||
52 | { | ||
53 | } | ||
54 | |||
55 | void | ||
56 | bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, u16 len) | ||
57 | { | ||
58 | } | ||
59 | |||
60 | void | ||
61 | bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin) | ||
62 | { | ||
63 | } | ||
64 | |||
65 | void | ||
66 | bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin) | ||
67 | { | ||
68 | } | ||
diff --git a/drivers/scsi/bfa/fcs.h b/drivers/scsi/bfa/fcs.h new file mode 100644 index 000000000000..deee685e8478 --- /dev/null +++ b/drivers/scsi/bfa/fcs.h | |||
@@ -0,0 +1,30 @@ | |||
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 | * fcs.h FCS module functions | ||
20 | */ | ||
21 | |||
22 | |||
23 | #ifndef __FCS_H__ | ||
24 | #define __FCS_H__ | ||
25 | |||
26 | #define __fcs_min_cfg(__fcs) (__fcs)->min_cfg | ||
27 | |||
28 | void bfa_fcs_modexit_comp(struct bfa_fcs_s *fcs); | ||
29 | |||
30 | #endif /* __FCS_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_auth.h b/drivers/scsi/bfa/fcs_auth.h new file mode 100644 index 000000000000..65d155fea3d7 --- /dev/null +++ b/drivers/scsi/bfa/fcs_auth.h | |||
@@ -0,0 +1,37 @@ | |||
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 | * fcs_uf.h FCS unsolicited frame receive | ||
20 | */ | ||
21 | |||
22 | |||
23 | #ifndef __FCS_AUTH_H__ | ||
24 | #define __FCS_AUTH_H__ | ||
25 | |||
26 | #include <fcs/bfa_fcs.h> | ||
27 | #include <fcs/bfa_fcs_vport.h> | ||
28 | #include <fcs/bfa_fcs_lport.h> | ||
29 | |||
30 | /* | ||
31 | * fcs friend functions: only between fcs modules | ||
32 | */ | ||
33 | void bfa_fcs_auth_uf_recv(struct bfa_fcs_fabric_s *fabric, int len); | ||
34 | void bfa_fcs_auth_start(struct bfa_fcs_fabric_s *fabric); | ||
35 | void bfa_fcs_auth_stop(struct bfa_fcs_fabric_s *fabric); | ||
36 | |||
37 | #endif /* __FCS_UF_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_fabric.h b/drivers/scsi/bfa/fcs_fabric.h new file mode 100644 index 000000000000..eee960820f86 --- /dev/null +++ b/drivers/scsi/bfa/fcs_fabric.h | |||
@@ -0,0 +1,61 @@ | |||
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 | * fcs_lport.h FCS logical port interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __FCS_FABRIC_H__ | ||
23 | #define __FCS_FABRIC_H__ | ||
24 | |||
25 | #include <fcs/bfa_fcs.h> | ||
26 | #include <fcs/bfa_fcs_vport.h> | ||
27 | #include <fcs/bfa_fcs_lport.h> | ||
28 | |||
29 | /* | ||
30 | * fcs friend functions: only between fcs modules | ||
31 | */ | ||
32 | void bfa_fcs_fabric_modinit(struct bfa_fcs_s *fcs); | ||
33 | void bfa_fcs_fabric_modexit(struct bfa_fcs_s *fcs); | ||
34 | void bfa_fcs_fabric_modsusp(struct bfa_fcs_s *fcs); | ||
35 | void bfa_fcs_fabric_link_up(struct bfa_fcs_fabric_s *fabric); | ||
36 | void bfa_fcs_fabric_link_down(struct bfa_fcs_fabric_s *fabric); | ||
37 | void bfa_fcs_fabric_addvport(struct bfa_fcs_fabric_s *fabric, | ||
38 | struct bfa_fcs_vport_s *vport); | ||
39 | void bfa_fcs_fabric_delvport(struct bfa_fcs_fabric_s *fabric, | ||
40 | struct bfa_fcs_vport_s *vport); | ||
41 | int bfa_fcs_fabric_is_online(struct bfa_fcs_fabric_s *fabric); | ||
42 | struct bfa_fcs_vport_s *bfa_fcs_fabric_vport_lookup( | ||
43 | struct bfa_fcs_fabric_s *fabric, wwn_t pwwn); | ||
44 | void bfa_fcs_fabric_modstart(struct bfa_fcs_s *fcs); | ||
45 | void bfa_fcs_fabric_uf_recv(struct bfa_fcs_fabric_s *fabric, | ||
46 | struct fchs_s *fchs, u16 len); | ||
47 | u16 bfa_fcs_fabric_vport_count(struct bfa_fcs_fabric_s *fabric); | ||
48 | bfa_boolean_t bfa_fcs_fabric_is_loopback(struct bfa_fcs_fabric_s *fabric); | ||
49 | enum bfa_pport_type bfa_fcs_fabric_port_type(struct bfa_fcs_fabric_s *fabric); | ||
50 | void bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric); | ||
51 | void bfa_fcs_fabric_port_delete_comp(struct bfa_fcs_fabric_s *fabric); | ||
52 | |||
53 | bfa_status_t bfa_fcs_fabric_addvf(struct bfa_fcs_fabric_s *vf, | ||
54 | struct bfa_fcs_s *fcs, struct bfa_port_cfg_s *port_cfg, | ||
55 | struct bfad_vf_s *vf_drv); | ||
56 | void bfa_fcs_auth_finished(struct bfa_fcs_fabric_s *fabric, | ||
57 | enum auth_status status); | ||
58 | |||
59 | void bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric, | ||
60 | wwn_t fabric_name); | ||
61 | #endif /* __FCS_FABRIC_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_fcpim.h b/drivers/scsi/bfa/fcs_fcpim.h new file mode 100644 index 000000000000..61e9e2687de3 --- /dev/null +++ b/drivers/scsi/bfa/fcs_fcpim.h | |||
@@ -0,0 +1,44 @@ | |||
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 | #ifndef __FCS_FCPIM_H__ | ||
18 | #define __FCS_FCPIM_H__ | ||
19 | |||
20 | #include <defs/bfa_defs_port.h> | ||
21 | #include <fcs/bfa_fcs_lport.h> | ||
22 | #include <fcs/bfa_fcs_rport.h> | ||
23 | |||
24 | /* | ||
25 | * Following routines are from FCPIM and will be called by rport. | ||
26 | */ | ||
27 | struct bfa_fcs_itnim_s *bfa_fcs_itnim_create(struct bfa_fcs_rport_s *rport); | ||
28 | void bfa_fcs_itnim_delete(struct bfa_fcs_itnim_s *itnim); | ||
29 | void bfa_fcs_itnim_rport_offline(struct bfa_fcs_itnim_s *itnim); | ||
30 | void bfa_fcs_itnim_rport_online(struct bfa_fcs_itnim_s *itnim); | ||
31 | bfa_status_t bfa_fcs_itnim_get_online_state(struct bfa_fcs_itnim_s *itnim); | ||
32 | |||
33 | void bfa_fcs_itnim_is_initiator(struct bfa_fcs_itnim_s *itnim); | ||
34 | void bfa_fcs_itnim_pause(struct bfa_fcs_itnim_s *itnim); | ||
35 | void bfa_fcs_itnim_resume(struct bfa_fcs_itnim_s *itnim); | ||
36 | |||
37 | /* | ||
38 | * Modudle init/cleanup routines. | ||
39 | */ | ||
40 | void bfa_fcs_fcpim_modinit(struct bfa_fcs_s *fcs); | ||
41 | void bfa_fcs_fcpim_modexit(struct bfa_fcs_s *fcs); | ||
42 | void bfa_fcs_fcpim_uf_recv(struct bfa_fcs_itnim_s *itnim, struct fchs_s *fchs, | ||
43 | u16 len); | ||
44 | #endif /* __FCS_FCPIM_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_fcptm.h b/drivers/scsi/bfa/fcs_fcptm.h new file mode 100644 index 000000000000..ffff0829fd31 --- /dev/null +++ b/drivers/scsi/bfa/fcs_fcptm.h | |||
@@ -0,0 +1,45 @@ | |||
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 | #ifndef __FCS_FCPTM_H__ | ||
19 | #define __FCS_FCPTM_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_port.h> | ||
22 | #include <fcs/bfa_fcs_lport.h> | ||
23 | #include <fcs/bfa_fcs_rport.h> | ||
24 | |||
25 | /* | ||
26 | * Following routines are from FCPTM and will be called by rport. | ||
27 | */ | ||
28 | struct bfa_fcs_tin_s *bfa_fcs_tin_create(struct bfa_fcs_rport_s *rport); | ||
29 | void bfa_fcs_tin_rport_offline(struct bfa_fcs_tin_s *tin); | ||
30 | void bfa_fcs_tin_rport_online(struct bfa_fcs_tin_s *tin); | ||
31 | void bfa_fcs_tin_delete(struct bfa_fcs_tin_s *tin); | ||
32 | void bfa_fcs_tin_rx_prli(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, | ||
33 | u16 len); | ||
34 | void bfa_fcs_tin_pause(struct bfa_fcs_tin_s *tin); | ||
35 | void bfa_fcs_tin_resume(struct bfa_fcs_tin_s *tin); | ||
36 | |||
37 | /* | ||
38 | * Modudle init/cleanup routines. | ||
39 | */ | ||
40 | void bfa_fcs_fcptm_modinit(struct bfa_fcs_s *fcs); | ||
41 | void bfa_fcs_fcptm_modexit(struct bfa_fcs_s *fcs); | ||
42 | void bfa_fcs_fcptm_uf_recv(struct bfa_fcs_tin_s *tin, struct fchs_s *fchs, | ||
43 | u16 len); | ||
44 | |||
45 | #endif /* __FCS_FCPTM_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_fcxp.h b/drivers/scsi/bfa/fcs_fcxp.h new file mode 100644 index 000000000000..8277fe9c2b70 --- /dev/null +++ b/drivers/scsi/bfa/fcs_fcxp.h | |||
@@ -0,0 +1,29 @@ | |||
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 | * fcs_fcxp.h FCXP helper macros for FCS | ||
20 | */ | ||
21 | |||
22 | |||
23 | #ifndef __FCS_FCXP_H__ | ||
24 | #define __FCS_FCXP_H__ | ||
25 | |||
26 | #define bfa_fcs_fcxp_alloc(__fcs) \ | ||
27 | bfa_fcxp_alloc(NULL, (__fcs)->bfa, 0, 0, NULL, NULL, NULL, NULL) | ||
28 | |||
29 | #endif /* __FCS_FCXP_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_lport.h b/drivers/scsi/bfa/fcs_lport.h new file mode 100644 index 000000000000..ae744ba35671 --- /dev/null +++ b/drivers/scsi/bfa/fcs_lport.h | |||
@@ -0,0 +1,117 @@ | |||
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 | * fcs_lport.h FCS logical port interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __FCS_LPORT_H__ | ||
23 | #define __FCS_LPORT_H__ | ||
24 | |||
25 | #define __VPORT_H__ | ||
26 | #include <defs/bfa_defs_port.h> | ||
27 | #include <bfa_svc.h> | ||
28 | #include <fcs/bfa_fcs_lport.h> | ||
29 | #include <fcs/bfa_fcs_rport.h> | ||
30 | #include <fcs/bfa_fcs_vport.h> | ||
31 | #include <fcs_fabric.h> | ||
32 | #include <fcs_ms.h> | ||
33 | #include <cs/bfa_q.h> | ||
34 | #include <fcbuild.h> | ||
35 | |||
36 | /* | ||
37 | * PID used in P2P/N2N ( In Big Endian) | ||
38 | */ | ||
39 | #define N2N_LOCAL_PID 0x010000 | ||
40 | #define N2N_REMOTE_PID 0x020000 | ||
41 | |||
42 | /* | ||
43 | * Misc Timeouts | ||
44 | */ | ||
45 | /* | ||
46 | * To be used when spawning a timer before retrying a failed command. Milli | ||
47 | * Secs. | ||
48 | */ | ||
49 | #define BFA_FCS_RETRY_TIMEOUT 2000 | ||
50 | |||
51 | /* | ||
52 | * Check for Port/Vport Mode/Role | ||
53 | */ | ||
54 | #define BFA_FCS_VPORT_IS_INITIATOR_MODE(port) \ | ||
55 | (port->port_cfg.roles & BFA_PORT_ROLE_FCP_IM) | ||
56 | |||
57 | #define BFA_FCS_VPORT_IS_TARGET_MODE(port) \ | ||
58 | (port->port_cfg.roles & BFA_PORT_ROLE_FCP_TM) | ||
59 | |||
60 | #define BFA_FCS_VPORT_IS_IPFC_MODE(port) \ | ||
61 | (port->port_cfg.roles & BFA_PORT_ROLE_FCP_IPFC) | ||
62 | |||
63 | /* | ||
64 | * Is this a Well Known Address | ||
65 | */ | ||
66 | #define BFA_FCS_PID_IS_WKA(pid) ((bfa_os_ntoh3b(pid) > 0xFFF000) ? 1 : 0) | ||
67 | |||
68 | /* | ||
69 | * Pointer to elements within Port | ||
70 | */ | ||
71 | #define BFA_FCS_GET_HAL_FROM_PORT(port) (port->fcs->bfa) | ||
72 | #define BFA_FCS_GET_NS_FROM_PORT(port) (&port->port_topo.pfab.ns) | ||
73 | #define BFA_FCS_GET_SCN_FROM_PORT(port) (&port->port_topo.pfab.scn) | ||
74 | #define BFA_FCS_GET_MS_FROM_PORT(port) (&port->port_topo.pfab.ms) | ||
75 | #define BFA_FCS_GET_FDMI_FROM_PORT(port) (&port->port_topo.pfab.ms.fdmi) | ||
76 | |||
77 | /* | ||
78 | * handler for unsolicied frames | ||
79 | */ | ||
80 | void bfa_fcs_port_uf_recv(struct bfa_fcs_port_s *lport, struct fchs_s *fchs, | ||
81 | u16 len); | ||
82 | |||
83 | /* | ||
84 | * Following routines will be called by Fabric to indicate port | ||
85 | * online/offline to vport. | ||
86 | */ | ||
87 | void bfa_fcs_lport_init(struct bfa_fcs_port_s *lport, struct bfa_fcs_s *fcs, | ||
88 | u16 vf_id, struct bfa_port_cfg_s *port_cfg, | ||
89 | struct bfa_fcs_vport_s *vport); | ||
90 | void bfa_fcs_port_online(struct bfa_fcs_port_s *port); | ||
91 | void bfa_fcs_port_offline(struct bfa_fcs_port_s *port); | ||
92 | void bfa_fcs_port_delete(struct bfa_fcs_port_s *port); | ||
93 | bfa_boolean_t bfa_fcs_port_is_online(struct bfa_fcs_port_s *port); | ||
94 | |||
95 | /* | ||
96 | * Lookup rport based on PID | ||
97 | */ | ||
98 | struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pid( | ||
99 | struct bfa_fcs_port_s *port, u32 pid); | ||
100 | |||
101 | /* | ||
102 | * Lookup rport based on PWWN | ||
103 | */ | ||
104 | struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_pwwn( | ||
105 | struct bfa_fcs_port_s *port, wwn_t pwwn); | ||
106 | struct bfa_fcs_rport_s *bfa_fcs_port_get_rport_by_nwwn( | ||
107 | struct bfa_fcs_port_s *port, wwn_t nwwn); | ||
108 | void bfa_fcs_port_add_rport(struct bfa_fcs_port_s *port, | ||
109 | struct bfa_fcs_rport_s *rport); | ||
110 | void bfa_fcs_port_del_rport(struct bfa_fcs_port_s *port, | ||
111 | struct bfa_fcs_rport_s *rport); | ||
112 | |||
113 | void bfa_fcs_port_modinit(struct bfa_fcs_s *fcs); | ||
114 | void bfa_fcs_port_modexit(struct bfa_fcs_s *fcs); | ||
115 | void bfa_fcs_port_lip(struct bfa_fcs_port_s *port); | ||
116 | |||
117 | #endif /* __FCS_LPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_ms.h b/drivers/scsi/bfa/fcs_ms.h new file mode 100644 index 000000000000..b6a8c12876f4 --- /dev/null +++ b/drivers/scsi/bfa/fcs_ms.h | |||
@@ -0,0 +1,35 @@ | |||
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 | * fcs_ms.h FCS ms interfaces | ||
20 | */ | ||
21 | #ifndef __FCS_MS_H__ | ||
22 | #define __FCS_MS_H__ | ||
23 | |||
24 | /* MS FCS routines */ | ||
25 | void bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port); | ||
26 | void bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port); | ||
27 | void bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port); | ||
28 | void bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port); | ||
29 | |||
30 | /* FDMI FCS routines */ | ||
31 | void bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms); | ||
32 | void bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms); | ||
33 | void bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms); | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/scsi/bfa/fcs_port.h b/drivers/scsi/bfa/fcs_port.h new file mode 100644 index 000000000000..abb65191dd27 --- /dev/null +++ b/drivers/scsi/bfa/fcs_port.h | |||
@@ -0,0 +1,32 @@ | |||
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 | * fcs_pport.h FCS physical port interfaces | ||
20 | */ | ||
21 | |||
22 | |||
23 | #ifndef __FCS_PPORT_H__ | ||
24 | #define __FCS_PPORT_H__ | ||
25 | |||
26 | /* | ||
27 | * fcs friend functions: only between fcs modules | ||
28 | */ | ||
29 | void bfa_fcs_pport_modinit(struct bfa_fcs_s *fcs); | ||
30 | void bfa_fcs_pport_modexit(struct bfa_fcs_s *fcs); | ||
31 | |||
32 | #endif /* __FCS_PPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_rport.h b/drivers/scsi/bfa/fcs_rport.h new file mode 100644 index 000000000000..f601e9d74236 --- /dev/null +++ b/drivers/scsi/bfa/fcs_rport.h | |||
@@ -0,0 +1,61 @@ | |||
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 | * fcs_rport.h FCS rport interfaces and defines | ||
20 | */ | ||
21 | |||
22 | #ifndef __FCS_RPORT_H__ | ||
23 | #define __FCS_RPORT_H__ | ||
24 | |||
25 | #include <fcs/bfa_fcs_rport.h> | ||
26 | |||
27 | void bfa_fcs_rport_modinit(struct bfa_fcs_s *fcs); | ||
28 | void bfa_fcs_rport_modexit(struct bfa_fcs_s *fcs); | ||
29 | |||
30 | void bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, | ||
31 | u16 len); | ||
32 | void bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport); | ||
33 | |||
34 | struct bfa_fcs_rport_s *bfa_fcs_rport_create(struct bfa_fcs_port_s *port, | ||
35 | u32 pid); | ||
36 | void bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport); | ||
37 | void bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport); | ||
38 | void bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport); | ||
39 | void bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *rx_fchs, | ||
40 | struct fc_logi_s *plogi_rsp); | ||
41 | void bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, | ||
42 | struct fchs_s *rx_fchs, | ||
43 | struct fc_logi_s *plogi); | ||
44 | void bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, | ||
45 | struct fc_logi_s *plogi); | ||
46 | void bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport); | ||
47 | void bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport); | ||
48 | void bfa_fcs_rport_itntm_ack(struct bfa_fcs_rport_s *rport); | ||
49 | void bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport); | ||
50 | void bfa_fcs_rport_fcptm_offline_done(struct bfa_fcs_rport_s *rport); | ||
51 | int bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport); | ||
52 | struct bfa_fcs_rport_s *bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, | ||
53 | wwn_t wwn); | ||
54 | |||
55 | |||
56 | /* Rport Features */ | ||
57 | void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport); | ||
58 | void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport); | ||
59 | void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport); | ||
60 | |||
61 | #endif /* __FCS_RPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_trcmod.h b/drivers/scsi/bfa/fcs_trcmod.h new file mode 100644 index 000000000000..41b5ae8d7644 --- /dev/null +++ b/drivers/scsi/bfa/fcs_trcmod.h | |||
@@ -0,0 +1,56 @@ | |||
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 | * fcs_trcmod.h BFA FCS trace modules | ||
20 | */ | ||
21 | |||
22 | #ifndef __FCS_TRCMOD_H__ | ||
23 | #define __FCS_TRCMOD_H__ | ||
24 | |||
25 | #include <cs/bfa_trc.h> | ||
26 | |||
27 | /* | ||
28 | * !!! Only append to the enums defined here to avoid any versioning | ||
29 | * !!! needed between trace utility and driver version | ||
30 | */ | ||
31 | enum { | ||
32 | BFA_TRC_FCS_FABRIC = 1, | ||
33 | BFA_TRC_FCS_VFAPI = 2, | ||
34 | BFA_TRC_FCS_PORT = 3, | ||
35 | BFA_TRC_FCS_VPORT = 4, | ||
36 | BFA_TRC_FCS_VP_API = 5, | ||
37 | BFA_TRC_FCS_VPS = 6, | ||
38 | BFA_TRC_FCS_RPORT = 7, | ||
39 | BFA_TRC_FCS_FCPIM = 8, | ||
40 | BFA_TRC_FCS_FCPTM = 9, | ||
41 | BFA_TRC_FCS_NS = 10, | ||
42 | BFA_TRC_FCS_SCN = 11, | ||
43 | BFA_TRC_FCS_LOOP = 12, | ||
44 | BFA_TRC_FCS_UF = 13, | ||
45 | BFA_TRC_FCS_PPORT = 14, | ||
46 | BFA_TRC_FCS_FCPIP = 15, | ||
47 | BFA_TRC_FCS_PORT_API = 16, | ||
48 | BFA_TRC_FCS_RPORT_API = 17, | ||
49 | BFA_TRC_FCS_AUTH = 18, | ||
50 | BFA_TRC_FCS_N2N = 19, | ||
51 | BFA_TRC_FCS_MS = 20, | ||
52 | BFA_TRC_FCS_FDMI = 21, | ||
53 | BFA_TRC_FCS_RPORT_FTRS = 22, | ||
54 | }; | ||
55 | |||
56 | #endif /* __FCS_TRCMOD_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_uf.h b/drivers/scsi/bfa/fcs_uf.h new file mode 100644 index 000000000000..96f1bdcb31ed --- /dev/null +++ b/drivers/scsi/bfa/fcs_uf.h | |||
@@ -0,0 +1,32 @@ | |||
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 | * fcs_uf.h FCS unsolicited frame receive | ||
20 | */ | ||
21 | |||
22 | |||
23 | #ifndef __FCS_UF_H__ | ||
24 | #define __FCS_UF_H__ | ||
25 | |||
26 | /* | ||
27 | * fcs friend functions: only between fcs modules | ||
28 | */ | ||
29 | void bfa_fcs_uf_modinit(struct bfa_fcs_s *fcs); | ||
30 | void bfa_fcs_uf_modexit(struct bfa_fcs_s *fcs); | ||
31 | |||
32 | #endif /* __FCS_UF_H__ */ | ||
diff --git a/drivers/scsi/bfa/fcs_vport.h b/drivers/scsi/bfa/fcs_vport.h new file mode 100644 index 000000000000..9e80b6a97b7f --- /dev/null +++ b/drivers/scsi/bfa/fcs_vport.h | |||
@@ -0,0 +1,39 @@ | |||
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 | #ifndef __FCS_VPORT_H__ | ||
19 | #define __FCS_VPORT_H__ | ||
20 | |||
21 | #include <fcs/bfa_fcs_lport.h> | ||
22 | #include <fcs/bfa_fcs_vport.h> | ||
23 | #include <defs/bfa_defs_pci.h> | ||
24 | |||
25 | /* | ||
26 | * Modudle init/cleanup routines. | ||
27 | */ | ||
28 | |||
29 | void bfa_fcs_vport_modinit(struct bfa_fcs_s *fcs); | ||
30 | void bfa_fcs_vport_modexit(struct bfa_fcs_s *fcs); | ||
31 | |||
32 | void bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport); | ||
33 | void bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport); | ||
34 | void bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport); | ||
35 | void bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport); | ||
36 | u32 bfa_fcs_vport_get_max(struct bfa_fcs_s *fcs); | ||
37 | |||
38 | #endif /* __FCS_VPORT_H__ */ | ||
39 | |||
diff --git a/drivers/scsi/bfa/fdmi.c b/drivers/scsi/bfa/fdmi.c new file mode 100644 index 000000000000..b845eb272c78 --- /dev/null +++ b/drivers/scsi/bfa/fdmi.c | |||
@@ -0,0 +1,1223 @@ | |||
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 | |||
23 | #include <bfa.h> | ||
24 | #include <bfa_svc.h> | ||
25 | #include "fcs_lport.h" | ||
26 | #include "fcs_rport.h" | ||
27 | #include "lport_priv.h" | ||
28 | #include "fcs_trcmod.h" | ||
29 | #include "fcs_fcxp.h" | ||
30 | #include <fcs/bfa_fcs_fdmi.h> | ||
31 | |||
32 | BFA_TRC_FILE(FCS, FDMI); | ||
33 | |||
34 | #define BFA_FCS_FDMI_CMD_MAX_RETRIES 2 | ||
35 | |||
36 | /* | ||
37 | * forward declarations | ||
38 | */ | ||
39 | static void bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, | ||
40 | struct bfa_fcxp_s *fcxp_alloced); | ||
41 | static void bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, | ||
42 | struct bfa_fcxp_s *fcxp_alloced); | ||
43 | static void bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, | ||
44 | struct bfa_fcxp_s *fcxp_alloced); | ||
45 | static void bfa_fcs_port_fdmi_rhba_response(void *fcsarg, | ||
46 | struct bfa_fcxp_s *fcxp, | ||
47 | void *cbarg, | ||
48 | bfa_status_t req_status, | ||
49 | u32 rsp_len, | ||
50 | u32 resid_len, | ||
51 | struct fchs_s *rsp_fchs); | ||
52 | static void bfa_fcs_port_fdmi_rprt_response(void *fcsarg, | ||
53 | struct bfa_fcxp_s *fcxp, | ||
54 | void *cbarg, | ||
55 | bfa_status_t req_status, | ||
56 | u32 rsp_len, | ||
57 | u32 resid_len, | ||
58 | struct fchs_s *rsp_fchs); | ||
59 | static void bfa_fcs_port_fdmi_rpa_response(void *fcsarg, | ||
60 | struct bfa_fcxp_s *fcxp, | ||
61 | void *cbarg, | ||
62 | bfa_status_t req_status, | ||
63 | u32 rsp_len, | ||
64 | u32 resid_len, | ||
65 | struct fchs_s *rsp_fchs); | ||
66 | static void bfa_fcs_port_fdmi_timeout(void *arg); | ||
67 | static u16 bfa_fcs_port_fdmi_build_rhba_pyld( | ||
68 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | ||
69 | static u16 bfa_fcs_port_fdmi_build_rprt_pyld( | ||
70 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | ||
71 | static u16 bfa_fcs_port_fdmi_build_rpa_pyld( | ||
72 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | ||
73 | static u16 bfa_fcs_port_fdmi_build_portattr_block( | ||
74 | struct bfa_fcs_port_fdmi_s *fdmi, u8 *pyld); | ||
75 | void bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi, | ||
76 | struct bfa_fcs_fdmi_hba_attr_s *hba_attr); | ||
77 | void bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi, | ||
78 | struct bfa_fcs_fdmi_port_attr_s *port_attr); | ||
79 | /** | ||
80 | * fcs_fdmi_sm FCS FDMI state machine | ||
81 | */ | ||
82 | |||
83 | /** | ||
84 | * FDMI State Machine events | ||
85 | */ | ||
86 | enum port_fdmi_event { | ||
87 | FDMISM_EVENT_PORT_ONLINE = 1, | ||
88 | FDMISM_EVENT_PORT_OFFLINE = 2, | ||
89 | FDMISM_EVENT_RSP_OK = 4, | ||
90 | FDMISM_EVENT_RSP_ERROR = 5, | ||
91 | FDMISM_EVENT_TIMEOUT = 6, | ||
92 | FDMISM_EVENT_RHBA_SENT = 7, | ||
93 | FDMISM_EVENT_RPRT_SENT = 8, | ||
94 | FDMISM_EVENT_RPA_SENT = 9, | ||
95 | }; | ||
96 | |||
97 | static void bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi, | ||
98 | enum port_fdmi_event event); | ||
99 | static void bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | ||
100 | enum port_fdmi_event event); | ||
101 | static void bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | ||
102 | enum port_fdmi_event event); | ||
103 | static void bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi, | ||
104 | enum port_fdmi_event event); | ||
105 | static void bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | ||
106 | enum port_fdmi_event event); | ||
107 | static void bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | ||
108 | enum port_fdmi_event event); | ||
109 | static void bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi, | ||
110 | enum port_fdmi_event event); | ||
111 | static void bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | ||
112 | enum port_fdmi_event event); | ||
113 | static void bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | ||
114 | enum port_fdmi_event event); | ||
115 | static void bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi, | ||
116 | enum port_fdmi_event event); | ||
117 | static void bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi, | ||
118 | enum port_fdmi_event event); | ||
119 | /** | ||
120 | * Start in offline state - awaiting MS to send start. | ||
121 | */ | ||
122 | static void | ||
123 | bfa_fcs_port_fdmi_sm_offline(struct bfa_fcs_port_fdmi_s *fdmi, | ||
124 | enum port_fdmi_event event) | ||
125 | { | ||
126 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
127 | |||
128 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
129 | bfa_trc(port->fcs, event); | ||
130 | |||
131 | fdmi->retry_cnt = 0; | ||
132 | |||
133 | switch (event) { | ||
134 | case FDMISM_EVENT_PORT_ONLINE: | ||
135 | if (port->vport) { | ||
136 | /* | ||
137 | * For Vports, register a new port. | ||
138 | */ | ||
139 | bfa_sm_set_state(fdmi, | ||
140 | bfa_fcs_port_fdmi_sm_sending_rprt); | ||
141 | bfa_fcs_port_fdmi_send_rprt(fdmi, NULL); | ||
142 | } else { | ||
143 | /* | ||
144 | * For a base port, we should first register the HBA | ||
145 | * atribute. The HBA attribute also contains the base | ||
146 | * port registration. | ||
147 | */ | ||
148 | bfa_sm_set_state(fdmi, | ||
149 | bfa_fcs_port_fdmi_sm_sending_rhba); | ||
150 | bfa_fcs_port_fdmi_send_rhba(fdmi, NULL); | ||
151 | } | ||
152 | break; | ||
153 | |||
154 | case FDMISM_EVENT_PORT_OFFLINE: | ||
155 | break; | ||
156 | |||
157 | default: | ||
158 | bfa_assert(0); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static void | ||
163 | bfa_fcs_port_fdmi_sm_sending_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | ||
164 | enum port_fdmi_event event) | ||
165 | { | ||
166 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
167 | |||
168 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
169 | bfa_trc(port->fcs, event); | ||
170 | |||
171 | switch (event) { | ||
172 | case FDMISM_EVENT_RHBA_SENT: | ||
173 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba); | ||
174 | break; | ||
175 | |||
176 | case FDMISM_EVENT_PORT_OFFLINE: | ||
177 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
178 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | ||
179 | &fdmi->fcxp_wqe); | ||
180 | break; | ||
181 | |||
182 | default: | ||
183 | bfa_assert(0); | ||
184 | } | ||
185 | } | ||
186 | |||
187 | static void | ||
188 | bfa_fcs_port_fdmi_sm_rhba(struct bfa_fcs_port_fdmi_s *fdmi, | ||
189 | enum port_fdmi_event event) | ||
190 | { | ||
191 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
192 | |||
193 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
194 | bfa_trc(port->fcs, event); | ||
195 | |||
196 | switch (event) { | ||
197 | case FDMISM_EVENT_RSP_ERROR: | ||
198 | /* | ||
199 | * if max retries have not been reached, start timer for a | ||
200 | * delayed retry | ||
201 | */ | ||
202 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | ||
203 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rhba_retry); | ||
204 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | ||
205 | &fdmi->timer, bfa_fcs_port_fdmi_timeout, | ||
206 | fdmi, BFA_FCS_RETRY_TIMEOUT); | ||
207 | } else { | ||
208 | /* | ||
209 | * set state to offline | ||
210 | */ | ||
211 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
212 | } | ||
213 | break; | ||
214 | |||
215 | case FDMISM_EVENT_RSP_OK: | ||
216 | /* | ||
217 | * Initiate Register Port Attributes | ||
218 | */ | ||
219 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa); | ||
220 | fdmi->retry_cnt = 0; | ||
221 | bfa_fcs_port_fdmi_send_rpa(fdmi, NULL); | ||
222 | break; | ||
223 | |||
224 | case FDMISM_EVENT_PORT_OFFLINE: | ||
225 | bfa_fcxp_discard(fdmi->fcxp); | ||
226 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
227 | break; | ||
228 | |||
229 | default: | ||
230 | bfa_assert(0); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | static void | ||
235 | bfa_fcs_port_fdmi_sm_rhba_retry(struct bfa_fcs_port_fdmi_s *fdmi, | ||
236 | enum port_fdmi_event event) | ||
237 | { | ||
238 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
239 | |||
240 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
241 | bfa_trc(port->fcs, event); | ||
242 | |||
243 | switch (event) { | ||
244 | case FDMISM_EVENT_TIMEOUT: | ||
245 | /* | ||
246 | * Retry Timer Expired. Re-send | ||
247 | */ | ||
248 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rhba); | ||
249 | bfa_fcs_port_fdmi_send_rhba(fdmi, NULL); | ||
250 | break; | ||
251 | |||
252 | case FDMISM_EVENT_PORT_OFFLINE: | ||
253 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
254 | bfa_timer_stop(&fdmi->timer); | ||
255 | break; | ||
256 | |||
257 | default: | ||
258 | bfa_assert(0); | ||
259 | } | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * RPRT : Register Port | ||
264 | */ | ||
265 | static void | ||
266 | bfa_fcs_port_fdmi_sm_sending_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | ||
267 | enum port_fdmi_event event) | ||
268 | { | ||
269 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
270 | |||
271 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
272 | bfa_trc(port->fcs, event); | ||
273 | |||
274 | switch (event) { | ||
275 | case FDMISM_EVENT_RPRT_SENT: | ||
276 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt); | ||
277 | break; | ||
278 | |||
279 | case FDMISM_EVENT_PORT_OFFLINE: | ||
280 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
281 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | ||
282 | &fdmi->fcxp_wqe); | ||
283 | break; | ||
284 | |||
285 | default: | ||
286 | bfa_assert(0); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | static void | ||
291 | bfa_fcs_port_fdmi_sm_rprt(struct bfa_fcs_port_fdmi_s *fdmi, | ||
292 | enum port_fdmi_event event) | ||
293 | { | ||
294 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
295 | |||
296 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
297 | bfa_trc(port->fcs, event); | ||
298 | |||
299 | switch (event) { | ||
300 | case FDMISM_EVENT_RSP_ERROR: | ||
301 | /* | ||
302 | * if max retries have not been reached, start timer for a | ||
303 | * delayed retry | ||
304 | */ | ||
305 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | ||
306 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rprt_retry); | ||
307 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | ||
308 | &fdmi->timer, bfa_fcs_port_fdmi_timeout, | ||
309 | fdmi, BFA_FCS_RETRY_TIMEOUT); | ||
310 | |||
311 | } else { | ||
312 | /* | ||
313 | * set state to offline | ||
314 | */ | ||
315 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
316 | fdmi->retry_cnt = 0; | ||
317 | } | ||
318 | break; | ||
319 | |||
320 | case FDMISM_EVENT_RSP_OK: | ||
321 | fdmi->retry_cnt = 0; | ||
322 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online); | ||
323 | break; | ||
324 | |||
325 | case FDMISM_EVENT_PORT_OFFLINE: | ||
326 | bfa_fcxp_discard(fdmi->fcxp); | ||
327 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
328 | break; | ||
329 | |||
330 | default: | ||
331 | bfa_assert(0); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | static void | ||
336 | bfa_fcs_port_fdmi_sm_rprt_retry(struct bfa_fcs_port_fdmi_s *fdmi, | ||
337 | enum port_fdmi_event event) | ||
338 | { | ||
339 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
340 | |||
341 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
342 | bfa_trc(port->fcs, event); | ||
343 | |||
344 | switch (event) { | ||
345 | case FDMISM_EVENT_TIMEOUT: | ||
346 | /* | ||
347 | * Retry Timer Expired. Re-send | ||
348 | */ | ||
349 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rprt); | ||
350 | bfa_fcs_port_fdmi_send_rprt(fdmi, NULL); | ||
351 | break; | ||
352 | |||
353 | case FDMISM_EVENT_PORT_OFFLINE: | ||
354 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
355 | bfa_timer_stop(&fdmi->timer); | ||
356 | break; | ||
357 | |||
358 | default: | ||
359 | bfa_assert(0); | ||
360 | } | ||
361 | } | ||
362 | |||
363 | /* | ||
364 | * Register Port Attributes | ||
365 | */ | ||
366 | static void | ||
367 | bfa_fcs_port_fdmi_sm_sending_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | ||
368 | enum port_fdmi_event event) | ||
369 | { | ||
370 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
371 | |||
372 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
373 | bfa_trc(port->fcs, event); | ||
374 | |||
375 | switch (event) { | ||
376 | case FDMISM_EVENT_RPA_SENT: | ||
377 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa); | ||
378 | break; | ||
379 | |||
380 | case FDMISM_EVENT_PORT_OFFLINE: | ||
381 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
382 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(port), | ||
383 | &fdmi->fcxp_wqe); | ||
384 | break; | ||
385 | |||
386 | default: | ||
387 | bfa_assert(0); | ||
388 | } | ||
389 | } | ||
390 | |||
391 | static void | ||
392 | bfa_fcs_port_fdmi_sm_rpa(struct bfa_fcs_port_fdmi_s *fdmi, | ||
393 | enum port_fdmi_event event) | ||
394 | { | ||
395 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
396 | |||
397 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
398 | bfa_trc(port->fcs, event); | ||
399 | |||
400 | switch (event) { | ||
401 | case FDMISM_EVENT_RSP_ERROR: | ||
402 | /* | ||
403 | * if max retries have not been reached, start timer for a | ||
404 | * delayed retry | ||
405 | */ | ||
406 | if (fdmi->retry_cnt++ < BFA_FCS_FDMI_CMD_MAX_RETRIES) { | ||
407 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_rpa_retry); | ||
408 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(port), | ||
409 | &fdmi->timer, bfa_fcs_port_fdmi_timeout, | ||
410 | fdmi, BFA_FCS_RETRY_TIMEOUT); | ||
411 | } else { | ||
412 | /* | ||
413 | * set state to offline | ||
414 | */ | ||
415 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
416 | fdmi->retry_cnt = 0; | ||
417 | } | ||
418 | break; | ||
419 | |||
420 | case FDMISM_EVENT_RSP_OK: | ||
421 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_online); | ||
422 | fdmi->retry_cnt = 0; | ||
423 | break; | ||
424 | |||
425 | case FDMISM_EVENT_PORT_OFFLINE: | ||
426 | bfa_fcxp_discard(fdmi->fcxp); | ||
427 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
428 | break; | ||
429 | |||
430 | default: | ||
431 | bfa_assert(0); | ||
432 | } | ||
433 | } | ||
434 | |||
435 | static void | ||
436 | bfa_fcs_port_fdmi_sm_rpa_retry(struct bfa_fcs_port_fdmi_s *fdmi, | ||
437 | enum port_fdmi_event event) | ||
438 | { | ||
439 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
440 | |||
441 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
442 | bfa_trc(port->fcs, event); | ||
443 | |||
444 | switch (event) { | ||
445 | case FDMISM_EVENT_TIMEOUT: | ||
446 | /* | ||
447 | * Retry Timer Expired. Re-send | ||
448 | */ | ||
449 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_sending_rpa); | ||
450 | bfa_fcs_port_fdmi_send_rpa(fdmi, NULL); | ||
451 | break; | ||
452 | |||
453 | case FDMISM_EVENT_PORT_OFFLINE: | ||
454 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
455 | bfa_timer_stop(&fdmi->timer); | ||
456 | break; | ||
457 | |||
458 | default: | ||
459 | bfa_assert(0); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | static void | ||
464 | bfa_fcs_port_fdmi_sm_online(struct bfa_fcs_port_fdmi_s *fdmi, | ||
465 | enum port_fdmi_event event) | ||
466 | { | ||
467 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
468 | |||
469 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
470 | bfa_trc(port->fcs, event); | ||
471 | |||
472 | switch (event) { | ||
473 | case FDMISM_EVENT_PORT_OFFLINE: | ||
474 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
475 | break; | ||
476 | |||
477 | default: | ||
478 | bfa_assert(0); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | |||
483 | /** | ||
484 | * RHBA : Register HBA Attributes. | ||
485 | */ | ||
486 | static void | ||
487 | bfa_fcs_port_fdmi_send_rhba(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
488 | { | ||
489 | struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg; | ||
490 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
491 | struct fchs_s fchs; | ||
492 | int len, attr_len; | ||
493 | struct bfa_fcxp_s *fcxp; | ||
494 | u8 *pyld; | ||
495 | |||
496 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
497 | |||
498 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
499 | if (!fcxp) { | ||
500 | bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | ||
501 | bfa_fcs_port_fdmi_send_rhba, fdmi); | ||
502 | return; | ||
503 | } | ||
504 | fdmi->fcxp = fcxp; | ||
505 | |||
506 | pyld = bfa_fcxp_get_reqbuf(fcxp); | ||
507 | bfa_os_memset(pyld, 0, FC_MAX_PDUSZ); | ||
508 | |||
509 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port), | ||
510 | FDMI_RHBA); | ||
511 | |||
512 | attr_len = bfa_fcs_port_fdmi_build_rhba_pyld(fdmi, | ||
513 | (u8 *) ((struct ct_hdr_s *) pyld + 1)); | ||
514 | |||
515 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
516 | FC_CLASS_3, (len + attr_len), &fchs, | ||
517 | bfa_fcs_port_fdmi_rhba_response, (void *)fdmi, | ||
518 | FC_MAX_PDUSZ, FC_RA_TOV); | ||
519 | |||
520 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RHBA_SENT); | ||
521 | } | ||
522 | |||
523 | static u16 | ||
524 | bfa_fcs_port_fdmi_build_rhba_pyld(struct bfa_fcs_port_fdmi_s *fdmi, | ||
525 | u8 *pyld) | ||
526 | { | ||
527 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
528 | struct bfa_fcs_fdmi_hba_attr_s hba_attr; /* @todo */ | ||
529 | struct bfa_fcs_fdmi_hba_attr_s *fcs_hba_attr = &hba_attr; /* @todo */ | ||
530 | struct fdmi_rhba_s *rhba = (struct fdmi_rhba_s *) pyld; | ||
531 | struct fdmi_attr_s *attr; | ||
532 | u8 *curr_ptr; | ||
533 | u16 len, count; | ||
534 | |||
535 | /* | ||
536 | * get hba attributes | ||
537 | */ | ||
538 | bfa_fcs_fdmi_get_hbaattr(fdmi, fcs_hba_attr); | ||
539 | |||
540 | rhba->hba_id = bfa_fcs_port_get_pwwn(port); | ||
541 | rhba->port_list.num_ports = bfa_os_htonl(1); | ||
542 | rhba->port_list.port_entry = bfa_fcs_port_get_pwwn(port); | ||
543 | |||
544 | len = sizeof(rhba->hba_id) + sizeof(rhba->port_list); | ||
545 | |||
546 | count = 0; | ||
547 | len += sizeof(rhba->hba_attr_blk.attr_count); | ||
548 | |||
549 | /* | ||
550 | * fill out the invididual entries of the HBA attrib Block | ||
551 | */ | ||
552 | curr_ptr = (u8 *) &rhba->hba_attr_blk.hba_attr; | ||
553 | |||
554 | /* | ||
555 | * Node Name | ||
556 | */ | ||
557 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
558 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_NODENAME); | ||
559 | attr->len = sizeof(wwn_t); | ||
560 | memcpy(attr->value, &bfa_fcs_port_get_nwwn(port), attr->len); | ||
561 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
562 | len += attr->len; | ||
563 | count++; | ||
564 | attr->len = | ||
565 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
566 | sizeof(attr->len)); | ||
567 | |||
568 | /* | ||
569 | * Manufacturer | ||
570 | */ | ||
571 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
572 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MANUFACTURER); | ||
573 | attr->len = (u16) strlen(fcs_hba_attr->manufacturer); | ||
574 | memcpy(attr->value, fcs_hba_attr->manufacturer, attr->len); | ||
575 | /* variable fields need to be 4 byte aligned */ | ||
576 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
577 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
578 | len += attr->len; | ||
579 | count++; | ||
580 | attr->len = | ||
581 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
582 | sizeof(attr->len)); | ||
583 | |||
584 | /* | ||
585 | * Serial Number | ||
586 | */ | ||
587 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
588 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_SERIALNUM); | ||
589 | attr->len = (u16) strlen(fcs_hba_attr->serial_num); | ||
590 | memcpy(attr->value, fcs_hba_attr->serial_num, attr->len); | ||
591 | /* variable fields need to be 4 byte aligned */ | ||
592 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
593 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
594 | len += attr->len; | ||
595 | count++; | ||
596 | attr->len = | ||
597 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
598 | sizeof(attr->len)); | ||
599 | |||
600 | /* | ||
601 | * Model | ||
602 | */ | ||
603 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
604 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL); | ||
605 | attr->len = (u16) strlen(fcs_hba_attr->model); | ||
606 | memcpy(attr->value, fcs_hba_attr->model, attr->len); | ||
607 | /* variable fields need to be 4 byte aligned */ | ||
608 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
609 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
610 | len += attr->len; | ||
611 | count++; | ||
612 | attr->len = | ||
613 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
614 | sizeof(attr->len)); | ||
615 | |||
616 | /* | ||
617 | * Model Desc | ||
618 | */ | ||
619 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
620 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MODEL_DESC); | ||
621 | attr->len = (u16) strlen(fcs_hba_attr->model_desc); | ||
622 | memcpy(attr->value, fcs_hba_attr->model_desc, attr->len); | ||
623 | /* variable fields need to be 4 byte aligned */ | ||
624 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
625 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
626 | len += attr->len; | ||
627 | count++; | ||
628 | attr->len = | ||
629 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
630 | sizeof(attr->len)); | ||
631 | |||
632 | /* | ||
633 | * H/W Version | ||
634 | */ | ||
635 | if (fcs_hba_attr->hw_version[0] != '\0') { | ||
636 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
637 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_HW_VERSION); | ||
638 | attr->len = (u16) strlen(fcs_hba_attr->hw_version); | ||
639 | memcpy(attr->value, fcs_hba_attr->hw_version, attr->len); | ||
640 | /* variable fields need to be 4 byte aligned */ | ||
641 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
642 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
643 | len += attr->len; | ||
644 | count++; | ||
645 | attr->len = | ||
646 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
647 | sizeof(attr->len)); | ||
648 | } | ||
649 | |||
650 | /* | ||
651 | * Driver Version | ||
652 | */ | ||
653 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
654 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_DRIVER_VERSION); | ||
655 | attr->len = (u16) strlen(fcs_hba_attr->driver_version); | ||
656 | memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); | ||
657 | /* variable fields need to be 4 byte aligned */ | ||
658 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
659 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
660 | len += attr->len;; | ||
661 | count++; | ||
662 | attr->len = | ||
663 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
664 | sizeof(attr->len)); | ||
665 | |||
666 | /* | ||
667 | * Option Rom Version | ||
668 | */ | ||
669 | if (fcs_hba_attr->option_rom_ver[0] != '\0') { | ||
670 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
671 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_ROM_VERSION); | ||
672 | attr->len = (u16) strlen(fcs_hba_attr->option_rom_ver); | ||
673 | memcpy(attr->value, fcs_hba_attr->option_rom_ver, attr->len); | ||
674 | /* variable fields need to be 4 byte aligned */ | ||
675 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
676 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
677 | len += attr->len; | ||
678 | count++; | ||
679 | attr->len = | ||
680 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
681 | sizeof(attr->len)); | ||
682 | } | ||
683 | |||
684 | /* | ||
685 | * f/w Version = driver version | ||
686 | */ | ||
687 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
688 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_FW_VERSION); | ||
689 | attr->len = (u16) strlen(fcs_hba_attr->driver_version); | ||
690 | memcpy(attr->value, fcs_hba_attr->driver_version, attr->len); | ||
691 | /* variable fields need to be 4 byte aligned */ | ||
692 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
693 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
694 | len += attr->len; | ||
695 | count++; | ||
696 | attr->len = | ||
697 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
698 | sizeof(attr->len)); | ||
699 | |||
700 | /* | ||
701 | * OS Name | ||
702 | */ | ||
703 | if (fcs_hba_attr->os_name[0] != '\0') { | ||
704 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
705 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_OS_NAME); | ||
706 | attr->len = (u16) strlen(fcs_hba_attr->os_name); | ||
707 | memcpy(attr->value, fcs_hba_attr->os_name, attr->len); | ||
708 | /* variable fields need to be 4 byte aligned */ | ||
709 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
710 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
711 | len += attr->len; | ||
712 | count++; | ||
713 | attr->len = | ||
714 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
715 | sizeof(attr->len)); | ||
716 | } | ||
717 | |||
718 | /* | ||
719 | * MAX_CT_PAYLOAD | ||
720 | */ | ||
721 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
722 | attr->type = bfa_os_htons(FDMI_HBA_ATTRIB_MAX_CT); | ||
723 | attr->len = sizeof(fcs_hba_attr->max_ct_pyld); | ||
724 | memcpy(attr->value, &fcs_hba_attr->max_ct_pyld, attr->len); | ||
725 | len += attr->len; | ||
726 | count++; | ||
727 | attr->len = | ||
728 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
729 | sizeof(attr->len)); | ||
730 | |||
731 | /* | ||
732 | * Update size of payload | ||
733 | */ | ||
734 | len += ((sizeof(attr->type) + sizeof(attr->len)) * count); | ||
735 | |||
736 | rhba->hba_attr_blk.attr_count = bfa_os_htonl(count); | ||
737 | return len; | ||
738 | } | ||
739 | |||
740 | static void | ||
741 | bfa_fcs_port_fdmi_rhba_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
742 | void *cbarg, bfa_status_t req_status, | ||
743 | u32 rsp_len, u32 resid_len, | ||
744 | struct fchs_s *rsp_fchs) | ||
745 | { | ||
746 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg; | ||
747 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
748 | struct ct_hdr_s *cthdr = NULL; | ||
749 | |||
750 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
751 | |||
752 | /* | ||
753 | * Sanity Checks | ||
754 | */ | ||
755 | if (req_status != BFA_STATUS_OK) { | ||
756 | bfa_trc(port->fcs, req_status); | ||
757 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | ||
758 | return; | ||
759 | } | ||
760 | |||
761 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
762 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
763 | |||
764 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
765 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | ||
766 | return; | ||
767 | } | ||
768 | |||
769 | bfa_trc(port->fcs, cthdr->reason_code); | ||
770 | bfa_trc(port->fcs, cthdr->exp_code); | ||
771 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | ||
772 | } | ||
773 | |||
774 | /** | ||
775 | * RPRT : Register Port | ||
776 | */ | ||
777 | static void | ||
778 | bfa_fcs_port_fdmi_send_rprt(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
779 | { | ||
780 | struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg; | ||
781 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
782 | struct fchs_s fchs; | ||
783 | u16 len, attr_len; | ||
784 | struct bfa_fcxp_s *fcxp; | ||
785 | u8 *pyld; | ||
786 | |||
787 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
788 | |||
789 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
790 | if (!fcxp) { | ||
791 | bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | ||
792 | bfa_fcs_port_fdmi_send_rprt, fdmi); | ||
793 | return; | ||
794 | } | ||
795 | fdmi->fcxp = fcxp; | ||
796 | |||
797 | pyld = bfa_fcxp_get_reqbuf(fcxp); | ||
798 | bfa_os_memset(pyld, 0, FC_MAX_PDUSZ); | ||
799 | |||
800 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port), | ||
801 | FDMI_RPRT); | ||
802 | |||
803 | attr_len = bfa_fcs_port_fdmi_build_rprt_pyld(fdmi, | ||
804 | (u8 *) ((struct ct_hdr_s *) pyld + 1)); | ||
805 | |||
806 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
807 | FC_CLASS_3, len + attr_len, &fchs, | ||
808 | bfa_fcs_port_fdmi_rprt_response, (void *)fdmi, | ||
809 | FC_MAX_PDUSZ, FC_RA_TOV); | ||
810 | |||
811 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RPRT_SENT); | ||
812 | } | ||
813 | |||
814 | /** | ||
815 | * This routine builds Port Attribute Block that used in RPA, RPRT commands. | ||
816 | */ | ||
817 | static u16 | ||
818 | bfa_fcs_port_fdmi_build_portattr_block(struct bfa_fcs_port_fdmi_s *fdmi, | ||
819 | u8 *pyld) | ||
820 | { | ||
821 | struct bfa_fcs_fdmi_port_attr_s fcs_port_attr; | ||
822 | struct fdmi_port_attr_s *port_attrib = (struct fdmi_port_attr_s *) pyld; | ||
823 | struct fdmi_attr_s *attr; | ||
824 | u8 *curr_ptr; | ||
825 | u16 len; | ||
826 | u8 count = 0; | ||
827 | |||
828 | /* | ||
829 | * get port attributes | ||
830 | */ | ||
831 | bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); | ||
832 | |||
833 | len = sizeof(port_attrib->attr_count); | ||
834 | |||
835 | /* | ||
836 | * fill out the invididual entries | ||
837 | */ | ||
838 | curr_ptr = (u8 *) &port_attrib->port_attr; | ||
839 | |||
840 | /* | ||
841 | * FC4 Types | ||
842 | */ | ||
843 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
844 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FC4_TYPES); | ||
845 | attr->len = sizeof(fcs_port_attr.supp_fc4_types); | ||
846 | memcpy(attr->value, fcs_port_attr.supp_fc4_types, attr->len); | ||
847 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
848 | len += attr->len; | ||
849 | ++count; | ||
850 | attr->len = | ||
851 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
852 | sizeof(attr->len)); | ||
853 | |||
854 | /* | ||
855 | * Supported Speed | ||
856 | */ | ||
857 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
858 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_SUPP_SPEED); | ||
859 | attr->len = sizeof(fcs_port_attr.supp_speed); | ||
860 | memcpy(attr->value, &fcs_port_attr.supp_speed, attr->len); | ||
861 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
862 | len += attr->len; | ||
863 | ++count; | ||
864 | attr->len = | ||
865 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
866 | sizeof(attr->len)); | ||
867 | |||
868 | /* | ||
869 | * current Port Speed | ||
870 | */ | ||
871 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
872 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_PORT_SPEED); | ||
873 | attr->len = sizeof(fcs_port_attr.curr_speed); | ||
874 | memcpy(attr->value, &fcs_port_attr.curr_speed, attr->len); | ||
875 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
876 | len += attr->len; | ||
877 | ++count; | ||
878 | attr->len = | ||
879 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
880 | sizeof(attr->len)); | ||
881 | |||
882 | /* | ||
883 | * max frame size | ||
884 | */ | ||
885 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
886 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_FRAME_SIZE); | ||
887 | attr->len = sizeof(fcs_port_attr.max_frm_size); | ||
888 | memcpy(attr->value, &fcs_port_attr.max_frm_size, attr->len); | ||
889 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
890 | len += attr->len; | ||
891 | ++count; | ||
892 | attr->len = | ||
893 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
894 | sizeof(attr->len)); | ||
895 | |||
896 | /* | ||
897 | * OS Device Name | ||
898 | */ | ||
899 | if (fcs_port_attr.os_device_name[0] != '\0') { | ||
900 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
901 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_DEV_NAME); | ||
902 | attr->len = (u16) strlen(fcs_port_attr.os_device_name); | ||
903 | memcpy(attr->value, fcs_port_attr.os_device_name, attr->len); | ||
904 | /* variable fields need to be 4 byte aligned */ | ||
905 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
906 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
907 | len += attr->len; | ||
908 | ++count; | ||
909 | attr->len = | ||
910 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
911 | sizeof(attr->len)); | ||
912 | |||
913 | } | ||
914 | /* | ||
915 | * Host Name | ||
916 | */ | ||
917 | if (fcs_port_attr.host_name[0] != '\0') { | ||
918 | attr = (struct fdmi_attr_s *) curr_ptr; | ||
919 | attr->type = bfa_os_htons(FDMI_PORT_ATTRIB_HOST_NAME); | ||
920 | attr->len = (u16) strlen(fcs_port_attr.host_name); | ||
921 | memcpy(attr->value, fcs_port_attr.host_name, attr->len); | ||
922 | /* variable fields need to be 4 byte aligned */ | ||
923 | attr->len = fc_roundup(attr->len, sizeof(u32)); | ||
924 | curr_ptr += sizeof(attr->type) + sizeof(attr->len) + attr->len; | ||
925 | len += attr->len; | ||
926 | ++count; | ||
927 | attr->len = | ||
928 | bfa_os_htons(attr->len + sizeof(attr->type) + | ||
929 | sizeof(attr->len)); | ||
930 | |||
931 | } | ||
932 | |||
933 | /* | ||
934 | * Update size of payload | ||
935 | */ | ||
936 | port_attrib->attr_count = bfa_os_htonl(count); | ||
937 | len += ((sizeof(attr->type) + sizeof(attr->len)) * count); | ||
938 | return len; | ||
939 | } | ||
940 | |||
941 | static u16 | ||
942 | bfa_fcs_port_fdmi_build_rprt_pyld(struct bfa_fcs_port_fdmi_s *fdmi, | ||
943 | u8 *pyld) | ||
944 | { | ||
945 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
946 | struct fdmi_rprt_s *rprt = (struct fdmi_rprt_s *) pyld; | ||
947 | u16 len; | ||
948 | |||
949 | rprt->hba_id = bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs)); | ||
950 | rprt->port_name = bfa_fcs_port_get_pwwn(port); | ||
951 | |||
952 | len = bfa_fcs_port_fdmi_build_portattr_block(fdmi, | ||
953 | (u8 *) &rprt->port_attr_blk); | ||
954 | |||
955 | len += sizeof(rprt->hba_id) + sizeof(rprt->port_name); | ||
956 | |||
957 | return len; | ||
958 | } | ||
959 | |||
960 | static void | ||
961 | bfa_fcs_port_fdmi_rprt_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
962 | void *cbarg, bfa_status_t req_status, | ||
963 | u32 rsp_len, u32 resid_len, | ||
964 | struct fchs_s *rsp_fchs) | ||
965 | { | ||
966 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg; | ||
967 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
968 | struct ct_hdr_s *cthdr = NULL; | ||
969 | |||
970 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
971 | |||
972 | /* | ||
973 | * Sanity Checks | ||
974 | */ | ||
975 | if (req_status != BFA_STATUS_OK) { | ||
976 | bfa_trc(port->fcs, req_status); | ||
977 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | ||
978 | return; | ||
979 | } | ||
980 | |||
981 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
982 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
983 | |||
984 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
985 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | ||
986 | return; | ||
987 | } | ||
988 | |||
989 | bfa_trc(port->fcs, cthdr->reason_code); | ||
990 | bfa_trc(port->fcs, cthdr->exp_code); | ||
991 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | ||
992 | } | ||
993 | |||
994 | /** | ||
995 | * RPA : Register Port Attributes. | ||
996 | */ | ||
997 | static void | ||
998 | bfa_fcs_port_fdmi_send_rpa(void *fdmi_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
999 | { | ||
1000 | struct bfa_fcs_port_fdmi_s *fdmi = fdmi_cbarg; | ||
1001 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
1002 | struct fchs_s fchs; | ||
1003 | u16 len, attr_len; | ||
1004 | struct bfa_fcxp_s *fcxp; | ||
1005 | u8 *pyld; | ||
1006 | |||
1007 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
1008 | |||
1009 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
1010 | if (!fcxp) { | ||
1011 | bfa_fcxp_alloc_wait(port->fcs->bfa, &fdmi->fcxp_wqe, | ||
1012 | bfa_fcs_port_fdmi_send_rpa, fdmi); | ||
1013 | return; | ||
1014 | } | ||
1015 | fdmi->fcxp = fcxp; | ||
1016 | |||
1017 | pyld = bfa_fcxp_get_reqbuf(fcxp); | ||
1018 | bfa_os_memset(pyld, 0, FC_MAX_PDUSZ); | ||
1019 | |||
1020 | len = fc_fdmi_reqhdr_build(&fchs, pyld, bfa_fcs_port_get_fcid(port), | ||
1021 | FDMI_RPA); | ||
1022 | |||
1023 | attr_len = bfa_fcs_port_fdmi_build_rpa_pyld(fdmi, | ||
1024 | (u8 *) ((struct ct_hdr_s *) pyld + 1)); | ||
1025 | |||
1026 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1027 | FC_CLASS_3, len + attr_len, &fchs, | ||
1028 | bfa_fcs_port_fdmi_rpa_response, (void *)fdmi, | ||
1029 | FC_MAX_PDUSZ, FC_RA_TOV); | ||
1030 | |||
1031 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RPA_SENT); | ||
1032 | } | ||
1033 | |||
1034 | static u16 | ||
1035 | bfa_fcs_port_fdmi_build_rpa_pyld(struct bfa_fcs_port_fdmi_s *fdmi, | ||
1036 | u8 *pyld) | ||
1037 | { | ||
1038 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
1039 | struct fdmi_rpa_s *rpa = (struct fdmi_rpa_s *) pyld; | ||
1040 | u16 len; | ||
1041 | |||
1042 | rpa->port_name = bfa_fcs_port_get_pwwn(port); | ||
1043 | |||
1044 | len = bfa_fcs_port_fdmi_build_portattr_block(fdmi, | ||
1045 | (u8 *) &rpa->port_attr_blk); | ||
1046 | |||
1047 | len += sizeof(rpa->port_name); | ||
1048 | |||
1049 | return len; | ||
1050 | } | ||
1051 | |||
1052 | static void | ||
1053 | bfa_fcs_port_fdmi_rpa_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
1054 | void *cbarg, bfa_status_t req_status, | ||
1055 | u32 rsp_len, u32 resid_len, | ||
1056 | struct fchs_s *rsp_fchs) | ||
1057 | { | ||
1058 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)cbarg; | ||
1059 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
1060 | struct ct_hdr_s *cthdr = NULL; | ||
1061 | |||
1062 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
1063 | |||
1064 | /* | ||
1065 | * Sanity Checks | ||
1066 | */ | ||
1067 | if (req_status != BFA_STATUS_OK) { | ||
1068 | bfa_trc(port->fcs, req_status); | ||
1069 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | ||
1070 | return; | ||
1071 | } | ||
1072 | |||
1073 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
1074 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
1075 | |||
1076 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
1077 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_OK); | ||
1078 | return; | ||
1079 | } | ||
1080 | |||
1081 | bfa_trc(port->fcs, cthdr->reason_code); | ||
1082 | bfa_trc(port->fcs, cthdr->exp_code); | ||
1083 | bfa_sm_send_event(fdmi, FDMISM_EVENT_RSP_ERROR); | ||
1084 | } | ||
1085 | |||
1086 | static void | ||
1087 | bfa_fcs_port_fdmi_timeout(void *arg) | ||
1088 | { | ||
1089 | struct bfa_fcs_port_fdmi_s *fdmi = (struct bfa_fcs_port_fdmi_s *)arg; | ||
1090 | |||
1091 | bfa_sm_send_event(fdmi, FDMISM_EVENT_TIMEOUT); | ||
1092 | } | ||
1093 | |||
1094 | void | ||
1095 | bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_port_fdmi_s *fdmi, | ||
1096 | struct bfa_fcs_fdmi_hba_attr_s *hba_attr) | ||
1097 | { | ||
1098 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
1099 | struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; | ||
1100 | struct bfa_adapter_attr_s adapter_attr; | ||
1101 | |||
1102 | bfa_os_memset(hba_attr, 0, sizeof(struct bfa_fcs_fdmi_hba_attr_s)); | ||
1103 | bfa_os_memset(&adapter_attr, 0, sizeof(struct bfa_adapter_attr_s)); | ||
1104 | |||
1105 | bfa_ioc_get_adapter_attr(&port->fcs->bfa->ioc, &adapter_attr); | ||
1106 | |||
1107 | strncpy(hba_attr->manufacturer, adapter_attr.manufacturer, | ||
1108 | sizeof(adapter_attr.manufacturer)); | ||
1109 | |||
1110 | strncpy(hba_attr->serial_num, adapter_attr.serial_num, | ||
1111 | sizeof(adapter_attr.serial_num)); | ||
1112 | |||
1113 | strncpy(hba_attr->model, adapter_attr.model, sizeof(hba_attr->model)); | ||
1114 | |||
1115 | strncpy(hba_attr->model_desc, adapter_attr.model_descr, | ||
1116 | sizeof(hba_attr->model_desc)); | ||
1117 | |||
1118 | strncpy(hba_attr->hw_version, adapter_attr.hw_ver, | ||
1119 | sizeof(hba_attr->hw_version)); | ||
1120 | |||
1121 | strncpy(hba_attr->driver_version, (char *)driver_info->version, | ||
1122 | sizeof(hba_attr->driver_version)); | ||
1123 | |||
1124 | strncpy(hba_attr->option_rom_ver, adapter_attr.optrom_ver, | ||
1125 | sizeof(hba_attr->option_rom_ver)); | ||
1126 | |||
1127 | strncpy(hba_attr->fw_version, adapter_attr.fw_ver, | ||
1128 | sizeof(hba_attr->fw_version)); | ||
1129 | |||
1130 | strncpy(hba_attr->os_name, driver_info->host_os_name, | ||
1131 | sizeof(hba_attr->os_name)); | ||
1132 | |||
1133 | /* | ||
1134 | * If there is a patch level, append it to the os name along with a | ||
1135 | * separator | ||
1136 | */ | ||
1137 | if (driver_info->host_os_patch[0] != '\0') { | ||
1138 | strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, | ||
1139 | sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); | ||
1140 | strncat(hba_attr->os_name, driver_info->host_os_patch, | ||
1141 | sizeof(driver_info->host_os_patch)); | ||
1142 | } | ||
1143 | |||
1144 | hba_attr->max_ct_pyld = bfa_os_htonl(FC_MAX_PDUSZ); | ||
1145 | |||
1146 | } | ||
1147 | |||
1148 | void | ||
1149 | bfa_fcs_fdmi_get_portattr(struct bfa_fcs_port_fdmi_s *fdmi, | ||
1150 | struct bfa_fcs_fdmi_port_attr_s *port_attr) | ||
1151 | { | ||
1152 | struct bfa_fcs_port_s *port = fdmi->ms->port; | ||
1153 | struct bfa_fcs_driver_info_s *driver_info = &port->fcs->driver_info; | ||
1154 | struct bfa_pport_attr_s pport_attr; | ||
1155 | |||
1156 | bfa_os_memset(port_attr, 0, sizeof(struct bfa_fcs_fdmi_port_attr_s)); | ||
1157 | |||
1158 | /* | ||
1159 | * get pport attributes from hal | ||
1160 | */ | ||
1161 | bfa_pport_get_attr(port->fcs->bfa, &pport_attr); | ||
1162 | |||
1163 | /* | ||
1164 | * get FC4 type Bitmask | ||
1165 | */ | ||
1166 | fc_get_fc4type_bitmask(FC_TYPE_FCP, port_attr->supp_fc4_types); | ||
1167 | |||
1168 | /* | ||
1169 | * Supported Speeds | ||
1170 | */ | ||
1171 | port_attr->supp_speed = bfa_os_htonl(BFA_FCS_FDMI_SUPORTED_SPEEDS); | ||
1172 | |||
1173 | /* | ||
1174 | * Current Speed | ||
1175 | */ | ||
1176 | port_attr->curr_speed = bfa_os_htonl(pport_attr.speed); | ||
1177 | |||
1178 | /* | ||
1179 | * Max PDU Size. | ||
1180 | */ | ||
1181 | port_attr->max_frm_size = bfa_os_htonl(FC_MAX_PDUSZ); | ||
1182 | |||
1183 | /* | ||
1184 | * OS device Name | ||
1185 | */ | ||
1186 | strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name, | ||
1187 | sizeof(port_attr->os_device_name)); | ||
1188 | |||
1189 | /* | ||
1190 | * Host name | ||
1191 | */ | ||
1192 | strncpy(port_attr->host_name, (char *)driver_info->host_machine_name, | ||
1193 | sizeof(port_attr->host_name)); | ||
1194 | |||
1195 | } | ||
1196 | |||
1197 | |||
1198 | void | ||
1199 | bfa_fcs_port_fdmi_init(struct bfa_fcs_port_ms_s *ms) | ||
1200 | { | ||
1201 | struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi; | ||
1202 | |||
1203 | fdmi->ms = ms; | ||
1204 | bfa_sm_set_state(fdmi, bfa_fcs_port_fdmi_sm_offline); | ||
1205 | } | ||
1206 | |||
1207 | void | ||
1208 | bfa_fcs_port_fdmi_offline(struct bfa_fcs_port_ms_s *ms) | ||
1209 | { | ||
1210 | struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi; | ||
1211 | |||
1212 | fdmi->ms = ms; | ||
1213 | bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_OFFLINE); | ||
1214 | } | ||
1215 | |||
1216 | void | ||
1217 | bfa_fcs_port_fdmi_online(struct bfa_fcs_port_ms_s *ms) | ||
1218 | { | ||
1219 | struct bfa_fcs_port_fdmi_s *fdmi = &ms->fdmi; | ||
1220 | |||
1221 | fdmi->ms = ms; | ||
1222 | bfa_sm_send_event(fdmi, FDMISM_EVENT_PORT_ONLINE); | ||
1223 | } | ||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen.h b/drivers/scsi/bfa/include/aen/bfa_aen.h new file mode 100644 index 000000000000..da8cac093d3d --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen.h | |||
@@ -0,0 +1,92 @@ | |||
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 | #ifndef __BFA_AEN_H__ | ||
18 | #define __BFA_AEN_H__ | ||
19 | |||
20 | #include "defs/bfa_defs_aen.h" | ||
21 | |||
22 | #define BFA_AEN_MAX_ENTRY 512 | ||
23 | |||
24 | extern s32 bfa_aen_max_cfg_entry; | ||
25 | struct bfa_aen_s { | ||
26 | void *bfad; | ||
27 | s32 max_entry; | ||
28 | s32 write_index; | ||
29 | s32 read_index; | ||
30 | u32 bfad_num; | ||
31 | u32 seq_num; | ||
32 | void (*aen_cb_notify)(void *bfad); | ||
33 | void (*gettimeofday)(struct bfa_timeval_s *tv); | ||
34 | struct bfa_trc_mod_s *trcmod; | ||
35 | struct bfa_aen_entry_s list[BFA_AEN_MAX_ENTRY]; /* Must be the last */ | ||
36 | }; | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Public APIs | ||
41 | */ | ||
42 | static inline void | ||
43 | bfa_aen_set_max_cfg_entry(int max_entry) | ||
44 | { | ||
45 | bfa_aen_max_cfg_entry = max_entry; | ||
46 | } | ||
47 | |||
48 | static inline s32 | ||
49 | bfa_aen_get_max_cfg_entry(void) | ||
50 | { | ||
51 | return bfa_aen_max_cfg_entry; | ||
52 | } | ||
53 | |||
54 | static inline s32 | ||
55 | bfa_aen_get_meminfo(void) | ||
56 | { | ||
57 | return (sizeof(struct bfa_aen_entry_s) * bfa_aen_get_max_cfg_entry()); | ||
58 | } | ||
59 | |||
60 | static inline s32 | ||
61 | bfa_aen_get_wi(struct bfa_aen_s *aen) | ||
62 | { | ||
63 | return aen->write_index; | ||
64 | } | ||
65 | |||
66 | static inline s32 | ||
67 | bfa_aen_get_ri(struct bfa_aen_s *aen) | ||
68 | { | ||
69 | return aen->read_index; | ||
70 | } | ||
71 | |||
72 | static inline s32 | ||
73 | bfa_aen_fetch_count(struct bfa_aen_s *aen, s32 read_index) | ||
74 | { | ||
75 | return ((aen->write_index + aen->max_entry) - read_index) | ||
76 | % aen->max_entry; | ||
77 | } | ||
78 | |||
79 | s32 bfa_aen_init(struct bfa_aen_s *aen, struct bfa_trc_mod_s *trcmod, | ||
80 | void *bfad, u32 inst_id, void (*aen_cb_notify)(void *), | ||
81 | void (*gettimeofday)(struct bfa_timeval_s *)); | ||
82 | |||
83 | s32 bfa_aen_post(struct bfa_aen_s *aen, enum bfa_aen_category aen_category, | ||
84 | int aen_type, union bfa_aen_data_u *aen_data); | ||
85 | |||
86 | s32 bfa_aen_fetch(struct bfa_aen_s *aen, struct bfa_aen_entry_s *aen_entry, | ||
87 | s32 entry_space, s32 rii, s32 *ri_arr, | ||
88 | s32 ri_arr_cnt); | ||
89 | |||
90 | s32 bfa_aen_get_inst(struct bfa_aen_s *aen); | ||
91 | |||
92 | #endif /* __BFA_AEN_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h b/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h new file mode 100644 index 000000000000..260d3ea1cab3 --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_adapter.h | |||
@@ -0,0 +1,31 @@ | |||
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 | /* messages define for BFA_AEN_CAT_ADAPTER Module */ | ||
19 | #ifndef __bfa_aen_adapter_h__ | ||
20 | #define __bfa_aen_adapter_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_ADAPTER_ADD \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_ADD) | ||
27 | #define BFA_AEN_ADAPTER_REMOVE \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ADAPTER, BFA_ADAPTER_AEN_REMOVE) | ||
29 | |||
30 | #endif | ||
31 | |||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_audit.h b/drivers/scsi/bfa/include/aen/bfa_aen_audit.h new file mode 100644 index 000000000000..12cd7aab5d53 --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_audit.h | |||
@@ -0,0 +1,31 @@ | |||
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 | /* messages define for BFA_AEN_CAT_AUDIT Module */ | ||
19 | #ifndef __bfa_aen_audit_h__ | ||
20 | #define __bfa_aen_audit_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_AUDIT_AUTH_ENABLE \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_ENABLE) | ||
27 | #define BFA_AEN_AUDIT_AUTH_DISABLE \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_AUDIT, BFA_AUDIT_AEN_AUTH_DISABLE) | ||
29 | |||
30 | #endif | ||
31 | |||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h b/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h new file mode 100644 index 000000000000..507d0b58d149 --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_ethport.h | |||
@@ -0,0 +1,35 @@ | |||
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 | /* messages define for BFA_AEN_CAT_ETHPORT Module */ | ||
19 | #ifndef __bfa_aen_ethport_h__ | ||
20 | #define __bfa_aen_ethport_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_ETHPORT_LINKUP \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKUP) | ||
27 | #define BFA_AEN_ETHPORT_LINKDOWN \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_LINKDOWN) | ||
29 | #define BFA_AEN_ETHPORT_ENABLE \ | ||
30 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_ENABLE) | ||
31 | #define BFA_AEN_ETHPORT_DISABLE \ | ||
32 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ETHPORT, BFA_ETHPORT_AEN_DISABLE) | ||
33 | |||
34 | #endif | ||
35 | |||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h new file mode 100644 index 000000000000..71378b446b69 --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_ioc.h | |||
@@ -0,0 +1,37 @@ | |||
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 | /* messages define for BFA_AEN_CAT_IOC Module */ | ||
19 | #ifndef __bfa_aen_ioc_h__ | ||
20 | #define __bfa_aen_ioc_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_IOC_HBGOOD \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBGOOD) | ||
27 | #define BFA_AEN_IOC_HBFAIL \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_HBFAIL) | ||
29 | #define BFA_AEN_IOC_ENABLE \ | ||
30 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_ENABLE) | ||
31 | #define BFA_AEN_IOC_DISABLE \ | ||
32 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_DISABLE) | ||
33 | #define BFA_AEN_IOC_FWMISMATCH \ | ||
34 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_IOC, BFA_IOC_AEN_FWMISMATCH) | ||
35 | |||
36 | #endif | ||
37 | |||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h b/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h new file mode 100644 index 000000000000..a7d8ddcfef99 --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_itnim.h | |||
@@ -0,0 +1,33 @@ | |||
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 | /* messages define for BFA_AEN_CAT_ITNIM Module */ | ||
19 | #ifndef __bfa_aen_itnim_h__ | ||
20 | #define __bfa_aen_itnim_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_ITNIM_ONLINE \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_ONLINE) | ||
27 | #define BFA_AEN_ITNIM_OFFLINE \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_OFFLINE) | ||
29 | #define BFA_AEN_ITNIM_DISCONNECT \ | ||
30 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_ITNIM, BFA_ITNIM_AEN_DISCONNECT) | ||
31 | |||
32 | #endif | ||
33 | |||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_lport.h b/drivers/scsi/bfa/include/aen/bfa_aen_lport.h new file mode 100644 index 000000000000..5a8ebb65193f --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_lport.h | |||
@@ -0,0 +1,51 @@ | |||
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 | /* messages define for BFA_AEN_CAT_LPORT Module */ | ||
19 | #ifndef __bfa_aen_lport_h__ | ||
20 | #define __bfa_aen_lport_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_LPORT_NEW \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW) | ||
27 | #define BFA_AEN_LPORT_DELETE \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE) | ||
29 | #define BFA_AEN_LPORT_ONLINE \ | ||
30 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_ONLINE) | ||
31 | #define BFA_AEN_LPORT_OFFLINE \ | ||
32 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_OFFLINE) | ||
33 | #define BFA_AEN_LPORT_DISCONNECT \ | ||
34 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DISCONNECT) | ||
35 | #define BFA_AEN_LPORT_NEW_PROP \ | ||
36 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_PROP) | ||
37 | #define BFA_AEN_LPORT_DELETE_PROP \ | ||
38 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_PROP) | ||
39 | #define BFA_AEN_LPORT_NEW_STANDARD \ | ||
40 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NEW_STANDARD) | ||
41 | #define BFA_AEN_LPORT_DELETE_STANDARD \ | ||
42 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_DELETE_STANDARD) | ||
43 | #define BFA_AEN_LPORT_NPIV_DUP_WWN \ | ||
44 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_DUP_WWN) | ||
45 | #define BFA_AEN_LPORT_NPIV_FABRIC_MAX \ | ||
46 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_FABRIC_MAX) | ||
47 | #define BFA_AEN_LPORT_NPIV_UNKNOWN \ | ||
48 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_LPORT, BFA_LPORT_AEN_NPIV_UNKNOWN) | ||
49 | |||
50 | #endif | ||
51 | |||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_port.h b/drivers/scsi/bfa/include/aen/bfa_aen_port.h new file mode 100644 index 000000000000..9add905a622d --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_port.h | |||
@@ -0,0 +1,57 @@ | |||
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 | /* messages define for BFA_AEN_CAT_PORT Module */ | ||
19 | #ifndef __bfa_aen_port_h__ | ||
20 | #define __bfa_aen_port_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_PORT_ONLINE \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ONLINE) | ||
27 | #define BFA_AEN_PORT_OFFLINE \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_OFFLINE) | ||
29 | #define BFA_AEN_PORT_RLIR \ | ||
30 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_RLIR) | ||
31 | #define BFA_AEN_PORT_SFP_INSERT \ | ||
32 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_INSERT) | ||
33 | #define BFA_AEN_PORT_SFP_REMOVE \ | ||
34 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_REMOVE) | ||
35 | #define BFA_AEN_PORT_SFP_POM \ | ||
36 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_POM) | ||
37 | #define BFA_AEN_PORT_ENABLE \ | ||
38 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_ENABLE) | ||
39 | #define BFA_AEN_PORT_DISABLE \ | ||
40 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISABLE) | ||
41 | #define BFA_AEN_PORT_AUTH_ON \ | ||
42 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_ON) | ||
43 | #define BFA_AEN_PORT_AUTH_OFF \ | ||
44 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_AUTH_OFF) | ||
45 | #define BFA_AEN_PORT_DISCONNECT \ | ||
46 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_DISCONNECT) | ||
47 | #define BFA_AEN_PORT_QOS_NEG \ | ||
48 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_QOS_NEG) | ||
49 | #define BFA_AEN_PORT_FABRIC_NAME_CHANGE \ | ||
50 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_FABRIC_NAME_CHANGE) | ||
51 | #define BFA_AEN_PORT_SFP_ACCESS_ERROR \ | ||
52 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_ACCESS_ERROR) | ||
53 | #define BFA_AEN_PORT_SFP_UNSUPPORT \ | ||
54 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_PORT, BFA_PORT_AEN_SFP_UNSUPPORT) | ||
55 | |||
56 | #endif | ||
57 | |||
diff --git a/drivers/scsi/bfa/include/aen/bfa_aen_rport.h b/drivers/scsi/bfa/include/aen/bfa_aen_rport.h new file mode 100644 index 000000000000..7e4be1fd5e15 --- /dev/null +++ b/drivers/scsi/bfa/include/aen/bfa_aen_rport.h | |||
@@ -0,0 +1,37 @@ | |||
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 | /* messages define for BFA_AEN_CAT_RPORT Module */ | ||
19 | #ifndef __bfa_aen_rport_h__ | ||
20 | #define __bfa_aen_rport_h__ | ||
21 | |||
22 | #include <cs/bfa_log.h> | ||
23 | #include <defs/bfa_defs_aen.h> | ||
24 | |||
25 | #define BFA_AEN_RPORT_ONLINE \ | ||
26 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_ONLINE) | ||
27 | #define BFA_AEN_RPORT_OFFLINE \ | ||
28 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_OFFLINE) | ||
29 | #define BFA_AEN_RPORT_DISCONNECT \ | ||
30 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_DISCONNECT) | ||
31 | #define BFA_AEN_RPORT_QOS_PRIO \ | ||
32 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_PRIO) | ||
33 | #define BFA_AEN_RPORT_QOS_FLOWID \ | ||
34 | BFA_LOG_CREATE_ID(BFA_AEN_CAT_RPORT, BFA_RPORT_AEN_QOS_FLOWID) | ||
35 | |||
36 | #endif | ||
37 | |||
diff --git a/drivers/scsi/bfa/include/bfa.h b/drivers/scsi/bfa/include/bfa.h new file mode 100644 index 000000000000..64c1412c5703 --- /dev/null +++ b/drivers/scsi/bfa/include/bfa.h | |||
@@ -0,0 +1,177 @@ | |||
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 | #ifndef __BFA_H__ | ||
18 | #define __BFA_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | #include <cs/bfa_debug.h> | ||
22 | #include <cs/bfa_q.h> | ||
23 | #include <cs/bfa_trc.h> | ||
24 | #include <cs/bfa_log.h> | ||
25 | #include <cs/bfa_plog.h> | ||
26 | #include <defs/bfa_defs_status.h> | ||
27 | #include <defs/bfa_defs_ioc.h> | ||
28 | #include <defs/bfa_defs_iocfc.h> | ||
29 | #include <aen/bfa_aen.h> | ||
30 | #include <bfi/bfi.h> | ||
31 | |||
32 | struct bfa_s; | ||
33 | #include <bfa_intr_priv.h> | ||
34 | |||
35 | struct bfa_pcidev_s; | ||
36 | |||
37 | /** | ||
38 | * PCI devices supported by the current BFA | ||
39 | */ | ||
40 | struct bfa_pciid_s { | ||
41 | u16 device_id; | ||
42 | u16 vendor_id; | ||
43 | }; | ||
44 | |||
45 | extern char bfa_version[]; | ||
46 | |||
47 | /** | ||
48 | * BFA Power Mgmt Commands | ||
49 | */ | ||
50 | enum bfa_pm_cmd { | ||
51 | BFA_PM_CTL_D0 = 0, | ||
52 | BFA_PM_CTL_D1 = 1, | ||
53 | BFA_PM_CTL_D2 = 2, | ||
54 | BFA_PM_CTL_D3 = 3, | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * BFA memory resources | ||
59 | */ | ||
60 | enum bfa_mem_type { | ||
61 | BFA_MEM_TYPE_KVA = 1, /*! Kernel Virtual Memory *(non-dma-able) */ | ||
62 | BFA_MEM_TYPE_DMA = 2, /*! DMA-able memory */ | ||
63 | BFA_MEM_TYPE_MAX = BFA_MEM_TYPE_DMA, | ||
64 | }; | ||
65 | |||
66 | struct bfa_mem_elem_s { | ||
67 | enum bfa_mem_type mem_type; /* see enum bfa_mem_type */ | ||
68 | u32 mem_len; /* Total Length in Bytes */ | ||
69 | u8 *kva; /* kernel virtual address */ | ||
70 | u64 dma; /* dma address if DMA memory */ | ||
71 | u8 *kva_curp; /* kva allocation cursor */ | ||
72 | u64 dma_curp; /* dma allocation cursor */ | ||
73 | }; | ||
74 | |||
75 | struct bfa_meminfo_s { | ||
76 | struct bfa_mem_elem_s meminfo[BFA_MEM_TYPE_MAX]; | ||
77 | }; | ||
78 | #define bfa_meminfo_kva(_m) \ | ||
79 | (_m)->meminfo[BFA_MEM_TYPE_KVA - 1].kva_curp | ||
80 | #define bfa_meminfo_dma_virt(_m) \ | ||
81 | (_m)->meminfo[BFA_MEM_TYPE_DMA - 1].kva_curp | ||
82 | #define bfa_meminfo_dma_phys(_m) \ | ||
83 | (_m)->meminfo[BFA_MEM_TYPE_DMA - 1].dma_curp | ||
84 | |||
85 | /** | ||
86 | * Generic Scatter Gather Element used by driver | ||
87 | */ | ||
88 | struct bfa_sge_s { | ||
89 | u32 sg_len; | ||
90 | void *sg_addr; | ||
91 | }; | ||
92 | |||
93 | #define bfa_sge_to_be(__sge) do { \ | ||
94 | ((u32 *)(__sge))[0] = bfa_os_htonl(((u32 *)(__sge))[0]); \ | ||
95 | ((u32 *)(__sge))[1] = bfa_os_htonl(((u32 *)(__sge))[1]); \ | ||
96 | ((u32 *)(__sge))[2] = bfa_os_htonl(((u32 *)(__sge))[2]); \ | ||
97 | } while (0) | ||
98 | |||
99 | |||
100 | /* | ||
101 | * bfa stats interfaces | ||
102 | */ | ||
103 | #define bfa_stats(_mod, _stats) (_mod)->stats._stats ++ | ||
104 | |||
105 | #define bfa_ioc_get_stats(__bfa, __ioc_stats) \ | ||
106 | bfa_ioc_fetch_stats(&(__bfa)->ioc, __ioc_stats) | ||
107 | #define bfa_ioc_clear_stats(__bfa) \ | ||
108 | bfa_ioc_clr_stats(&(__bfa)->ioc) | ||
109 | |||
110 | /* | ||
111 | * bfa API functions | ||
112 | */ | ||
113 | void bfa_get_pciids(struct bfa_pciid_s **pciids, int *npciids); | ||
114 | void bfa_cfg_get_default(struct bfa_iocfc_cfg_s *cfg); | ||
115 | void bfa_cfg_get_min(struct bfa_iocfc_cfg_s *cfg); | ||
116 | void bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, | ||
117 | struct bfa_meminfo_s *meminfo); | ||
118 | void bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | ||
119 | struct bfa_meminfo_s *meminfo, | ||
120 | struct bfa_pcidev_s *pcidev); | ||
121 | void bfa_init_trc(struct bfa_s *bfa, struct bfa_trc_mod_s *trcmod); | ||
122 | void bfa_init_log(struct bfa_s *bfa, struct bfa_log_mod_s *logmod); | ||
123 | void bfa_init_aen(struct bfa_s *bfa, struct bfa_aen_s *aen); | ||
124 | void bfa_init_plog(struct bfa_s *bfa, struct bfa_plog_s *plog); | ||
125 | void bfa_detach(struct bfa_s *bfa); | ||
126 | void bfa_init(struct bfa_s *bfa); | ||
127 | void bfa_start(struct bfa_s *bfa); | ||
128 | void bfa_stop(struct bfa_s *bfa); | ||
129 | void bfa_attach_fcs(struct bfa_s *bfa); | ||
130 | void bfa_cb_init(void *bfad, bfa_status_t status); | ||
131 | void bfa_cb_stop(void *bfad, bfa_status_t status); | ||
132 | void bfa_cb_updateq(void *bfad, bfa_status_t status); | ||
133 | |||
134 | bfa_boolean_t bfa_intx(struct bfa_s *bfa); | ||
135 | void bfa_isr_enable(struct bfa_s *bfa); | ||
136 | void bfa_isr_disable(struct bfa_s *bfa); | ||
137 | void bfa_msix_getvecs(struct bfa_s *bfa, u32 *msix_vecs_bmap, | ||
138 | u32 *num_vecs, u32 *max_vec_bit); | ||
139 | #define bfa_msix(__bfa, __vec) (__bfa)->msix.handler[__vec](__bfa, __vec) | ||
140 | |||
141 | void bfa_comp_deq(struct bfa_s *bfa, struct list_head *comp_q); | ||
142 | void bfa_comp_process(struct bfa_s *bfa, struct list_head *comp_q); | ||
143 | void bfa_comp_free(struct bfa_s *bfa, struct list_head *comp_q); | ||
144 | |||
145 | typedef void (*bfa_cb_ioc_t) (void *cbarg, enum bfa_status status); | ||
146 | void bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr); | ||
147 | bfa_status_t bfa_iocfc_get_stats(struct bfa_s *bfa, | ||
148 | struct bfa_iocfc_stats_s *stats, | ||
149 | bfa_cb_ioc_t cbfn, void *cbarg); | ||
150 | bfa_status_t bfa_iocfc_clear_stats(struct bfa_s *bfa, | ||
151 | bfa_cb_ioc_t cbfn, void *cbarg); | ||
152 | void bfa_get_attr(struct bfa_s *bfa, struct bfa_ioc_attr_s *ioc_attr); | ||
153 | |||
154 | void bfa_adapter_get_attr(struct bfa_s *bfa, | ||
155 | struct bfa_adapter_attr_s *ad_attr); | ||
156 | u64 bfa_adapter_get_id(struct bfa_s *bfa); | ||
157 | |||
158 | bfa_status_t bfa_iocfc_israttr_set(struct bfa_s *bfa, | ||
159 | struct bfa_iocfc_intr_attr_s *attr); | ||
160 | |||
161 | void bfa_iocfc_enable(struct bfa_s *bfa); | ||
162 | void bfa_iocfc_disable(struct bfa_s *bfa); | ||
163 | void bfa_ioc_auto_recover(bfa_boolean_t auto_recover); | ||
164 | void bfa_cb_ioc_disable(void *bfad); | ||
165 | void bfa_timer_tick(struct bfa_s *bfa); | ||
166 | #define bfa_timer_start(_bfa, _timer, _timercb, _arg, _timeout) \ | ||
167 | bfa_timer_begin(&(_bfa)->timer_mod, _timer, _timercb, _arg, _timeout) | ||
168 | |||
169 | /* | ||
170 | * BFA debug API functions | ||
171 | */ | ||
172 | bfa_status_t bfa_debug_fwtrc(struct bfa_s *bfa, void *trcdata, int *trclen); | ||
173 | bfa_status_t bfa_debug_fwsave(struct bfa_s *bfa, void *trcdata, int *trclen); | ||
174 | |||
175 | #include "bfa_priv.h" | ||
176 | |||
177 | #endif /* __BFA_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/bfa_fcpim.h b/drivers/scsi/bfa/include/bfa_fcpim.h new file mode 100644 index 000000000000..04789795fa53 --- /dev/null +++ b/drivers/scsi/bfa/include/bfa_fcpim.h | |||
@@ -0,0 +1,159 @@ | |||
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 | #ifndef __BFA_FCPIM_H__ | ||
19 | #define __BFA_FCPIM_H__ | ||
20 | |||
21 | #include <bfa.h> | ||
22 | #include <bfa_svc.h> | ||
23 | #include <bfi/bfi_fcpim.h> | ||
24 | #include <defs/bfa_defs_fcpim.h> | ||
25 | |||
26 | /* | ||
27 | * forward declarations | ||
28 | */ | ||
29 | struct bfa_itnim_s; | ||
30 | struct bfa_ioim_s; | ||
31 | struct bfa_tskim_s; | ||
32 | struct bfad_ioim_s; | ||
33 | struct bfad_tskim_s; | ||
34 | |||
35 | /* | ||
36 | * bfa fcpim module API functions | ||
37 | */ | ||
38 | void bfa_fcpim_path_tov_set(struct bfa_s *bfa, u16 path_tov); | ||
39 | u16 bfa_fcpim_path_tov_get(struct bfa_s *bfa); | ||
40 | void bfa_fcpim_qdepth_set(struct bfa_s *bfa, u16 q_depth); | ||
41 | u16 bfa_fcpim_qdepth_get(struct bfa_s *bfa); | ||
42 | bfa_status_t bfa_fcpim_get_modstats(struct bfa_s *bfa, | ||
43 | struct bfa_fcpim_stats_s *modstats); | ||
44 | bfa_status_t bfa_fcpim_clr_modstats(struct bfa_s *bfa); | ||
45 | |||
46 | /* | ||
47 | * bfa itnim API functions | ||
48 | */ | ||
49 | struct bfa_itnim_s *bfa_itnim_create(struct bfa_s *bfa, | ||
50 | struct bfa_rport_s *rport, void *itnim); | ||
51 | void bfa_itnim_delete(struct bfa_itnim_s *itnim); | ||
52 | void bfa_itnim_online(struct bfa_itnim_s *itnim, | ||
53 | bfa_boolean_t seq_rec); | ||
54 | void bfa_itnim_offline(struct bfa_itnim_s *itnim); | ||
55 | void bfa_itnim_get_stats(struct bfa_itnim_s *itnim, | ||
56 | struct bfa_itnim_hal_stats_s *stats); | ||
57 | void bfa_itnim_clear_stats(struct bfa_itnim_s *itnim); | ||
58 | |||
59 | |||
60 | /** | ||
61 | * BFA completion callback for bfa_itnim_online(). | ||
62 | * | ||
63 | * @param[in] itnim FCS or driver itnim instance | ||
64 | * | ||
65 | * return None | ||
66 | */ | ||
67 | void bfa_cb_itnim_online(void *itnim); | ||
68 | |||
69 | /** | ||
70 | * BFA completion callback for bfa_itnim_offline(). | ||
71 | * | ||
72 | * @param[in] itnim FCS or driver itnim instance | ||
73 | * | ||
74 | * return None | ||
75 | */ | ||
76 | void bfa_cb_itnim_offline(void *itnim); | ||
77 | void bfa_cb_itnim_tov_begin(void *itnim); | ||
78 | void bfa_cb_itnim_tov(void *itnim); | ||
79 | |||
80 | /** | ||
81 | * BFA notification to FCS/driver for second level error recovery. | ||
82 | * | ||
83 | * Atleast one I/O request has timedout and target is unresponsive to | ||
84 | * repeated abort requests. Second level error recovery should be initiated | ||
85 | * by starting implicit logout and recovery procedures. | ||
86 | * | ||
87 | * @param[in] itnim FCS or driver itnim instance | ||
88 | * | ||
89 | * return None | ||
90 | */ | ||
91 | void bfa_cb_itnim_sler(void *itnim); | ||
92 | |||
93 | /* | ||
94 | * bfa ioim API functions | ||
95 | */ | ||
96 | struct bfa_ioim_s *bfa_ioim_alloc(struct bfa_s *bfa, | ||
97 | struct bfad_ioim_s *dio, | ||
98 | struct bfa_itnim_s *itnim, | ||
99 | u16 nsgles); | ||
100 | |||
101 | void bfa_ioim_free(struct bfa_ioim_s *ioim); | ||
102 | void bfa_ioim_start(struct bfa_ioim_s *ioim); | ||
103 | void bfa_ioim_abort(struct bfa_ioim_s *ioim); | ||
104 | void bfa_ioim_delayed_comp(struct bfa_ioim_s *ioim, | ||
105 | bfa_boolean_t iotov); | ||
106 | |||
107 | |||
108 | /** | ||
109 | * I/O completion notification. | ||
110 | * | ||
111 | * @param[in] dio driver IO structure | ||
112 | * @param[in] io_status IO completion status | ||
113 | * @param[in] scsi_status SCSI status returned by target | ||
114 | * @param[in] sns_len SCSI sense length, 0 if none | ||
115 | * @param[in] sns_info SCSI sense data, if any | ||
116 | * @param[in] residue Residual length | ||
117 | * | ||
118 | * @return None | ||
119 | */ | ||
120 | void bfa_cb_ioim_done(void *bfad, struct bfad_ioim_s *dio, | ||
121 | enum bfi_ioim_status io_status, | ||
122 | u8 scsi_status, int sns_len, | ||
123 | u8 *sns_info, s32 residue); | ||
124 | |||
125 | /** | ||
126 | * I/O good completion notification. | ||
127 | * | ||
128 | * @param[in] dio driver IO structure | ||
129 | * | ||
130 | * @return None | ||
131 | */ | ||
132 | void bfa_cb_ioim_good_comp(void *bfad, struct bfad_ioim_s *dio); | ||
133 | |||
134 | /** | ||
135 | * I/O abort completion notification | ||
136 | * | ||
137 | * @param[in] dio driver IO that was aborted | ||
138 | * | ||
139 | * @return None | ||
140 | */ | ||
141 | void bfa_cb_ioim_abort(void *bfad, struct bfad_ioim_s *dio); | ||
142 | void bfa_cb_ioim_resfree(void *hcb_bfad); | ||
143 | |||
144 | void bfa_cb_ioim_resfree(void *hcb_bfad); | ||
145 | |||
146 | /* | ||
147 | * bfa tskim API functions | ||
148 | */ | ||
149 | struct bfa_tskim_s *bfa_tskim_alloc(struct bfa_s *bfa, | ||
150 | struct bfad_tskim_s *dtsk); | ||
151 | void bfa_tskim_free(struct bfa_tskim_s *tskim); | ||
152 | void bfa_tskim_start(struct bfa_tskim_s *tskim, | ||
153 | struct bfa_itnim_s *itnim, lun_t lun, | ||
154 | enum fcp_tm_cmnd tm, u8 t_secs); | ||
155 | void bfa_cb_tskim_done(void *bfad, struct bfad_tskim_s *dtsk, | ||
156 | enum bfi_tskim_status tsk_status); | ||
157 | |||
158 | #endif /* __BFA_FCPIM_H__ */ | ||
159 | |||
diff --git a/drivers/scsi/bfa/include/bfa_fcptm.h b/drivers/scsi/bfa/include/bfa_fcptm.h new file mode 100644 index 000000000000..5f5ffe0bb1bb --- /dev/null +++ b/drivers/scsi/bfa/include/bfa_fcptm.h | |||
@@ -0,0 +1,47 @@ | |||
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 | #ifndef __BFA_FCPTM_H__ | ||
19 | #define __BFA_FCPTM_H__ | ||
20 | |||
21 | #include <bfa.h> | ||
22 | #include <bfa_svc.h> | ||
23 | #include <bfi/bfi_fcptm.h> | ||
24 | |||
25 | /* | ||
26 | * forward declarations | ||
27 | */ | ||
28 | struct bfa_tin_s; | ||
29 | struct bfa_iotm_s; | ||
30 | struct bfa_tsktm_s; | ||
31 | |||
32 | /* | ||
33 | * bfa fcptm module API functions | ||
34 | */ | ||
35 | void bfa_fcptm_path_tov_set(struct bfa_s *bfa, u16 path_tov); | ||
36 | u16 bfa_fcptm_path_tov_get(struct bfa_s *bfa); | ||
37 | void bfa_fcptm_qdepth_set(struct bfa_s *bfa, u16 q_depth); | ||
38 | u16 bfa_fcptm_qdepth_get(struct bfa_s *bfa); | ||
39 | |||
40 | /* | ||
41 | * bfa tin API functions | ||
42 | */ | ||
43 | void bfa_tin_get_stats(struct bfa_tin_s *tin, struct bfa_tin_stats_s *stats); | ||
44 | void bfa_tin_clear_stats(struct bfa_tin_s *tin); | ||
45 | |||
46 | #endif /* __BFA_FCPTM_H__ */ | ||
47 | |||
diff --git a/drivers/scsi/bfa/include/bfa_svc.h b/drivers/scsi/bfa/include/bfa_svc.h new file mode 100644 index 000000000000..0c80b74f72ef --- /dev/null +++ b/drivers/scsi/bfa/include/bfa_svc.h | |||
@@ -0,0 +1,324 @@ | |||
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 | #ifndef __BFA_SVC_H__ | ||
18 | #define __BFA_SVC_H__ | ||
19 | |||
20 | /* | ||
21 | * forward declarations | ||
22 | */ | ||
23 | struct bfa_fcxp_s; | ||
24 | |||
25 | #include <defs/bfa_defs_status.h> | ||
26 | #include <defs/bfa_defs_pport.h> | ||
27 | #include <defs/bfa_defs_rport.h> | ||
28 | #include <defs/bfa_defs_qos.h> | ||
29 | #include <cs/bfa_sm.h> | ||
30 | #include <bfa.h> | ||
31 | |||
32 | /** | ||
33 | * BFA rport information. | ||
34 | */ | ||
35 | struct bfa_rport_info_s { | ||
36 | u16 max_frmsz; /* max rcv pdu size */ | ||
37 | u32 pid : 24, /* remote port ID */ | ||
38 | lp_tag : 8; | ||
39 | u32 local_pid : 24, /* local port ID */ | ||
40 | cisc : 8; /* CIRO supported */ | ||
41 | u8 fc_class; /* supported FC classes. enum fc_cos */ | ||
42 | u8 vf_en; /* virtual fabric enable */ | ||
43 | u16 vf_id; /* virtual fabric ID */ | ||
44 | enum bfa_pport_speed speed; /* Rport's current speed */ | ||
45 | }; | ||
46 | |||
47 | /** | ||
48 | * BFA rport data structure | ||
49 | */ | ||
50 | struct bfa_rport_s { | ||
51 | struct list_head qe; /* queue element */ | ||
52 | bfa_sm_t sm; /* state machine */ | ||
53 | struct bfa_s *bfa; /* backpointer to BFA */ | ||
54 | void *rport_drv; /* fcs/driver rport object */ | ||
55 | u16 fw_handle; /* firmware rport handle */ | ||
56 | u16 rport_tag; /* BFA rport tag */ | ||
57 | struct bfa_rport_info_s rport_info; /* rport info from *fcs/driver */ | ||
58 | struct bfa_reqq_wait_s reqq_wait; /* to wait for room in reqq */ | ||
59 | struct bfa_cb_qe_s hcb_qe; /* BFA callback qelem */ | ||
60 | struct bfa_rport_hal_stats_s stats; /* BFA rport statistics */ | ||
61 | struct bfa_rport_qos_attr_s qos_attr; | ||
62 | union a { | ||
63 | bfa_status_t status; /* f/w status */ | ||
64 | void *fw_msg; /* QoS scn event */ | ||
65 | } event_arg; | ||
66 | }; | ||
67 | #define BFA_RPORT_FC_COS(_rport) ((_rport)->rport_info.fc_class) | ||
68 | |||
69 | /** | ||
70 | * Send completion callback. | ||
71 | */ | ||
72 | typedef void (*bfa_cb_fcxp_send_t) (void *bfad_fcxp, struct bfa_fcxp_s *fcxp, | ||
73 | void *cbarg, enum bfa_status req_status, | ||
74 | u32 rsp_len, u32 resid_len, | ||
75 | struct fchs_s *rsp_fchs); | ||
76 | |||
77 | /** | ||
78 | * BFA fcxp allocation (asynchronous) | ||
79 | */ | ||
80 | typedef void (*bfa_fcxp_alloc_cbfn_t) (void *cbarg, struct bfa_fcxp_s *fcxp); | ||
81 | |||
82 | struct bfa_fcxp_wqe_s { | ||
83 | struct list_head qe; | ||
84 | bfa_fcxp_alloc_cbfn_t alloc_cbfn; | ||
85 | void *alloc_cbarg; | ||
86 | }; | ||
87 | |||
88 | typedef u64 (*bfa_fcxp_get_sgaddr_t) (void *bfad_fcxp, int sgeid); | ||
89 | typedef u32 (*bfa_fcxp_get_sglen_t) (void *bfad_fcxp, int sgeid); | ||
90 | |||
91 | #define BFA_UF_BUFSZ (2 * 1024 + 256) | ||
92 | |||
93 | /** | ||
94 | * @todo private | ||
95 | */ | ||
96 | struct bfa_uf_buf_s { | ||
97 | u8 d[BFA_UF_BUFSZ]; | ||
98 | }; | ||
99 | |||
100 | |||
101 | struct bfa_uf_s { | ||
102 | struct list_head qe; /* queue element */ | ||
103 | struct bfa_s *bfa; /* bfa instance */ | ||
104 | u16 uf_tag; /* identifying tag f/w messages */ | ||
105 | u16 vf_id; | ||
106 | u16 src_rport_handle; | ||
107 | u16 rsvd; | ||
108 | u8 *data_ptr; | ||
109 | u16 data_len; /* actual receive length */ | ||
110 | u16 pb_len; /* posted buffer length */ | ||
111 | void *buf_kva; /* buffer virtual address */ | ||
112 | u64 buf_pa; /* buffer physical address */ | ||
113 | struct bfa_cb_qe_s hcb_qe; /* comp: BFA comp qelem */ | ||
114 | struct bfa_sge_s sges[BFI_SGE_INLINE_MAX]; | ||
115 | }; | ||
116 | |||
117 | typedef void (*bfa_cb_pport_t) (void *cbarg, enum bfa_status status); | ||
118 | |||
119 | /** | ||
120 | * bfa lport login/logout service interface | ||
121 | */ | ||
122 | struct bfa_lps_s { | ||
123 | struct list_head qe; /* queue element */ | ||
124 | struct bfa_s *bfa; /* parent bfa instance */ | ||
125 | bfa_sm_t sm; /* finite state machine */ | ||
126 | u8 lp_tag; /* lport tag */ | ||
127 | u8 reqq; /* lport request queue */ | ||
128 | u8 alpa; /* ALPA for loop topologies */ | ||
129 | u32 lp_pid; /* lport port ID */ | ||
130 | bfa_boolean_t fdisc; /* send FDISC instead of FLOGI*/ | ||
131 | bfa_boolean_t auth_en; /* enable authentication */ | ||
132 | bfa_boolean_t auth_req; /* authentication required */ | ||
133 | bfa_boolean_t npiv_en; /* NPIV is allowed by peer */ | ||
134 | bfa_boolean_t fport; /* attached peer is F_PORT */ | ||
135 | bfa_boolean_t brcd_switch;/* attached peer is brcd switch */ | ||
136 | bfa_status_t status; /* login status */ | ||
137 | u16 pdusz; /* max receive PDU size */ | ||
138 | u16 pr_bbcred; /* BB_CREDIT from peer */ | ||
139 | u8 lsrjt_rsn; /* LSRJT reason */ | ||
140 | u8 lsrjt_expl; /* LSRJT explanation */ | ||
141 | wwn_t pwwn; /* port wwn of lport */ | ||
142 | wwn_t nwwn; /* node wwn of lport */ | ||
143 | wwn_t pr_pwwn; /* port wwn of lport peer */ | ||
144 | wwn_t pr_nwwn; /* node wwn of lport peer */ | ||
145 | mac_t lp_mac; /* fpma/spma MAC for lport */ | ||
146 | mac_t fcf_mac; /* FCF MAC of lport */ | ||
147 | struct bfa_reqq_wait_s wqe; /* request wait queue element */ | ||
148 | void *uarg; /* user callback arg */ | ||
149 | struct bfa_cb_qe_s hcb_qe; /* comp: callback qelem */ | ||
150 | struct bfi_lps_login_rsp_s *loginrsp; | ||
151 | bfa_eproto_status_t ext_status; | ||
152 | }; | ||
153 | |||
154 | /* | ||
155 | * bfa pport API functions | ||
156 | */ | ||
157 | bfa_status_t bfa_pport_enable(struct bfa_s *bfa); | ||
158 | bfa_status_t bfa_pport_disable(struct bfa_s *bfa); | ||
159 | bfa_status_t bfa_pport_cfg_speed(struct bfa_s *bfa, | ||
160 | enum bfa_pport_speed speed); | ||
161 | enum bfa_pport_speed bfa_pport_get_speed(struct bfa_s *bfa); | ||
162 | bfa_status_t bfa_pport_cfg_topology(struct bfa_s *bfa, | ||
163 | enum bfa_pport_topology topo); | ||
164 | enum bfa_pport_topology bfa_pport_get_topology(struct bfa_s *bfa); | ||
165 | bfa_status_t bfa_pport_cfg_hardalpa(struct bfa_s *bfa, u8 alpa); | ||
166 | bfa_boolean_t bfa_pport_get_hardalpa(struct bfa_s *bfa, u8 *alpa); | ||
167 | u8 bfa_pport_get_myalpa(struct bfa_s *bfa); | ||
168 | bfa_status_t bfa_pport_clr_hardalpa(struct bfa_s *bfa); | ||
169 | bfa_status_t bfa_pport_cfg_maxfrsize(struct bfa_s *bfa, u16 maxsize); | ||
170 | u16 bfa_pport_get_maxfrsize(struct bfa_s *bfa); | ||
171 | u32 bfa_pport_mypid(struct bfa_s *bfa); | ||
172 | u8 bfa_pport_get_rx_bbcredit(struct bfa_s *bfa); | ||
173 | bfa_status_t bfa_pport_trunk_enable(struct bfa_s *bfa, u8 bitmap); | ||
174 | bfa_status_t bfa_pport_trunk_disable(struct bfa_s *bfa); | ||
175 | bfa_boolean_t bfa_pport_trunk_query(struct bfa_s *bfa, u32 *bitmap); | ||
176 | void bfa_pport_get_attr(struct bfa_s *bfa, struct bfa_pport_attr_s *attr); | ||
177 | wwn_t bfa_pport_get_wwn(struct bfa_s *bfa, bfa_boolean_t node); | ||
178 | bfa_status_t bfa_pport_get_stats(struct bfa_s *bfa, | ||
179 | union bfa_pport_stats_u *stats, | ||
180 | bfa_cb_pport_t cbfn, void *cbarg); | ||
181 | bfa_status_t bfa_pport_clear_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, | ||
182 | void *cbarg); | ||
183 | void bfa_pport_event_register(struct bfa_s *bfa, | ||
184 | void (*event_cbfn) (void *cbarg, | ||
185 | bfa_pport_event_t event), void *event_cbarg); | ||
186 | bfa_boolean_t bfa_pport_is_disabled(struct bfa_s *bfa); | ||
187 | void bfa_pport_cfg_qos(struct bfa_s *bfa, bfa_boolean_t on_off); | ||
188 | void bfa_pport_cfg_ratelim(struct bfa_s *bfa, bfa_boolean_t on_off); | ||
189 | bfa_status_t bfa_pport_cfg_ratelim_speed(struct bfa_s *bfa, | ||
190 | enum bfa_pport_speed speed); | ||
191 | enum bfa_pport_speed bfa_pport_get_ratelim_speed(struct bfa_s *bfa); | ||
192 | |||
193 | void bfa_pport_set_tx_bbcredit(struct bfa_s *bfa, u16 tx_bbcredit); | ||
194 | void bfa_pport_busy(struct bfa_s *bfa, bfa_boolean_t status); | ||
195 | void bfa_pport_beacon(struct bfa_s *bfa, bfa_boolean_t beacon, | ||
196 | bfa_boolean_t link_e2e_beacon); | ||
197 | void bfa_cb_pport_event(void *cbarg, bfa_pport_event_t event); | ||
198 | void bfa_pport_qos_get_attr(struct bfa_s *bfa, struct bfa_qos_attr_s *qos_attr); | ||
199 | void bfa_pport_qos_get_vc_attr(struct bfa_s *bfa, | ||
200 | struct bfa_qos_vc_attr_s *qos_vc_attr); | ||
201 | bfa_status_t bfa_pport_get_qos_stats(struct bfa_s *bfa, | ||
202 | union bfa_pport_stats_u *stats, | ||
203 | bfa_cb_pport_t cbfn, void *cbarg); | ||
204 | bfa_status_t bfa_pport_clear_qos_stats(struct bfa_s *bfa, bfa_cb_pport_t cbfn, | ||
205 | void *cbarg); | ||
206 | bfa_boolean_t bfa_pport_is_ratelim(struct bfa_s *bfa); | ||
207 | bfa_boolean_t bfa_pport_is_linkup(struct bfa_s *bfa); | ||
208 | |||
209 | /* | ||
210 | * bfa rport API functions | ||
211 | */ | ||
212 | struct bfa_rport_s *bfa_rport_create(struct bfa_s *bfa, void *rport_drv); | ||
213 | void bfa_rport_delete(struct bfa_rport_s *rport); | ||
214 | void bfa_rport_online(struct bfa_rport_s *rport, | ||
215 | struct bfa_rport_info_s *rport_info); | ||
216 | void bfa_rport_offline(struct bfa_rport_s *rport); | ||
217 | void bfa_rport_speed(struct bfa_rport_s *rport, enum bfa_pport_speed speed); | ||
218 | void bfa_rport_get_stats(struct bfa_rport_s *rport, | ||
219 | struct bfa_rport_hal_stats_s *stats); | ||
220 | void bfa_rport_clear_stats(struct bfa_rport_s *rport); | ||
221 | void bfa_cb_rport_online(void *rport); | ||
222 | void bfa_cb_rport_offline(void *rport); | ||
223 | void bfa_cb_rport_qos_scn_flowid(void *rport, | ||
224 | struct bfa_rport_qos_attr_s old_qos_attr, | ||
225 | struct bfa_rport_qos_attr_s new_qos_attr); | ||
226 | void bfa_cb_rport_qos_scn_prio(void *rport, | ||
227 | struct bfa_rport_qos_attr_s old_qos_attr, | ||
228 | struct bfa_rport_qos_attr_s new_qos_attr); | ||
229 | void bfa_rport_get_qos_attr(struct bfa_rport_s *rport, | ||
230 | struct bfa_rport_qos_attr_s *qos_attr); | ||
231 | |||
232 | /* | ||
233 | * bfa fcxp API functions | ||
234 | */ | ||
235 | struct bfa_fcxp_s *bfa_fcxp_alloc(void *bfad_fcxp, struct bfa_s *bfa, | ||
236 | int nreq_sgles, int nrsp_sgles, | ||
237 | bfa_fcxp_get_sgaddr_t get_req_sga, | ||
238 | bfa_fcxp_get_sglen_t get_req_sglen, | ||
239 | bfa_fcxp_get_sgaddr_t get_rsp_sga, | ||
240 | bfa_fcxp_get_sglen_t get_rsp_sglen); | ||
241 | void bfa_fcxp_alloc_wait(struct bfa_s *bfa, struct bfa_fcxp_wqe_s *wqe, | ||
242 | bfa_fcxp_alloc_cbfn_t alloc_cbfn, void *cbarg); | ||
243 | void bfa_fcxp_walloc_cancel(struct bfa_s *bfa, | ||
244 | struct bfa_fcxp_wqe_s *wqe); | ||
245 | void bfa_fcxp_discard(struct bfa_fcxp_s *fcxp); | ||
246 | |||
247 | void *bfa_fcxp_get_reqbuf(struct bfa_fcxp_s *fcxp); | ||
248 | void *bfa_fcxp_get_rspbuf(struct bfa_fcxp_s *fcxp); | ||
249 | |||
250 | void bfa_fcxp_free(struct bfa_fcxp_s *fcxp); | ||
251 | |||
252 | void bfa_fcxp_send(struct bfa_fcxp_s *fcxp, | ||
253 | struct bfa_rport_s *rport, u16 vf_id, u8 lp_tag, | ||
254 | bfa_boolean_t cts, enum fc_cos cos, | ||
255 | u32 reqlen, struct fchs_s *fchs, | ||
256 | bfa_cb_fcxp_send_t cbfn, | ||
257 | void *cbarg, | ||
258 | u32 rsp_maxlen, u8 rsp_timeout); | ||
259 | bfa_status_t bfa_fcxp_abort(struct bfa_fcxp_s *fcxp); | ||
260 | u32 bfa_fcxp_get_reqbufsz(struct bfa_fcxp_s *fcxp); | ||
261 | u32 bfa_fcxp_get_maxrsp(struct bfa_s *bfa); | ||
262 | |||
263 | static inline void * | ||
264 | bfa_uf_get_frmbuf(struct bfa_uf_s *uf) | ||
265 | { | ||
266 | return uf->data_ptr; | ||
267 | } | ||
268 | |||
269 | static inline u16 | ||
270 | bfa_uf_get_frmlen(struct bfa_uf_s *uf) | ||
271 | { | ||
272 | return uf->data_len; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Callback prototype for unsolicited frame receive handler. | ||
277 | * | ||
278 | * @param[in] cbarg callback arg for receive handler | ||
279 | * @param[in] uf unsolicited frame descriptor | ||
280 | * | ||
281 | * @return None | ||
282 | */ | ||
283 | typedef void (*bfa_cb_uf_recv_t) (void *cbarg, struct bfa_uf_s *uf); | ||
284 | |||
285 | /* | ||
286 | * bfa uf API functions | ||
287 | */ | ||
288 | void bfa_uf_recv_register(struct bfa_s *bfa, bfa_cb_uf_recv_t ufrecv, | ||
289 | void *cbarg); | ||
290 | void bfa_uf_free(struct bfa_uf_s *uf); | ||
291 | |||
292 | /** | ||
293 | * bfa lport service api | ||
294 | */ | ||
295 | |||
296 | struct bfa_lps_s *bfa_lps_alloc(struct bfa_s *bfa); | ||
297 | void bfa_lps_delete(struct bfa_lps_s *lps); | ||
298 | void bfa_lps_discard(struct bfa_lps_s *lps); | ||
299 | void bfa_lps_flogi(struct bfa_lps_s *lps, void *uarg, u8 alpa, u16 pdusz, | ||
300 | wwn_t pwwn, wwn_t nwwn, bfa_boolean_t auth_en); | ||
301 | void bfa_lps_fdisc(struct bfa_lps_s *lps, void *uarg, u16 pdusz, wwn_t pwwn, | ||
302 | wwn_t nwwn); | ||
303 | void bfa_lps_flogo(struct bfa_lps_s *lps); | ||
304 | void bfa_lps_fdisclogo(struct bfa_lps_s *lps); | ||
305 | u8 bfa_lps_get_tag(struct bfa_lps_s *lps); | ||
306 | bfa_boolean_t bfa_lps_is_npiv_en(struct bfa_lps_s *lps); | ||
307 | bfa_boolean_t bfa_lps_is_fport(struct bfa_lps_s *lps); | ||
308 | bfa_boolean_t bfa_lps_is_brcd_fabric(struct bfa_lps_s *lps); | ||
309 | bfa_boolean_t bfa_lps_is_authreq(struct bfa_lps_s *lps); | ||
310 | bfa_eproto_status_t bfa_lps_get_extstatus(struct bfa_lps_s *lps); | ||
311 | u32 bfa_lps_get_pid(struct bfa_lps_s *lps); | ||
312 | u8 bfa_lps_get_tag_from_pid(struct bfa_s *bfa, u32 pid); | ||
313 | u16 bfa_lps_get_peer_bbcredit(struct bfa_lps_s *lps); | ||
314 | wwn_t bfa_lps_get_peer_pwwn(struct bfa_lps_s *lps); | ||
315 | wwn_t bfa_lps_get_peer_nwwn(struct bfa_lps_s *lps); | ||
316 | u8 bfa_lps_get_lsrjt_rsn(struct bfa_lps_s *lps); | ||
317 | u8 bfa_lps_get_lsrjt_expl(struct bfa_lps_s *lps); | ||
318 | void bfa_cb_lps_flogi_comp(void *bfad, void *uarg, bfa_status_t status); | ||
319 | void bfa_cb_lps_flogo_comp(void *bfad, void *uarg); | ||
320 | void bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status); | ||
321 | void bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg); | ||
322 | |||
323 | #endif /* __BFA_SVC_H__ */ | ||
324 | |||
diff --git a/drivers/scsi/bfa/include/bfa_timer.h b/drivers/scsi/bfa/include/bfa_timer.h new file mode 100644 index 000000000000..e407103fa565 --- /dev/null +++ b/drivers/scsi/bfa/include/bfa_timer.h | |||
@@ -0,0 +1,53 @@ | |||
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 | #ifndef __BFA_TIMER_H__ | ||
18 | #define __BFA_TIMER_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | #include <cs/bfa_q.h> | ||
22 | |||
23 | struct bfa_s; | ||
24 | |||
25 | typedef void (*bfa_timer_cbfn_t)(void *); | ||
26 | |||
27 | /** | ||
28 | * BFA timer data structure | ||
29 | */ | ||
30 | struct bfa_timer_s { | ||
31 | struct list_head qe; | ||
32 | bfa_timer_cbfn_t timercb; | ||
33 | void *arg; | ||
34 | int timeout; /**< in millisecs. */ | ||
35 | }; | ||
36 | |||
37 | /** | ||
38 | * Timer module structure | ||
39 | */ | ||
40 | struct bfa_timer_mod_s { | ||
41 | struct list_head timer_q; | ||
42 | }; | ||
43 | |||
44 | #define BFA_TIMER_FREQ 500 /**< specified in millisecs */ | ||
45 | |||
46 | void bfa_timer_beat(struct bfa_timer_mod_s *mod); | ||
47 | void bfa_timer_init(struct bfa_timer_mod_s *mod); | ||
48 | void bfa_timer_begin(struct bfa_timer_mod_s *mod, struct bfa_timer_s *timer, | ||
49 | bfa_timer_cbfn_t timercb, void *arg, | ||
50 | unsigned int timeout); | ||
51 | void bfa_timer_stop(struct bfa_timer_s *timer); | ||
52 | |||
53 | #endif /* __BFA_TIMER_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/bfi/bfi.h b/drivers/scsi/bfa/include/bfi/bfi.h new file mode 100644 index 000000000000..6cadfe0d4ba1 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi.h | |||
@@ -0,0 +1,174 @@ | |||
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 | #ifndef __BFI_H__ | ||
19 | #define __BFI_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include <defs/bfa_defs_status.h> | ||
23 | |||
24 | #pragma pack(1) | ||
25 | |||
26 | /** | ||
27 | * Msg header common to all msgs | ||
28 | */ | ||
29 | struct bfi_mhdr_s { | ||
30 | u8 msg_class; /* @ref bfi_mclass_t */ | ||
31 | u8 msg_id; /* msg opcode with in the class */ | ||
32 | union { | ||
33 | struct { | ||
34 | u8 rsvd; | ||
35 | u8 lpu_id; /* msg destination */ | ||
36 | } h2i; | ||
37 | u16 i2htok; /* token in msgs to host */ | ||
38 | } mtag; | ||
39 | }; | ||
40 | |||
41 | #define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \ | ||
42 | (_mh).msg_class = (_mc); \ | ||
43 | (_mh).msg_id = (_op); \ | ||
44 | (_mh).mtag.h2i.lpu_id = (_lpuid); \ | ||
45 | } while (0) | ||
46 | |||
47 | #define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \ | ||
48 | (_mh).msg_class = (_mc); \ | ||
49 | (_mh).msg_id = (_op); \ | ||
50 | (_mh).mtag.i2htok = (_i2htok); \ | ||
51 | } while (0) | ||
52 | |||
53 | /* | ||
54 | * Message opcodes: 0-127 to firmware, 128-255 to host | ||
55 | */ | ||
56 | #define BFI_I2H_OPCODE_BASE 128 | ||
57 | #define BFA_I2HM(_x) ((_x) + BFI_I2H_OPCODE_BASE) | ||
58 | |||
59 | /** | ||
60 | **************************************************************************** | ||
61 | * | ||
62 | * Scatter Gather Element and Page definition | ||
63 | * | ||
64 | **************************************************************************** | ||
65 | */ | ||
66 | |||
67 | #define BFI_SGE_INLINE 1 | ||
68 | #define BFI_SGE_INLINE_MAX (BFI_SGE_INLINE + 1) | ||
69 | |||
70 | /** | ||
71 | * SG Flags | ||
72 | */ | ||
73 | enum { | ||
74 | BFI_SGE_DATA = 0, /* data address, not last */ | ||
75 | BFI_SGE_DATA_CPL = 1, /* data addr, last in current page */ | ||
76 | BFI_SGE_DATA_LAST = 3, /* data address, last */ | ||
77 | BFI_SGE_LINK = 2, /* link address */ | ||
78 | BFI_SGE_PGDLEN = 2, /* cumulative data length for page */ | ||
79 | }; | ||
80 | |||
81 | /** | ||
82 | * DMA addresses | ||
83 | */ | ||
84 | union bfi_addr_u { | ||
85 | struct { | ||
86 | u32 addr_lo; | ||
87 | u32 addr_hi; | ||
88 | } a32; | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * Scatter Gather Element | ||
93 | */ | ||
94 | struct bfi_sge_s { | ||
95 | #ifdef __BIGENDIAN | ||
96 | u32 flags : 2, | ||
97 | rsvd : 2, | ||
98 | sg_len : 28; | ||
99 | #else | ||
100 | u32 sg_len : 28, | ||
101 | rsvd : 2, | ||
102 | flags : 2; | ||
103 | #endif | ||
104 | union bfi_addr_u sga; | ||
105 | }; | ||
106 | |||
107 | /** | ||
108 | * Scatter Gather Page | ||
109 | */ | ||
110 | #define BFI_SGPG_DATA_SGES 7 | ||
111 | #define BFI_SGPG_SGES_MAX (BFI_SGPG_DATA_SGES + 1) | ||
112 | #define BFI_SGPG_RSVD_WD_LEN 8 | ||
113 | struct bfi_sgpg_s { | ||
114 | struct bfi_sge_s sges[BFI_SGPG_SGES_MAX]; | ||
115 | u32 rsvd[BFI_SGPG_RSVD_WD_LEN]; | ||
116 | }; | ||
117 | |||
118 | /* | ||
119 | * Large Message structure - 128 Bytes size Msgs | ||
120 | */ | ||
121 | #define BFI_LMSG_SZ 128 | ||
122 | #define BFI_LMSG_PL_WSZ \ | ||
123 | ((BFI_LMSG_SZ - sizeof(struct bfi_mhdr_s)) / 4) | ||
124 | |||
125 | struct bfi_msg_s { | ||
126 | struct bfi_mhdr_s mhdr; | ||
127 | u32 pl[BFI_LMSG_PL_WSZ]; | ||
128 | }; | ||
129 | |||
130 | /** | ||
131 | * Mailbox message structure | ||
132 | */ | ||
133 | #define BFI_MBMSG_SZ 7 | ||
134 | struct bfi_mbmsg_s { | ||
135 | struct bfi_mhdr_s mh; | ||
136 | u32 pl[BFI_MBMSG_SZ]; | ||
137 | }; | ||
138 | |||
139 | /** | ||
140 | * Message Classes | ||
141 | */ | ||
142 | enum bfi_mclass { | ||
143 | BFI_MC_IOC = 1, /* IO Controller (IOC) */ | ||
144 | BFI_MC_DIAG = 2, /* Diagnostic Msgs */ | ||
145 | BFI_MC_FLASH = 3, /* Flash message class */ | ||
146 | BFI_MC_CEE = 4, | ||
147 | BFI_MC_FC_PORT = 5, /* FC port */ | ||
148 | BFI_MC_IOCFC = 6, /* FC - IO Controller (IOC) */ | ||
149 | BFI_MC_LL = 7, /* Link Layer */ | ||
150 | BFI_MC_UF = 8, /* Unsolicited frame receive */ | ||
151 | BFI_MC_FCXP = 9, /* FC Transport */ | ||
152 | BFI_MC_LPS = 10, /* lport fc login services */ | ||
153 | BFI_MC_RPORT = 11, /* Remote port */ | ||
154 | BFI_MC_ITNIM = 12, /* I-T nexus (Initiator mode) */ | ||
155 | BFI_MC_IOIM_READ = 13, /* read IO (Initiator mode) */ | ||
156 | BFI_MC_IOIM_WRITE = 14, /* write IO (Initiator mode) */ | ||
157 | BFI_MC_IOIM_IO = 15, /* IO (Initiator mode) */ | ||
158 | BFI_MC_IOIM = 16, /* IO (Initiator mode) */ | ||
159 | BFI_MC_IOIM_IOCOM = 17, /* good IO completion */ | ||
160 | BFI_MC_TSKIM = 18, /* Initiator Task management */ | ||
161 | BFI_MC_SBOOT = 19, /* SAN boot services */ | ||
162 | BFI_MC_IPFC = 20, /* IP over FC Msgs */ | ||
163 | BFI_MC_PORT = 21, /* Physical port */ | ||
164 | BFI_MC_MAX = 32 | ||
165 | }; | ||
166 | |||
167 | #define BFI_IOC_MAX_CQS 4 | ||
168 | #define BFI_IOC_MAX_CQS_ASIC 8 | ||
169 | #define BFI_IOC_MSGLEN_MAX 32 /* 32 bytes */ | ||
170 | |||
171 | #pragma pack() | ||
172 | |||
173 | #endif /* __BFI_H__ */ | ||
174 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_boot.h b/drivers/scsi/bfa/include/bfi/bfi_boot.h new file mode 100644 index 000000000000..5955afe7d108 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_boot.h | |||
@@ -0,0 +1,34 @@ | |||
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 | * bfi_boot.h | ||
19 | */ | ||
20 | |||
21 | #ifndef __BFI_BOOT_H__ | ||
22 | #define __BFI_BOOT_H__ | ||
23 | |||
24 | #define BFI_BOOT_TYPE_OFF 8 | ||
25 | #define BFI_BOOT_PARAM_OFF 12 | ||
26 | |||
27 | #define BFI_BOOT_TYPE_NORMAL 0 /* param is device id */ | ||
28 | #define BFI_BOOT_TYPE_FLASH 1 | ||
29 | #define BFI_BOOT_TYPE_MEMTEST 2 | ||
30 | |||
31 | #define BFI_BOOT_MEMTEST_RES_ADDR 0x900 | ||
32 | #define BFI_BOOT_MEMTEST_RES_SIG 0xA0A1A2A3 | ||
33 | |||
34 | #endif | ||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cbreg.h b/drivers/scsi/bfa/include/bfi/bfi_cbreg.h new file mode 100644 index 000000000000..b3bb52b565b1 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_cbreg.h | |||
@@ -0,0 +1,305 @@ | |||
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 | * bfi_cbreg.h crossbow host block register definitions | ||
20 | * | ||
21 | * !!! Do not edit. Auto generated. !!! | ||
22 | */ | ||
23 | |||
24 | #ifndef __BFI_CBREG_H__ | ||
25 | #define __BFI_CBREG_H__ | ||
26 | |||
27 | |||
28 | #define HOSTFN0_INT_STATUS 0x00014000 | ||
29 | #define __HOSTFN0_INT_STATUS_LVL_MK 0x00f00000 | ||
30 | #define __HOSTFN0_INT_STATUS_LVL_SH 20 | ||
31 | #define __HOSTFN0_INT_STATUS_LVL(_v) ((_v) << __HOSTFN0_INT_STATUS_LVL_SH) | ||
32 | #define __HOSTFN0_INT_STATUS_P 0x000fffff | ||
33 | #define HOSTFN0_INT_MSK 0x00014004 | ||
34 | #define HOST_PAGE_NUM_FN0 0x00014008 | ||
35 | #define __HOST_PAGE_NUM_FN 0x000001ff | ||
36 | #define HOSTFN1_INT_STATUS 0x00014100 | ||
37 | #define __HOSTFN1_INT_STAT_LVL_MK 0x00f00000 | ||
38 | #define __HOSTFN1_INT_STAT_LVL_SH 20 | ||
39 | #define __HOSTFN1_INT_STAT_LVL(_v) ((_v) << __HOSTFN1_INT_STAT_LVL_SH) | ||
40 | #define __HOSTFN1_INT_STAT_P 0x000fffff | ||
41 | #define HOSTFN1_INT_MSK 0x00014104 | ||
42 | #define HOST_PAGE_NUM_FN1 0x00014108 | ||
43 | #define APP_PLL_400_CTL_REG 0x00014204 | ||
44 | #define __P_400_PLL_LOCK 0x80000000 | ||
45 | #define __APP_PLL_400_SRAM_USE_100MHZ 0x00100000 | ||
46 | #define __APP_PLL_400_RESET_TIMER_MK 0x000e0000 | ||
47 | #define __APP_PLL_400_RESET_TIMER_SH 17 | ||
48 | #define __APP_PLL_400_RESET_TIMER(_v) ((_v) << __APP_PLL_400_RESET_TIMER_SH) | ||
49 | #define __APP_PLL_400_LOGIC_SOFT_RESET 0x00010000 | ||
50 | #define __APP_PLL_400_CNTLMT0_1_MK 0x0000c000 | ||
51 | #define __APP_PLL_400_CNTLMT0_1_SH 14 | ||
52 | #define __APP_PLL_400_CNTLMT0_1(_v) ((_v) << __APP_PLL_400_CNTLMT0_1_SH) | ||
53 | #define __APP_PLL_400_JITLMT0_1_MK 0x00003000 | ||
54 | #define __APP_PLL_400_JITLMT0_1_SH 12 | ||
55 | #define __APP_PLL_400_JITLMT0_1(_v) ((_v) << __APP_PLL_400_JITLMT0_1_SH) | ||
56 | #define __APP_PLL_400_HREF 0x00000800 | ||
57 | #define __APP_PLL_400_HDIV 0x00000400 | ||
58 | #define __APP_PLL_400_P0_1_MK 0x00000300 | ||
59 | #define __APP_PLL_400_P0_1_SH 8 | ||
60 | #define __APP_PLL_400_P0_1(_v) ((_v) << __APP_PLL_400_P0_1_SH) | ||
61 | #define __APP_PLL_400_Z0_2_MK 0x000000e0 | ||
62 | #define __APP_PLL_400_Z0_2_SH 5 | ||
63 | #define __APP_PLL_400_Z0_2(_v) ((_v) << __APP_PLL_400_Z0_2_SH) | ||
64 | #define __APP_PLL_400_RSEL200500 0x00000010 | ||
65 | #define __APP_PLL_400_ENARST 0x00000008 | ||
66 | #define __APP_PLL_400_BYPASS 0x00000004 | ||
67 | #define __APP_PLL_400_LRESETN 0x00000002 | ||
68 | #define __APP_PLL_400_ENABLE 0x00000001 | ||
69 | #define APP_PLL_212_CTL_REG 0x00014208 | ||
70 | #define __P_212_PLL_LOCK 0x80000000 | ||
71 | #define __APP_PLL_212_RESET_TIMER_MK 0x000e0000 | ||
72 | #define __APP_PLL_212_RESET_TIMER_SH 17 | ||
73 | #define __APP_PLL_212_RESET_TIMER(_v) ((_v) << __APP_PLL_212_RESET_TIMER_SH) | ||
74 | #define __APP_PLL_212_LOGIC_SOFT_RESET 0x00010000 | ||
75 | #define __APP_PLL_212_CNTLMT0_1_MK 0x0000c000 | ||
76 | #define __APP_PLL_212_CNTLMT0_1_SH 14 | ||
77 | #define __APP_PLL_212_CNTLMT0_1(_v) ((_v) << __APP_PLL_212_CNTLMT0_1_SH) | ||
78 | #define __APP_PLL_212_JITLMT0_1_MK 0x00003000 | ||
79 | #define __APP_PLL_212_JITLMT0_1_SH 12 | ||
80 | #define __APP_PLL_212_JITLMT0_1(_v) ((_v) << __APP_PLL_212_JITLMT0_1_SH) | ||
81 | #define __APP_PLL_212_HREF 0x00000800 | ||
82 | #define __APP_PLL_212_HDIV 0x00000400 | ||
83 | #define __APP_PLL_212_P0_1_MK 0x00000300 | ||
84 | #define __APP_PLL_212_P0_1_SH 8 | ||
85 | #define __APP_PLL_212_P0_1(_v) ((_v) << __APP_PLL_212_P0_1_SH) | ||
86 | #define __APP_PLL_212_Z0_2_MK 0x000000e0 | ||
87 | #define __APP_PLL_212_Z0_2_SH 5 | ||
88 | #define __APP_PLL_212_Z0_2(_v) ((_v) << __APP_PLL_212_Z0_2_SH) | ||
89 | #define __APP_PLL_212_RSEL200500 0x00000010 | ||
90 | #define __APP_PLL_212_ENARST 0x00000008 | ||
91 | #define __APP_PLL_212_BYPASS 0x00000004 | ||
92 | #define __APP_PLL_212_LRESETN 0x00000002 | ||
93 | #define __APP_PLL_212_ENABLE 0x00000001 | ||
94 | #define HOST_SEM0_REG 0x00014230 | ||
95 | #define __HOST_SEMAPHORE 0x00000001 | ||
96 | #define HOST_SEM1_REG 0x00014234 | ||
97 | #define HOST_SEM2_REG 0x00014238 | ||
98 | #define HOST_SEM3_REG 0x0001423c | ||
99 | #define HOST_SEM0_INFO_REG 0x00014240 | ||
100 | #define HOST_SEM1_INFO_REG 0x00014244 | ||
101 | #define HOST_SEM2_INFO_REG 0x00014248 | ||
102 | #define HOST_SEM3_INFO_REG 0x0001424c | ||
103 | #define HOSTFN0_LPU0_CMD_STAT 0x00019000 | ||
104 | #define __HOSTFN0_LPU0_MBOX_INFO_MK 0xfffffffe | ||
105 | #define __HOSTFN0_LPU0_MBOX_INFO_SH 1 | ||
106 | #define __HOSTFN0_LPU0_MBOX_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX_INFO_SH) | ||
107 | #define __HOSTFN0_LPU0_MBOX_CMD_STATUS 0x00000001 | ||
108 | #define LPU0_HOSTFN0_CMD_STAT 0x00019008 | ||
109 | #define __LPU0_HOSTFN0_MBOX_INFO_MK 0xfffffffe | ||
110 | #define __LPU0_HOSTFN0_MBOX_INFO_SH 1 | ||
111 | #define __LPU0_HOSTFN0_MBOX_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX_INFO_SH) | ||
112 | #define __LPU0_HOSTFN0_MBOX_CMD_STATUS 0x00000001 | ||
113 | #define HOSTFN1_LPU1_CMD_STAT 0x00019014 | ||
114 | #define __HOSTFN1_LPU1_MBOX_INFO_MK 0xfffffffe | ||
115 | #define __HOSTFN1_LPU1_MBOX_INFO_SH 1 | ||
116 | #define __HOSTFN1_LPU1_MBOX_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX_INFO_SH) | ||
117 | #define __HOSTFN1_LPU1_MBOX_CMD_STATUS 0x00000001 | ||
118 | #define LPU1_HOSTFN1_CMD_STAT 0x0001901c | ||
119 | #define __LPU1_HOSTFN1_MBOX_INFO_MK 0xfffffffe | ||
120 | #define __LPU1_HOSTFN1_MBOX_INFO_SH 1 | ||
121 | #define __LPU1_HOSTFN1_MBOX_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX_INFO_SH) | ||
122 | #define __LPU1_HOSTFN1_MBOX_CMD_STATUS 0x00000001 | ||
123 | #define CPE_Q0_DEPTH 0x00010014 | ||
124 | #define CPE_Q0_PI 0x0001001c | ||
125 | #define CPE_Q0_CI 0x00010020 | ||
126 | #define CPE_Q1_DEPTH 0x00010034 | ||
127 | #define CPE_Q1_PI 0x0001003c | ||
128 | #define CPE_Q1_CI 0x00010040 | ||
129 | #define CPE_Q2_DEPTH 0x00010054 | ||
130 | #define CPE_Q2_PI 0x0001005c | ||
131 | #define CPE_Q2_CI 0x00010060 | ||
132 | #define CPE_Q3_DEPTH 0x00010074 | ||
133 | #define CPE_Q3_PI 0x0001007c | ||
134 | #define CPE_Q3_CI 0x00010080 | ||
135 | #define CPE_Q4_DEPTH 0x00010094 | ||
136 | #define CPE_Q4_PI 0x0001009c | ||
137 | #define CPE_Q4_CI 0x000100a0 | ||
138 | #define CPE_Q5_DEPTH 0x000100b4 | ||
139 | #define CPE_Q5_PI 0x000100bc | ||
140 | #define CPE_Q5_CI 0x000100c0 | ||
141 | #define CPE_Q6_DEPTH 0x000100d4 | ||
142 | #define CPE_Q6_PI 0x000100dc | ||
143 | #define CPE_Q6_CI 0x000100e0 | ||
144 | #define CPE_Q7_DEPTH 0x000100f4 | ||
145 | #define CPE_Q7_PI 0x000100fc | ||
146 | #define CPE_Q7_CI 0x00010100 | ||
147 | #define RME_Q0_DEPTH 0x00011014 | ||
148 | #define RME_Q0_PI 0x0001101c | ||
149 | #define RME_Q0_CI 0x00011020 | ||
150 | #define RME_Q1_DEPTH 0x00011034 | ||
151 | #define RME_Q1_PI 0x0001103c | ||
152 | #define RME_Q1_CI 0x00011040 | ||
153 | #define RME_Q2_DEPTH 0x00011054 | ||
154 | #define RME_Q2_PI 0x0001105c | ||
155 | #define RME_Q2_CI 0x00011060 | ||
156 | #define RME_Q3_DEPTH 0x00011074 | ||
157 | #define RME_Q3_PI 0x0001107c | ||
158 | #define RME_Q3_CI 0x00011080 | ||
159 | #define RME_Q4_DEPTH 0x00011094 | ||
160 | #define RME_Q4_PI 0x0001109c | ||
161 | #define RME_Q4_CI 0x000110a0 | ||
162 | #define RME_Q5_DEPTH 0x000110b4 | ||
163 | #define RME_Q5_PI 0x000110bc | ||
164 | #define RME_Q5_CI 0x000110c0 | ||
165 | #define RME_Q6_DEPTH 0x000110d4 | ||
166 | #define RME_Q6_PI 0x000110dc | ||
167 | #define RME_Q6_CI 0x000110e0 | ||
168 | #define RME_Q7_DEPTH 0x000110f4 | ||
169 | #define RME_Q7_PI 0x000110fc | ||
170 | #define RME_Q7_CI 0x00011100 | ||
171 | #define PSS_CTL_REG 0x00018800 | ||
172 | #define __PSS_I2C_CLK_DIV_MK 0x00030000 | ||
173 | #define __PSS_I2C_CLK_DIV_SH 16 | ||
174 | #define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH) | ||
175 | #define __PSS_LMEM_INIT_DONE 0x00001000 | ||
176 | #define __PSS_LMEM_RESET 0x00000200 | ||
177 | #define __PSS_LMEM_INIT_EN 0x00000100 | ||
178 | #define __PSS_LPU1_RESET 0x00000002 | ||
179 | #define __PSS_LPU0_RESET 0x00000001 | ||
180 | |||
181 | |||
182 | /* | ||
183 | * These definitions are either in error/missing in spec. Its auto-generated | ||
184 | * from hard coded values in regparse.pl. | ||
185 | */ | ||
186 | #define __EMPHPOST_AT_4G_MK_FIX 0x0000001c | ||
187 | #define __EMPHPOST_AT_4G_SH_FIX 0x00000002 | ||
188 | #define __EMPHPRE_AT_4G_FIX 0x00000003 | ||
189 | #define __SFP_TXRATE_EN_FIX 0x00000100 | ||
190 | #define __SFP_RXRATE_EN_FIX 0x00000080 | ||
191 | |||
192 | |||
193 | /* | ||
194 | * These register definitions are auto-generated from hard coded values | ||
195 | * in regparse.pl. | ||
196 | */ | ||
197 | #define HOSTFN0_LPU_MBOX0_0 0x00019200 | ||
198 | #define HOSTFN1_LPU_MBOX0_8 0x00019260 | ||
199 | #define LPU_HOSTFN0_MBOX0_0 0x00019280 | ||
200 | #define LPU_HOSTFN1_MBOX0_8 0x000192e0 | ||
201 | |||
202 | |||
203 | /* | ||
204 | * These register mapping definitions are auto-generated from mapping tables | ||
205 | * in regparse.pl. | ||
206 | */ | ||
207 | #define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG | ||
208 | #define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG | ||
209 | #define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG | ||
210 | #define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG | ||
211 | #define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG | ||
212 | |||
213 | #define CPE_Q_DEPTH(__n) \ | ||
214 | (CPE_Q0_DEPTH + (__n) * (CPE_Q1_DEPTH - CPE_Q0_DEPTH)) | ||
215 | #define CPE_Q_PI(__n) \ | ||
216 | (CPE_Q0_PI + (__n) * (CPE_Q1_PI - CPE_Q0_PI)) | ||
217 | #define CPE_Q_CI(__n) \ | ||
218 | (CPE_Q0_CI + (__n) * (CPE_Q1_CI - CPE_Q0_CI)) | ||
219 | #define RME_Q_DEPTH(__n) \ | ||
220 | (RME_Q0_DEPTH + (__n) * (RME_Q1_DEPTH - RME_Q0_DEPTH)) | ||
221 | #define RME_Q_PI(__n) \ | ||
222 | (RME_Q0_PI + (__n) * (RME_Q1_PI - RME_Q0_PI)) | ||
223 | #define RME_Q_CI(__n) \ | ||
224 | (RME_Q0_CI + (__n) * (RME_Q1_CI - RME_Q0_CI)) | ||
225 | |||
226 | #define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) | ||
227 | #define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) | ||
228 | #define CPE_Q_MASK(__q) ((__q) & 0x3) | ||
229 | #define RME_Q_MASK(__q) ((__q) & 0x3) | ||
230 | |||
231 | |||
232 | /* | ||
233 | * PCI MSI-X vector defines | ||
234 | */ | ||
235 | enum { | ||
236 | BFA_MSIX_CPE_Q0 = 0, | ||
237 | BFA_MSIX_CPE_Q1 = 1, | ||
238 | BFA_MSIX_CPE_Q2 = 2, | ||
239 | BFA_MSIX_CPE_Q3 = 3, | ||
240 | BFA_MSIX_CPE_Q4 = 4, | ||
241 | BFA_MSIX_CPE_Q5 = 5, | ||
242 | BFA_MSIX_CPE_Q6 = 6, | ||
243 | BFA_MSIX_CPE_Q7 = 7, | ||
244 | BFA_MSIX_RME_Q0 = 8, | ||
245 | BFA_MSIX_RME_Q1 = 9, | ||
246 | BFA_MSIX_RME_Q2 = 10, | ||
247 | BFA_MSIX_RME_Q3 = 11, | ||
248 | BFA_MSIX_RME_Q4 = 12, | ||
249 | BFA_MSIX_RME_Q5 = 13, | ||
250 | BFA_MSIX_RME_Q6 = 14, | ||
251 | BFA_MSIX_RME_Q7 = 15, | ||
252 | BFA_MSIX_ERR_EMC = 16, | ||
253 | BFA_MSIX_ERR_LPU0 = 17, | ||
254 | BFA_MSIX_ERR_LPU1 = 18, | ||
255 | BFA_MSIX_ERR_PSS = 19, | ||
256 | BFA_MSIX_MBOX_LPU0 = 20, | ||
257 | BFA_MSIX_MBOX_LPU1 = 21, | ||
258 | BFA_MSIX_CB_MAX = 22, | ||
259 | }; | ||
260 | |||
261 | /* | ||
262 | * And corresponding host interrupt status bit field defines | ||
263 | */ | ||
264 | #define __HFN_INT_CPE_Q0 0x00000001U | ||
265 | #define __HFN_INT_CPE_Q1 0x00000002U | ||
266 | #define __HFN_INT_CPE_Q2 0x00000004U | ||
267 | #define __HFN_INT_CPE_Q3 0x00000008U | ||
268 | #define __HFN_INT_CPE_Q4 0x00000010U | ||
269 | #define __HFN_INT_CPE_Q5 0x00000020U | ||
270 | #define __HFN_INT_CPE_Q6 0x00000040U | ||
271 | #define __HFN_INT_CPE_Q7 0x00000080U | ||
272 | #define __HFN_INT_RME_Q0 0x00000100U | ||
273 | #define __HFN_INT_RME_Q1 0x00000200U | ||
274 | #define __HFN_INT_RME_Q2 0x00000400U | ||
275 | #define __HFN_INT_RME_Q3 0x00000800U | ||
276 | #define __HFN_INT_RME_Q4 0x00001000U | ||
277 | #define __HFN_INT_RME_Q5 0x00002000U | ||
278 | #define __HFN_INT_RME_Q6 0x00004000U | ||
279 | #define __HFN_INT_RME_Q7 0x00008000U | ||
280 | #define __HFN_INT_ERR_EMC 0x00010000U | ||
281 | #define __HFN_INT_ERR_LPU0 0x00020000U | ||
282 | #define __HFN_INT_ERR_LPU1 0x00040000U | ||
283 | #define __HFN_INT_ERR_PSS 0x00080000U | ||
284 | #define __HFN_INT_MBOX_LPU0 0x00100000U | ||
285 | #define __HFN_INT_MBOX_LPU1 0x00200000U | ||
286 | #define __HFN_INT_MBOX1_LPU0 0x00400000U | ||
287 | #define __HFN_INT_MBOX1_LPU1 0x00800000U | ||
288 | #define __HFN_INT_CPE_MASK 0x000000ffU | ||
289 | #define __HFN_INT_RME_MASK 0x0000ff00U | ||
290 | |||
291 | |||
292 | /* | ||
293 | * crossbow memory map. | ||
294 | */ | ||
295 | #define PSS_SMEM_PAGE_START 0x8000 | ||
296 | #define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15)) | ||
297 | #define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff) | ||
298 | |||
299 | /* | ||
300 | * End of crossbow memory map | ||
301 | */ | ||
302 | |||
303 | |||
304 | #endif /* __BFI_CBREG_H__ */ | ||
305 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_cee.h b/drivers/scsi/bfa/include/bfi/bfi_cee.h new file mode 100644 index 000000000000..0970596583ea --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_cee.h | |||
@@ -0,0 +1,119 @@ | |||
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 | * Copyright (c) 2006-2009 Brocade Communications Systems, Inc. | ||
19 | * All rights reserved. | ||
20 | * | ||
21 | * bfi_dcbx.h BFI Interface (Mailbox commands and related structures) | ||
22 | * between host driver and DCBX/LLDP firmware module. | ||
23 | * | ||
24 | **/ | ||
25 | |||
26 | #ifndef __BFI_CEE_H__ | ||
27 | #define __BFI_CEE_H__ | ||
28 | |||
29 | #include <bfi/bfi.h> | ||
30 | |||
31 | #pragma pack(1) | ||
32 | |||
33 | |||
34 | enum bfi_cee_h2i_msgs_e { | ||
35 | BFI_CEE_H2I_GET_CFG_REQ = 1, | ||
36 | BFI_CEE_H2I_RESET_STATS = 2, | ||
37 | BFI_CEE_H2I_GET_STATS_REQ = 3, | ||
38 | }; | ||
39 | |||
40 | |||
41 | enum bfi_cee_i2h_msgs_e { | ||
42 | BFI_CEE_I2H_GET_CFG_RSP = BFA_I2HM(1), | ||
43 | BFI_CEE_I2H_RESET_STATS_RSP = BFA_I2HM(2), | ||
44 | BFI_CEE_I2H_GET_STATS_RSP = BFA_I2HM(3), | ||
45 | }; | ||
46 | |||
47 | |||
48 | /* Data structures */ | ||
49 | |||
50 | /* | ||
51 | * BFI_CEE_H2I_RESET_STATS | ||
52 | */ | ||
53 | struct bfi_lldp_reset_stats_s { | ||
54 | struct bfi_mhdr_s mh; | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * BFI_CEE_H2I_RESET_STATS | ||
59 | */ | ||
60 | struct bfi_cee_reset_stats_s { | ||
61 | struct bfi_mhdr_s mh; | ||
62 | }; | ||
63 | |||
64 | /* | ||
65 | * BFI_CEE_H2I_GET_CFG_REQ | ||
66 | */ | ||
67 | struct bfi_cee_get_req_s { | ||
68 | struct bfi_mhdr_s mh; | ||
69 | union bfi_addr_u dma_addr; | ||
70 | }; | ||
71 | |||
72 | |||
73 | /* | ||
74 | * BFI_CEE_I2H_GET_CFG_RSP | ||
75 | */ | ||
76 | struct bfi_cee_get_rsp_s { | ||
77 | struct bfi_mhdr_s mh; | ||
78 | u8 cmd_status; | ||
79 | u8 rsvd[3]; | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * BFI_CEE_H2I_GET_STATS_REQ | ||
84 | */ | ||
85 | struct bfi_cee_stats_req_s { | ||
86 | struct bfi_mhdr_s mh; | ||
87 | union bfi_addr_u dma_addr; | ||
88 | }; | ||
89 | |||
90 | |||
91 | /* | ||
92 | * BFI_CEE_I2H_GET_STATS_RSP | ||
93 | */ | ||
94 | struct bfi_cee_stats_rsp_s { | ||
95 | struct bfi_mhdr_s mh; | ||
96 | u8 cmd_status; | ||
97 | u8 rsvd[3]; | ||
98 | }; | ||
99 | |||
100 | |||
101 | |||
102 | union bfi_cee_h2i_msg_u { | ||
103 | struct bfi_mhdr_s mh; | ||
104 | struct bfi_cee_get_req_s get_req; | ||
105 | struct bfi_cee_stats_req_s stats_req; | ||
106 | }; | ||
107 | |||
108 | |||
109 | union bfi_cee_i2h_msg_u { | ||
110 | struct bfi_mhdr_s mh; | ||
111 | struct bfi_cee_get_rsp_s get_rsp; | ||
112 | struct bfi_cee_stats_rsp_s stats_rsp; | ||
113 | }; | ||
114 | |||
115 | #pragma pack() | ||
116 | |||
117 | |||
118 | #endif /* __BFI_CEE_H__ */ | ||
119 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ctreg.h b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h new file mode 100644 index 000000000000..d3caa58c0a0a --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_ctreg.h | |||
@@ -0,0 +1,611 @@ | |||
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 | * bfi_ctreg.h catapult host block register definitions | ||
20 | * | ||
21 | * !!! Do not edit. Auto generated. !!! | ||
22 | */ | ||
23 | |||
24 | #ifndef __BFI_CTREG_H__ | ||
25 | #define __BFI_CTREG_H__ | ||
26 | |||
27 | |||
28 | #define HOSTFN0_LPU_MBOX0_0 0x00019200 | ||
29 | #define HOSTFN1_LPU_MBOX0_8 0x00019260 | ||
30 | #define LPU_HOSTFN0_MBOX0_0 0x00019280 | ||
31 | #define LPU_HOSTFN1_MBOX0_8 0x000192e0 | ||
32 | #define HOSTFN2_LPU_MBOX0_0 0x00019400 | ||
33 | #define HOSTFN3_LPU_MBOX0_8 0x00019460 | ||
34 | #define LPU_HOSTFN2_MBOX0_0 0x00019480 | ||
35 | #define LPU_HOSTFN3_MBOX0_8 0x000194e0 | ||
36 | #define HOSTFN0_INT_STATUS 0x00014000 | ||
37 | #define __HOSTFN0_HALT_OCCURRED 0x01000000 | ||
38 | #define __HOSTFN0_INT_STATUS_LVL_MK 0x00f00000 | ||
39 | #define __HOSTFN0_INT_STATUS_LVL_SH 20 | ||
40 | #define __HOSTFN0_INT_STATUS_LVL(_v) ((_v) << __HOSTFN0_INT_STATUS_LVL_SH) | ||
41 | #define __HOSTFN0_INT_STATUS_P_MK 0x000f0000 | ||
42 | #define __HOSTFN0_INT_STATUS_P_SH 16 | ||
43 | #define __HOSTFN0_INT_STATUS_P(_v) ((_v) << __HOSTFN0_INT_STATUS_P_SH) | ||
44 | #define __HOSTFN0_INT_STATUS_F 0x0000ffff | ||
45 | #define HOSTFN0_INT_MSK 0x00014004 | ||
46 | #define HOST_PAGE_NUM_FN0 0x00014008 | ||
47 | #define __HOST_PAGE_NUM_FN 0x000001ff | ||
48 | #define HOST_MSIX_ERR_INDEX_FN0 0x0001400c | ||
49 | #define __MSIX_ERR_INDEX_FN 0x000001ff | ||
50 | #define HOSTFN1_INT_STATUS 0x00014100 | ||
51 | #define __HOSTFN1_HALT_OCCURRED 0x01000000 | ||
52 | #define __HOSTFN1_INT_STATUS_LVL_MK 0x00f00000 | ||
53 | #define __HOSTFN1_INT_STATUS_LVL_SH 20 | ||
54 | #define __HOSTFN1_INT_STATUS_LVL(_v) ((_v) << __HOSTFN1_INT_STATUS_LVL_SH) | ||
55 | #define __HOSTFN1_INT_STATUS_P_MK 0x000f0000 | ||
56 | #define __HOSTFN1_INT_STATUS_P_SH 16 | ||
57 | #define __HOSTFN1_INT_STATUS_P(_v) ((_v) << __HOSTFN1_INT_STATUS_P_SH) | ||
58 | #define __HOSTFN1_INT_STATUS_F 0x0000ffff | ||
59 | #define HOSTFN1_INT_MSK 0x00014104 | ||
60 | #define HOST_PAGE_NUM_FN1 0x00014108 | ||
61 | #define HOST_MSIX_ERR_INDEX_FN1 0x0001410c | ||
62 | #define APP_PLL_425_CTL_REG 0x00014204 | ||
63 | #define __P_425_PLL_LOCK 0x80000000 | ||
64 | #define __APP_PLL_425_SRAM_USE_100MHZ 0x00100000 | ||
65 | #define __APP_PLL_425_RESET_TIMER_MK 0x000e0000 | ||
66 | #define __APP_PLL_425_RESET_TIMER_SH 17 | ||
67 | #define __APP_PLL_425_RESET_TIMER(_v) ((_v) << __APP_PLL_425_RESET_TIMER_SH) | ||
68 | #define __APP_PLL_425_LOGIC_SOFT_RESET 0x00010000 | ||
69 | #define __APP_PLL_425_CNTLMT0_1_MK 0x0000c000 | ||
70 | #define __APP_PLL_425_CNTLMT0_1_SH 14 | ||
71 | #define __APP_PLL_425_CNTLMT0_1(_v) ((_v) << __APP_PLL_425_CNTLMT0_1_SH) | ||
72 | #define __APP_PLL_425_JITLMT0_1_MK 0x00003000 | ||
73 | #define __APP_PLL_425_JITLMT0_1_SH 12 | ||
74 | #define __APP_PLL_425_JITLMT0_1(_v) ((_v) << __APP_PLL_425_JITLMT0_1_SH) | ||
75 | #define __APP_PLL_425_HREF 0x00000800 | ||
76 | #define __APP_PLL_425_HDIV 0x00000400 | ||
77 | #define __APP_PLL_425_P0_1_MK 0x00000300 | ||
78 | #define __APP_PLL_425_P0_1_SH 8 | ||
79 | #define __APP_PLL_425_P0_1(_v) ((_v) << __APP_PLL_425_P0_1_SH) | ||
80 | #define __APP_PLL_425_Z0_2_MK 0x000000e0 | ||
81 | #define __APP_PLL_425_Z0_2_SH 5 | ||
82 | #define __APP_PLL_425_Z0_2(_v) ((_v) << __APP_PLL_425_Z0_2_SH) | ||
83 | #define __APP_PLL_425_RSEL200500 0x00000010 | ||
84 | #define __APP_PLL_425_ENARST 0x00000008 | ||
85 | #define __APP_PLL_425_BYPASS 0x00000004 | ||
86 | #define __APP_PLL_425_LRESETN 0x00000002 | ||
87 | #define __APP_PLL_425_ENABLE 0x00000001 | ||
88 | #define APP_PLL_312_CTL_REG 0x00014208 | ||
89 | #define __P_312_PLL_LOCK 0x80000000 | ||
90 | #define __ENABLE_MAC_AHB_1 0x00800000 | ||
91 | #define __ENABLE_MAC_AHB_0 0x00400000 | ||
92 | #define __ENABLE_MAC_1 0x00200000 | ||
93 | #define __ENABLE_MAC_0 0x00100000 | ||
94 | #define __APP_PLL_312_RESET_TIMER_MK 0x000e0000 | ||
95 | #define __APP_PLL_312_RESET_TIMER_SH 17 | ||
96 | #define __APP_PLL_312_RESET_TIMER(_v) ((_v) << __APP_PLL_312_RESET_TIMER_SH) | ||
97 | #define __APP_PLL_312_LOGIC_SOFT_RESET 0x00010000 | ||
98 | #define __APP_PLL_312_CNTLMT0_1_MK 0x0000c000 | ||
99 | #define __APP_PLL_312_CNTLMT0_1_SH 14 | ||
100 | #define __APP_PLL_312_CNTLMT0_1(_v) ((_v) << __APP_PLL_312_CNTLMT0_1_SH) | ||
101 | #define __APP_PLL_312_JITLMT0_1_MK 0x00003000 | ||
102 | #define __APP_PLL_312_JITLMT0_1_SH 12 | ||
103 | #define __APP_PLL_312_JITLMT0_1(_v) ((_v) << __APP_PLL_312_JITLMT0_1_SH) | ||
104 | #define __APP_PLL_312_HREF 0x00000800 | ||
105 | #define __APP_PLL_312_HDIV 0x00000400 | ||
106 | #define __APP_PLL_312_P0_1_MK 0x00000300 | ||
107 | #define __APP_PLL_312_P0_1_SH 8 | ||
108 | #define __APP_PLL_312_P0_1(_v) ((_v) << __APP_PLL_312_P0_1_SH) | ||
109 | #define __APP_PLL_312_Z0_2_MK 0x000000e0 | ||
110 | #define __APP_PLL_312_Z0_2_SH 5 | ||
111 | #define __APP_PLL_312_Z0_2(_v) ((_v) << __APP_PLL_312_Z0_2_SH) | ||
112 | #define __APP_PLL_312_RSEL200500 0x00000010 | ||
113 | #define __APP_PLL_312_ENARST 0x00000008 | ||
114 | #define __APP_PLL_312_BYPASS 0x00000004 | ||
115 | #define __APP_PLL_312_LRESETN 0x00000002 | ||
116 | #define __APP_PLL_312_ENABLE 0x00000001 | ||
117 | #define MBIST_CTL_REG 0x00014220 | ||
118 | #define __EDRAM_BISTR_START 0x00000004 | ||
119 | #define __MBIST_RESET 0x00000002 | ||
120 | #define __MBIST_START 0x00000001 | ||
121 | #define MBIST_STAT_REG 0x00014224 | ||
122 | #define __EDRAM_BISTR_STATUS 0x00000008 | ||
123 | #define __EDRAM_BISTR_DONE 0x00000004 | ||
124 | #define __MEM_BIT_STATUS 0x00000002 | ||
125 | #define __MBIST_DONE 0x00000001 | ||
126 | #define HOST_SEM0_REG 0x00014230 | ||
127 | #define __HOST_SEMAPHORE 0x00000001 | ||
128 | #define HOST_SEM1_REG 0x00014234 | ||
129 | #define HOST_SEM2_REG 0x00014238 | ||
130 | #define HOST_SEM3_REG 0x0001423c | ||
131 | #define HOST_SEM0_INFO_REG 0x00014240 | ||
132 | #define HOST_SEM1_INFO_REG 0x00014244 | ||
133 | #define HOST_SEM2_INFO_REG 0x00014248 | ||
134 | #define HOST_SEM3_INFO_REG 0x0001424c | ||
135 | #define ETH_MAC_SER_REG 0x00014288 | ||
136 | #define __APP_EMS_CKBUFAMPIN 0x00000020 | ||
137 | #define __APP_EMS_REFCLKSEL 0x00000010 | ||
138 | #define __APP_EMS_CMLCKSEL 0x00000008 | ||
139 | #define __APP_EMS_REFCKBUFEN2 0x00000004 | ||
140 | #define __APP_EMS_REFCKBUFEN1 0x00000002 | ||
141 | #define __APP_EMS_CHANNEL_SEL 0x00000001 | ||
142 | #define HOSTFN2_INT_STATUS 0x00014300 | ||
143 | #define __HOSTFN2_HALT_OCCURRED 0x01000000 | ||
144 | #define __HOSTFN2_INT_STATUS_LVL_MK 0x00f00000 | ||
145 | #define __HOSTFN2_INT_STATUS_LVL_SH 20 | ||
146 | #define __HOSTFN2_INT_STATUS_LVL(_v) ((_v) << __HOSTFN2_INT_STATUS_LVL_SH) | ||
147 | #define __HOSTFN2_INT_STATUS_P_MK 0x000f0000 | ||
148 | #define __HOSTFN2_INT_STATUS_P_SH 16 | ||
149 | #define __HOSTFN2_INT_STATUS_P(_v) ((_v) << __HOSTFN2_INT_STATUS_P_SH) | ||
150 | #define __HOSTFN2_INT_STATUS_F 0x0000ffff | ||
151 | #define HOSTFN2_INT_MSK 0x00014304 | ||
152 | #define HOST_PAGE_NUM_FN2 0x00014308 | ||
153 | #define HOST_MSIX_ERR_INDEX_FN2 0x0001430c | ||
154 | #define HOSTFN3_INT_STATUS 0x00014400 | ||
155 | #define __HALT_OCCURRED 0x01000000 | ||
156 | #define __HOSTFN3_INT_STATUS_LVL_MK 0x00f00000 | ||
157 | #define __HOSTFN3_INT_STATUS_LVL_SH 20 | ||
158 | #define __HOSTFN3_INT_STATUS_LVL(_v) ((_v) << __HOSTFN3_INT_STATUS_LVL_SH) | ||
159 | #define __HOSTFN3_INT_STATUS_P_MK 0x000f0000 | ||
160 | #define __HOSTFN3_INT_STATUS_P_SH 16 | ||
161 | #define __HOSTFN3_INT_STATUS_P(_v) ((_v) << __HOSTFN3_INT_STATUS_P_SH) | ||
162 | #define __HOSTFN3_INT_STATUS_F 0x0000ffff | ||
163 | #define HOSTFN3_INT_MSK 0x00014404 | ||
164 | #define HOST_PAGE_NUM_FN3 0x00014408 | ||
165 | #define HOST_MSIX_ERR_INDEX_FN3 0x0001440c | ||
166 | #define FNC_ID_REG 0x00014600 | ||
167 | #define __FUNCTION_NUMBER 0x00000007 | ||
168 | #define FNC_PERS_REG 0x00014604 | ||
169 | #define __F3_FUNCTION_ACTIVE 0x80000000 | ||
170 | #define __F3_FUNCTION_MODE 0x40000000 | ||
171 | #define __F3_PORT_MAP_MK 0x30000000 | ||
172 | #define __F3_PORT_MAP_SH 28 | ||
173 | #define __F3_PORT_MAP(_v) ((_v) << __F3_PORT_MAP_SH) | ||
174 | #define __F3_VM_MODE 0x08000000 | ||
175 | #define __F3_INTX_STATUS_MK 0x07000000 | ||
176 | #define __F3_INTX_STATUS_SH 24 | ||
177 | #define __F3_INTX_STATUS(_v) ((_v) << __F3_INTX_STATUS_SH) | ||
178 | #define __F2_FUNCTION_ACTIVE 0x00800000 | ||
179 | #define __F2_FUNCTION_MODE 0x00400000 | ||
180 | #define __F2_PORT_MAP_MK 0x00300000 | ||
181 | #define __F2_PORT_MAP_SH 20 | ||
182 | #define __F2_PORT_MAP(_v) ((_v) << __F2_PORT_MAP_SH) | ||
183 | #define __F2_VM_MODE 0x00080000 | ||
184 | #define __F2_INTX_STATUS_MK 0x00070000 | ||
185 | #define __F2_INTX_STATUS_SH 16 | ||
186 | #define __F2_INTX_STATUS(_v) ((_v) << __F2_INTX_STATUS_SH) | ||
187 | #define __F1_FUNCTION_ACTIVE 0x00008000 | ||
188 | #define __F1_FUNCTION_MODE 0x00004000 | ||
189 | #define __F1_PORT_MAP_MK 0x00003000 | ||
190 | #define __F1_PORT_MAP_SH 12 | ||
191 | #define __F1_PORT_MAP(_v) ((_v) << __F1_PORT_MAP_SH) | ||
192 | #define __F1_VM_MODE 0x00000800 | ||
193 | #define __F1_INTX_STATUS_MK 0x00000700 | ||
194 | #define __F1_INTX_STATUS_SH 8 | ||
195 | #define __F1_INTX_STATUS(_v) ((_v) << __F1_INTX_STATUS_SH) | ||
196 | #define __F0_FUNCTION_ACTIVE 0x00000080 | ||
197 | #define __F0_FUNCTION_MODE 0x00000040 | ||
198 | #define __F0_PORT_MAP_MK 0x00000030 | ||
199 | #define __F0_PORT_MAP_SH 4 | ||
200 | #define __F0_PORT_MAP(_v) ((_v) << __F0_PORT_MAP_SH) | ||
201 | #define __F0_VM_MODE 0x00000008 | ||
202 | #define __F0_INTX_STATUS 0x00000007 | ||
203 | enum { | ||
204 | __F0_INTX_STATUS_MSIX = 0x0, | ||
205 | __F0_INTX_STATUS_INTA = 0x1, | ||
206 | __F0_INTX_STATUS_INTB = 0x2, | ||
207 | __F0_INTX_STATUS_INTC = 0x3, | ||
208 | __F0_INTX_STATUS_INTD = 0x4, | ||
209 | }; | ||
210 | #define OP_MODE 0x0001460c | ||
211 | #define __APP_ETH_CLK_LOWSPEED 0x00000004 | ||
212 | #define __GLOBAL_CORECLK_HALFSPEED 0x00000002 | ||
213 | #define __GLOBAL_FCOE_MODE 0x00000001 | ||
214 | #define HOST_SEM4_REG 0x00014610 | ||
215 | #define HOST_SEM5_REG 0x00014614 | ||
216 | #define HOST_SEM6_REG 0x00014618 | ||
217 | #define HOST_SEM7_REG 0x0001461c | ||
218 | #define HOST_SEM4_INFO_REG 0x00014620 | ||
219 | #define HOST_SEM5_INFO_REG 0x00014624 | ||
220 | #define HOST_SEM6_INFO_REG 0x00014628 | ||
221 | #define HOST_SEM7_INFO_REG 0x0001462c | ||
222 | #define HOSTFN0_LPU0_MBOX0_CMD_STAT 0x00019000 | ||
223 | #define __HOSTFN0_LPU0_MBOX0_INFO_MK 0xfffffffe | ||
224 | #define __HOSTFN0_LPU0_MBOX0_INFO_SH 1 | ||
225 | #define __HOSTFN0_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU0_MBOX0_INFO_SH) | ||
226 | #define __HOSTFN0_LPU0_MBOX0_CMD_STATUS 0x00000001 | ||
227 | #define HOSTFN0_LPU1_MBOX0_CMD_STAT 0x00019004 | ||
228 | #define __HOSTFN0_LPU1_MBOX0_INFO_MK 0xfffffffe | ||
229 | #define __HOSTFN0_LPU1_MBOX0_INFO_SH 1 | ||
230 | #define __HOSTFN0_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN0_LPU1_MBOX0_INFO_SH) | ||
231 | #define __HOSTFN0_LPU1_MBOX0_CMD_STATUS 0x00000001 | ||
232 | #define LPU0_HOSTFN0_MBOX0_CMD_STAT 0x00019008 | ||
233 | #define __LPU0_HOSTFN0_MBOX0_INFO_MK 0xfffffffe | ||
234 | #define __LPU0_HOSTFN0_MBOX0_INFO_SH 1 | ||
235 | #define __LPU0_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN0_MBOX0_INFO_SH) | ||
236 | #define __LPU0_HOSTFN0_MBOX0_CMD_STATUS 0x00000001 | ||
237 | #define LPU1_HOSTFN0_MBOX0_CMD_STAT 0x0001900c | ||
238 | #define __LPU1_HOSTFN0_MBOX0_INFO_MK 0xfffffffe | ||
239 | #define __LPU1_HOSTFN0_MBOX0_INFO_SH 1 | ||
240 | #define __LPU1_HOSTFN0_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN0_MBOX0_INFO_SH) | ||
241 | #define __LPU1_HOSTFN0_MBOX0_CMD_STATUS 0x00000001 | ||
242 | #define HOSTFN1_LPU0_MBOX0_CMD_STAT 0x00019010 | ||
243 | #define __HOSTFN1_LPU0_MBOX0_INFO_MK 0xfffffffe | ||
244 | #define __HOSTFN1_LPU0_MBOX0_INFO_SH 1 | ||
245 | #define __HOSTFN1_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU0_MBOX0_INFO_SH) | ||
246 | #define __HOSTFN1_LPU0_MBOX0_CMD_STATUS 0x00000001 | ||
247 | #define HOSTFN1_LPU1_MBOX0_CMD_STAT 0x00019014 | ||
248 | #define __HOSTFN1_LPU1_MBOX0_INFO_MK 0xfffffffe | ||
249 | #define __HOSTFN1_LPU1_MBOX0_INFO_SH 1 | ||
250 | #define __HOSTFN1_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN1_LPU1_MBOX0_INFO_SH) | ||
251 | #define __HOSTFN1_LPU1_MBOX0_CMD_STATUS 0x00000001 | ||
252 | #define LPU0_HOSTFN1_MBOX0_CMD_STAT 0x00019018 | ||
253 | #define __LPU0_HOSTFN1_MBOX0_INFO_MK 0xfffffffe | ||
254 | #define __LPU0_HOSTFN1_MBOX0_INFO_SH 1 | ||
255 | #define __LPU0_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN1_MBOX0_INFO_SH) | ||
256 | #define __LPU0_HOSTFN1_MBOX0_CMD_STATUS 0x00000001 | ||
257 | #define LPU1_HOSTFN1_MBOX0_CMD_STAT 0x0001901c | ||
258 | #define __LPU1_HOSTFN1_MBOX0_INFO_MK 0xfffffffe | ||
259 | #define __LPU1_HOSTFN1_MBOX0_INFO_SH 1 | ||
260 | #define __LPU1_HOSTFN1_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN1_MBOX0_INFO_SH) | ||
261 | #define __LPU1_HOSTFN1_MBOX0_CMD_STATUS 0x00000001 | ||
262 | #define HOSTFN2_LPU0_MBOX0_CMD_STAT 0x00019150 | ||
263 | #define __HOSTFN2_LPU0_MBOX0_INFO_MK 0xfffffffe | ||
264 | #define __HOSTFN2_LPU0_MBOX0_INFO_SH 1 | ||
265 | #define __HOSTFN2_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU0_MBOX0_INFO_SH) | ||
266 | #define __HOSTFN2_LPU0_MBOX0_CMD_STATUS 0x00000001 | ||
267 | #define HOSTFN2_LPU1_MBOX0_CMD_STAT 0x00019154 | ||
268 | #define __HOSTFN2_LPU1_MBOX0_INFO_MK 0xfffffffe | ||
269 | #define __HOSTFN2_LPU1_MBOX0_INFO_SH 1 | ||
270 | #define __HOSTFN2_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN2_LPU1_MBOX0_INFO_SH) | ||
271 | #define __HOSTFN2_LPU1_MBOX0BOX0_CMD_STATUS 0x00000001 | ||
272 | #define LPU0_HOSTFN2_MBOX0_CMD_STAT 0x00019158 | ||
273 | #define __LPU0_HOSTFN2_MBOX0_INFO_MK 0xfffffffe | ||
274 | #define __LPU0_HOSTFN2_MBOX0_INFO_SH 1 | ||
275 | #define __LPU0_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN2_MBOX0_INFO_SH) | ||
276 | #define __LPU0_HOSTFN2_MBOX0_CMD_STATUS 0x00000001 | ||
277 | #define LPU1_HOSTFN2_MBOX0_CMD_STAT 0x0001915c | ||
278 | #define __LPU1_HOSTFN2_MBOX0_INFO_MK 0xfffffffe | ||
279 | #define __LPU1_HOSTFN2_MBOX0_INFO_SH 1 | ||
280 | #define __LPU1_HOSTFN2_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN2_MBOX0_INFO_SH) | ||
281 | #define __LPU1_HOSTFN2_MBOX0_CMD_STATUS 0x00000001 | ||
282 | #define HOSTFN3_LPU0_MBOX0_CMD_STAT 0x00019160 | ||
283 | #define __HOSTFN3_LPU0_MBOX0_INFO_MK 0xfffffffe | ||
284 | #define __HOSTFN3_LPU0_MBOX0_INFO_SH 1 | ||
285 | #define __HOSTFN3_LPU0_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU0_MBOX0_INFO_SH) | ||
286 | #define __HOSTFN3_LPU0_MBOX0_CMD_STATUS 0x00000001 | ||
287 | #define HOSTFN3_LPU1_MBOX0_CMD_STAT 0x00019164 | ||
288 | #define __HOSTFN3_LPU1_MBOX0_INFO_MK 0xfffffffe | ||
289 | #define __HOSTFN3_LPU1_MBOX0_INFO_SH 1 | ||
290 | #define __HOSTFN3_LPU1_MBOX0_INFO(_v) ((_v) << __HOSTFN3_LPU1_MBOX0_INFO_SH) | ||
291 | #define __HOSTFN3_LPU1_MBOX0_CMD_STATUS 0x00000001 | ||
292 | #define LPU0_HOSTFN3_MBOX0_CMD_STAT 0x00019168 | ||
293 | #define __LPU0_HOSTFN3_MBOX0_INFO_MK 0xfffffffe | ||
294 | #define __LPU0_HOSTFN3_MBOX0_INFO_SH 1 | ||
295 | #define __LPU0_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU0_HOSTFN3_MBOX0_INFO_SH) | ||
296 | #define __LPU0_HOSTFN3_MBOX0_CMD_STATUS 0x00000001 | ||
297 | #define LPU1_HOSTFN3_MBOX0_CMD_STAT 0x0001916c | ||
298 | #define __LPU1_HOSTFN3_MBOX0_INFO_MK 0xfffffffe | ||
299 | #define __LPU1_HOSTFN3_MBOX0_INFO_SH 1 | ||
300 | #define __LPU1_HOSTFN3_MBOX0_INFO(_v) ((_v) << __LPU1_HOSTFN3_MBOX0_INFO_SH) | ||
301 | #define __LPU1_HOSTFN3_MBOX0_CMD_STATUS 0x00000001 | ||
302 | #define FW_INIT_HALT_P0 0x000191ac | ||
303 | #define __FW_INIT_HALT_P 0x00000001 | ||
304 | #define FW_INIT_HALT_P1 0x000191bc | ||
305 | #define CPE_PI_PTR_Q0 0x00038000 | ||
306 | #define __CPE_PI_UNUSED_MK 0xffff0000 | ||
307 | #define __CPE_PI_UNUSED_SH 16 | ||
308 | #define __CPE_PI_UNUSED(_v) ((_v) << __CPE_PI_UNUSED_SH) | ||
309 | #define __CPE_PI_PTR 0x0000ffff | ||
310 | #define CPE_PI_PTR_Q1 0x00038040 | ||
311 | #define CPE_CI_PTR_Q0 0x00038004 | ||
312 | #define __CPE_CI_UNUSED_MK 0xffff0000 | ||
313 | #define __CPE_CI_UNUSED_SH 16 | ||
314 | #define __CPE_CI_UNUSED(_v) ((_v) << __CPE_CI_UNUSED_SH) | ||
315 | #define __CPE_CI_PTR 0x0000ffff | ||
316 | #define CPE_CI_PTR_Q1 0x00038044 | ||
317 | #define CPE_DEPTH_Q0 0x00038008 | ||
318 | #define __CPE_DEPTH_UNUSED_MK 0xf8000000 | ||
319 | #define __CPE_DEPTH_UNUSED_SH 27 | ||
320 | #define __CPE_DEPTH_UNUSED(_v) ((_v) << __CPE_DEPTH_UNUSED_SH) | ||
321 | #define __CPE_MSIX_VEC_INDEX_MK 0x07ff0000 | ||
322 | #define __CPE_MSIX_VEC_INDEX_SH 16 | ||
323 | #define __CPE_MSIX_VEC_INDEX(_v) ((_v) << __CPE_MSIX_VEC_INDEX_SH) | ||
324 | #define __CPE_DEPTH 0x0000ffff | ||
325 | #define CPE_DEPTH_Q1 0x00038048 | ||
326 | #define CPE_QCTRL_Q0 0x0003800c | ||
327 | #define __CPE_CTRL_UNUSED30_MK 0xfc000000 | ||
328 | #define __CPE_CTRL_UNUSED30_SH 26 | ||
329 | #define __CPE_CTRL_UNUSED30(_v) ((_v) << __CPE_CTRL_UNUSED30_SH) | ||
330 | #define __CPE_FUNC_INT_CTRL_MK 0x03000000 | ||
331 | #define __CPE_FUNC_INT_CTRL_SH 24 | ||
332 | #define __CPE_FUNC_INT_CTRL(_v) ((_v) << __CPE_FUNC_INT_CTRL_SH) | ||
333 | enum { | ||
334 | __CPE_FUNC_INT_CTRL_DISABLE = 0x0, | ||
335 | __CPE_FUNC_INT_CTRL_F2NF = 0x1, | ||
336 | __CPE_FUNC_INT_CTRL_3QUART = 0x2, | ||
337 | __CPE_FUNC_INT_CTRL_HALF = 0x3, | ||
338 | }; | ||
339 | #define __CPE_CTRL_UNUSED20_MK 0x00f00000 | ||
340 | #define __CPE_CTRL_UNUSED20_SH 20 | ||
341 | #define __CPE_CTRL_UNUSED20(_v) ((_v) << __CPE_CTRL_UNUSED20_SH) | ||
342 | #define __CPE_SCI_TH_MK 0x000f0000 | ||
343 | #define __CPE_SCI_TH_SH 16 | ||
344 | #define __CPE_SCI_TH(_v) ((_v) << __CPE_SCI_TH_SH) | ||
345 | #define __CPE_CTRL_UNUSED10_MK 0x0000c000 | ||
346 | #define __CPE_CTRL_UNUSED10_SH 14 | ||
347 | #define __CPE_CTRL_UNUSED10(_v) ((_v) << __CPE_CTRL_UNUSED10_SH) | ||
348 | #define __CPE_ACK_PENDING 0x00002000 | ||
349 | #define __CPE_CTRL_UNUSED40_MK 0x00001c00 | ||
350 | #define __CPE_CTRL_UNUSED40_SH 10 | ||
351 | #define __CPE_CTRL_UNUSED40(_v) ((_v) << __CPE_CTRL_UNUSED40_SH) | ||
352 | #define __CPE_PCIEID_MK 0x00000300 | ||
353 | #define __CPE_PCIEID_SH 8 | ||
354 | #define __CPE_PCIEID(_v) ((_v) << __CPE_PCIEID_SH) | ||
355 | #define __CPE_CTRL_UNUSED00_MK 0x000000fe | ||
356 | #define __CPE_CTRL_UNUSED00_SH 1 | ||
357 | #define __CPE_CTRL_UNUSED00(_v) ((_v) << __CPE_CTRL_UNUSED00_SH) | ||
358 | #define __CPE_ESIZE 0x00000001 | ||
359 | #define CPE_QCTRL_Q1 0x0003804c | ||
360 | #define __CPE_CTRL_UNUSED31_MK 0xfc000000 | ||
361 | #define __CPE_CTRL_UNUSED31_SH 26 | ||
362 | #define __CPE_CTRL_UNUSED31(_v) ((_v) << __CPE_CTRL_UNUSED31_SH) | ||
363 | #define __CPE_CTRL_UNUSED21_MK 0x00f00000 | ||
364 | #define __CPE_CTRL_UNUSED21_SH 20 | ||
365 | #define __CPE_CTRL_UNUSED21(_v) ((_v) << __CPE_CTRL_UNUSED21_SH) | ||
366 | #define __CPE_CTRL_UNUSED11_MK 0x0000c000 | ||
367 | #define __CPE_CTRL_UNUSED11_SH 14 | ||
368 | #define __CPE_CTRL_UNUSED11(_v) ((_v) << __CPE_CTRL_UNUSED11_SH) | ||
369 | #define __CPE_CTRL_UNUSED41_MK 0x00001c00 | ||
370 | #define __CPE_CTRL_UNUSED41_SH 10 | ||
371 | #define __CPE_CTRL_UNUSED41(_v) ((_v) << __CPE_CTRL_UNUSED41_SH) | ||
372 | #define __CPE_CTRL_UNUSED01_MK 0x000000fe | ||
373 | #define __CPE_CTRL_UNUSED01_SH 1 | ||
374 | #define __CPE_CTRL_UNUSED01(_v) ((_v) << __CPE_CTRL_UNUSED01_SH) | ||
375 | #define RME_PI_PTR_Q0 0x00038020 | ||
376 | #define __LATENCY_TIME_STAMP_MK 0xffff0000 | ||
377 | #define __LATENCY_TIME_STAMP_SH 16 | ||
378 | #define __LATENCY_TIME_STAMP(_v) ((_v) << __LATENCY_TIME_STAMP_SH) | ||
379 | #define __RME_PI_PTR 0x0000ffff | ||
380 | #define RME_PI_PTR_Q1 0x00038060 | ||
381 | #define RME_CI_PTR_Q0 0x00038024 | ||
382 | #define __DELAY_TIME_STAMP_MK 0xffff0000 | ||
383 | #define __DELAY_TIME_STAMP_SH 16 | ||
384 | #define __DELAY_TIME_STAMP(_v) ((_v) << __DELAY_TIME_STAMP_SH) | ||
385 | #define __RME_CI_PTR 0x0000ffff | ||
386 | #define RME_CI_PTR_Q1 0x00038064 | ||
387 | #define RME_DEPTH_Q0 0x00038028 | ||
388 | #define __RME_DEPTH_UNUSED_MK 0xf8000000 | ||
389 | #define __RME_DEPTH_UNUSED_SH 27 | ||
390 | #define __RME_DEPTH_UNUSED(_v) ((_v) << __RME_DEPTH_UNUSED_SH) | ||
391 | #define __RME_MSIX_VEC_INDEX_MK 0x07ff0000 | ||
392 | #define __RME_MSIX_VEC_INDEX_SH 16 | ||
393 | #define __RME_MSIX_VEC_INDEX(_v) ((_v) << __RME_MSIX_VEC_INDEX_SH) | ||
394 | #define __RME_DEPTH 0x0000ffff | ||
395 | #define RME_DEPTH_Q1 0x00038068 | ||
396 | #define RME_QCTRL_Q0 0x0003802c | ||
397 | #define __RME_INT_LATENCY_TIMER_MK 0xff000000 | ||
398 | #define __RME_INT_LATENCY_TIMER_SH 24 | ||
399 | #define __RME_INT_LATENCY_TIMER(_v) ((_v) << __RME_INT_LATENCY_TIMER_SH) | ||
400 | #define __RME_INT_DELAY_TIMER_MK 0x00ff0000 | ||
401 | #define __RME_INT_DELAY_TIMER_SH 16 | ||
402 | #define __RME_INT_DELAY_TIMER(_v) ((_v) << __RME_INT_DELAY_TIMER_SH) | ||
403 | #define __RME_INT_DELAY_DISABLE 0x00008000 | ||
404 | #define __RME_DLY_DELAY_DISABLE 0x00004000 | ||
405 | #define __RME_ACK_PENDING 0x00002000 | ||
406 | #define __RME_FULL_INTERRUPT_DISABLE 0x00001000 | ||
407 | #define __RME_CTRL_UNUSED10_MK 0x00000c00 | ||
408 | #define __RME_CTRL_UNUSED10_SH 10 | ||
409 | #define __RME_CTRL_UNUSED10(_v) ((_v) << __RME_CTRL_UNUSED10_SH) | ||
410 | #define __RME_PCIEID_MK 0x00000300 | ||
411 | #define __RME_PCIEID_SH 8 | ||
412 | #define __RME_PCIEID(_v) ((_v) << __RME_PCIEID_SH) | ||
413 | #define __RME_CTRL_UNUSED00_MK 0x000000fe | ||
414 | #define __RME_CTRL_UNUSED00_SH 1 | ||
415 | #define __RME_CTRL_UNUSED00(_v) ((_v) << __RME_CTRL_UNUSED00_SH) | ||
416 | #define __RME_ESIZE 0x00000001 | ||
417 | #define RME_QCTRL_Q1 0x0003806c | ||
418 | #define __RME_CTRL_UNUSED11_MK 0x00000c00 | ||
419 | #define __RME_CTRL_UNUSED11_SH 10 | ||
420 | #define __RME_CTRL_UNUSED11(_v) ((_v) << __RME_CTRL_UNUSED11_SH) | ||
421 | #define __RME_CTRL_UNUSED01_MK 0x000000fe | ||
422 | #define __RME_CTRL_UNUSED01_SH 1 | ||
423 | #define __RME_CTRL_UNUSED01(_v) ((_v) << __RME_CTRL_UNUSED01_SH) | ||
424 | #define PSS_CTL_REG 0x00018800 | ||
425 | #define __PSS_I2C_CLK_DIV_MK 0x007f0000 | ||
426 | #define __PSS_I2C_CLK_DIV_SH 16 | ||
427 | #define __PSS_I2C_CLK_DIV(_v) ((_v) << __PSS_I2C_CLK_DIV_SH) | ||
428 | #define __PSS_LMEM_INIT_DONE 0x00001000 | ||
429 | #define __PSS_LMEM_RESET 0x00000200 | ||
430 | #define __PSS_LMEM_INIT_EN 0x00000100 | ||
431 | #define __PSS_LPU1_RESET 0x00000002 | ||
432 | #define __PSS_LPU0_RESET 0x00000001 | ||
433 | #define HQM_QSET0_RXQ_DRBL_P0 0x00038000 | ||
434 | #define __RXQ0_ADD_VECTORS_P 0x80000000 | ||
435 | #define __RXQ0_STOP_P 0x40000000 | ||
436 | #define __RXQ0_PRD_PTR_P 0x0000ffff | ||
437 | #define HQM_QSET1_RXQ_DRBL_P0 0x00038080 | ||
438 | #define __RXQ1_ADD_VECTORS_P 0x80000000 | ||
439 | #define __RXQ1_STOP_P 0x40000000 | ||
440 | #define __RXQ1_PRD_PTR_P 0x0000ffff | ||
441 | #define HQM_QSET0_RXQ_DRBL_P1 0x0003c000 | ||
442 | #define HQM_QSET1_RXQ_DRBL_P1 0x0003c080 | ||
443 | #define HQM_QSET0_TXQ_DRBL_P0 0x00038020 | ||
444 | #define __TXQ0_ADD_VECTORS_P 0x80000000 | ||
445 | #define __TXQ0_STOP_P 0x40000000 | ||
446 | #define __TXQ0_PRD_PTR_P 0x0000ffff | ||
447 | #define HQM_QSET1_TXQ_DRBL_P0 0x000380a0 | ||
448 | #define __TXQ1_ADD_VECTORS_P 0x80000000 | ||
449 | #define __TXQ1_STOP_P 0x40000000 | ||
450 | #define __TXQ1_PRD_PTR_P 0x0000ffff | ||
451 | #define HQM_QSET0_TXQ_DRBL_P1 0x0003c020 | ||
452 | #define HQM_QSET1_TXQ_DRBL_P1 0x0003c0a0 | ||
453 | #define HQM_QSET0_IB_DRBL_1_P0 0x00038040 | ||
454 | #define __IB1_0_ACK_P 0x80000000 | ||
455 | #define __IB1_0_DISABLE_P 0x40000000 | ||
456 | #define __IB1_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff | ||
457 | #define HQM_QSET1_IB_DRBL_1_P0 0x000380c0 | ||
458 | #define __IB1_1_ACK_P 0x80000000 | ||
459 | #define __IB1_1_DISABLE_P 0x40000000 | ||
460 | #define __IB1_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff | ||
461 | #define HQM_QSET0_IB_DRBL_1_P1 0x0003c040 | ||
462 | #define HQM_QSET1_IB_DRBL_1_P1 0x0003c0c0 | ||
463 | #define HQM_QSET0_IB_DRBL_2_P0 0x00038060 | ||
464 | #define __IB2_0_ACK_P 0x80000000 | ||
465 | #define __IB2_0_DISABLE_P 0x40000000 | ||
466 | #define __IB2_0_NUM_OF_ACKED_EVENTS_P 0x0000ffff | ||
467 | #define HQM_QSET1_IB_DRBL_2_P0 0x000380e0 | ||
468 | #define __IB2_1_ACK_P 0x80000000 | ||
469 | #define __IB2_1_DISABLE_P 0x40000000 | ||
470 | #define __IB2_1_NUM_OF_ACKED_EVENTS_P 0x0000ffff | ||
471 | #define HQM_QSET0_IB_DRBL_2_P1 0x0003c060 | ||
472 | #define HQM_QSET1_IB_DRBL_2_P1 0x0003c0e0 | ||
473 | |||
474 | |||
475 | /* | ||
476 | * These definitions are either in error/missing in spec. Its auto-generated | ||
477 | * from hard coded values in regparse.pl. | ||
478 | */ | ||
479 | #define __EMPHPOST_AT_4G_MK_FIX 0x0000001c | ||
480 | #define __EMPHPOST_AT_4G_SH_FIX 0x00000002 | ||
481 | #define __EMPHPRE_AT_4G_FIX 0x00000003 | ||
482 | #define __SFP_TXRATE_EN_FIX 0x00000100 | ||
483 | #define __SFP_RXRATE_EN_FIX 0x00000080 | ||
484 | |||
485 | |||
486 | /* | ||
487 | * These register definitions are auto-generated from hard coded values | ||
488 | * in regparse.pl. | ||
489 | */ | ||
490 | |||
491 | |||
492 | /* | ||
493 | * These register mapping definitions are auto-generated from mapping tables | ||
494 | * in regparse.pl. | ||
495 | */ | ||
496 | #define BFA_IOC0_HBEAT_REG HOST_SEM0_INFO_REG | ||
497 | #define BFA_IOC0_STATE_REG HOST_SEM1_INFO_REG | ||
498 | #define BFA_IOC1_HBEAT_REG HOST_SEM2_INFO_REG | ||
499 | #define BFA_IOC1_STATE_REG HOST_SEM3_INFO_REG | ||
500 | #define BFA_FW_USE_COUNT HOST_SEM4_INFO_REG | ||
501 | |||
502 | #define CPE_DEPTH_Q(__n) \ | ||
503 | (CPE_DEPTH_Q0 + (__n) * (CPE_DEPTH_Q1 - CPE_DEPTH_Q0)) | ||
504 | #define CPE_QCTRL_Q(__n) \ | ||
505 | (CPE_QCTRL_Q0 + (__n) * (CPE_QCTRL_Q1 - CPE_QCTRL_Q0)) | ||
506 | #define CPE_PI_PTR_Q(__n) \ | ||
507 | (CPE_PI_PTR_Q0 + (__n) * (CPE_PI_PTR_Q1 - CPE_PI_PTR_Q0)) | ||
508 | #define CPE_CI_PTR_Q(__n) \ | ||
509 | (CPE_CI_PTR_Q0 + (__n) * (CPE_CI_PTR_Q1 - CPE_CI_PTR_Q0)) | ||
510 | #define RME_DEPTH_Q(__n) \ | ||
511 | (RME_DEPTH_Q0 + (__n) * (RME_DEPTH_Q1 - RME_DEPTH_Q0)) | ||
512 | #define RME_QCTRL_Q(__n) \ | ||
513 | (RME_QCTRL_Q0 + (__n) * (RME_QCTRL_Q1 - RME_QCTRL_Q0)) | ||
514 | #define RME_PI_PTR_Q(__n) \ | ||
515 | (RME_PI_PTR_Q0 + (__n) * (RME_PI_PTR_Q1 - RME_PI_PTR_Q0)) | ||
516 | #define RME_CI_PTR_Q(__n) \ | ||
517 | (RME_CI_PTR_Q0 + (__n) * (RME_CI_PTR_Q1 - RME_CI_PTR_Q0)) | ||
518 | #define HQM_QSET_RXQ_DRBL_P0(__n) \ | ||
519 | (HQM_QSET0_RXQ_DRBL_P0 + (__n) * (HQM_QSET1_RXQ_DRBL_P0 - \ | ||
520 | HQM_QSET0_RXQ_DRBL_P0)) | ||
521 | #define HQM_QSET_TXQ_DRBL_P0(__n) \ | ||
522 | (HQM_QSET0_TXQ_DRBL_P0 + (__n) * (HQM_QSET1_TXQ_DRBL_P0 - \ | ||
523 | HQM_QSET0_TXQ_DRBL_P0)) | ||
524 | #define HQM_QSET_IB_DRBL_1_P0(__n) \ | ||
525 | (HQM_QSET0_IB_DRBL_1_P0 + (__n) * (HQM_QSET1_IB_DRBL_1_P0 - \ | ||
526 | HQM_QSET0_IB_DRBL_1_P0)) | ||
527 | #define HQM_QSET_IB_DRBL_2_P0(__n) \ | ||
528 | (HQM_QSET0_IB_DRBL_2_P0 + (__n) * (HQM_QSET1_IB_DRBL_2_P0 - \ | ||
529 | HQM_QSET0_IB_DRBL_2_P0)) | ||
530 | #define HQM_QSET_RXQ_DRBL_P1(__n) \ | ||
531 | (HQM_QSET0_RXQ_DRBL_P1 + (__n) * (HQM_QSET1_RXQ_DRBL_P1 - \ | ||
532 | HQM_QSET0_RXQ_DRBL_P1)) | ||
533 | #define HQM_QSET_TXQ_DRBL_P1(__n) \ | ||
534 | (HQM_QSET0_TXQ_DRBL_P1 + (__n) * (HQM_QSET1_TXQ_DRBL_P1 - \ | ||
535 | HQM_QSET0_TXQ_DRBL_P1)) | ||
536 | #define HQM_QSET_IB_DRBL_1_P1(__n) \ | ||
537 | (HQM_QSET0_IB_DRBL_1_P1 + (__n) * (HQM_QSET1_IB_DRBL_1_P1 - \ | ||
538 | HQM_QSET0_IB_DRBL_1_P1)) | ||
539 | #define HQM_QSET_IB_DRBL_2_P1(__n) \ | ||
540 | (HQM_QSET0_IB_DRBL_2_P1 + (__n) * (HQM_QSET1_IB_DRBL_2_P1 - \ | ||
541 | HQM_QSET0_IB_DRBL_2_P1)) | ||
542 | |||
543 | #define CPE_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) | ||
544 | #define RME_Q_NUM(__fn, __q) (((__fn) << 2) + (__q)) | ||
545 | #define CPE_Q_MASK(__q) ((__q) & 0x3) | ||
546 | #define RME_Q_MASK(__q) ((__q) & 0x3) | ||
547 | |||
548 | |||
549 | /* | ||
550 | * PCI MSI-X vector defines | ||
551 | */ | ||
552 | enum { | ||
553 | BFA_MSIX_CPE_Q0 = 0, | ||
554 | BFA_MSIX_CPE_Q1 = 1, | ||
555 | BFA_MSIX_CPE_Q2 = 2, | ||
556 | BFA_MSIX_CPE_Q3 = 3, | ||
557 | BFA_MSIX_RME_Q0 = 4, | ||
558 | BFA_MSIX_RME_Q1 = 5, | ||
559 | BFA_MSIX_RME_Q2 = 6, | ||
560 | BFA_MSIX_RME_Q3 = 7, | ||
561 | BFA_MSIX_LPU_ERR = 8, | ||
562 | BFA_MSIX_CT_MAX = 9, | ||
563 | }; | ||
564 | |||
565 | /* | ||
566 | * And corresponding host interrupt status bit field defines | ||
567 | */ | ||
568 | #define __HFN_INT_CPE_Q0 0x00000001U | ||
569 | #define __HFN_INT_CPE_Q1 0x00000002U | ||
570 | #define __HFN_INT_CPE_Q2 0x00000004U | ||
571 | #define __HFN_INT_CPE_Q3 0x00000008U | ||
572 | #define __HFN_INT_CPE_Q4 0x00000010U | ||
573 | #define __HFN_INT_CPE_Q5 0x00000020U | ||
574 | #define __HFN_INT_CPE_Q6 0x00000040U | ||
575 | #define __HFN_INT_CPE_Q7 0x00000080U | ||
576 | #define __HFN_INT_RME_Q0 0x00000100U | ||
577 | #define __HFN_INT_RME_Q1 0x00000200U | ||
578 | #define __HFN_INT_RME_Q2 0x00000400U | ||
579 | #define __HFN_INT_RME_Q3 0x00000800U | ||
580 | #define __HFN_INT_RME_Q4 0x00001000U | ||
581 | #define __HFN_INT_RME_Q5 0x00002000U | ||
582 | #define __HFN_INT_RME_Q6 0x00004000U | ||
583 | #define __HFN_INT_RME_Q7 0x00008000U | ||
584 | #define __HFN_INT_ERR_EMC 0x00010000U | ||
585 | #define __HFN_INT_ERR_LPU0 0x00020000U | ||
586 | #define __HFN_INT_ERR_LPU1 0x00040000U | ||
587 | #define __HFN_INT_ERR_PSS 0x00080000U | ||
588 | #define __HFN_INT_MBOX_LPU0 0x00100000U | ||
589 | #define __HFN_INT_MBOX_LPU1 0x00200000U | ||
590 | #define __HFN_INT_MBOX1_LPU0 0x00400000U | ||
591 | #define __HFN_INT_MBOX1_LPU1 0x00800000U | ||
592 | #define __HFN_INT_CPE_MASK 0x000000ffU | ||
593 | #define __HFN_INT_RME_MASK 0x0000ff00U | ||
594 | |||
595 | |||
596 | /* | ||
597 | * catapult memory map. | ||
598 | */ | ||
599 | #define LL_PGN_HQM0 0x0096 | ||
600 | #define LL_PGN_HQM1 0x0097 | ||
601 | #define PSS_SMEM_PAGE_START 0x8000 | ||
602 | #define PSS_SMEM_PGNUM(_pg0, _ma) ((_pg0) + ((_ma) >> 15)) | ||
603 | #define PSS_SMEM_PGOFF(_ma) ((_ma) & 0x7fff) | ||
604 | |||
605 | /* | ||
606 | * End of catapult memory map | ||
607 | */ | ||
608 | |||
609 | |||
610 | #endif /* __BFI_CTREG_H__ */ | ||
611 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fabric.h b/drivers/scsi/bfa/include/bfi/bfi_fabric.h new file mode 100644 index 000000000000..c0669ed41078 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_fabric.h | |||
@@ -0,0 +1,92 @@ | |||
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 | #ifndef __BFI_FABRIC_H__ | ||
19 | #define __BFI_FABRIC_H__ | ||
20 | |||
21 | #include <bfi/bfi.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_fabric_h2i_msgs { | ||
26 | BFI_FABRIC_H2I_CREATE_REQ = 1, | ||
27 | BFI_FABRIC_H2I_DELETE_REQ = 2, | ||
28 | BFI_FABRIC_H2I_SETAUTH = 3, | ||
29 | }; | ||
30 | |||
31 | enum bfi_fabric_i2h_msgs { | ||
32 | BFI_FABRIC_I2H_CREATE_RSP = BFA_I2HM(1), | ||
33 | BFI_FABRIC_I2H_DELETE_RSP = BFA_I2HM(2), | ||
34 | BFI_FABRIC_I2H_SETAUTH_RSP = BFA_I2HM(3), | ||
35 | BFI_FABRIC_I2H_ONLINE = BFA_I2HM(4), | ||
36 | BFI_FABRIC_I2H_OFFLINE = BFA_I2HM(5), | ||
37 | }; | ||
38 | |||
39 | struct bfi_fabric_create_req_s { | ||
40 | bfi_mhdr_t mh; /* common msg header */ | ||
41 | u8 vf_en; /* virtual fabric enable */ | ||
42 | u8 rsvd; | ||
43 | u16 vf_id; /* virtual fabric ID */ | ||
44 | wwn_t pwwn; /* port name */ | ||
45 | wwn_t nwwn; /* node name */ | ||
46 | }; | ||
47 | |||
48 | struct bfi_fabric_create_rsp_s { | ||
49 | bfi_mhdr_t mh; /* common msg header */ | ||
50 | u16 bfa_handle; /* host fabric handle */ | ||
51 | u8 status; /* fabric create status */ | ||
52 | u8 rsvd; | ||
53 | }; | ||
54 | |||
55 | struct bfi_fabric_delete_req_s { | ||
56 | bfi_mhdr_t mh; /* common msg header */ | ||
57 | u16 fw_handle; /* firmware fabric handle */ | ||
58 | u16 rsvd; | ||
59 | }; | ||
60 | |||
61 | struct bfi_fabric_delete_rsp_s { | ||
62 | bfi_mhdr_t mh; /* common msg header */ | ||
63 | u16 bfa_handle; /* host fabric handle */ | ||
64 | u8 status; /* fabric deletion status */ | ||
65 | u8 rsvd; | ||
66 | }; | ||
67 | |||
68 | #define BFI_FABRIC_AUTHSECRET_LEN 64 | ||
69 | struct bfi_fabric_setauth_req_s { | ||
70 | bfi_mhdr_t mh; /* common msg header */ | ||
71 | u16 fw_handle; /* f/w handle of fabric */ | ||
72 | u8 algorithm; | ||
73 | u8 group; | ||
74 | u8 secret[BFI_FABRIC_AUTHSECRET_LEN]; | ||
75 | }; | ||
76 | |||
77 | union bfi_fabric_h2i_msg_u { | ||
78 | bfi_msg_t *msg; | ||
79 | struct bfi_fabric_create_req_s *create_req; | ||
80 | struct bfi_fabric_delete_req_s *delete_req; | ||
81 | }; | ||
82 | |||
83 | union bfi_fabric_i2h_msg_u { | ||
84 | bfi_msg_t *msg; | ||
85 | struct bfi_fabric_create_rsp_s *create_rsp; | ||
86 | struct bfi_fabric_delete_rsp_s *delete_rsp; | ||
87 | }; | ||
88 | |||
89 | #pragma pack() | ||
90 | |||
91 | #endif /* __BFI_FABRIC_H__ */ | ||
92 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcpim.h b/drivers/scsi/bfa/include/bfi/bfi_fcpim.h new file mode 100644 index 000000000000..52c059fb4c3a --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_fcpim.h | |||
@@ -0,0 +1,301 @@ | |||
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 | #ifndef __BFI_FCPIM_H__ | ||
19 | #define __BFI_FCPIM_H__ | ||
20 | |||
21 | #include "bfi.h" | ||
22 | #include <protocol/fcp.h> | ||
23 | |||
24 | #pragma pack(1) | ||
25 | |||
26 | /* | ||
27 | * Initiator mode I-T nexus interface defines. | ||
28 | */ | ||
29 | |||
30 | enum bfi_itnim_h2i { | ||
31 | BFI_ITNIM_H2I_CREATE_REQ = 1, /* i-t nexus creation */ | ||
32 | BFI_ITNIM_H2I_DELETE_REQ = 2, /* i-t nexus deletion */ | ||
33 | }; | ||
34 | |||
35 | enum bfi_itnim_i2h { | ||
36 | BFI_ITNIM_I2H_CREATE_RSP = BFA_I2HM(1), | ||
37 | BFI_ITNIM_I2H_DELETE_RSP = BFA_I2HM(2), | ||
38 | BFI_ITNIM_I2H_SLER_EVENT = BFA_I2HM(3), | ||
39 | }; | ||
40 | |||
41 | struct bfi_itnim_create_req_s { | ||
42 | struct bfi_mhdr_s mh; /* common msg header */ | ||
43 | u16 fw_handle; /* f/w handle for itnim */ | ||
44 | u8 class; /* FC class for IO */ | ||
45 | u8 seq_rec; /* sequence recovery support */ | ||
46 | u8 msg_no; /* seq id of the msg */ | ||
47 | }; | ||
48 | |||
49 | struct bfi_itnim_create_rsp_s { | ||
50 | struct bfi_mhdr_s mh; /* common msg header */ | ||
51 | u16 bfa_handle; /* bfa handle for itnim */ | ||
52 | u8 status; /* fcp request status */ | ||
53 | u8 seq_id; /* seq id of the msg */ | ||
54 | }; | ||
55 | |||
56 | struct bfi_itnim_delete_req_s { | ||
57 | struct bfi_mhdr_s mh; /* common msg header */ | ||
58 | u16 fw_handle; /* f/w itnim handle */ | ||
59 | u8 seq_id; /* seq id of the msg */ | ||
60 | u8 rsvd; | ||
61 | }; | ||
62 | |||
63 | struct bfi_itnim_delete_rsp_s { | ||
64 | struct bfi_mhdr_s mh; /* common msg header */ | ||
65 | u16 bfa_handle; /* bfa handle for itnim */ | ||
66 | u8 status; /* fcp request status */ | ||
67 | u8 seq_id; /* seq id of the msg */ | ||
68 | }; | ||
69 | |||
70 | struct bfi_itnim_sler_event_s { | ||
71 | struct bfi_mhdr_s mh; /* common msg header */ | ||
72 | u16 bfa_handle; /* bfa handle for itnim */ | ||
73 | u16 rsvd; | ||
74 | }; | ||
75 | |||
76 | union bfi_itnim_h2i_msg_u { | ||
77 | struct bfi_itnim_create_req_s *create_req; | ||
78 | struct bfi_itnim_delete_req_s *delete_req; | ||
79 | struct bfi_msg_s *msg; | ||
80 | }; | ||
81 | |||
82 | union bfi_itnim_i2h_msg_u { | ||
83 | struct bfi_itnim_create_rsp_s *create_rsp; | ||
84 | struct bfi_itnim_delete_rsp_s *delete_rsp; | ||
85 | struct bfi_itnim_sler_event_s *sler_event; | ||
86 | struct bfi_msg_s *msg; | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * Initiator mode IO interface defines. | ||
91 | */ | ||
92 | |||
93 | enum bfi_ioim_h2i { | ||
94 | BFI_IOIM_H2I_IOABORT_REQ = 1, /* IO abort request */ | ||
95 | BFI_IOIM_H2I_IOCLEANUP_REQ = 2, /* IO cleanup request */ | ||
96 | }; | ||
97 | |||
98 | enum bfi_ioim_i2h { | ||
99 | BFI_IOIM_I2H_IO_RSP = BFA_I2HM(1), /* non-fp IO response */ | ||
100 | BFI_IOIM_I2H_IOABORT_RSP = BFA_I2HM(2),/* ABORT rsp */ | ||
101 | }; | ||
102 | |||
103 | /** | ||
104 | * IO command DIF info | ||
105 | */ | ||
106 | struct bfi_ioim_dif_s { | ||
107 | u32 dif_info[4]; | ||
108 | }; | ||
109 | |||
110 | /** | ||
111 | * FCP IO messages overview | ||
112 | * | ||
113 | * @note | ||
114 | * - Max CDB length supported is 64 bytes. | ||
115 | * - SCSI Linked commands and SCSI bi-directional Commands not | ||
116 | * supported. | ||
117 | * | ||
118 | */ | ||
119 | struct bfi_ioim_req_s { | ||
120 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
121 | u16 io_tag; /* I/O tag */ | ||
122 | u16 rport_hdl; /* itnim/rport firmware handle */ | ||
123 | struct fcp_cmnd_s cmnd; /* IO request info */ | ||
124 | |||
125 | /** | ||
126 | * SG elements array within the IO request must be double word | ||
127 | * aligned. This aligment is required to optimize SGM setup for the IO. | ||
128 | */ | ||
129 | struct bfi_sge_s sges[BFI_SGE_INLINE_MAX]; | ||
130 | u8 io_timeout; | ||
131 | u8 dif_en; | ||
132 | u8 rsvd_a[2]; | ||
133 | struct bfi_ioim_dif_s dif; | ||
134 | }; | ||
135 | |||
136 | /** | ||
137 | * This table shows various IO status codes from firmware and their | ||
138 | * meaning. Host driver can use these status codes to further process | ||
139 | * IO completions. | ||
140 | * | ||
141 | * BFI_IOIM_STS_OK : IO completed with error free SCSI & | ||
142 | * transport status. | ||
143 | * - io-tag can be reused. | ||
144 | * | ||
145 | * BFA_IOIM_STS_SCSI_ERR : IO completed with scsi error. | ||
146 | * - io-tag can be reused. | ||
147 | * | ||
148 | * BFI_IOIM_STS_HOST_ABORTED : IO was aborted successfully due to | ||
149 | * host request. | ||
150 | * - io-tag cannot be reused yet. | ||
151 | * | ||
152 | * BFI_IOIM_STS_ABORTED : IO was aborted successfully | ||
153 | * internally by f/w. | ||
154 | * - io-tag cannot be reused yet. | ||
155 | * | ||
156 | * BFI_IOIM_STS_TIMEDOUT : IO timedout and ABTS/RRQ is happening | ||
157 | * in the firmware and | ||
158 | * - io-tag cannot be reused yet. | ||
159 | * | ||
160 | * BFI_IOIM_STS_SQER_NEEDED : Firmware could not recover the IO | ||
161 | * with sequence level error | ||
162 | * logic and hence host needs to retry | ||
163 | * this IO with a different IO tag | ||
164 | * - io-tag cannot be used yet. | ||
165 | * | ||
166 | * BFI_IOIM_STS_NEXUS_ABORT : Second Level Error Recovery from host | ||
167 | * is required because 2 consecutive ABTS | ||
168 | * timedout and host needs logout and | ||
169 | * re-login with the target | ||
170 | * - io-tag cannot be used yet. | ||
171 | * | ||
172 | * BFI_IOIM_STS_UNDERRUN : IO completed with SCSI status good, | ||
173 | * but the data tranferred is less than | ||
174 | * the fcp data length in the command. | ||
175 | * ex. SCSI INQUIRY where transferred | ||
176 | * data length and residue count in FCP | ||
177 | * response accounts for total fcp-dl | ||
178 | * - io-tag can be reused. | ||
179 | * | ||
180 | * BFI_IOIM_STS_OVERRUN : IO completed with SCSI status good, | ||
181 | * but the data transerred is more than | ||
182 | * fcp data length in the command. ex. | ||
183 | * TAPE IOs where blocks can of unequal | ||
184 | * lengths. | ||
185 | * - io-tag can be reused. | ||
186 | * | ||
187 | * BFI_IOIM_STS_RES_FREE : Firmware has completed using io-tag | ||
188 | * during abort process | ||
189 | * - io-tag can be reused. | ||
190 | * | ||
191 | * BFI_IOIM_STS_PROTO_ERR : Firmware detected a protocol error. | ||
192 | * ex target sent more data than | ||
193 | * requested, or there was data frame | ||
194 | * loss and other reasons | ||
195 | * - io-tag cannot be used yet. | ||
196 | * | ||
197 | * BFI_IOIM_STS_DIF_ERR : Firwmare detected DIF error. ex: DIF | ||
198 | * CRC err or Ref Tag err or App tag err. | ||
199 | * - io-tag can be reused. | ||
200 | * | ||
201 | * BFA_IOIM_STS_TSK_MGT_ABORT : IO was aborted because of Task | ||
202 | * Management command from the host | ||
203 | * - io-tag can be reused. | ||
204 | * | ||
205 | * BFI_IOIM_STS_UTAG : Firmware does not know about this | ||
206 | * io_tag. | ||
207 | * - io-tag can be reused. | ||
208 | */ | ||
209 | enum bfi_ioim_status { | ||
210 | BFI_IOIM_STS_OK = 0, | ||
211 | BFI_IOIM_STS_HOST_ABORTED = 1, | ||
212 | BFI_IOIM_STS_ABORTED = 2, | ||
213 | BFI_IOIM_STS_TIMEDOUT = 3, | ||
214 | BFI_IOIM_STS_RES_FREE = 4, | ||
215 | BFI_IOIM_STS_SQER_NEEDED = 5, | ||
216 | BFI_IOIM_STS_PROTO_ERR = 6, | ||
217 | BFI_IOIM_STS_UTAG = 7, | ||
218 | BFI_IOIM_STS_PATHTOV = 8, | ||
219 | }; | ||
220 | |||
221 | #define BFI_IOIM_SNSLEN (256) | ||
222 | /** | ||
223 | * I/O response message | ||
224 | */ | ||
225 | struct bfi_ioim_rsp_s { | ||
226 | struct bfi_mhdr_s mh; /* common msg header */ | ||
227 | u16 io_tag; /* completed IO tag */ | ||
228 | u16 bfa_rport_hndl; /* releated rport handle */ | ||
229 | u8 io_status; /* IO completion status */ | ||
230 | u8 reuse_io_tag; /* IO tag can be reused */ | ||
231 | u16 abort_tag; /* host abort request tag */ | ||
232 | u8 scsi_status; /* scsi status from target */ | ||
233 | u8 sns_len; /* scsi sense length */ | ||
234 | u8 resid_flags; /* IO residue flags */ | ||
235 | u8 rsvd_a; | ||
236 | u32 residue; /* IO residual length in bytes */ | ||
237 | u32 rsvd_b[3]; | ||
238 | }; | ||
239 | |||
240 | struct bfi_ioim_abort_req_s { | ||
241 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
242 | u16 io_tag; /* I/O tag */ | ||
243 | u16 abort_tag; /* unique request tag */ | ||
244 | }; | ||
245 | |||
246 | /* | ||
247 | * Initiator mode task management command interface defines. | ||
248 | */ | ||
249 | |||
250 | enum bfi_tskim_h2i { | ||
251 | BFI_TSKIM_H2I_TM_REQ = 1, /* task-mgmt command */ | ||
252 | BFI_TSKIM_H2I_ABORT_REQ = 2, /* task-mgmt command */ | ||
253 | }; | ||
254 | |||
255 | enum bfi_tskim_i2h { | ||
256 | BFI_TSKIM_I2H_TM_RSP = BFA_I2HM(1), | ||
257 | }; | ||
258 | |||
259 | struct bfi_tskim_req_s { | ||
260 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
261 | u16 tsk_tag; /* task management tag */ | ||
262 | u16 itn_fhdl; /* itn firmware handle */ | ||
263 | lun_t lun; /* LU number */ | ||
264 | u8 tm_flags; /* see fcp_tm_cmnd_t */ | ||
265 | u8 t_secs; /* Timeout value in seconds */ | ||
266 | u8 rsvd[2]; | ||
267 | }; | ||
268 | |||
269 | struct bfi_tskim_abortreq_s { | ||
270 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
271 | u16 tsk_tag; /* task management tag */ | ||
272 | u16 rsvd; | ||
273 | }; | ||
274 | |||
275 | enum bfi_tskim_status { | ||
276 | /* | ||
277 | * Following are FCP-4 spec defined status codes, | ||
278 | * **DO NOT CHANGE THEM ** | ||
279 | */ | ||
280 | BFI_TSKIM_STS_OK = 0, | ||
281 | BFI_TSKIM_STS_NOT_SUPP = 4, | ||
282 | BFI_TSKIM_STS_FAILED = 5, | ||
283 | |||
284 | /** | ||
285 | * Defined by BFA | ||
286 | */ | ||
287 | BFI_TSKIM_STS_TIMEOUT = 10, /* TM request timedout */ | ||
288 | BFI_TSKIM_STS_ABORTED = 11, /* Aborted on host request */ | ||
289 | }; | ||
290 | |||
291 | struct bfi_tskim_rsp_s { | ||
292 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
293 | u16 tsk_tag; /* task mgmt cmnd tag */ | ||
294 | u8 tsk_status; /* @ref bfi_tskim_status */ | ||
295 | u8 rsvd; | ||
296 | }; | ||
297 | |||
298 | #pragma pack() | ||
299 | |||
300 | #endif /* __BFI_FCPIM_H__ */ | ||
301 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_fcxp.h b/drivers/scsi/bfa/include/bfi/bfi_fcxp.h new file mode 100644 index 000000000000..e0e995a32828 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_fcxp.h | |||
@@ -0,0 +1,71 @@ | |||
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 | #ifndef __BFI_FCXP_H__ | ||
19 | #define __BFI_FCXP_H__ | ||
20 | |||
21 | #include "bfi.h" | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_fcxp_h2i { | ||
26 | BFI_FCXP_H2I_SEND_REQ = 1, | ||
27 | }; | ||
28 | |||
29 | enum bfi_fcxp_i2h { | ||
30 | BFI_FCXP_I2H_SEND_RSP = BFA_I2HM(1), | ||
31 | }; | ||
32 | |||
33 | #define BFA_FCXP_MAX_SGES 2 | ||
34 | |||
35 | /** | ||
36 | * FCXP send request structure | ||
37 | */ | ||
38 | struct bfi_fcxp_send_req_s { | ||
39 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
40 | u16 fcxp_tag; /* driver request tag */ | ||
41 | u16 max_frmsz; /* max send frame size */ | ||
42 | u16 vf_id; /* vsan tag if applicable */ | ||
43 | u16 rport_fw_hndl; /* FW Handle for the remote port */ | ||
44 | u8 class; /* FC class used for req/rsp */ | ||
45 | u8 rsp_timeout; /* timeout in secs, 0-no response */ | ||
46 | u8 cts; /* continue sequence */ | ||
47 | u8 lp_tag; /* lport tag */ | ||
48 | struct fchs_s fchs; /* request FC header structure */ | ||
49 | u32 req_len; /* request payload length */ | ||
50 | u32 rsp_maxlen; /* max response length expected */ | ||
51 | struct bfi_sge_s req_sge[BFA_FCXP_MAX_SGES]; /* request buf */ | ||
52 | struct bfi_sge_s rsp_sge[BFA_FCXP_MAX_SGES]; /* response buf */ | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * FCXP send response structure | ||
57 | */ | ||
58 | struct bfi_fcxp_send_rsp_s { | ||
59 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
60 | u16 fcxp_tag; /* send request tag */ | ||
61 | u8 req_status; /* request status */ | ||
62 | u8 rsvd; | ||
63 | u32 rsp_len; /* actual response length */ | ||
64 | u32 residue_len; /* residual response length */ | ||
65 | struct fchs_s fchs; /* response FC header structure */ | ||
66 | }; | ||
67 | |||
68 | #pragma pack() | ||
69 | |||
70 | #endif /* __BFI_FCXP_H__ */ | ||
71 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_ioc.h b/drivers/scsi/bfa/include/bfi/bfi_ioc.h new file mode 100644 index 000000000000..026e9c06ae97 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_ioc.h | |||
@@ -0,0 +1,202 @@ | |||
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 | #ifndef __BFI_IOC_H__ | ||
19 | #define __BFI_IOC_H__ | ||
20 | |||
21 | #include "bfi.h" | ||
22 | #include <defs/bfa_defs_ioc.h> | ||
23 | |||
24 | #pragma pack(1) | ||
25 | |||
26 | enum bfi_ioc_h2i_msgs { | ||
27 | BFI_IOC_H2I_ENABLE_REQ = 1, | ||
28 | BFI_IOC_H2I_DISABLE_REQ = 2, | ||
29 | BFI_IOC_H2I_GETATTR_REQ = 3, | ||
30 | BFI_IOC_H2I_DBG_SYNC = 4, | ||
31 | BFI_IOC_H2I_DBG_DUMP = 5, | ||
32 | }; | ||
33 | |||
34 | enum bfi_ioc_i2h_msgs { | ||
35 | BFI_IOC_I2H_ENABLE_REPLY = BFA_I2HM(1), | ||
36 | BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2), | ||
37 | BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3), | ||
38 | BFI_IOC_I2H_READY_EVENT = BFA_I2HM(4), | ||
39 | BFI_IOC_I2H_HBEAT = BFA_I2HM(5), | ||
40 | }; | ||
41 | |||
42 | /** | ||
43 | * BFI_IOC_H2I_GETATTR_REQ message | ||
44 | */ | ||
45 | struct bfi_ioc_getattr_req_s { | ||
46 | struct bfi_mhdr_s mh; | ||
47 | union bfi_addr_u attr_addr; | ||
48 | }; | ||
49 | |||
50 | struct bfi_ioc_attr_s { | ||
51 | wwn_t mfg_wwn; | ||
52 | mac_t mfg_mac; | ||
53 | u16 rsvd_a; | ||
54 | char brcd_serialnum[STRSZ(BFA_MFG_SERIALNUM_SIZE)]; | ||
55 | u8 pcie_gen; | ||
56 | u8 pcie_lanes_orig; | ||
57 | u8 pcie_lanes; | ||
58 | u8 rx_bbcredit; /* receive buffer credits */ | ||
59 | u32 adapter_prop; /* adapter properties */ | ||
60 | u16 maxfrsize; /* max receive frame size */ | ||
61 | char asic_rev; | ||
62 | u8 rsvd_b; | ||
63 | char fw_version[BFA_VERSION_LEN]; | ||
64 | char optrom_version[BFA_VERSION_LEN]; | ||
65 | struct bfa_mfg_vpd_s vpd; | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * BFI_IOC_I2H_GETATTR_REPLY message | ||
70 | */ | ||
71 | struct bfi_ioc_getattr_reply_s { | ||
72 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
73 | u8 status; /* cfg reply status */ | ||
74 | u8 rsvd[3]; | ||
75 | }; | ||
76 | |||
77 | /** | ||
78 | * Firmware memory page offsets | ||
79 | */ | ||
80 | #define BFI_IOC_SMEM_PG0_CB (0x40) | ||
81 | #define BFI_IOC_SMEM_PG0_CT (0x180) | ||
82 | |||
83 | /** | ||
84 | * Firmware trace offset | ||
85 | */ | ||
86 | #define BFI_IOC_TRC_OFF (0x4b00) | ||
87 | #define BFI_IOC_TRC_ENTS 256 | ||
88 | |||
89 | #define BFI_IOC_FW_SIGNATURE (0xbfadbfad) | ||
90 | #define BFI_IOC_MD5SUM_SZ 4 | ||
91 | struct bfi_ioc_image_hdr_s { | ||
92 | u32 signature; /* constant signature */ | ||
93 | u32 rsvd_a; | ||
94 | u32 exec; /* exec vector */ | ||
95 | u32 param; /* parameters */ | ||
96 | u32 rsvd_b[4]; | ||
97 | u32 md5sum[BFI_IOC_MD5SUM_SZ]; | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * BFI_IOC_I2H_READY_EVENT message | ||
102 | */ | ||
103 | struct bfi_ioc_rdy_event_s { | ||
104 | struct bfi_mhdr_s mh; /* common msg header */ | ||
105 | u8 init_status; /* init event status */ | ||
106 | u8 rsvd[3]; | ||
107 | }; | ||
108 | |||
109 | struct bfi_ioc_hbeat_s { | ||
110 | struct bfi_mhdr_s mh; /* common msg header */ | ||
111 | u32 hb_count; /* current heart beat count */ | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * IOC hardware/firmware state | ||
116 | */ | ||
117 | enum bfi_ioc_state { | ||
118 | BFI_IOC_UNINIT = 0, /* not initialized */ | ||
119 | BFI_IOC_INITING = 1, /* h/w is being initialized */ | ||
120 | BFI_IOC_HWINIT = 2, /* h/w is initialized */ | ||
121 | BFI_IOC_CFG = 3, /* IOC configuration in progress */ | ||
122 | BFI_IOC_OP = 4, /* IOC is operational */ | ||
123 | BFI_IOC_DISABLING = 5, /* IOC is being disabled */ | ||
124 | BFI_IOC_DISABLED = 6, /* IOC is disabled */ | ||
125 | BFI_IOC_CFG_DISABLED = 7, /* IOC is being disabled;transient */ | ||
126 | BFI_IOC_HBFAIL = 8, /* IOC heart-beat failure */ | ||
127 | BFI_IOC_MEMTEST = 9, /* IOC is doing memtest */ | ||
128 | }; | ||
129 | |||
130 | #define BFI_IOC_ENDIAN_SIG 0x12345678 | ||
131 | |||
132 | enum { | ||
133 | BFI_ADAPTER_TYPE_FC = 0x01, /* FC adapters */ | ||
134 | BFI_ADAPTER_TYPE_MK = 0x0f0000, /* adapter type mask */ | ||
135 | BFI_ADAPTER_TYPE_SH = 16, /* adapter type shift */ | ||
136 | BFI_ADAPTER_NPORTS_MK = 0xff00, /* number of ports mask */ | ||
137 | BFI_ADAPTER_NPORTS_SH = 8, /* number of ports shift */ | ||
138 | BFI_ADAPTER_SPEED_MK = 0xff, /* adapter speed mask */ | ||
139 | BFI_ADAPTER_SPEED_SH = 0, /* adapter speed shift */ | ||
140 | BFI_ADAPTER_PROTO = 0x100000, /* prototype adapaters */ | ||
141 | BFI_ADAPTER_TTV = 0x200000, /* TTV debug capable */ | ||
142 | BFI_ADAPTER_UNSUPP = 0x400000, /* unknown adapter type */ | ||
143 | }; | ||
144 | |||
145 | #define BFI_ADAPTER_GETP(__prop,__adap_prop) \ | ||
146 | (((__adap_prop) & BFI_ADAPTER_ ## __prop ## _MK) >> \ | ||
147 | BFI_ADAPTER_ ## __prop ## _SH) | ||
148 | #define BFI_ADAPTER_SETP(__prop, __val) \ | ||
149 | ((__val) << BFI_ADAPTER_ ## __prop ## _SH) | ||
150 | #define BFI_ADAPTER_IS_PROTO(__adap_type) \ | ||
151 | ((__adap_type) & BFI_ADAPTER_PROTO) | ||
152 | #define BFI_ADAPTER_IS_TTV(__adap_type) \ | ||
153 | ((__adap_type) & BFI_ADAPTER_TTV) | ||
154 | #define BFI_ADAPTER_IS_UNSUPP(__adap_type) \ | ||
155 | ((__adap_type) & BFI_ADAPTER_UNSUPP) | ||
156 | #define BFI_ADAPTER_IS_SPECIAL(__adap_type) \ | ||
157 | ((__adap_type) & (BFI_ADAPTER_TTV | BFI_ADAPTER_PROTO | \ | ||
158 | BFI_ADAPTER_UNSUPP)) | ||
159 | |||
160 | /** | ||
161 | * BFI_IOC_H2I_ENABLE_REQ & BFI_IOC_H2I_DISABLE_REQ messages | ||
162 | */ | ||
163 | struct bfi_ioc_ctrl_req_s { | ||
164 | struct bfi_mhdr_s mh; | ||
165 | u8 ioc_class; | ||
166 | u8 rsvd[3]; | ||
167 | }; | ||
168 | |||
169 | /** | ||
170 | * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages | ||
171 | */ | ||
172 | struct bfi_ioc_ctrl_reply_s { | ||
173 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
174 | u8 status; /* enable/disable status */ | ||
175 | u8 rsvd[3]; | ||
176 | }; | ||
177 | |||
178 | #define BFI_IOC_MSGSZ 8 | ||
179 | /** | ||
180 | * H2I Messages | ||
181 | */ | ||
182 | union bfi_ioc_h2i_msg_u { | ||
183 | struct bfi_mhdr_s mh; | ||
184 | struct bfi_ioc_ctrl_req_s enable_req; | ||
185 | struct bfi_ioc_ctrl_req_s disable_req; | ||
186 | struct bfi_ioc_getattr_req_s getattr_req; | ||
187 | u32 mboxmsg[BFI_IOC_MSGSZ]; | ||
188 | }; | ||
189 | |||
190 | /** | ||
191 | * I2H Messages | ||
192 | */ | ||
193 | union bfi_ioc_i2h_msg_u { | ||
194 | struct bfi_mhdr_s mh; | ||
195 | struct bfi_ioc_rdy_event_s rdy_event; | ||
196 | u32 mboxmsg[BFI_IOC_MSGSZ]; | ||
197 | }; | ||
198 | |||
199 | #pragma pack() | ||
200 | |||
201 | #endif /* __BFI_IOC_H__ */ | ||
202 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_iocfc.h b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h new file mode 100644 index 000000000000..c3760df72575 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_iocfc.h | |||
@@ -0,0 +1,177 @@ | |||
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 | #ifndef __BFI_IOCFC_H__ | ||
19 | #define __BFI_IOCFC_H__ | ||
20 | |||
21 | #include "bfi.h" | ||
22 | #include <defs/bfa_defs_ioc.h> | ||
23 | #include <defs/bfa_defs_iocfc.h> | ||
24 | #include <defs/bfa_defs_boot.h> | ||
25 | |||
26 | #pragma pack(1) | ||
27 | |||
28 | enum bfi_iocfc_h2i_msgs { | ||
29 | BFI_IOCFC_H2I_CFG_REQ = 1, | ||
30 | BFI_IOCFC_H2I_GET_STATS_REQ = 2, | ||
31 | BFI_IOCFC_H2I_CLEAR_STATS_REQ = 3, | ||
32 | BFI_IOCFC_H2I_SET_INTR_REQ = 4, | ||
33 | BFI_IOCFC_H2I_UPDATEQ_REQ = 5, | ||
34 | }; | ||
35 | |||
36 | enum bfi_iocfc_i2h_msgs { | ||
37 | BFI_IOCFC_I2H_CFG_REPLY = BFA_I2HM(1), | ||
38 | BFI_IOCFC_I2H_GET_STATS_RSP = BFA_I2HM(2), | ||
39 | BFI_IOCFC_I2H_CLEAR_STATS_RSP = BFA_I2HM(3), | ||
40 | BFI_IOCFC_I2H_UPDATEQ_RSP = BFA_I2HM(5), | ||
41 | }; | ||
42 | |||
43 | struct bfi_iocfc_cfg_s { | ||
44 | u8 num_cqs; /* Number of CQs to be used */ | ||
45 | u8 sense_buf_len; /* SCSI sense length */ | ||
46 | u8 trunk_enabled; /* port trunking enabled */ | ||
47 | u8 trunk_ports; /* trunk ports bit map */ | ||
48 | u32 endian_sig; /* endian signature of host */ | ||
49 | |||
50 | /** | ||
51 | * Request and response circular queue base addresses, size and | ||
52 | * shadow index pointers. | ||
53 | */ | ||
54 | union bfi_addr_u req_cq_ba[BFI_IOC_MAX_CQS]; | ||
55 | union bfi_addr_u req_shadow_ci[BFI_IOC_MAX_CQS]; | ||
56 | u16 req_cq_elems[BFI_IOC_MAX_CQS]; | ||
57 | union bfi_addr_u rsp_cq_ba[BFI_IOC_MAX_CQS]; | ||
58 | union bfi_addr_u rsp_shadow_pi[BFI_IOC_MAX_CQS]; | ||
59 | u16 rsp_cq_elems[BFI_IOC_MAX_CQS]; | ||
60 | |||
61 | union bfi_addr_u stats_addr; /* DMA-able address for stats */ | ||
62 | union bfi_addr_u cfgrsp_addr; /* config response dma address */ | ||
63 | union bfi_addr_u ioim_snsbase; /* IO sense buffer base address */ | ||
64 | struct bfa_iocfc_intr_attr_s intr_attr; /* IOC interrupt attributes */ | ||
65 | }; | ||
66 | |||
67 | /** | ||
68 | * Boot target wwn information for this port. This contains either the stored | ||
69 | * or discovered boot target port wwns for the port. | ||
70 | */ | ||
71 | struct bfi_iocfc_bootwwns { | ||
72 | wwn_t wwn[BFA_BOOT_BOOTLUN_MAX]; | ||
73 | u8 nwwns; | ||
74 | u8 rsvd[7]; | ||
75 | }; | ||
76 | |||
77 | struct bfi_iocfc_cfgrsp_s { | ||
78 | struct bfa_iocfc_fwcfg_s fwcfg; | ||
79 | struct bfa_iocfc_intr_attr_s intr_attr; | ||
80 | struct bfi_iocfc_bootwwns bootwwns; | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * BFI_IOCFC_H2I_CFG_REQ message | ||
85 | */ | ||
86 | struct bfi_iocfc_cfg_req_s { | ||
87 | struct bfi_mhdr_s mh; | ||
88 | union bfi_addr_u ioc_cfg_dma_addr; | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * BFI_IOCFC_I2H_CFG_REPLY message | ||
93 | */ | ||
94 | struct bfi_iocfc_cfg_reply_s { | ||
95 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
96 | u8 cfg_success; /* cfg reply status */ | ||
97 | u8 lpu_bm; /* LPUs assigned for this IOC */ | ||
98 | u8 rsvd[2]; | ||
99 | }; | ||
100 | |||
101 | /** | ||
102 | * BFI_IOCFC_H2I_GET_STATS_REQ & BFI_IOCFC_H2I_CLEAR_STATS_REQ messages | ||
103 | */ | ||
104 | struct bfi_iocfc_stats_req_s { | ||
105 | struct bfi_mhdr_s mh; /* msg header */ | ||
106 | u32 msgtag; /* msgtag for reply */ | ||
107 | }; | ||
108 | |||
109 | /** | ||
110 | * BFI_IOCFC_I2H_GET_STATS_RSP & BFI_IOCFC_I2H_CLEAR_STATS_RSP messages | ||
111 | */ | ||
112 | struct bfi_iocfc_stats_rsp_s { | ||
113 | struct bfi_mhdr_s mh; /* common msg header */ | ||
114 | u8 status; /* reply status */ | ||
115 | u8 rsvd[3]; | ||
116 | u32 msgtag; /* msgtag for reply */ | ||
117 | }; | ||
118 | |||
119 | /** | ||
120 | * BFI_IOCFC_H2I_SET_INTR_REQ message | ||
121 | */ | ||
122 | struct bfi_iocfc_set_intr_req_s { | ||
123 | struct bfi_mhdr_s mh; /* common msg header */ | ||
124 | u8 coalesce; /* enable intr coalescing*/ | ||
125 | u8 rsvd[3]; | ||
126 | u16 delay; /* delay timer 0..1125us */ | ||
127 | u16 latency; /* latency timer 0..225us */ | ||
128 | }; | ||
129 | |||
130 | /** | ||
131 | * BFI_IOCFC_H2I_UPDATEQ_REQ message | ||
132 | */ | ||
133 | struct bfi_iocfc_updateq_req_s { | ||
134 | struct bfi_mhdr_s mh; /* common msg header */ | ||
135 | u32 reqq_ba; /* reqq base addr */ | ||
136 | u32 rspq_ba; /* rspq base addr */ | ||
137 | u32 reqq_sci; /* reqq shadow ci */ | ||
138 | u32 rspq_spi; /* rspq shadow pi */ | ||
139 | }; | ||
140 | |||
141 | /** | ||
142 | * BFI_IOCFC_I2H_UPDATEQ_RSP message | ||
143 | */ | ||
144 | struct bfi_iocfc_updateq_rsp_s { | ||
145 | struct bfi_mhdr_s mh; /* common msg header */ | ||
146 | u8 status; /* updateq status */ | ||
147 | u8 rsvd[3]; | ||
148 | }; | ||
149 | |||
150 | /** | ||
151 | * H2I Messages | ||
152 | */ | ||
153 | union bfi_iocfc_h2i_msg_u { | ||
154 | struct bfi_mhdr_s mh; | ||
155 | struct bfi_iocfc_cfg_req_s cfg_req; | ||
156 | struct bfi_iocfc_stats_req_s stats_get; | ||
157 | struct bfi_iocfc_stats_req_s stats_clr; | ||
158 | struct bfi_iocfc_updateq_req_s updateq_req; | ||
159 | u32 mboxmsg[BFI_IOC_MSGSZ]; | ||
160 | }; | ||
161 | |||
162 | /** | ||
163 | * I2H Messages | ||
164 | */ | ||
165 | union bfi_iocfc_i2h_msg_u { | ||
166 | struct bfi_mhdr_s mh; | ||
167 | struct bfi_iocfc_cfg_reply_s cfg_reply; | ||
168 | struct bfi_iocfc_stats_rsp_s stats_get_rsp; | ||
169 | struct bfi_iocfc_stats_rsp_s stats_clr_rsp; | ||
170 | struct bfi_iocfc_updateq_rsp_s updateq_rsp; | ||
171 | u32 mboxmsg[BFI_IOC_MSGSZ]; | ||
172 | }; | ||
173 | |||
174 | #pragma pack() | ||
175 | |||
176 | #endif /* __BFI_IOCFC_H__ */ | ||
177 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lport.h b/drivers/scsi/bfa/include/bfi/bfi_lport.h new file mode 100644 index 000000000000..29010614bac9 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_lport.h | |||
@@ -0,0 +1,89 @@ | |||
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 | #ifndef __BFI_LPORT_H__ | ||
19 | #define __BFI_LPORT_H__ | ||
20 | |||
21 | #include <bfi/bfi.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_lport_h2i_msgs { | ||
26 | BFI_LPORT_H2I_CREATE_REQ = 1, | ||
27 | BFI_LPORT_H2I_DELETE_REQ = 2, | ||
28 | }; | ||
29 | |||
30 | enum bfi_lport_i2h_msgs { | ||
31 | BFI_LPORT_I2H_CREATE_RSP = BFA_I2HM(1), | ||
32 | BFI_LPORT_I2H_DELETE_RSP = BFA_I2HM(2), | ||
33 | BFI_LPORT_I2H_ONLINE = BFA_I2HM(3), | ||
34 | BFI_LPORT_I2H_OFFLINE = BFA_I2HM(4), | ||
35 | }; | ||
36 | |||
37 | #define BFI_LPORT_MAX_SYNNAME 64 | ||
38 | |||
39 | enum bfi_lport_role_e { | ||
40 | BFI_LPORT_ROLE_FCPIM = 1, | ||
41 | BFI_LPORT_ROLE_FCPTM = 2, | ||
42 | BFI_LPORT_ROLE_IPFC = 4, | ||
43 | }; | ||
44 | |||
45 | struct bfi_lport_create_req_s { | ||
46 | bfi_mhdr_t mh; /* common msg header */ | ||
47 | u16 fabric_fwhdl; /* parent fabric instance */ | ||
48 | u8 roles; /* lport FC-4 roles */ | ||
49 | u8 rsvd; | ||
50 | wwn_t pwwn; /* port name */ | ||
51 | wwn_t nwwn; /* node name */ | ||
52 | u8 symname[BFI_LPORT_MAX_SYNNAME]; | ||
53 | }; | ||
54 | |||
55 | struct bfi_lport_create_rsp_s { | ||
56 | bfi_mhdr_t mh; /* common msg header */ | ||
57 | u8 status; /* lport creation status */ | ||
58 | u8 rsvd[3]; | ||
59 | }; | ||
60 | |||
61 | struct bfi_lport_delete_req_s { | ||
62 | bfi_mhdr_t mh; /* common msg header */ | ||
63 | u16 fw_handle; /* firmware lport handle */ | ||
64 | u16 rsvd; | ||
65 | }; | ||
66 | |||
67 | struct bfi_lport_delete_rsp_s { | ||
68 | bfi_mhdr_t mh; /* common msg header */ | ||
69 | u16 bfa_handle; /* host lport handle */ | ||
70 | u8 status; /* lport deletion status */ | ||
71 | u8 rsvd; | ||
72 | }; | ||
73 | |||
74 | union bfi_lport_h2i_msg_u { | ||
75 | bfi_msg_t *msg; | ||
76 | struct bfi_lport_create_req_s *create_req; | ||
77 | struct bfi_lport_delete_req_s *delete_req; | ||
78 | }; | ||
79 | |||
80 | union bfi_lport_i2h_msg_u { | ||
81 | bfi_msg_t *msg; | ||
82 | struct bfi_lport_create_rsp_s *create_rsp; | ||
83 | struct bfi_lport_delete_rsp_s *delete_rsp; | ||
84 | }; | ||
85 | |||
86 | #pragma pack() | ||
87 | |||
88 | #endif /* __BFI_LPORT_H__ */ | ||
89 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_lps.h b/drivers/scsi/bfa/include/bfi/bfi_lps.h new file mode 100644 index 000000000000..414b0e30f6ef --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_lps.h | |||
@@ -0,0 +1,96 @@ | |||
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 | #ifndef __BFI_LPS_H__ | ||
19 | #define __BFI_LPS_H__ | ||
20 | |||
21 | #include <bfi/bfi.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_lps_h2i_msgs { | ||
26 | BFI_LPS_H2I_LOGIN_REQ = 1, | ||
27 | BFI_LPS_H2I_LOGOUT_REQ = 2, | ||
28 | }; | ||
29 | |||
30 | enum bfi_lps_i2h_msgs { | ||
31 | BFI_LPS_H2I_LOGIN_RSP = BFA_I2HM(1), | ||
32 | BFI_LPS_H2I_LOGOUT_RSP = BFA_I2HM(2), | ||
33 | }; | ||
34 | |||
35 | struct bfi_lps_login_req_s { | ||
36 | struct bfi_mhdr_s mh; /* common msg header */ | ||
37 | u8 lp_tag; | ||
38 | u8 alpa; | ||
39 | u16 pdu_size; | ||
40 | wwn_t pwwn; | ||
41 | wwn_t nwwn; | ||
42 | u8 fdisc; | ||
43 | u8 auth_en; | ||
44 | u8 rsvd[2]; | ||
45 | }; | ||
46 | |||
47 | struct bfi_lps_login_rsp_s { | ||
48 | struct bfi_mhdr_s mh; /* common msg header */ | ||
49 | u8 lp_tag; | ||
50 | u8 status; | ||
51 | u8 lsrjt_rsn; | ||
52 | u8 lsrjt_expl; | ||
53 | wwn_t port_name; | ||
54 | wwn_t node_name; | ||
55 | u16 bb_credit; | ||
56 | u8 f_port; | ||
57 | u8 npiv_en; | ||
58 | u32 lp_pid : 24; | ||
59 | u32 auth_req : 8; | ||
60 | mac_t lp_mac; | ||
61 | mac_t fcf_mac; | ||
62 | u8 ext_status; | ||
63 | u8 brcd_switch;/* attached peer is brcd switch */ | ||
64 | }; | ||
65 | |||
66 | struct bfi_lps_logout_req_s { | ||
67 | struct bfi_mhdr_s mh; /* common msg header */ | ||
68 | u8 lp_tag; | ||
69 | u8 rsvd[3]; | ||
70 | wwn_t port_name; | ||
71 | }; | ||
72 | |||
73 | struct bfi_lps_logout_rsp_s { | ||
74 | struct bfi_mhdr_s mh; /* common msg header */ | ||
75 | u8 lp_tag; | ||
76 | u8 status; | ||
77 | u8 rsvd[2]; | ||
78 | }; | ||
79 | |||
80 | union bfi_lps_h2i_msg_u { | ||
81 | struct bfi_mhdr_s *msg; | ||
82 | struct bfi_lps_login_req_s *login_req; | ||
83 | struct bfi_lps_logout_req_s *logout_req; | ||
84 | }; | ||
85 | |||
86 | union bfi_lps_i2h_msg_u { | ||
87 | struct bfi_msg_s *msg; | ||
88 | struct bfi_lps_login_rsp_s *login_rsp; | ||
89 | struct bfi_lps_logout_rsp_s *logout_rsp; | ||
90 | }; | ||
91 | |||
92 | #pragma pack() | ||
93 | |||
94 | #endif /* __BFI_LPS_H__ */ | ||
95 | |||
96 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_port.h b/drivers/scsi/bfa/include/bfi/bfi_port.h new file mode 100644 index 000000000000..3ec3bea110ba --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_port.h | |||
@@ -0,0 +1,115 @@ | |||
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 | #ifndef __BFI_PORT_H__ | ||
18 | #define __BFI_PORT_H__ | ||
19 | |||
20 | #include <bfi/bfi.h> | ||
21 | #include <defs/bfa_defs_pport.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_port_h2i { | ||
26 | BFI_PORT_H2I_ENABLE_REQ = (1), | ||
27 | BFI_PORT_H2I_DISABLE_REQ = (2), | ||
28 | BFI_PORT_H2I_GET_STATS_REQ = (3), | ||
29 | BFI_PORT_H2I_CLEAR_STATS_REQ = (4), | ||
30 | }; | ||
31 | |||
32 | enum bfi_port_i2h { | ||
33 | BFI_PORT_I2H_ENABLE_RSP = BFA_I2HM(1), | ||
34 | BFI_PORT_I2H_DISABLE_RSP = BFA_I2HM(2), | ||
35 | BFI_PORT_I2H_GET_STATS_RSP = BFA_I2HM(3), | ||
36 | BFI_PORT_I2H_CLEAR_STATS_RSP = BFA_I2HM(4), | ||
37 | }; | ||
38 | |||
39 | /** | ||
40 | * Generic REQ type | ||
41 | */ | ||
42 | struct bfi_port_generic_req_s { | ||
43 | struct bfi_mhdr_s mh; /* msg header */ | ||
44 | u32 msgtag; /* msgtag for reply */ | ||
45 | u32 rsvd; | ||
46 | }; | ||
47 | |||
48 | /** | ||
49 | * Generic RSP type | ||
50 | */ | ||
51 | struct bfi_port_generic_rsp_s { | ||
52 | struct bfi_mhdr_s mh; /* common msg header */ | ||
53 | u8 status; /* port enable status */ | ||
54 | u8 rsvd[3]; | ||
55 | u32 msgtag; /* msgtag for reply */ | ||
56 | }; | ||
57 | |||
58 | /** | ||
59 | * @todo | ||
60 | * BFI_PORT_H2I_ENABLE_REQ | ||
61 | */ | ||
62 | |||
63 | /** | ||
64 | * @todo | ||
65 | * BFI_PORT_I2H_ENABLE_RSP | ||
66 | */ | ||
67 | |||
68 | /** | ||
69 | * BFI_PORT_H2I_DISABLE_REQ | ||
70 | */ | ||
71 | |||
72 | /** | ||
73 | * BFI_PORT_I2H_DISABLE_RSP | ||
74 | */ | ||
75 | |||
76 | /** | ||
77 | * BFI_PORT_H2I_GET_STATS_REQ | ||
78 | */ | ||
79 | struct bfi_port_get_stats_req_s { | ||
80 | struct bfi_mhdr_s mh; /* common msg header */ | ||
81 | union bfi_addr_u dma_addr; | ||
82 | }; | ||
83 | |||
84 | /** | ||
85 | * BFI_PORT_I2H_GET_STATS_RSP | ||
86 | */ | ||
87 | |||
88 | /** | ||
89 | * BFI_PORT_H2I_CLEAR_STATS_REQ | ||
90 | */ | ||
91 | |||
92 | /** | ||
93 | * BFI_PORT_I2H_CLEAR_STATS_RSP | ||
94 | */ | ||
95 | |||
96 | union bfi_port_h2i_msg_u { | ||
97 | struct bfi_mhdr_s mh; | ||
98 | struct bfi_port_generic_req_s enable_req; | ||
99 | struct bfi_port_generic_req_s disable_req; | ||
100 | struct bfi_port_get_stats_req_s getstats_req; | ||
101 | struct bfi_port_generic_req_s clearstats_req; | ||
102 | }; | ||
103 | |||
104 | union bfi_port_i2h_msg_u { | ||
105 | struct bfi_mhdr_s mh; | ||
106 | struct bfi_port_generic_rsp_s enable_rsp; | ||
107 | struct bfi_port_generic_rsp_s disable_rsp; | ||
108 | struct bfi_port_generic_rsp_s getstats_rsp; | ||
109 | struct bfi_port_generic_rsp_s clearstats_rsp; | ||
110 | }; | ||
111 | |||
112 | #pragma pack() | ||
113 | |||
114 | #endif /* __BFI_PORT_H__ */ | ||
115 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_pport.h b/drivers/scsi/bfa/include/bfi/bfi_pport.h new file mode 100644 index 000000000000..c96d246851af --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_pport.h | |||
@@ -0,0 +1,184 @@ | |||
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 | #ifndef __BFI_PPORT_H__ | ||
18 | #define __BFI_PPORT_H__ | ||
19 | |||
20 | #include <bfi/bfi.h> | ||
21 | #include <defs/bfa_defs_pport.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_pport_h2i { | ||
26 | BFI_PPORT_H2I_ENABLE_REQ = (1), | ||
27 | BFI_PPORT_H2I_DISABLE_REQ = (2), | ||
28 | BFI_PPORT_H2I_GET_STATS_REQ = (3), | ||
29 | BFI_PPORT_H2I_CLEAR_STATS_REQ = (4), | ||
30 | BFI_PPORT_H2I_SET_SVC_PARAMS_REQ = (5), | ||
31 | BFI_PPORT_H2I_ENABLE_RX_VF_TAG_REQ = (6), | ||
32 | BFI_PPORT_H2I_ENABLE_TX_VF_TAG_REQ = (7), | ||
33 | BFI_PPORT_H2I_GET_QOS_STATS_REQ = (8), | ||
34 | BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ = (9), | ||
35 | }; | ||
36 | |||
37 | enum bfi_pport_i2h { | ||
38 | BFI_PPORT_I2H_ENABLE_RSP = BFA_I2HM(1), | ||
39 | BFI_PPORT_I2H_DISABLE_RSP = BFA_I2HM(2), | ||
40 | BFI_PPORT_I2H_GET_STATS_RSP = BFA_I2HM(3), | ||
41 | BFI_PPORT_I2H_CLEAR_STATS_RSP = BFA_I2HM(4), | ||
42 | BFI_PPORT_I2H_SET_SVC_PARAMS_RSP = BFA_I2HM(5), | ||
43 | BFI_PPORT_I2H_ENABLE_RX_VF_TAG_RSP = BFA_I2HM(6), | ||
44 | BFI_PPORT_I2H_ENABLE_TX_VF_TAG_RSP = BFA_I2HM(7), | ||
45 | BFI_PPORT_I2H_EVENT = BFA_I2HM(8), | ||
46 | BFI_PPORT_I2H_GET_QOS_STATS_RSP = BFA_I2HM(9), | ||
47 | BFI_PPORT_I2H_CLEAR_QOS_STATS_RSP = BFA_I2HM(10), | ||
48 | }; | ||
49 | |||
50 | /** | ||
51 | * Generic REQ type | ||
52 | */ | ||
53 | struct bfi_pport_generic_req_s { | ||
54 | struct bfi_mhdr_s mh; /* msg header */ | ||
55 | u32 msgtag; /* msgtag for reply */ | ||
56 | }; | ||
57 | |||
58 | /** | ||
59 | * Generic RSP type | ||
60 | */ | ||
61 | struct bfi_pport_generic_rsp_s { | ||
62 | struct bfi_mhdr_s mh; /* common msg header */ | ||
63 | u8 status; /* port enable status */ | ||
64 | u8 rsvd[3]; | ||
65 | u32 msgtag; /* msgtag for reply */ | ||
66 | }; | ||
67 | |||
68 | /** | ||
69 | * BFI_PPORT_H2I_ENABLE_REQ | ||
70 | */ | ||
71 | struct bfi_pport_enable_req_s { | ||
72 | struct bfi_mhdr_s mh; /* msg header */ | ||
73 | u32 rsvd1; | ||
74 | wwn_t nwwn; /* node wwn of physical port */ | ||
75 | wwn_t pwwn; /* port wwn of physical port */ | ||
76 | struct bfa_pport_cfg_s port_cfg; /* port configuration */ | ||
77 | union bfi_addr_u stats_dma_addr; /* DMA address for stats */ | ||
78 | u32 msgtag; /* msgtag for reply */ | ||
79 | u32 rsvd2; | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * BFI_PPORT_I2H_ENABLE_RSP | ||
84 | */ | ||
85 | #define bfi_pport_enable_rsp_t struct bfi_pport_generic_rsp_s | ||
86 | |||
87 | /** | ||
88 | * BFI_PPORT_H2I_DISABLE_REQ | ||
89 | */ | ||
90 | #define bfi_pport_disable_req_t struct bfi_pport_generic_req_s | ||
91 | |||
92 | /** | ||
93 | * BFI_PPORT_I2H_DISABLE_RSP | ||
94 | */ | ||
95 | #define bfi_pport_disable_rsp_t struct bfi_pport_generic_rsp_s | ||
96 | |||
97 | /** | ||
98 | * BFI_PPORT_H2I_GET_STATS_REQ | ||
99 | */ | ||
100 | #define bfi_pport_get_stats_req_t struct bfi_pport_generic_req_s | ||
101 | |||
102 | /** | ||
103 | * BFI_PPORT_I2H_GET_STATS_RSP | ||
104 | */ | ||
105 | #define bfi_pport_get_stats_rsp_t struct bfi_pport_generic_rsp_s | ||
106 | |||
107 | /** | ||
108 | * BFI_PPORT_H2I_CLEAR_STATS_REQ | ||
109 | */ | ||
110 | #define bfi_pport_clear_stats_req_t struct bfi_pport_generic_req_s | ||
111 | |||
112 | /** | ||
113 | * BFI_PPORT_I2H_CLEAR_STATS_RSP | ||
114 | */ | ||
115 | #define bfi_pport_clear_stats_rsp_t struct bfi_pport_generic_rsp_s | ||
116 | |||
117 | /** | ||
118 | * BFI_PPORT_H2I_GET_QOS_STATS_REQ | ||
119 | */ | ||
120 | #define bfi_pport_get_qos_stats_req_t struct bfi_pport_generic_req_s | ||
121 | |||
122 | /** | ||
123 | * BFI_PPORT_H2I_GET_QOS_STATS_RSP | ||
124 | */ | ||
125 | #define bfi_pport_get_qos_stats_rsp_t struct bfi_pport_generic_rsp_s | ||
126 | |||
127 | /** | ||
128 | * BFI_PPORT_H2I_CLEAR_QOS_STATS_REQ | ||
129 | */ | ||
130 | #define bfi_pport_clear_qos_stats_req_t struct bfi_pport_generic_req_s | ||
131 | |||
132 | /** | ||
133 | * BFI_PPORT_H2I_CLEAR_QOS_STATS_RSP | ||
134 | */ | ||
135 | #define bfi_pport_clear_qos_stats_rsp_t struct bfi_pport_generic_rsp_s | ||
136 | |||
137 | /** | ||
138 | * BFI_PPORT_H2I_SET_SVC_PARAMS_REQ | ||
139 | */ | ||
140 | struct bfi_pport_set_svc_params_req_s { | ||
141 | struct bfi_mhdr_s mh; /* msg header */ | ||
142 | u16 tx_bbcredit; /* Tx credits */ | ||
143 | u16 rsvd; | ||
144 | }; | ||
145 | |||
146 | /** | ||
147 | * BFI_PPORT_I2H_SET_SVC_PARAMS_RSP | ||
148 | */ | ||
149 | |||
150 | /** | ||
151 | * BFI_PPORT_I2H_EVENT | ||
152 | */ | ||
153 | struct bfi_pport_event_s { | ||
154 | struct bfi_mhdr_s mh; /* common msg header */ | ||
155 | struct bfa_pport_link_s link_state; | ||
156 | }; | ||
157 | |||
158 | union bfi_pport_h2i_msg_u { | ||
159 | struct bfi_mhdr_s *mhdr; | ||
160 | struct bfi_pport_enable_req_s *penable; | ||
161 | struct bfi_pport_generic_req_s *pdisable; | ||
162 | struct bfi_pport_generic_req_s *pgetstats; | ||
163 | struct bfi_pport_generic_req_s *pclearstats; | ||
164 | struct bfi_pport_set_svc_params_req_s *psetsvcparams; | ||
165 | struct bfi_pport_get_qos_stats_req_s *pgetqosstats; | ||
166 | struct bfi_pport_generic_req_s *pclearqosstats; | ||
167 | }; | ||
168 | |||
169 | union bfi_pport_i2h_msg_u { | ||
170 | struct bfi_msg_s *msg; | ||
171 | struct bfi_pport_generic_rsp_s *enable_rsp; | ||
172 | struct bfi_pport_disable_rsp_s *disable_rsp; | ||
173 | struct bfi_pport_generic_rsp_s *getstats_rsp; | ||
174 | struct bfi_pport_clear_stats_rsp_s *clearstats_rsp; | ||
175 | struct bfi_pport_set_svc_params_rsp_s *setsvcparasm_rsp; | ||
176 | struct bfi_pport_get_qos_stats_rsp_s *getqosstats_rsp; | ||
177 | struct bfi_pport_clear_qos_stats_rsp_s *clearqosstats_rsp; | ||
178 | struct bfi_pport_event_s *event; | ||
179 | }; | ||
180 | |||
181 | #pragma pack() | ||
182 | |||
183 | #endif /* __BFI_PPORT_H__ */ | ||
184 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_rport.h b/drivers/scsi/bfa/include/bfi/bfi_rport.h new file mode 100644 index 000000000000..3520f55f09d7 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_rport.h | |||
@@ -0,0 +1,104 @@ | |||
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 | #ifndef __BFI_RPORT_H__ | ||
19 | #define __BFI_RPORT_H__ | ||
20 | |||
21 | #include <bfi/bfi.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_rport_h2i_msgs { | ||
26 | BFI_RPORT_H2I_CREATE_REQ = 1, | ||
27 | BFI_RPORT_H2I_DELETE_REQ = 2, | ||
28 | BFI_RPORT_H2I_SET_SPEED_REQ = 3, | ||
29 | }; | ||
30 | |||
31 | enum bfi_rport_i2h_msgs { | ||
32 | BFI_RPORT_I2H_CREATE_RSP = BFA_I2HM(1), | ||
33 | BFI_RPORT_I2H_DELETE_RSP = BFA_I2HM(2), | ||
34 | BFI_RPORT_I2H_QOS_SCN = BFA_I2HM(3), | ||
35 | }; | ||
36 | |||
37 | struct bfi_rport_create_req_s { | ||
38 | struct bfi_mhdr_s mh; /* common msg header */ | ||
39 | u16 bfa_handle; /* host rport handle */ | ||
40 | u16 max_frmsz; /* max rcv pdu size */ | ||
41 | u32 pid : 24, /* remote port ID */ | ||
42 | lp_tag : 8; /* local port tag */ | ||
43 | u32 local_pid : 24, /* local port ID */ | ||
44 | cisc : 8; | ||
45 | u8 fc_class; /* supported FC classes */ | ||
46 | u8 vf_en; /* virtual fabric enable */ | ||
47 | u16 vf_id; /* virtual fabric ID */ | ||
48 | }; | ||
49 | |||
50 | struct bfi_rport_create_rsp_s { | ||
51 | struct bfi_mhdr_s mh; /* common msg header */ | ||
52 | u8 status; /* rport creation status */ | ||
53 | u8 rsvd[3]; | ||
54 | u16 bfa_handle; /* host rport handle */ | ||
55 | u16 fw_handle; /* firmware rport handle */ | ||
56 | struct bfa_rport_qos_attr_s qos_attr; /* QoS Attributes */ | ||
57 | }; | ||
58 | |||
59 | struct bfa_rport_speed_req_s { | ||
60 | struct bfi_mhdr_s mh; /* common msg header */ | ||
61 | u16 fw_handle; /* firmware rport handle */ | ||
62 | u8 speed; /*! rport's speed via RPSC */ | ||
63 | u8 rsvd; | ||
64 | }; | ||
65 | |||
66 | struct bfi_rport_delete_req_s { | ||
67 | struct bfi_mhdr_s mh; /* common msg header */ | ||
68 | u16 fw_handle; /* firmware rport handle */ | ||
69 | u16 rsvd; | ||
70 | }; | ||
71 | |||
72 | struct bfi_rport_delete_rsp_s { | ||
73 | struct bfi_mhdr_s mh; /* common msg header */ | ||
74 | u16 bfa_handle; /* host rport handle */ | ||
75 | u8 status; /* rport deletion status */ | ||
76 | u8 rsvd; | ||
77 | }; | ||
78 | |||
79 | struct bfi_rport_qos_scn_s { | ||
80 | struct bfi_mhdr_s mh; /* common msg header */ | ||
81 | u16 bfa_handle; /* host rport handle */ | ||
82 | u16 rsvd; | ||
83 | struct bfa_rport_qos_attr_s old_qos_attr; /* Old QoS Attributes */ | ||
84 | struct bfa_rport_qos_attr_s new_qos_attr; /* New QoS Attributes */ | ||
85 | }; | ||
86 | |||
87 | union bfi_rport_h2i_msg_u { | ||
88 | struct bfi_msg_s *msg; | ||
89 | struct bfi_rport_create_req_s *create_req; | ||
90 | struct bfi_rport_delete_req_s *delete_req; | ||
91 | struct bfi_rport_speed_req_s *speed_req; | ||
92 | }; | ||
93 | |||
94 | union bfi_rport_i2h_msg_u { | ||
95 | struct bfi_msg_s *msg; | ||
96 | struct bfi_rport_create_rsp_s *create_rsp; | ||
97 | struct bfi_rport_delete_rsp_s *delete_rsp; | ||
98 | struct bfi_rport_qos_scn_s *qos_scn_evt; | ||
99 | }; | ||
100 | |||
101 | #pragma pack() | ||
102 | |||
103 | #endif /* __BFI_RPORT_H__ */ | ||
104 | |||
diff --git a/drivers/scsi/bfa/include/bfi/bfi_uf.h b/drivers/scsi/bfa/include/bfi/bfi_uf.h new file mode 100644 index 000000000000..f328a9e7e622 --- /dev/null +++ b/drivers/scsi/bfa/include/bfi/bfi_uf.h | |||
@@ -0,0 +1,52 @@ | |||
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 | #ifndef __BFI_UF_H__ | ||
19 | #define __BFI_UF_H__ | ||
20 | |||
21 | #include "bfi.h" | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum bfi_uf_h2i { | ||
26 | BFI_UF_H2I_BUF_POST = 1, | ||
27 | }; | ||
28 | |||
29 | enum bfi_uf_i2h { | ||
30 | BFI_UF_I2H_FRM_RCVD = BFA_I2HM(1), | ||
31 | }; | ||
32 | |||
33 | #define BFA_UF_MAX_SGES 2 | ||
34 | |||
35 | struct bfi_uf_buf_post_s { | ||
36 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
37 | u16 buf_tag; /* buffer tag */ | ||
38 | u16 buf_len; /* total buffer length */ | ||
39 | struct bfi_sge_s sge[BFA_UF_MAX_SGES]; /* buffer DMA SGEs */ | ||
40 | }; | ||
41 | |||
42 | struct bfi_uf_frm_rcvd_s { | ||
43 | struct bfi_mhdr_s mh; /* Common msg header */ | ||
44 | u16 buf_tag; /* buffer tag */ | ||
45 | u16 rsvd; | ||
46 | u16 frm_len; /* received frame length */ | ||
47 | u16 xfr_len; /* tranferred length */ | ||
48 | }; | ||
49 | |||
50 | #pragma pack() | ||
51 | |||
52 | #endif /* __BFI_UF_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h b/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h new file mode 100644 index 000000000000..43ba7064e81a --- /dev/null +++ b/drivers/scsi/bfa/include/cna/bfa_cna_trcmod.h | |||
@@ -0,0 +1,36 @@ | |||
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 | * bfa_cna_trcmod.h CNA trace modules | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_CNA_TRCMOD_H__ | ||
23 | #define __BFA_CNA_TRCMOD_H__ | ||
24 | |||
25 | #include <cs/bfa_trc.h> | ||
26 | |||
27 | /* | ||
28 | * !!! Only append to the enums defined here to avoid any versioning | ||
29 | * !!! needed between trace utility and driver version | ||
30 | */ | ||
31 | enum { | ||
32 | BFA_TRC_CNA_CEE = 1, | ||
33 | BFA_TRC_CNA_PORT = 2, | ||
34 | }; | ||
35 | |||
36 | #endif /* __BFA_CNA_TRCMOD_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/cna/cee/bfa_cee.h b/drivers/scsi/bfa/include/cna/cee/bfa_cee.h new file mode 100644 index 000000000000..77f297f68046 --- /dev/null +++ b/drivers/scsi/bfa/include/cna/cee/bfa_cee.h | |||
@@ -0,0 +1,77 @@ | |||
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 | #ifndef __BFA_CEE_H__ | ||
19 | #define __BFA_CEE_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_cee.h> | ||
22 | #include <bfa_ioc.h> | ||
23 | #include <cs/bfa_trc.h> | ||
24 | #include <cs/bfa_log.h> | ||
25 | |||
26 | typedef void (*bfa_cee_get_attr_cbfn_t) (void *dev, bfa_status_t status); | ||
27 | typedef void (*bfa_cee_get_stats_cbfn_t) (void *dev, bfa_status_t status); | ||
28 | typedef void (*bfa_cee_reset_stats_cbfn_t) (void *dev, bfa_status_t status); | ||
29 | typedef void (*bfa_cee_hbfail_cbfn_t) (void *dev, bfa_status_t status); | ||
30 | |||
31 | struct bfa_cee_cbfn_s { | ||
32 | bfa_cee_get_attr_cbfn_t get_attr_cbfn; | ||
33 | void *get_attr_cbarg; | ||
34 | bfa_cee_get_stats_cbfn_t get_stats_cbfn; | ||
35 | void *get_stats_cbarg; | ||
36 | bfa_cee_reset_stats_cbfn_t reset_stats_cbfn; | ||
37 | void *reset_stats_cbarg; | ||
38 | }; | ||
39 | |||
40 | struct bfa_cee_s { | ||
41 | void *dev; | ||
42 | bfa_boolean_t get_attr_pending; | ||
43 | bfa_boolean_t get_stats_pending; | ||
44 | bfa_boolean_t reset_stats_pending; | ||
45 | bfa_status_t get_attr_status; | ||
46 | bfa_status_t get_stats_status; | ||
47 | bfa_status_t reset_stats_status; | ||
48 | struct bfa_cee_cbfn_s cbfn; | ||
49 | struct bfa_ioc_hbfail_notify_s hbfail; | ||
50 | struct bfa_trc_mod_s *trcmod; | ||
51 | struct bfa_log_mod_s *logmod; | ||
52 | struct bfa_cee_attr_s *attr; | ||
53 | struct bfa_cee_stats_s *stats; | ||
54 | struct bfa_dma_s attr_dma; | ||
55 | struct bfa_dma_s stats_dma; | ||
56 | struct bfa_ioc_s *ioc; | ||
57 | struct bfa_mbox_cmd_s get_cfg_mb; | ||
58 | struct bfa_mbox_cmd_s get_stats_mb; | ||
59 | struct bfa_mbox_cmd_s reset_stats_mb; | ||
60 | }; | ||
61 | |||
62 | u32 bfa_cee_meminfo(void); | ||
63 | void bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, | ||
64 | u64 dma_pa); | ||
65 | void bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev, | ||
66 | struct bfa_trc_mod_s *trcmod, | ||
67 | struct bfa_log_mod_s *logmod); | ||
68 | void bfa_cee_detach(struct bfa_cee_s *cee); | ||
69 | bfa_status_t bfa_cee_get_attr(struct bfa_cee_s *cee, | ||
70 | struct bfa_cee_attr_s *attr, | ||
71 | bfa_cee_get_attr_cbfn_t cbfn, void *cbarg); | ||
72 | bfa_status_t bfa_cee_get_stats(struct bfa_cee_s *cee, | ||
73 | struct bfa_cee_stats_s *stats, | ||
74 | bfa_cee_get_stats_cbfn_t cbfn, void *cbarg); | ||
75 | bfa_status_t bfa_cee_reset_stats(struct bfa_cee_s *cee, | ||
76 | bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg); | ||
77 | #endif /* __BFA_CEE_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/cna/port/bfa_port.h b/drivers/scsi/bfa/include/cna/port/bfa_port.h new file mode 100644 index 000000000000..7cbf17d3141b --- /dev/null +++ b/drivers/scsi/bfa/include/cna/port/bfa_port.h | |||
@@ -0,0 +1,69 @@ | |||
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 | #ifndef __BFA_PORT_H__ | ||
19 | #define __BFA_PORT_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_port.h> | ||
22 | #include <bfa_ioc.h> | ||
23 | #include <cs/bfa_trc.h> | ||
24 | #include <cs/bfa_log.h> | ||
25 | |||
26 | typedef void (*bfa_port_stats_cbfn_t) (void *dev, bfa_status_t status); | ||
27 | typedef void (*bfa_port_endis_cbfn_t) (void *dev, bfa_status_t status); | ||
28 | |||
29 | struct bfa_port_s { | ||
30 | void *dev; | ||
31 | struct bfa_ioc_s *ioc; | ||
32 | struct bfa_trc_mod_s *trcmod; | ||
33 | struct bfa_log_mod_s *logmod; | ||
34 | u32 msgtag; | ||
35 | bfa_boolean_t stats_busy; | ||
36 | struct bfa_mbox_cmd_s stats_mb; | ||
37 | bfa_port_stats_cbfn_t stats_cbfn; | ||
38 | void *stats_cbarg; | ||
39 | bfa_status_t stats_status; | ||
40 | union bfa_pport_stats_u *stats; | ||
41 | struct bfa_dma_s stats_dma; | ||
42 | bfa_boolean_t endis_pending; | ||
43 | struct bfa_mbox_cmd_s endis_mb; | ||
44 | bfa_port_endis_cbfn_t endis_cbfn; | ||
45 | void *endis_cbarg; | ||
46 | bfa_status_t endis_status; | ||
47 | struct bfa_ioc_hbfail_notify_s hbfail; | ||
48 | }; | ||
49 | |||
50 | void bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, | ||
51 | void *dev, struct bfa_trc_mod_s *trcmod, | ||
52 | struct bfa_log_mod_s *logmod); | ||
53 | void bfa_port_detach(struct bfa_port_s *port); | ||
54 | void bfa_port_hbfail(void *arg); | ||
55 | |||
56 | bfa_status_t bfa_port_get_stats(struct bfa_port_s *port, | ||
57 | union bfa_pport_stats_u *stats, | ||
58 | bfa_port_stats_cbfn_t cbfn, void *cbarg); | ||
59 | bfa_status_t bfa_port_clear_stats(struct bfa_port_s *port, | ||
60 | bfa_port_stats_cbfn_t cbfn, void *cbarg); | ||
61 | bfa_status_t bfa_port_enable(struct bfa_port_s *port, | ||
62 | bfa_port_endis_cbfn_t cbfn, void *cbarg); | ||
63 | bfa_status_t bfa_port_disable(struct bfa_port_s *port, | ||
64 | bfa_port_endis_cbfn_t cbfn, void *cbarg); | ||
65 | u32 bfa_port_meminfo(void); | ||
66 | void bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, | ||
67 | u64 dma_pa); | ||
68 | |||
69 | #endif /* __BFA_PORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h b/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h new file mode 100644 index 000000000000..1563ee512218 --- /dev/null +++ b/drivers/scsi/bfa/include/cna/pstats/ethport_defs.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License (GPL) Version 2 as | ||
9 | * published by the Free Software Foundation | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #ifndef __ETHPORT_DEFS_H__ | ||
18 | #define __ETHPORT_DEFS_H__ | ||
19 | |||
20 | struct bnad_drv_stats { | ||
21 | u64 netif_queue_stop; | ||
22 | u64 netif_queue_wakeup; | ||
23 | u64 tso4; | ||
24 | u64 tso6; | ||
25 | u64 tso_err; | ||
26 | u64 tcpcsum_offload; | ||
27 | u64 udpcsum_offload; | ||
28 | u64 csum_help; | ||
29 | u64 csum_help_err; | ||
30 | |||
31 | u64 hw_stats_updates; | ||
32 | u64 netif_rx_schedule; | ||
33 | u64 netif_rx_complete; | ||
34 | u64 netif_rx_dropped; | ||
35 | }; | ||
36 | #endif | ||
diff --git a/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h b/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h new file mode 100644 index 000000000000..eb7548030d0f --- /dev/null +++ b/drivers/scsi/bfa/include/cna/pstats/phyport_defs.h | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. | ||
3 | * All rights reserved. | ||
4 | * | ||
5 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License (GPL) Version 2 as | ||
9 | * published by the Free Software Foundation | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | * General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #ifndef __PHYPORT_DEFS_H__ | ||
18 | #define __PHYPORT_DEFS_H__ | ||
19 | |||
20 | #define BNA_TXF_ID_MAX 64 | ||
21 | #define BNA_RXF_ID_MAX 64 | ||
22 | |||
23 | /* | ||
24 | * Statistics | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | * TxF Frame Statistics | ||
29 | */ | ||
30 | struct bna_stats_txf { | ||
31 | u64 ucast_octets; | ||
32 | u64 ucast; | ||
33 | u64 ucast_vlan; | ||
34 | |||
35 | u64 mcast_octets; | ||
36 | u64 mcast; | ||
37 | u64 mcast_vlan; | ||
38 | |||
39 | u64 bcast_octets; | ||
40 | u64 bcast; | ||
41 | u64 bcast_vlan; | ||
42 | |||
43 | u64 errors; | ||
44 | u64 filter_vlan; /* frames filtered due to VLAN */ | ||
45 | u64 filter_mac_sa; /* frames filtered due to SA check */ | ||
46 | }; | ||
47 | |||
48 | /* | ||
49 | * RxF Frame Statistics | ||
50 | */ | ||
51 | struct bna_stats_rxf { | ||
52 | u64 ucast_octets; | ||
53 | u64 ucast; | ||
54 | u64 ucast_vlan; | ||
55 | |||
56 | u64 mcast_octets; | ||
57 | u64 mcast; | ||
58 | u64 mcast_vlan; | ||
59 | |||
60 | u64 bcast_octets; | ||
61 | u64 bcast; | ||
62 | u64 bcast_vlan; | ||
63 | u64 frame_drops; | ||
64 | }; | ||
65 | |||
66 | /* | ||
67 | * FC Tx Frame Statistics | ||
68 | */ | ||
69 | struct bna_stats_fc_tx { | ||
70 | u64 txf_ucast_octets; | ||
71 | u64 txf_ucast; | ||
72 | u64 txf_ucast_vlan; | ||
73 | |||
74 | u64 txf_mcast_octets; | ||
75 | u64 txf_mcast; | ||
76 | u64 txf_mcast_vlan; | ||
77 | |||
78 | u64 txf_bcast_octets; | ||
79 | u64 txf_bcast; | ||
80 | u64 txf_bcast_vlan; | ||
81 | |||
82 | u64 txf_parity_errors; | ||
83 | u64 txf_timeout; | ||
84 | u64 txf_fid_parity_errors; | ||
85 | }; | ||
86 | |||
87 | /* | ||
88 | * FC Rx Frame Statistics | ||
89 | */ | ||
90 | struct bna_stats_fc_rx { | ||
91 | u64 rxf_ucast_octets; | ||
92 | u64 rxf_ucast; | ||
93 | u64 rxf_ucast_vlan; | ||
94 | |||
95 | u64 rxf_mcast_octets; | ||
96 | u64 rxf_mcast; | ||
97 | u64 rxf_mcast_vlan; | ||
98 | |||
99 | u64 rxf_bcast_octets; | ||
100 | u64 rxf_bcast; | ||
101 | u64 rxf_bcast_vlan; | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * RAD Frame Statistics | ||
106 | */ | ||
107 | struct cna_stats_rad { | ||
108 | u64 rx_frames; | ||
109 | u64 rx_octets; | ||
110 | u64 rx_vlan_frames; | ||
111 | |||
112 | u64 rx_ucast; | ||
113 | u64 rx_ucast_octets; | ||
114 | u64 rx_ucast_vlan; | ||
115 | |||
116 | u64 rx_mcast; | ||
117 | u64 rx_mcast_octets; | ||
118 | u64 rx_mcast_vlan; | ||
119 | |||
120 | u64 rx_bcast; | ||
121 | u64 rx_bcast_octets; | ||
122 | u64 rx_bcast_vlan; | ||
123 | |||
124 | u64 rx_drops; | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * BPC Tx Registers | ||
129 | */ | ||
130 | struct cna_stats_bpc_tx { | ||
131 | u64 tx_pause[8]; | ||
132 | u64 tx_zero_pause[8]; /* Pause cancellation */ | ||
133 | u64 tx_first_pause[8]; /* Pause initiation rather | ||
134 | *than retention */ | ||
135 | }; | ||
136 | |||
137 | /* | ||
138 | * BPC Rx Registers | ||
139 | */ | ||
140 | struct cna_stats_bpc_rx { | ||
141 | u64 rx_pause[8]; | ||
142 | u64 rx_zero_pause[8]; /* Pause cancellation */ | ||
143 | u64 rx_first_pause[8]; /* Pause initiation rather | ||
144 | *than retention */ | ||
145 | }; | ||
146 | |||
147 | /* | ||
148 | * MAC Rx Statistics | ||
149 | */ | ||
150 | struct cna_stats_mac_rx { | ||
151 | u64 frame_64; /* both rx and tx counter */ | ||
152 | u64 frame_65_127; /* both rx and tx counter */ | ||
153 | u64 frame_128_255; /* both rx and tx counter */ | ||
154 | u64 frame_256_511; /* both rx and tx counter */ | ||
155 | u64 frame_512_1023; /* both rx and tx counter */ | ||
156 | u64 frame_1024_1518; /* both rx and tx counter */ | ||
157 | u64 frame_1518_1522; /* both rx and tx counter */ | ||
158 | u64 rx_bytes; | ||
159 | u64 rx_packets; | ||
160 | u64 rx_fcs_error; | ||
161 | u64 rx_multicast; | ||
162 | u64 rx_broadcast; | ||
163 | u64 rx_control_frames; | ||
164 | u64 rx_pause; | ||
165 | u64 rx_unknown_opcode; | ||
166 | u64 rx_alignment_error; | ||
167 | u64 rx_frame_length_error; | ||
168 | u64 rx_code_error; | ||
169 | u64 rx_carrier_sense_error; | ||
170 | u64 rx_undersize; | ||
171 | u64 rx_oversize; | ||
172 | u64 rx_fragments; | ||
173 | u64 rx_jabber; | ||
174 | u64 rx_drop; | ||
175 | }; | ||
176 | |||
177 | /* | ||
178 | * MAC Tx Statistics | ||
179 | */ | ||
180 | struct cna_stats_mac_tx { | ||
181 | u64 tx_bytes; | ||
182 | u64 tx_packets; | ||
183 | u64 tx_multicast; | ||
184 | u64 tx_broadcast; | ||
185 | u64 tx_pause; | ||
186 | u64 tx_deferral; | ||
187 | u64 tx_excessive_deferral; | ||
188 | u64 tx_single_collision; | ||
189 | u64 tx_muliple_collision; | ||
190 | u64 tx_late_collision; | ||
191 | u64 tx_excessive_collision; | ||
192 | u64 tx_total_collision; | ||
193 | u64 tx_pause_honored; | ||
194 | u64 tx_drop; | ||
195 | u64 tx_jabber; | ||
196 | u64 tx_fcs_error; | ||
197 | u64 tx_control_frame; | ||
198 | u64 tx_oversize; | ||
199 | u64 tx_undersize; | ||
200 | u64 tx_fragments; | ||
201 | }; | ||
202 | |||
203 | /* | ||
204 | * Complete statistics | ||
205 | */ | ||
206 | struct bna_stats { | ||
207 | struct cna_stats_mac_rx mac_rx_stats; | ||
208 | struct cna_stats_bpc_rx bpc_rx_stats; | ||
209 | struct cna_stats_rad rad_stats; | ||
210 | struct bna_stats_fc_rx fc_rx_stats; | ||
211 | struct cna_stats_mac_tx mac_tx_stats; | ||
212 | struct cna_stats_bpc_tx bpc_tx_stats; | ||
213 | struct bna_stats_fc_tx fc_tx_stats; | ||
214 | struct bna_stats_rxf rxf_stats[BNA_TXF_ID_MAX]; | ||
215 | struct bna_stats_txf txf_stats[BNA_RXF_ID_MAX]; | ||
216 | }; | ||
217 | |||
218 | #endif | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_checksum.h b/drivers/scsi/bfa/include/cs/bfa_checksum.h new file mode 100644 index 000000000000..af8c1d533ba8 --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_checksum.h | |||
@@ -0,0 +1,60 @@ | |||
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 | * bfa_checksum.h BFA checksum utilities | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_CHECKSUM_H__ | ||
23 | #define __BFA_CHECKSUM_H__ | ||
24 | |||
25 | static inline u32 | ||
26 | bfa_checksum_u32(u32 *buf, int sz) | ||
27 | { | ||
28 | int i, m = sz >> 2; | ||
29 | u32 sum = 0; | ||
30 | |||
31 | for (i = 0; i < m; i++) | ||
32 | sum ^= buf[i]; | ||
33 | |||
34 | return (sum); | ||
35 | } | ||
36 | |||
37 | static inline u16 | ||
38 | bfa_checksum_u16(u16 *buf, int sz) | ||
39 | { | ||
40 | int i, m = sz >> 1; | ||
41 | u16 sum = 0; | ||
42 | |||
43 | for (i = 0; i < m; i++) | ||
44 | sum ^= buf[i]; | ||
45 | |||
46 | return (sum); | ||
47 | } | ||
48 | |||
49 | static inline u8 | ||
50 | bfa_checksum_u8(u8 *buf, int sz) | ||
51 | { | ||
52 | int i; | ||
53 | u8 sum = 0; | ||
54 | |||
55 | for (i = 0; i < sz; i++) | ||
56 | sum ^= buf[i]; | ||
57 | |||
58 | return (sum); | ||
59 | } | ||
60 | #endif | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_debug.h b/drivers/scsi/bfa/include/cs/bfa_debug.h new file mode 100644 index 000000000000..441be86b1b0f --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_debug.h | |||
@@ -0,0 +1,44 @@ | |||
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 | * bfa_debug.h BFA debug interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_DEBUG_H__ | ||
23 | #define __BFA_DEBUG_H__ | ||
24 | |||
25 | #define bfa_assert(__cond) do { \ | ||
26 | if (!(__cond)) \ | ||
27 | bfa_panic(__LINE__, __FILE__, #__cond); \ | ||
28 | } while (0) | ||
29 | |||
30 | #define bfa_sm_fault(__mod, __event) do { \ | ||
31 | bfa_sm_panic((__mod)->logm, __LINE__, __FILE__, __event); \ | ||
32 | } while (0) | ||
33 | |||
34 | #ifndef BFA_PERF_BUILD | ||
35 | #define bfa_assert_fp(__cond) bfa_assert(__cond) | ||
36 | #else | ||
37 | #define bfa_assert_fp(__cond) | ||
38 | #endif | ||
39 | |||
40 | struct bfa_log_mod_s; | ||
41 | void bfa_panic(int line, char *file, char *panicstr); | ||
42 | void bfa_sm_panic(struct bfa_log_mod_s *logm, int line, char *file, int event); | ||
43 | |||
44 | #endif /* __BFA_DEBUG_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_log.h b/drivers/scsi/bfa/include/cs/bfa_log.h new file mode 100644 index 000000000000..761cbe22130a --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_log.h | |||
@@ -0,0 +1,184 @@ | |||
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 | * bfa_log.h BFA log library data structure and function definition | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_LOG_H__ | ||
23 | #define __BFA_LOG_H__ | ||
24 | |||
25 | #include <bfa_os_inc.h> | ||
26 | #include <defs/bfa_defs_status.h> | ||
27 | #include <defs/bfa_defs_aen.h> | ||
28 | |||
29 | /* | ||
30 | * BFA log module definition | ||
31 | * | ||
32 | * To create a new module id: | ||
33 | * Add a #define at the end of the list below. Select a value for your | ||
34 | * definition so that it is one (1) greater than the previous | ||
35 | * definition. Modify the definition of BFA_LOG_MODULE_ID_MAX to become | ||
36 | * your new definition. | ||
37 | * Should have no gaps in between the values because this is used in arrays. | ||
38 | * IMPORTANT: AEN_IDs must be at the begining, otherwise update bfa_defs_aen.h | ||
39 | */ | ||
40 | |||
41 | enum bfa_log_module_id { | ||
42 | BFA_LOG_UNUSED_ID = 0, | ||
43 | |||
44 | /* AEN defs begin */ | ||
45 | BFA_LOG_AEN_MIN = BFA_LOG_UNUSED_ID, | ||
46 | |||
47 | BFA_LOG_AEN_ID_ADAPTER = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ADAPTER,/* 1 */ | ||
48 | BFA_LOG_AEN_ID_PORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_PORT, /* 2 */ | ||
49 | BFA_LOG_AEN_ID_LPORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_LPORT, /* 3 */ | ||
50 | BFA_LOG_AEN_ID_RPORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_RPORT, /* 4 */ | ||
51 | BFA_LOG_AEN_ID_ITNIM = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ITNIM, /* 5 */ | ||
52 | BFA_LOG_AEN_ID_TIN = BFA_LOG_AEN_MIN + BFA_AEN_CAT_TIN, /* 6 */ | ||
53 | BFA_LOG_AEN_ID_IPFC = BFA_LOG_AEN_MIN + BFA_AEN_CAT_IPFC, /* 7 */ | ||
54 | BFA_LOG_AEN_ID_AUDIT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_AUDIT, /* 8 */ | ||
55 | BFA_LOG_AEN_ID_IOC = BFA_LOG_AEN_MIN + BFA_AEN_CAT_IOC, /* 9 */ | ||
56 | BFA_LOG_AEN_ID_ETHPORT = BFA_LOG_AEN_MIN + BFA_AEN_CAT_ETHPORT,/* 10 */ | ||
57 | |||
58 | BFA_LOG_AEN_MAX = BFA_LOG_AEN_ID_ETHPORT, | ||
59 | /* AEN defs end */ | ||
60 | |||
61 | BFA_LOG_MODULE_ID_MIN = BFA_LOG_AEN_MAX, | ||
62 | |||
63 | BFA_LOG_FW_ID = BFA_LOG_MODULE_ID_MIN + 1, | ||
64 | BFA_LOG_HAL_ID = BFA_LOG_MODULE_ID_MIN + 2, | ||
65 | BFA_LOG_FCS_ID = BFA_LOG_MODULE_ID_MIN + 3, | ||
66 | BFA_LOG_WDRV_ID = BFA_LOG_MODULE_ID_MIN + 4, | ||
67 | BFA_LOG_LINUX_ID = BFA_LOG_MODULE_ID_MIN + 5, | ||
68 | BFA_LOG_SOLARIS_ID = BFA_LOG_MODULE_ID_MIN + 6, | ||
69 | |||
70 | BFA_LOG_MODULE_ID_MAX = BFA_LOG_SOLARIS_ID, | ||
71 | |||
72 | /* Not part of any arrays */ | ||
73 | BFA_LOG_MODULE_ID_ALL = BFA_LOG_MODULE_ID_MAX + 1, | ||
74 | BFA_LOG_AEN_ALL = BFA_LOG_MODULE_ID_MAX + 2, | ||
75 | BFA_LOG_DRV_ALL = BFA_LOG_MODULE_ID_MAX + 3, | ||
76 | }; | ||
77 | |||
78 | /* | ||
79 | * BFA log catalog name | ||
80 | */ | ||
81 | #define BFA_LOG_CAT_NAME "BFA" | ||
82 | |||
83 | /* | ||
84 | * bfa log severity values | ||
85 | */ | ||
86 | enum bfa_log_severity { | ||
87 | BFA_LOG_INVALID = 0, | ||
88 | BFA_LOG_CRITICAL = 1, | ||
89 | BFA_LOG_ERROR = 2, | ||
90 | BFA_LOG_WARNING = 3, | ||
91 | BFA_LOG_INFO = 4, | ||
92 | BFA_LOG_NONE = 5, | ||
93 | BFA_LOG_LEVEL_MAX = BFA_LOG_NONE | ||
94 | }; | ||
95 | |||
96 | #define BFA_LOG_MODID_OFFSET 16 | ||
97 | |||
98 | |||
99 | struct bfa_log_msgdef_s { | ||
100 | u32 msg_id; /* message id */ | ||
101 | int attributes; /* attributes */ | ||
102 | int severity; /* severity level */ | ||
103 | char *msg_value; | ||
104 | /* msg string */ | ||
105 | char *message; | ||
106 | /* msg format string */ | ||
107 | int arg_type; /* argument type */ | ||
108 | int arg_num; /* number of argument */ | ||
109 | }; | ||
110 | |||
111 | /* | ||
112 | * supported argument type | ||
113 | */ | ||
114 | enum bfa_log_arg_type { | ||
115 | BFA_LOG_S = 0, /* string */ | ||
116 | BFA_LOG_D, /* decimal */ | ||
117 | BFA_LOG_I, /* integer */ | ||
118 | BFA_LOG_O, /* oct number */ | ||
119 | BFA_LOG_U, /* unsigned integer */ | ||
120 | BFA_LOG_X, /* hex number */ | ||
121 | BFA_LOG_F, /* floating */ | ||
122 | BFA_LOG_C, /* character */ | ||
123 | BFA_LOG_L, /* double */ | ||
124 | BFA_LOG_P /* pointer */ | ||
125 | }; | ||
126 | |||
127 | #define BFA_LOG_ARG_TYPE 2 | ||
128 | #define BFA_LOG_ARG0 (0 * BFA_LOG_ARG_TYPE) | ||
129 | #define BFA_LOG_ARG1 (1 * BFA_LOG_ARG_TYPE) | ||
130 | #define BFA_LOG_ARG2 (2 * BFA_LOG_ARG_TYPE) | ||
131 | #define BFA_LOG_ARG3 (3 * BFA_LOG_ARG_TYPE) | ||
132 | |||
133 | #define BFA_LOG_GET_MOD_ID(msgid) ((msgid >> BFA_LOG_MODID_OFFSET) & 0xff) | ||
134 | #define BFA_LOG_GET_MSG_IDX(msgid) (msgid & 0xffff) | ||
135 | #define BFA_LOG_GET_MSG_ID(msgdef) ((msgdef)->msg_id) | ||
136 | #define BFA_LOG_GET_MSG_FMT_STRING(msgdef) ((msgdef)->message) | ||
137 | #define BFA_LOG_GET_SEVERITY(msgdef) ((msgdef)->severity) | ||
138 | |||
139 | /* | ||
140 | * Event attributes | ||
141 | */ | ||
142 | #define BFA_LOG_ATTR_NONE 0 | ||
143 | #define BFA_LOG_ATTR_AUDIT 1 | ||
144 | #define BFA_LOG_ATTR_LOG 2 | ||
145 | #define BFA_LOG_ATTR_FFDC 4 | ||
146 | |||
147 | #define BFA_LOG_CREATE_ID(msw, lsw) \ | ||
148 | (((u32)msw << BFA_LOG_MODID_OFFSET) | lsw) | ||
149 | |||
150 | struct bfa_log_mod_s; | ||
151 | |||
152 | /** | ||
153 | * callback function | ||
154 | */ | ||
155 | typedef void (*bfa_log_cb_t)(struct bfa_log_mod_s *log_mod, u32 msg_id, | ||
156 | const char *format, ...); | ||
157 | |||
158 | |||
159 | struct bfa_log_mod_s { | ||
160 | char instance_info[16]; /* instance info */ | ||
161 | int log_level[BFA_LOG_MODULE_ID_MAX + 1]; | ||
162 | /* log level for modules */ | ||
163 | bfa_log_cb_t cbfn; /* callback function */ | ||
164 | }; | ||
165 | |||
166 | extern int bfa_log_init(struct bfa_log_mod_s *log_mod, | ||
167 | char *instance_name, bfa_log_cb_t cbfn); | ||
168 | extern int bfa_log(struct bfa_log_mod_s *log_mod, u32 msg_id, ...); | ||
169 | extern bfa_status_t bfa_log_set_level(struct bfa_log_mod_s *log_mod, | ||
170 | int mod_id, enum bfa_log_severity log_level); | ||
171 | extern bfa_status_t bfa_log_set_level_all(struct bfa_log_mod_s *log_mod, | ||
172 | enum bfa_log_severity log_level); | ||
173 | extern bfa_status_t bfa_log_set_level_aen(struct bfa_log_mod_s *log_mod, | ||
174 | enum bfa_log_severity log_level); | ||
175 | extern enum bfa_log_severity bfa_log_get_level(struct bfa_log_mod_s *log_mod, | ||
176 | int mod_id); | ||
177 | extern enum bfa_log_severity bfa_log_get_msg_level( | ||
178 | struct bfa_log_mod_s *log_mod, u32 msg_id); | ||
179 | /* | ||
180 | * array of messages generated from xml files | ||
181 | */ | ||
182 | extern struct bfa_log_msgdef_s bfa_log_msg_array[]; | ||
183 | |||
184 | #endif | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_perf.h b/drivers/scsi/bfa/include/cs/bfa_perf.h new file mode 100644 index 000000000000..45aa5f978ff5 --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_perf.h | |||
@@ -0,0 +1,34 @@ | |||
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 | #ifndef __BFAD_PERF_H__ | ||
18 | #define __BFAD_PERF_H__ | ||
19 | |||
20 | #ifdef BFAD_PERF_BUILD | ||
21 | |||
22 | #undef bfa_trc | ||
23 | #undef bfa_trc32 | ||
24 | #undef bfa_assert | ||
25 | #undef BFA_TRC_FILE | ||
26 | |||
27 | #define bfa_trc(_trcp, _data) | ||
28 | #define bfa_trc32(_trcp, _data) | ||
29 | #define bfa_assert(__cond) | ||
30 | #define BFA_TRC_FILE(__mod, __submod) | ||
31 | |||
32 | #endif | ||
33 | |||
34 | #endif /* __BFAD_PERF_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_plog.h b/drivers/scsi/bfa/include/cs/bfa_plog.h new file mode 100644 index 000000000000..670f86e5fc6e --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_plog.h | |||
@@ -0,0 +1,162 @@ | |||
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 | #ifndef __BFA_PORTLOG_H__ | ||
18 | #define __BFA_PORTLOG_H__ | ||
19 | |||
20 | #include "protocol/fc.h" | ||
21 | #include <defs/bfa_defs_types.h> | ||
22 | |||
23 | #define BFA_PL_NLOG_ENTS 256 | ||
24 | #define BFA_PL_LOG_REC_INCR(_x) ((_x)++, (_x) %= BFA_PL_NLOG_ENTS) | ||
25 | |||
26 | #define BFA_PL_STRING_LOG_SZ 32 /* number of chars in string log */ | ||
27 | #define BFA_PL_INT_LOG_SZ 8 /* number of integers in the integer log */ | ||
28 | |||
29 | enum bfa_plog_log_type { | ||
30 | BFA_PL_LOG_TYPE_INVALID = 0, | ||
31 | BFA_PL_LOG_TYPE_INT = 1, | ||
32 | BFA_PL_LOG_TYPE_STRING = 2, | ||
33 | }; | ||
34 | |||
35 | /* | ||
36 | * the (fixed size) record format for each entry in the portlog | ||
37 | */ | ||
38 | struct bfa_plog_rec_s { | ||
39 | u32 tv; /* Filled by the portlog driver when the * | ||
40 | * entry is added to the circular log. */ | ||
41 | u8 port; /* Source port that logged this entry. CM | ||
42 | * entities will use 0xFF */ | ||
43 | u8 mid; /* Integer value to be used by all entities * | ||
44 | * while logging. The module id to string * | ||
45 | * conversion will be done by BFAL. See | ||
46 | * enum bfa_plog_mid */ | ||
47 | u8 eid; /* indicates Rx, Tx, IOCTL, etc. See | ||
48 | * enum bfa_plog_eid */ | ||
49 | u8 log_type; /* indicates string log or integer log. | ||
50 | * see bfa_plog_log_type_t */ | ||
51 | u8 log_num_ints; | ||
52 | /* | ||
53 | * interpreted only if log_type is INT_LOG. indicates number of | ||
54 | * integers in the int_log[] (0-PL_INT_LOG_SZ). | ||
55 | */ | ||
56 | u8 rsvd; | ||
57 | u16 misc; /* can be used to indicate fc frame length, | ||
58 | *etc.. */ | ||
59 | union { | ||
60 | char string_log[BFA_PL_STRING_LOG_SZ]; | ||
61 | u32 int_log[BFA_PL_INT_LOG_SZ]; | ||
62 | } log_entry; | ||
63 | |||
64 | }; | ||
65 | |||
66 | /* | ||
67 | * the following #defines will be used by the logging entities to indicate | ||
68 | * their module id. BFAL will convert the integer value to string format | ||
69 | * | ||
70 | * process to be used while changing the following #defines: | ||
71 | * - Always add new entries at the end | ||
72 | * - define corresponding string in BFAL | ||
73 | * - Do not remove any entry or rearrange the order. | ||
74 | */ | ||
75 | enum bfa_plog_mid { | ||
76 | BFA_PL_MID_INVALID = 0, | ||
77 | BFA_PL_MID_DEBUG = 1, | ||
78 | BFA_PL_MID_DRVR = 2, | ||
79 | BFA_PL_MID_HAL = 3, | ||
80 | BFA_PL_MID_HAL_FCXP = 4, | ||
81 | BFA_PL_MID_HAL_UF = 5, | ||
82 | BFA_PL_MID_FCS = 6, | ||
83 | BFA_PL_MID_MAX = 7 | ||
84 | }; | ||
85 | |||
86 | #define BFA_PL_MID_STRLEN 8 | ||
87 | struct bfa_plog_mid_strings_s { | ||
88 | char m_str[BFA_PL_MID_STRLEN]; | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * the following #defines will be used by the logging entities to indicate | ||
93 | * their event type. BFAL will convert the integer value to string format | ||
94 | * | ||
95 | * process to be used while changing the following #defines: | ||
96 | * - Always add new entries at the end | ||
97 | * - define corresponding string in BFAL | ||
98 | * - Do not remove any entry or rearrange the order. | ||
99 | */ | ||
100 | enum bfa_plog_eid { | ||
101 | BFA_PL_EID_INVALID = 0, | ||
102 | BFA_PL_EID_IOC_DISABLE = 1, | ||
103 | BFA_PL_EID_IOC_ENABLE = 2, | ||
104 | BFA_PL_EID_PORT_DISABLE = 3, | ||
105 | BFA_PL_EID_PORT_ENABLE = 4, | ||
106 | BFA_PL_EID_PORT_ST_CHANGE = 5, | ||
107 | BFA_PL_EID_TX = 6, | ||
108 | BFA_PL_EID_TX_ACK1 = 7, | ||
109 | BFA_PL_EID_TX_RJT = 8, | ||
110 | BFA_PL_EID_TX_BSY = 9, | ||
111 | BFA_PL_EID_RX = 10, | ||
112 | BFA_PL_EID_RX_ACK1 = 11, | ||
113 | BFA_PL_EID_RX_RJT = 12, | ||
114 | BFA_PL_EID_RX_BSY = 13, | ||
115 | BFA_PL_EID_CT_IN = 14, | ||
116 | BFA_PL_EID_CT_OUT = 15, | ||
117 | BFA_PL_EID_DRIVER_START = 16, | ||
118 | BFA_PL_EID_RSCN = 17, | ||
119 | BFA_PL_EID_DEBUG = 18, | ||
120 | BFA_PL_EID_MISC = 19, | ||
121 | BFA_PL_EID_MAX = 20 | ||
122 | }; | ||
123 | |||
124 | #define BFA_PL_ENAME_STRLEN 8 | ||
125 | struct bfa_plog_eid_strings_s { | ||
126 | char e_str[BFA_PL_ENAME_STRLEN]; | ||
127 | }; | ||
128 | |||
129 | #define BFA_PL_SIG_LEN 8 | ||
130 | #define BFA_PL_SIG_STR "12pl123" | ||
131 | |||
132 | /* | ||
133 | * per port circular log buffer | ||
134 | */ | ||
135 | struct bfa_plog_s { | ||
136 | char plog_sig[BFA_PL_SIG_LEN]; /* Start signature */ | ||
137 | u8 plog_enabled; | ||
138 | u8 rsvd[7]; | ||
139 | u32 ticks; | ||
140 | u16 head; | ||
141 | u16 tail; | ||
142 | struct bfa_plog_rec_s plog_recs[BFA_PL_NLOG_ENTS]; | ||
143 | }; | ||
144 | |||
145 | void bfa_plog_init(struct bfa_plog_s *plog); | ||
146 | void bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
147 | enum bfa_plog_eid event, u16 misc, char *log_str); | ||
148 | void bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
149 | enum bfa_plog_eid event, u16 misc, | ||
150 | u32 *intarr, u32 num_ints); | ||
151 | void bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
152 | enum bfa_plog_eid event, u16 misc, | ||
153 | struct fchs_s *fchdr); | ||
154 | void bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
155 | enum bfa_plog_eid event, u16 misc, | ||
156 | struct fchs_s *fchdr, u32 pld_w0); | ||
157 | void bfa_plog_clear(struct bfa_plog_s *plog); | ||
158 | void bfa_plog_enable(struct bfa_plog_s *plog); | ||
159 | void bfa_plog_disable(struct bfa_plog_s *plog); | ||
160 | bfa_boolean_t bfa_plog_get_setting(struct bfa_plog_s *plog); | ||
161 | |||
162 | #endif /* __BFA_PORTLOG_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_q.h b/drivers/scsi/bfa/include/cs/bfa_q.h new file mode 100644 index 000000000000..ea895facedbc --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_q.h | |||
@@ -0,0 +1,81 @@ | |||
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 | * bfa_q.h Circular queue definitions. | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_Q_H__ | ||
23 | #define __BFA_Q_H__ | ||
24 | |||
25 | #define bfa_q_first(_q) ((void *)(((struct list_head *) (_q))->next)) | ||
26 | #define bfa_q_next(_qe) (((struct list_head *) (_qe))->next) | ||
27 | #define bfa_q_prev(_qe) (((struct list_head *) (_qe))->prev) | ||
28 | |||
29 | /* | ||
30 | * bfa_q_qe_init - to initialize a queue element | ||
31 | */ | ||
32 | #define bfa_q_qe_init(_qe) { \ | ||
33 | bfa_q_next(_qe) = (struct list_head *) NULL; \ | ||
34 | bfa_q_prev(_qe) = (struct list_head *) NULL; \ | ||
35 | } | ||
36 | |||
37 | /* | ||
38 | * bfa_q_deq - dequeue an element from head of the queue | ||
39 | */ | ||
40 | #define bfa_q_deq(_q, _qe) { \ | ||
41 | if (!list_empty(_q)) { \ | ||
42 | (*((struct list_head **) (_qe))) = bfa_q_next(_q); \ | ||
43 | bfa_q_prev(bfa_q_next(*((struct list_head **) _qe))) = \ | ||
44 | (struct list_head *) (_q); \ | ||
45 | bfa_q_next(_q) = bfa_q_next(*((struct list_head **) _qe)); \ | ||
46 | BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \ | ||
47 | } else { \ | ||
48 | *((struct list_head **) (_qe)) = (struct list_head *) NULL; \ | ||
49 | } \ | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * bfa_q_deq_tail - dequeue an element from tail of the queue | ||
54 | */ | ||
55 | #define bfa_q_deq_tail(_q, _qe) { \ | ||
56 | if (!list_empty(_q)) { \ | ||
57 | *((struct list_head **) (_qe)) = bfa_q_prev(_q); \ | ||
58 | bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \ | ||
59 | (struct list_head *) (_q); \ | ||
60 | bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe); \ | ||
61 | BFA_Q_DBG_INIT(*((struct list_head **) _qe)); \ | ||
62 | } else { \ | ||
63 | *((struct list_head **) (_qe)) = (struct list_head *) NULL; \ | ||
64 | } \ | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * #ifdef BFA_DEBUG (Using bfa_assert to check for debug_build is not | ||
69 | * consistent across modules) | ||
70 | */ | ||
71 | #ifndef BFA_PERF_BUILD | ||
72 | #define BFA_Q_DBG_INIT(_qe) bfa_q_qe_init(_qe) | ||
73 | #else | ||
74 | #define BFA_Q_DBG_INIT(_qe) | ||
75 | #endif | ||
76 | |||
77 | #define bfa_q_is_on_q(_q, _qe) \ | ||
78 | bfa_q_is_on_q_func(_q, (struct list_head *)(_qe)) | ||
79 | extern int bfa_q_is_on_q_func(struct list_head *q, struct list_head *qe); | ||
80 | |||
81 | #endif | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_sm.h b/drivers/scsi/bfa/include/cs/bfa_sm.h new file mode 100644 index 000000000000..9877066680a6 --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_sm.h | |||
@@ -0,0 +1,69 @@ | |||
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 | * bfasm.h State machine defines | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_SM_H__ | ||
23 | #define __BFA_SM_H__ | ||
24 | |||
25 | typedef void (*bfa_sm_t)(void *sm, int event); | ||
26 | |||
27 | #define bfa_sm_set_state(_sm, _state) (_sm)->sm = (bfa_sm_t)(_state) | ||
28 | #define bfa_sm_send_event(_sm, _event) (_sm)->sm((_sm), (_event)) | ||
29 | #define bfa_sm_get_state(_sm) ((_sm)->sm) | ||
30 | #define bfa_sm_cmp_state(_sm, _state) ((_sm)->sm == (bfa_sm_t)(_state)) | ||
31 | |||
32 | /** | ||
33 | * For converting from state machine function to state encoding. | ||
34 | */ | ||
35 | struct bfa_sm_table_s { | ||
36 | bfa_sm_t sm; /* state machine function */ | ||
37 | int state; /* state machine encoding */ | ||
38 | char *name; /* state name for display */ | ||
39 | }; | ||
40 | #define BFA_SM(_sm) ((bfa_sm_t)(_sm)) | ||
41 | |||
42 | int bfa_sm_to_state(struct bfa_sm_table_s *smt, bfa_sm_t sm); | ||
43 | |||
44 | /** | ||
45 | * State machine with entry actions. | ||
46 | */ | ||
47 | typedef void (*bfa_fsm_t)(void *fsm, int event); | ||
48 | |||
49 | /** | ||
50 | * oc - object class eg. bfa_ioc | ||
51 | * st - state, eg. reset | ||
52 | * otype - object type, eg. struct bfa_ioc_s | ||
53 | * etype - object type, eg. enum ioc_event | ||
54 | */ | ||
55 | #define bfa_fsm_state_decl(oc, st, otype, etype) \ | ||
56 | static void oc ## _sm_ ## st(otype * fsm, etype event); \ | ||
57 | static void oc ## _sm_ ## st ## _entry(otype * fsm) | ||
58 | |||
59 | #define bfa_fsm_set_state(_fsm, _state) do { \ | ||
60 | (_fsm)->fsm = (bfa_fsm_t)(_state); \ | ||
61 | _state ## _entry(_fsm); \ | ||
62 | } while (0) | ||
63 | |||
64 | #define bfa_fsm_send_event(_fsm, _event) \ | ||
65 | (_fsm)->fsm((_fsm), (_event)) | ||
66 | #define bfa_fsm_cmp_state(_fsm, _state) \ | ||
67 | ((_fsm)->fsm == (bfa_fsm_t)(_state)) | ||
68 | |||
69 | #endif | ||
diff --git a/drivers/scsi/bfa/include/cs/bfa_trc.h b/drivers/scsi/bfa/include/cs/bfa_trc.h new file mode 100644 index 000000000000..3e743928c74c --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_trc.h | |||
@@ -0,0 +1,176 @@ | |||
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 | #ifndef __BFA_TRC_H__ | ||
18 | #define __BFA_TRC_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | |||
22 | #ifndef BFA_TRC_MAX | ||
23 | #define BFA_TRC_MAX (4 * 1024) | ||
24 | #endif | ||
25 | |||
26 | #ifndef BFA_TRC_TS | ||
27 | #define BFA_TRC_TS(_trcm) ((_trcm)->ticks ++) | ||
28 | #endif | ||
29 | |||
30 | struct bfa_trc_s { | ||
31 | #ifdef __BIGENDIAN | ||
32 | u16 fileno; | ||
33 | u16 line; | ||
34 | #else | ||
35 | u16 line; | ||
36 | u16 fileno; | ||
37 | #endif | ||
38 | u32 timestamp; | ||
39 | union { | ||
40 | struct { | ||
41 | u32 rsvd; | ||
42 | u32 u32; | ||
43 | } u32; | ||
44 | u64 u64; | ||
45 | } data; | ||
46 | }; | ||
47 | |||
48 | |||
49 | struct bfa_trc_mod_s { | ||
50 | u32 head; | ||
51 | u32 tail; | ||
52 | u32 ntrc; | ||
53 | u32 stopped; | ||
54 | u32 ticks; | ||
55 | u32 rsvd[3]; | ||
56 | struct bfa_trc_s trc[BFA_TRC_MAX]; | ||
57 | }; | ||
58 | |||
59 | |||
60 | enum { | ||
61 | BFA_TRC_FW = 1, /* firmware modules */ | ||
62 | BFA_TRC_HAL = 2, /* BFA modules */ | ||
63 | BFA_TRC_FCS = 3, /* BFA FCS modules */ | ||
64 | BFA_TRC_LDRV = 4, /* Linux driver modules */ | ||
65 | BFA_TRC_SDRV = 5, /* Solaris driver modules */ | ||
66 | BFA_TRC_VDRV = 6, /* vmware driver modules */ | ||
67 | BFA_TRC_WDRV = 7, /* windows driver modules */ | ||
68 | BFA_TRC_AEN = 8, /* AEN module */ | ||
69 | BFA_TRC_BIOS = 9, /* bios driver modules */ | ||
70 | BFA_TRC_EFI = 10, /* EFI driver modules */ | ||
71 | BNA_TRC_WDRV = 11, /* BNA windows driver modules */ | ||
72 | BNA_TRC_VDRV = 12, /* BNA vmware driver modules */ | ||
73 | BNA_TRC_SDRV = 13, /* BNA Solaris driver modules */ | ||
74 | BNA_TRC_LDRV = 14, /* BNA Linux driver modules */ | ||
75 | BNA_TRC_HAL = 15, /* BNA modules */ | ||
76 | BFA_TRC_CNA = 16, /* Common modules */ | ||
77 | BNA_TRC_IMDRV = 17 /* BNA windows intermediate driver modules */ | ||
78 | }; | ||
79 | #define BFA_TRC_MOD_SH 10 | ||
80 | #define BFA_TRC_MOD(__mod) ((BFA_TRC_ ## __mod) << BFA_TRC_MOD_SH) | ||
81 | |||
82 | /** | ||
83 | * Define a new tracing file (module). Module should match one defined above. | ||
84 | */ | ||
85 | #define BFA_TRC_FILE(__mod, __submod) \ | ||
86 | static int __trc_fileno = ((BFA_TRC_ ## __mod ## _ ## __submod) | \ | ||
87 | BFA_TRC_MOD(__mod)) | ||
88 | |||
89 | |||
90 | #define bfa_trc32(_trcp, _data) \ | ||
91 | __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data) | ||
92 | |||
93 | |||
94 | #ifndef BFA_BOOT_BUILD | ||
95 | #define bfa_trc(_trcp, _data) \ | ||
96 | __bfa_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u64)_data) | ||
97 | #else | ||
98 | void bfa_boot_trc(struct bfa_trc_mod_s *trcmod, u16 fileno, | ||
99 | u16 line, u32 data); | ||
100 | #define bfa_trc(_trcp, _data) \ | ||
101 | bfa_boot_trc((_trcp)->trcmod, __trc_fileno, __LINE__, (u32)_data) | ||
102 | #endif | ||
103 | |||
104 | |||
105 | static inline void | ||
106 | bfa_trc_init(struct bfa_trc_mod_s *trcm) | ||
107 | { | ||
108 | trcm->head = trcm->tail = trcm->stopped = 0; | ||
109 | trcm->ntrc = BFA_TRC_MAX; | ||
110 | } | ||
111 | |||
112 | |||
113 | static inline void | ||
114 | bfa_trc_stop(struct bfa_trc_mod_s *trcm) | ||
115 | { | ||
116 | trcm->stopped = 1; | ||
117 | } | ||
118 | |||
119 | #ifdef FWTRC | ||
120 | extern void dc_flush(void *data); | ||
121 | #else | ||
122 | #define dc_flush(data) | ||
123 | #endif | ||
124 | |||
125 | |||
126 | static inline void | ||
127 | __bfa_trc(struct bfa_trc_mod_s *trcm, int fileno, int line, u64 data) | ||
128 | { | ||
129 | int tail = trcm->tail; | ||
130 | struct bfa_trc_s *trc = &trcm->trc[tail]; | ||
131 | |||
132 | if (trcm->stopped) | ||
133 | return; | ||
134 | |||
135 | trc->fileno = (u16) fileno; | ||
136 | trc->line = (u16) line; | ||
137 | trc->data.u64 = data; | ||
138 | trc->timestamp = BFA_TRC_TS(trcm); | ||
139 | dc_flush(trc); | ||
140 | |||
141 | trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1); | ||
142 | if (trcm->tail == trcm->head) | ||
143 | trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1); | ||
144 | dc_flush(trcm); | ||
145 | } | ||
146 | |||
147 | |||
148 | static inline void | ||
149 | __bfa_trc32(struct bfa_trc_mod_s *trcm, int fileno, int line, u32 data) | ||
150 | { | ||
151 | int tail = trcm->tail; | ||
152 | struct bfa_trc_s *trc = &trcm->trc[tail]; | ||
153 | |||
154 | if (trcm->stopped) | ||
155 | return; | ||
156 | |||
157 | trc->fileno = (u16) fileno; | ||
158 | trc->line = (u16) line; | ||
159 | trc->data.u32.u32 = data; | ||
160 | trc->timestamp = BFA_TRC_TS(trcm); | ||
161 | dc_flush(trc); | ||
162 | |||
163 | trcm->tail = (trcm->tail + 1) & (BFA_TRC_MAX - 1); | ||
164 | if (trcm->tail == trcm->head) | ||
165 | trcm->head = (trcm->head + 1) & (BFA_TRC_MAX - 1); | ||
166 | dc_flush(trcm); | ||
167 | } | ||
168 | |||
169 | #ifndef BFA_PERF_BUILD | ||
170 | #define bfa_trc_fp(_trcp, _data) bfa_trc(_trcp, _data) | ||
171 | #else | ||
172 | #define bfa_trc_fp(_trcp, _data) | ||
173 | #endif | ||
174 | |||
175 | #endif /* __BFA_TRC_H__ */ | ||
176 | |||
diff --git a/drivers/scsi/bfa/include/cs/bfa_wc.h b/drivers/scsi/bfa/include/cs/bfa_wc.h new file mode 100644 index 000000000000..0460bd4fc7c4 --- /dev/null +++ b/drivers/scsi/bfa/include/cs/bfa_wc.h | |||
@@ -0,0 +1,68 @@ | |||
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 | * bfa_wc.h Generic wait counter. | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_WC_H__ | ||
23 | #define __BFA_WC_H__ | ||
24 | |||
25 | typedef void (*bfa_wc_resume_t) (void *cbarg); | ||
26 | |||
27 | struct bfa_wc_s { | ||
28 | bfa_wc_resume_t wc_resume; | ||
29 | void *wc_cbarg; | ||
30 | int wc_count; | ||
31 | }; | ||
32 | |||
33 | static inline void | ||
34 | bfa_wc_up(struct bfa_wc_s *wc) | ||
35 | { | ||
36 | wc->wc_count++; | ||
37 | } | ||
38 | |||
39 | static inline void | ||
40 | bfa_wc_down(struct bfa_wc_s *wc) | ||
41 | { | ||
42 | wc->wc_count--; | ||
43 | if (wc->wc_count == 0) | ||
44 | wc->wc_resume(wc->wc_cbarg); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * Initialize a waiting counter. | ||
49 | */ | ||
50 | static inline void | ||
51 | bfa_wc_init(struct bfa_wc_s *wc, bfa_wc_resume_t wc_resume, void *wc_cbarg) | ||
52 | { | ||
53 | wc->wc_resume = wc_resume; | ||
54 | wc->wc_cbarg = wc_cbarg; | ||
55 | wc->wc_count = 0; | ||
56 | bfa_wc_up(wc); | ||
57 | } | ||
58 | |||
59 | /** | ||
60 | * Wait for counter to reach zero | ||
61 | */ | ||
62 | static inline void | ||
63 | bfa_wc_wait(struct bfa_wc_s *wc) | ||
64 | { | ||
65 | bfa_wc_down(wc); | ||
66 | } | ||
67 | |||
68 | #endif | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h new file mode 100644 index 000000000000..8c208fc8e329 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_adapter.h | |||
@@ -0,0 +1,82 @@ | |||
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 | #ifndef __BFA_DEFS_ADAPTER_H__ | ||
18 | #define __BFA_DEFS_ADAPTER_H__ | ||
19 | |||
20 | #include <protocol/types.h> | ||
21 | #include <defs/bfa_defs_version.h> | ||
22 | #include <defs/bfa_defs_mfg.h> | ||
23 | |||
24 | /** | ||
25 | * BFA adapter level attributes. | ||
26 | */ | ||
27 | enum { | ||
28 | BFA_ADAPTER_SERIAL_NUM_LEN = STRSZ(BFA_MFG_SERIALNUM_SIZE), | ||
29 | /* | ||
30 | *!< adapter serial num length | ||
31 | */ | ||
32 | BFA_ADAPTER_MODEL_NAME_LEN = 16, /* model name length */ | ||
33 | BFA_ADAPTER_MODEL_DESCR_LEN = 128, /* model description length */ | ||
34 | BFA_ADAPTER_MFG_NAME_LEN = 8, /* manufacturer name length */ | ||
35 | BFA_ADAPTER_SYM_NAME_LEN = 64, /* adapter symbolic name length */ | ||
36 | BFA_ADAPTER_OS_TYPE_LEN = 64, /* adapter os type length */ | ||
37 | }; | ||
38 | |||
39 | struct bfa_adapter_attr_s { | ||
40 | char manufacturer[BFA_ADAPTER_MFG_NAME_LEN]; | ||
41 | char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; | ||
42 | u32 rsvd1; | ||
43 | char model[BFA_ADAPTER_MODEL_NAME_LEN]; | ||
44 | char model_descr[BFA_ADAPTER_MODEL_DESCR_LEN]; | ||
45 | wwn_t pwwn; | ||
46 | char node_symname[FC_SYMNAME_MAX]; | ||
47 | char hw_ver[BFA_VERSION_LEN]; | ||
48 | char fw_ver[BFA_VERSION_LEN]; | ||
49 | char optrom_ver[BFA_VERSION_LEN]; | ||
50 | char os_type[BFA_ADAPTER_OS_TYPE_LEN]; | ||
51 | struct bfa_mfg_vpd_s vpd; | ||
52 | struct mac_s mac; | ||
53 | |||
54 | u8 nports; | ||
55 | u8 max_speed; | ||
56 | u8 prototype; | ||
57 | char asic_rev; | ||
58 | |||
59 | u8 pcie_gen; | ||
60 | u8 pcie_lanes_orig; | ||
61 | u8 pcie_lanes; | ||
62 | u8 cna_capable; | ||
63 | }; | ||
64 | |||
65 | /** | ||
66 | * BFA adapter level events | ||
67 | * Arguments below are in BFAL context from Mgmt | ||
68 | * BFA_PORT_AEN_ADD: [in]: None [out]: serial_num, pwwn, nports | ||
69 | * BFA_PORT_AEN_REMOVE: [in]: pwwn [out]: serial_num, pwwn, nports | ||
70 | */ | ||
71 | enum bfa_adapter_aen_event { | ||
72 | BFA_ADAPTER_AEN_ADD = 1, /* New Adapter found event */ | ||
73 | BFA_ADAPTER_AEN_REMOVE = 2, /* Adapter removed event */ | ||
74 | }; | ||
75 | |||
76 | struct bfa_adapter_aen_data_s { | ||
77 | char serial_num[BFA_ADAPTER_SERIAL_NUM_LEN]; | ||
78 | u32 nports; /* Number of NPorts */ | ||
79 | wwn_t pwwn; /* WWN of one of its physical port */ | ||
80 | }; | ||
81 | |||
82 | #endif /* __BFA_DEFS_ADAPTER_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_aen.h b/drivers/scsi/bfa/include/defs/bfa_defs_aen.h new file mode 100644 index 000000000000..4c81a613db3d --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_aen.h | |||
@@ -0,0 +1,73 @@ | |||
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 | #ifndef __BFA_DEFS_AEN_H__ | ||
19 | #define __BFA_DEFS_AEN_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_types.h> | ||
22 | #include <defs/bfa_defs_ioc.h> | ||
23 | #include <defs/bfa_defs_adapter.h> | ||
24 | #include <defs/bfa_defs_port.h> | ||
25 | #include <defs/bfa_defs_lport.h> | ||
26 | #include <defs/bfa_defs_rport.h> | ||
27 | #include <defs/bfa_defs_itnim.h> | ||
28 | #include <defs/bfa_defs_tin.h> | ||
29 | #include <defs/bfa_defs_ipfc.h> | ||
30 | #include <defs/bfa_defs_audit.h> | ||
31 | #include <defs/bfa_defs_ethport.h> | ||
32 | |||
33 | enum bfa_aen_category { | ||
34 | BFA_AEN_CAT_ADAPTER = 1, | ||
35 | BFA_AEN_CAT_PORT = 2, | ||
36 | BFA_AEN_CAT_LPORT = 3, | ||
37 | BFA_AEN_CAT_RPORT = 4, | ||
38 | BFA_AEN_CAT_ITNIM = 5, | ||
39 | BFA_AEN_CAT_TIN = 6, | ||
40 | BFA_AEN_CAT_IPFC = 7, | ||
41 | BFA_AEN_CAT_AUDIT = 8, | ||
42 | BFA_AEN_CAT_IOC = 9, | ||
43 | BFA_AEN_CAT_ETHPORT = 10, | ||
44 | BFA_AEN_MAX_CAT = 10 | ||
45 | }; | ||
46 | |||
47 | #pragma pack(1) | ||
48 | union bfa_aen_data_u { | ||
49 | struct bfa_adapter_aen_data_s adapter; | ||
50 | struct bfa_port_aen_data_s port; | ||
51 | struct bfa_lport_aen_data_s lport; | ||
52 | struct bfa_rport_aen_data_s rport; | ||
53 | struct bfa_itnim_aen_data_s itnim; | ||
54 | struct bfa_audit_aen_data_s audit; | ||
55 | struct bfa_ioc_aen_data_s ioc; | ||
56 | struct bfa_ethport_aen_data_s ethport; | ||
57 | }; | ||
58 | |||
59 | struct bfa_aen_entry_s { | ||
60 | enum bfa_aen_category aen_category; | ||
61 | int aen_type; | ||
62 | union bfa_aen_data_u aen_data; | ||
63 | struct bfa_timeval_s aen_tv; | ||
64 | s32 seq_num; | ||
65 | s32 bfad_num; | ||
66 | s32 rsvd[1]; | ||
67 | }; | ||
68 | |||
69 | #pragma pack() | ||
70 | |||
71 | #define bfa_aen_event_t int | ||
72 | |||
73 | #endif /* __BFA_DEFS_AEN_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_audit.h b/drivers/scsi/bfa/include/defs/bfa_defs_audit.h new file mode 100644 index 000000000000..8e3a962bf20c --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_audit.h | |||
@@ -0,0 +1,38 @@ | |||
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 | #ifndef __BFA_DEFS_AUDIT_H__ | ||
19 | #define __BFA_DEFS_AUDIT_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | |||
23 | /** | ||
24 | * BFA audit events | ||
25 | */ | ||
26 | enum bfa_audit_aen_event { | ||
27 | BFA_AUDIT_AEN_AUTH_ENABLE = 1, | ||
28 | BFA_AUDIT_AEN_AUTH_DISABLE = 2, | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * audit event data | ||
33 | */ | ||
34 | struct bfa_audit_aen_data_s { | ||
35 | wwn_t pwwn; | ||
36 | }; | ||
37 | |||
38 | #endif /* __BFA_DEFS_AUDIT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_auth.h b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h new file mode 100644 index 000000000000..dd19c83aba58 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_auth.h | |||
@@ -0,0 +1,112 @@ | |||
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 | #ifndef __BFA_DEFS_AUTH_H__ | ||
18 | #define __BFA_DEFS_AUTH_H__ | ||
19 | |||
20 | #include <defs/bfa_defs_types.h> | ||
21 | |||
22 | #define PUBLIC_KEY 15409 | ||
23 | #define PRIVATE_KEY 19009 | ||
24 | #define KEY_LEN 32399 | ||
25 | #define BFA_AUTH_SECRET_STRING_LEN 256 | ||
26 | #define BFA_AUTH_FAIL_TIMEOUT 0xFF | ||
27 | |||
28 | /** | ||
29 | * Authentication status | ||
30 | */ | ||
31 | enum bfa_auth_status { | ||
32 | BFA_AUTH_STATUS_NONE = 0, /* no authentication */ | ||
33 | BFA_AUTH_UNINIT = 1, /* state - uninit */ | ||
34 | BFA_AUTH_NEG_SEND = 2, /* state - negotiate send */ | ||
35 | BFA_AUTH_CHAL_WAIT = 3, /* state - challenge wait */ | ||
36 | BFA_AUTH_NEG_RETRY = 4, /* state - negotiate retry */ | ||
37 | BFA_AUTH_REPLY_SEND = 5, /* state - reply send */ | ||
38 | BFA_AUTH_STATUS_WAIT = 6, /* state - status wait */ | ||
39 | BFA_AUTH_SUCCESS = 7, /* state - success */ | ||
40 | BFA_AUTH_FAILED = 8, /* state - failed */ | ||
41 | BFA_AUTH_STATUS_UNKNOWN = 9, /* authentication status unknown */ | ||
42 | }; | ||
43 | |||
44 | struct auth_proto_stats_s { | ||
45 | u32 auth_rjts; | ||
46 | u32 auth_negs; | ||
47 | u32 auth_dones; | ||
48 | |||
49 | u32 dhchap_challenges; | ||
50 | u32 dhchap_replies; | ||
51 | u32 dhchap_successes; | ||
52 | }; | ||
53 | |||
54 | /** | ||
55 | * Authentication related statistics | ||
56 | */ | ||
57 | struct bfa_auth_stats_s { | ||
58 | u32 auth_failures; /* authentication failures */ | ||
59 | u32 auth_successes; /* authentication successes*/ | ||
60 | struct auth_proto_stats_s auth_rx_stats; /* Rx protocol stats */ | ||
61 | struct auth_proto_stats_s auth_tx_stats; /* Tx protocol stats */ | ||
62 | }; | ||
63 | |||
64 | /** | ||
65 | * Authentication hash function algorithms | ||
66 | */ | ||
67 | enum bfa_auth_algo { | ||
68 | BFA_AUTH_ALGO_MD5 = 1, /* Message-Digest algorithm 5 */ | ||
69 | BFA_AUTH_ALGO_SHA1 = 2, /* Secure Hash Algorithm 1 */ | ||
70 | BFA_AUTH_ALGO_MS = 3, /* MD5, then SHA-1 */ | ||
71 | BFA_AUTH_ALGO_SM = 4, /* SHA-1, then MD5 */ | ||
72 | }; | ||
73 | |||
74 | /** | ||
75 | * DH Groups | ||
76 | * | ||
77 | * Current value could be combination of one or more of the following values | ||
78 | */ | ||
79 | enum bfa_auth_group { | ||
80 | BFA_AUTH_GROUP_DHNULL = 0, /* DH NULL (value == 0) */ | ||
81 | BFA_AUTH_GROUP_DH768 = 1, /* DH group 768 (value == 1) */ | ||
82 | BFA_AUTH_GROUP_DH1024 = 2, /* DH group 1024 (value == 2) */ | ||
83 | BFA_AUTH_GROUP_DH1280 = 4, /* DH group 1280 (value == 3) */ | ||
84 | BFA_AUTH_GROUP_DH1536 = 8, /* DH group 1536 (value == 4) */ | ||
85 | |||
86 | BFA_AUTH_GROUP_ALL = 256 /* Use default DH group order | ||
87 | * 0, 1, 2, 3, 4 */ | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * Authentication secret sources | ||
92 | */ | ||
93 | enum bfa_auth_secretsource { | ||
94 | BFA_AUTH_SECSRC_LOCAL = 1, /* locally configured */ | ||
95 | BFA_AUTH_SECSRC_RADIUS = 2, /* use radius server */ | ||
96 | BFA_AUTH_SECSRC_TACACS = 3, /* TACACS server */ | ||
97 | }; | ||
98 | |||
99 | /** | ||
100 | * Authentication attributes | ||
101 | */ | ||
102 | struct bfa_auth_attr_s { | ||
103 | enum bfa_auth_status status; | ||
104 | enum bfa_auth_algo algo; | ||
105 | enum bfa_auth_group dh_grp; | ||
106 | u16 rjt_code; | ||
107 | u16 rjt_code_exp; | ||
108 | u8 secret_set; | ||
109 | u8 resv[7]; | ||
110 | }; | ||
111 | |||
112 | #endif /* __BFA_DEFS_AUTH_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_boot.h b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h new file mode 100644 index 000000000000..6f4aa5283545 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_boot.h | |||
@@ -0,0 +1,71 @@ | |||
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 | #ifndef __BFA_DEFS_BOOT_H__ | ||
19 | #define __BFA_DEFS_BOOT_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | #include <defs/bfa_defs_types.h> | ||
23 | #include <defs/bfa_defs_pport.h> | ||
24 | |||
25 | enum { | ||
26 | BFA_BOOT_BOOTLUN_MAX = 4, /* maximum boot lun per IOC */ | ||
27 | }; | ||
28 | |||
29 | #define BOOT_CFG_REV1 1 | ||
30 | |||
31 | /** | ||
32 | * Boot options setting. Boot options setting determines from where | ||
33 | * to get the boot lun information | ||
34 | */ | ||
35 | enum bfa_boot_bootopt { | ||
36 | BFA_BOOT_AUTO_DISCOVER = 0, /* Boot from blun provided by fabric */ | ||
37 | BFA_BOOT_STORED_BLUN = 1, /* Boot from bluns stored in flash */ | ||
38 | BFA_BOOT_FIRST_LUN = 2, /* Boot from first discovered blun */ | ||
39 | }; | ||
40 | |||
41 | /** | ||
42 | * Boot lun information. | ||
43 | */ | ||
44 | struct bfa_boot_bootlun_s { | ||
45 | wwn_t pwwn; /* port wwn of target */ | ||
46 | lun_t lun; /* 64-bit lun */ | ||
47 | }; | ||
48 | |||
49 | /** | ||
50 | * BOOT boot configuraton | ||
51 | */ | ||
52 | struct bfa_boot_cfg_s { | ||
53 | u8 version; | ||
54 | u8 rsvd1; | ||
55 | u16 chksum; | ||
56 | |||
57 | u8 enable; /* enable/disable SAN boot */ | ||
58 | u8 speed; /* boot speed settings */ | ||
59 | u8 topology; /* boot topology setting */ | ||
60 | u8 bootopt; /* bfa_boot_bootopt_t */ | ||
61 | |||
62 | u32 nbluns; /* number of boot luns */ | ||
63 | |||
64 | u32 rsvd2; | ||
65 | |||
66 | struct bfa_boot_bootlun_s blun[BFA_BOOT_BOOTLUN_MAX]; | ||
67 | struct bfa_boot_bootlun_s blun_disc[BFA_BOOT_BOOTLUN_MAX]; | ||
68 | }; | ||
69 | |||
70 | |||
71 | #endif /* __BFA_DEFS_BOOT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_cee.h b/drivers/scsi/bfa/include/defs/bfa_defs_cee.h new file mode 100644 index 000000000000..520a22f52dd1 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_cee.h | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. | ||
3 | * All rights reserved | ||
4 | * www.brocade.com | ||
5 | * | ||
6 | * bfa_defs_cee.h Interface declarations between host based | ||
7 | * BFAL and DCBX/LLDP module in Firmware | ||
8 | * | ||
9 | * Linux driver for Brocade Fibre Channel Host Bus Adapter. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License (GPL) Version 2 as | ||
13 | * published by the Free Software Foundation | ||
14 | * | ||
15 | * This program is distributed in the hope that it will be useful, but | ||
16 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
18 | * General Public License for more details. | ||
19 | */ | ||
20 | #ifndef __BFA_DEFS_CEE_H__ | ||
21 | #define __BFA_DEFS_CEE_H__ | ||
22 | |||
23 | #include <defs/bfa_defs_types.h> | ||
24 | #include <defs/bfa_defs_pport.h> | ||
25 | #include <protocol/types.h> | ||
26 | |||
27 | #pragma pack(1) | ||
28 | |||
29 | #define BFA_CEE_LLDP_MAX_STRING_LEN (128) | ||
30 | |||
31 | |||
32 | /* FIXME: this is coming from the protocol spec. Can the host & apps share the | ||
33 | protocol .h files ? | ||
34 | */ | ||
35 | #define BFA_CEE_LLDP_SYS_CAP_OTHER 0x0001 | ||
36 | #define BFA_CEE_LLDP_SYS_CAP_REPEATER 0x0002 | ||
37 | #define BFA_CEE_LLDP_SYS_CAP_MAC_BRIDGE 0x0004 | ||
38 | #define BFA_CEE_LLDP_SYS_CAP_WLAN_AP 0x0008 | ||
39 | #define BFA_CEE_LLDP_SYS_CAP_ROUTER 0x0010 | ||
40 | #define BFA_CEE_LLDP_SYS_CAP_TELEPHONE 0x0020 | ||
41 | #define BFA_CEE_LLDP_SYS_CAP_DOCSIS_CD 0x0040 | ||
42 | #define BFA_CEE_LLDP_SYS_CAP_STATION 0x0080 | ||
43 | #define BFA_CEE_LLDP_SYS_CAP_CVLAN 0x0100 | ||
44 | #define BFA_CEE_LLDP_SYS_CAP_SVLAN 0x0200 | ||
45 | #define BFA_CEE_LLDP_SYS_CAP_TPMR 0x0400 | ||
46 | |||
47 | |||
48 | /* LLDP string type */ | ||
49 | struct bfa_cee_lldp_str_s { | ||
50 | u8 sub_type; | ||
51 | u8 len; | ||
52 | u8 rsvd[2]; | ||
53 | u8 value[BFA_CEE_LLDP_MAX_STRING_LEN]; | ||
54 | }; | ||
55 | |||
56 | |||
57 | /* LLDP paramters */ | ||
58 | struct bfa_cee_lldp_cfg_s { | ||
59 | struct bfa_cee_lldp_str_s chassis_id; | ||
60 | struct bfa_cee_lldp_str_s port_id; | ||
61 | struct bfa_cee_lldp_str_s port_desc; | ||
62 | struct bfa_cee_lldp_str_s sys_name; | ||
63 | struct bfa_cee_lldp_str_s sys_desc; | ||
64 | struct bfa_cee_lldp_str_s mgmt_addr; | ||
65 | u16 time_to_interval; | ||
66 | u16 enabled_system_cap; | ||
67 | }; | ||
68 | |||
69 | enum bfa_cee_dcbx_version_e { | ||
70 | DCBX_PROTOCOL_PRECEE = 1, | ||
71 | DCBX_PROTOCOL_CEE = 2, | ||
72 | }; | ||
73 | |||
74 | enum bfa_cee_lls_e { | ||
75 | CEE_LLS_DOWN_NO_TLV = 0, /* LLS is down because the TLV not sent by | ||
76 | * the peer */ | ||
77 | CEE_LLS_DOWN = 1, /* LLS is down as advertised by the peer */ | ||
78 | CEE_LLS_UP = 2, | ||
79 | }; | ||
80 | |||
81 | /* CEE/DCBX parameters */ | ||
82 | struct bfa_cee_dcbx_cfg_s { | ||
83 | u8 pgid[8]; | ||
84 | u8 pg_percentage[8]; | ||
85 | u8 pfc_enabled; /* bitmap of priorties with PFC enabled */ | ||
86 | u8 fcoe_user_priority; /* bitmap of priorities used for FcoE | ||
87 | * traffic */ | ||
88 | u8 dcbx_version; /* operating version:CEE or preCEE */ | ||
89 | u8 lls_fcoe; /* FCoE Logical Link Status */ | ||
90 | u8 lls_lan; /* LAN Logical Link Status */ | ||
91 | u8 rsvd[3]; | ||
92 | }; | ||
93 | |||
94 | /* CEE status */ | ||
95 | /* Making this to tri-state for the benefit of port list command */ | ||
96 | enum bfa_cee_status_e { | ||
97 | CEE_PHY_DOWN = 0, | ||
98 | CEE_PHY_UP = 1, | ||
99 | CEE_UP = 2, | ||
100 | }; | ||
101 | |||
102 | /* CEE Query */ | ||
103 | struct bfa_cee_attr_s { | ||
104 | u8 cee_status; | ||
105 | u8 error_reason; | ||
106 | struct bfa_cee_lldp_cfg_s lldp_remote; | ||
107 | struct bfa_cee_dcbx_cfg_s dcbx_remote; | ||
108 | mac_t src_mac; | ||
109 | u8 link_speed; | ||
110 | u8 filler[3]; | ||
111 | }; | ||
112 | |||
113 | |||
114 | |||
115 | |||
116 | /* LLDP/DCBX/CEE Statistics */ | ||
117 | |||
118 | struct bfa_cee_lldp_stats_s { | ||
119 | u32 frames_transmitted; | ||
120 | u32 frames_aged_out; | ||
121 | u32 frames_discarded; | ||
122 | u32 frames_in_error; | ||
123 | u32 frames_rcvd; | ||
124 | u32 tlvs_discarded; | ||
125 | u32 tlvs_unrecognized; | ||
126 | }; | ||
127 | |||
128 | struct bfa_cee_dcbx_stats_s { | ||
129 | u32 subtlvs_unrecognized; | ||
130 | u32 negotiation_failed; | ||
131 | u32 remote_cfg_changed; | ||
132 | u32 tlvs_received; | ||
133 | u32 tlvs_invalid; | ||
134 | u32 seqno; | ||
135 | u32 ackno; | ||
136 | u32 recvd_seqno; | ||
137 | u32 recvd_ackno; | ||
138 | }; | ||
139 | |||
140 | struct bfa_cee_cfg_stats_s { | ||
141 | u32 cee_status_down; | ||
142 | u32 cee_status_up; | ||
143 | u32 cee_hw_cfg_changed; | ||
144 | u32 recvd_invalid_cfg; | ||
145 | }; | ||
146 | |||
147 | |||
148 | struct bfa_cee_stats_s { | ||
149 | struct bfa_cee_lldp_stats_s lldp_stats; | ||
150 | struct bfa_cee_dcbx_stats_s dcbx_stats; | ||
151 | struct bfa_cee_cfg_stats_s cfg_stats; | ||
152 | }; | ||
153 | |||
154 | #pragma pack() | ||
155 | |||
156 | |||
157 | #endif /* __BFA_DEFS_CEE_H__ */ | ||
158 | |||
159 | |||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_driver.h b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h new file mode 100644 index 000000000000..57049805762b --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_driver.h | |||
@@ -0,0 +1,40 @@ | |||
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 | #ifndef __BFA_DEFS_DRIVER_H__ | ||
19 | #define __BFA_DEFS_DRIVER_H__ | ||
20 | |||
21 | /** | ||
22 | * Driver statistics | ||
23 | */ | ||
24 | u16 tm_io_abort; | ||
25 | u16 tm_io_abort_comp; | ||
26 | u16 tm_lun_reset; | ||
27 | u16 tm_lun_reset_comp; | ||
28 | u16 tm_target_reset; | ||
29 | u16 tm_bus_reset; | ||
30 | u16 ioc_restart; /* IOC restart count */ | ||
31 | u16 io_pending; /* outstanding io count per-IOC */ | ||
32 | u64 control_req; | ||
33 | u64 input_req; | ||
34 | u64 output_req; | ||
35 | u64 input_words; | ||
36 | u64 output_words; | ||
37 | } bfa_driver_stats_t; | ||
38 | |||
39 | |||
40 | #endif /* __BFA_DEFS_DRIVER_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h b/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h new file mode 100644 index 000000000000..79f9b3e146f7 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_ethport.h | |||
@@ -0,0 +1,98 @@ | |||
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 | #ifndef __BFA_DEFS_ETHPORT_H__ | ||
19 | #define __BFA_DEFS_ETHPORT_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_status.h> | ||
22 | #include <protocol/types.h> | ||
23 | #include <cna/pstats/phyport_defs.h> | ||
24 | #include <cna/pstats/ethport_defs.h> | ||
25 | |||
26 | struct bna_tx_info_s { | ||
27 | u32 miniport_state; | ||
28 | u32 adapter_state; | ||
29 | u64 tx_count; | ||
30 | u64 tx_wi; | ||
31 | u64 tx_sg; | ||
32 | u64 tx_tcp_chksum; | ||
33 | u64 tx_udp_chksum; | ||
34 | u64 tx_ip_chksum; | ||
35 | u64 tx_lsov1; | ||
36 | u64 tx_lsov2; | ||
37 | u64 tx_max_sg_len ; | ||
38 | }; | ||
39 | |||
40 | struct bna_rx_queue_info_s { | ||
41 | u16 q_id ; | ||
42 | u16 buf_size ; | ||
43 | u16 buf_count ; | ||
44 | u16 rsvd ; | ||
45 | u64 rx_count ; | ||
46 | u64 rx_dropped ; | ||
47 | u64 rx_unsupported ; | ||
48 | u64 rx_internal_err ; | ||
49 | u64 rss_count ; | ||
50 | u64 vlan_count ; | ||
51 | u64 rx_tcp_chksum ; | ||
52 | u64 rx_udp_chksum ; | ||
53 | u64 rx_ip_chksum ; | ||
54 | u64 rx_hds ; | ||
55 | }; | ||
56 | |||
57 | struct bna_rx_q_set_s { | ||
58 | u16 q_set_type; | ||
59 | u32 miniport_state; | ||
60 | u32 adapter_state; | ||
61 | struct bna_rx_queue_info_s rx_queue[2]; | ||
62 | }; | ||
63 | |||
64 | struct bna_port_stats_s { | ||
65 | struct bna_tx_info_s tx_stats; | ||
66 | u16 qset_count ; | ||
67 | struct bna_rx_q_set_s rx_qset[8]; | ||
68 | }; | ||
69 | |||
70 | struct bfa_ethport_stats_s { | ||
71 | struct bna_stats_txf txf_stats[1]; | ||
72 | struct bna_stats_rxf rxf_stats[1]; | ||
73 | struct bnad_drv_stats drv_stats; | ||
74 | }; | ||
75 | |||
76 | /** | ||
77 | * Ethernet port events | ||
78 | * Arguments below are in BFAL context from Mgmt | ||
79 | * BFA_PORT_AEN_ETH_LINKUP: [in]: mac [out]: mac | ||
80 | * BFA_PORT_AEN_ETH_LINKDOWN: [in]: mac [out]: mac | ||
81 | * BFA_PORT_AEN_ETH_ENABLE: [in]: mac [out]: mac | ||
82 | * BFA_PORT_AEN_ETH_DISABLE: [in]: mac [out]: mac | ||
83 | * | ||
84 | */ | ||
85 | enum bfa_ethport_aen_event { | ||
86 | BFA_ETHPORT_AEN_LINKUP = 1, /* Base Port Ethernet link up event */ | ||
87 | BFA_ETHPORT_AEN_LINKDOWN = 2, /* Base Port Ethernet link down event */ | ||
88 | BFA_ETHPORT_AEN_ENABLE = 3, /* Base Port Ethernet link enable event */ | ||
89 | BFA_ETHPORT_AEN_DISABLE = 4, /* Base Port Ethernet link disable | ||
90 | * event */ | ||
91 | }; | ||
92 | |||
93 | struct bfa_ethport_aen_data_s { | ||
94 | mac_t mac; /* MAC address of the physical port */ | ||
95 | }; | ||
96 | |||
97 | |||
98 | #endif /* __BFA_DEFS_ETHPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h b/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h new file mode 100644 index 000000000000..c08f4f5026ac --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_fcpim.h | |||
@@ -0,0 +1,45 @@ | |||
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 | #ifndef __BFA_DEFS_FCPIM_H__ | ||
18 | #define __BFA_DEFS_FCPIM_H__ | ||
19 | |||
20 | struct bfa_fcpim_stats_s { | ||
21 | u32 total_ios; /* Total IO count */ | ||
22 | u32 qresumes; /* IO waiting for CQ space */ | ||
23 | u32 no_iotags; /* NO IO contexts */ | ||
24 | u32 io_aborts; /* IO abort requests */ | ||
25 | u32 no_tskims; /* NO task management contexts */ | ||
26 | u32 iocomp_ok; /* IO completions with OK status */ | ||
27 | u32 iocomp_underrun; /* IO underrun (good) */ | ||
28 | u32 iocomp_overrun; /* IO overrun (good) */ | ||
29 | u32 iocomp_aborted; /* Aborted IO requests */ | ||
30 | u32 iocomp_timedout; /* IO timeouts */ | ||
31 | u32 iocom_nexus_abort; /* IO selection timeouts */ | ||
32 | u32 iocom_proto_err; /* IO protocol errors */ | ||
33 | u32 iocom_dif_err; /* IO SBC-3 protection errors */ | ||
34 | u32 iocom_tm_abort; /* IO aborted by TM requests */ | ||
35 | u32 iocom_sqer_needed; /* IO retry for SQ error | ||
36 | *recovery */ | ||
37 | u32 iocom_res_free; /* Delayed freeing of IO resources */ | ||
38 | u32 iocomp_scsierr; /* IO with non-good SCSI status */ | ||
39 | u32 iocom_hostabrts; /* Host IO abort requests */ | ||
40 | u32 iocom_utags; /* IO comp with unknown tags */ | ||
41 | u32 io_cleanups; /* IO implicitly aborted */ | ||
42 | u32 io_tmaborts; /* IO aborted due to TM commands */ | ||
43 | u32 rsvd; | ||
44 | }; | ||
45 | #endif /*__BFA_DEFS_FCPIM_H__*/ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_im_common.h b/drivers/scsi/bfa/include/defs/bfa_defs_im_common.h new file mode 100644 index 000000000000..9ccf53bef65a --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_im_common.h | |||
@@ -0,0 +1,32 @@ | |||
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 | #ifndef __BFA_DEFS_IM_COMMON_H__ | ||
19 | #define __BFA_DEFS_IM_COMMON_H__ | ||
20 | |||
21 | #define BFA_ADAPTER_NAME_LEN 256 | ||
22 | #define BFA_ADAPTER_GUID_LEN 256 | ||
23 | #define RESERVED_VLAN_NAME L"PORT VLAN" | ||
24 | #define PASSTHRU_VLAN_NAME L"PASSTHRU VLAN" | ||
25 | |||
26 | u64 tx_pkt_cnt; | ||
27 | u64 rx_pkt_cnt; | ||
28 | u32 duration; | ||
29 | u8 status; | ||
30 | } bfa_im_stats_t, *pbfa_im_stats_t; | ||
31 | |||
32 | #endif /* __BFA_DEFS_IM_COMMON_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_im_team.h b/drivers/scsi/bfa/include/defs/bfa_defs_im_team.h new file mode 100644 index 000000000000..a486a7eb81d6 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_im_team.h | |||
@@ -0,0 +1,72 @@ | |||
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 | #ifndef __BFA_DEFS_IM_TEAM_H__ | ||
19 | #define __BFA_DEFS_IM_TEAM_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | |||
23 | #define BFA_TEAM_MAX_PORTS 8 | ||
24 | #define BFA_TEAM_NAME_LEN 256 | ||
25 | #define BFA_MAX_NUM_TEAMS 16 | ||
26 | #define BFA_TEAM_INVALID_DELAY -1 | ||
27 | |||
28 | BFA_LACP_RATE_SLOW = 1, | ||
29 | BFA_LACP_RATE_FAST | ||
30 | } bfa_im_lacp_rate_t; | ||
31 | |||
32 | BFA_TEAM_MODE_FAIL_OVER = 1, | ||
33 | BFA_TEAM_MODE_FAIL_BACK, | ||
34 | BFA_TEAM_MODE_LACP, | ||
35 | BFA_TEAM_MODE_NONE | ||
36 | } bfa_im_team_mode_t; | ||
37 | |||
38 | BFA_XMIT_POLICY_L2 = 1, | ||
39 | BFA_XMIT_POLICY_L3_L4 | ||
40 | } bfa_im_xmit_policy_t; | ||
41 | |||
42 | bfa_im_team_mode_t team_mode; | ||
43 | bfa_im_lacp_rate_t lacp_rate; | ||
44 | bfa_im_xmit_policy_t xmit_policy; | ||
45 | int delay; | ||
46 | wchar_t primary[BFA_ADAPTER_NAME_LEN]; | ||
47 | wchar_t preferred_primary[BFA_ADAPTER_NAME_LEN]; | ||
48 | mac_t mac; | ||
49 | u16 num_ports; | ||
50 | u16 num_vlans; | ||
51 | u16 vlan_list[BFA_MAX_VLANS_PER_PORT]; | ||
52 | wchar_t team_guid_list[BFA_TEAM_MAX_PORTS][BFA_ADAPTER_GUID_LEN]; | ||
53 | wchar_t ioc_name_list[BFA_TEAM_MAX_PORTS][BFA_ADAPTER_NAME_LEN]; | ||
54 | } bfa_im_team_attr_t; | ||
55 | |||
56 | wchar_t team_name[BFA_TEAM_NAME_LEN]; | ||
57 | bfa_im_xmit_policy_t xmit_policy; | ||
58 | int delay; | ||
59 | wchar_t primary[BFA_ADAPTER_NAME_LEN]; | ||
60 | wchar_t preferred_primary[BFA_ADAPTER_NAME_LEN]; | ||
61 | } bfa_im_team_edit_t, *pbfa_im_team_edit_t; | ||
62 | |||
63 | wchar_t team_name[BFA_TEAM_NAME_LEN]; | ||
64 | bfa_im_team_mode_t team_mode; | ||
65 | mac_t mac; | ||
66 | } bfa_im_team_info_t; | ||
67 | |||
68 | bfa_im_team_info_t team_info[BFA_MAX_NUM_TEAMS]; | ||
69 | u16 num_teams; | ||
70 | } bfa_im_team_list_t, *pbfa_im_team_list_t; | ||
71 | |||
72 | #endif /* __BFA_DEFS_IM_TEAM_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h new file mode 100644 index 000000000000..b1d532da3a9d --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_ioc.h | |||
@@ -0,0 +1,152 @@ | |||
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 | #ifndef __BFA_DEFS_IOC_H__ | ||
19 | #define __BFA_DEFS_IOC_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | #include <defs/bfa_defs_types.h> | ||
23 | #include <defs/bfa_defs_version.h> | ||
24 | #include <defs/bfa_defs_adapter.h> | ||
25 | #include <defs/bfa_defs_pm.h> | ||
26 | |||
27 | enum { | ||
28 | BFA_IOC_DRIVER_LEN = 16, | ||
29 | BFA_IOC_CHIP_REV_LEN = 8, | ||
30 | }; | ||
31 | |||
32 | /** | ||
33 | * Driver and firmware versions. | ||
34 | */ | ||
35 | struct bfa_ioc_driver_attr_s { | ||
36 | char driver[BFA_IOC_DRIVER_LEN]; /* driver name */ | ||
37 | char driver_ver[BFA_VERSION_LEN]; /* driver version */ | ||
38 | char fw_ver[BFA_VERSION_LEN]; /* firmware version*/ | ||
39 | char bios_ver[BFA_VERSION_LEN]; /* bios version */ | ||
40 | char efi_ver[BFA_VERSION_LEN]; /* EFI version */ | ||
41 | char ob_ver[BFA_VERSION_LEN]; /* openboot version*/ | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * IOC PCI device attributes | ||
46 | */ | ||
47 | struct bfa_ioc_pci_attr_s { | ||
48 | u16 vendor_id; /* PCI vendor ID */ | ||
49 | u16 device_id; /* PCI device ID */ | ||
50 | u16 ssid; /* subsystem ID */ | ||
51 | u16 ssvid; /* subsystem vendor ID */ | ||
52 | u32 pcifn; /* PCI device function */ | ||
53 | u32 rsvd; /* padding */ | ||
54 | u8 chip_rev[BFA_IOC_CHIP_REV_LEN]; /* chip revision */ | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * IOC states | ||
59 | */ | ||
60 | enum bfa_ioc_state { | ||
61 | BFA_IOC_RESET = 1, /* IOC is in reset state */ | ||
62 | BFA_IOC_SEMWAIT = 2, /* Waiting for IOC hardware semaphore */ | ||
63 | BFA_IOC_HWINIT = 3, /* IOC hardware is being initialized */ | ||
64 | BFA_IOC_GETATTR = 4, /* IOC is being configured */ | ||
65 | BFA_IOC_OPERATIONAL = 5, /* IOC is operational */ | ||
66 | BFA_IOC_INITFAIL = 6, /* IOC hardware failure */ | ||
67 | BFA_IOC_HBFAIL = 7, /* IOC heart-beat failure */ | ||
68 | BFA_IOC_DISABLING = 8, /* IOC is being disabled */ | ||
69 | BFA_IOC_DISABLED = 9, /* IOC is disabled */ | ||
70 | BFA_IOC_FWMISMATCH = 10, /* IOC firmware different from drivers */ | ||
71 | }; | ||
72 | |||
73 | /** | ||
74 | * IOC firmware stats | ||
75 | */ | ||
76 | struct bfa_fw_ioc_stats_s { | ||
77 | u32 hb_count; | ||
78 | u32 cfg_reqs; | ||
79 | u32 enable_reqs; | ||
80 | u32 disable_reqs; | ||
81 | u32 stats_reqs; | ||
82 | u32 clrstats_reqs; | ||
83 | u32 unknown_reqs; | ||
84 | u32 ic_reqs; /* interrupt coalesce reqs */ | ||
85 | }; | ||
86 | |||
87 | /** | ||
88 | * IOC driver stats | ||
89 | */ | ||
90 | struct bfa_ioc_drv_stats_s { | ||
91 | u32 ioc_isrs; | ||
92 | u32 ioc_enables; | ||
93 | u32 ioc_disables; | ||
94 | u32 ioc_hbfails; | ||
95 | u32 ioc_boots; | ||
96 | u32 stats_tmos; | ||
97 | u32 hb_count; | ||
98 | u32 disable_reqs; | ||
99 | u32 enable_reqs; | ||
100 | u32 disable_replies; | ||
101 | u32 enable_replies; | ||
102 | }; | ||
103 | |||
104 | /** | ||
105 | * IOC statistics | ||
106 | */ | ||
107 | struct bfa_ioc_stats_s { | ||
108 | struct bfa_ioc_drv_stats_s drv_stats; /* driver IOC stats */ | ||
109 | struct bfa_fw_ioc_stats_s fw_stats; /* firmware IOC stats */ | ||
110 | }; | ||
111 | |||
112 | |||
113 | enum bfa_ioc_type_e { | ||
114 | BFA_IOC_TYPE_FC = 1, | ||
115 | BFA_IOC_TYPE_FCoE = 2, | ||
116 | BFA_IOC_TYPE_LL = 3, | ||
117 | }; | ||
118 | |||
119 | /** | ||
120 | * IOC attributes returned in queries | ||
121 | */ | ||
122 | struct bfa_ioc_attr_s { | ||
123 | enum bfa_ioc_type_e ioc_type; | ||
124 | enum bfa_ioc_state state; /* IOC state */ | ||
125 | struct bfa_adapter_attr_s adapter_attr; /* HBA attributes */ | ||
126 | struct bfa_ioc_driver_attr_s driver_attr; /* driver attr */ | ||
127 | struct bfa_ioc_pci_attr_s pci_attr; | ||
128 | u8 port_id; /* port number */ | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * BFA IOC level events | ||
133 | */ | ||
134 | enum bfa_ioc_aen_event { | ||
135 | BFA_IOC_AEN_HBGOOD = 1, /* Heart Beat restore event */ | ||
136 | BFA_IOC_AEN_HBFAIL = 2, /* Heart Beat failure event */ | ||
137 | BFA_IOC_AEN_ENABLE = 3, /* IOC enabled event */ | ||
138 | BFA_IOC_AEN_DISABLE = 4, /* IOC disabled event */ | ||
139 | BFA_IOC_AEN_FWMISMATCH = 5, /* IOC firmware mismatch */ | ||
140 | }; | ||
141 | |||
142 | /** | ||
143 | * BFA IOC level event data, now just a place holder | ||
144 | */ | ||
145 | struct bfa_ioc_aen_data_s { | ||
146 | enum bfa_ioc_type_e ioc_type; | ||
147 | wwn_t pwwn; | ||
148 | mac_t mac; | ||
149 | }; | ||
150 | |||
151 | #endif /* __BFA_DEFS_IOC_H__ */ | ||
152 | |||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h new file mode 100644 index 000000000000..d76bcbd9820f --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_iocfc.h | |||
@@ -0,0 +1,310 @@ | |||
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 | #ifndef __BFA_DEFS_IOCFC_H__ | ||
19 | #define __BFA_DEFS_IOCFC_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | #include <defs/bfa_defs_types.h> | ||
23 | #include <defs/bfa_defs_version.h> | ||
24 | #include <defs/bfa_defs_adapter.h> | ||
25 | #include <defs/bfa_defs_pm.h> | ||
26 | |||
27 | #define BFA_IOCFC_INTR_DELAY 1125 | ||
28 | #define BFA_IOCFC_INTR_LATENCY 225 | ||
29 | |||
30 | /** | ||
31 | * Interrupt coalescing configuration. | ||
32 | */ | ||
33 | struct bfa_iocfc_intr_attr_s { | ||
34 | bfa_boolean_t coalesce; /* enable/disable coalescing */ | ||
35 | u16 latency; /* latency in microseconds */ | ||
36 | u16 delay; /* delay in microseconds */ | ||
37 | }; | ||
38 | |||
39 | /** | ||
40 | * IOC firmware configuraton | ||
41 | */ | ||
42 | struct bfa_iocfc_fwcfg_s { | ||
43 | u16 num_fabrics; /* number of fabrics */ | ||
44 | u16 num_lports; /* number of local lports */ | ||
45 | u16 num_rports; /* number of remote ports */ | ||
46 | u16 num_ioim_reqs; /* number of IO reqs */ | ||
47 | u16 num_tskim_reqs; /* task management requests */ | ||
48 | u16 num_iotm_reqs; /* number of TM IO reqs */ | ||
49 | u16 num_tsktm_reqs; /* TM task management requests*/ | ||
50 | u16 num_fcxp_reqs; /* unassisted FC exchanges */ | ||
51 | u16 num_uf_bufs; /* unsolicited recv buffers */ | ||
52 | u8 num_cqs; | ||
53 | u8 rsvd; | ||
54 | }; | ||
55 | |||
56 | struct bfa_iocfc_drvcfg_s { | ||
57 | u16 num_reqq_elems; /* number of req queue elements */ | ||
58 | u16 num_rspq_elems; /* number of rsp queue elements */ | ||
59 | u16 num_sgpgs; /* number of total SG pages */ | ||
60 | u16 num_sboot_tgts; /* number of SAN boot targets */ | ||
61 | u16 num_sboot_luns; /* number of SAN boot luns */ | ||
62 | u16 ioc_recover; /* IOC recovery mode */ | ||
63 | u16 min_cfg; /* minimum configuration */ | ||
64 | u16 path_tov; /* device path timeout */ | ||
65 | bfa_boolean_t delay_comp; /* delay completion of | ||
66 | failed inflight IOs */ | ||
67 | u32 rsvd; | ||
68 | }; | ||
69 | /** | ||
70 | * IOC configuration | ||
71 | */ | ||
72 | struct bfa_iocfc_cfg_s { | ||
73 | struct bfa_iocfc_fwcfg_s fwcfg; /* firmware side config */ | ||
74 | struct bfa_iocfc_drvcfg_s drvcfg; /* driver side config */ | ||
75 | }; | ||
76 | |||
77 | /** | ||
78 | * IOC firmware IO stats | ||
79 | */ | ||
80 | struct bfa_fw_io_stats_s { | ||
81 | u32 host_abort; /* IO aborted by host driver*/ | ||
82 | u32 host_cleanup; /* IO clean up by host driver */ | ||
83 | |||
84 | u32 fw_io_timeout; /* IOs timedout */ | ||
85 | u32 fw_frm_parse; /* frame parsed by f/w */ | ||
86 | u32 fw_frm_data; /* fcp_data frame parsed by f/w */ | ||
87 | u32 fw_frm_rsp; /* fcp_rsp frame parsed by f/w */ | ||
88 | u32 fw_frm_xfer_rdy; /* xfer_rdy frame parsed by f/w */ | ||
89 | u32 fw_frm_bls_acc; /* BLS ACC frame parsed by f/w */ | ||
90 | u32 fw_frm_tgt_abort; /* target ABTS parsed by f/w */ | ||
91 | u32 fw_frm_unknown; /* unknown parsed by f/w */ | ||
92 | u32 fw_data_dma; /* f/w DMA'ed the data frame */ | ||
93 | u32 fw_frm_drop; /* f/w drop the frame */ | ||
94 | |||
95 | u32 rec_timeout; /* FW rec timed out */ | ||
96 | u32 error_rec; /* FW sending rec on | ||
97 | * an error condition*/ | ||
98 | u32 wait_for_si; /* FW wait for SI */ | ||
99 | u32 rec_rsp_inval; /* REC rsp invalid */ | ||
100 | u32 seqr_io_abort; /* target does not know cmd so abort */ | ||
101 | u32 seqr_io_retry; /* SEQR failed so retry IO */ | ||
102 | |||
103 | u32 itn_cisc_upd_rsp; /* ITN cisc updated on fcp_rsp */ | ||
104 | u32 itn_cisc_upd_data; /* ITN cisc updated on fcp_data */ | ||
105 | u32 itn_cisc_upd_xfer_rdy; /* ITN cisc updated on fcp_data */ | ||
106 | |||
107 | u32 fcp_data_lost; /* fcp data lost */ | ||
108 | |||
109 | u32 ro_set_in_xfer_rdy; /* Target set RO in Xfer_rdy frame */ | ||
110 | u32 xfer_rdy_ooo_err; /* Out of order Xfer_rdy received */ | ||
111 | u32 xfer_rdy_unknown_err; /* unknown error in xfer_rdy frame */ | ||
112 | |||
113 | u32 io_abort_timeout; /* ABTS timedout */ | ||
114 | u32 sler_initiated; /* SLER initiated */ | ||
115 | |||
116 | u32 unexp_fcp_rsp; /* fcp response in wrong state */ | ||
117 | |||
118 | u32 fcp_rsp_under_run; /* fcp rsp IO underrun */ | ||
119 | u32 fcp_rsp_under_run_wr; /* fcp rsp IO underrun for write */ | ||
120 | u32 fcp_rsp_under_run_err; /* fcp rsp IO underrun error */ | ||
121 | u32 fcp_rsp_resid_inval; /* invalid residue */ | ||
122 | u32 fcp_rsp_over_run; /* fcp rsp IO overrun */ | ||
123 | u32 fcp_rsp_over_run_err; /* fcp rsp IO overrun error */ | ||
124 | u32 fcp_rsp_proto_err; /* protocol error in fcp rsp */ | ||
125 | u32 fcp_rsp_sense_err; /* error in sense info in fcp rsp */ | ||
126 | u32 fcp_conf_req; /* FCP conf requested */ | ||
127 | |||
128 | u32 tgt_aborted_io; /* target initiated abort */ | ||
129 | |||
130 | u32 ioh_edtov_timeout_event;/* IOH edtov timer popped */ | ||
131 | u32 ioh_fcp_rsp_excp_event; /* IOH FCP_RSP exception */ | ||
132 | u32 ioh_fcp_conf_event; /* IOH FCP_CONF */ | ||
133 | u32 ioh_mult_frm_rsp_event; /* IOH multi_frame FCP_RSP */ | ||
134 | u32 ioh_hit_class2_event; /* IOH hit class2 */ | ||
135 | u32 ioh_miss_other_event; /* IOH miss other */ | ||
136 | u32 ioh_seq_cnt_err_event; /* IOH seq cnt error */ | ||
137 | u32 ioh_len_err_event; /* IOH len error - fcp_dl != | ||
138 | * bytes xfered */ | ||
139 | u32 ioh_seq_len_err_event; /* IOH seq len error */ | ||
140 | u32 ioh_data_oor_event; /* Data out of range */ | ||
141 | u32 ioh_ro_ooo_event; /* Relative offset out of range */ | ||
142 | u32 ioh_cpu_owned_event; /* IOH hit -iost owned by f/w */ | ||
143 | u32 ioh_unexp_frame_event; /* unexpected frame recieved | ||
144 | * count */ | ||
145 | u32 ioh_err_int; /* IOH error int during data-phase | ||
146 | * for scsi write | ||
147 | */ | ||
148 | }; | ||
149 | |||
150 | /** | ||
151 | * IOC port firmware stats | ||
152 | */ | ||
153 | |||
154 | struct bfa_fw_port_fpg_stats_s { | ||
155 | u32 intr_evt; | ||
156 | u32 intr; | ||
157 | u32 intr_excess; | ||
158 | u32 intr_cause0; | ||
159 | u32 intr_other; | ||
160 | u32 intr_other_ign; | ||
161 | u32 sig_lost; | ||
162 | u32 sig_regained; | ||
163 | u32 sync_lost; | ||
164 | u32 sync_to; | ||
165 | u32 sync_regained; | ||
166 | u32 div2_overflow; | ||
167 | u32 div2_underflow; | ||
168 | u32 efifo_overflow; | ||
169 | u32 efifo_underflow; | ||
170 | u32 idle_rx; | ||
171 | u32 lrr_rx; | ||
172 | u32 lr_rx; | ||
173 | u32 ols_rx; | ||
174 | u32 nos_rx; | ||
175 | u32 lip_rx; | ||
176 | u32 arbf0_rx; | ||
177 | u32 mrk_rx; | ||
178 | u32 const_mrk_rx; | ||
179 | u32 prim_unknown; | ||
180 | u32 rsvd; | ||
181 | }; | ||
182 | |||
183 | |||
184 | struct bfa_fw_port_lksm_stats_s { | ||
185 | u32 hwsm_success; /* hwsm state machine success */ | ||
186 | u32 hwsm_fails; /* hwsm fails */ | ||
187 | u32 hwsm_wdtov; /* hwsm timed out */ | ||
188 | u32 swsm_success; /* swsm success */ | ||
189 | u32 swsm_fails; /* swsm fails */ | ||
190 | u32 swsm_wdtov; /* swsm timed out */ | ||
191 | u32 busybufs; /* link init failed due to busybuf */ | ||
192 | u32 buf_waits; /* bufwait state entries */ | ||
193 | u32 link_fails; /* link failures */ | ||
194 | u32 psp_errors; /* primitive sequence protocol errors */ | ||
195 | u32 lr_unexp; /* No. of times LR rx-ed unexpectedly */ | ||
196 | u32 lrr_unexp; /* No. of times LRR rx-ed unexpectedly */ | ||
197 | u32 lr_tx; /* No. of times LR tx started */ | ||
198 | u32 lrr_tx; /* No. of times LRR tx started */ | ||
199 | u32 ols_tx; /* No. of times OLS tx started */ | ||
200 | u32 nos_tx; /* No. of times NOS tx started */ | ||
201 | }; | ||
202 | |||
203 | |||
204 | struct bfa_fw_port_snsm_stats_s { | ||
205 | u32 hwsm_success; /* Successful hwsm terminations */ | ||
206 | u32 hwsm_fails; /* hwsm fail count */ | ||
207 | u32 hwsm_wdtov; /* hwsm timed out */ | ||
208 | u32 swsm_success; /* swsm success */ | ||
209 | u32 swsm_wdtov; /* swsm timed out */ | ||
210 | u32 error_resets; /* error resets initiated by upsm */ | ||
211 | u32 sync_lost; /* Sync loss count */ | ||
212 | u32 sig_lost; /* Signal loss count */ | ||
213 | }; | ||
214 | |||
215 | |||
216 | struct bfa_fw_port_physm_stats_s { | ||
217 | u32 module_inserts; /* Module insert count */ | ||
218 | u32 module_xtracts; /* Module extracts count */ | ||
219 | u32 module_invalids; /* Invalid module inserted count */ | ||
220 | u32 module_read_ign; /* Module validation status ignored */ | ||
221 | u32 laser_faults; /* Laser fault count */ | ||
222 | u32 rsvd; | ||
223 | }; | ||
224 | |||
225 | |||
226 | struct bfa_fw_fip_stats_s { | ||
227 | u32 disc_req; /* Discovery solicit requests */ | ||
228 | u32 disc_rsp; /* Discovery solicit response */ | ||
229 | u32 disc_err; /* Discovery advt. parse errors */ | ||
230 | u32 disc_unsol; /* Discovery unsolicited */ | ||
231 | u32 disc_timeouts; /* Discovery timeouts */ | ||
232 | u32 linksvc_unsupp; /* Unsupported link service req */ | ||
233 | u32 linksvc_err; /* Parse error in link service req */ | ||
234 | u32 logo_req; /* Number of FIP logos received */ | ||
235 | u32 clrvlink_req; /* Clear virtual link req */ | ||
236 | u32 op_unsupp; /* Unsupported FIP operation */ | ||
237 | u32 untagged; /* Untagged frames (ignored) */ | ||
238 | u32 rsvd; | ||
239 | }; | ||
240 | |||
241 | |||
242 | struct bfa_fw_lps_stats_s { | ||
243 | u32 mac_invalids; /* Invalid mac assigned */ | ||
244 | u32 rsvd; | ||
245 | }; | ||
246 | |||
247 | |||
248 | struct bfa_fw_fcoe_stats_s { | ||
249 | u32 cee_linkups; /* CEE link up count */ | ||
250 | u32 cee_linkdns; /* CEE link down count */ | ||
251 | u32 fip_linkups; /* FIP link up count */ | ||
252 | u32 fip_linkdns; /* FIP link up count */ | ||
253 | u32 fip_fails; /* FIP fail count */ | ||
254 | u32 mac_invalids; /* Invalid mac assigned */ | ||
255 | }; | ||
256 | |||
257 | /** | ||
258 | * IOC firmware FCoE port stats | ||
259 | */ | ||
260 | struct bfa_fw_fcoe_port_stats_s { | ||
261 | struct bfa_fw_fcoe_stats_s fcoe_stats; | ||
262 | struct bfa_fw_fip_stats_s fip_stats; | ||
263 | }; | ||
264 | |||
265 | /** | ||
266 | * IOC firmware FC port stats | ||
267 | */ | ||
268 | struct bfa_fw_fc_port_stats_s { | ||
269 | struct bfa_fw_port_fpg_stats_s fpg_stats; | ||
270 | struct bfa_fw_port_physm_stats_s physm_stats; | ||
271 | struct bfa_fw_port_snsm_stats_s snsm_stats; | ||
272 | struct bfa_fw_port_lksm_stats_s lksm_stats; | ||
273 | }; | ||
274 | |||
275 | /** | ||
276 | * IOC firmware FC port stats | ||
277 | */ | ||
278 | union bfa_fw_port_stats_s { | ||
279 | struct bfa_fw_fc_port_stats_s fc_stats; | ||
280 | struct bfa_fw_fcoe_port_stats_s fcoe_stats; | ||
281 | }; | ||
282 | |||
283 | /** | ||
284 | * IOC firmware stats | ||
285 | */ | ||
286 | struct bfa_fw_stats_s { | ||
287 | struct bfa_fw_ioc_stats_s ioc_stats; | ||
288 | struct bfa_fw_io_stats_s io_stats; | ||
289 | union bfa_fw_port_stats_s port_stats; | ||
290 | }; | ||
291 | |||
292 | /** | ||
293 | * IOC statistics | ||
294 | */ | ||
295 | struct bfa_iocfc_stats_s { | ||
296 | struct bfa_fw_stats_s fw_stats; /* firmware IOC stats */ | ||
297 | }; | ||
298 | |||
299 | /** | ||
300 | * IOC attributes returned in queries | ||
301 | */ | ||
302 | struct bfa_iocfc_attr_s { | ||
303 | struct bfa_iocfc_cfg_s config; /* IOCFC config */ | ||
304 | struct bfa_iocfc_intr_attr_s intr_attr; /* interrupt attr */ | ||
305 | }; | ||
306 | |||
307 | #define BFA_IOCFC_PATHTOV_MAX 60 | ||
308 | #define BFA_IOCFC_QDEPTH_MAX 2000 | ||
309 | |||
310 | #endif /* __BFA_DEFS_IOC_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h b/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h new file mode 100644 index 000000000000..7cb63ea98f38 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_ipfc.h | |||
@@ -0,0 +1,70 @@ | |||
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 | #ifndef __BFA_DEFS_IPFC_H__ | ||
18 | #define __BFA_DEFS_IPFC_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | #include <protocol/types.h> | ||
22 | #include <defs/bfa_defs_types.h> | ||
23 | |||
24 | /** | ||
25 | * FCS ip remote port states | ||
26 | */ | ||
27 | enum bfa_iprp_state { | ||
28 | BFA_IPRP_UNINIT = 0, /* PORT is not yet initialized */ | ||
29 | BFA_IPRP_ONLINE = 1, /* process login is complete */ | ||
30 | BFA_IPRP_OFFLINE = 2, /* iprp is offline */ | ||
31 | }; | ||
32 | |||
33 | /** | ||
34 | * FCS remote port statistics | ||
35 | */ | ||
36 | struct bfa_iprp_stats_s { | ||
37 | u32 offlines; | ||
38 | u32 onlines; | ||
39 | u32 rscns; | ||
40 | u32 plogis; | ||
41 | u32 logos; | ||
42 | u32 plogi_timeouts; | ||
43 | u32 plogi_rejects; | ||
44 | }; | ||
45 | |||
46 | /** | ||
47 | * FCS iprp attribute returned in queries | ||
48 | */ | ||
49 | struct bfa_iprp_attr_s { | ||
50 | enum bfa_iprp_state state; | ||
51 | }; | ||
52 | |||
53 | struct bfa_ipfc_stats_s { | ||
54 | u32 arp_sent; | ||
55 | u32 arp_recv; | ||
56 | u32 arp_reply_sent; | ||
57 | u32 arp_reply_recv; | ||
58 | u32 farp_sent; | ||
59 | u32 farp_recv; | ||
60 | u32 farp_reply_sent; | ||
61 | u32 farp_reply_recv; | ||
62 | u32 farp_reject_sent; | ||
63 | u32 farp_reject_recv; | ||
64 | }; | ||
65 | |||
66 | struct bfa_ipfc_attr_s { | ||
67 | bfa_boolean_t enabled; | ||
68 | }; | ||
69 | |||
70 | #endif /* __BFA_DEFS_IPFC_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h new file mode 100644 index 000000000000..2ec769903d24 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_itnim.h | |||
@@ -0,0 +1,126 @@ | |||
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 | #ifndef __BFA_DEFS_ITNIM_H__ | ||
18 | #define __BFA_DEFS_ITNIM_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | #include <protocol/types.h> | ||
22 | |||
23 | /** | ||
24 | * FCS itnim states | ||
25 | */ | ||
26 | enum bfa_itnim_state { | ||
27 | BFA_ITNIM_OFFLINE = 0, /* offline */ | ||
28 | BFA_ITNIM_PRLI_SEND = 1, /* prli send */ | ||
29 | BFA_ITNIM_PRLI_SENT = 2, /* prli sent */ | ||
30 | BFA_ITNIM_PRLI_RETRY = 3, /* prli retry */ | ||
31 | BFA_ITNIM_HCB_ONLINE = 4, /* online callback */ | ||
32 | BFA_ITNIM_ONLINE = 5, /* online */ | ||
33 | BFA_ITNIM_HCB_OFFLINE = 6, /* offline callback */ | ||
34 | BFA_ITNIM_INITIATIOR = 7, /* initiator */ | ||
35 | }; | ||
36 | |||
37 | struct bfa_itnim_hal_stats_s { | ||
38 | u32 onlines; /* ITN nexus onlines (PRLI done) */ | ||
39 | u32 offlines; /* ITN Nexus offlines */ | ||
40 | u32 creates; /* ITN create requests */ | ||
41 | u32 deletes; /* ITN delete requests */ | ||
42 | u32 create_comps; /* ITN create completions */ | ||
43 | u32 delete_comps; /* ITN delete completions */ | ||
44 | u32 sler_events; /* SLER (sequence level error | ||
45 | * recovery) events */ | ||
46 | u32 ioc_disabled; /* Num IOC disables */ | ||
47 | u32 cleanup_comps; /* ITN cleanup completions */ | ||
48 | u32 tm_cmnds; /* task management(TM) cmnds sent */ | ||
49 | u32 tm_fw_rsps; /* TM cmds firmware responses */ | ||
50 | u32 tm_success; /* TM successes */ | ||
51 | u32 tm_failures; /* TM failures */ | ||
52 | u32 tm_io_comps; /* TM IO completions */ | ||
53 | u32 tm_qresumes; /* TM queue resumes (after waiting | ||
54 | * for resources) | ||
55 | */ | ||
56 | u32 tm_iocdowns; /* TM cmnds affected by IOC down */ | ||
57 | u32 tm_cleanups; /* TM cleanups */ | ||
58 | u32 tm_cleanup_comps; | ||
59 | /* TM cleanup completions */ | ||
60 | u32 ios; /* IO requests */ | ||
61 | u32 io_comps; /* IO completions */ | ||
62 | u64 input_reqs; /* INPUT requests */ | ||
63 | u64 output_reqs; /* OUTPUT requests */ | ||
64 | }; | ||
65 | |||
66 | /** | ||
67 | * FCS remote port statistics | ||
68 | */ | ||
69 | struct bfa_itnim_stats_s { | ||
70 | u32 onlines; /* num rport online */ | ||
71 | u32 offlines; /* num rport offline */ | ||
72 | u32 prli_sent; /* num prli sent out */ | ||
73 | u32 fcxp_alloc_wait;/* num fcxp alloc waits */ | ||
74 | u32 prli_rsp_err; /* num prli rsp errors */ | ||
75 | u32 prli_rsp_acc; /* num prli rsp accepts */ | ||
76 | u32 initiator; /* rport is an initiator */ | ||
77 | u32 prli_rsp_parse_err; /* prli rsp parsing errors */ | ||
78 | u32 prli_rsp_rjt; /* num prli rsp rejects */ | ||
79 | u32 timeout; /* num timeouts detected */ | ||
80 | u32 sler; /* num sler notification from BFA */ | ||
81 | u32 rsvd; | ||
82 | struct bfa_itnim_hal_stats_s hal_stats; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * FCS itnim attributes returned in queries | ||
87 | */ | ||
88 | struct bfa_itnim_attr_s { | ||
89 | enum bfa_itnim_state state; /* FCS itnim state */ | ||
90 | u8 retry; /* data retransmision support */ | ||
91 | u8 task_retry_id; /* task retry ident support */ | ||
92 | u8 rec_support; /* REC supported */ | ||
93 | u8 conf_comp; /* confirmed completion supp */ | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * BFA ITNIM events. | ||
98 | * Arguments below are in BFAL context from Mgmt | ||
99 | * BFA_ITNIM_AEN_NEW: [in]: None [out]: vf_id, lpwwn | ||
100 | * BFA_ITNIM_AEN_DELETE: [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets), | ||
101 | * [out]: vf_id, ppwwn, lpwwn, rpwwn | ||
102 | * BFA_ITNIM_AEN_ONLINE: [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets), | ||
103 | * [out]: vf_id, ppwwn, lpwwn, rpwwn | ||
104 | * BFA_ITNIM_AEN_OFFLINE: [in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets), | ||
105 | * [out]: vf_id, ppwwn, lpwwn, rpwwn | ||
106 | * BFA_ITNIM_AEN_DISCONNECT:[in]: vf_id, lpwwn, rpwwn (0 = all fcp4 targets), | ||
107 | * [out]: vf_id, ppwwn, lpwwn, rpwwn | ||
108 | */ | ||
109 | enum bfa_itnim_aen_event { | ||
110 | BFA_ITNIM_AEN_ONLINE = 1, /* Target online */ | ||
111 | BFA_ITNIM_AEN_OFFLINE = 2, /* Target offline */ | ||
112 | BFA_ITNIM_AEN_DISCONNECT = 3, /* Target disconnected */ | ||
113 | }; | ||
114 | |||
115 | /** | ||
116 | * BFA ITNIM event data structure. | ||
117 | */ | ||
118 | struct bfa_itnim_aen_data_s { | ||
119 | u16 vf_id; /* vf_id of the IT nexus */ | ||
120 | u16 rsvd[3]; | ||
121 | wwn_t ppwwn; /* WWN of its physical port */ | ||
122 | wwn_t lpwwn; /* WWN of logical port */ | ||
123 | wwn_t rpwwn; /* WWN of remote(target) port */ | ||
124 | }; | ||
125 | |||
126 | #endif /* __BFA_DEFS_ITNIM_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_led.h b/drivers/scsi/bfa/include/defs/bfa_defs_led.h new file mode 100644 index 000000000000..62039273264e --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_led.h | |||
@@ -0,0 +1,35 @@ | |||
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 | #ifndef __BFA_DEFS_LED_H__ | ||
19 | #define __BFA_DEFS_LED_H__ | ||
20 | |||
21 | #define BFA_LED_MAX_NUM 3 | ||
22 | |||
23 | enum bfa_led_op { | ||
24 | BFA_LED_OFF = 0, | ||
25 | BFA_LED_ON = 1, | ||
26 | BFA_LED_FLICK = 2, | ||
27 | BFA_LED_BLINK = 3, | ||
28 | }; | ||
29 | |||
30 | enum bfa_led_color { | ||
31 | BFA_LED_GREEN = 0, | ||
32 | BFA_LED_AMBER = 1, | ||
33 | }; | ||
34 | |||
35 | #endif /* __BFA_DEFS_LED_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_lport.h b/drivers/scsi/bfa/include/defs/bfa_defs_lport.h new file mode 100644 index 000000000000..7359f82aacfc --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_lport.h | |||
@@ -0,0 +1,68 @@ | |||
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 | #ifndef __BFA_DEFS_LPORT_H__ | ||
19 | #define __BFA_DEFS_LPORT_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_types.h> | ||
22 | #include <defs/bfa_defs_port.h> | ||
23 | |||
24 | /** | ||
25 | * BFA AEN logical port events. | ||
26 | * Arguments below are in BFAL context from Mgmt | ||
27 | * BFA_LPORT_AEN_NEW: [in]: None [out]: vf_id, ppwwn, lpwwn, roles | ||
28 | * BFA_LPORT_AEN_DELETE: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
29 | * BFA_LPORT_AEN_ONLINE: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
30 | * BFA_LPORT_AEN_OFFLINE: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
31 | * BFA_LPORT_AEN_DISCONNECT:[in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
32 | * BFA_LPORT_AEN_NEW_PROP: [in]: None [out]: vf_id, ppwwn. lpwwn, roles | ||
33 | * BFA_LPORT_AEN_DELETE_PROP: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
34 | * BFA_LPORT_AEN_NEW_STANDARD: [in]: None [out]: vf_id, ppwwn. lpwwn, roles | ||
35 | * BFA_LPORT_AEN_DELETE_STANDARD: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
36 | * BFA_LPORT_AEN_NPIV_DUP_WWN: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
37 | * BFA_LPORT_AEN_NPIV_FABRIC_MAX: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
38 | * BFA_LPORT_AEN_NPIV_UNKNOWN: [in]: lpwwn [out]: vf_id, ppwwn. lpwwn, roles | ||
39 | */ | ||
40 | enum bfa_lport_aen_event { | ||
41 | BFA_LPORT_AEN_NEW = 1, /* LPort created event */ | ||
42 | BFA_LPORT_AEN_DELETE = 2, /* LPort deleted event */ | ||
43 | BFA_LPORT_AEN_ONLINE = 3, /* LPort online event */ | ||
44 | BFA_LPORT_AEN_OFFLINE = 4, /* LPort offline event */ | ||
45 | BFA_LPORT_AEN_DISCONNECT = 5, /* LPort disconnect event */ | ||
46 | BFA_LPORT_AEN_NEW_PROP = 6, /* VPort created event */ | ||
47 | BFA_LPORT_AEN_DELETE_PROP = 7, /* VPort deleted event */ | ||
48 | BFA_LPORT_AEN_NEW_STANDARD = 8, /* VPort created event */ | ||
49 | BFA_LPORT_AEN_DELETE_STANDARD = 9, /* VPort deleted event */ | ||
50 | BFA_LPORT_AEN_NPIV_DUP_WWN = 10, /* VPort configured with | ||
51 | * duplicate WWN event | ||
52 | */ | ||
53 | BFA_LPORT_AEN_NPIV_FABRIC_MAX = 11, /* Max NPIV in fabric/fport */ | ||
54 | BFA_LPORT_AEN_NPIV_UNKNOWN = 12, /* Unknown NPIV Error code event */ | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | * BFA AEN event data structure | ||
59 | */ | ||
60 | struct bfa_lport_aen_data_s { | ||
61 | u16 vf_id; /* vf_id of this logical port */ | ||
62 | u16 rsvd; | ||
63 | enum bfa_port_role roles; /* Logical port mode,IM/TM/IP etc */ | ||
64 | wwn_t ppwwn; /* WWN of its physical port */ | ||
65 | wwn_t lpwwn; /* WWN of this logical port */ | ||
66 | }; | ||
67 | |||
68 | #endif /* __BFA_DEFS_LPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h new file mode 100644 index 000000000000..13fd4ab6aae2 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_mfg.h | |||
@@ -0,0 +1,58 @@ | |||
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 | #ifndef __BFA_DEFS_MFG_H__ | ||
18 | #define __BFA_DEFS_MFG_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | |||
22 | /** | ||
23 | * Manufacturing block version | ||
24 | */ | ||
25 | #define BFA_MFG_VERSION 1 | ||
26 | |||
27 | /** | ||
28 | * Manufacturing block format | ||
29 | */ | ||
30 | #define BFA_MFG_SERIALNUM_SIZE 11 | ||
31 | #define BFA_MFG_PARTNUM_SIZE 14 | ||
32 | #define BFA_MFG_SUPPLIER_ID_SIZE 10 | ||
33 | #define BFA_MFG_SUPPLIER_PARTNUM_SIZE 20 | ||
34 | #define BFA_MFG_SUPPLIER_SERIALNUM_SIZE 20 | ||
35 | #define BFA_MFG_SUPPLIER_REVISION_SIZE 4 | ||
36 | #define STRSZ(_n) (((_n) + 4) & ~3) | ||
37 | |||
38 | /** | ||
39 | * VPD data length | ||
40 | */ | ||
41 | #define BFA_MFG_VPD_LEN 256 | ||
42 | |||
43 | /** | ||
44 | * All numerical fields are in big-endian format. | ||
45 | */ | ||
46 | struct bfa_mfg_vpd_s { | ||
47 | u8 version; /* vpd data version */ | ||
48 | u8 vpd_sig[3]; /* characters 'V', 'P', 'D' */ | ||
49 | u8 chksum; /* u8 checksum */ | ||
50 | u8 vendor; /* vendor */ | ||
51 | u8 len; /* vpd data length excluding header */ | ||
52 | u8 rsv; | ||
53 | u8 data[BFA_MFG_VPD_LEN]; /* vpd data */ | ||
54 | }; | ||
55 | |||
56 | #pragma pack(1) | ||
57 | |||
58 | #endif /* __BFA_DEFS_MFG_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pci.h b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h new file mode 100644 index 000000000000..c9b83321694b --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pci.h | |||
@@ -0,0 +1,41 @@ | |||
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 | #ifndef __BFA_DEFS_PCI_H__ | ||
19 | #define __BFA_DEFS_PCI_H__ | ||
20 | |||
21 | /** | ||
22 | * PCI device and vendor ID information | ||
23 | */ | ||
24 | enum { | ||
25 | BFA_PCI_VENDOR_ID_BROCADE = 0x1657, | ||
26 | BFA_PCI_DEVICE_ID_FC_8G2P = 0x13, | ||
27 | BFA_PCI_DEVICE_ID_FC_8G1P = 0x17, | ||
28 | BFA_PCI_DEVICE_ID_CT = 0x14, | ||
29 | }; | ||
30 | |||
31 | /** | ||
32 | * PCI sub-system device and vendor ID information | ||
33 | */ | ||
34 | enum { | ||
35 | BFA_PCI_FCOE_SSDEVICE_ID = 0x14, | ||
36 | }; | ||
37 | |||
38 | #define BFA_PCI_ACCESS_RANGES 1 /* Maximum number of device address ranges | ||
39 | * mapped through different BAR(s). */ | ||
40 | |||
41 | #endif /* __BFA_DEFS_PCI_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pm.h b/drivers/scsi/bfa/include/defs/bfa_defs_pm.h new file mode 100644 index 000000000000..e8d6d959006e --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pm.h | |||
@@ -0,0 +1,33 @@ | |||
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 | #ifndef __BFA_DEFS_PM_H__ | ||
19 | #define __BFA_DEFS_PM_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | |||
23 | /** | ||
24 | * BFA power management device states | ||
25 | */ | ||
26 | enum bfa_pm_ds { | ||
27 | BFA_PM_DS_D0 = 0, /* full power mode */ | ||
28 | BFA_PM_DS_D1 = 1, /* power save state 1 */ | ||
29 | BFA_PM_DS_D2 = 2, /* power save state 2 */ | ||
30 | BFA_PM_DS_D3 = 3, /* power off state */ | ||
31 | }; | ||
32 | |||
33 | #endif /* __BFA_DEFS_PM_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pom.h b/drivers/scsi/bfa/include/defs/bfa_defs_pom.h new file mode 100644 index 000000000000..d9fa278472b7 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pom.h | |||
@@ -0,0 +1,56 @@ | |||
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 | #ifndef __BFA_DEFS_POM_H__ | ||
18 | #define __BFA_DEFS_POM_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | #include <defs/bfa_defs_types.h> | ||
22 | |||
23 | /** | ||
24 | * POM health status levels for each attributes. | ||
25 | */ | ||
26 | enum bfa_pom_entry_health { | ||
27 | BFA_POM_HEALTH_NOINFO = 1, /* no information */ | ||
28 | BFA_POM_HEALTH_NORMAL = 2, /* health is normal */ | ||
29 | BFA_POM_HEALTH_WARNING = 3, /* warning level */ | ||
30 | BFA_POM_HEALTH_ALARM = 4, /* alarming level */ | ||
31 | }; | ||
32 | |||
33 | /** | ||
34 | * Reading of temperature/voltage/current/power | ||
35 | */ | ||
36 | struct bfa_pom_entry_s { | ||
37 | enum bfa_pom_entry_health health; /* POM entry health */ | ||
38 | u32 curr_value; /* current value */ | ||
39 | u32 thr_warn_high; /* threshold warning high */ | ||
40 | u32 thr_warn_low; /* threshold warning low */ | ||
41 | u32 thr_alarm_low; /* threshold alaram low */ | ||
42 | u32 thr_alarm_high; /* threshold alarm high */ | ||
43 | }; | ||
44 | |||
45 | /** | ||
46 | * POM attributes | ||
47 | */ | ||
48 | struct bfa_pom_attr_s { | ||
49 | struct bfa_pom_entry_s temperature; /* centigrade */ | ||
50 | struct bfa_pom_entry_s voltage; /* volts */ | ||
51 | struct bfa_pom_entry_s curr; /* milli amps */ | ||
52 | struct bfa_pom_entry_s txpower; /* micro watts */ | ||
53 | struct bfa_pom_entry_s rxpower; /* micro watts */ | ||
54 | }; | ||
55 | |||
56 | #endif /* __BFA_DEFS_POM_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_port.h b/drivers/scsi/bfa/include/defs/bfa_defs_port.h new file mode 100644 index 000000000000..de0696c81bc4 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_port.h | |||
@@ -0,0 +1,245 @@ | |||
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 | #ifndef __BFA_DEFS_PORT_H__ | ||
19 | #define __BFA_DEFS_PORT_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include <protocol/types.h> | ||
23 | #include <defs/bfa_defs_pport.h> | ||
24 | #include <defs/bfa_defs_ioc.h> | ||
25 | |||
26 | #define BFA_FCS_FABRIC_IPADDR_SZ 16 | ||
27 | |||
28 | /** | ||
29 | * symbolic names for base port/virtual port | ||
30 | */ | ||
31 | #define BFA_SYMNAME_MAXLEN 128 /* vmware/windows uses 128 bytes */ | ||
32 | struct bfa_port_symname_s { | ||
33 | char symname[BFA_SYMNAME_MAXLEN]; | ||
34 | }; | ||
35 | |||
36 | /** | ||
37 | * Roles of FCS port: | ||
38 | * - FCP IM and FCP TM roles cannot be enabled together for a FCS port | ||
39 | * - Create multiple ports if both IM and TM functions required. | ||
40 | * - Atleast one role must be specified. | ||
41 | */ | ||
42 | enum bfa_port_role { | ||
43 | BFA_PORT_ROLE_FCP_IM = 0x01, /* FCP initiator role */ | ||
44 | BFA_PORT_ROLE_FCP_TM = 0x02, /* FCP target role */ | ||
45 | BFA_PORT_ROLE_FCP_IPFC = 0x04, /* IP over FC role */ | ||
46 | BFA_PORT_ROLE_FCP_MAX = BFA_PORT_ROLE_FCP_IPFC | BFA_PORT_ROLE_FCP_IM | ||
47 | }; | ||
48 | |||
49 | /** | ||
50 | * FCS port configuration. | ||
51 | */ | ||
52 | struct bfa_port_cfg_s { | ||
53 | wwn_t pwwn; /* port wwn */ | ||
54 | wwn_t nwwn; /* node wwn */ | ||
55 | struct bfa_port_symname_s sym_name; /* vm port symbolic name */ | ||
56 | enum bfa_port_role roles; /* FCS port roles */ | ||
57 | u32 rsvd; | ||
58 | u8 tag[16]; /* opaque tag from application */ | ||
59 | }; | ||
60 | |||
61 | /** | ||
62 | * FCS port states | ||
63 | */ | ||
64 | enum bfa_port_state { | ||
65 | BFA_PORT_UNINIT = 0, /* PORT is not yet initialized */ | ||
66 | BFA_PORT_FDISC = 1, /* FDISC is in progress */ | ||
67 | BFA_PORT_ONLINE = 2, /* login to fabric is complete */ | ||
68 | BFA_PORT_OFFLINE = 3, /* No login to fabric */ | ||
69 | }; | ||
70 | |||
71 | /** | ||
72 | * FCS port type. Required for VmWare. | ||
73 | */ | ||
74 | enum bfa_port_type { | ||
75 | BFA_PORT_TYPE_PHYSICAL = 0, | ||
76 | BFA_PORT_TYPE_VIRTUAL, | ||
77 | }; | ||
78 | |||
79 | /** | ||
80 | * FCS port offline reason. Required for VmWare. | ||
81 | */ | ||
82 | enum bfa_port_offline_reason { | ||
83 | BFA_PORT_OFFLINE_UNKNOWN = 0, | ||
84 | BFA_PORT_OFFLINE_LINKDOWN, | ||
85 | BFA_PORT_OFFLINE_FAB_UNSUPPORTED, /* NPIV not supported by the | ||
86 | * fabric */ | ||
87 | BFA_PORT_OFFLINE_FAB_NORESOURCES, | ||
88 | BFA_PORT_OFFLINE_FAB_LOGOUT, | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * FCS lport info. Required for VmWare. | ||
93 | */ | ||
94 | struct bfa_port_info_s { | ||
95 | u8 port_type; /* bfa_port_type_t : physical or | ||
96 | * virtual */ | ||
97 | u8 port_state; /* one of bfa_port_state values */ | ||
98 | u8 offline_reason; /* one of bfa_port_offline_reason_t | ||
99 | * values */ | ||
100 | wwn_t port_wwn; | ||
101 | wwn_t node_wwn; | ||
102 | |||
103 | /* | ||
104 | * following 4 feilds are valid for Physical Ports only | ||
105 | */ | ||
106 | u32 max_vports_supp; /* Max supported vports */ | ||
107 | u32 num_vports_inuse; /* Num of in use vports */ | ||
108 | u32 max_rports_supp; /* Max supported rports */ | ||
109 | u32 num_rports_inuse; /* Num of doscovered rports */ | ||
110 | |||
111 | }; | ||
112 | |||
113 | /** | ||
114 | * FCS port statistics | ||
115 | */ | ||
116 | struct bfa_port_stats_s { | ||
117 | u32 ns_plogi_sent; | ||
118 | u32 ns_plogi_rsp_err; | ||
119 | u32 ns_plogi_acc_err; | ||
120 | u32 ns_plogi_accepts; | ||
121 | u32 ns_rejects; /* NS command rejects */ | ||
122 | u32 ns_plogi_unknown_rsp; | ||
123 | u32 ns_plogi_alloc_wait; | ||
124 | |||
125 | u32 ns_retries; /* NS command retries */ | ||
126 | u32 ns_timeouts; /* NS command timeouts */ | ||
127 | |||
128 | u32 ns_rspnid_sent; | ||
129 | u32 ns_rspnid_accepts; | ||
130 | u32 ns_rspnid_rsp_err; | ||
131 | u32 ns_rspnid_rejects; | ||
132 | u32 ns_rspnid_alloc_wait; | ||
133 | |||
134 | u32 ns_rftid_sent; | ||
135 | u32 ns_rftid_accepts; | ||
136 | u32 ns_rftid_rsp_err; | ||
137 | u32 ns_rftid_rejects; | ||
138 | u32 ns_rftid_alloc_wait; | ||
139 | |||
140 | u32 ns_rffid_sent; | ||
141 | u32 ns_rffid_accepts; | ||
142 | u32 ns_rffid_rsp_err; | ||
143 | u32 ns_rffid_rejects; | ||
144 | u32 ns_rffid_alloc_wait; | ||
145 | |||
146 | u32 ns_gidft_sent; | ||
147 | u32 ns_gidft_accepts; | ||
148 | u32 ns_gidft_rsp_err; | ||
149 | u32 ns_gidft_rejects; | ||
150 | u32 ns_gidft_unknown_rsp; | ||
151 | u32 ns_gidft_alloc_wait; | ||
152 | |||
153 | /* | ||
154 | * Mgmt Server stats | ||
155 | */ | ||
156 | u32 ms_retries; /* MS command retries */ | ||
157 | u32 ms_timeouts; /* MS command timeouts */ | ||
158 | u32 ms_plogi_sent; | ||
159 | u32 ms_plogi_rsp_err; | ||
160 | u32 ms_plogi_acc_err; | ||
161 | u32 ms_plogi_accepts; | ||
162 | u32 ms_rejects; /* NS command rejects */ | ||
163 | u32 ms_plogi_unknown_rsp; | ||
164 | u32 ms_plogi_alloc_wait; | ||
165 | |||
166 | u32 num_rscn; /* Num of RSCN received */ | ||
167 | u32 num_portid_rscn;/* Num portid format RSCN | ||
168 | * received */ | ||
169 | |||
170 | u32 uf_recvs; /* unsolicited recv frames */ | ||
171 | u32 uf_recv_drops; /* dropped received frames */ | ||
172 | |||
173 | u32 rsvd; /* padding for 64 bit alignment */ | ||
174 | }; | ||
175 | |||
176 | /** | ||
177 | * BFA port attribute returned in queries | ||
178 | */ | ||
179 | struct bfa_port_attr_s { | ||
180 | enum bfa_port_state state; /* port state */ | ||
181 | u32 pid; /* port ID */ | ||
182 | struct bfa_port_cfg_s port_cfg; /* port configuration */ | ||
183 | enum bfa_pport_type port_type; /* current topology */ | ||
184 | u32 loopback; /* cable is externally looped back */ | ||
185 | wwn_t fabric_name; /* attached switch's nwwn */ | ||
186 | u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /* attached | ||
187 | * fabric's ip addr */ | ||
188 | }; | ||
189 | |||
190 | /** | ||
191 | * BFA physical port Level events | ||
192 | * Arguments below are in BFAL context from Mgmt | ||
193 | * BFA_PORT_AEN_ONLINE: [in]: pwwn [out]: pwwn | ||
194 | * BFA_PORT_AEN_OFFLINE: [in]: pwwn [out]: pwwn | ||
195 | * BFA_PORT_AEN_RLIR: [in]: None [out]: pwwn, rlir_data, rlir_len | ||
196 | * BFA_PORT_AEN_SFP_INSERT: [in]: pwwn [out]: port_id, pwwn | ||
197 | * BFA_PORT_AEN_SFP_REMOVE: [in]: pwwn [out]: port_id, pwwn | ||
198 | * BFA_PORT_AEN_SFP_POM: [in]: pwwn [out]: level, port_id, pwwn | ||
199 | * BFA_PORT_AEN_ENABLE: [in]: pwwn [out]: pwwn | ||
200 | * BFA_PORT_AEN_DISABLE: [in]: pwwn [out]: pwwn | ||
201 | * BFA_PORT_AEN_AUTH_ON: [in]: pwwn [out]: pwwn | ||
202 | * BFA_PORT_AEN_AUTH_OFF: [in]: pwwn [out]: pwwn | ||
203 | * BFA_PORT_AEN_DISCONNECT: [in]: pwwn [out]: pwwn | ||
204 | * BFA_PORT_AEN_QOS_NEG: [in]: pwwn [out]: pwwn | ||
205 | * BFA_PORT_AEN_FABRIC_NAME_CHANGE: [in]: pwwn, [out]: pwwn, fwwn | ||
206 | * | ||
207 | */ | ||
208 | enum bfa_port_aen_event { | ||
209 | BFA_PORT_AEN_ONLINE = 1, /* Physical Port online event */ | ||
210 | BFA_PORT_AEN_OFFLINE = 2, /* Physical Port offline event */ | ||
211 | BFA_PORT_AEN_RLIR = 3, /* RLIR event, not supported */ | ||
212 | BFA_PORT_AEN_SFP_INSERT = 4, /* SFP inserted event */ | ||
213 | BFA_PORT_AEN_SFP_REMOVE = 5, /* SFP removed event */ | ||
214 | BFA_PORT_AEN_SFP_POM = 6, /* SFP POM event */ | ||
215 | BFA_PORT_AEN_ENABLE = 7, /* Physical Port enable event */ | ||
216 | BFA_PORT_AEN_DISABLE = 8, /* Physical Port disable event */ | ||
217 | BFA_PORT_AEN_AUTH_ON = 9, /* Physical Port auth success event */ | ||
218 | BFA_PORT_AEN_AUTH_OFF = 10, /* Physical Port auth fail event */ | ||
219 | BFA_PORT_AEN_DISCONNECT = 11, /* Physical Port disconnect event */ | ||
220 | BFA_PORT_AEN_QOS_NEG = 12, /* Base Port QOS negotiation event */ | ||
221 | BFA_PORT_AEN_FABRIC_NAME_CHANGE = 13, /* Fabric Name/WWN change | ||
222 | * event */ | ||
223 | BFA_PORT_AEN_SFP_ACCESS_ERROR = 14, /* SFP read error event */ | ||
224 | BFA_PORT_AEN_SFP_UNSUPPORT = 15, /* Unsupported SFP event */ | ||
225 | }; | ||
226 | |||
227 | enum bfa_port_aen_sfp_pom { | ||
228 | BFA_PORT_AEN_SFP_POM_GREEN = 1, /* Normal */ | ||
229 | BFA_PORT_AEN_SFP_POM_AMBER = 2, /* Warning */ | ||
230 | BFA_PORT_AEN_SFP_POM_RED = 3, /* Critical */ | ||
231 | BFA_PORT_AEN_SFP_POM_MAX = BFA_PORT_AEN_SFP_POM_RED | ||
232 | }; | ||
233 | |||
234 | struct bfa_port_aen_data_s { | ||
235 | enum bfa_ioc_type_e ioc_type; | ||
236 | wwn_t pwwn; /* WWN of the physical port */ | ||
237 | wwn_t fwwn; /* WWN of the fabric port */ | ||
238 | mac_t mac; /* MAC addres of the ethernet port, | ||
239 | * applicable to CNA port only */ | ||
240 | int phy_port_num; /*! For SFP related events */ | ||
241 | enum bfa_port_aen_sfp_pom level; /* Only transitions will | ||
242 | * be informed */ | ||
243 | }; | ||
244 | |||
245 | #endif /* __BFA_DEFS_PORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_pport.h b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h new file mode 100644 index 000000000000..a000bc4e2d4a --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_pport.h | |||
@@ -0,0 +1,383 @@ | |||
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 | #ifndef __BFA_DEFS_PPORT_H__ | ||
19 | #define __BFA_DEFS_PPORT_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include <protocol/fc.h> | ||
23 | #include <defs/bfa_defs_types.h> | ||
24 | #include <defs/bfa_defs_qos.h> | ||
25 | #include <cna/pstats/phyport_defs.h> | ||
26 | |||
27 | /* Modify char* port_stt[] in bfal_port.c if a new state was added */ | ||
28 | enum bfa_pport_states { | ||
29 | BFA_PPORT_ST_UNINIT = 1, | ||
30 | BFA_PPORT_ST_ENABLING_QWAIT = 2, | ||
31 | BFA_PPORT_ST_ENABLING = 3, | ||
32 | BFA_PPORT_ST_LINKDOWN = 4, | ||
33 | BFA_PPORT_ST_LINKUP = 5, | ||
34 | BFA_PPORT_ST_DISABLING_QWAIT = 6, | ||
35 | BFA_PPORT_ST_DISABLING = 7, | ||
36 | BFA_PPORT_ST_DISABLED = 8, | ||
37 | BFA_PPORT_ST_STOPPED = 9, | ||
38 | BFA_PPORT_ST_IOCDOWN = 10, | ||
39 | BFA_PPORT_ST_IOCDIS = 11, | ||
40 | BFA_PPORT_ST_FWMISMATCH = 12, | ||
41 | BFA_PPORT_ST_MAX_STATE, | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * Port speed settings. Each specific speed is a bit field. Use multiple | ||
46 | * bits to specify speeds to be selected for auto-negotiation. | ||
47 | */ | ||
48 | enum bfa_pport_speed { | ||
49 | BFA_PPORT_SPEED_UNKNOWN = 0, | ||
50 | BFA_PPORT_SPEED_1GBPS = 1, | ||
51 | BFA_PPORT_SPEED_2GBPS = 2, | ||
52 | BFA_PPORT_SPEED_4GBPS = 4, | ||
53 | BFA_PPORT_SPEED_8GBPS = 8, | ||
54 | BFA_PPORT_SPEED_10GBPS = 10, | ||
55 | BFA_PPORT_SPEED_AUTO = | ||
56 | (BFA_PPORT_SPEED_1GBPS | BFA_PPORT_SPEED_2GBPS | | ||
57 | BFA_PPORT_SPEED_4GBPS | BFA_PPORT_SPEED_8GBPS), | ||
58 | }; | ||
59 | |||
60 | /** | ||
61 | * Port operational type (in sync with SNIA port type). | ||
62 | */ | ||
63 | enum bfa_pport_type { | ||
64 | BFA_PPORT_TYPE_UNKNOWN = 1, /* port type is unkown */ | ||
65 | BFA_PPORT_TYPE_TRUNKED = 2, /* Trunked mode */ | ||
66 | BFA_PPORT_TYPE_NPORT = 5, /* P2P with switched fabric */ | ||
67 | BFA_PPORT_TYPE_NLPORT = 6, /* public loop */ | ||
68 | BFA_PPORT_TYPE_LPORT = 20, /* private loop */ | ||
69 | BFA_PPORT_TYPE_P2P = 21, /* P2P with no switched fabric */ | ||
70 | BFA_PPORT_TYPE_VPORT = 22, /* NPIV - virtual port */ | ||
71 | }; | ||
72 | |||
73 | /** | ||
74 | * Port topology setting. A port's topology and fabric login status | ||
75 | * determine its operational type. | ||
76 | */ | ||
77 | enum bfa_pport_topology { | ||
78 | BFA_PPORT_TOPOLOGY_NONE = 0, /* No valid topology */ | ||
79 | BFA_PPORT_TOPOLOGY_P2P = 1, /* P2P only */ | ||
80 | BFA_PPORT_TOPOLOGY_LOOP = 2, /* LOOP topology */ | ||
81 | BFA_PPORT_TOPOLOGY_AUTO = 3, /* auto topology selection */ | ||
82 | }; | ||
83 | |||
84 | /** | ||
85 | * Physical port loopback types. | ||
86 | */ | ||
87 | enum bfa_pport_opmode { | ||
88 | BFA_PPORT_OPMODE_NORMAL = 0x00, /* normal non-loopback mode */ | ||
89 | BFA_PPORT_OPMODE_LB_INT = 0x01, /* internal loop back */ | ||
90 | BFA_PPORT_OPMODE_LB_SLW = 0x02, /* serial link wrapback (serdes) */ | ||
91 | BFA_PPORT_OPMODE_LB_EXT = 0x04, /* external loop back (serdes) */ | ||
92 | BFA_PPORT_OPMODE_LB_CBL = 0x08, /* cabled loop back */ | ||
93 | BFA_PPORT_OPMODE_LB_NLINT = 0x20, /* NL_Port internal loopback */ | ||
94 | }; | ||
95 | |||
96 | #define BFA_PPORT_OPMODE_LB_HARD(_mode) \ | ||
97 | ((_mode == BFA_PPORT_OPMODE_LB_INT) || \ | ||
98 | (_mode == BFA_PPORT_OPMODE_LB_SLW) || \ | ||
99 | (_mode == BFA_PPORT_OPMODE_LB_EXT)) | ||
100 | |||
101 | /** | ||
102 | Port State (in sync with SNIA port state). | ||
103 | */ | ||
104 | enum bfa_pport_snia_state { | ||
105 | BFA_PPORT_STATE_UNKNOWN = 1, /* port is not initialized */ | ||
106 | BFA_PPORT_STATE_ONLINE = 2, /* port is ONLINE */ | ||
107 | BFA_PPORT_STATE_DISABLED = 3, /* port is disabled by user */ | ||
108 | BFA_PPORT_STATE_BYPASSED = 4, /* port is bypassed (in LOOP) */ | ||
109 | BFA_PPORT_STATE_DIAG = 5, /* port diagnostics is active */ | ||
110 | BFA_PPORT_STATE_LINKDOWN = 6, /* link is down */ | ||
111 | BFA_PPORT_STATE_LOOPBACK = 8, /* port is looped back */ | ||
112 | }; | ||
113 | |||
114 | /** | ||
115 | * Port link state | ||
116 | */ | ||
117 | enum bfa_pport_linkstate { | ||
118 | BFA_PPORT_LINKUP = 1, /* Physical port/Trunk link up */ | ||
119 | BFA_PPORT_LINKDOWN = 2, /* Physical port/Trunk link down */ | ||
120 | BFA_PPORT_TRUNK_LINKDOWN = 3, /* Trunk link down (new tmaster) */ | ||
121 | }; | ||
122 | |||
123 | /** | ||
124 | * Port link state event | ||
125 | */ | ||
126 | #define bfa_pport_event_t enum bfa_pport_linkstate | ||
127 | |||
128 | /** | ||
129 | * Port link state reason code | ||
130 | */ | ||
131 | enum bfa_pport_linkstate_rsn { | ||
132 | BFA_PPORT_LINKSTATE_RSN_NONE = 0, | ||
133 | BFA_PPORT_LINKSTATE_RSN_DISABLED = 1, | ||
134 | BFA_PPORT_LINKSTATE_RSN_RX_NOS = 2, | ||
135 | BFA_PPORT_LINKSTATE_RSN_RX_OLS = 3, | ||
136 | BFA_PPORT_LINKSTATE_RSN_RX_LIP = 4, | ||
137 | BFA_PPORT_LINKSTATE_RSN_RX_LIPF7 = 5, | ||
138 | BFA_PPORT_LINKSTATE_RSN_SFP_REMOVED = 6, | ||
139 | BFA_PPORT_LINKSTATE_RSN_PORT_FAULT = 7, | ||
140 | BFA_PPORT_LINKSTATE_RSN_RX_LOS = 8, | ||
141 | BFA_PPORT_LINKSTATE_RSN_LOCAL_FAULT = 9, | ||
142 | BFA_PPORT_LINKSTATE_RSN_REMOTE_FAULT = 10, | ||
143 | BFA_PPORT_LINKSTATE_RSN_TIMEOUT = 11, | ||
144 | |||
145 | |||
146 | |||
147 | /* CEE related reason codes/errors */ | ||
148 | CEE_LLDP_INFO_AGED_OUT = 20, | ||
149 | CEE_LLDP_SHUTDOWN_TLV_RCVD = 21, | ||
150 | CEE_PEER_NOT_ADVERTISE_DCBX = 22, | ||
151 | CEE_PEER_NOT_ADVERTISE_PG = 23, | ||
152 | CEE_PEER_NOT_ADVERTISE_PFC = 24, | ||
153 | CEE_PEER_NOT_ADVERTISE_FCOE = 25, | ||
154 | CEE_PG_NOT_COMPATIBLE = 26, | ||
155 | CEE_PFC_NOT_COMPATIBLE = 27, | ||
156 | CEE_FCOE_NOT_COMPATIBLE = 28, | ||
157 | CEE_BAD_PG_RCVD = 29, | ||
158 | CEE_BAD_BW_RCVD = 30, | ||
159 | CEE_BAD_PFC_RCVD = 31, | ||
160 | CEE_BAD_FCOE_PRI_RCVD = 32, | ||
161 | CEE_FCOE_PRI_PFC_OFF = 33, | ||
162 | CEE_DUP_CONTROL_TLV_RCVD = 34, | ||
163 | CEE_DUP_FEAT_TLV_RCVD = 35, | ||
164 | CEE_APPLY_NEW_CFG = 36, /* reason, not an error */ | ||
165 | CEE_PROTOCOL_INIT = 37, /* reason, not an error */ | ||
166 | CEE_PHY_LINK_DOWN = 38, | ||
167 | CEE_LLS_FCOE_ABSENT = 39, | ||
168 | CEE_LLS_FCOE_DOWN = 40 | ||
169 | }; | ||
170 | |||
171 | /** | ||
172 | * Default Target Rate Limiting Speed. | ||
173 | */ | ||
174 | #define BFA_PPORT_DEF_TRL_SPEED BFA_PPORT_SPEED_1GBPS | ||
175 | |||
176 | /** | ||
177 | * Physical port configuration | ||
178 | */ | ||
179 | struct bfa_pport_cfg_s { | ||
180 | u8 topology; /* bfa_pport_topology */ | ||
181 | u8 speed; /* enum bfa_pport_speed */ | ||
182 | u8 trunked; /* trunked or not */ | ||
183 | u8 qos_enabled; /* qos enabled or not */ | ||
184 | u8 trunk_ports; /* bitmap of trunked ports */ | ||
185 | u8 cfg_hardalpa; /* is hard alpa configured */ | ||
186 | u16 maxfrsize; /* maximum frame size */ | ||
187 | u8 hardalpa; /* configured hard alpa */ | ||
188 | u8 rx_bbcredit; /* receive buffer credits */ | ||
189 | u8 tx_bbcredit; /* transmit buffer credits */ | ||
190 | u8 ratelimit; /* ratelimit enabled or not */ | ||
191 | u8 trl_def_speed; /* ratelimit default speed */ | ||
192 | u8 rsvd[3]; | ||
193 | u16 path_tov; /* device path timeout */ | ||
194 | u16 q_depth; /* SCSI Queue depth */ | ||
195 | }; | ||
196 | |||
197 | /** | ||
198 | * Port attribute values. | ||
199 | */ | ||
200 | struct bfa_pport_attr_s { | ||
201 | /* | ||
202 | * Static fields | ||
203 | */ | ||
204 | wwn_t nwwn; /* node wwn */ | ||
205 | wwn_t pwwn; /* port wwn */ | ||
206 | enum fc_cos cos_supported; /* supported class of services */ | ||
207 | u32 rsvd; | ||
208 | struct fc_symname_s port_symname; /* port symbolic name */ | ||
209 | enum bfa_pport_speed speed_supported; /* supported speeds */ | ||
210 | bfa_boolean_t pbind_enabled; /* Will be set if Persistent binding | ||
211 | * enabled. Relevant only in Windows | ||
212 | */ | ||
213 | |||
214 | /* | ||
215 | * Configured values | ||
216 | */ | ||
217 | struct bfa_pport_cfg_s pport_cfg; /* pport cfg */ | ||
218 | |||
219 | /* | ||
220 | * Dynamic field - info from BFA | ||
221 | */ | ||
222 | enum bfa_pport_states port_state; /* current port state */ | ||
223 | enum bfa_pport_speed speed; /* current speed */ | ||
224 | enum bfa_pport_topology topology; /* current topology */ | ||
225 | bfa_boolean_t beacon; /* current beacon status */ | ||
226 | bfa_boolean_t link_e2e_beacon;/* set if link beacon on */ | ||
227 | bfa_boolean_t plog_enabled; /* set if portlog is enabled*/ | ||
228 | |||
229 | /* | ||
230 | * Dynamic field - info from FCS | ||
231 | */ | ||
232 | u32 pid; /* port ID */ | ||
233 | enum bfa_pport_type port_type; /* current topology */ | ||
234 | u32 loopback; /* external loopback */ | ||
235 | u32 rsvd1; | ||
236 | u32 rsvd2; /* padding for 64 bit */ | ||
237 | }; | ||
238 | |||
239 | /** | ||
240 | * FC Port statistics. | ||
241 | */ | ||
242 | struct bfa_pport_fc_stats_s { | ||
243 | u64 secs_reset; /* seconds since stats is reset */ | ||
244 | u64 tx_frames; /* transmitted frames */ | ||
245 | u64 tx_words; /* transmitted words */ | ||
246 | u64 rx_frames; /* received frames */ | ||
247 | u64 rx_words; /* received words */ | ||
248 | u64 lip_count; /* LIPs seen */ | ||
249 | u64 nos_count; /* NOS count */ | ||
250 | u64 error_frames; /* errored frames (sent?) */ | ||
251 | u64 dropped_frames; /* dropped frames */ | ||
252 | u64 link_failures; /* link failure count */ | ||
253 | u64 loss_of_syncs; /* loss of sync count */ | ||
254 | u64 loss_of_signals;/* loss of signal count */ | ||
255 | u64 primseq_errs; /* primitive sequence protocol */ | ||
256 | u64 bad_os_count; /* invalid ordered set */ | ||
257 | u64 err_enc_out; /* Encoding error outside frame */ | ||
258 | u64 invalid_crcs; /* frames received with invalid CRC*/ | ||
259 | u64 undersized_frm; /* undersized frames */ | ||
260 | u64 oversized_frm; /* oversized frames */ | ||
261 | u64 bad_eof_frm; /* frames with bad EOF */ | ||
262 | struct bfa_qos_stats_s qos_stats; /* QoS statistics */ | ||
263 | }; | ||
264 | |||
265 | /** | ||
266 | * Eth Port statistics. | ||
267 | */ | ||
268 | struct bfa_pport_eth_stats_s { | ||
269 | u64 secs_reset; /* seconds since stats is reset */ | ||
270 | u64 frame_64; /* both rx and tx counter */ | ||
271 | u64 frame_65_127; /* both rx and tx counter */ | ||
272 | u64 frame_128_255; /* both rx and tx counter */ | ||
273 | u64 frame_256_511; /* both rx and tx counter */ | ||
274 | u64 frame_512_1023; /* both rx and tx counter */ | ||
275 | u64 frame_1024_1518; /* both rx and tx counter */ | ||
276 | u64 frame_1519_1522; /* both rx and tx counter */ | ||
277 | |||
278 | u64 tx_bytes; | ||
279 | u64 tx_packets; | ||
280 | u64 tx_mcast_packets; | ||
281 | u64 tx_bcast_packets; | ||
282 | u64 tx_control_frame; | ||
283 | u64 tx_drop; | ||
284 | u64 tx_jabber; | ||
285 | u64 tx_fcs_error; | ||
286 | u64 tx_fragments; | ||
287 | |||
288 | u64 rx_bytes; | ||
289 | u64 rx_packets; | ||
290 | u64 rx_mcast_packets; | ||
291 | u64 rx_bcast_packets; | ||
292 | u64 rx_control_frames; | ||
293 | u64 rx_unknown_opcode; | ||
294 | u64 rx_drop; | ||
295 | u64 rx_jabber; | ||
296 | u64 rx_fcs_error; | ||
297 | u64 rx_alignment_error; | ||
298 | u64 rx_frame_length_error; | ||
299 | u64 rx_code_error; | ||
300 | u64 rx_fragments; | ||
301 | |||
302 | u64 rx_pause; /* BPC */ | ||
303 | u64 rx_zero_pause; /* BPC Pause cancellation */ | ||
304 | u64 tx_pause; /* BPC */ | ||
305 | u64 tx_zero_pause; /* BPC Pause cancellation */ | ||
306 | u64 rx_fcoe_pause; /* BPC */ | ||
307 | u64 rx_fcoe_zero_pause; /* BPC Pause cancellation */ | ||
308 | u64 tx_fcoe_pause; /* BPC */ | ||
309 | u64 tx_fcoe_zero_pause; /* BPC Pause cancellation */ | ||
310 | }; | ||
311 | |||
312 | /** | ||
313 | * Port statistics. | ||
314 | */ | ||
315 | union bfa_pport_stats_u { | ||
316 | struct bfa_pport_fc_stats_s fc; | ||
317 | struct bfa_pport_eth_stats_s eth; | ||
318 | }; | ||
319 | |||
320 | /** | ||
321 | * Port FCP mappings. | ||
322 | */ | ||
323 | struct bfa_pport_fcpmap_s { | ||
324 | char osdevname[256]; | ||
325 | u32 bus; | ||
326 | u32 target; | ||
327 | u32 oslun; | ||
328 | u32 fcid; | ||
329 | wwn_t nwwn; | ||
330 | wwn_t pwwn; | ||
331 | u64 fcplun; | ||
332 | char luid[256]; | ||
333 | }; | ||
334 | |||
335 | /** | ||
336 | * Port RNID info. | ||
337 | */ | ||
338 | struct bfa_pport_rnid_s { | ||
339 | wwn_t wwn; | ||
340 | u32 unittype; | ||
341 | u32 portid; | ||
342 | u32 attached_nodes_num; | ||
343 | u16 ip_version; | ||
344 | u16 udp_port; | ||
345 | u8 ipaddr[16]; | ||
346 | u16 rsvd; | ||
347 | u16 topologydiscoveryflags; | ||
348 | }; | ||
349 | |||
350 | /** | ||
351 | * Link state information | ||
352 | */ | ||
353 | struct bfa_pport_link_s { | ||
354 | u8 linkstate; /* Link state bfa_pport_linkstate */ | ||
355 | u8 linkstate_rsn; /* bfa_pport_linkstate_rsn_t */ | ||
356 | u8 topology; /* P2P/LOOP bfa_pport_topology */ | ||
357 | u8 speed; /* Link speed (1/2/4/8 G) */ | ||
358 | u32 linkstate_opt; /* Linkstate optional data (debug) */ | ||
359 | u8 trunked; /* Trunked or not (1 or 0) */ | ||
360 | u8 resvd[3]; | ||
361 | struct bfa_qos_attr_s qos_attr; /* QoS Attributes */ | ||
362 | struct bfa_qos_vc_attr_s qos_vc_attr; /* VC info from ELP */ | ||
363 | union { | ||
364 | struct { | ||
365 | u8 tmaster;/* Trunk Master or | ||
366 | * not (1 or 0) */ | ||
367 | u8 tlinks; /* Trunk links bitmap | ||
368 | * (linkup) */ | ||
369 | u8 resv1; /* Reserved */ | ||
370 | } trunk_info; | ||
371 | |||
372 | struct { | ||
373 | u8 myalpa; /* alpa claimed */ | ||
374 | u8 login_req; /* Login required or | ||
375 | * not (1 or 0) */ | ||
376 | u8 alpabm_val;/* alpa bitmap valid | ||
377 | * or not (1 or 0) */ | ||
378 | struct fc_alpabm_s alpabm; /* alpa bitmap */ | ||
379 | } loop_info; | ||
380 | } tl; | ||
381 | }; | ||
382 | |||
383 | #endif /* __BFA_DEFS_PPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_qos.h b/drivers/scsi/bfa/include/defs/bfa_defs_qos.h new file mode 100644 index 000000000000..aadbacd1d2d7 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_qos.h | |||
@@ -0,0 +1,99 @@ | |||
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 | #ifndef __BFA_DEFS_QOS_H__ | ||
19 | #define __BFA_DEFS_QOS_H__ | ||
20 | |||
21 | /** | ||
22 | * QoS states | ||
23 | */ | ||
24 | enum bfa_qos_state { | ||
25 | BFA_QOS_ONLINE = 1, /* QoS is online */ | ||
26 | BFA_QOS_OFFLINE = 2, /* QoS is offline */ | ||
27 | }; | ||
28 | |||
29 | |||
30 | /** | ||
31 | * QoS Priority levels. | ||
32 | */ | ||
33 | enum bfa_qos_priority { | ||
34 | BFA_QOS_UNKNOWN = 0, | ||
35 | BFA_QOS_HIGH = 1, /* QoS Priority Level High */ | ||
36 | BFA_QOS_MED = 2, /* QoS Priority Level Medium */ | ||
37 | BFA_QOS_LOW = 3, /* QoS Priority Level Low */ | ||
38 | }; | ||
39 | |||
40 | |||
41 | /** | ||
42 | * QoS bandwidth allocation for each priority level | ||
43 | */ | ||
44 | enum bfa_qos_bw_alloc { | ||
45 | BFA_QOS_BW_HIGH = 60, /* bandwidth allocation for High */ | ||
46 | BFA_QOS_BW_MED = 30, /* bandwidth allocation for Medium */ | ||
47 | BFA_QOS_BW_LOW = 10, /* bandwidth allocation for Low */ | ||
48 | }; | ||
49 | |||
50 | /** | ||
51 | * QoS attribute returned in QoS Query | ||
52 | */ | ||
53 | struct bfa_qos_attr_s { | ||
54 | enum bfa_qos_state state; /* QoS current state */ | ||
55 | u32 total_bb_cr; /* Total BB Credits */ | ||
56 | }; | ||
57 | |||
58 | /** | ||
59 | * These fields should be displayed only from the CLI. | ||
60 | * There will be a separate BFAL API (get_qos_vc_attr ?) | ||
61 | * to retrieve this. | ||
62 | * | ||
63 | */ | ||
64 | #define BFA_QOS_MAX_VC 16 | ||
65 | |||
66 | struct bfa_qos_vc_info_s { | ||
67 | u8 vc_credit; | ||
68 | u8 borrow_credit; | ||
69 | u8 priority; | ||
70 | u8 resvd; | ||
71 | }; | ||
72 | |||
73 | struct bfa_qos_vc_attr_s { | ||
74 | u16 total_vc_count; /* Total VC Count */ | ||
75 | u16 shared_credit; | ||
76 | u32 elp_opmode_flags; | ||
77 | struct bfa_qos_vc_info_s vc_info[BFA_QOS_MAX_VC]; /* as many as | ||
78 | * total_vc_count */ | ||
79 | }; | ||
80 | |||
81 | /** | ||
82 | * QoS statistics | ||
83 | */ | ||
84 | struct bfa_qos_stats_s { | ||
85 | u32 flogi_sent; /* QoS Flogi sent */ | ||
86 | u32 flogi_acc_recvd; /* QoS Flogi Acc received */ | ||
87 | u32 flogi_rjt_recvd; /* QoS Flogi rejects received */ | ||
88 | u32 flogi_retries; /* QoS Flogi retries */ | ||
89 | |||
90 | u32 elp_recvd; /* QoS ELP received */ | ||
91 | u32 elp_accepted; /* QoS ELP Accepted */ | ||
92 | u32 elp_rejected; /* QoS ELP rejected */ | ||
93 | u32 elp_dropped; /* QoS ELP dropped */ | ||
94 | |||
95 | u32 qos_rscn_recvd; /* QoS RSCN received */ | ||
96 | u32 rsvd; /* padding for 64 bit alignment */ | ||
97 | }; | ||
98 | |||
99 | #endif /* __BFA_DEFS_QOS_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_rport.h b/drivers/scsi/bfa/include/defs/bfa_defs_rport.h new file mode 100644 index 000000000000..e0af59d6d2f6 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_rport.h | |||
@@ -0,0 +1,199 @@ | |||
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 | #ifndef __BFA_DEFS_RPORT_H__ | ||
19 | #define __BFA_DEFS_RPORT_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include <protocol/types.h> | ||
23 | #include <defs/bfa_defs_pport.h> | ||
24 | #include <defs/bfa_defs_port.h> | ||
25 | #include <defs/bfa_defs_qos.h> | ||
26 | |||
27 | /** | ||
28 | * FCS remote port states | ||
29 | */ | ||
30 | enum bfa_rport_state { | ||
31 | BFA_RPORT_UNINIT = 0, /* PORT is not yet initialized */ | ||
32 | BFA_RPORT_OFFLINE = 1, /* rport is offline */ | ||
33 | BFA_RPORT_PLOGI = 2, /* PLOGI to rport is in progress */ | ||
34 | BFA_RPORT_ONLINE = 3, /* login to rport is complete */ | ||
35 | BFA_RPORT_PLOGI_RETRY = 4, /* retrying login to rport */ | ||
36 | BFA_RPORT_NSQUERY = 5, /* nameserver query */ | ||
37 | BFA_RPORT_ADISC = 6, /* ADISC authentication */ | ||
38 | BFA_RPORT_LOGO = 7, /* logging out with rport */ | ||
39 | BFA_RPORT_LOGORCV = 8, /* handling LOGO from rport */ | ||
40 | BFA_RPORT_NSDISC = 9, /* re-discover rport */ | ||
41 | }; | ||
42 | |||
43 | /** | ||
44 | * Rport Scsi Function : Initiator/Target. | ||
45 | */ | ||
46 | enum bfa_rport_function { | ||
47 | BFA_RPORT_INITIATOR = 0x01, /* SCSI Initiator */ | ||
48 | BFA_RPORT_TARGET = 0x02, /* SCSI Target */ | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * port/node symbolic names for rport | ||
53 | */ | ||
54 | #define BFA_RPORT_SYMNAME_MAXLEN 255 | ||
55 | struct bfa_rport_symname_s { | ||
56 | char symname[BFA_RPORT_SYMNAME_MAXLEN]; | ||
57 | }; | ||
58 | |||
59 | struct bfa_rport_hal_stats_s { | ||
60 | u32 sm_un_cr; /* uninit: create events */ | ||
61 | u32 sm_un_unexp; /* uninit: exception events */ | ||
62 | u32 sm_cr_on; /* created: online events */ | ||
63 | u32 sm_cr_del; /* created: delete events */ | ||
64 | u32 sm_cr_hwf; /* created: IOC down */ | ||
65 | u32 sm_cr_unexp; /* created: exception events */ | ||
66 | u32 sm_fwc_rsp; /* fw create: f/w responses */ | ||
67 | u32 sm_fwc_del; /* fw create: delete events */ | ||
68 | u32 sm_fwc_off; /* fw create: offline events */ | ||
69 | u32 sm_fwc_hwf; /* fw create: IOC down */ | ||
70 | u32 sm_fwc_unexp; /* fw create: exception events*/ | ||
71 | u32 sm_on_off; /* online: offline events */ | ||
72 | u32 sm_on_del; /* online: delete events */ | ||
73 | u32 sm_on_hwf; /* online: IOC down events */ | ||
74 | u32 sm_on_unexp; /* online: exception events */ | ||
75 | u32 sm_fwd_rsp; /* fw delete: fw responses */ | ||
76 | u32 sm_fwd_del; /* fw delete: delete events */ | ||
77 | u32 sm_fwd_hwf; /* fw delete: IOC down events */ | ||
78 | u32 sm_fwd_unexp; /* fw delete: exception events*/ | ||
79 | u32 sm_off_del; /* offline: delete events */ | ||
80 | u32 sm_off_on; /* offline: online events */ | ||
81 | u32 sm_off_hwf; /* offline: IOC down events */ | ||
82 | u32 sm_off_unexp; /* offline: exception events */ | ||
83 | u32 sm_del_fwrsp; /* delete: fw responses */ | ||
84 | u32 sm_del_hwf; /* delete: IOC down events */ | ||
85 | u32 sm_del_unexp; /* delete: exception events */ | ||
86 | u32 sm_delp_fwrsp; /* delete pend: fw responses */ | ||
87 | u32 sm_delp_hwf; /* delete pend: IOC downs */ | ||
88 | u32 sm_delp_unexp; /* delete pend: exceptions */ | ||
89 | u32 sm_offp_fwrsp; /* off-pending: fw responses */ | ||
90 | u32 sm_offp_del; /* off-pending: deletes */ | ||
91 | u32 sm_offp_hwf; /* off-pending: IOC downs */ | ||
92 | u32 sm_offp_unexp; /* off-pending: exceptions */ | ||
93 | u32 sm_iocd_off; /* IOC down: offline events */ | ||
94 | u32 sm_iocd_del; /* IOC down: delete events */ | ||
95 | u32 sm_iocd_on; /* IOC down: online events */ | ||
96 | u32 sm_iocd_unexp; /* IOC down: exceptions */ | ||
97 | u32 rsvd; | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * FCS remote port statistics | ||
102 | */ | ||
103 | struct bfa_rport_stats_s { | ||
104 | u32 offlines; /* remote port offline count */ | ||
105 | u32 onlines; /* remote port online count */ | ||
106 | u32 rscns; /* RSCN affecting rport */ | ||
107 | u32 plogis; /* plogis sent */ | ||
108 | u32 plogi_accs; /* plogi accepts */ | ||
109 | u32 plogi_timeouts; /* plogi timeouts */ | ||
110 | u32 plogi_rejects; /* rcvd plogi rejects */ | ||
111 | u32 plogi_failed; /* local failure */ | ||
112 | u32 plogi_rcvd; /* plogis rcvd */ | ||
113 | u32 prli_rcvd; /* inbound PRLIs */ | ||
114 | u32 adisc_rcvd; /* ADISCs received */ | ||
115 | u32 adisc_rejects; /* recvd ADISC rejects */ | ||
116 | u32 adisc_sent; /* ADISC requests sent */ | ||
117 | u32 adisc_accs; /* ADISC accepted by rport */ | ||
118 | u32 adisc_failed; /* ADISC failed (no response) */ | ||
119 | u32 adisc_rejected; /* ADISC rejected by us */ | ||
120 | u32 logos; /* logos sent */ | ||
121 | u32 logo_accs; /* LOGO accepts from rport */ | ||
122 | u32 logo_failed; /* LOGO failures */ | ||
123 | u32 logo_rejected; /* LOGO rejects from rport */ | ||
124 | u32 logo_rcvd; /* LOGO from remote port */ | ||
125 | |||
126 | u32 rpsc_rcvd; /* RPSC received */ | ||
127 | u32 rpsc_rejects; /* recvd RPSC rejects */ | ||
128 | u32 rpsc_sent; /* RPSC requests sent */ | ||
129 | u32 rpsc_accs; /* RPSC accepted by rport */ | ||
130 | u32 rpsc_failed; /* RPSC failed (no response) */ | ||
131 | u32 rpsc_rejected; /* RPSC rejected by us */ | ||
132 | |||
133 | u32 rsvd; | ||
134 | struct bfa_rport_hal_stats_s hal_stats; /* BFA rport stats */ | ||
135 | }; | ||
136 | |||
137 | /** | ||
138 | * Rport's QoS attributes | ||
139 | */ | ||
140 | struct bfa_rport_qos_attr_s { | ||
141 | enum bfa_qos_priority qos_priority; /* rport's QoS priority */ | ||
142 | u32 qos_flow_id; /* QoS flow Id */ | ||
143 | }; | ||
144 | |||
145 | /** | ||
146 | * FCS remote port attributes returned in queries | ||
147 | */ | ||
148 | struct bfa_rport_attr_s { | ||
149 | wwn_t nwwn; /* node wwn */ | ||
150 | wwn_t pwwn; /* port wwn */ | ||
151 | enum fc_cos cos_supported; /* supported class of services */ | ||
152 | u32 pid; /* port ID */ | ||
153 | u32 df_sz; /* Max payload size */ | ||
154 | enum bfa_rport_state state; /* Rport State machine state */ | ||
155 | enum fc_cos fc_cos; /* FC classes of services */ | ||
156 | bfa_boolean_t cisc; /* CISC capable device */ | ||
157 | struct bfa_rport_symname_s symname; /* Symbolic Name */ | ||
158 | enum bfa_rport_function scsi_function; /* Initiator/Target */ | ||
159 | struct bfa_rport_qos_attr_s qos_attr; /* qos attributes */ | ||
160 | enum bfa_pport_speed curr_speed; /* operating speed got from | ||
161 | * RPSC ELS. UNKNOWN, if RPSC | ||
162 | * is not supported */ | ||
163 | bfa_boolean_t trl_enforced; /* TRL enforced ? TRUE/FALSE */ | ||
164 | enum bfa_pport_speed assigned_speed; /* Speed assigned by the user. | ||
165 | * will be used if RPSC is not | ||
166 | * supported by the rport */ | ||
167 | }; | ||
168 | |||
169 | #define bfa_rport_aen_qos_data_t struct bfa_rport_qos_attr_s | ||
170 | |||
171 | /** | ||
172 | * BFA remote port events | ||
173 | * Arguments below are in BFAL context from Mgmt | ||
174 | * BFA_RPORT_AEN_ONLINE: [in]: lpwwn [out]: vf_id, lpwwn, rpwwn | ||
175 | * BFA_RPORT_AEN_OFFLINE: [in]: lpwwn [out]: vf_id, lpwwn, rpwwn | ||
176 | * BFA_RPORT_AEN_DISCONNECT:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn | ||
177 | * BFA_RPORT_AEN_QOS_PRIO: [in]: lpwwn [out]: vf_id, lpwwn, rpwwn, prio | ||
178 | * BFA_RPORT_AEN_QOS_FLOWID:[in]: lpwwn [out]: vf_id, lpwwn, rpwwn, flow_id | ||
179 | */ | ||
180 | enum bfa_rport_aen_event { | ||
181 | BFA_RPORT_AEN_ONLINE = 1, /* RPort online event */ | ||
182 | BFA_RPORT_AEN_OFFLINE = 2, /* RPort offline event */ | ||
183 | BFA_RPORT_AEN_DISCONNECT = 3, /* RPort disconnect event */ | ||
184 | BFA_RPORT_AEN_QOS_PRIO = 4, /* QOS priority change event */ | ||
185 | BFA_RPORT_AEN_QOS_FLOWID = 5, /* QOS flow Id change event */ | ||
186 | }; | ||
187 | |||
188 | struct bfa_rport_aen_data_s { | ||
189 | u16 vf_id; /* vf_id of this logical port */ | ||
190 | u16 rsvd[3]; | ||
191 | wwn_t ppwwn; /* WWN of its physical port */ | ||
192 | wwn_t lpwwn; /* WWN of this logical port */ | ||
193 | wwn_t rpwwn; /* WWN of this remote port */ | ||
194 | union { | ||
195 | bfa_rport_aen_qos_data_t qos; | ||
196 | } priv; | ||
197 | }; | ||
198 | |||
199 | #endif /* __BFA_DEFS_RPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_status.h b/drivers/scsi/bfa/include/defs/bfa_defs_status.h new file mode 100644 index 000000000000..cdceaeb9f4b8 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_status.h | |||
@@ -0,0 +1,255 @@ | |||
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 | #ifndef __BFA_DEFS_STATUS_H__ | ||
18 | #define __BFA_DEFS_STATUS_H__ | ||
19 | |||
20 | /** | ||
21 | * API status return values | ||
22 | * | ||
23 | * NOTE: The error msgs are auto generated from the comments. Only singe line | ||
24 | * comments are supported | ||
25 | */ | ||
26 | enum bfa_status { | ||
27 | BFA_STATUS_OK = 0, /* Success */ | ||
28 | BFA_STATUS_FAILED = 1, /* Operation failed */ | ||
29 | BFA_STATUS_EINVAL = 2, /* Invalid params Check input | ||
30 | * parameters */ | ||
31 | BFA_STATUS_ENOMEM = 3, /* Out of resources */ | ||
32 | BFA_STATUS_ENOSYS = 4, /* Function not implemented */ | ||
33 | BFA_STATUS_ETIMER = 5, /* Timer expired - Retry, if | ||
34 | * persists, contact support */ | ||
35 | BFA_STATUS_EPROTOCOL = 6, /* Protocol error */ | ||
36 | BFA_STATUS_ENOFCPORTS = 7, /* No FC ports resources */ | ||
37 | BFA_STATUS_NOFLASH = 8, /* Flash not present */ | ||
38 | BFA_STATUS_BADFLASH = 9, /* Flash is corrupted or bad */ | ||
39 | BFA_STATUS_SFP_UNSUPP = 10, /* Unsupported SFP - Replace SFP */ | ||
40 | BFA_STATUS_UNKNOWN_VFID = 11, /* VF_ID not found */ | ||
41 | BFA_STATUS_DATACORRUPTED = 12, /* Diag returned data corrupted | ||
42 | * contact support */ | ||
43 | BFA_STATUS_DEVBUSY = 13, /* Device busy - Retry operation */ | ||
44 | BFA_STATUS_ABORTED = 14, /* Operation aborted */ | ||
45 | BFA_STATUS_NODEV = 15, /* Dev is not present */ | ||
46 | BFA_STATUS_HDMA_FAILED = 16, /* Host dma failed contact support */ | ||
47 | BFA_STATUS_FLASH_BAD_LEN = 17, /* Flash bad length */ | ||
48 | BFA_STATUS_UNKNOWN_LWWN = 18, /* LPORT PWWN not found */ | ||
49 | BFA_STATUS_UNKNOWN_RWWN = 19, /* RPORT PWWN not found */ | ||
50 | BFA_STATUS_FCPT_LS_RJT = 20, /* Got LS_RJT for FC Pass | ||
51 | * through Req */ | ||
52 | BFA_STATUS_VPORT_EXISTS = 21, /* VPORT already exists */ | ||
53 | BFA_STATUS_VPORT_MAX = 22, /* Reached max VPORT supported | ||
54 | * limit */ | ||
55 | BFA_STATUS_UNSUPP_SPEED = 23, /* Invalid Speed Check speed | ||
56 | * setting */ | ||
57 | BFA_STATUS_INVLD_DFSZ = 24, /* Invalid Max data field size */ | ||
58 | BFA_STATUS_CNFG_FAILED = 25, /* Setting can not be persisted */ | ||
59 | BFA_STATUS_CMD_NOTSUPP = 26, /* Command/API not supported */ | ||
60 | BFA_STATUS_NO_ADAPTER = 27, /* No Brocade Adapter Found */ | ||
61 | BFA_STATUS_LINKDOWN = 28, /* Link is down - Check or replace | ||
62 | * SFP/cable */ | ||
63 | BFA_STATUS_FABRIC_RJT = 29, /* Reject from attached fabric */ | ||
64 | BFA_STATUS_UNKNOWN_VWWN = 30, /* VPORT PWWN not found */ | ||
65 | BFA_STATUS_NSLOGIN_FAILED = 31, /* Nameserver login failed */ | ||
66 | BFA_STATUS_NO_RPORTS = 32, /* No remote ports found */ | ||
67 | BFA_STATUS_NSQUERY_FAILED = 33, /* Nameserver query failed */ | ||
68 | BFA_STATUS_PORT_OFFLINE = 34, /* Port is not online */ | ||
69 | BFA_STATUS_RPORT_OFFLINE = 35, /* RPORT is not online */ | ||
70 | BFA_STATUS_TGTOPEN_FAILED = 36, /* Remote SCSI target open failed */ | ||
71 | BFA_STATUS_BAD_LUNS = 37, /* No valid LUNs found */ | ||
72 | BFA_STATUS_IO_FAILURE = 38, /* SCSI target IO failure */ | ||
73 | BFA_STATUS_NO_FABRIC = 39, /* No switched fabric present */ | ||
74 | BFA_STATUS_EBADF = 40, /* Bad file descriptor */ | ||
75 | BFA_STATUS_EINTR = 41, /* A signal was caught during ioctl */ | ||
76 | BFA_STATUS_EIO = 42, /* I/O error */ | ||
77 | BFA_STATUS_ENOTTY = 43, /* Inappropriate I/O control | ||
78 | * operation */ | ||
79 | BFA_STATUS_ENXIO = 44, /* No such device or address */ | ||
80 | BFA_STATUS_EFOPEN = 45, /* Failed to open file */ | ||
81 | BFA_STATUS_VPORT_WWN_BP = 46, /* WWN is same as base port's WWN */ | ||
82 | BFA_STATUS_PORT_NOT_DISABLED = 47, /* Port not disabled disable port | ||
83 | * first */ | ||
84 | BFA_STATUS_BADFRMHDR = 48, /* Bad frame header */ | ||
85 | BFA_STATUS_BADFRMSZ = 49, /* Bad frame size check and replace | ||
86 | * SFP/cable */ | ||
87 | BFA_STATUS_MISSINGFRM = 50, /* Missing frame check and replace | ||
88 | * SFP/cable */ | ||
89 | BFA_STATUS_LINKTIMEOUT = 51, /* Link timeout check and replace | ||
90 | * SFP/cable */ | ||
91 | BFA_STATUS_NO_FCPIM_NEXUS = 52, /* No FCP Nexus exists with the | ||
92 | * rport */ | ||
93 | BFA_STATUS_CHECKSUM_FAIL = 53, /* checksum failure */ | ||
94 | BFA_STATUS_GZME_FAILED = 54, /* Get zone member query failed */ | ||
95 | BFA_STATUS_SCSISTART_REQD = 55, /* SCSI disk require START command */ | ||
96 | BFA_STATUS_IOC_FAILURE = 56, /* IOC failure - Retry, if persists | ||
97 | * contact support */ | ||
98 | BFA_STATUS_INVALID_WWN = 57, /* Invalid WWN */ | ||
99 | BFA_STATUS_MISMATCH = 58, /* Version mismatch */ | ||
100 | BFA_STATUS_IOC_ENABLED = 59, /* IOC is already enabled */ | ||
101 | BFA_STATUS_ADAPTER_ENABLED = 60, /* Adapter is not disabled disable | ||
102 | * adapter first */ | ||
103 | BFA_STATUS_IOC_NON_OP = 61, /* IOC is not operational. Enable IOC | ||
104 | * and if it still fails, | ||
105 | * contact support */ | ||
106 | BFA_STATUS_ADDR_MAP_FAILURE = 62, /* PCI base address not mapped | ||
107 | * in OS */ | ||
108 | BFA_STATUS_SAME_NAME = 63, /* Name exists! use a different | ||
109 | * name */ | ||
110 | BFA_STATUS_PENDING = 64, /* API completes asynchronously */ | ||
111 | BFA_STATUS_8G_SPD = 65, /* Speed setting not valid for | ||
112 | * 8G HBA */ | ||
113 | BFA_STATUS_4G_SPD = 66, /* Speed setting not valid for | ||
114 | * 4G HBA */ | ||
115 | BFA_STATUS_AD_IS_ENABLE = 67, /* Adapter is already enabled */ | ||
116 | BFA_STATUS_EINVAL_TOV = 68, /* Invalid path failover TOV */ | ||
117 | BFA_STATUS_EINVAL_QDEPTH = 69, /* Invalid queue depth value */ | ||
118 | BFA_STATUS_VERSION_FAIL = 70, /* Application/Driver version | ||
119 | * mismatch */ | ||
120 | BFA_STATUS_DIAG_BUSY = 71, /* diag busy */ | ||
121 | BFA_STATUS_BEACON_ON = 72, /* Port Beacon already on */ | ||
122 | BFA_STATUS_BEACON_OFF = 73, /* Port Beacon already off */ | ||
123 | BFA_STATUS_LBEACON_ON = 74, /* Link End-to-End Beacon already | ||
124 | * on */ | ||
125 | BFA_STATUS_LBEACON_OFF = 75, /* Link End-to-End Beacon already | ||
126 | * off */ | ||
127 | BFA_STATUS_PORT_NOT_INITED = 76, /* Port not initialized */ | ||
128 | BFA_STATUS_RPSC_ENABLED = 77, /* Target has a valid speed */ | ||
129 | BFA_STATUS_ENOFSAVE = 78, /* No saved firmware trace */ | ||
130 | BFA_STATUS_BAD_FILE = 79, /* Not a valid Brocade Boot Code | ||
131 | * file */ | ||
132 | BFA_STATUS_RLIM_EN = 80, /* Target rate limiting is already | ||
133 | * enabled */ | ||
134 | BFA_STATUS_RLIM_DIS = 81, /* Target rate limiting is already | ||
135 | * disabled */ | ||
136 | BFA_STATUS_IOC_DISABLED = 82, /* IOC is already disabled */ | ||
137 | BFA_STATUS_ADAPTER_DISABLED = 83, /* Adapter is already disabled */ | ||
138 | BFA_STATUS_BIOS_DISABLED = 84, /* Bios is already disabled */ | ||
139 | BFA_STATUS_AUTH_ENABLED = 85, /* Authentication is already | ||
140 | * enabled */ | ||
141 | BFA_STATUS_AUTH_DISABLED = 86, /* Authentication is already | ||
142 | * disabled */ | ||
143 | BFA_STATUS_ERROR_TRL_ENABLED = 87, /* Target rate limiting is | ||
144 | * enabled */ | ||
145 | BFA_STATUS_ERROR_QOS_ENABLED = 88, /* QoS is enabled */ | ||
146 | BFA_STATUS_NO_SFP_DEV = 89, /* No SFP device check or replace SFP */ | ||
147 | BFA_STATUS_MEMTEST_FAILED = 90, /* Memory test failed contact | ||
148 | * support */ | ||
149 | BFA_STATUS_INVALID_DEVID = 91, /* Invalid device id provided */ | ||
150 | BFA_STATUS_QOS_ENABLED = 92, /* QOS is already enabled */ | ||
151 | BFA_STATUS_QOS_DISABLED = 93, /* QOS is already disabled */ | ||
152 | BFA_STATUS_INCORRECT_DRV_CONFIG = 94, /* Check configuration | ||
153 | * key/value pair */ | ||
154 | BFA_STATUS_REG_FAIL = 95, /* Can't read windows registry */ | ||
155 | BFA_STATUS_IM_INV_CODE = 96, /* Invalid IOCTL code */ | ||
156 | BFA_STATUS_IM_INV_VLAN = 97, /* Invalid VLAN ID */ | ||
157 | BFA_STATUS_IM_INV_ADAPT_NAME = 98, /* Invalid adapter name */ | ||
158 | BFA_STATUS_IM_LOW_RESOURCES = 99, /* Memory allocation failure in | ||
159 | * driver */ | ||
160 | BFA_STATUS_IM_VLANID_IS_PVID = 100, /* Given VLAN id same as PVID */ | ||
161 | BFA_STATUS_IM_VLANID_EXISTS = 101, /* Given VLAN id already exists */ | ||
162 | BFA_STATUS_IM_FW_UPDATE_FAIL = 102, /* Updating firmware with new | ||
163 | * VLAN ID failed */ | ||
164 | BFA_STATUS_PORTLOG_ENABLED = 103, /* Port Log is already enabled */ | ||
165 | BFA_STATUS_PORTLOG_DISABLED = 104, /* Port Log is already disabled */ | ||
166 | BFA_STATUS_FILE_NOT_FOUND = 105, /* Specified file could not be | ||
167 | * found */ | ||
168 | BFA_STATUS_QOS_FC_ONLY = 106, /* QOS can be enabled for FC mode | ||
169 | * only */ | ||
170 | BFA_STATUS_RLIM_FC_ONLY = 107, /* RATELIM can be enabled for FC mode | ||
171 | * only */ | ||
172 | BFA_STATUS_CT_SPD = 108, /* Invalid speed selection for Catapult. */ | ||
173 | BFA_STATUS_LEDTEST_OP = 109, /* LED test is operating */ | ||
174 | BFA_STATUS_CEE_NOT_DN = 110, /* eth port is not at down state, please | ||
175 | * bring down first */ | ||
176 | BFA_STATUS_10G_SPD = 111, /* Speed setting not valid for 10G HBA */ | ||
177 | BFA_STATUS_IM_INV_TEAM_NAME = 112, /* Invalid team name */ | ||
178 | BFA_STATUS_IM_DUP_TEAM_NAME = 113, /* Given team name already | ||
179 | * exists */ | ||
180 | BFA_STATUS_IM_ADAPT_ALREADY_IN_TEAM = 114, /* Given adapter is part | ||
181 | * of another team */ | ||
182 | BFA_STATUS_IM_ADAPT_HAS_VLANS = 115, /* Adapter has VLANs configured. | ||
183 | * Delete all VLANs before | ||
184 | * creating team */ | ||
185 | BFA_STATUS_IM_PVID_MISMATCH = 116, /* Mismatching PVIDs configured | ||
186 | * for adapters */ | ||
187 | BFA_STATUS_IM_LINK_SPEED_MISMATCH = 117, /* Mismatching link speeds | ||
188 | * configured for adapters */ | ||
189 | BFA_STATUS_IM_MTU_MISMATCH = 118, /* Mismatching MTUs configured for | ||
190 | * adapters */ | ||
191 | BFA_STATUS_IM_RSS_MISMATCH = 119, /* Mismatching RSS parameters | ||
192 | * configured for adapters */ | ||
193 | BFA_STATUS_IM_HDS_MISMATCH = 120, /* Mismatching HDS parameters | ||
194 | * configured for adapters */ | ||
195 | BFA_STATUS_IM_OFFLOAD_MISMATCH = 121, /* Mismatching offload | ||
196 | * parameters configured for | ||
197 | * adapters */ | ||
198 | BFA_STATUS_IM_PORT_PARAMS = 122, /* Error setting port parameters */ | ||
199 | BFA_STATUS_IM_PORT_NOT_IN_TEAM = 123, /* Port is not part of team */ | ||
200 | BFA_STATUS_IM_CANNOT_REM_PRI = 124, /* Primary adapter cannot be | ||
201 | * removed. Change primary before | ||
202 | * removing */ | ||
203 | BFA_STATUS_IM_MAX_PORTS_REACHED = 125, /* Exceeding maximum ports | ||
204 | * per team */ | ||
205 | BFA_STATUS_IM_LAST_PORT_DELETE = 126, /* Last port in team being | ||
206 | * deleted */ | ||
207 | BFA_STATUS_IM_NO_DRIVER = 127, /* IM driver is not installed */ | ||
208 | BFA_STATUS_IM_MAX_VLANS_REACHED = 128, /* Exceeding maximum VLANs | ||
209 | * per port */ | ||
210 | BFA_STATUS_TOMCAT_SPD_NOT_ALLOWED = 129, /* Bios speed config not | ||
211 | * allowed for CNA */ | ||
212 | BFA_STATUS_NO_MINPORT_DRIVER = 130, /* Miniport driver is not | ||
213 | * loaded */ | ||
214 | BFA_STATUS_CARD_TYPE_MISMATCH = 131, /* Card type mismatch */ | ||
215 | BFA_STATUS_BAD_ASICBLK = 132, /* Bad ASIC block */ | ||
216 | BFA_STATUS_NO_DRIVER = 133, /* Storage/Ethernet driver not loaded */ | ||
217 | BFA_STATUS_INVALID_MAC = 134, /* Invalid mac address */ | ||
218 | BFA_STATUS_IM_NO_VLAN = 135, /* No VLANs configured on the adapter */ | ||
219 | BFA_STATUS_IM_ETH_LB_FAILED = 136, /* Ethernet loopback test failed */ | ||
220 | BFA_STATUS_IM_PVID_REMOVE = 137, /* Cannot remove port vlan (PVID) */ | ||
221 | BFA_STATUS_IM_PVID_EDIT = 138, /* Cannot edit port vlan (PVID) */ | ||
222 | BFA_STATUS_CNA_NO_BOOT = 139, /* Boot upload not allowed for CNA */ | ||
223 | BFA_STATUS_IM_PVID_NON_ZERO = 140, /* Port VLAN ID (PVID) is Set to | ||
224 | * Non-Zero Value */ | ||
225 | BFA_STATUS_IM_INETCFG_LOCK_FAILED = 141, /* Acquiring Network | ||
226 | * Subsytem Lock Failed.Please | ||
227 | * try after some time */ | ||
228 | BFA_STATUS_IM_GET_INETCFG_FAILED = 142, /* Acquiring Network Subsytem | ||
229 | * handle Failed. Please try | ||
230 | * after some time */ | ||
231 | BFA_STATUS_IM_NOT_BOUND = 143, /* Brocade 10G Ethernet Service is not | ||
232 | * Enabled on this port */ | ||
233 | BFA_STATUS_INSUFFICIENT_PERMS = 144, /* User doesn't have sufficient | ||
234 | * permissions to execute the BCU | ||
235 | * application */ | ||
236 | BFA_STATUS_IM_INV_VLAN_NAME = 145, /* Invalid/Reserved Vlan name | ||
237 | * string. The name is not allowed | ||
238 | * for the normal Vlans */ | ||
239 | BFA_STATUS_CMD_NOTSUPP_CNA = 146, /* Command not supported for CNA */ | ||
240 | BFA_STATUS_IM_PASSTHRU_EDIT = 147, /* Can not edit passthru vlan id */ | ||
241 | BFA_STATUS_IM_BIND_FAILED = 148, /*! < IM Driver bind operation | ||
242 | * failed */ | ||
243 | BFA_STATUS_IM_UNBIND_FAILED = 149, /* ! < IM Driver unbind operation | ||
244 | * failed */ | ||
245 | BFA_STATUS_MAX_VAL /* Unknown error code */ | ||
246 | }; | ||
247 | #define bfa_status_t enum bfa_status | ||
248 | |||
249 | enum bfa_eproto_status { | ||
250 | BFA_EPROTO_BAD_ACCEPT = 0, | ||
251 | BFA_EPROTO_UNKNOWN_RSP = 1 | ||
252 | }; | ||
253 | #define bfa_eproto_status_t enum bfa_eproto_status | ||
254 | |||
255 | #endif /* __BFA_DEFS_STATUS_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tin.h b/drivers/scsi/bfa/include/defs/bfa_defs_tin.h new file mode 100644 index 000000000000..e05a2db7abed --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_tin.h | |||
@@ -0,0 +1,118 @@ | |||
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 | #ifndef __BFA_DEFS_TIN_H__ | ||
19 | #define __BFA_DEFS_TIN_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | #include <protocol/fc.h> | ||
23 | |||
24 | /** | ||
25 | * FCS tin states | ||
26 | */ | ||
27 | enum bfa_tin_state_e { | ||
28 | BFA_TIN_SM_OFFLINE = 0, /* tin is offline */ | ||
29 | BFA_TIN_SM_WOS_LOGIN = 1, /* Waiting PRLI ACC/RJT from ULP */ | ||
30 | BFA_TIN_SM_WFW_ONLINE = 2, /* Waiting ACK to PRLI ACC from FW */ | ||
31 | BFA_TIN_SM_ONLINE = 3, /* tin login is complete */ | ||
32 | BFA_TIN_SM_WIO_RELOGIN = 4, /* tin relogin is in progress */ | ||
33 | BFA_TIN_SM_WIO_LOGOUT = 5, /* Processing of PRLO req from | ||
34 | * Initiator is in progress | ||
35 | */ | ||
36 | BFA_TIN_SM_WOS_LOGOUT = 6, /* Processing of PRLO req from | ||
37 | * Initiator is in progress | ||
38 | */ | ||
39 | BFA_TIN_SM_WIO_CLEAN = 7, /* Waiting for IO cleanup before tin | ||
40 | * is offline. This can be triggered | ||
41 | * by RPORT LOGO (rcvd/sent) or by | ||
42 | * PRLO (rcvd/sent) | ||
43 | */ | ||
44 | }; | ||
45 | |||
46 | struct bfa_prli_req_s { | ||
47 | struct fchs_s fchs; | ||
48 | struct fc_prli_s prli_payload; | ||
49 | }; | ||
50 | |||
51 | struct bfa_prlo_req_s { | ||
52 | struct fchs_s fchs; | ||
53 | struct fc_prlo_s prlo_payload; | ||
54 | }; | ||
55 | |||
56 | void bfa_tin_send_login_rsp(void *bfa_tin, u32 login_rsp, | ||
57 | struct fc_ls_rjt_s rjt_payload); | ||
58 | void bfa_tin_send_logout_rsp(void *bfa_tin, u32 logout_rsp, | ||
59 | struct fc_ls_rjt_s rjt_payload); | ||
60 | /** | ||
61 | * FCS target port statistics | ||
62 | */ | ||
63 | struct bfa_tin_stats_s { | ||
64 | u32 onlines; /* ITN nexus onlines (PRLI done) */ | ||
65 | u32 offlines; /* ITN Nexus offlines */ | ||
66 | u32 prli_req_parse_err; /* prli req parsing errors */ | ||
67 | u32 prli_rsp_rjt; /* num prli rsp rejects sent */ | ||
68 | u32 prli_rsp_acc; /* num prli rsp accepts sent */ | ||
69 | u32 cleanup_comps; /* ITN cleanup completions */ | ||
70 | }; | ||
71 | |||
72 | /** | ||
73 | * FCS tin attributes returned in queries | ||
74 | */ | ||
75 | struct bfa_tin_attr_s { | ||
76 | enum bfa_tin_state_e state; | ||
77 | u8 seq_retry; /* Sequence retry supported */ | ||
78 | u8 rsvd[3]; | ||
79 | }; | ||
80 | |||
81 | /** | ||
82 | * BFA TIN async event data structure for BFAL | ||
83 | */ | ||
84 | enum bfa_tin_aen_event { | ||
85 | BFA_TIN_AEN_ONLINE = 1, /* Target online */ | ||
86 | BFA_TIN_AEN_OFFLINE = 2, /* Target offline */ | ||
87 | BFA_TIN_AEN_DISCONNECT = 3, /* Target disconnected */ | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * BFA TIN event data structure. | ||
92 | */ | ||
93 | struct bfa_tin_aen_data_s { | ||
94 | u16 vf_id; /* vf_id of the IT nexus */ | ||
95 | u16 rsvd[3]; | ||
96 | wwn_t lpwwn; /* WWN of logical port */ | ||
97 | wwn_t rpwwn; /* WWN of remote(target) port */ | ||
98 | }; | ||
99 | |||
100 | /** | ||
101 | * Below APIs are needed from BFA driver | ||
102 | * Move these to BFA driver public header file? | ||
103 | */ | ||
104 | /* TIN rcvd new PRLI & gets bfad_tin_t ptr from driver this callback */ | ||
105 | void *bfad_tin_rcvd_login_req(void *bfad_tm_port, void *bfa_tin, | ||
106 | wwn_t rp_wwn, u32 rp_fcid, | ||
107 | struct bfa_prli_req_s prli_req); | ||
108 | /* TIN rcvd new PRLO */ | ||
109 | void bfad_tin_rcvd_logout_req(void *bfad_tin, wwn_t rp_wwn, u32 rp_fcid, | ||
110 | struct bfa_prlo_req_s prlo_req); | ||
111 | /* TIN is online and ready for IO */ | ||
112 | void bfad_tin_online(void *bfad_tin); | ||
113 | /* TIN is offline and BFA driver can shutdown its upper stack */ | ||
114 | void bfad_tin_offline(void *bfad_tin); | ||
115 | /* TIN does not need this BFA driver tin tag anymore, so can be freed */ | ||
116 | void bfad_tin_res_free(void *bfad_tin); | ||
117 | |||
118 | #endif /* __BFA_DEFS_TIN_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h b/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h new file mode 100644 index 000000000000..31881d218515 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_tsensor.h | |||
@@ -0,0 +1,43 @@ | |||
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 | #ifndef __BFA_DEFS_TSENSOR_H__ | ||
19 | #define __BFA_DEFS_TSENSOR_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include <defs/bfa_defs_types.h> | ||
23 | |||
24 | /** | ||
25 | * Temperature sensor status values | ||
26 | */ | ||
27 | enum bfa_tsensor_status { | ||
28 | BFA_TSENSOR_STATUS_UNKNOWN = 1, /* unkown status */ | ||
29 | BFA_TSENSOR_STATUS_FAULTY = 2, /* sensor is faulty */ | ||
30 | BFA_TSENSOR_STATUS_BELOW_MIN = 3, /* temperature below mininum */ | ||
31 | BFA_TSENSOR_STATUS_NOMINAL = 4, /* normal temperature */ | ||
32 | BFA_TSENSOR_STATUS_ABOVE_MAX = 5, /* temperature above maximum */ | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * Temperature sensor attribute | ||
37 | */ | ||
38 | struct bfa_tsensor_attr_s { | ||
39 | enum bfa_tsensor_status status; /* temperature sensor status */ | ||
40 | u32 value; /* current temperature in celsius */ | ||
41 | }; | ||
42 | |||
43 | #endif /* __BFA_DEFS_TSENSOR_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_types.h b/drivers/scsi/bfa/include/defs/bfa_defs_types.h new file mode 100644 index 000000000000..4348332b107a --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_types.h | |||
@@ -0,0 +1,30 @@ | |||
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 | #ifndef __BFA_DEFS_TYPES_H__ | ||
18 | #define __BFA_DEFS_TYPES_H__ | ||
19 | |||
20 | #include <bfa_os_inc.h> | ||
21 | |||
22 | enum bfa_boolean { | ||
23 | BFA_FALSE = 0, | ||
24 | BFA_TRUE = 1 | ||
25 | }; | ||
26 | #define bfa_boolean_t enum bfa_boolean | ||
27 | |||
28 | #define BFA_STRING_32 32 | ||
29 | |||
30 | #endif /* __BFA_DEFS_TYPES_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_version.h b/drivers/scsi/bfa/include/defs/bfa_defs_version.h new file mode 100644 index 000000000000..f8902a2c9aad --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_version.h | |||
@@ -0,0 +1,22 @@ | |||
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 | #ifndef __BFA_DEFS_VERSION_H__ | ||
18 | #define __BFA_DEFS_VERSION_H__ | ||
19 | |||
20 | #define BFA_VERSION_LEN 64 | ||
21 | |||
22 | #endif | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vf.h b/drivers/scsi/bfa/include/defs/bfa_defs_vf.h new file mode 100644 index 000000000000..3235be5e9423 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_vf.h | |||
@@ -0,0 +1,74 @@ | |||
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 | #ifndef __BFA_DEFS_VF_H__ | ||
19 | #define __BFA_DEFS_VF_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include <defs/bfa_defs_port.h> | ||
23 | #include <protocol/types.h> | ||
24 | |||
25 | /** | ||
26 | * VF states | ||
27 | */ | ||
28 | enum bfa_vf_state { | ||
29 | BFA_VF_UNINIT = 0, /* fabric is not yet initialized */ | ||
30 | BFA_VF_LINK_DOWN = 1, /* link is down */ | ||
31 | BFA_VF_FLOGI = 2, /* flogi is in progress */ | ||
32 | BFA_VF_AUTH = 3, /* authentication in progress */ | ||
33 | BFA_VF_NOFABRIC = 4, /* fabric is not present */ | ||
34 | BFA_VF_ONLINE = 5, /* login to fabric is complete */ | ||
35 | BFA_VF_EVFP = 6, /* EVFP is in progress */ | ||
36 | BFA_VF_ISOLATED = 7, /* port isolated due to vf_id mismatch */ | ||
37 | }; | ||
38 | |||
39 | /** | ||
40 | * VF statistics | ||
41 | */ | ||
42 | struct bfa_vf_stats_s { | ||
43 | u32 flogi_sent; /* Num FLOGIs sent */ | ||
44 | u32 flogi_rsp_err; /* FLOGI response errors */ | ||
45 | u32 flogi_acc_err; /* FLOGI accept errors */ | ||
46 | u32 flogi_accepts; /* FLOGI accepts received */ | ||
47 | u32 flogi_rejects; /* FLOGI rejects received */ | ||
48 | u32 flogi_unknown_rsp; /* Unknown responses for FLOGI */ | ||
49 | u32 flogi_alloc_wait; /* Allocation waits prior to | ||
50 | * sending FLOGI | ||
51 | */ | ||
52 | u32 flogi_rcvd; /* FLOGIs received */ | ||
53 | u32 flogi_rejected; /* Incoming FLOGIs rejected */ | ||
54 | u32 fabric_onlines; /* Internal fabric online | ||
55 | * notification sent to other | ||
56 | * modules | ||
57 | */ | ||
58 | u32 fabric_offlines; /* Internal fabric offline | ||
59 | * notification sent to other | ||
60 | * modules | ||
61 | */ | ||
62 | u32 resvd; | ||
63 | }; | ||
64 | |||
65 | /** | ||
66 | * VF attributes returned in queries | ||
67 | */ | ||
68 | struct bfa_vf_attr_s { | ||
69 | enum bfa_vf_state state; /* VF state */ | ||
70 | u32 rsvd; | ||
71 | wwn_t fabric_name; /* fabric name */ | ||
72 | }; | ||
73 | |||
74 | #endif /* __BFA_DEFS_VF_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/defs/bfa_defs_vport.h b/drivers/scsi/bfa/include/defs/bfa_defs_vport.h new file mode 100644 index 000000000000..9f021f43b3b4 --- /dev/null +++ b/drivers/scsi/bfa/include/defs/bfa_defs_vport.h | |||
@@ -0,0 +1,91 @@ | |||
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 | #ifndef __BFA_DEFS_VPORT_H__ | ||
19 | #define __BFA_DEFS_VPORT_H__ | ||
20 | |||
21 | #include <bfa_os_inc.h> | ||
22 | #include <defs/bfa_defs_port.h> | ||
23 | #include <protocol/types.h> | ||
24 | |||
25 | /** | ||
26 | * VPORT states | ||
27 | */ | ||
28 | enum bfa_vport_state { | ||
29 | BFA_FCS_VPORT_UNINIT = 0, | ||
30 | BFA_FCS_VPORT_CREATED = 1, | ||
31 | BFA_FCS_VPORT_OFFLINE = 1, | ||
32 | BFA_FCS_VPORT_FDISC_SEND = 2, | ||
33 | BFA_FCS_VPORT_FDISC = 3, | ||
34 | BFA_FCS_VPORT_FDISC_RETRY = 4, | ||
35 | BFA_FCS_VPORT_ONLINE = 5, | ||
36 | BFA_FCS_VPORT_DELETING = 6, | ||
37 | BFA_FCS_VPORT_CLEANUP = 6, | ||
38 | BFA_FCS_VPORT_LOGO_SEND = 7, | ||
39 | BFA_FCS_VPORT_LOGO = 8, | ||
40 | BFA_FCS_VPORT_ERROR = 9, | ||
41 | BFA_FCS_VPORT_MAX_STATE, | ||
42 | }; | ||
43 | |||
44 | /** | ||
45 | * vport statistics | ||
46 | */ | ||
47 | struct bfa_vport_stats_s { | ||
48 | struct bfa_port_stats_s port_stats; /* base class (port) stats */ | ||
49 | /* | ||
50 | * TODO - remove | ||
51 | */ | ||
52 | |||
53 | u32 fdisc_sent; /* num fdisc sent */ | ||
54 | u32 fdisc_accepts; /* fdisc accepts */ | ||
55 | u32 fdisc_retries; /* fdisc retries */ | ||
56 | u32 fdisc_timeouts; /* fdisc timeouts */ | ||
57 | u32 fdisc_rsp_err; /* fdisc response error */ | ||
58 | u32 fdisc_acc_bad; /* bad fdisc accepts */ | ||
59 | u32 fdisc_rejects; /* fdisc rejects */ | ||
60 | u32 fdisc_unknown_rsp; | ||
61 | /* | ||
62 | *!< fdisc rsp unknown error | ||
63 | */ | ||
64 | u32 fdisc_alloc_wait;/* fdisc req (fcxp)alloc wait */ | ||
65 | |||
66 | u32 logo_alloc_wait;/* logo req (fcxp) alloc wait */ | ||
67 | u32 logo_sent; /* logo sent */ | ||
68 | u32 logo_accepts; /* logo accepts */ | ||
69 | u32 logo_rejects; /* logo rejects */ | ||
70 | u32 logo_rsp_err; /* logo rsp errors */ | ||
71 | u32 logo_unknown_rsp; | ||
72 | /* logo rsp unknown errors */ | ||
73 | |||
74 | u32 fab_no_npiv; /* fabric does not support npiv */ | ||
75 | |||
76 | u32 fab_offline; /* offline events from fab SM */ | ||
77 | u32 fab_online; /* online events from fab SM */ | ||
78 | u32 fab_cleanup; /* cleanup request from fab SM */ | ||
79 | u32 rsvd; | ||
80 | }; | ||
81 | |||
82 | /** | ||
83 | * BFA vport attribute returned in queries | ||
84 | */ | ||
85 | struct bfa_vport_attr_s { | ||
86 | struct bfa_port_attr_s port_attr; /* base class (port) attributes */ | ||
87 | enum bfa_vport_state vport_state; /* vport state */ | ||
88 | u32 rsvd; | ||
89 | }; | ||
90 | |||
91 | #endif /* __BFA_DEFS_VPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb.h b/drivers/scsi/bfa/include/fcb/bfa_fcb.h new file mode 100644 index 000000000000..2963b0bc30e7 --- /dev/null +++ b/drivers/scsi/bfa/include/fcb/bfa_fcb.h | |||
@@ -0,0 +1,33 @@ | |||
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 | * bfa_fcb.h BFA FCS callback interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCB_H__ | ||
23 | #define __BFA_FCB_H__ | ||
24 | |||
25 | /** | ||
26 | * fcb Main fcs callbacks | ||
27 | */ | ||
28 | |||
29 | void bfa_fcb_exit(struct bfad_s *bfad); | ||
30 | |||
31 | |||
32 | |||
33 | #endif /* __BFA_FCB_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h new file mode 100644 index 000000000000..a6c70aee0aa3 --- /dev/null +++ b/drivers/scsi/bfa/include/fcb/bfa_fcb_fcpim.h | |||
@@ -0,0 +1,76 @@ | |||
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 | * : bfad_fcpim.h - BFA FCS initiator mode remote port callbacks | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFAD_FCB_FCPIM_H__ | ||
23 | #define __BFAD_FCB_FCPIM_H__ | ||
24 | |||
25 | struct bfad_itnim_s; | ||
26 | |||
27 | /* | ||
28 | * RPIM callbacks | ||
29 | */ | ||
30 | |||
31 | /** | ||
32 | * Memory allocation for remote port instance. Called before PRLI is | ||
33 | * initiated to the remote target port. | ||
34 | * | ||
35 | * @param[in] bfad - driver instance | ||
36 | * @param[out] itnim - FCS remote port (IM) instance | ||
37 | * @param[out] itnim_drv - driver remote port (IM) instance | ||
38 | * | ||
39 | * @return None | ||
40 | */ | ||
41 | void bfa_fcb_itnim_alloc(struct bfad_s *bfad, struct bfa_fcs_itnim_s **itnim, | ||
42 | struct bfad_itnim_s **itnim_drv); | ||
43 | |||
44 | /** | ||
45 | * Free remote port (IM) instance. | ||
46 | * | ||
47 | * @param[in] bfad - driver instance | ||
48 | * @param[in] itnim_drv - driver remote port instance | ||
49 | * | ||
50 | * @return None | ||
51 | */ | ||
52 | void bfa_fcb_itnim_free(struct bfad_s *bfad, | ||
53 | struct bfad_itnim_s *itnim_drv); | ||
54 | |||
55 | /** | ||
56 | * Notification of when login with a remote target device is complete. | ||
57 | * | ||
58 | * @param[in] itnim_drv - driver remote port instance | ||
59 | * | ||
60 | * @return None | ||
61 | */ | ||
62 | void bfa_fcb_itnim_online(struct bfad_itnim_s *itnim_drv); | ||
63 | |||
64 | /** | ||
65 | * Notification when login with the remote device is severed. | ||
66 | * | ||
67 | * @param[in] itnim_drv - driver remote port instance | ||
68 | * | ||
69 | * @return None | ||
70 | */ | ||
71 | void bfa_fcb_itnim_offline(struct bfad_itnim_s *itnim_drv); | ||
72 | |||
73 | void bfa_fcb_itnim_tov_begin(struct bfad_itnim_s *itnim_drv); | ||
74 | void bfa_fcb_itnim_tov(struct bfad_itnim_s *itnim_drv); | ||
75 | |||
76 | #endif /* __BFAD_FCB_FCPIM_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h new file mode 100644 index 000000000000..5fd7f986fa32 --- /dev/null +++ b/drivers/scsi/bfa/include/fcb/bfa_fcb_port.h | |||
@@ -0,0 +1,113 @@ | |||
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 | * bfa_fcb_port.h BFA FCS virtual port driver interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCB_PORT_H__ | ||
23 | #define __BFA_FCB_PORT_H__ | ||
24 | |||
25 | #include <fcb/bfa_fcb_vport.h> | ||
26 | /** | ||
27 | * fcs_port_fcb FCS port driver interfaces | ||
28 | */ | ||
29 | |||
30 | /* | ||
31 | * Forward declarations | ||
32 | */ | ||
33 | struct bfad_port_s; | ||
34 | |||
35 | /* | ||
36 | * Callback functions from BFA FCS to driver | ||
37 | */ | ||
38 | |||
39 | /** | ||
40 | * Call from FCS to driver module when a port is instantiated. The port | ||
41 | * can be a base port or a virtual port with in the base fabric or | ||
42 | * a virtual fabric. | ||
43 | * | ||
44 | * On this callback, driver is supposed to create scsi_host, scsi_tgt or | ||
45 | * network interfaces bases on ports personality/roles. | ||
46 | * | ||
47 | * base port of base fabric: vf_drv == NULL && vp_drv == NULL | ||
48 | * vport of base fabric: vf_drv == NULL && vp_drv != NULL | ||
49 | * base port of VF: vf_drv != NULL && vp_drv == NULL | ||
50 | * vport of VF: vf_drv != NULL && vp_drv != NULL | ||
51 | * | ||
52 | * @param[in] bfad - driver instance | ||
53 | * @param[in] port - FCS port instance | ||
54 | * @param[in] roles - port roles: IM, TM, IP | ||
55 | * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF) | ||
56 | * @param[in] vp_drv - vport driver instance, NULL if base port | ||
57 | * | ||
58 | * @return None | ||
59 | */ | ||
60 | struct bfad_port_s *bfa_fcb_port_new(struct bfad_s *bfad, | ||
61 | struct bfa_fcs_port_s *port, | ||
62 | enum bfa_port_role roles, struct bfad_vf_s *vf_drv, | ||
63 | struct bfad_vport_s *vp_drv); | ||
64 | |||
65 | /** | ||
66 | * Call from FCS to driver module when a port is deleted. The port | ||
67 | * can be a base port or a virtual port with in the base fabric or | ||
68 | * a virtual fabric. | ||
69 | * | ||
70 | * @param[in] bfad - driver instance | ||
71 | * @param[in] roles - port roles: IM, TM, IP | ||
72 | * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF) | ||
73 | * @param[in] vp_drv - vport driver instance, NULL if base port | ||
74 | * | ||
75 | * @return None | ||
76 | */ | ||
77 | void bfa_fcb_port_delete(struct bfad_s *bfad, enum bfa_port_role roles, | ||
78 | struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv); | ||
79 | |||
80 | /** | ||
81 | * Notification when port transitions to ONLINE state. | ||
82 | * | ||
83 | * Online notification is a logical link up for the local port. This | ||
84 | * notification is sent after a successfull FLOGI, or a successful | ||
85 | * link initialization in proviate-loop or N2N topologies. | ||
86 | * | ||
87 | * @param[in] bfad - driver instance | ||
88 | * @param[in] roles - port roles: IM, TM, IP | ||
89 | * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF) | ||
90 | * @param[in] vp_drv - vport driver instance, NULL if base port | ||
91 | * | ||
92 | * @return None | ||
93 | */ | ||
94 | void bfa_fcb_port_online(struct bfad_s *bfad, enum bfa_port_role roles, | ||
95 | struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv); | ||
96 | |||
97 | /** | ||
98 | * Notification when port transitions to OFFLINE state. | ||
99 | * | ||
100 | * Offline notification is a logical link down for the local port. | ||
101 | * | ||
102 | * @param[in] bfad - driver instance | ||
103 | * @param[in] roles - port roles: IM, TM, IP | ||
104 | * @param[in] vf_drv - VF driver instance, NULL if base fabric (no VF) | ||
105 | * @param[in] vp_drv - vport driver instance, NULL if base port | ||
106 | * | ||
107 | * @return None | ||
108 | */ | ||
109 | void bfa_fcb_port_offline(struct bfad_s *bfad, enum bfa_port_role roles, | ||
110 | struct bfad_vf_s *vf_drv, struct bfad_vport_s *vp_drv); | ||
111 | |||
112 | |||
113 | #endif /* __BFA_FCB_PORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h new file mode 100644 index 000000000000..e0261bb6d1c1 --- /dev/null +++ b/drivers/scsi/bfa/include/fcb/bfa_fcb_rport.h | |||
@@ -0,0 +1,80 @@ | |||
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 | * bfa_fcb_rport.h BFA FCS rport driver interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCB_RPORT_H__ | ||
23 | #define __BFA_FCB_RPORT_H__ | ||
24 | |||
25 | /** | ||
26 | * fcs_rport_fcb Remote port driver interfaces | ||
27 | */ | ||
28 | |||
29 | |||
30 | struct bfad_rport_s; | ||
31 | |||
32 | /* | ||
33 | * Callback functions from BFA FCS to driver | ||
34 | */ | ||
35 | |||
36 | /** | ||
37 | * Completion callback for bfa_fcs_rport_add(). | ||
38 | * | ||
39 | * @param[in] rport_drv - driver instance of rport | ||
40 | * | ||
41 | * @return None | ||
42 | */ | ||
43 | void bfa_fcb_rport_add(struct bfad_rport_s *rport_drv); | ||
44 | |||
45 | /** | ||
46 | * Completion callback for bfa_fcs_rport_remove(). | ||
47 | * | ||
48 | * @param[in] rport_drv - driver instance of rport | ||
49 | * | ||
50 | * @return None | ||
51 | */ | ||
52 | void bfa_fcb_rport_remove(struct bfad_rport_s *rport_drv); | ||
53 | |||
54 | /** | ||
55 | * Call to allocate a rport instance. | ||
56 | * | ||
57 | * @param[in] bfad - driver instance | ||
58 | * @param[out] rport - BFA FCS instance of rport | ||
59 | * @param[out] rport_drv - driver instance of rport | ||
60 | * | ||
61 | * @retval BFA_STATUS_OK - successfully allocated | ||
62 | * @retval BFA_STATUS_ENOMEM - cannot allocate | ||
63 | */ | ||
64 | bfa_status_t bfa_fcb_rport_alloc(struct bfad_s *bfad, | ||
65 | struct bfa_fcs_rport_s **rport, | ||
66 | struct bfad_rport_s **rport_drv); | ||
67 | |||
68 | /** | ||
69 | * Call to free rport memory resources. | ||
70 | * | ||
71 | * @param[in] bfad - driver instance | ||
72 | * @param[in] rport_drv - driver instance of rport | ||
73 | * | ||
74 | * @return None | ||
75 | */ | ||
76 | void bfa_fcb_rport_free(struct bfad_s *bfad, struct bfad_rport_s **rport_drv); | ||
77 | |||
78 | |||
79 | |||
80 | #endif /* __BFA_FCB_RPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h new file mode 100644 index 000000000000..cfd3fac0a4e2 --- /dev/null +++ b/drivers/scsi/bfa/include/fcb/bfa_fcb_vf.h | |||
@@ -0,0 +1,47 @@ | |||
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 | * bfa_fcb_vf.h BFA FCS virtual fabric driver interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCB_VF_H__ | ||
23 | #define __BFA_FCB_VF_H__ | ||
24 | |||
25 | /** | ||
26 | * fcs_vf_fcb Virtual fabric driver intrefaces | ||
27 | */ | ||
28 | |||
29 | |||
30 | struct bfad_vf_s; | ||
31 | |||
32 | /* | ||
33 | * Callback functions from BFA FCS to driver | ||
34 | */ | ||
35 | |||
36 | /** | ||
37 | * Completion callback for bfa_fcs_vf_stop(). | ||
38 | * | ||
39 | * @param[in] vf_drv - driver instance of vf | ||
40 | * | ||
41 | * @return None | ||
42 | */ | ||
43 | void bfa_fcb_vf_stop(struct bfad_vf_s *vf_drv); | ||
44 | |||
45 | |||
46 | |||
47 | #endif /* __BFA_FCB_VF_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h new file mode 100644 index 000000000000..a39f474c2fcf --- /dev/null +++ b/drivers/scsi/bfa/include/fcb/bfa_fcb_vport.h | |||
@@ -0,0 +1,47 @@ | |||
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 | * bfa_fcb_vport.h BFA FCS virtual port driver interfaces | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCB_VPORT_H__ | ||
23 | #define __BFA_FCB_VPORT_H__ | ||
24 | |||
25 | /** | ||
26 | * fcs_vport_fcb Virtual port driver interfaces | ||
27 | */ | ||
28 | |||
29 | |||
30 | struct bfad_vport_s; | ||
31 | |||
32 | /* | ||
33 | * Callback functions from BFA FCS to driver | ||
34 | */ | ||
35 | |||
36 | /** | ||
37 | * Completion callback for bfa_fcs_vport_delete(). | ||
38 | * | ||
39 | * @param[in] vport_drv - driver instance of vport | ||
40 | * | ||
41 | * @return None | ||
42 | */ | ||
43 | void bfa_fcb_vport_delete(struct bfad_vport_s *vport_drv); | ||
44 | |||
45 | |||
46 | |||
47 | #endif /* __BFA_FCB_VPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs.h b/drivers/scsi/bfa/include/fcs/bfa_fcs.h new file mode 100644 index 000000000000..627669c65546 --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs.h | |||
@@ -0,0 +1,73 @@ | |||
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 | #ifndef __BFA_FCS_H__ | ||
19 | #define __BFA_FCS_H__ | ||
20 | |||
21 | #include <cs/bfa_debug.h> | ||
22 | #include <defs/bfa_defs_status.h> | ||
23 | #include <defs/bfa_defs_version.h> | ||
24 | #include <bfa.h> | ||
25 | #include <fcs/bfa_fcs_fabric.h> | ||
26 | |||
27 | #define BFA_FCS_OS_STR_LEN 64 | ||
28 | |||
29 | struct bfa_fcs_stats_s { | ||
30 | struct { | ||
31 | u32 untagged; /* untagged receive frames */ | ||
32 | u32 tagged; /* tagged receive frames */ | ||
33 | u32 vfid_unknown; /* VF id is unknown */ | ||
34 | } uf; | ||
35 | }; | ||
36 | |||
37 | struct bfa_fcs_driver_info_s { | ||
38 | u8 version[BFA_VERSION_LEN]; /* Driver Version */ | ||
39 | u8 host_machine_name[BFA_FCS_OS_STR_LEN]; | ||
40 | u8 host_os_name[BFA_FCS_OS_STR_LEN]; /* OS name and version */ | ||
41 | u8 host_os_patch[BFA_FCS_OS_STR_LEN];/* patch or service pack */ | ||
42 | u8 os_device_name[BFA_FCS_OS_STR_LEN]; /* Driver Device Name */ | ||
43 | }; | ||
44 | |||
45 | struct bfa_fcs_s { | ||
46 | struct bfa_s *bfa; /* corresponding BFA bfa instance */ | ||
47 | struct bfad_s *bfad; /* corresponding BDA driver instance */ | ||
48 | struct bfa_log_mod_s *logm; /* driver logging module instance */ | ||
49 | struct bfa_trc_mod_s *trcmod; /* tracing module */ | ||
50 | struct bfa_aen_s *aen; /* aen component */ | ||
51 | bfa_boolean_t vf_enabled; /* VF mode is enabled */ | ||
52 | bfa_boolean_t min_cfg; /* min cfg enabled/disabled */ | ||
53 | u16 port_vfid; /* port default VF ID */ | ||
54 | struct bfa_fcs_driver_info_s driver_info; | ||
55 | struct bfa_fcs_fabric_s fabric; /* base fabric state machine */ | ||
56 | struct bfa_fcs_stats_s stats; /* FCS statistics */ | ||
57 | struct bfa_wc_s wc; /* waiting counter */ | ||
58 | }; | ||
59 | |||
60 | /* | ||
61 | * bfa fcs API functions | ||
62 | */ | ||
63 | void bfa_fcs_init(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, | ||
64 | bfa_boolean_t min_cfg); | ||
65 | void bfa_fcs_driver_info_init(struct bfa_fcs_s *fcs, | ||
66 | struct bfa_fcs_driver_info_s *driver_info); | ||
67 | void bfa_fcs_exit(struct bfa_fcs_s *fcs); | ||
68 | void bfa_fcs_trc_init(struct bfa_fcs_s *fcs, struct bfa_trc_mod_s *trcmod); | ||
69 | void bfa_fcs_log_init(struct bfa_fcs_s *fcs, struct bfa_log_mod_s *logmod); | ||
70 | void bfa_fcs_aen_init(struct bfa_fcs_s *fcs, struct bfa_aen_s *aen); | ||
71 | void bfa_fcs_start(struct bfa_fcs_s *fcs); | ||
72 | |||
73 | #endif /* __BFA_FCS_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h new file mode 100644 index 000000000000..28c4c9ff08b3 --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_auth.h | |||
@@ -0,0 +1,82 @@ | |||
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 | #ifndef __BFA_FCS_AUTH_H__ | ||
19 | #define __BFA_FCS_AUTH_H__ | ||
20 | |||
21 | struct bfa_fcs_s; | ||
22 | |||
23 | #include <defs/bfa_defs_status.h> | ||
24 | #include <defs/bfa_defs_auth.h> | ||
25 | #include <defs/bfa_defs_vf.h> | ||
26 | #include <cs/bfa_q.h> | ||
27 | #include <cs/bfa_sm.h> | ||
28 | #include <defs/bfa_defs_pport.h> | ||
29 | #include <fcs/bfa_fcs_lport.h> | ||
30 | #include <protocol/fc_sp.h> | ||
31 | |||
32 | struct bfa_fcs_fabric_s; | ||
33 | |||
34 | |||
35 | |||
36 | struct bfa_fcs_auth_s { | ||
37 | bfa_sm_t sm; /* state machine */ | ||
38 | bfa_boolean_t policy; /* authentication enabled/disabled */ | ||
39 | enum bfa_auth_status status; /* authentication status */ | ||
40 | enum auth_rjt_codes rjt_code; /* auth reject status */ | ||
41 | enum auth_rjt_code_exps rjt_code_exp; /* auth reject reason */ | ||
42 | enum bfa_auth_algo algo; /* Authentication algorithm */ | ||
43 | struct bfa_auth_stats_s stats; /* Statistics */ | ||
44 | enum auth_dh_gid group; /* DH(diffie-hellman) Group */ | ||
45 | enum bfa_auth_secretsource source; /* Secret source */ | ||
46 | char secret[BFA_AUTH_SECRET_STRING_LEN]; | ||
47 | /* secret string */ | ||
48 | u8 secret_len; | ||
49 | /* secret string length */ | ||
50 | u8 nretries; | ||
51 | /* number of retries */ | ||
52 | struct bfa_fcs_fabric_s *fabric;/* pointer to fabric */ | ||
53 | u8 sentcode; /* pointer to response data */ | ||
54 | u8 *response; /* pointer to response data */ | ||
55 | struct bfa_timer_s delay_timer; /* delay timer */ | ||
56 | struct bfa_fcxp_s *fcxp; /* pointer to fcxp */ | ||
57 | struct bfa_fcxp_wqe_s fcxp_wqe; | ||
58 | }; | ||
59 | |||
60 | /** | ||
61 | * bfa fcs authentication public functions | ||
62 | */ | ||
63 | bfa_status_t bfa_fcs_auth_get_attr(struct bfa_fcs_s *port, | ||
64 | struct bfa_auth_attr_s *attr); | ||
65 | bfa_status_t bfa_fcs_auth_set_policy(struct bfa_fcs_s *port, | ||
66 | bfa_boolean_t policy); | ||
67 | enum bfa_auth_status bfa_fcs_auth_get_status(struct bfa_fcs_s *port); | ||
68 | bfa_status_t bfa_fcs_auth_set_algo(struct bfa_fcs_s *port, | ||
69 | enum bfa_auth_algo algo); | ||
70 | bfa_status_t bfa_fcs_auth_get_stats(struct bfa_fcs_s *port, | ||
71 | struct bfa_auth_stats_s *stats); | ||
72 | bfa_status_t bfa_fcs_auth_set_dh_group(struct bfa_fcs_s *port, int group); | ||
73 | bfa_status_t bfa_fcs_auth_set_secretstring(struct bfa_fcs_s *port, | ||
74 | char *secret); | ||
75 | bfa_status_t bfa_fcs_auth_set_secretstring_encrypt(struct bfa_fcs_s *port, | ||
76 | u32 secret[], u32 len); | ||
77 | bfa_status_t bfa_fcs_auth_set_secretsource(struct bfa_fcs_s *port, | ||
78 | enum bfa_auth_secretsource src); | ||
79 | bfa_status_t bfa_fcs_auth_reset_stats(struct bfa_fcs_s *port); | ||
80 | bfa_status_t bfa_fcs_auth_reinit(struct bfa_fcs_s *port); | ||
81 | |||
82 | #endif /* __BFA_FCS_AUTH_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h new file mode 100644 index 000000000000..4ffd2242d3de --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_fabric.h | |||
@@ -0,0 +1,112 @@ | |||
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 | #ifndef __BFA_FCS_FABRIC_H__ | ||
19 | #define __BFA_FCS_FABRIC_H__ | ||
20 | |||
21 | struct bfa_fcs_s; | ||
22 | |||
23 | #include <defs/bfa_defs_status.h> | ||
24 | #include <defs/bfa_defs_vf.h> | ||
25 | #include <cs/bfa_q.h> | ||
26 | #include <cs/bfa_sm.h> | ||
27 | #include <defs/bfa_defs_pport.h> | ||
28 | #include <fcs/bfa_fcs_lport.h> | ||
29 | #include <protocol/fc_sp.h> | ||
30 | #include <fcs/bfa_fcs_auth.h> | ||
31 | |||
32 | /* | ||
33 | * forward declaration | ||
34 | */ | ||
35 | struct bfad_vf_s; | ||
36 | |||
37 | enum bfa_fcs_fabric_type { | ||
38 | BFA_FCS_FABRIC_UNKNOWN = 0, | ||
39 | BFA_FCS_FABRIC_SWITCHED = 1, | ||
40 | BFA_FCS_FABRIC_PLOOP = 2, | ||
41 | BFA_FCS_FABRIC_N2N = 3, | ||
42 | }; | ||
43 | |||
44 | |||
45 | struct bfa_fcs_fabric_s { | ||
46 | struct list_head qe; /* queue element */ | ||
47 | bfa_sm_t sm; /* state machine */ | ||
48 | struct bfa_fcs_s *fcs; /* FCS instance */ | ||
49 | struct bfa_fcs_port_s bport; /* base logical port */ | ||
50 | enum bfa_fcs_fabric_type fab_type; /* fabric type */ | ||
51 | enum bfa_pport_type oper_type; /* current link topology */ | ||
52 | u8 is_vf; /* is virtual fabric? */ | ||
53 | u8 is_npiv; /* is NPIV supported ? */ | ||
54 | u8 is_auth; /* is Security/Auth supported ? */ | ||
55 | u16 bb_credit; /* BB credit from fabric */ | ||
56 | u16 vf_id; /* virtual fabric ID */ | ||
57 | u16 num_vports; /* num vports */ | ||
58 | u16 rsvd; | ||
59 | struct list_head vport_q; /* queue of virtual ports */ | ||
60 | struct list_head vf_q; /* queue of virtual fabrics */ | ||
61 | struct bfad_vf_s *vf_drv; /* driver vf structure */ | ||
62 | struct bfa_timer_s link_timer; /* Link Failure timer. Vport */ | ||
63 | wwn_t fabric_name; /* attached fabric name */ | ||
64 | bfa_boolean_t auth_reqd; /* authentication required */ | ||
65 | struct bfa_timer_s delay_timer; /* delay timer */ | ||
66 | union { | ||
67 | u16 swp_vfid;/* switch port VF id */ | ||
68 | } event_arg; | ||
69 | struct bfa_fcs_auth_s auth; /* authentication config */ | ||
70 | struct bfa_wc_s wc; /* wait counter for delete */ | ||
71 | struct bfa_vf_stats_s stats; /* fabric/vf stats */ | ||
72 | struct bfa_lps_s *lps; /* lport login services */ | ||
73 | u8 fabric_ip_addr[BFA_FCS_FABRIC_IPADDR_SZ]; /* attached | ||
74 | * fabric's ip addr | ||
75 | */ | ||
76 | }; | ||
77 | |||
78 | #define bfa_fcs_fabric_npiv_capable(__f) (__f)->is_npiv | ||
79 | #define bfa_fcs_fabric_is_switched(__f) \ | ||
80 | ((__f)->fab_type == BFA_FCS_FABRIC_SWITCHED) | ||
81 | |||
82 | /** | ||
83 | * The design calls for a single implementation of base fabric and vf. | ||
84 | */ | ||
85 | #define bfa_fcs_vf_t struct bfa_fcs_fabric_s | ||
86 | |||
87 | struct bfa_vf_event_s { | ||
88 | u32 undefined; | ||
89 | }; | ||
90 | |||
91 | /** | ||
92 | * bfa fcs vf public functions | ||
93 | */ | ||
94 | bfa_status_t bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id); | ||
95 | bfa_status_t bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs); | ||
96 | bfa_status_t bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, | ||
97 | u16 vf_id, struct bfa_port_cfg_s *port_cfg, | ||
98 | struct bfad_vf_s *vf_drv); | ||
99 | bfa_status_t bfa_fcs_vf_delete(bfa_fcs_vf_t *vf); | ||
100 | void bfa_fcs_vf_start(bfa_fcs_vf_t *vf); | ||
101 | bfa_status_t bfa_fcs_vf_stop(bfa_fcs_vf_t *vf); | ||
102 | void bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs); | ||
103 | void bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs); | ||
104 | void bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr); | ||
105 | void bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, | ||
106 | struct bfa_vf_stats_s *vf_stats); | ||
107 | void bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf); | ||
108 | void bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t vpwwn[], int *nports); | ||
109 | bfa_fcs_vf_t *bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id); | ||
110 | struct bfad_vf_s *bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf); | ||
111 | |||
112 | #endif /* __BFA_FCS_FABRIC_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h new file mode 100644 index 000000000000..e719f2c3eb35 --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_fcpim.h | |||
@@ -0,0 +1,131 @@ | |||
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 | * bfa_fcs_fcpim.h BFA FCS FCP Initiator Mode interfaces/defines. | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCS_FCPIM_H__ | ||
23 | #define __BFA_FCS_FCPIM_H__ | ||
24 | |||
25 | #include <defs/bfa_defs_status.h> | ||
26 | #include <defs/bfa_defs_itnim.h> | ||
27 | #include <fcs/bfa_fcs.h> | ||
28 | #include <fcs/bfa_fcs_rport.h> | ||
29 | #include <fcs/bfa_fcs_lport.h> | ||
30 | #include <bfa_fcpim.h> | ||
31 | |||
32 | /* | ||
33 | * forward declarations | ||
34 | */ | ||
35 | struct bfad_itnim_s; | ||
36 | |||
37 | struct bfa_fcs_itnim_s { | ||
38 | bfa_sm_t sm; /* state machine */ | ||
39 | struct bfa_fcs_rport_s *rport; /* parent remote rport */ | ||
40 | struct bfad_itnim_s *itnim_drv; /* driver peer instance */ | ||
41 | struct bfa_fcs_s *fcs; /* fcs instance */ | ||
42 | struct bfa_timer_s timer; /* timer functions */ | ||
43 | struct bfa_itnim_s *bfa_itnim; /* BFA itnim struct */ | ||
44 | bfa_boolean_t seq_rec; /* seq recovery support */ | ||
45 | bfa_boolean_t rec_support; /* REC supported */ | ||
46 | bfa_boolean_t conf_comp; /* FCP_CONF support */ | ||
47 | bfa_boolean_t task_retry_id; /* task retry id supp */ | ||
48 | struct bfa_fcxp_wqe_s fcxp_wqe; /* wait qelem for fcxp */ | ||
49 | struct bfa_fcxp_s *fcxp; /* FCXP in use */ | ||
50 | struct bfa_itnim_stats_s stats; /* itn statistics */ | ||
51 | }; | ||
52 | |||
53 | |||
54 | static inline struct bfad_port_s * | ||
55 | bfa_fcs_itnim_get_drvport(struct bfa_fcs_itnim_s *itnim) | ||
56 | { | ||
57 | return itnim->rport->port->bfad_port; | ||
58 | } | ||
59 | |||
60 | |||
61 | static inline struct bfa_fcs_port_s * | ||
62 | bfa_fcs_itnim_get_port(struct bfa_fcs_itnim_s *itnim) | ||
63 | { | ||
64 | return itnim->rport->port; | ||
65 | } | ||
66 | |||
67 | |||
68 | static inline wwn_t | ||
69 | bfa_fcs_itnim_get_nwwn(struct bfa_fcs_itnim_s *itnim) | ||
70 | { | ||
71 | return itnim->rport->nwwn; | ||
72 | } | ||
73 | |||
74 | |||
75 | static inline wwn_t | ||
76 | bfa_fcs_itnim_get_pwwn(struct bfa_fcs_itnim_s *itnim) | ||
77 | { | ||
78 | return itnim->rport->pwwn; | ||
79 | } | ||
80 | |||
81 | |||
82 | static inline u32 | ||
83 | bfa_fcs_itnim_get_fcid(struct bfa_fcs_itnim_s *itnim) | ||
84 | { | ||
85 | return itnim->rport->pid; | ||
86 | } | ||
87 | |||
88 | |||
89 | static inline u32 | ||
90 | bfa_fcs_itnim_get_maxfrsize(struct bfa_fcs_itnim_s *itnim) | ||
91 | { | ||
92 | return itnim->rport->maxfrsize; | ||
93 | } | ||
94 | |||
95 | |||
96 | static inline enum fc_cos | ||
97 | bfa_fcs_itnim_get_cos(struct bfa_fcs_itnim_s *itnim) | ||
98 | { | ||
99 | return itnim->rport->fc_cos; | ||
100 | } | ||
101 | |||
102 | |||
103 | static inline struct bfad_itnim_s * | ||
104 | bfa_fcs_itnim_get_drvitn(struct bfa_fcs_itnim_s *itnim) | ||
105 | { | ||
106 | return itnim->itnim_drv; | ||
107 | } | ||
108 | |||
109 | |||
110 | static inline struct bfa_itnim_s * | ||
111 | bfa_fcs_itnim_get_halitn(struct bfa_fcs_itnim_s *itnim) | ||
112 | { | ||
113 | return itnim->bfa_itnim; | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * bfa fcs FCP Initiator mode API functions | ||
118 | */ | ||
119 | void bfa_fcs_itnim_get_attr(struct bfa_fcs_itnim_s *itnim, | ||
120 | struct bfa_itnim_attr_s *attr); | ||
121 | void bfa_fcs_itnim_get_stats(struct bfa_fcs_itnim_s *itnim, | ||
122 | struct bfa_itnim_stats_s *stats); | ||
123 | struct bfa_fcs_itnim_s *bfa_fcs_itnim_lookup(struct bfa_fcs_port_s *port, | ||
124 | wwn_t rpwwn); | ||
125 | bfa_status_t bfa_fcs_itnim_attr_get(struct bfa_fcs_port_s *port, wwn_t rpwwn, | ||
126 | struct bfa_itnim_attr_s *attr); | ||
127 | bfa_status_t bfa_fcs_itnim_stats_get(struct bfa_fcs_port_s *port, wwn_t rpwwn, | ||
128 | struct bfa_itnim_stats_s *stats); | ||
129 | bfa_status_t bfa_fcs_itnim_stats_clear(struct bfa_fcs_port_s *port, | ||
130 | wwn_t rpwwn); | ||
131 | #endif /* __BFA_FCS_FCPIM_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h new file mode 100644 index 000000000000..4441fffc9c82 --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_fdmi.h | |||
@@ -0,0 +1,63 @@ | |||
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 | * bfa_fcs_fdmi.h BFA fcs fdmi module public interface | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCS_FDMI_H__ | ||
23 | #define __BFA_FCS_FDMI_H__ | ||
24 | #include <bfa_os_inc.h> | ||
25 | #include <protocol/fdmi.h> | ||
26 | |||
27 | #define BFA_FCS_FDMI_SUPORTED_SPEEDS (FDMI_TRANS_SPEED_1G | \ | ||
28 | FDMI_TRANS_SPEED_2G | \ | ||
29 | FDMI_TRANS_SPEED_4G | \ | ||
30 | FDMI_TRANS_SPEED_8G) | ||
31 | |||
32 | /* | ||
33 | * HBA Attribute Block : BFA internal representation. Note : Some variable | ||
34 | * sizes have been trimmed to suit BFA For Ex : Model will be "Brocade". Based | ||
35 | * on this the size has been reduced to 16 bytes from the standard's 64 bytes. | ||
36 | */ | ||
37 | struct bfa_fcs_fdmi_hba_attr_s { | ||
38 | wwn_t node_name; | ||
39 | u8 manufacturer[64]; | ||
40 | u8 serial_num[64]; | ||
41 | u8 model[16]; | ||
42 | u8 model_desc[256]; | ||
43 | u8 hw_version[8]; | ||
44 | u8 driver_version[8]; | ||
45 | u8 option_rom_ver[BFA_VERSION_LEN]; | ||
46 | u8 fw_version[8]; | ||
47 | u8 os_name[256]; | ||
48 | u32 max_ct_pyld; | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * Port Attribute Block | ||
53 | */ | ||
54 | struct bfa_fcs_fdmi_port_attr_s { | ||
55 | u8 supp_fc4_types[32]; /* supported FC4 types */ | ||
56 | u32 supp_speed; /* supported speed */ | ||
57 | u32 curr_speed; /* current Speed */ | ||
58 | u32 max_frm_size; /* max frame size */ | ||
59 | u8 os_device_name[256]; /* OS device Name */ | ||
60 | u8 host_name[256]; /* host name */ | ||
61 | }; | ||
62 | |||
63 | #endif /* __BFA_FCS_FDMI_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h new file mode 100644 index 000000000000..b85cba884b96 --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_lport.h | |||
@@ -0,0 +1,226 @@ | |||
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 | * bfa_fcs_port.h BFA fcs port module public interface | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCS_PORT_H__ | ||
23 | #define __BFA_FCS_PORT_H__ | ||
24 | |||
25 | #include <defs/bfa_defs_status.h> | ||
26 | #include <defs/bfa_defs_port.h> | ||
27 | #include <defs/bfa_defs_pport.h> | ||
28 | #include <defs/bfa_defs_rport.h> | ||
29 | #include <cs/bfa_q.h> | ||
30 | #include <bfa_svc.h> | ||
31 | #include <cs/bfa_wc.h> | ||
32 | |||
33 | struct bfa_fcs_s; | ||
34 | struct bfa_fcs_fabric_s; | ||
35 | |||
36 | /* | ||
37 | * @todo : need to move to a global config file. | ||
38 | * Maximum Vports supported per physical port or vf. | ||
39 | */ | ||
40 | #define BFA_FCS_MAX_VPORTS_SUPP_CB 255 | ||
41 | #define BFA_FCS_MAX_VPORTS_SUPP_CT 191 | ||
42 | |||
43 | /* | ||
44 | * @todo : need to move to a global config file. | ||
45 | * Maximum Rports supported per port (physical/logical). | ||
46 | */ | ||
47 | #define BFA_FCS_MAX_RPORTS_SUPP 256 /* @todo : tentative value */ | ||
48 | |||
49 | |||
50 | struct bfa_fcs_port_ns_s { | ||
51 | bfa_sm_t sm; /* state machine */ | ||
52 | struct bfa_timer_s timer; | ||
53 | struct bfa_fcs_port_s *port; /* parent port */ | ||
54 | struct bfa_fcxp_s *fcxp; | ||
55 | struct bfa_fcxp_wqe_s fcxp_wqe; | ||
56 | }; | ||
57 | |||
58 | |||
59 | struct bfa_fcs_port_scn_s { | ||
60 | bfa_sm_t sm; /* state machine */ | ||
61 | struct bfa_timer_s timer; | ||
62 | struct bfa_fcs_port_s *port; /* parent port */ | ||
63 | struct bfa_fcxp_s *fcxp; | ||
64 | struct bfa_fcxp_wqe_s fcxp_wqe; | ||
65 | }; | ||
66 | |||
67 | |||
68 | struct bfa_fcs_port_fdmi_s { | ||
69 | bfa_sm_t sm; /* state machine */ | ||
70 | struct bfa_timer_s timer; | ||
71 | struct bfa_fcs_port_ms_s *ms; /* parent ms */ | ||
72 | struct bfa_fcxp_s *fcxp; | ||
73 | struct bfa_fcxp_wqe_s fcxp_wqe; | ||
74 | u8 retry_cnt; /* retry count */ | ||
75 | u8 rsvd[3]; | ||
76 | }; | ||
77 | |||
78 | |||
79 | struct bfa_fcs_port_ms_s { | ||
80 | bfa_sm_t sm; /* state machine */ | ||
81 | struct bfa_timer_s timer; | ||
82 | struct bfa_fcs_port_s *port; /* parent port */ | ||
83 | struct bfa_fcxp_s *fcxp; | ||
84 | struct bfa_fcxp_wqe_s fcxp_wqe; | ||
85 | struct bfa_fcs_port_fdmi_s fdmi; /* FDMI component of MS */ | ||
86 | u8 retry_cnt; /* retry count */ | ||
87 | u8 rsvd[3]; | ||
88 | }; | ||
89 | |||
90 | |||
91 | struct bfa_fcs_port_fab_s { | ||
92 | struct bfa_fcs_port_ns_s ns; /* NS component of port */ | ||
93 | struct bfa_fcs_port_scn_s scn; /* scn component of port */ | ||
94 | struct bfa_fcs_port_ms_s ms; /* MS component of port */ | ||
95 | }; | ||
96 | |||
97 | |||
98 | |||
99 | #define MAX_ALPA_COUNT 127 | ||
100 | |||
101 | struct bfa_fcs_port_loop_s { | ||
102 | u8 num_alpa; /* Num of ALPA entries in the map */ | ||
103 | u8 alpa_pos_map[MAX_ALPA_COUNT]; /* ALPA Positional | ||
104 | *Map */ | ||
105 | struct bfa_fcs_port_s *port; /* parent port */ | ||
106 | }; | ||
107 | |||
108 | |||
109 | |||
110 | struct bfa_fcs_port_n2n_s { | ||
111 | u32 rsvd; | ||
112 | u16 reply_oxid; /* ox_id from the req flogi to be | ||
113 | *used in flogi acc */ | ||
114 | wwn_t rem_port_wwn; /* Attached port's wwn */ | ||
115 | }; | ||
116 | |||
117 | |||
118 | union bfa_fcs_port_topo_u { | ||
119 | struct bfa_fcs_port_fab_s pfab; | ||
120 | struct bfa_fcs_port_loop_s ploop; | ||
121 | struct bfa_fcs_port_n2n_s pn2n; | ||
122 | }; | ||
123 | |||
124 | |||
125 | struct bfa_fcs_port_s { | ||
126 | struct list_head qe; /* used by port/vport */ | ||
127 | bfa_sm_t sm; /* state machine */ | ||
128 | struct bfa_fcs_fabric_s *fabric; /* parent fabric */ | ||
129 | struct bfa_port_cfg_s port_cfg; /* port configuration */ | ||
130 | struct bfa_timer_s link_timer; /* timer for link offline */ | ||
131 | u32 pid : 24; /* FC address */ | ||
132 | u8 lp_tag; /* lport tag */ | ||
133 | u16 num_rports; /* Num of r-ports */ | ||
134 | struct list_head rport_q; /* queue of discovered r-ports */ | ||
135 | struct bfa_fcs_s *fcs; /* FCS instance */ | ||
136 | union bfa_fcs_port_topo_u port_topo; /* fabric/loop/n2n details */ | ||
137 | struct bfad_port_s *bfad_port; /* driver peer instance */ | ||
138 | struct bfa_fcs_vport_s *vport; /* NULL for base ports */ | ||
139 | struct bfa_fcxp_s *fcxp; | ||
140 | struct bfa_fcxp_wqe_s fcxp_wqe; | ||
141 | struct bfa_port_stats_s stats; | ||
142 | struct bfa_wc_s wc; /* waiting counter for events */ | ||
143 | }; | ||
144 | |||
145 | #define bfa_fcs_lport_t struct bfa_fcs_port_s | ||
146 | |||
147 | /** | ||
148 | * Symbolic Name related defines | ||
149 | * Total bytes 255. | ||
150 | * Physical Port's symbolic name 128 bytes. | ||
151 | * For Vports, Vport's symbolic name is appended to the Physical port's | ||
152 | * Symbolic Name. | ||
153 | * | ||
154 | * Physical Port's symbolic name Format : (Total 128 bytes) | ||
155 | * Adapter Model number/name : 12 bytes | ||
156 | * Driver Version : 10 bytes | ||
157 | * Host Machine Name : 30 bytes | ||
158 | * Host OS Info : 48 bytes | ||
159 | * Host OS PATCH Info : 16 bytes | ||
160 | * ( remaining 12 bytes reserved to be used for separator) | ||
161 | */ | ||
162 | #define BFA_FCS_PORT_SYMBNAME_SEPARATOR " | " | ||
163 | |||
164 | #define BFA_FCS_PORT_SYMBNAME_MODEL_SZ 12 | ||
165 | #define BFA_FCS_PORT_SYMBNAME_VERSION_SZ 10 | ||
166 | #define BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ 30 | ||
167 | #define BFA_FCS_PORT_SYMBNAME_OSINFO_SZ 48 | ||
168 | #define BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ 16 | ||
169 | |||
170 | /** | ||
171 | * Get FC port ID for a logical port. | ||
172 | */ | ||
173 | #define bfa_fcs_port_get_fcid(_lport) ((_lport)->pid) | ||
174 | #define bfa_fcs_port_get_pwwn(_lport) ((_lport)->port_cfg.pwwn) | ||
175 | #define bfa_fcs_port_get_nwwn(_lport) ((_lport)->port_cfg.nwwn) | ||
176 | #define bfa_fcs_port_get_psym_name(_lport) ((_lport)->port_cfg.sym_name) | ||
177 | #define bfa_fcs_port_is_initiator(_lport) \ | ||
178 | ((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_IM) | ||
179 | #define bfa_fcs_port_is_target(_lport) \ | ||
180 | ((_lport)->port_cfg.roles & BFA_PORT_ROLE_FCP_TM) | ||
181 | #define bfa_fcs_port_get_nrports(_lport) \ | ||
182 | ((_lport) ? (_lport)->num_rports : 0) | ||
183 | |||
184 | static inline struct bfad_port_s * | ||
185 | bfa_fcs_port_get_drvport(struct bfa_fcs_port_s *port) | ||
186 | { | ||
187 | return port->bfad_port; | ||
188 | } | ||
189 | |||
190 | |||
191 | #define bfa_fcs_port_get_opertype(_lport) (_lport)->fabric->oper_type | ||
192 | |||
193 | |||
194 | #define bfa_fcs_port_get_fabric_name(_lport) (_lport)->fabric->fabric_name | ||
195 | |||
196 | |||
197 | #define bfa_fcs_port_get_fabric_ipaddr(_lport) (_lport)->fabric->fabric_ip_addr | ||
198 | |||
199 | /** | ||
200 | * bfa fcs port public functions | ||
201 | */ | ||
202 | void bfa_fcs_cfg_base_port(struct bfa_fcs_s *fcs, | ||
203 | struct bfa_port_cfg_s *port_cfg); | ||
204 | struct bfa_fcs_port_s *bfa_fcs_get_base_port(struct bfa_fcs_s *fcs); | ||
205 | void bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, | ||
206 | wwn_t rport_wwns[], int *nrports); | ||
207 | |||
208 | wwn_t bfa_fcs_port_get_rport(struct bfa_fcs_port_s *port, wwn_t wwn, | ||
209 | int index, int nrports, bfa_boolean_t bwwn); | ||
210 | |||
211 | struct bfa_fcs_port_s *bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, | ||
212 | u16 vf_id, wwn_t lpwwn); | ||
213 | |||
214 | void bfa_fcs_port_get_info(struct bfa_fcs_port_s *port, | ||
215 | struct bfa_port_info_s *port_info); | ||
216 | void bfa_fcs_port_get_attr(struct bfa_fcs_port_s *port, | ||
217 | struct bfa_port_attr_s *port_attr); | ||
218 | void bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port, | ||
219 | struct bfa_port_stats_s *port_stats); | ||
220 | void bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port); | ||
221 | enum bfa_pport_speed bfa_fcs_port_get_rport_max_speed( | ||
222 | struct bfa_fcs_port_s *port); | ||
223 | void bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port); | ||
224 | void bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port); | ||
225 | |||
226 | #endif /* __BFA_FCS_PORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h new file mode 100644 index 000000000000..702b95b76c2d --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_rport.h | |||
@@ -0,0 +1,104 @@ | |||
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 | #ifndef __BFA_FCS_RPORT_H__ | ||
19 | #define __BFA_FCS_RPORT_H__ | ||
20 | |||
21 | #include <defs/bfa_defs_status.h> | ||
22 | #include <cs/bfa_q.h> | ||
23 | #include <fcs/bfa_fcs.h> | ||
24 | #include <defs/bfa_defs_rport.h> | ||
25 | |||
26 | #define BFA_FCS_RPORT_DEF_DEL_TIMEOUT 90 /* in secs */ | ||
27 | /* | ||
28 | * forward declarations | ||
29 | */ | ||
30 | struct bfad_rport_s; | ||
31 | |||
32 | struct bfa_fcs_itnim_s; | ||
33 | struct bfa_fcs_tin_s; | ||
34 | struct bfa_fcs_iprp_s; | ||
35 | |||
36 | /* Rport Features (RPF) */ | ||
37 | struct bfa_fcs_rpf_s { | ||
38 | bfa_sm_t sm; /* state machine */ | ||
39 | struct bfa_fcs_rport_s *rport; /* parent rport */ | ||
40 | struct bfa_timer_s timer; /* general purpose timer */ | ||
41 | struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */ | ||
42 | struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */ | ||
43 | int rpsc_retries; /* max RPSC retry attempts */ | ||
44 | enum bfa_pport_speed rpsc_speed; /* Current Speed from RPSC. | ||
45 | * O if RPSC fails */ | ||
46 | enum bfa_pport_speed assigned_speed; /* Speed assigned by the user. | ||
47 | * will be used if RPSC is not | ||
48 | * supported by the rport */ | ||
49 | }; | ||
50 | |||
51 | struct bfa_fcs_rport_s { | ||
52 | struct list_head qe; /* used by port/vport */ | ||
53 | struct bfa_fcs_port_s *port; /* parent FCS port */ | ||
54 | struct bfa_fcs_s *fcs; /* fcs instance */ | ||
55 | struct bfad_rport_s *rp_drv; /* driver peer instance */ | ||
56 | u32 pid; /* port ID of rport */ | ||
57 | u16 maxfrsize; /* maximum frame size */ | ||
58 | u16 reply_oxid; /* OX_ID of inbound requests */ | ||
59 | enum fc_cos fc_cos; /* FC classes of service supp */ | ||
60 | bfa_boolean_t cisc; /* CISC capable device */ | ||
61 | wwn_t pwwn; /* port wwn of rport */ | ||
62 | wwn_t nwwn; /* node wwn of rport */ | ||
63 | struct bfa_rport_symname_s psym_name; /* port symbolic name */ | ||
64 | bfa_sm_t sm; /* state machine */ | ||
65 | struct bfa_timer_s timer; /* general purpose timer */ | ||
66 | struct bfa_fcs_itnim_s *itnim; /* ITN initiator mode role */ | ||
67 | struct bfa_fcs_tin_s *tin; /* ITN initiator mode role */ | ||
68 | struct bfa_fcs_iprp_s *iprp; /* IP/FC role */ | ||
69 | struct bfa_rport_s *bfa_rport; /* BFA Rport */ | ||
70 | struct bfa_fcxp_s *fcxp; /* FCXP needed for discarding */ | ||
71 | int plogi_retries; /* max plogi retry attempts */ | ||
72 | int ns_retries; /* max NS query retry attempts */ | ||
73 | struct bfa_fcxp_wqe_s fcxp_wqe; /* fcxp wait queue element */ | ||
74 | struct bfa_rport_stats_s stats; /* rport stats */ | ||
75 | enum bfa_rport_function scsi_function; /* Initiator/Target */ | ||
76 | struct bfa_fcs_rpf_s rpf; /* Rport features module */ | ||
77 | }; | ||
78 | |||
79 | static inline struct bfa_rport_s * | ||
80 | bfa_fcs_rport_get_halrport(struct bfa_fcs_rport_s *rport) | ||
81 | { | ||
82 | return rport->bfa_rport; | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * bfa fcs rport API functions | ||
87 | */ | ||
88 | bfa_status_t bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn, | ||
89 | struct bfa_fcs_rport_s *rport, | ||
90 | struct bfad_rport_s *rport_drv); | ||
91 | bfa_status_t bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport); | ||
92 | void bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, | ||
93 | struct bfa_rport_attr_s *attr); | ||
94 | void bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport, | ||
95 | struct bfa_rport_stats_s *stats); | ||
96 | void bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport); | ||
97 | struct bfa_fcs_rport_s *bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port, | ||
98 | wwn_t rpwwn); | ||
99 | struct bfa_fcs_rport_s *bfa_fcs_rport_lookup_by_nwwn( | ||
100 | struct bfa_fcs_port_s *port, wwn_t rnwwn); | ||
101 | void bfa_fcs_rport_set_del_timeout(u8 rport_tmo); | ||
102 | void bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, | ||
103 | enum bfa_pport_speed speed); | ||
104 | #endif /* __BFA_FCS_RPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h new file mode 100644 index 000000000000..cd33f2cd5c34 --- /dev/null +++ b/drivers/scsi/bfa/include/fcs/bfa_fcs_vport.h | |||
@@ -0,0 +1,63 @@ | |||
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 | * bfa_fcs_vport.h BFA fcs vport module public interface | ||
20 | */ | ||
21 | |||
22 | #ifndef __BFA_FCS_VPORT_H__ | ||
23 | #define __BFA_FCS_VPORT_H__ | ||
24 | |||
25 | #include <defs/bfa_defs_status.h> | ||
26 | #include <defs/bfa_defs_port.h> | ||
27 | #include <defs/bfa_defs_vport.h> | ||
28 | #include <fcs/bfa_fcs.h> | ||
29 | #include <fcb/bfa_fcb_vport.h> | ||
30 | |||
31 | struct bfa_fcs_vport_s { | ||
32 | struct list_head qe; /* queue elem */ | ||
33 | bfa_sm_t sm; /* state machine */ | ||
34 | bfa_fcs_lport_t lport; /* logical port */ | ||
35 | struct bfa_timer_s timer; /* general purpose timer */ | ||
36 | struct bfad_vport_s *vport_drv; /* Driver private */ | ||
37 | struct bfa_vport_stats_s vport_stats; /* vport statistics */ | ||
38 | struct bfa_lps_s *lps; /* Lport login service */ | ||
39 | int fdisc_retries; | ||
40 | }; | ||
41 | |||
42 | #define bfa_fcs_vport_get_port(vport) \ | ||
43 | ((struct bfa_fcs_port_s *)(&vport->port)) | ||
44 | |||
45 | /** | ||
46 | * bfa fcs vport public functions | ||
47 | */ | ||
48 | bfa_status_t bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, | ||
49 | struct bfa_fcs_s *fcs, u16 vf_id, | ||
50 | struct bfa_port_cfg_s *port_cfg, | ||
51 | struct bfad_vport_s *vport_drv); | ||
52 | bfa_status_t bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport); | ||
53 | bfa_status_t bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport); | ||
54 | bfa_status_t bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport); | ||
55 | void bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, | ||
56 | struct bfa_vport_attr_s *vport_attr); | ||
57 | void bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, | ||
58 | struct bfa_vport_stats_s *vport_stats); | ||
59 | void bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport); | ||
60 | struct bfa_fcs_vport_s *bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, | ||
61 | u16 vf_id, wwn_t vpwwn); | ||
62 | |||
63 | #endif /* __BFA_FCS_VPORT_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/log/bfa_log_fcs.h b/drivers/scsi/bfa/include/log/bfa_log_fcs.h new file mode 100644 index 000000000000..b6f5df8827f8 --- /dev/null +++ b/drivers/scsi/bfa/include/log/bfa_log_fcs.h | |||
@@ -0,0 +1,28 @@ | |||
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 | * messages define for FCS Module | ||
20 | */ | ||
21 | #ifndef __BFA_LOG_FCS_H__ | ||
22 | #define __BFA_LOG_FCS_H__ | ||
23 | #include <cs/bfa_log.h> | ||
24 | #define BFA_LOG_FCS_FABRIC_NOSWITCH \ | ||
25 | (((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 1) | ||
26 | #define BFA_LOG_FCS_FABRIC_ISOLATED \ | ||
27 | (((u32) BFA_LOG_FCS_ID << BFA_LOG_MODID_OFFSET) | 2) | ||
28 | #endif | ||
diff --git a/drivers/scsi/bfa/include/log/bfa_log_hal.h b/drivers/scsi/bfa/include/log/bfa_log_hal.h new file mode 100644 index 000000000000..0412aea2ec30 --- /dev/null +++ b/drivers/scsi/bfa/include/log/bfa_log_hal.h | |||
@@ -0,0 +1,30 @@ | |||
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 | /* messages define for HAL Module */ | ||
19 | #ifndef __BFA_LOG_HAL_H__ | ||
20 | #define __BFA_LOG_HAL_H__ | ||
21 | #include <cs/bfa_log.h> | ||
22 | #define BFA_LOG_HAL_ASSERT \ | ||
23 | (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 1) | ||
24 | #define BFA_LOG_HAL_HEARTBEAT_FAILURE \ | ||
25 | (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 2) | ||
26 | #define BFA_LOG_HAL_FCPIM_PARM_INVALID \ | ||
27 | (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 3) | ||
28 | #define BFA_LOG_HAL_SM_ASSERT \ | ||
29 | (((u32) BFA_LOG_HAL_ID << BFA_LOG_MODID_OFFSET) | 4) | ||
30 | #endif | ||
diff --git a/drivers/scsi/bfa/include/log/bfa_log_linux.h b/drivers/scsi/bfa/include/log/bfa_log_linux.h new file mode 100644 index 000000000000..317c0547ee16 --- /dev/null +++ b/drivers/scsi/bfa/include/log/bfa_log_linux.h | |||
@@ -0,0 +1,44 @@ | |||
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 | /* messages define for LINUX Module */ | ||
19 | #ifndef __BFA_LOG_LINUX_H__ | ||
20 | #define __BFA_LOG_LINUX_H__ | ||
21 | #include <cs/bfa_log.h> | ||
22 | #define BFA_LOG_LINUX_DEVICE_CLAIMED \ | ||
23 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 1) | ||
24 | #define BFA_LOG_LINUX_HASH_INIT_FAILED \ | ||
25 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 2) | ||
26 | #define BFA_LOG_LINUX_SYSFS_FAILED \ | ||
27 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 3) | ||
28 | #define BFA_LOG_LINUX_MEM_ALLOC_FAILED \ | ||
29 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 4) | ||
30 | #define BFA_LOG_LINUX_DRIVER_REGISTRATION_FAILED \ | ||
31 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 5) | ||
32 | #define BFA_LOG_LINUX_ITNIM_FREE \ | ||
33 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 6) | ||
34 | #define BFA_LOG_LINUX_ITNIM_ONLINE \ | ||
35 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 7) | ||
36 | #define BFA_LOG_LINUX_ITNIM_OFFLINE \ | ||
37 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 8) | ||
38 | #define BFA_LOG_LINUX_SCSI_HOST_FREE \ | ||
39 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 9) | ||
40 | #define BFA_LOG_LINUX_SCSI_ABORT \ | ||
41 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 10) | ||
42 | #define BFA_LOG_LINUX_SCSI_ABORT_COMP \ | ||
43 | (((u32) BFA_LOG_LINUX_ID << BFA_LOG_MODID_OFFSET) | 11) | ||
44 | #endif | ||
diff --git a/drivers/scsi/bfa/include/log/bfa_log_wdrv.h b/drivers/scsi/bfa/include/log/bfa_log_wdrv.h new file mode 100644 index 000000000000..809a95f7afe2 --- /dev/null +++ b/drivers/scsi/bfa/include/log/bfa_log_wdrv.h | |||
@@ -0,0 +1,36 @@ | |||
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 | * messages define for WDRV Module | ||
20 | */ | ||
21 | #ifndef __BFA_LOG_WDRV_H__ | ||
22 | #define __BFA_LOG_WDRV_H__ | ||
23 | #include <cs/bfa_log.h> | ||
24 | #define BFA_LOG_WDRV_IOC_INIT_ERROR \ | ||
25 | (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 1) | ||
26 | #define BFA_LOG_WDRV_IOC_INTERNAL_ERROR \ | ||
27 | (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 2) | ||
28 | #define BFA_LOG_WDRV_IOC_START_ERROR \ | ||
29 | (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 3) | ||
30 | #define BFA_LOG_WDRV_IOC_STOP_ERROR \ | ||
31 | (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 4) | ||
32 | #define BFA_LOG_WDRV_INSUFFICIENT_RESOURCES \ | ||
33 | (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 5) | ||
34 | #define BFA_LOG_WDRV_BASE_ADDRESS_MAP_ERROR \ | ||
35 | (((u32) BFA_LOG_WDRV_ID << BFA_LOG_MODID_OFFSET) | 6) | ||
36 | #endif | ||
diff --git a/drivers/scsi/bfa/include/protocol/ct.h b/drivers/scsi/bfa/include/protocol/ct.h new file mode 100644 index 000000000000..c59d6630b070 --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/ct.h | |||
@@ -0,0 +1,492 @@ | |||
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 | #ifndef __CT_H__ | ||
19 | #define __CT_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | struct ct_hdr_s{ | ||
26 | u32 rev_id:8; /* Revision of the CT */ | ||
27 | u32 in_id:24; /* Initiator Id */ | ||
28 | u32 gs_type:8; /* Generic service Type */ | ||
29 | u32 gs_sub_type:8; /* Generic service sub type */ | ||
30 | u32 options:8; /* options */ | ||
31 | u32 rsvrd:8; /* reserved */ | ||
32 | u32 cmd_rsp_code:16;/* ct command/response code */ | ||
33 | u32 max_res_size:16;/* maximum/residual size */ | ||
34 | u32 frag_id:8; /* fragment ID */ | ||
35 | u32 reason_code:8; /* reason code */ | ||
36 | u32 exp_code:8; /* explanation code */ | ||
37 | u32 vendor_unq:8; /* vendor unique */ | ||
38 | }; | ||
39 | |||
40 | /* | ||
41 | * defines for the Revision | ||
42 | */ | ||
43 | enum { | ||
44 | CT_GS3_REVISION = 0x01, | ||
45 | }; | ||
46 | |||
47 | /* | ||
48 | * defines for gs_type | ||
49 | */ | ||
50 | enum { | ||
51 | CT_GSTYPE_KEYSERVICE = 0xF7, | ||
52 | CT_GSTYPE_ALIASSERVICE = 0xF8, | ||
53 | CT_GSTYPE_MGMTSERVICE = 0xFA, | ||
54 | CT_GSTYPE_TIMESERVICE = 0xFB, | ||
55 | CT_GSTYPE_DIRSERVICE = 0xFC, | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * defines for gs_sub_type for gs type directory service | ||
60 | */ | ||
61 | enum { | ||
62 | CT_GSSUBTYPE_NAMESERVER = 0x02, | ||
63 | }; | ||
64 | |||
65 | /* | ||
66 | * defines for gs_sub_type for gs type management service | ||
67 | */ | ||
68 | enum { | ||
69 | CT_GSSUBTYPE_CFGSERVER = 0x01, | ||
70 | CT_GSSUBTYPE_UNZONED_NS = 0x02, | ||
71 | CT_GSSUBTYPE_ZONESERVER = 0x03, | ||
72 | CT_GSSUBTYPE_LOCKSERVER = 0x04, | ||
73 | CT_GSSUBTYPE_HBA_MGMTSERVER = 0x10, /* for FDMI */ | ||
74 | }; | ||
75 | |||
76 | /* | ||
77 | * defines for CT response code field | ||
78 | */ | ||
79 | enum { | ||
80 | CT_RSP_REJECT = 0x8001, | ||
81 | CT_RSP_ACCEPT = 0x8002, | ||
82 | }; | ||
83 | |||
84 | /* | ||
85 | * defintions for CT reason code | ||
86 | */ | ||
87 | enum { | ||
88 | CT_RSN_INV_CMD = 0x01, | ||
89 | CT_RSN_INV_VER = 0x02, | ||
90 | CT_RSN_LOGIC_ERR = 0x03, | ||
91 | CT_RSN_INV_SIZE = 0x04, | ||
92 | CT_RSN_LOGICAL_BUSY = 0x05, | ||
93 | CT_RSN_PROTO_ERR = 0x07, | ||
94 | CT_RSN_UNABLE_TO_PERF = 0x09, | ||
95 | CT_RSN_NOT_SUPP = 0x0B, | ||
96 | CT_RSN_SERVER_NOT_AVBL = 0x0D, | ||
97 | CT_RSN_SESSION_COULD_NOT_BE_ESTBD = 0x0E, | ||
98 | CT_RSN_VENDOR_SPECIFIC = 0xFF, | ||
99 | |||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * definitions for explanations code for Name server | ||
104 | */ | ||
105 | enum { | ||
106 | CT_NS_EXP_NOADDITIONAL = 0x00, | ||
107 | CT_NS_EXP_ID_NOT_REG = 0x01, | ||
108 | CT_NS_EXP_PN_NOT_REG = 0x02, | ||
109 | CT_NS_EXP_NN_NOT_REG = 0x03, | ||
110 | CT_NS_EXP_CS_NOT_REG = 0x04, | ||
111 | CT_NS_EXP_IPN_NOT_REG = 0x05, | ||
112 | CT_NS_EXP_IPA_NOT_REG = 0x06, | ||
113 | CT_NS_EXP_FT_NOT_REG = 0x07, | ||
114 | CT_NS_EXP_SPN_NOT_REG = 0x08, | ||
115 | CT_NS_EXP_SNN_NOT_REG = 0x09, | ||
116 | CT_NS_EXP_PT_NOT_REG = 0x0A, | ||
117 | CT_NS_EXP_IPP_NOT_REG = 0x0B, | ||
118 | CT_NS_EXP_FPN_NOT_REG = 0x0C, | ||
119 | CT_NS_EXP_HA_NOT_REG = 0x0D, | ||
120 | CT_NS_EXP_FD_NOT_REG = 0x0E, | ||
121 | CT_NS_EXP_FF_NOT_REG = 0x0F, | ||
122 | CT_NS_EXP_ACCESSDENIED = 0x10, | ||
123 | CT_NS_EXP_UNACCEPTABLE_ID = 0x11, | ||
124 | CT_NS_EXP_DATABASEEMPTY = 0x12, | ||
125 | CT_NS_EXP_NOT_REG_IN_SCOPE = 0x13, | ||
126 | CT_NS_EXP_DOM_ID_NOT_PRESENT = 0x14, | ||
127 | CT_NS_EXP_PORT_NUM_NOT_PRESENT = 0x15, | ||
128 | CT_NS_EXP_NO_DEVICE_ATTACHED = 0x16 | ||
129 | }; | ||
130 | |||
131 | /* | ||
132 | * defintions for the explanation code for all servers | ||
133 | */ | ||
134 | enum { | ||
135 | CT_EXP_AUTH_EXCEPTION = 0xF1, | ||
136 | CT_EXP_DB_FULL = 0xF2, | ||
137 | CT_EXP_DB_EMPTY = 0xF3, | ||
138 | CT_EXP_PROCESSING_REQ = 0xF4, | ||
139 | CT_EXP_UNABLE_TO_VERIFY_CONN = 0xF5, | ||
140 | CT_EXP_DEVICES_NOT_IN_CMN_ZONE = 0xF6 | ||
141 | }; | ||
142 | |||
143 | /* | ||
144 | * Command codes for Name server | ||
145 | */ | ||
146 | enum { | ||
147 | GS_GID_PN = 0x0121, /* Get Id on port name */ | ||
148 | GS_GPN_ID = 0x0112, /* Get port name on ID */ | ||
149 | GS_GNN_ID = 0x0113, /* Get node name on ID */ | ||
150 | GS_GID_FT = 0x0171, /* Get Id on FC4 type */ | ||
151 | GS_GSPN_ID = 0x0118, /* Get symbolic PN on ID */ | ||
152 | GS_RFT_ID = 0x0217, /* Register fc4type on ID */ | ||
153 | GS_RSPN_ID = 0x0218, /* Register symbolic PN on ID */ | ||
154 | GS_RPN_ID = 0x0212, /* Register port name */ | ||
155 | GS_RNN_ID = 0x0213, /* Register node name */ | ||
156 | GS_RCS_ID = 0x0214, /* Register class of service */ | ||
157 | GS_RPT_ID = 0x021A, /* Register port type */ | ||
158 | GS_GA_NXT = 0x0100, /* Get all next */ | ||
159 | GS_RFF_ID = 0x021F, /* Register FC4 Feature */ | ||
160 | }; | ||
161 | |||
162 | struct fcgs_id_req_s{ | ||
163 | u32 rsvd:8; | ||
164 | u32 dap:24; /* port identifier */ | ||
165 | }; | ||
166 | #define fcgs_gpnid_req_t struct fcgs_id_req_s | ||
167 | #define fcgs_gnnid_req_t struct fcgs_id_req_s | ||
168 | #define fcgs_gspnid_req_t struct fcgs_id_req_s | ||
169 | |||
170 | struct fcgs_gidpn_req_s{ | ||
171 | wwn_t port_name; /* port wwn */ | ||
172 | }; | ||
173 | |||
174 | struct fcgs_gidpn_resp_s{ | ||
175 | u32 rsvd:8; | ||
176 | u32 dap:24; /* port identifier */ | ||
177 | }; | ||
178 | |||
179 | /** | ||
180 | * RFT_ID | ||
181 | */ | ||
182 | struct fcgs_rftid_req_s { | ||
183 | u32 rsvd:8; | ||
184 | u32 dap:24; /* port identifier */ | ||
185 | u32 fc4_type[8]; /* fc4 types */ | ||
186 | }; | ||
187 | |||
188 | /** | ||
189 | * RFF_ID : Register FC4 features. | ||
190 | */ | ||
191 | |||
192 | #define FC_GS_FCP_FC4_FEATURE_INITIATOR 0x02 | ||
193 | #define FC_GS_FCP_FC4_FEATURE_TARGET 0x01 | ||
194 | |||
195 | struct fcgs_rffid_req_s{ | ||
196 | u32 rsvd :8; | ||
197 | u32 dap :24; /* port identifier */ | ||
198 | u32 rsvd1 :16; | ||
199 | u32 fc4ftr_bits :8; /* fc4 feature bits */ | ||
200 | u32 fc4_type :8; /* corresponding FC4 Type */ | ||
201 | }; | ||
202 | |||
203 | /** | ||
204 | * GID_FT Request | ||
205 | */ | ||
206 | struct fcgs_gidft_req_s{ | ||
207 | u8 reserved; | ||
208 | u8 domain_id; /* domain, 0 - all fabric */ | ||
209 | u8 area_id; /* area, 0 - whole domain */ | ||
210 | u8 fc4_type; /* FC_TYPE_FCP for SCSI devices */ | ||
211 | }; /* GID_FT Request */ | ||
212 | |||
213 | /** | ||
214 | * GID_FT Response | ||
215 | */ | ||
216 | struct fcgs_gidft_resp_s { | ||
217 | u8 last:1; /* last port identifier flag */ | ||
218 | u8 reserved:7; | ||
219 | u32 pid:24; /* port identifier */ | ||
220 | }; /* GID_FT Response */ | ||
221 | |||
222 | /** | ||
223 | * RSPN_ID | ||
224 | */ | ||
225 | struct fcgs_rspnid_req_s{ | ||
226 | u32 rsvd:8; | ||
227 | u32 dap:24; /* port identifier */ | ||
228 | u8 spn_len; /* symbolic port name length */ | ||
229 | u8 spn[256]; /* symbolic port name */ | ||
230 | }; | ||
231 | |||
232 | /** | ||
233 | * RPN_ID | ||
234 | */ | ||
235 | struct fcgs_rpnid_req_s{ | ||
236 | u32 rsvd:8; | ||
237 | u32 port_id:24; | ||
238 | wwn_t port_name; | ||
239 | }; | ||
240 | |||
241 | /** | ||
242 | * RNN_ID | ||
243 | */ | ||
244 | struct fcgs_rnnid_req_s{ | ||
245 | u32 rsvd:8; | ||
246 | u32 port_id:24; | ||
247 | wwn_t node_name; | ||
248 | }; | ||
249 | |||
250 | /** | ||
251 | * RCS_ID | ||
252 | */ | ||
253 | struct fcgs_rcsid_req_s{ | ||
254 | u32 rsvd:8; | ||
255 | u32 port_id:24; | ||
256 | u32 cos; | ||
257 | }; | ||
258 | |||
259 | /** | ||
260 | * RPT_ID | ||
261 | */ | ||
262 | struct fcgs_rptid_req_s{ | ||
263 | u32 rsvd:8; | ||
264 | u32 port_id:24; | ||
265 | u32 port_type:8; | ||
266 | u32 rsvd1:24; | ||
267 | }; | ||
268 | |||
269 | /** | ||
270 | * GA_NXT Request | ||
271 | */ | ||
272 | struct fcgs_ganxt_req_s{ | ||
273 | u32 rsvd:8; | ||
274 | u32 port_id:24; | ||
275 | }; | ||
276 | |||
277 | /** | ||
278 | * GA_NXT Response | ||
279 | */ | ||
280 | struct fcgs_ganxt_rsp_s{ | ||
281 | u32 port_type:8; /* Port Type */ | ||
282 | u32 port_id:24; /* Port Identifier */ | ||
283 | wwn_t port_name; /* Port Name */ | ||
284 | u8 spn_len; /* Length of Symbolic Port Name */ | ||
285 | char spn[255]; /* Symbolic Port Name */ | ||
286 | wwn_t node_name; /* Node Name */ | ||
287 | u8 snn_len; /* Length of Symbolic Node Name */ | ||
288 | char snn[255]; /* Symbolic Node Name */ | ||
289 | u8 ipa[8]; /* Initial Process Associator */ | ||
290 | u8 ip[16]; /* IP Address */ | ||
291 | u32 cos; /* Class of Service */ | ||
292 | u32 fc4types[8]; /* FC-4 TYPEs */ | ||
293 | wwn_t fabric_port_name; | ||
294 | /* Fabric Port Name */ | ||
295 | u32 rsvd:8; /* Reserved */ | ||
296 | u32 hard_addr:24; /* Hard Address */ | ||
297 | }; | ||
298 | |||
299 | /* | ||
300 | * Fabric Config Server | ||
301 | */ | ||
302 | |||
303 | /* | ||
304 | * Command codes for Fabric Configuration Server | ||
305 | */ | ||
306 | enum { | ||
307 | GS_FC_GFN_CMD = 0x0114, /* GS FC Get Fabric Name */ | ||
308 | GS_FC_GMAL_CMD = 0x0116, /* GS FC GMAL */ | ||
309 | GS_FC_TRACE_CMD = 0x0400, /* GS FC Trace Route */ | ||
310 | GS_FC_PING_CMD = 0x0401, /* GS FC Ping */ | ||
311 | }; | ||
312 | |||
313 | /* | ||
314 | * Source or Destination Port Tags. | ||
315 | */ | ||
316 | enum { | ||
317 | GS_FTRACE_TAG_NPORT_ID = 1, | ||
318 | GS_FTRACE_TAG_NPORT_NAME = 2, | ||
319 | }; | ||
320 | |||
321 | /* | ||
322 | * Port Value : Could be a Port id or wwn | ||
323 | */ | ||
324 | union fcgs_port_val_u{ | ||
325 | u32 nport_id; | ||
326 | wwn_t nport_wwn; | ||
327 | }; | ||
328 | |||
329 | #define GS_FTRACE_MAX_HOP_COUNT 20 | ||
330 | #define GS_FTRACE_REVISION 1 | ||
331 | |||
332 | /* | ||
333 | * Ftrace Related Structures. | ||
334 | */ | ||
335 | |||
336 | /* | ||
337 | * STR (Switch Trace) Reject Reason Codes. From FC-SW. | ||
338 | */ | ||
339 | enum { | ||
340 | GS_FTRACE_STR_CMD_COMPLETED_SUCC = 0, | ||
341 | GS_FTRACE_STR_CMD_NOT_SUPP_IN_NEXT_SWITCH, | ||
342 | GS_FTRACE_STR_NO_RESP_FROM_NEXT_SWITCH, | ||
343 | GS_FTRACE_STR_MAX_HOP_CNT_REACHED, | ||
344 | GS_FTRACE_STR_SRC_PORT_NOT_FOUND, | ||
345 | GS_FTRACE_STR_DST_PORT_NOT_FOUND, | ||
346 | GS_FTRACE_STR_DEVICES_NOT_IN_COMMON_ZONE, | ||
347 | GS_FTRACE_STR_NO_ROUTE_BW_PORTS, | ||
348 | GS_FTRACE_STR_NO_ADDL_EXPLN, | ||
349 | GS_FTRACE_STR_FABRIC_BUSY, | ||
350 | GS_FTRACE_STR_FABRIC_BUILD_IN_PROGRESS, | ||
351 | GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_START = 0xf0, | ||
352 | GS_FTRACE_STR_VENDOR_SPECIFIC_ERR_END = 0xff, | ||
353 | }; | ||
354 | |||
355 | /* | ||
356 | * Ftrace Request | ||
357 | */ | ||
358 | struct fcgs_ftrace_req_s{ | ||
359 | u32 revision; | ||
360 | u16 src_port_tag; /* Source Port tag */ | ||
361 | u16 src_port_len; /* Source Port len */ | ||
362 | union fcgs_port_val_u src_port_val; /* Source Port value */ | ||
363 | u16 dst_port_tag; /* Destination Port tag */ | ||
364 | u16 dst_port_len; /* Destination Port len */ | ||
365 | union fcgs_port_val_u dst_port_val; /* Destination Port value */ | ||
366 | u32 token; | ||
367 | u8 vendor_id[8]; /* T10 Vendor Identifier */ | ||
368 | u8 vendor_info[8]; /* Vendor specific Info */ | ||
369 | u32 max_hop_cnt; /* Max Hop Count */ | ||
370 | }; | ||
371 | |||
372 | /* | ||
373 | * Path info structure | ||
374 | */ | ||
375 | struct fcgs_ftrace_path_info_s{ | ||
376 | wwn_t switch_name; /* Switch WWN */ | ||
377 | u32 domain_id; | ||
378 | wwn_t ingress_port_name; /* Ingress ports wwn */ | ||
379 | u32 ingress_phys_port_num; /* Ingress ports physical port | ||
380 | * number | ||
381 | */ | ||
382 | wwn_t egress_port_name; /* Ingress ports wwn */ | ||
383 | u32 egress_phys_port_num; /* Ingress ports physical port | ||
384 | * number | ||
385 | */ | ||
386 | }; | ||
387 | |||
388 | /* | ||
389 | * Ftrace Acc Response | ||
390 | */ | ||
391 | struct fcgs_ftrace_resp_s{ | ||
392 | u32 revision; | ||
393 | u32 token; | ||
394 | u8 vendor_id[8]; /* T10 Vendor Identifier */ | ||
395 | u8 vendor_info[8]; /* Vendor specific Info */ | ||
396 | u32 str_rej_reason_code; /* STR Reject Reason Code */ | ||
397 | u32 num_path_info_entries; /* No. of path info entries */ | ||
398 | /* | ||
399 | * path info entry/entries. | ||
400 | */ | ||
401 | struct fcgs_ftrace_path_info_s path_info[1]; | ||
402 | |||
403 | }; | ||
404 | |||
405 | /* | ||
406 | * Fabric Config Server : FCPing | ||
407 | */ | ||
408 | |||
409 | /* | ||
410 | * FC Ping Request | ||
411 | */ | ||
412 | struct fcgs_fcping_req_s{ | ||
413 | u32 revision; | ||
414 | u16 port_tag; | ||
415 | u16 port_len; /* Port len */ | ||
416 | union fcgs_port_val_u port_val; /* Port value */ | ||
417 | u32 token; | ||
418 | }; | ||
419 | |||
420 | /* | ||
421 | * FC Ping Response | ||
422 | */ | ||
423 | struct fcgs_fcping_resp_s{ | ||
424 | u32 token; | ||
425 | }; | ||
426 | |||
427 | /* | ||
428 | * Command codes for zone server query. | ||
429 | */ | ||
430 | enum { | ||
431 | ZS_GZME = 0x0124, /* Get zone member extended */ | ||
432 | }; | ||
433 | |||
434 | /* | ||
435 | * ZS GZME request | ||
436 | */ | ||
437 | #define ZS_GZME_ZNAMELEN 32 | ||
438 | struct zs_gzme_req_s{ | ||
439 | u8 znamelen; | ||
440 | u8 rsvd[3]; | ||
441 | u8 zname[ZS_GZME_ZNAMELEN]; | ||
442 | }; | ||
443 | |||
444 | enum zs_mbr_type{ | ||
445 | ZS_MBR_TYPE_PWWN = 1, | ||
446 | ZS_MBR_TYPE_DOMPORT = 2, | ||
447 | ZS_MBR_TYPE_PORTID = 3, | ||
448 | ZS_MBR_TYPE_NWWN = 4, | ||
449 | }; | ||
450 | |||
451 | struct zs_mbr_wwn_s{ | ||
452 | u8 mbr_type; | ||
453 | u8 rsvd[3]; | ||
454 | wwn_t wwn; | ||
455 | }; | ||
456 | |||
457 | struct zs_query_resp_s{ | ||
458 | u32 nmbrs; /* number of zone members */ | ||
459 | struct zs_mbr_wwn_s mbr[1]; | ||
460 | }; | ||
461 | |||
462 | /* | ||
463 | * GMAL Command ( Get ( interconnect Element) Management Address List) | ||
464 | * To retrieve the IP Address of a Switch. | ||
465 | */ | ||
466 | |||
467 | #define CT_GMAL_RESP_PREFIX_TELNET "telnet://" | ||
468 | #define CT_GMAL_RESP_PREFIX_HTTP "http://" | ||
469 | |||
470 | /* GMAL/GFN request */ | ||
471 | struct fcgs_req_s { | ||
472 | wwn_t wwn; /* PWWN/NWWN */ | ||
473 | }; | ||
474 | |||
475 | #define fcgs_gmal_req_t struct fcgs_req_s | ||
476 | #define fcgs_gfn_req_t struct fcgs_req_s | ||
477 | |||
478 | /* Accept Response to GMAL */ | ||
479 | struct fcgs_gmal_resp_s { | ||
480 | u32 ms_len; /* Num of entries */ | ||
481 | u8 ms_ma[256]; | ||
482 | }; | ||
483 | |||
484 | struct fc_gmal_entry_s { | ||
485 | u8 len; | ||
486 | u8 prefix[7]; /* like "http://" */ | ||
487 | u8 ip_addr[248]; | ||
488 | }; | ||
489 | |||
490 | #pragma pack() | ||
491 | |||
492 | #endif | ||
diff --git a/drivers/scsi/bfa/include/protocol/fc.h b/drivers/scsi/bfa/include/protocol/fc.h new file mode 100644 index 000000000000..3e39ba58cfb5 --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/fc.h | |||
@@ -0,0 +1,1105 @@ | |||
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 | #ifndef __FC_H__ | ||
19 | #define __FC_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | /* | ||
26 | * Fibre Channel Header Structure (FCHS) definition | ||
27 | */ | ||
28 | struct fchs_s { | ||
29 | #ifdef __BIGENDIAN | ||
30 | u32 routing:4; /* routing bits */ | ||
31 | u32 cat_info:4; /* category info */ | ||
32 | #else | ||
33 | u32 cat_info:4; /* category info */ | ||
34 | u32 routing:4; /* routing bits */ | ||
35 | #endif | ||
36 | u32 d_id:24; /* destination identifier */ | ||
37 | |||
38 | u32 cs_ctl:8; /* class specific control */ | ||
39 | u32 s_id:24; /* source identifier */ | ||
40 | |||
41 | u32 type:8; /* data structure type */ | ||
42 | u32 f_ctl:24; /* initial frame control */ | ||
43 | |||
44 | u8 seq_id; /* sequence identifier */ | ||
45 | u8 df_ctl; /* data field control */ | ||
46 | u16 seq_cnt; /* sequence count */ | ||
47 | |||
48 | u16 ox_id; /* originator exchange ID */ | ||
49 | u16 rx_id; /* responder exchange ID */ | ||
50 | |||
51 | u32 ro; /* relative offset */ | ||
52 | }; | ||
53 | /* | ||
54 | * Fibre Channel BB_E Header Structure | ||
55 | */ | ||
56 | struct fcbbehs_s { | ||
57 | u16 ver_rsvd; | ||
58 | u32 rsvd[2]; | ||
59 | u32 rsvd__sof; | ||
60 | }; | ||
61 | |||
62 | #define FC_SEQ_ID_MAX 256 | ||
63 | |||
64 | /* | ||
65 | * routing bit definitions | ||
66 | */ | ||
67 | enum { | ||
68 | FC_RTG_FC4_DEV_DATA = 0x0, /* FC-4 Device Data */ | ||
69 | FC_RTG_EXT_LINK = 0x2, /* Extended Link Data */ | ||
70 | FC_RTG_FC4_LINK_DATA = 0x3, /* FC-4 Link Data */ | ||
71 | FC_RTG_VIDEO_DATA = 0x4, /* Video Data */ | ||
72 | FC_RTG_EXT_HDR = 0x5, /* VFT, IFR or Encapsuled */ | ||
73 | FC_RTG_BASIC_LINK = 0x8, /* Basic Link data */ | ||
74 | FC_RTG_LINK_CTRL = 0xC, /* Link Control */ | ||
75 | }; | ||
76 | |||
77 | /* | ||
78 | * information category for extended link data and FC-4 Link Data | ||
79 | */ | ||
80 | enum { | ||
81 | FC_CAT_LD_REQUEST = 0x2, /* Request */ | ||
82 | FC_CAT_LD_REPLY = 0x3, /* Reply */ | ||
83 | FC_CAT_LD_DIAG = 0xF, /* for DIAG use only */ | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * information category for extended headers (VFT, IFR or encapsulation) | ||
88 | */ | ||
89 | enum { | ||
90 | FC_CAT_VFT_HDR = 0x0, /* Virtual fabric tagging header */ | ||
91 | FC_CAT_IFR_HDR = 0x1, /* Inter-Fabric routing header */ | ||
92 | FC_CAT_ENC_HDR = 0x2, /* Encapsulation header */ | ||
93 | }; | ||
94 | |||
95 | /* | ||
96 | * information category for FC-4 device data | ||
97 | */ | ||
98 | enum { | ||
99 | FC_CAT_UNCATEG_INFO = 0x0, /* Uncategorized information */ | ||
100 | FC_CAT_SOLICIT_DATA = 0x1, /* Solicited Data */ | ||
101 | FC_CAT_UNSOLICIT_CTRL = 0x2, /* Unsolicited Control */ | ||
102 | FC_CAT_SOLICIT_CTRL = 0x3, /* Solicited Control */ | ||
103 | FC_CAT_UNSOLICIT_DATA = 0x4, /* Unsolicited Data */ | ||
104 | FC_CAT_DATA_DESC = 0x5, /* Data Descriptor */ | ||
105 | FC_CAT_UNSOLICIT_CMD = 0x6, /* Unsolicited Command */ | ||
106 | FC_CAT_CMD_STATUS = 0x7, /* Command Status */ | ||
107 | }; | ||
108 | |||
109 | /* | ||
110 | * information category for Link Control | ||
111 | */ | ||
112 | enum { | ||
113 | FC_CAT_ACK_1 = 0x00, | ||
114 | FC_CAT_ACK_0_N = 0x01, | ||
115 | FC_CAT_P_RJT = 0x02, | ||
116 | FC_CAT_F_RJT = 0x03, | ||
117 | FC_CAT_P_BSY = 0x04, | ||
118 | FC_CAT_F_BSY_DATA = 0x05, | ||
119 | FC_CAT_F_BSY_LINK_CTL = 0x06, | ||
120 | FC_CAT_F_LCR = 0x07, | ||
121 | FC_CAT_NTY = 0x08, | ||
122 | FC_CAT_END = 0x09, | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * Type Field Definitions. FC-PH Section 18.5 pg. 165 | ||
127 | */ | ||
128 | enum { | ||
129 | FC_TYPE_BLS = 0x0, /* Basic Link Service */ | ||
130 | FC_TYPE_ELS = 0x1, /* Extended Link Service */ | ||
131 | FC_TYPE_IP = 0x5, /* IP */ | ||
132 | FC_TYPE_FCP = 0x8, /* SCSI-FCP */ | ||
133 | FC_TYPE_GPP = 0x9, /* SCSI_GPP */ | ||
134 | FC_TYPE_SERVICES = 0x20, /* Fibre Channel Services */ | ||
135 | FC_TYPE_FC_FSS = 0x22, /* Fabric Switch Services */ | ||
136 | FC_TYPE_FC_AL = 0x23, /* FC-AL */ | ||
137 | FC_TYPE_FC_SNMP = 0x24, /* FC-SNMP */ | ||
138 | FC_TYPE_MAX = 256, /* 256 FC-4 types */ | ||
139 | }; | ||
140 | |||
141 | struct fc_fc4types_s{ | ||
142 | u8 bits[FC_TYPE_MAX / 8]; | ||
143 | }; | ||
144 | |||
145 | /* | ||
146 | * Frame Control Definitions. FC-PH Table-45. pg. 168 | ||
147 | */ | ||
148 | enum { | ||
149 | FCTL_EC_ORIG = 0x000000, /* exchange originator */ | ||
150 | FCTL_EC_RESP = 0x800000, /* exchange responder */ | ||
151 | FCTL_SEQ_INI = 0x000000, /* sequence initiator */ | ||
152 | FCTL_SEQ_REC = 0x400000, /* sequence recipient */ | ||
153 | FCTL_FS_EXCH = 0x200000, /* first sequence of xchg */ | ||
154 | FCTL_LS_EXCH = 0x100000, /* last sequence of xchg */ | ||
155 | FCTL_END_SEQ = 0x080000, /* last frame of sequence */ | ||
156 | FCTL_SI_XFER = 0x010000, /* seq initiative transfer */ | ||
157 | FCTL_RO_PRESENT = 0x000008, /* relative offset present */ | ||
158 | FCTL_FILLBYTE_MASK = 0x000003 /* , fill byte mask */ | ||
159 | }; | ||
160 | |||
161 | /* | ||
162 | * Fabric Well Known Addresses | ||
163 | */ | ||
164 | enum { | ||
165 | FC_MIN_WELL_KNOWN_ADDR = 0xFFFFF0, | ||
166 | FC_DOMAIN_CONTROLLER_MASK = 0xFFFC00, | ||
167 | FC_ALIAS_SERVER = 0xFFFFF8, | ||
168 | FC_MGMT_SERVER = 0xFFFFFA, | ||
169 | FC_TIME_SERVER = 0xFFFFFB, | ||
170 | FC_NAME_SERVER = 0xFFFFFC, | ||
171 | FC_FABRIC_CONTROLLER = 0xFFFFFD, | ||
172 | FC_FABRIC_PORT = 0xFFFFFE, | ||
173 | FC_BROADCAST_SERVER = 0xFFFFFF | ||
174 | }; | ||
175 | |||
176 | /* | ||
177 | * domain/area/port defines | ||
178 | */ | ||
179 | #define FC_DOMAIN_MASK 0xFF0000 | ||
180 | #define FC_DOMAIN_SHIFT 16 | ||
181 | #define FC_AREA_MASK 0x00FF00 | ||
182 | #define FC_AREA_SHIFT 8 | ||
183 | #define FC_PORT_MASK 0x0000FF | ||
184 | #define FC_PORT_SHIFT 0 | ||
185 | |||
186 | #define FC_GET_DOMAIN(p) (((p) & FC_DOMAIN_MASK) >> FC_DOMAIN_SHIFT) | ||
187 | #define FC_GET_AREA(p) (((p) & FC_AREA_MASK) >> FC_AREA_SHIFT) | ||
188 | #define FC_GET_PORT(p) (((p) & FC_PORT_MASK) >> FC_PORT_SHIFT) | ||
189 | |||
190 | #define FC_DOMAIN_CTRLR(p) (FC_DOMAIN_CONTROLLER_MASK | (FC_GET_DOMAIN(p))) | ||
191 | |||
192 | enum { | ||
193 | FC_RXID_ANY = 0xFFFFU, | ||
194 | }; | ||
195 | |||
196 | /* | ||
197 | * generic ELS command | ||
198 | */ | ||
199 | struct fc_els_cmd_s{ | ||
200 | u32 els_code:8; /* ELS Command Code */ | ||
201 | u32 reserved:24; | ||
202 | }; | ||
203 | |||
204 | /* | ||
205 | * ELS Command Codes. FC-PH Table-75. pg. 223 | ||
206 | */ | ||
207 | enum { | ||
208 | FC_ELS_LS_RJT = 0x1, /* Link Service Reject. */ | ||
209 | FC_ELS_ACC = 0x02, /* Accept */ | ||
210 | FC_ELS_PLOGI = 0x03, /* N_Port Login. */ | ||
211 | FC_ELS_FLOGI = 0x04, /* F_Port Login. */ | ||
212 | FC_ELS_LOGO = 0x05, /* Logout. */ | ||
213 | FC_ELS_ABTX = 0x06, /* Abort Exchange */ | ||
214 | FC_ELS_RES = 0x08, /* Read Exchange status */ | ||
215 | FC_ELS_RSS = 0x09, /* Read sequence status block */ | ||
216 | FC_ELS_RSI = 0x0A, /* Request Sequence Initiative */ | ||
217 | FC_ELS_ESTC = 0x0C, /* Estimate Credit. */ | ||
218 | FC_ELS_RTV = 0x0E, /* Read Timeout Value. */ | ||
219 | FC_ELS_RLS = 0x0F, /* Read Link Status. */ | ||
220 | FC_ELS_ECHO = 0x10, /* Echo */ | ||
221 | FC_ELS_TEST = 0x11, /* Test */ | ||
222 | FC_ELS_RRQ = 0x12, /* Reinstate Recovery Qualifier. */ | ||
223 | FC_ELS_REC = 0x13, /* Add this for TAPE support in FCR */ | ||
224 | FC_ELS_PRLI = 0x20, /* Process Login */ | ||
225 | FC_ELS_PRLO = 0x21, /* Process Logout. */ | ||
226 | FC_ELS_SCN = 0x22, /* State Change Notification. */ | ||
227 | FC_ELS_TPRLO = 0x24, /* Third Party Process Logout. */ | ||
228 | FC_ELS_PDISC = 0x50, /* Discover N_Port Parameters. */ | ||
229 | FC_ELS_FDISC = 0x51, /* Discover F_Port Parameters. */ | ||
230 | FC_ELS_ADISC = 0x52, /* Discover Address. */ | ||
231 | FC_ELS_FAN = 0x60, /* Fabric Address Notification */ | ||
232 | FC_ELS_RSCN = 0x61, /* Reg State Change Notification */ | ||
233 | FC_ELS_SCR = 0x62, /* State Change Registration. */ | ||
234 | FC_ELS_RTIN = 0x77, /* Mangement server request */ | ||
235 | FC_ELS_RNID = 0x78, /* Mangement server request */ | ||
236 | FC_ELS_RLIR = 0x79, /* Registered Link Incident Record */ | ||
237 | |||
238 | FC_ELS_RPSC = 0x7D, /* Report Port Speed Capabilities */ | ||
239 | FC_ELS_QSA = 0x7E, /* Query Security Attributes. Ref FC-SP */ | ||
240 | FC_ELS_E2E_LBEACON = 0x81, | ||
241 | /* End-to-End Link Beacon */ | ||
242 | FC_ELS_AUTH = 0x90, /* Authentication. Ref FC-SP */ | ||
243 | FC_ELS_RFCN = 0x97, /* Request Fabric Change Notification. Ref | ||
244 | *FC-SP */ | ||
245 | |||
246 | }; | ||
247 | |||
248 | /* | ||
249 | * Version numbers for FC-PH standards, | ||
250 | * used in login to indicate what port | ||
251 | * supports. See FC-PH-X table 158. | ||
252 | */ | ||
253 | enum { | ||
254 | FC_PH_VER_4_3 = 0x09, | ||
255 | FC_PH_VER_PH_3 = 0x20, | ||
256 | }; | ||
257 | |||
258 | /* | ||
259 | * PDU size defines | ||
260 | */ | ||
261 | enum { | ||
262 | FC_MIN_PDUSZ = 512, | ||
263 | FC_MAX_PDUSZ = 2112, | ||
264 | }; | ||
265 | |||
266 | /* | ||
267 | * N_Port PLOGI Common Service Parameters. | ||
268 | * FC-PH-x. Figure-76. pg. 308. | ||
269 | */ | ||
270 | struct fc_plogi_csp_s{ | ||
271 | u8 verhi; /* FC-PH high version */ | ||
272 | u8 verlo; /* FC-PH low version */ | ||
273 | u16 bbcred; /* BB_Credit */ | ||
274 | |||
275 | #ifdef __BIGENDIAN | ||
276 | u8 ciro:1, /* continuously increasing RO */ | ||
277 | rro:1, /* random relative offset */ | ||
278 | npiv_supp:1, /* NPIV supported */ | ||
279 | port_type:1, /* N_Port/F_port */ | ||
280 | altbbcred:1, /* alternate BB_Credit */ | ||
281 | resolution:1, /* ms/ns ED_TOV resolution */ | ||
282 | vvl_info:1, /* VVL Info included */ | ||
283 | reserved1:1; | ||
284 | |||
285 | u8 hg_supp:1, | ||
286 | query_dbc:1, | ||
287 | security:1, | ||
288 | sync_cap:1, | ||
289 | r_t_tov:1, | ||
290 | dh_dup_supp:1, | ||
291 | cisc:1, /* continuously increasing seq count */ | ||
292 | payload:1; | ||
293 | #else | ||
294 | u8 reserved2:2, | ||
295 | resolution:1, /* ms/ns ED_TOV resolution */ | ||
296 | altbbcred:1, /* alternate BB_Credit */ | ||
297 | port_type:1, /* N_Port/F_port */ | ||
298 | npiv_supp:1, /* NPIV supported */ | ||
299 | rro:1, /* random relative offset */ | ||
300 | ciro:1; /* continuously increasing RO */ | ||
301 | |||
302 | u8 payload:1, | ||
303 | cisc:1, /* continuously increasing seq count */ | ||
304 | dh_dup_supp:1, | ||
305 | r_t_tov:1, | ||
306 | sync_cap:1, | ||
307 | security:1, | ||
308 | query_dbc:1, | ||
309 | hg_supp:1; | ||
310 | #endif | ||
311 | |||
312 | u16 rxsz; /* recieve data_field size */ | ||
313 | |||
314 | u16 conseq; | ||
315 | u16 ro_bitmap; | ||
316 | |||
317 | u32 e_d_tov; | ||
318 | }; | ||
319 | |||
320 | /* | ||
321 | * N_Port PLOGI Class Specific Parameters. | ||
322 | * FC-PH-x. Figure 78. pg. 318. | ||
323 | */ | ||
324 | struct fc_plogi_clp_s{ | ||
325 | #ifdef __BIGENDIAN | ||
326 | u32 class_valid:1; | ||
327 | u32 intermix:1; /* class intermix supported if set =1. | ||
328 | * valid only for class1. Reserved for | ||
329 | * class2 & class3 | ||
330 | */ | ||
331 | u32 reserved1:2; | ||
332 | u32 sequential:1; | ||
333 | u32 reserved2:3; | ||
334 | #else | ||
335 | u32 reserved2:3; | ||
336 | u32 sequential:1; | ||
337 | u32 reserved1:2; | ||
338 | u32 intermix:1; /* class intermix supported if set =1. | ||
339 | * valid only for class1. Reserved for | ||
340 | * class2 & class3 | ||
341 | */ | ||
342 | u32 class_valid:1; | ||
343 | #endif | ||
344 | |||
345 | u32 reserved3:24; | ||
346 | |||
347 | u32 reserved4:16; | ||
348 | u32 rxsz:16; /* Receive data_field size */ | ||
349 | |||
350 | u32 reserved5:8; | ||
351 | u32 conseq:8; | ||
352 | u32 e2e_credit:16; /* end to end credit */ | ||
353 | |||
354 | u32 reserved7:8; | ||
355 | u32 ospx:8; | ||
356 | u32 reserved8:16; | ||
357 | }; | ||
358 | |||
359 | #define FLOGI_VVL_BRCD 0x42524344 /* ASCII value for each character in | ||
360 | * string "BRCD" */ | ||
361 | |||
362 | /* | ||
363 | * PLOGI els command and reply payload | ||
364 | */ | ||
365 | struct fc_logi_s{ | ||
366 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
367 | struct fc_plogi_csp_s csp; /* common service params */ | ||
368 | wwn_t port_name; | ||
369 | wwn_t node_name; | ||
370 | struct fc_plogi_clp_s class1; /* class 1 service parameters */ | ||
371 | struct fc_plogi_clp_s class2; /* class 2 service parameters */ | ||
372 | struct fc_plogi_clp_s class3; /* class 3 service parameters */ | ||
373 | struct fc_plogi_clp_s class4; /* class 4 service parameters */ | ||
374 | u8 vvl[16]; /* vendor version level */ | ||
375 | }; | ||
376 | |||
377 | /* | ||
378 | * LOGO els command payload | ||
379 | */ | ||
380 | struct fc_logo_s{ | ||
381 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
382 | u32 res1:8; | ||
383 | u32 nport_id:24; /* N_Port identifier of source */ | ||
384 | wwn_t orig_port_name; /* Port name of the LOGO originator */ | ||
385 | }; | ||
386 | |||
387 | /* | ||
388 | * ADISC els command payload | ||
389 | */ | ||
390 | struct fc_adisc_s { | ||
391 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
392 | u32 res1:8; | ||
393 | u32 orig_HA:24; /* originator hard address */ | ||
394 | wwn_t orig_port_name; /* originator port name */ | ||
395 | wwn_t orig_node_name; /* originator node name */ | ||
396 | u32 res2:8; | ||
397 | u32 nport_id:24; /* originator NPortID */ | ||
398 | }; | ||
399 | |||
400 | /* | ||
401 | * Exchange status block | ||
402 | */ | ||
403 | struct fc_exch_status_blk_s{ | ||
404 | u32 oxid:16; | ||
405 | u32 rxid:16; | ||
406 | u32 res1:8; | ||
407 | u32 orig_np:24; /* originator NPortID */ | ||
408 | u32 res2:8; | ||
409 | u32 resp_np:24; /* responder NPortID */ | ||
410 | u32 es_bits; | ||
411 | u32 res3; | ||
412 | /* | ||
413 | * un modified section of the fields | ||
414 | */ | ||
415 | }; | ||
416 | |||
417 | /* | ||
418 | * RES els command payload | ||
419 | */ | ||
420 | struct fc_res_s { | ||
421 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
422 | u32 res1:8; | ||
423 | u32 nport_id:24; /* N_Port identifier of source */ | ||
424 | u32 oxid:16; | ||
425 | u32 rxid:16; | ||
426 | u8 assoc_hdr[32]; | ||
427 | }; | ||
428 | |||
429 | /* | ||
430 | * RES els accept payload | ||
431 | */ | ||
432 | struct fc_res_acc_s{ | ||
433 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
434 | struct fc_exch_status_blk_s fc_exch_blk; /* Exchange status block */ | ||
435 | }; | ||
436 | |||
437 | /* | ||
438 | * REC els command payload | ||
439 | */ | ||
440 | struct fc_rec_s { | ||
441 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
442 | u32 res1:8; | ||
443 | u32 nport_id:24; /* N_Port identifier of source */ | ||
444 | u32 oxid:16; | ||
445 | u32 rxid:16; | ||
446 | }; | ||
447 | |||
448 | #define FC_REC_ESB_OWN_RSP 0x80000000 /* responder owns */ | ||
449 | #define FC_REC_ESB_SI 0x40000000 /* SI is owned */ | ||
450 | #define FC_REC_ESB_COMP 0x20000000 /* exchange is complete */ | ||
451 | #define FC_REC_ESB_ENDCOND_ABN 0x10000000 /* abnormal ending */ | ||
452 | #define FC_REC_ESB_RQACT 0x04000000 /* recovery qual active */ | ||
453 | #define FC_REC_ESB_ERRP_MSK 0x03000000 | ||
454 | #define FC_REC_ESB_OXID_INV 0x00800000 /* invalid OXID */ | ||
455 | #define FC_REC_ESB_RXID_INV 0x00400000 /* invalid RXID */ | ||
456 | #define FC_REC_ESB_PRIO_INUSE 0x00200000 | ||
457 | |||
458 | /* | ||
459 | * REC els accept payload | ||
460 | */ | ||
461 | struct fc_rec_acc_s { | ||
462 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
463 | u32 oxid:16; | ||
464 | u32 rxid:16; | ||
465 | u32 res1:8; | ||
466 | u32 orig_id:24; /* N_Port id of exchange originator */ | ||
467 | u32 res2:8; | ||
468 | u32 resp_id:24; /* N_Port id of exchange responder */ | ||
469 | u32 count; /* data transfer count */ | ||
470 | u32 e_stat; /* exchange status */ | ||
471 | }; | ||
472 | |||
473 | /* | ||
474 | * RSI els payload | ||
475 | */ | ||
476 | struct fc_rsi_s { | ||
477 | struct fc_els_cmd_s els_cmd; | ||
478 | u32 res1:8; | ||
479 | u32 orig_sid:24; | ||
480 | u32 oxid:16; | ||
481 | u32 rxid:16; | ||
482 | }; | ||
483 | |||
484 | /* | ||
485 | * structure for PRLI paramater pages, both request & response | ||
486 | * see FC-PH-X table 113 & 115 for explanation also FCP table 8 | ||
487 | */ | ||
488 | struct fc_prli_params_s{ | ||
489 | u32 reserved: 16; | ||
490 | #ifdef __BIGENDIAN | ||
491 | u32 reserved1: 5; | ||
492 | u32 rec_support : 1; | ||
493 | u32 task_retry_id : 1; | ||
494 | u32 retry : 1; | ||
495 | |||
496 | u32 confirm : 1; | ||
497 | u32 doverlay:1; | ||
498 | u32 initiator:1; | ||
499 | u32 target:1; | ||
500 | u32 cdmix:1; | ||
501 | u32 drmix:1; | ||
502 | u32 rxrdisab:1; | ||
503 | u32 wxrdisab:1; | ||
504 | #else | ||
505 | u32 retry : 1; | ||
506 | u32 task_retry_id : 1; | ||
507 | u32 rec_support : 1; | ||
508 | u32 reserved1: 5; | ||
509 | |||
510 | u32 wxrdisab:1; | ||
511 | u32 rxrdisab:1; | ||
512 | u32 drmix:1; | ||
513 | u32 cdmix:1; | ||
514 | u32 target:1; | ||
515 | u32 initiator:1; | ||
516 | u32 doverlay:1; | ||
517 | u32 confirm : 1; | ||
518 | #endif | ||
519 | }; | ||
520 | |||
521 | /* | ||
522 | * valid values for rspcode in PRLI ACC payload | ||
523 | */ | ||
524 | enum { | ||
525 | FC_PRLI_ACC_XQTD = 0x1, /* request executed */ | ||
526 | FC_PRLI_ACC_PREDEF_IMG = 0x5, /* predefined image - no prli needed */ | ||
527 | }; | ||
528 | |||
529 | struct fc_prli_params_page_s{ | ||
530 | u32 type:8; | ||
531 | u32 codext:8; | ||
532 | #ifdef __BIGENDIAN | ||
533 | u32 origprocasv:1; | ||
534 | u32 rsppav:1; | ||
535 | u32 imagepair:1; | ||
536 | u32 reserved1:1; | ||
537 | u32 rspcode:4; | ||
538 | #else | ||
539 | u32 rspcode:4; | ||
540 | u32 reserved1:1; | ||
541 | u32 imagepair:1; | ||
542 | u32 rsppav:1; | ||
543 | u32 origprocasv:1; | ||
544 | #endif | ||
545 | u32 reserved2:8; | ||
546 | |||
547 | u32 origprocas; | ||
548 | u32 rspprocas; | ||
549 | struct fc_prli_params_s servparams; | ||
550 | }; | ||
551 | |||
552 | /* | ||
553 | * PRLI request and accept payload, FC-PH-X tables 112 & 114 | ||
554 | */ | ||
555 | struct fc_prli_s{ | ||
556 | u32 command:8; | ||
557 | u32 pglen:8; | ||
558 | u32 pagebytes:16; | ||
559 | struct fc_prli_params_page_s parampage; | ||
560 | }; | ||
561 | |||
562 | /* | ||
563 | * PRLO logout params page | ||
564 | */ | ||
565 | struct fc_prlo_params_page_s{ | ||
566 | u32 type:8; | ||
567 | u32 type_ext:8; | ||
568 | #ifdef __BIGENDIAN | ||
569 | u32 opa_valid:1; /* originator process associator | ||
570 | * valid | ||
571 | */ | ||
572 | u32 rpa_valid:1; /* responder process associator valid */ | ||
573 | u32 res1:14; | ||
574 | #else | ||
575 | u32 res1:14; | ||
576 | u32 rpa_valid:1; /* responder process associator valid */ | ||
577 | u32 opa_valid:1; /* originator process associator | ||
578 | * valid | ||
579 | */ | ||
580 | #endif | ||
581 | u32 orig_process_assc; | ||
582 | u32 resp_process_assc; | ||
583 | |||
584 | u32 res2; | ||
585 | }; | ||
586 | |||
587 | /* | ||
588 | * PRLO els command payload | ||
589 | */ | ||
590 | struct fc_prlo_s{ | ||
591 | u32 command:8; | ||
592 | u32 page_len:8; | ||
593 | u32 payload_len:16; | ||
594 | struct fc_prlo_params_page_s prlo_params[1]; | ||
595 | }; | ||
596 | |||
597 | /* | ||
598 | * PRLO Logout response parameter page | ||
599 | */ | ||
600 | struct fc_prlo_acc_params_page_s{ | ||
601 | u32 type:8; | ||
602 | u32 type_ext:8; | ||
603 | |||
604 | #ifdef __BIGENDIAN | ||
605 | u32 opa_valid:1; /* originator process associator | ||
606 | * valid | ||
607 | */ | ||
608 | u32 rpa_valid:1; /* responder process associator valid */ | ||
609 | u32 res1:14; | ||
610 | #else | ||
611 | u32 res1:14; | ||
612 | u32 rpa_valid:1; /* responder process associator valid */ | ||
613 | u32 opa_valid:1; /* originator process associator | ||
614 | * valid | ||
615 | */ | ||
616 | #endif | ||
617 | u32 orig_process_assc; | ||
618 | u32 resp_process_assc; | ||
619 | |||
620 | u32 fc4type_csp; | ||
621 | }; | ||
622 | |||
623 | /* | ||
624 | * PRLO els command ACC payload | ||
625 | */ | ||
626 | struct fc_prlo_acc_s{ | ||
627 | u32 command:8; | ||
628 | u32 page_len:8; | ||
629 | u32 payload_len:16; | ||
630 | struct fc_prlo_acc_params_page_s prlo_acc_params[1]; | ||
631 | }; | ||
632 | |||
633 | /* | ||
634 | * SCR els command payload | ||
635 | */ | ||
636 | enum { | ||
637 | FC_SCR_REG_FUNC_FABRIC_DETECTED = 0x01, | ||
638 | FC_SCR_REG_FUNC_N_PORT_DETECTED = 0x02, | ||
639 | FC_SCR_REG_FUNC_FULL = 0x03, | ||
640 | FC_SCR_REG_FUNC_CLEAR_REG = 0xFF, | ||
641 | }; | ||
642 | |||
643 | /* SCR VU registrations */ | ||
644 | enum { | ||
645 | FC_VU_SCR_REG_FUNC_FABRIC_NAME_CHANGE = 0x01 | ||
646 | }; | ||
647 | |||
648 | struct fc_scr_s{ | ||
649 | u32 command:8; | ||
650 | u32 res:24; | ||
651 | u32 vu_reg_func:8; /* Vendor Unique Registrations */ | ||
652 | u32 res1:16; | ||
653 | u32 reg_func:8; | ||
654 | }; | ||
655 | |||
656 | /* | ||
657 | * Information category for Basic link data | ||
658 | */ | ||
659 | enum { | ||
660 | FC_CAT_NOP = 0x0, | ||
661 | FC_CAT_ABTS = 0x1, | ||
662 | FC_CAT_RMC = 0x2, | ||
663 | FC_CAT_BA_ACC = 0x4, | ||
664 | FC_CAT_BA_RJT = 0x5, | ||
665 | FC_CAT_PRMT = 0x6, | ||
666 | }; | ||
667 | |||
668 | /* | ||
669 | * LS_RJT els reply payload | ||
670 | */ | ||
671 | struct fc_ls_rjt_s { | ||
672 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
673 | u32 res1:8; | ||
674 | u32 reason_code:8; /* Reason code for reject */ | ||
675 | u32 reason_code_expl:8; /* Reason code explanation */ | ||
676 | u32 vendor_unique:8; /* Vendor specific */ | ||
677 | }; | ||
678 | |||
679 | /* | ||
680 | * LS_RJT reason codes | ||
681 | */ | ||
682 | enum { | ||
683 | FC_LS_RJT_RSN_INV_CMD_CODE = 0x01, | ||
684 | FC_LS_RJT_RSN_LOGICAL_ERROR = 0x03, | ||
685 | FC_LS_RJT_RSN_LOGICAL_BUSY = 0x05, | ||
686 | FC_LS_RJT_RSN_PROTOCOL_ERROR = 0x07, | ||
687 | FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD = 0x09, | ||
688 | FC_LS_RJT_RSN_CMD_NOT_SUPP = 0x0B, | ||
689 | }; | ||
690 | |||
691 | /* | ||
692 | * LS_RJT reason code explanation | ||
693 | */ | ||
694 | enum { | ||
695 | FC_LS_RJT_EXP_NO_ADDL_INFO = 0x00, | ||
696 | FC_LS_RJT_EXP_SPARMS_ERR_OPTIONS = 0x01, | ||
697 | FC_LS_RJT_EXP_SPARMS_ERR_INI_CTL = 0x03, | ||
698 | FC_LS_RJT_EXP_SPARMS_ERR_REC_CTL = 0x05, | ||
699 | FC_LS_RJT_EXP_SPARMS_ERR_RXSZ = 0x07, | ||
700 | FC_LS_RJT_EXP_SPARMS_ERR_CONSEQ = 0x09, | ||
701 | FC_LS_RJT_EXP_SPARMS_ERR_CREDIT = 0x0B, | ||
702 | FC_LS_RJT_EXP_INV_PORT_NAME = 0x0D, | ||
703 | FC_LS_RJT_EXP_INV_NODE_FABRIC_NAME = 0x0E, | ||
704 | FC_LS_RJT_EXP_INV_CSP = 0x0F, | ||
705 | FC_LS_RJT_EXP_INV_ASSOC_HDR = 0x11, | ||
706 | FC_LS_RJT_EXP_ASSOC_HDR_REQD = 0x13, | ||
707 | FC_LS_RJT_EXP_INV_ORIG_S_ID = 0x15, | ||
708 | FC_LS_RJT_EXP_INV_OXID_RXID_COMB = 0x17, | ||
709 | FC_LS_RJT_EXP_CMD_ALREADY_IN_PROG = 0x19, | ||
710 | FC_LS_RJT_EXP_LOGIN_REQUIRED = 0x1E, | ||
711 | FC_LS_RJT_EXP_INVALID_NPORT_ID = 0x1F, | ||
712 | FC_LS_RJT_EXP_INSUFF_RES = 0x29, | ||
713 | FC_LS_RJT_EXP_CMD_NOT_SUPP = 0x2C, | ||
714 | FC_LS_RJT_EXP_INV_PAYLOAD_LEN = 0x2D, | ||
715 | }; | ||
716 | |||
717 | /* | ||
718 | * RRQ els command payload | ||
719 | */ | ||
720 | struct fc_rrq_s{ | ||
721 | struct fc_els_cmd_s els_cmd; /* ELS command code */ | ||
722 | u32 res1:8; | ||
723 | u32 s_id:24; /* exchange originator S_ID */ | ||
724 | |||
725 | u32 ox_id:16; /* originator exchange ID */ | ||
726 | u32 rx_id:16; /* responder exchange ID */ | ||
727 | |||
728 | u32 res2[8]; /* optional association header */ | ||
729 | }; | ||
730 | |||
731 | /* | ||
732 | * ABTS BA_ACC reply payload | ||
733 | */ | ||
734 | struct fc_ba_acc_s{ | ||
735 | u32 seq_id_valid:8; /* set to 0x00 for Abort Exchange */ | ||
736 | u32 seq_id:8; /* invalid for Abort Exchange */ | ||
737 | u32 res2:16; | ||
738 | u32 ox_id:16; /* OX_ID from ABTS frame */ | ||
739 | u32 rx_id:16; /* RX_ID from ABTS frame */ | ||
740 | u32 low_seq_cnt:16; /* set to 0x0000 for Abort Exchange */ | ||
741 | u32 high_seq_cnt:16;/* set to 0xFFFF for Abort Exchange */ | ||
742 | }; | ||
743 | |||
744 | /* | ||
745 | * ABTS BA_RJT reject payload | ||
746 | */ | ||
747 | struct fc_ba_rjt_s{ | ||
748 | u32 res1:8; /* Reserved */ | ||
749 | u32 reason_code:8; /* reason code for reject */ | ||
750 | u32 reason_expl:8; /* reason code explanation */ | ||
751 | u32 vendor_unique:8;/* vendor unique reason code,set to 0 */ | ||
752 | }; | ||
753 | |||
754 | /* | ||
755 | * TPRLO logout parameter page | ||
756 | */ | ||
757 | struct fc_tprlo_params_page_s{ | ||
758 | u32 type:8; | ||
759 | u32 type_ext:8; | ||
760 | |||
761 | #ifdef __BIGENDIAN | ||
762 | u32 opa_valid:1; | ||
763 | u32 rpa_valid:1; | ||
764 | u32 tpo_nport_valid:1; | ||
765 | u32 global_process_logout:1; | ||
766 | u32 res1:12; | ||
767 | #else | ||
768 | u32 res1:12; | ||
769 | u32 global_process_logout:1; | ||
770 | u32 tpo_nport_valid:1; | ||
771 | u32 rpa_valid:1; | ||
772 | u32 opa_valid:1; | ||
773 | #endif | ||
774 | |||
775 | u32 orig_process_assc; | ||
776 | u32 resp_process_assc; | ||
777 | |||
778 | u32 res2:8; | ||
779 | u32 tpo_nport_id; | ||
780 | }; | ||
781 | |||
782 | /* | ||
783 | * TPRLO ELS command payload | ||
784 | */ | ||
785 | struct fc_tprlo_s{ | ||
786 | u32 command:8; | ||
787 | u32 page_len:8; | ||
788 | u32 payload_len:16; | ||
789 | |||
790 | struct fc_tprlo_params_page_s tprlo_params[1]; | ||
791 | }; | ||
792 | |||
793 | enum fc_tprlo_type{ | ||
794 | FC_GLOBAL_LOGO = 1, | ||
795 | FC_TPR_LOGO | ||
796 | }; | ||
797 | |||
798 | /* | ||
799 | * TPRLO els command ACC payload | ||
800 | */ | ||
801 | struct fc_tprlo_acc_s{ | ||
802 | u32 command:8; | ||
803 | u32 page_len:8; | ||
804 | u32 payload_len:16; | ||
805 | struct fc_prlo_acc_params_page_s tprlo_acc_params[1]; | ||
806 | }; | ||
807 | |||
808 | /* | ||
809 | * RSCN els command req payload | ||
810 | */ | ||
811 | #define FC_RSCN_PGLEN 0x4 | ||
812 | |||
813 | enum fc_rscn_format{ | ||
814 | FC_RSCN_FORMAT_PORTID = 0x0, | ||
815 | FC_RSCN_FORMAT_AREA = 0x1, | ||
816 | FC_RSCN_FORMAT_DOMAIN = 0x2, | ||
817 | FC_RSCN_FORMAT_FABRIC = 0x3, | ||
818 | }; | ||
819 | |||
820 | struct fc_rscn_event_s{ | ||
821 | u32 format:2; | ||
822 | u32 qualifier:4; | ||
823 | u32 resvd:2; | ||
824 | u32 portid:24; | ||
825 | }; | ||
826 | |||
827 | struct fc_rscn_pl_s{ | ||
828 | u8 command; | ||
829 | u8 pagelen; | ||
830 | u16 payldlen; | ||
831 | struct fc_rscn_event_s event[1]; | ||
832 | }; | ||
833 | |||
834 | /* | ||
835 | * ECHO els command req payload | ||
836 | */ | ||
837 | struct fc_echo_s { | ||
838 | struct fc_els_cmd_s els_cmd; | ||
839 | }; | ||
840 | |||
841 | /* | ||
842 | * RNID els command | ||
843 | */ | ||
844 | |||
845 | #define RNID_NODEID_DATA_FORMAT_COMMON 0x00 | ||
846 | #define RNID_NODEID_DATA_FORMAT_FCP3 0x08 | ||
847 | #define RNID_NODEID_DATA_FORMAT_DISCOVERY 0xDF | ||
848 | |||
849 | #define RNID_ASSOCIATED_TYPE_UNKNOWN 0x00000001 | ||
850 | #define RNID_ASSOCIATED_TYPE_OTHER 0x00000002 | ||
851 | #define RNID_ASSOCIATED_TYPE_HUB 0x00000003 | ||
852 | #define RNID_ASSOCIATED_TYPE_SWITCH 0x00000004 | ||
853 | #define RNID_ASSOCIATED_TYPE_GATEWAY 0x00000005 | ||
854 | #define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE 0x00000009 | ||
855 | #define RNID_ASSOCIATED_TYPE_HOST 0x0000000A | ||
856 | #define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM 0x0000000B | ||
857 | #define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE 0x0000000E | ||
858 | #define RNID_ASSOCIATED_TYPE_NAS_SERVER 0x00000011 | ||
859 | #define RNID_ASSOCIATED_TYPE_BRIDGE 0x00000002 | ||
860 | #define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE 0x00000003 | ||
861 | #define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE 0x000000FF | ||
862 | |||
863 | /* | ||
864 | * RNID els command payload | ||
865 | */ | ||
866 | struct fc_rnid_cmd_s{ | ||
867 | struct fc_els_cmd_s els_cmd; | ||
868 | u32 node_id_data_format:8; | ||
869 | u32 reserved:24; | ||
870 | }; | ||
871 | |||
872 | /* | ||
873 | * RNID els response payload | ||
874 | */ | ||
875 | |||
876 | struct fc_rnid_common_id_data_s{ | ||
877 | wwn_t port_name; | ||
878 | wwn_t node_name; | ||
879 | }; | ||
880 | |||
881 | struct fc_rnid_general_topology_data_s{ | ||
882 | u32 vendor_unique[4]; | ||
883 | u32 asso_type; | ||
884 | u32 phy_port_num; | ||
885 | u32 num_attached_nodes; | ||
886 | u32 node_mgmt:8; | ||
887 | u32 ip_version:8; | ||
888 | u32 udp_tcp_port_num:16; | ||
889 | u32 ip_address[4]; | ||
890 | u32 reserved:16; | ||
891 | u32 vendor_specific:16; | ||
892 | }; | ||
893 | |||
894 | struct fc_rnid_acc_s{ | ||
895 | struct fc_els_cmd_s els_cmd; | ||
896 | u32 node_id_data_format:8; | ||
897 | u32 common_id_data_length:8; | ||
898 | u32 reserved:8; | ||
899 | u32 specific_id_data_length:8; | ||
900 | struct fc_rnid_common_id_data_s common_id_data; | ||
901 | struct fc_rnid_general_topology_data_s gen_topology_data; | ||
902 | }; | ||
903 | |||
904 | #define RNID_ASSOCIATED_TYPE_UNKNOWN 0x00000001 | ||
905 | #define RNID_ASSOCIATED_TYPE_OTHER 0x00000002 | ||
906 | #define RNID_ASSOCIATED_TYPE_HUB 0x00000003 | ||
907 | #define RNID_ASSOCIATED_TYPE_SWITCH 0x00000004 | ||
908 | #define RNID_ASSOCIATED_TYPE_GATEWAY 0x00000005 | ||
909 | #define RNID_ASSOCIATED_TYPE_STORAGE_DEVICE 0x00000009 | ||
910 | #define RNID_ASSOCIATED_TYPE_HOST 0x0000000A | ||
911 | #define RNID_ASSOCIATED_TYPE_STORAGE_SUBSYSTEM 0x0000000B | ||
912 | #define RNID_ASSOCIATED_TYPE_STORAGE_ACCESS_DEVICE 0x0000000E | ||
913 | #define RNID_ASSOCIATED_TYPE_NAS_SERVER 0x00000011 | ||
914 | #define RNID_ASSOCIATED_TYPE_BRIDGE 0x00000002 | ||
915 | #define RNID_ASSOCIATED_TYPE_VIRTUALIZATION_DEVICE 0x00000003 | ||
916 | #define RNID_ASSOCIATED_TYPE_MULTI_FUNCTION_DEVICE 0x000000FF | ||
917 | |||
918 | enum fc_rpsc_speed_cap{ | ||
919 | RPSC_SPEED_CAP_1G = 0x8000, | ||
920 | RPSC_SPEED_CAP_2G = 0x4000, | ||
921 | RPSC_SPEED_CAP_4G = 0x2000, | ||
922 | RPSC_SPEED_CAP_10G = 0x1000, | ||
923 | RPSC_SPEED_CAP_8G = 0x0800, | ||
924 | RPSC_SPEED_CAP_16G = 0x0400, | ||
925 | |||
926 | RPSC_SPEED_CAP_UNKNOWN = 0x0001, | ||
927 | }; | ||
928 | |||
929 | enum fc_rpsc_op_speed_s{ | ||
930 | RPSC_OP_SPEED_1G = 0x8000, | ||
931 | RPSC_OP_SPEED_2G = 0x4000, | ||
932 | RPSC_OP_SPEED_4G = 0x2000, | ||
933 | RPSC_OP_SPEED_10G = 0x1000, | ||
934 | RPSC_OP_SPEED_8G = 0x0800, | ||
935 | RPSC_OP_SPEED_16G = 0x0400, | ||
936 | |||
937 | RPSC_OP_SPEED_NOT_EST = 0x0001, /*! speed not established */ | ||
938 | }; | ||
939 | |||
940 | struct fc_rpsc_speed_info_s{ | ||
941 | u16 port_speed_cap; /*! see fc_rpsc_speed_cap_t */ | ||
942 | u16 port_op_speed; /*! see fc_rpsc_op_speed_t */ | ||
943 | }; | ||
944 | |||
945 | enum link_e2e_beacon_subcmd{ | ||
946 | LINK_E2E_BEACON_ON = 1, | ||
947 | LINK_E2E_BEACON_OFF = 2 | ||
948 | }; | ||
949 | |||
950 | enum beacon_type{ | ||
951 | BEACON_TYPE_NORMAL = 1, /*! Normal Beaconing. Green */ | ||
952 | BEACON_TYPE_WARN = 2, /*! Warning Beaconing. Yellow/Amber */ | ||
953 | BEACON_TYPE_CRITICAL = 3 /*! Critical Beaconing. Red */ | ||
954 | }; | ||
955 | |||
956 | struct link_e2e_beacon_param_s { | ||
957 | u8 beacon_type; /* Beacon Type. See beacon_type_t */ | ||
958 | u8 beacon_frequency; | ||
959 | /* Beacon frequency. Number of blinks | ||
960 | * per 10 seconds | ||
961 | */ | ||
962 | u16 beacon_duration;/* Beacon duration (in Seconds). The | ||
963 | * command operation should be | ||
964 | * terminated at the end of this | ||
965 | * timeout value. | ||
966 | * | ||
967 | * Ignored if diag_sub_cmd is | ||
968 | * LINK_E2E_BEACON_OFF. | ||
969 | * | ||
970 | * If 0, beaconing will continue till a | ||
971 | * BEACON OFF request is received | ||
972 | */ | ||
973 | }; | ||
974 | |||
975 | /* | ||
976 | * Link E2E beacon request/good response format. For LS_RJTs use fc_ls_rjt_t | ||
977 | */ | ||
978 | struct link_e2e_beacon_req_s{ | ||
979 | u32 ls_code; /*! FC_ELS_E2E_LBEACON in requests * | ||
980 | *or FC_ELS_ACC in good replies */ | ||
981 | u32 ls_sub_cmd; /*! See link_e2e_beacon_subcmd_t */ | ||
982 | struct link_e2e_beacon_param_s beacon_parm; | ||
983 | }; | ||
984 | |||
985 | /** | ||
986 | * If RPSC request is sent to the Domain Controller, the request is for | ||
987 | * all the ports within that domain (TODO - I don't think FOS implements | ||
988 | * this...). | ||
989 | */ | ||
990 | struct fc_rpsc_cmd_s{ | ||
991 | struct fc_els_cmd_s els_cmd; | ||
992 | }; | ||
993 | |||
994 | /* | ||
995 | * RPSC Acc | ||
996 | */ | ||
997 | struct fc_rpsc_acc_s{ | ||
998 | u32 command:8; | ||
999 | u32 rsvd:8; | ||
1000 | u32 num_entries:16; | ||
1001 | |||
1002 | struct fc_rpsc_speed_info_s speed_info[1]; | ||
1003 | }; | ||
1004 | |||
1005 | /** | ||
1006 | * If RPSC2 request is sent to the Domain Controller, | ||
1007 | */ | ||
1008 | #define FC_BRCD_TOKEN 0x42524344 | ||
1009 | |||
1010 | struct fc_rpsc2_cmd_s{ | ||
1011 | struct fc_els_cmd_s els_cmd; | ||
1012 | u32 token; | ||
1013 | u16 resvd; | ||
1014 | u16 num_pids; /* Number of pids in the request */ | ||
1015 | struct { | ||
1016 | u32 rsvd1:8; | ||
1017 | u32 pid:24; /* port identifier */ | ||
1018 | } pid_list[1]; | ||
1019 | }; | ||
1020 | |||
1021 | enum fc_rpsc2_port_type{ | ||
1022 | RPSC2_PORT_TYPE_UNKNOWN = 0, | ||
1023 | RPSC2_PORT_TYPE_NPORT = 1, | ||
1024 | RPSC2_PORT_TYPE_NLPORT = 2, | ||
1025 | RPSC2_PORT_TYPE_NPIV_PORT = 0x5f, | ||
1026 | RPSC2_PORT_TYPE_NPORT_TRUNK = 0x6f, | ||
1027 | }; | ||
1028 | |||
1029 | /* | ||
1030 | * RPSC2 portInfo entry structure | ||
1031 | */ | ||
1032 | struct fc_rpsc2_port_info_s{ | ||
1033 | u32 pid; /* PID */ | ||
1034 | u16 resvd1; | ||
1035 | u16 index; /* port number / index */ | ||
1036 | u8 resvd2; | ||
1037 | u8 type; /* port type N/NL/... */ | ||
1038 | u16 speed; /* port Operating Speed */ | ||
1039 | }; | ||
1040 | |||
1041 | /* | ||
1042 | * RPSC2 Accept payload | ||
1043 | */ | ||
1044 | struct fc_rpsc2_acc_s{ | ||
1045 | u8 els_cmd; | ||
1046 | u8 resvd; | ||
1047 | u16 num_pids; /* Number of pids in the request */ | ||
1048 | struct fc_rpsc2_port_info_s port_info[1]; /* port information */ | ||
1049 | }; | ||
1050 | |||
1051 | /** | ||
1052 | * bit fields so that multiple classes can be specified | ||
1053 | */ | ||
1054 | enum fc_cos{ | ||
1055 | FC_CLASS_2 = 0x04, | ||
1056 | FC_CLASS_3 = 0x08, | ||
1057 | FC_CLASS_2_3 = 0x0C, | ||
1058 | }; | ||
1059 | |||
1060 | /* | ||
1061 | * symbolic name | ||
1062 | */ | ||
1063 | struct fc_symname_s{ | ||
1064 | u8 symname[FC_SYMNAME_MAX]; | ||
1065 | }; | ||
1066 | |||
1067 | struct fc_alpabm_s{ | ||
1068 | u8 alpa_bm[FC_ALPA_MAX / 8]; | ||
1069 | }; | ||
1070 | |||
1071 | /* | ||
1072 | * protocol default timeout values | ||
1073 | */ | ||
1074 | #define FC_ED_TOV 2 | ||
1075 | #define FC_REC_TOV (FC_ED_TOV + 1) | ||
1076 | #define FC_RA_TOV 10 | ||
1077 | #define FC_ELS_TOV (2 * FC_RA_TOV) | ||
1078 | |||
1079 | /* | ||
1080 | * virtual fabric related defines | ||
1081 | */ | ||
1082 | #define FC_VF_ID_NULL 0 /* must not be used as VF_ID */ | ||
1083 | #define FC_VF_ID_MIN 1 | ||
1084 | #define FC_VF_ID_MAX 0xEFF | ||
1085 | #define FC_VF_ID_CTL 0xFEF /* control VF_ID */ | ||
1086 | |||
1087 | /** | ||
1088 | * Virtual Fabric Tagging header format | ||
1089 | * @caution This is defined only in BIG ENDIAN format. | ||
1090 | */ | ||
1091 | struct fc_vft_s{ | ||
1092 | u32 r_ctl:8; | ||
1093 | u32 ver:2; | ||
1094 | u32 type:4; | ||
1095 | u32 res_a:2; | ||
1096 | u32 priority:3; | ||
1097 | u32 vf_id:12; | ||
1098 | u32 res_b:1; | ||
1099 | u32 hopct:8; | ||
1100 | u32 res_c:24; | ||
1101 | }; | ||
1102 | |||
1103 | #pragma pack() | ||
1104 | |||
1105 | #endif | ||
diff --git a/drivers/scsi/bfa/include/protocol/fc_sp.h b/drivers/scsi/bfa/include/protocol/fc_sp.h new file mode 100644 index 000000000000..55bb0b31d04b --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/fc_sp.h | |||
@@ -0,0 +1,224 @@ | |||
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 | #ifndef __FC_SP_H__ | ||
19 | #define __FC_SP_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum auth_els_flags{ | ||
26 | FC_AUTH_ELS_MORE_FRAGS_FLAG = 0x80, /*! bit-7. More Fragments | ||
27 | * Follow | ||
28 | */ | ||
29 | FC_AUTH_ELS_CONCAT_FLAG = 0x40, /*! bit-6. Concatenation Flag */ | ||
30 | FC_AUTH_ELS_SEQ_NUM_FLAG = 0x01 /*! bit-0. Sequence Number */ | ||
31 | }; | ||
32 | |||
33 | enum auth_msg_codes{ | ||
34 | FC_AUTH_MC_AUTH_RJT = 0x0A, /*! Auth Reject */ | ||
35 | FC_AUTH_MC_AUTH_NEG = 0x0B, /*! Auth Negotiate */ | ||
36 | FC_AUTH_MC_AUTH_DONE = 0x0C, /*! Auth Done */ | ||
37 | |||
38 | FC_AUTH_MC_DHCHAP_CHAL = 0x10, /*! DHCHAP Challenge */ | ||
39 | FC_AUTH_MC_DHCHAP_REPLY = 0x11, /*! DHCHAP Reply */ | ||
40 | FC_AUTH_MC_DHCHAP_SUCC = 0x12, /*! DHCHAP Success */ | ||
41 | |||
42 | FC_AUTH_MC_FCAP_REQ = 0x13, /*! FCAP Request */ | ||
43 | FC_AUTH_MC_FCAP_ACK = 0x14, /*! FCAP Acknowledge */ | ||
44 | FC_AUTH_MC_FCAP_CONF = 0x15, /*! FCAP Confirm */ | ||
45 | |||
46 | FC_AUTH_MC_FCPAP_INIT = 0x16, /*! FCPAP Init */ | ||
47 | FC_AUTH_MC_FCPAP_ACC = 0x17, /*! FCPAP Accept */ | ||
48 | FC_AUTH_MC_FCPAP_COMP = 0x18, /*! FCPAP Complete */ | ||
49 | |||
50 | FC_AUTH_MC_IKE_SA_INIT = 0x22, /*! IKE SA INIT */ | ||
51 | FC_AUTH_MC_IKE_SA_AUTH = 0x23, /*! IKE SA Auth */ | ||
52 | FC_AUTH_MC_IKE_CREATE_CHILD_SA = 0x24, /*! IKE Create Child SA */ | ||
53 | FC_AUTH_MC_IKE_INFO = 0x25, /*! IKE informational */ | ||
54 | }; | ||
55 | |||
56 | enum auth_proto_version{ | ||
57 | FC_AUTH_PROTO_VER_1 = 1, /*! Protocol Version 1 */ | ||
58 | }; | ||
59 | |||
60 | enum { | ||
61 | FC_AUTH_ELS_COMMAND_CODE = 0x90,/*! Authentication ELS Command code */ | ||
62 | FC_AUTH_PROTO_PARAM_LEN_SZ = 4, /*! Size of Proto Parameter Len Field */ | ||
63 | FC_AUTH_PROTO_PARAM_VAL_SZ = 4, /*! Size of Proto Parameter Val Field */ | ||
64 | FC_MAX_AUTH_SECRET_LEN = 256, | ||
65 | /*! Maximum secret string length */ | ||
66 | FC_AUTH_NUM_USABLE_PROTO_LEN_SZ = 4, | ||
67 | /*! Size of usable protocols field */ | ||
68 | FC_AUTH_RESP_VALUE_LEN_SZ = 4, | ||
69 | /*! Size of response value length */ | ||
70 | FC_MAX_CHAP_KEY_LEN = 256, /*! Maximum md5 digest length */ | ||
71 | FC_MAX_AUTH_RETRIES = 3, /*! Maximum number of retries */ | ||
72 | FC_MD5_DIGEST_LEN = 16, /*! MD5 digest length */ | ||
73 | FC_SHA1_DIGEST_LEN = 20, /*! SHA1 digest length */ | ||
74 | FC_MAX_DHG_SUPPORTED = 1, /*! Maximum DH Groups supported */ | ||
75 | FC_MAX_ALG_SUPPORTED = 1, /*! Maximum algorithms supported */ | ||
76 | FC_MAX_PROTO_SUPPORTED = 1, /*! Maximum protocols supported */ | ||
77 | FC_START_TXN_ID = 2, /*! Starting transaction ID */ | ||
78 | }; | ||
79 | |||
80 | enum auth_proto_id{ | ||
81 | FC_AUTH_PROTO_DHCHAP = 0x00000001, | ||
82 | FC_AUTH_PROTO_FCAP = 0x00000002, | ||
83 | FC_AUTH_PROTO_FCPAP = 0x00000003, | ||
84 | FC_AUTH_PROTO_IKEv2 = 0x00000004, | ||
85 | FC_AUTH_PROTO_IKEv2_AUTH = 0x00000005, | ||
86 | }; | ||
87 | |||
88 | struct auth_name_s{ | ||
89 | u16 name_tag; /*! Name Tag = 1 for Authentication */ | ||
90 | u16 name_len; /*! Name Length = 8 for Authentication | ||
91 | */ | ||
92 | wwn_t name; /*! Name. TODO - is this PWWN */ | ||
93 | }; | ||
94 | |||
95 | |||
96 | enum auth_hash_func{ | ||
97 | FC_AUTH_HASH_FUNC_MD5 = 0x00000005, | ||
98 | FC_AUTH_HASH_FUNC_SHA_1 = 0x00000006, | ||
99 | }; | ||
100 | |||
101 | enum auth_dh_gid{ | ||
102 | FC_AUTH_DH_GID_0_DHG_NULL = 0x00000000, | ||
103 | FC_AUTH_DH_GID_1_DHG_1024 = 0x00000001, | ||
104 | FC_AUTH_DH_GID_2_DHG_1280 = 0x00000002, | ||
105 | FC_AUTH_DH_GID_3_DHG_1536 = 0x00000003, | ||
106 | FC_AUTH_DH_GID_4_DHG_2048 = 0x00000004, | ||
107 | FC_AUTH_DH_GID_6_DHG_3072 = 0x00000006, | ||
108 | FC_AUTH_DH_GID_7_DHG_4096 = 0x00000007, | ||
109 | FC_AUTH_DH_GID_8_DHG_6144 = 0x00000008, | ||
110 | FC_AUTH_DH_GID_9_DHG_8192 = 0x00000009, | ||
111 | }; | ||
112 | |||
113 | struct auth_els_msg_s { | ||
114 | u8 auth_els_code; /* Authentication ELS Code (0x90) */ | ||
115 | u8 auth_els_flag; /* Authentication ELS Flags */ | ||
116 | u8 auth_msg_code; /* Authentication Message Code */ | ||
117 | u8 proto_version; /* Protocol Version */ | ||
118 | u32 msg_len; /* Message Length */ | ||
119 | u32 trans_id; /* Transaction Identifier (T_ID) */ | ||
120 | |||
121 | /* Msg payload follows... */ | ||
122 | }; | ||
123 | |||
124 | |||
125 | enum auth_neg_param_tags { | ||
126 | FC_AUTH_NEG_DHCHAP_HASHLIST = 0x0001, | ||
127 | FC_AUTH_NEG_DHCHAP_DHG_ID_LIST = 0x0002, | ||
128 | }; | ||
129 | |||
130 | |||
131 | struct dhchap_param_format_s { | ||
132 | u16 tag; /*! Parameter Tag. See | ||
133 | * auth_neg_param_tags_t | ||
134 | */ | ||
135 | u16 word_cnt; | ||
136 | |||
137 | /* followed by variable length parameter value... */ | ||
138 | }; | ||
139 | |||
140 | struct auth_proto_params_s { | ||
141 | u32 proto_param_len; | ||
142 | u32 proto_id; | ||
143 | |||
144 | /* | ||
145 | * Followed by variable length Protocol specific parameters. DH-CHAP | ||
146 | * uses dhchap_param_format_t | ||
147 | */ | ||
148 | }; | ||
149 | |||
150 | struct auth_neg_msg_s { | ||
151 | struct auth_name_s auth_ini_name; | ||
152 | u32 usable_auth_protos; | ||
153 | struct auth_proto_params_s proto_params[1]; /*! (1..usable_auth_proto) | ||
154 | * protocol params | ||
155 | */ | ||
156 | }; | ||
157 | |||
158 | struct auth_dh_val_s { | ||
159 | u32 dh_val_len; | ||
160 | u32 dh_val[1]; | ||
161 | }; | ||
162 | |||
163 | struct auth_dhchap_chal_msg_s { | ||
164 | struct auth_els_msg_s hdr; | ||
165 | struct auth_name_s auth_responder_name; /* TODO VRK - is auth_name_t | ||
166 | * type OK? | ||
167 | */ | ||
168 | u32 hash_id; | ||
169 | u32 dh_grp_id; | ||
170 | u32 chal_val_len; | ||
171 | char chal_val[1]; | ||
172 | |||
173 | /* ...followed by variable Challenge length/value and DH length/value */ | ||
174 | }; | ||
175 | |||
176 | |||
177 | enum auth_rjt_codes { | ||
178 | FC_AUTH_RJT_CODE_AUTH_FAILURE = 0x01, | ||
179 | FC_AUTH_RJT_CODE_LOGICAL_ERR = 0x02, | ||
180 | }; | ||
181 | |||
182 | enum auth_rjt_code_exps { | ||
183 | FC_AUTH_CEXP_AUTH_MECH_NOT_USABLE = 0x01, | ||
184 | FC_AUTH_CEXP_DH_GROUP_NOT_USABLE = 0x02, | ||
185 | FC_AUTH_CEXP_HASH_FUNC_NOT_USABLE = 0x03, | ||
186 | FC_AUTH_CEXP_AUTH_XACT_STARTED = 0x04, | ||
187 | FC_AUTH_CEXP_AUTH_FAILED = 0x05, | ||
188 | FC_AUTH_CEXP_INCORRECT_PLD = 0x06, | ||
189 | FC_AUTH_CEXP_INCORRECT_PROTO_MSG = 0x07, | ||
190 | FC_AUTH_CEXP_RESTART_AUTH_PROTO = 0x08, | ||
191 | FC_AUTH_CEXP_AUTH_CONCAT_NOT_SUPP = 0x09, | ||
192 | FC_AUTH_CEXP_PROTO_VER_NOT_SUPP = 0x0A, | ||
193 | }; | ||
194 | |||
195 | enum auth_status { | ||
196 | FC_AUTH_STATE_INPROGRESS = 0, /*! authentication in progress */ | ||
197 | FC_AUTH_STATE_FAILED = 1, /*! authentication failed */ | ||
198 | FC_AUTH_STATE_SUCCESS = 2 /*! authentication successful */ | ||
199 | }; | ||
200 | |||
201 | struct auth_rjt_msg_s { | ||
202 | struct auth_els_msg_s hdr; | ||
203 | u8 reason_code; | ||
204 | u8 reason_code_exp; | ||
205 | u8 rsvd[2]; | ||
206 | }; | ||
207 | |||
208 | |||
209 | struct auth_dhchap_neg_msg_s { | ||
210 | struct auth_els_msg_s hdr; | ||
211 | struct auth_neg_msg_s nego; | ||
212 | }; | ||
213 | |||
214 | struct auth_dhchap_reply_msg_s { | ||
215 | struct auth_els_msg_s hdr; | ||
216 | |||
217 | /* | ||
218 | * followed by response value length & Value + DH Value Length & Value | ||
219 | */ | ||
220 | }; | ||
221 | |||
222 | #pragma pack() | ||
223 | |||
224 | #endif /* __FC_SP_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/protocol/fcp.h b/drivers/scsi/bfa/include/protocol/fcp.h new file mode 100644 index 000000000000..9ade68ad2853 --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/fcp.h | |||
@@ -0,0 +1,186 @@ | |||
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 | #ifndef __FCPPROTO_H__ | ||
19 | #define __FCPPROTO_H__ | ||
20 | |||
21 | #include <protocol/scsi.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | enum { | ||
26 | FCP_RJT = 0x01000000, /* SRR reject */ | ||
27 | FCP_SRR_ACCEPT = 0x02000000, /* SRR accept */ | ||
28 | FCP_SRR = 0x14000000, /* Sequence Retransmission Request */ | ||
29 | }; | ||
30 | |||
31 | /* | ||
32 | * SRR FC-4 LS payload | ||
33 | */ | ||
34 | struct fc_srr_s{ | ||
35 | u32 ls_cmd; | ||
36 | u32 ox_id:16; /* ox-id */ | ||
37 | u32 rx_id:16; /* rx-id */ | ||
38 | u32 ro; /* relative offset */ | ||
39 | u32 r_ctl:8; /* R_CTL for I.U. */ | ||
40 | u32 res:24; | ||
41 | }; | ||
42 | |||
43 | |||
44 | /* | ||
45 | * FCP_CMND definitions | ||
46 | */ | ||
47 | #define FCP_CMND_CDB_LEN 16 | ||
48 | #define FCP_CMND_LUN_LEN 8 | ||
49 | |||
50 | struct fcp_cmnd_s{ | ||
51 | lun_t lun; /* 64-bit LU number */ | ||
52 | u8 crn; /* command reference number */ | ||
53 | #ifdef __BIGENDIAN | ||
54 | u8 resvd:1, | ||
55 | priority:4, /* FCP-3: SAM-3 priority */ | ||
56 | taskattr:3; /* scsi task attribute */ | ||
57 | #else | ||
58 | u8 taskattr:3, /* scsi task attribute */ | ||
59 | priority:4, /* FCP-3: SAM-3 priority */ | ||
60 | resvd:1; | ||
61 | #endif | ||
62 | u8 tm_flags; /* task management flags */ | ||
63 | #ifdef __BIGENDIAN | ||
64 | u8 addl_cdb_len:6, /* additional CDB length words */ | ||
65 | iodir:2; /* read/write FCP_DATA IUs */ | ||
66 | #else | ||
67 | u8 iodir:2, /* read/write FCP_DATA IUs */ | ||
68 | addl_cdb_len:6; /* additional CDB length */ | ||
69 | #endif | ||
70 | struct scsi_cdb_s cdb; | ||
71 | |||
72 | /* | ||
73 | * !!! additional cdb bytes follows here!!! | ||
74 | */ | ||
75 | u32 fcp_dl; /* bytes to be transferred */ | ||
76 | }; | ||
77 | |||
78 | #define fcp_cmnd_cdb_len(_cmnd) ((_cmnd)->addl_cdb_len * 4 + FCP_CMND_CDB_LEN) | ||
79 | #define fcp_cmnd_fcpdl(_cmnd) ((&(_cmnd)->fcp_dl)[(_cmnd)->addl_cdb_len]) | ||
80 | |||
81 | /* | ||
82 | * fcp_cmnd_t.iodir field values | ||
83 | */ | ||
84 | enum fcp_iodir{ | ||
85 | FCP_IODIR_NONE = 0, | ||
86 | FCP_IODIR_WRITE = 1, | ||
87 | FCP_IODIR_READ = 2, | ||
88 | FCP_IODIR_RW = 3, | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * Task attribute field | ||
93 | */ | ||
94 | enum { | ||
95 | FCP_TASK_ATTR_SIMPLE = 0, | ||
96 | FCP_TASK_ATTR_HOQ = 1, | ||
97 | FCP_TASK_ATTR_ORDERED = 2, | ||
98 | FCP_TASK_ATTR_ACA = 4, | ||
99 | FCP_TASK_ATTR_UNTAGGED = 5, /* obsolete in FCP-3 */ | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * Task management flags field - only one bit shall be set | ||
104 | */ | ||
105 | #ifndef BIT | ||
106 | #define BIT(_x) (1 << (_x)) | ||
107 | #endif | ||
108 | enum fcp_tm_cmnd{ | ||
109 | FCP_TM_ABORT_TASK_SET = BIT(1), | ||
110 | FCP_TM_CLEAR_TASK_SET = BIT(2), | ||
111 | FCP_TM_LUN_RESET = BIT(4), | ||
112 | FCP_TM_TARGET_RESET = BIT(5), /* obsolete in FCP-3 */ | ||
113 | FCP_TM_CLEAR_ACA = BIT(6), | ||
114 | }; | ||
115 | |||
116 | /* | ||
117 | * FCP_XFER_RDY IU defines | ||
118 | */ | ||
119 | struct fcp_xfer_rdy_s{ | ||
120 | u32 data_ro; | ||
121 | u32 burst_len; | ||
122 | u32 reserved; | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * FCP_RSP residue flags | ||
127 | */ | ||
128 | enum fcp_residue{ | ||
129 | FCP_NO_RESIDUE = 0, /* no residue */ | ||
130 | FCP_RESID_OVER = 1, /* more data left that was not sent */ | ||
131 | FCP_RESID_UNDER = 2, /* less data than requested */ | ||
132 | }; | ||
133 | |||
134 | enum { | ||
135 | FCP_RSPINFO_GOOD = 0, | ||
136 | FCP_RSPINFO_DATALEN_MISMATCH = 1, | ||
137 | FCP_RSPINFO_CMND_INVALID = 2, | ||
138 | FCP_RSPINFO_ROLEN_MISMATCH = 3, | ||
139 | FCP_RSPINFO_TM_NOT_SUPP = 4, | ||
140 | FCP_RSPINFO_TM_FAILED = 5, | ||
141 | }; | ||
142 | |||
143 | struct fcp_rspinfo_s{ | ||
144 | u32 res0:24; | ||
145 | u32 rsp_code:8; /* response code (as above) */ | ||
146 | u32 res1; | ||
147 | }; | ||
148 | |||
149 | struct fcp_resp_s{ | ||
150 | u32 reserved[2]; /* 2 words reserved */ | ||
151 | u16 reserved2; | ||
152 | #ifdef __BIGENDIAN | ||
153 | u8 reserved3:3; | ||
154 | u8 fcp_conf_req:1; /* FCP_CONF is requested */ | ||
155 | u8 resid_flags:2; /* underflow/overflow */ | ||
156 | u8 sns_len_valid:1;/* sense len is valid */ | ||
157 | u8 rsp_len_valid:1;/* response len is valid */ | ||
158 | #else | ||
159 | u8 rsp_len_valid:1;/* response len is valid */ | ||
160 | u8 sns_len_valid:1;/* sense len is valid */ | ||
161 | u8 resid_flags:2; /* underflow/overflow */ | ||
162 | u8 fcp_conf_req:1; /* FCP_CONF is requested */ | ||
163 | u8 reserved3:3; | ||
164 | #endif | ||
165 | u8 scsi_status; /* one byte SCSI status */ | ||
166 | u32 residue; /* residual data bytes */ | ||
167 | u32 sns_len; /* length od sense info */ | ||
168 | u32 rsp_len; /* length of response info */ | ||
169 | }; | ||
170 | |||
171 | #define fcp_snslen(__fcprsp) ((__fcprsp)->sns_len_valid ? \ | ||
172 | (__fcprsp)->sns_len : 0) | ||
173 | #define fcp_rsplen(__fcprsp) ((__fcprsp)->rsp_len_valid ? \ | ||
174 | (__fcprsp)->rsp_len : 0) | ||
175 | #define fcp_rspinfo(__fcprsp) ((struct fcp_rspinfo_s *)((__fcprsp) + 1)) | ||
176 | #define fcp_snsinfo(__fcprsp) (((u8 *)fcp_rspinfo(__fcprsp)) + \ | ||
177 | fcp_rsplen(__fcprsp)) | ||
178 | |||
179 | struct fcp_cmnd_fr_s{ | ||
180 | struct fchs_s fchs; | ||
181 | struct fcp_cmnd_s fcp; | ||
182 | }; | ||
183 | |||
184 | #pragma pack() | ||
185 | |||
186 | #endif | ||
diff --git a/drivers/scsi/bfa/include/protocol/fdmi.h b/drivers/scsi/bfa/include/protocol/fdmi.h new file mode 100644 index 000000000000..6c05c268c71b --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/fdmi.h | |||
@@ -0,0 +1,163 @@ | |||
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 | #ifndef __FDMI_H__ | ||
19 | #define __FDMI_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | #include <protocol/fc.h> | ||
23 | #include <protocol/ct.h> | ||
24 | |||
25 | #pragma pack(1) | ||
26 | |||
27 | /* | ||
28 | * FDMI Command Codes | ||
29 | */ | ||
30 | #define FDMI_GRHL 0x0100 | ||
31 | #define FDMI_GHAT 0x0101 | ||
32 | #define FDMI_GRPL 0x0102 | ||
33 | #define FDMI_GPAT 0x0110 | ||
34 | #define FDMI_RHBA 0x0200 | ||
35 | #define FDMI_RHAT 0x0201 | ||
36 | #define FDMI_RPRT 0x0210 | ||
37 | #define FDMI_RPA 0x0211 | ||
38 | #define FDMI_DHBA 0x0300 | ||
39 | #define FDMI_DPRT 0x0310 | ||
40 | |||
41 | /* | ||
42 | * FDMI reason codes | ||
43 | */ | ||
44 | #define FDMI_NO_ADDITIONAL_EXP 0x00 | ||
45 | #define FDMI_HBA_ALREADY_REG 0x10 | ||
46 | #define FDMI_HBA_ATTRIB_NOT_REG 0x11 | ||
47 | #define FDMI_HBA_ATTRIB_MULTIPLE 0x12 | ||
48 | #define FDMI_HBA_ATTRIB_LENGTH_INVALID 0x13 | ||
49 | #define FDMI_HBA_ATTRIB_NOT_PRESENT 0x14 | ||
50 | #define FDMI_PORT_ORIG_NOT_IN_LIST 0x15 | ||
51 | #define FDMI_PORT_HBA_NOT_IN_LIST 0x16 | ||
52 | #define FDMI_PORT_ATTRIB_NOT_REG 0x20 | ||
53 | #define FDMI_PORT_NOT_REG 0x21 | ||
54 | #define FDMI_PORT_ATTRIB_MULTIPLE 0x22 | ||
55 | #define FDMI_PORT_ATTRIB_LENGTH_INVALID 0x23 | ||
56 | #define FDMI_PORT_ALREADY_REGISTEREED 0x24 | ||
57 | |||
58 | /* | ||
59 | * FDMI Transmission Speed Mask values | ||
60 | */ | ||
61 | #define FDMI_TRANS_SPEED_1G 0x00000001 | ||
62 | #define FDMI_TRANS_SPEED_2G 0x00000002 | ||
63 | #define FDMI_TRANS_SPEED_10G 0x00000004 | ||
64 | #define FDMI_TRANS_SPEED_4G 0x00000008 | ||
65 | #define FDMI_TRANS_SPEED_8G 0x00000010 | ||
66 | #define FDMI_TRANS_SPEED_16G 0x00000020 | ||
67 | #define FDMI_TRANS_SPEED_UNKNOWN 0x00008000 | ||
68 | |||
69 | /* | ||
70 | * FDMI HBA attribute types | ||
71 | */ | ||
72 | enum fdmi_hba_attribute_type { | ||
73 | FDMI_HBA_ATTRIB_NODENAME = 1, /* 0x0001 */ | ||
74 | FDMI_HBA_ATTRIB_MANUFACTURER, /* 0x0002 */ | ||
75 | FDMI_HBA_ATTRIB_SERIALNUM, /* 0x0003 */ | ||
76 | FDMI_HBA_ATTRIB_MODEL, /* 0x0004 */ | ||
77 | FDMI_HBA_ATTRIB_MODEL_DESC, /* 0x0005 */ | ||
78 | FDMI_HBA_ATTRIB_HW_VERSION, /* 0x0006 */ | ||
79 | FDMI_HBA_ATTRIB_DRIVER_VERSION, /* 0x0007 */ | ||
80 | FDMI_HBA_ATTRIB_ROM_VERSION, /* 0x0008 */ | ||
81 | FDMI_HBA_ATTRIB_FW_VERSION, /* 0x0009 */ | ||
82 | FDMI_HBA_ATTRIB_OS_NAME, /* 0x000A */ | ||
83 | FDMI_HBA_ATTRIB_MAX_CT, /* 0x000B */ | ||
84 | |||
85 | FDMI_HBA_ATTRIB_MAX_TYPE | ||
86 | }; | ||
87 | |||
88 | /* | ||
89 | * FDMI Port attribute types | ||
90 | */ | ||
91 | enum fdmi_port_attribute_type { | ||
92 | FDMI_PORT_ATTRIB_FC4_TYPES = 1, /* 0x0001 */ | ||
93 | FDMI_PORT_ATTRIB_SUPP_SPEED, /* 0x0002 */ | ||
94 | FDMI_PORT_ATTRIB_PORT_SPEED, /* 0x0003 */ | ||
95 | FDMI_PORT_ATTRIB_FRAME_SIZE, /* 0x0004 */ | ||
96 | FDMI_PORT_ATTRIB_DEV_NAME, /* 0x0005 */ | ||
97 | FDMI_PORT_ATTRIB_HOST_NAME, /* 0x0006 */ | ||
98 | |||
99 | FDMI_PORT_ATTR_MAX_TYPE | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * FDMI attribute | ||
104 | */ | ||
105 | struct fdmi_attr_s { | ||
106 | u16 type; | ||
107 | u16 len; | ||
108 | u8 value[1]; | ||
109 | }; | ||
110 | |||
111 | /* | ||
112 | * HBA Attribute Block | ||
113 | */ | ||
114 | struct fdmi_hba_attr_s { | ||
115 | u32 attr_count; /* # of attributes */ | ||
116 | struct fdmi_attr_s hba_attr; /* n attributes */ | ||
117 | }; | ||
118 | |||
119 | /* | ||
120 | * Registered Port List | ||
121 | */ | ||
122 | struct fdmi_port_list_s { | ||
123 | u32 num_ports; /* number Of Port Entries */ | ||
124 | wwn_t port_entry; /* one or more */ | ||
125 | }; | ||
126 | |||
127 | /* | ||
128 | * Port Attribute Block | ||
129 | */ | ||
130 | struct fdmi_port_attr_s { | ||
131 | u32 attr_count; /* # of attributes */ | ||
132 | struct fdmi_attr_s port_attr; /* n attributes */ | ||
133 | }; | ||
134 | |||
135 | /* | ||
136 | * FDMI Register HBA Attributes | ||
137 | */ | ||
138 | struct fdmi_rhba_s { | ||
139 | wwn_t hba_id; /* HBA Identifier */ | ||
140 | struct fdmi_port_list_s port_list; /* Registered Port List */ | ||
141 | struct fdmi_hba_attr_s hba_attr_blk; /* HBA attribute block */ | ||
142 | }; | ||
143 | |||
144 | /* | ||
145 | * FDMI Register Port | ||
146 | */ | ||
147 | struct fdmi_rprt_s { | ||
148 | wwn_t hba_id; /* HBA Identifier */ | ||
149 | wwn_t port_name; /* Port wwn */ | ||
150 | struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */ | ||
151 | }; | ||
152 | |||
153 | /* | ||
154 | * FDMI Register Port Attributes | ||
155 | */ | ||
156 | struct fdmi_rpa_s { | ||
157 | wwn_t port_name; /* port wwn */ | ||
158 | struct fdmi_port_attr_s port_attr_blk; /* Port Attr Block */ | ||
159 | }; | ||
160 | |||
161 | #pragma pack() | ||
162 | |||
163 | #endif | ||
diff --git a/drivers/scsi/bfa/include/protocol/pcifw.h b/drivers/scsi/bfa/include/protocol/pcifw.h new file mode 100644 index 000000000000..6830dc3ee58a --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/pcifw.h | |||
@@ -0,0 +1,75 @@ | |||
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 | * pcifw.h PCI FW related headers | ||
20 | */ | ||
21 | |||
22 | #ifndef __PCIFW_H__ | ||
23 | #define __PCIFW_H__ | ||
24 | |||
25 | #pragma pack(1) | ||
26 | |||
27 | struct pnp_hdr_s{ | ||
28 | u32 signature; /* "$PnP" */ | ||
29 | u8 rev; /* Struct revision */ | ||
30 | u8 len; /* Header structure len in multiples | ||
31 | * of 16 bytes */ | ||
32 | u16 off; /* Offset to next header 00 if none */ | ||
33 | u8 rsvd; /* Reserved byte */ | ||
34 | u8 cksum; /* 8-bit checksum for this header */ | ||
35 | u32 pnp_dev_id; /* PnP Device Id */ | ||
36 | u16 mfstr; /* Pointer to manufacturer string */ | ||
37 | u16 prstr; /* Pointer to product string */ | ||
38 | u8 devtype[3]; /* Device Type Code */ | ||
39 | u8 devind; /* Device Indicator */ | ||
40 | u16 bcventr; /* Bootstrap entry vector */ | ||
41 | u16 rsvd2; /* Reserved */ | ||
42 | u16 sriv; /* Static resource information vector */ | ||
43 | }; | ||
44 | |||
45 | struct pci_3_0_ds_s{ | ||
46 | u32 sig; /* Signature "PCIR" */ | ||
47 | u16 vendid; /* Vendor ID */ | ||
48 | u16 devid; /* Device ID */ | ||
49 | u16 devlistoff; /* Device List Offset */ | ||
50 | u16 len; /* PCI Data Structure Length */ | ||
51 | u8 rev; /* PCI Data Structure Revision */ | ||
52 | u8 clcode[3]; /* Class Code */ | ||
53 | u16 imglen; /* Code image length in multiples of | ||
54 | * 512 bytes */ | ||
55 | u16 coderev; /* Revision level of code/data */ | ||
56 | u8 codetype; /* Code type 0x00 - BIOS */ | ||
57 | u8 indr; /* Last image indicator */ | ||
58 | u16 mrtimglen; /* Max Run Time Image Length */ | ||
59 | u16 cuoff; /* Config Utility Code Header Offset */ | ||
60 | u16 dmtfclp; /* DMTF CLP entry point offset */ | ||
61 | }; | ||
62 | |||
63 | struct pci_optrom_hdr_s{ | ||
64 | u16 sig; /* Signature 0x55AA */ | ||
65 | u8 len; /* Option ROM length in units of 512 bytes */ | ||
66 | u8 inivec[3]; /* Initialization vector */ | ||
67 | u8 rsvd[16]; /* Reserved field */ | ||
68 | u16 verptr; /* Pointer to version string - private */ | ||
69 | u16 pcids; /* Pointer to PCI data structure */ | ||
70 | u16 pnphdr; /* Pointer to PnP expansion header */ | ||
71 | }; | ||
72 | |||
73 | #pragma pack() | ||
74 | |||
75 | #endif | ||
diff --git a/drivers/scsi/bfa/include/protocol/scsi.h b/drivers/scsi/bfa/include/protocol/scsi.h new file mode 100644 index 000000000000..b220e6b4f6e1 --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/scsi.h | |||
@@ -0,0 +1,1648 @@ | |||
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 | #ifndef __SCSI_H__ | ||
19 | #define __SCSI_H__ | ||
20 | |||
21 | #include <protocol/types.h> | ||
22 | |||
23 | #pragma pack(1) | ||
24 | |||
25 | /* | ||
26 | * generic SCSI cdb definition | ||
27 | */ | ||
28 | #define SCSI_MAX_CDBLEN 16 | ||
29 | struct scsi_cdb_s{ | ||
30 | u8 scsi_cdb[SCSI_MAX_CDBLEN]; | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * scsi lun serial number definition | ||
35 | */ | ||
36 | #define SCSI_LUN_SN_LEN 32 | ||
37 | struct scsi_lun_sn_s{ | ||
38 | u8 lun_sn[SCSI_LUN_SN_LEN]; | ||
39 | }; | ||
40 | |||
41 | /* | ||
42 | * SCSI Direct Access Commands | ||
43 | */ | ||
44 | enum { | ||
45 | SCSI_OP_TEST_UNIT_READY = 0x00, | ||
46 | SCSI_OP_REQUEST_SENSE = 0x03, | ||
47 | SCSI_OP_FORMAT_UNIT = 0x04, | ||
48 | SCSI_OP_READ6 = 0x08, | ||
49 | SCSI_OP_WRITE6 = 0x0A, | ||
50 | SCSI_OP_WRITE_FILEMARKS = 0x10, | ||
51 | SCSI_OP_INQUIRY = 0x12, | ||
52 | SCSI_OP_MODE_SELECT6 = 0x15, | ||
53 | SCSI_OP_RESERVE6 = 0x16, | ||
54 | SCSI_OP_RELEASE6 = 0x17, | ||
55 | SCSI_OP_MODE_SENSE6 = 0x1A, | ||
56 | SCSI_OP_START_STOP_UNIT = 0x1B, | ||
57 | SCSI_OP_SEND_DIAGNOSTIC = 0x1D, | ||
58 | SCSI_OP_READ_CAPACITY = 0x25, | ||
59 | SCSI_OP_READ10 = 0x28, | ||
60 | SCSI_OP_WRITE10 = 0x2A, | ||
61 | SCSI_OP_VERIFY10 = 0x2F, | ||
62 | SCSI_OP_READ_DEFECT_DATA = 0x37, | ||
63 | SCSI_OP_LOG_SELECT = 0x4C, | ||
64 | SCSI_OP_LOG_SENSE = 0x4D, | ||
65 | SCSI_OP_MODE_SELECT10 = 0x55, | ||
66 | SCSI_OP_RESERVE10 = 0x56, | ||
67 | SCSI_OP_RELEASE10 = 0x57, | ||
68 | SCSI_OP_MODE_SENSE10 = 0x5A, | ||
69 | SCSI_OP_PER_RESERVE_IN = 0x5E, | ||
70 | SCSI_OP_PER_RESERVE_OUR = 0x5E, | ||
71 | SCSI_OP_READ16 = 0x88, | ||
72 | SCSI_OP_WRITE16 = 0x8A, | ||
73 | SCSI_OP_VERIFY16 = 0x8F, | ||
74 | SCSI_OP_READ_CAPACITY16 = 0x9E, | ||
75 | SCSI_OP_REPORT_LUNS = 0xA0, | ||
76 | SCSI_OP_READ12 = 0xA8, | ||
77 | SCSI_OP_WRITE12 = 0xAA, | ||
78 | SCSI_OP_UNDEF = 0xFF, | ||
79 | }; | ||
80 | |||
81 | /* | ||
82 | * SCSI START_STOP_UNIT command | ||
83 | */ | ||
84 | struct scsi_start_stop_unit_s{ | ||
85 | u8 opcode; | ||
86 | #ifdef __BIGENDIAN | ||
87 | u8 lun:3; | ||
88 | u8 reserved1:4; | ||
89 | u8 immed:1; | ||
90 | #else | ||
91 | u8 immed:1; | ||
92 | u8 reserved1:4; | ||
93 | u8 lun:3; | ||
94 | #endif | ||
95 | u8 reserved2; | ||
96 | u8 reserved3; | ||
97 | #ifdef __BIGENDIAN | ||
98 | u8 power_conditions:4; | ||
99 | u8 reserved4:2; | ||
100 | u8 loEj:1; | ||
101 | u8 start:1; | ||
102 | #else | ||
103 | u8 start:1; | ||
104 | u8 loEj:1; | ||
105 | u8 reserved4:2; | ||
106 | u8 power_conditions:4; | ||
107 | #endif | ||
108 | u8 control; | ||
109 | }; | ||
110 | |||
111 | /* | ||
112 | * SCSI SEND_DIAGNOSTIC command | ||
113 | */ | ||
114 | struct scsi_send_diagnostic_s{ | ||
115 | u8 opcode; | ||
116 | #ifdef __BIGENDIAN | ||
117 | u8 self_test_code:3; | ||
118 | u8 pf:1; | ||
119 | u8 reserved1:1; | ||
120 | u8 self_test:1; | ||
121 | u8 dev_offl:1; | ||
122 | u8 unit_offl:1; | ||
123 | #else | ||
124 | u8 unit_offl:1; | ||
125 | u8 dev_offl:1; | ||
126 | u8 self_test:1; | ||
127 | u8 reserved1:1; | ||
128 | u8 pf:1; | ||
129 | u8 self_test_code:3; | ||
130 | #endif | ||
131 | u8 reserved2; | ||
132 | |||
133 | u8 param_list_length[2]; /* MSB first */ | ||
134 | u8 control; | ||
135 | |||
136 | }; | ||
137 | |||
138 | /* | ||
139 | * SCSI READ10/WRITE10 commands | ||
140 | */ | ||
141 | struct scsi_rw10_s{ | ||
142 | u8 opcode; | ||
143 | #ifdef __BIGENDIAN | ||
144 | u8 lun:3; | ||
145 | u8 dpo:1; /* Disable Page Out */ | ||
146 | u8 fua:1; /* Force Unit Access */ | ||
147 | u8 reserved1:2; | ||
148 | u8 rel_adr:1; /* relative address */ | ||
149 | #else | ||
150 | u8 rel_adr:1; | ||
151 | u8 reserved1:2; | ||
152 | u8 fua:1; | ||
153 | u8 dpo:1; | ||
154 | u8 lun:3; | ||
155 | #endif | ||
156 | u8 lba0; /* logical block address - MSB */ | ||
157 | u8 lba1; | ||
158 | u8 lba2; | ||
159 | u8 lba3; /* LSB */ | ||
160 | u8 reserved3; | ||
161 | u8 xfer_length0; /* transfer length in blocks - MSB */ | ||
162 | u8 xfer_length1; /* LSB */ | ||
163 | u8 control; | ||
164 | }; | ||
165 | |||
166 | #define SCSI_CDB10_GET_LBA(cdb) \ | ||
167 | (((cdb)->lba0 << 24) | ((cdb)->lba1 << 16) | \ | ||
168 | ((cdb)->lba2 << 8) | (cdb)->lba3) | ||
169 | |||
170 | #define SCSI_CDB10_SET_LBA(cdb, lba) { \ | ||
171 | (cdb)->lba0 = lba >> 24; \ | ||
172 | (cdb)->lba1 = (lba >> 16) & 0xFF; \ | ||
173 | (cdb)->lba2 = (lba >> 8) & 0xFF; \ | ||
174 | (cdb)->lba3 = lba & 0xFF; \ | ||
175 | } | ||
176 | |||
177 | #define SCSI_CDB10_GET_TL(cdb) \ | ||
178 | ((cdb)->xfer_length0 << 8 | (cdb)->xfer_length1) | ||
179 | #define SCSI_CDB10_SET_TL(cdb, tl) { \ | ||
180 | (cdb)->xfer_length0 = tl >> 8; \ | ||
181 | (cdb)->xfer_length1 = tl & 0xFF; \ | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * SCSI READ6/WRITE6 commands | ||
186 | */ | ||
187 | struct scsi_rw6_s{ | ||
188 | u8 opcode; | ||
189 | #ifdef __BIGENDIAN | ||
190 | u8 lun:3; | ||
191 | u8 lba0:5; /* MSb */ | ||
192 | #else | ||
193 | u8 lba0:5; /* MSb */ | ||
194 | u8 lun:3; | ||
195 | #endif | ||
196 | u8 lba1; | ||
197 | u8 lba2; /* LSB */ | ||
198 | u8 xfer_length; | ||
199 | u8 control; | ||
200 | }; | ||
201 | |||
202 | #define SCSI_TAPE_CDB6_GET_TL(cdb) \ | ||
203 | (((cdb)->tl0 << 16) | ((cdb)->tl1 << 8) | (cdb)->tl2) | ||
204 | |||
205 | #define SCSI_TAPE_CDB6_SET_TL(cdb, tl) { \ | ||
206 | (cdb)->tl0 = tl >> 16; \ | ||
207 | (cdb)->tl1 = (tl >> 8) & 0xFF; \ | ||
208 | (cdb)->tl2 = tl & 0xFF; \ | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * SCSI sequential (TAPE) wrtie command | ||
213 | */ | ||
214 | struct scsi_tape_wr_s{ | ||
215 | u8 opcode; | ||
216 | #ifdef __BIGENDIAN | ||
217 | u8 rsvd:7; | ||
218 | u8 fixed:1; /* MSb */ | ||
219 | #else | ||
220 | u8 fixed:1; /* MSb */ | ||
221 | u8 rsvd:7; | ||
222 | #endif | ||
223 | u8 tl0; /* Msb */ | ||
224 | u8 tl1; | ||
225 | u8 tl2; /* Lsb */ | ||
226 | |||
227 | u8 control; | ||
228 | }; | ||
229 | |||
230 | #define SCSI_CDB6_GET_LBA(cdb) \ | ||
231 | (((cdb)->lba0 << 16) | ((cdb)->lba1 << 8) | (cdb)->lba2) | ||
232 | |||
233 | #define SCSI_CDB6_SET_LBA(cdb, lba) { \ | ||
234 | (cdb)->lba0 = lba >> 16; \ | ||
235 | (cdb)->lba1 = (lba >> 8) & 0xFF; \ | ||
236 | (cdb)->lba2 = lba & 0xFF; \ | ||
237 | } | ||
238 | |||
239 | #define SCSI_CDB6_GET_TL(cdb) ((cdb)->xfer_length) | ||
240 | #define SCSI_CDB6_SET_TL(cdb, tl) { \ | ||
241 | (cdb)->xfer_length = tl; \ | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * SCSI sense data format | ||
246 | */ | ||
247 | struct scsi_sense_s{ | ||
248 | #ifdef __BIGENDIAN | ||
249 | u8 valid:1; | ||
250 | u8 rsp_code:7; | ||
251 | #else | ||
252 | u8 rsp_code:7; | ||
253 | u8 valid:1; | ||
254 | #endif | ||
255 | u8 seg_num; | ||
256 | #ifdef __BIGENDIAN | ||
257 | u8 file_mark:1; | ||
258 | u8 eom:1; /* end of media */ | ||
259 | u8 ili:1; /* incorrect length indicator */ | ||
260 | u8 reserved:1; | ||
261 | u8 sense_key:4; | ||
262 | #else | ||
263 | u8 sense_key:4; | ||
264 | u8 reserved:1; | ||
265 | u8 ili:1; /* incorrect length indicator */ | ||
266 | u8 eom:1; /* end of media */ | ||
267 | u8 file_mark:1; | ||
268 | #endif | ||
269 | u8 information[4]; /* device-type or command specific info | ||
270 | */ | ||
271 | u8 add_sense_length; | ||
272 | /* additional sense length */ | ||
273 | u8 command_info[4];/* command specific information | ||
274 | */ | ||
275 | u8 asc; /* additional sense code */ | ||
276 | u8 ascq; /* additional sense code qualifier */ | ||
277 | u8 fru_code; /* field replaceable unit code */ | ||
278 | #ifdef __BIGENDIAN | ||
279 | u8 sksv:1; /* sense key specific valid */ | ||
280 | u8 c_d:1; /* command/data bit */ | ||
281 | u8 res1:2; | ||
282 | u8 bpv:1; /* bit pointer valid */ | ||
283 | u8 bpointer:3; /* bit pointer */ | ||
284 | #else | ||
285 | u8 bpointer:3; /* bit pointer */ | ||
286 | u8 bpv:1; /* bit pointer valid */ | ||
287 | u8 res1:2; | ||
288 | u8 c_d:1; /* command/data bit */ | ||
289 | u8 sksv:1; /* sense key specific valid */ | ||
290 | #endif | ||
291 | u8 fpointer[2]; /* field pointer */ | ||
292 | }; | ||
293 | |||
294 | #define SCSI_SENSE_CUR_ERR 0x70 | ||
295 | #define SCSI_SENSE_DEF_ERR 0x71 | ||
296 | |||
297 | /* | ||
298 | * SCSI sense key values | ||
299 | */ | ||
300 | #define SCSI_SK_NO_SENSE 0x0 | ||
301 | #define SCSI_SK_REC_ERR 0x1 /* recovered error */ | ||
302 | #define SCSI_SK_NOT_READY 0x2 | ||
303 | #define SCSI_SK_MED_ERR 0x3 /* medium error */ | ||
304 | #define SCSI_SK_HW_ERR 0x4 /* hardware error */ | ||
305 | #define SCSI_SK_ILLEGAL_REQ 0x5 | ||
306 | #define SCSI_SK_UNIT_ATT 0x6 /* unit attention */ | ||
307 | #define SCSI_SK_DATA_PROTECT 0x7 | ||
308 | #define SCSI_SK_BLANK_CHECK 0x8 | ||
309 | #define SCSI_SK_VENDOR_SPEC 0x9 | ||
310 | #define SCSI_SK_COPY_ABORTED 0xA | ||
311 | #define SCSI_SK_ABORTED_CMND 0xB | ||
312 | #define SCSI_SK_VOL_OVERFLOW 0xD | ||
313 | #define SCSI_SK_MISCOMPARE 0xE | ||
314 | |||
315 | /* | ||
316 | * SCSI additional sense codes | ||
317 | */ | ||
318 | #define SCSI_ASC_NO_ADD_SENSE 0x00 | ||
319 | #define SCSI_ASC_LUN_NOT_READY 0x04 | ||
320 | #define SCSI_ASC_LUN_COMMUNICATION 0x08 | ||
321 | #define SCSI_ASC_WRITE_ERROR 0x0C | ||
322 | #define SCSI_ASC_INVALID_CMND_CODE 0x20 | ||
323 | #define SCSI_ASC_BAD_LBA 0x21 | ||
324 | #define SCSI_ASC_INVALID_FIELD_IN_CDB 0x24 | ||
325 | #define SCSI_ASC_LUN_NOT_SUPPORTED 0x25 | ||
326 | #define SCSI_ASC_LUN_WRITE_PROTECT 0x27 | ||
327 | #define SCSI_ASC_POWERON_BDR 0x29 /* power on reset, bus reset, | ||
328 | * bus device reset | ||
329 | */ | ||
330 | #define SCSI_ASC_PARAMS_CHANGED 0x2A | ||
331 | #define SCSI_ASC_CMND_CLEARED_BY_A_I 0x2F | ||
332 | #define SCSI_ASC_SAVING_PARAM_NOTSUPP 0x39 | ||
333 | #define SCSI_ASC_TOCC 0x3F /* target operating condtions | ||
334 | * changed | ||
335 | */ | ||
336 | #define SCSI_ASC_PARITY_ERROR 0x47 | ||
337 | #define SCSI_ASC_CMND_PHASE_ERROR 0x4A | ||
338 | #define SCSI_ASC_DATA_PHASE_ERROR 0x4B | ||
339 | #define SCSI_ASC_VENDOR_SPEC 0x7F | ||
340 | |||
341 | /* | ||
342 | * SCSI additional sense code qualifiers | ||
343 | */ | ||
344 | #define SCSI_ASCQ_CAUSE_NOT_REPORT 0x00 | ||
345 | #define SCSI_ASCQ_BECOMING_READY 0x01 | ||
346 | #define SCSI_ASCQ_INIT_CMD_REQ 0x02 | ||
347 | #define SCSI_ASCQ_FORMAT_IN_PROGRESS 0x04 | ||
348 | #define SCSI_ASCQ_OPERATION_IN_PROGRESS 0x07 | ||
349 | #define SCSI_ASCQ_SELF_TEST_IN_PROGRESS 0x09 | ||
350 | #define SCSI_ASCQ_WR_UNEXP_UNSOL_DATA 0x0C | ||
351 | #define SCSI_ASCQ_WR_NOTENG_UNSOL_DATA 0x0D | ||
352 | |||
353 | #define SCSI_ASCQ_LBA_OUT_OF_RANGE 0x00 | ||
354 | #define SCSI_ASCQ_INVALID_ELEMENT_ADDR 0x01 | ||
355 | |||
356 | #define SCSI_ASCQ_LUN_WRITE_PROTECTED 0x00 | ||
357 | #define SCSI_ASCQ_LUN_HW_WRITE_PROTECTED 0x01 | ||
358 | #define SCSI_ASCQ_LUN_SW_WRITE_PROTECTED 0x02 | ||
359 | |||
360 | #define SCSI_ASCQ_POR 0x01 /* power on reset */ | ||
361 | #define SCSI_ASCQ_SBR 0x02 /* scsi bus reset */ | ||
362 | #define SCSI_ASCQ_BDR 0x03 /* bus device reset */ | ||
363 | #define SCSI_ASCQ_DIR 0x04 /* device internal reset */ | ||
364 | |||
365 | #define SCSI_ASCQ_MODE_PARAMS_CHANGED 0x01 | ||
366 | #define SCSI_ASCQ_LOG_PARAMS_CHANGED 0x02 | ||
367 | #define SCSI_ASCQ_RESERVATIONS_PREEMPTED 0x03 | ||
368 | #define SCSI_ASCQ_RESERVATIONS_RELEASED 0x04 | ||
369 | #define SCSI_ASCQ_REGISTRATIONS_PREEMPTED 0x05 | ||
370 | |||
371 | #define SCSI_ASCQ_MICROCODE_CHANGED 0x01 | ||
372 | #define SCSI_ASCQ_CHANGED_OPER_COND 0x02 | ||
373 | #define SCSI_ASCQ_INQ_CHANGED 0x03 /* inquiry data changed */ | ||
374 | #define SCSI_ASCQ_DI_CHANGED 0x05 /* device id changed */ | ||
375 | #define SCSI_ASCQ_RL_DATA_CHANGED 0x0E /* report luns data changed */ | ||
376 | |||
377 | #define SCSI_ASCQ_DP_CRC_ERR 0x01 /* data phase crc error */ | ||
378 | #define SCSI_ASCQ_DP_SCSI_PARITY_ERR 0x02 /* data phase scsi parity error | ||
379 | */ | ||
380 | #define SCSI_ASCQ_IU_CRC_ERR 0x03 /* information unit crc error */ | ||
381 | #define SCSI_ASCQ_PROTO_SERV_CRC_ERR 0x05 | ||
382 | |||
383 | #define SCSI_ASCQ_LUN_TIME_OUT 0x01 | ||
384 | |||
385 | /* ------------------------------------------------------------ | ||
386 | * SCSI INQUIRY | ||
387 | * ------------------------------------------------------------*/ | ||
388 | |||
389 | struct scsi_inquiry_s{ | ||
390 | u8 opcode; | ||
391 | #ifdef __BIGENDIAN | ||
392 | u8 lun:3; | ||
393 | u8 reserved1:3; | ||
394 | u8 cmd_dt:1; | ||
395 | u8 evpd:1; | ||
396 | #else | ||
397 | u8 evpd:1; | ||
398 | u8 cmd_dt:1; | ||
399 | u8 reserved1:3; | ||
400 | u8 lun:3; | ||
401 | #endif | ||
402 | u8 page_code; | ||
403 | u8 reserved2; | ||
404 | u8 alloc_length; | ||
405 | u8 control; | ||
406 | }; | ||
407 | |||
408 | struct scsi_inquiry_vendor_s{ | ||
409 | u8 vendor_id[8]; | ||
410 | }; | ||
411 | |||
412 | struct scsi_inquiry_prodid_s{ | ||
413 | u8 product_id[16]; | ||
414 | }; | ||
415 | |||
416 | struct scsi_inquiry_prodrev_s{ | ||
417 | u8 product_rev[4]; | ||
418 | }; | ||
419 | |||
420 | struct scsi_inquiry_data_s{ | ||
421 | #ifdef __BIGENDIAN | ||
422 | u8 peripheral_qual:3; /* peripheral qualifier */ | ||
423 | u8 device_type:5; /* peripheral device type */ | ||
424 | |||
425 | u8 rmb:1; /* removable medium bit */ | ||
426 | u8 device_type_mod:7; /* device type modifier */ | ||
427 | |||
428 | u8 version; | ||
429 | |||
430 | u8 aenc:1; /* async event notification capability | ||
431 | */ | ||
432 | u8 trm_iop:1; /* terminate I/O process */ | ||
433 | u8 norm_aca:1; /* normal ACA supported */ | ||
434 | u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */ | ||
435 | u8 rsp_data_format:4; | ||
436 | |||
437 | u8 additional_len; | ||
438 | u8 sccs:1; | ||
439 | u8 reserved1:7; | ||
440 | |||
441 | u8 reserved2:1; | ||
442 | u8 enc_serv:1; /* enclosure service component */ | ||
443 | u8 reserved3:1; | ||
444 | u8 multi_port:1; /* multi-port device */ | ||
445 | u8 m_chngr:1; /* device in medium transport element */ | ||
446 | u8 ack_req_q:1; /* SIP specific bit */ | ||
447 | u8 addr32:1; /* SIP specific bit */ | ||
448 | u8 addr16:1; /* SIP specific bit */ | ||
449 | |||
450 | u8 rel_adr:1; /* relative address */ | ||
451 | u8 w_bus32:1; | ||
452 | u8 w_bus16:1; | ||
453 | u8 synchronous:1; | ||
454 | u8 linked_commands:1; | ||
455 | u8 trans_dis:1; | ||
456 | u8 cmd_queue:1; /* command queueing supported */ | ||
457 | u8 soft_reset:1; /* soft reset alternative (VS) */ | ||
458 | #else | ||
459 | u8 device_type:5; /* peripheral device type */ | ||
460 | u8 peripheral_qual:3; | ||
461 | /* peripheral qualifier */ | ||
462 | |||
463 | u8 device_type_mod:7; | ||
464 | /* device type modifier */ | ||
465 | u8 rmb:1; /* removable medium bit */ | ||
466 | |||
467 | u8 version; | ||
468 | |||
469 | u8 rsp_data_format:4; | ||
470 | u8 hi_support:1; /* SCSI-3: supports REPORT LUNS */ | ||
471 | u8 norm_aca:1; /* normal ACA supported */ | ||
472 | u8 terminate_iop:1;/* terminate I/O process */ | ||
473 | u8 aenc:1; /* async event notification capability | ||
474 | */ | ||
475 | |||
476 | u8 additional_len; | ||
477 | u8 reserved1:7; | ||
478 | u8 sccs:1; | ||
479 | |||
480 | u8 addr16:1; /* SIP specific bit */ | ||
481 | u8 addr32:1; /* SIP specific bit */ | ||
482 | u8 ack_req_q:1; /* SIP specific bit */ | ||
483 | u8 m_chngr:1; /* device in medium transport element */ | ||
484 | u8 multi_port:1; /* multi-port device */ | ||
485 | u8 reserved3:1; /* TBD - Vendor Specific */ | ||
486 | u8 enc_serv:1; /* enclosure service component */ | ||
487 | u8 reserved2:1; | ||
488 | |||
489 | u8 soft_seset:1; /* soft reset alternative (VS) */ | ||
490 | u8 cmd_queue:1; /* command queueing supported */ | ||
491 | u8 trans_dis:1; | ||
492 | u8 linked_commands:1; | ||
493 | u8 synchronous:1; | ||
494 | u8 w_bus16:1; | ||
495 | u8 w_bus32:1; | ||
496 | u8 rel_adr:1; /* relative address */ | ||
497 | #endif | ||
498 | struct scsi_inquiry_vendor_s vendor_id; | ||
499 | struct scsi_inquiry_prodid_s product_id; | ||
500 | struct scsi_inquiry_prodrev_s product_rev; | ||
501 | u8 vendor_specific[20]; | ||
502 | u8 reserved4[40]; | ||
503 | }; | ||
504 | |||
505 | /* | ||
506 | * inquiry.peripheral_qual field values | ||
507 | */ | ||
508 | #define SCSI_DEVQUAL_DEFAULT 0 | ||
509 | #define SCSI_DEVQUAL_NOT_CONNECTED 1 | ||
510 | #define SCSI_DEVQUAL_NOT_SUPPORTED 3 | ||
511 | |||
512 | /* | ||
513 | * inquiry.device_type field values | ||
514 | */ | ||
515 | #define SCSI_DEVICE_DIRECT_ACCESS 0x00 | ||
516 | #define SCSI_DEVICE_SEQ_ACCESS 0x01 | ||
517 | #define SCSI_DEVICE_ARRAY_CONTROLLER 0x0C | ||
518 | #define SCSI_DEVICE_UNKNOWN 0x1F | ||
519 | |||
520 | /* | ||
521 | * inquiry.version | ||
522 | */ | ||
523 | #define SCSI_VERSION_ANSI_X3131 2 /* ANSI X3.131 SCSI-2 */ | ||
524 | #define SCSI_VERSION_SPC 3 /* SPC (SCSI-3), ANSI X3.301:1997 */ | ||
525 | #define SCSI_VERSION_SPC_2 4 /* SPC-2 */ | ||
526 | |||
527 | /* | ||
528 | * response data format | ||
529 | */ | ||
530 | #define SCSI_RSP_DATA_FORMAT 2 /* SCSI-2 & SPC */ | ||
531 | |||
532 | /* | ||
533 | * SCSI inquiry page codes | ||
534 | */ | ||
535 | #define SCSI_INQ_PAGE_VPD_PAGES 0x00 /* supported vpd pages */ | ||
536 | #define SCSI_INQ_PAGE_USN_PAGE 0x80 /* unit serial number page */ | ||
537 | #define SCSI_INQ_PAGE_DEV_IDENT 0x83 /* device indentification page | ||
538 | */ | ||
539 | #define SCSI_INQ_PAGES_MAX 3 | ||
540 | |||
541 | /* | ||
542 | * supported vital product data pages | ||
543 | */ | ||
544 | struct scsi_inq_page_vpd_pages_s{ | ||
545 | #ifdef __BIGENDIAN | ||
546 | u8 peripheral_qual:3; | ||
547 | u8 device_type:5; | ||
548 | #else | ||
549 | u8 device_type:5; | ||
550 | u8 peripheral_qual:3; | ||
551 | #endif | ||
552 | u8 page_code; | ||
553 | u8 reserved; | ||
554 | u8 page_length; | ||
555 | u8 pages[SCSI_INQ_PAGES_MAX]; | ||
556 | }; | ||
557 | |||
558 | /* | ||
559 | * Unit serial number page | ||
560 | */ | ||
561 | #define SCSI_INQ_USN_LEN 32 | ||
562 | |||
563 | struct scsi_inq_usn_s{ | ||
564 | char usn[SCSI_INQ_USN_LEN]; | ||
565 | }; | ||
566 | |||
567 | struct scsi_inq_page_usn_s{ | ||
568 | #ifdef __BIGENDIAN | ||
569 | u8 peripheral_qual:3; | ||
570 | u8 device_type:5; | ||
571 | #else | ||
572 | u8 device_type:5; | ||
573 | u8 peripheral_qual:3; | ||
574 | #endif | ||
575 | u8 page_code; | ||
576 | u8 reserved1; | ||
577 | u8 page_length; | ||
578 | struct scsi_inq_usn_s usn; | ||
579 | }; | ||
580 | |||
581 | enum { | ||
582 | SCSI_INQ_DIP_CODE_BINARY = 1, /* identifier has binary value */ | ||
583 | SCSI_INQ_DIP_CODE_ASCII = 2, /* identifier has ascii value */ | ||
584 | }; | ||
585 | |||
586 | enum { | ||
587 | SCSI_INQ_DIP_ASSOC_LUN = 0, /* id is associated with device */ | ||
588 | SCSI_INQ_DIP_ASSOC_PORT = 1, /* id is associated with port that | ||
589 | * received the request | ||
590 | */ | ||
591 | }; | ||
592 | |||
593 | enum { | ||
594 | SCSI_INQ_ID_TYPE_VENDOR = 1, | ||
595 | SCSI_INQ_ID_TYPE_IEEE = 2, | ||
596 | SCSI_INQ_ID_TYPE_FC_FS = 3, | ||
597 | SCSI_INQ_ID_TYPE_OTHER = 4, | ||
598 | }; | ||
599 | |||
600 | struct scsi_inq_dip_desc_s{ | ||
601 | #ifdef __BIGENDIAN | ||
602 | u8 res0:4; | ||
603 | u8 code_set:4; | ||
604 | u8 res1:2; | ||
605 | u8 association:2; | ||
606 | u8 id_type:4; | ||
607 | #else | ||
608 | u8 code_set:4; | ||
609 | u8 res0:4; | ||
610 | u8 id_type:4; | ||
611 | u8 association:2; | ||
612 | u8 res1:2; | ||
613 | #endif | ||
614 | u8 res2; | ||
615 | u8 id_len; | ||
616 | struct scsi_lun_sn_s id; | ||
617 | }; | ||
618 | |||
619 | /* | ||
620 | * Device indentification page | ||
621 | */ | ||
622 | struct scsi_inq_page_dev_ident_s{ | ||
623 | #ifdef __BIGENDIAN | ||
624 | u8 peripheral_qual:3; | ||
625 | u8 device_type:5; | ||
626 | #else | ||
627 | u8 device_type:5; | ||
628 | u8 peripheral_qual:3; | ||
629 | #endif | ||
630 | u8 page_code; | ||
631 | u8 reserved1; | ||
632 | u8 page_length; | ||
633 | struct scsi_inq_dip_desc_s desc; | ||
634 | }; | ||
635 | |||
636 | /* ------------------------------------------------------------ | ||
637 | * READ CAPACITY | ||
638 | * ------------------------------------------------------------ | ||
639 | */ | ||
640 | |||
641 | struct scsi_read_capacity_s{ | ||
642 | u8 opcode; | ||
643 | #ifdef __BIGENDIAN | ||
644 | u8 lun:3; | ||
645 | u8 reserved1:4; | ||
646 | u8 rel_adr:1; | ||
647 | #else | ||
648 | u8 rel_adr:1; | ||
649 | u8 reserved1:4; | ||
650 | u8 lun:3; | ||
651 | #endif | ||
652 | u8 lba0; /* MSB */ | ||
653 | u8 lba1; | ||
654 | u8 lba2; | ||
655 | u8 lba3; /* LSB */ | ||
656 | u8 reserved2; | ||
657 | u8 reserved3; | ||
658 | #ifdef __BIGENDIAN | ||
659 | u8 reserved4:7; | ||
660 | u8 pmi:1; /* partial medium indicator */ | ||
661 | #else | ||
662 | u8 pmi:1; /* partial medium indicator */ | ||
663 | u8 reserved4:7; | ||
664 | #endif | ||
665 | u8 control; | ||
666 | }; | ||
667 | |||
668 | struct scsi_read_capacity_data_s{ | ||
669 | u32 max_lba; /* maximum LBA available */ | ||
670 | u32 block_length; /* in bytes */ | ||
671 | }; | ||
672 | |||
673 | struct scsi_read_capacity16_data_s{ | ||
674 | u64 lba; /* maximum LBA available */ | ||
675 | u32 block_length; /* in bytes */ | ||
676 | #ifdef __BIGENDIAN | ||
677 | u8 reserved1:4, | ||
678 | p_type:3, | ||
679 | prot_en:1; | ||
680 | u8 reserved2:4, | ||
681 | lb_pbe:4; /* logical blocks per physical block | ||
682 | * exponent */ | ||
683 | u16 reserved3:2, | ||
684 | lba_align:14; /* lowest aligned logical block | ||
685 | * address */ | ||
686 | #else | ||
687 | u16 lba_align:14, /* lowest aligned logical block | ||
688 | * address */ | ||
689 | reserved3:2; | ||
690 | u8 lb_pbe:4, /* logical blocks per physical block | ||
691 | * exponent */ | ||
692 | reserved2:4; | ||
693 | u8 prot_en:1, | ||
694 | p_type:3, | ||
695 | reserved1:4; | ||
696 | #endif | ||
697 | u64 reserved4; | ||
698 | u64 reserved5; | ||
699 | }; | ||
700 | |||
701 | /* ------------------------------------------------------------ | ||
702 | * REPORT LUNS command | ||
703 | * ------------------------------------------------------------ | ||
704 | */ | ||
705 | |||
706 | struct scsi_report_luns_s{ | ||
707 | u8 opcode; /* A0h - REPORT LUNS opCode */ | ||
708 | u8 reserved1[5]; | ||
709 | u8 alloc_length[4];/* allocation length MSB first */ | ||
710 | u8 reserved2; | ||
711 | u8 control; | ||
712 | }; | ||
713 | |||
714 | #define SCSI_REPORT_LUN_ALLOC_LENGTH(rl) \ | ||
715 | ((rl->alloc_length[0] << 24) | (rl->alloc_length[1] << 16) | \ | ||
716 | (rl->alloc_length[2] << 8) | (rl->alloc_length[3])) | ||
717 | |||
718 | #define SCSI_REPORT_LUNS_SET_ALLOCLEN(rl, alloc_len) { \ | ||
719 | (rl)->alloc_length[0] = (alloc_len) >> 24; \ | ||
720 | (rl)->alloc_length[1] = ((alloc_len) >> 16) & 0xFF; \ | ||
721 | (rl)->alloc_length[2] = ((alloc_len) >> 8) & 0xFF; \ | ||
722 | (rl)->alloc_length[3] = (alloc_len) & 0xFF; \ | ||
723 | } | ||
724 | |||
725 | struct scsi_report_luns_data_s{ | ||
726 | u32 lun_list_length; /* length of LUN list length */ | ||
727 | u32 reserved; | ||
728 | lun_t lun[1]; /* first LUN in lun list */ | ||
729 | }; | ||
730 | |||
731 | /* ------------------------------------------------------------- | ||
732 | * SCSI mode parameters | ||
733 | * ----------------------------------------------------------- | ||
734 | */ | ||
735 | enum { | ||
736 | SCSI_DA_MEDIUM_DEF = 0, /* direct access default medium type */ | ||
737 | SCSI_DA_MEDIUM_SS = 1, /* direct access single sided */ | ||
738 | SCSI_DA_MEDIUM_DS = 2, /* direct access double sided */ | ||
739 | }; | ||
740 | |||
741 | /* | ||
742 | * SCSI Mode Select(6) cdb | ||
743 | */ | ||
744 | struct scsi_mode_select6_s{ | ||
745 | u8 opcode; | ||
746 | #ifdef __BIGENDIAN | ||
747 | u8 reserved1:3; | ||
748 | u8 pf:1; /* page format */ | ||
749 | u8 reserved2:3; | ||
750 | u8 sp:1; /* save pages if set to 1 */ | ||
751 | #else | ||
752 | u8 sp:1; /* save pages if set to 1 */ | ||
753 | u8 reserved2:3; | ||
754 | u8 pf:1; /* page format */ | ||
755 | u8 reserved1:3; | ||
756 | #endif | ||
757 | u8 reserved3[2]; | ||
758 | u8 alloc_len; | ||
759 | u8 control; | ||
760 | }; | ||
761 | |||
762 | /* | ||
763 | * SCSI Mode Select(10) cdb | ||
764 | */ | ||
765 | struct scsi_mode_select10_s{ | ||
766 | u8 opcode; | ||
767 | #ifdef __BIGENDIAN | ||
768 | u8 reserved1:3; | ||
769 | u8 pf:1; /* page format */ | ||
770 | u8 reserved2:3; | ||
771 | u8 sp:1; /* save pages if set to 1 */ | ||
772 | #else | ||
773 | u8 sp:1; /* save pages if set to 1 */ | ||
774 | u8 reserved2:3; | ||
775 | u8 pf:1; /* page format */ | ||
776 | u8 reserved1:3; | ||
777 | #endif | ||
778 | u8 reserved3[5]; | ||
779 | u8 alloc_len_msb; | ||
780 | u8 alloc_len_lsb; | ||
781 | u8 control; | ||
782 | }; | ||
783 | |||
784 | /* | ||
785 | * SCSI Mode Sense(6) cdb | ||
786 | */ | ||
787 | struct scsi_mode_sense6_s{ | ||
788 | u8 opcode; | ||
789 | #ifdef __BIGENDIAN | ||
790 | u8 reserved1:4; | ||
791 | u8 dbd:1; /* disable block discriptors if set to 1 */ | ||
792 | u8 reserved2:3; | ||
793 | |||
794 | u8 pc:2; /* page control */ | ||
795 | u8 page_code:6; | ||
796 | #else | ||
797 | u8 reserved2:3; | ||
798 | u8 dbd:1; /* disable block descriptors if set to 1 */ | ||
799 | u8 reserved1:4; | ||
800 | |||
801 | u8 page_code:6; | ||
802 | u8 pc:2; /* page control */ | ||
803 | #endif | ||
804 | u8 reserved3; | ||
805 | u8 alloc_len; | ||
806 | u8 control; | ||
807 | }; | ||
808 | |||
809 | /* | ||
810 | * SCSI Mode Sense(10) cdb | ||
811 | */ | ||
812 | struct scsi_mode_sense10_s{ | ||
813 | u8 opcode; | ||
814 | #ifdef __BIGENDIAN | ||
815 | u8 reserved1:3; | ||
816 | u8 LLBAA:1; /* long LBA accepted if set to 1 */ | ||
817 | u8 dbd:1; /* disable block descriptors if set | ||
818 | * to 1 | ||
819 | */ | ||
820 | u8 reserved2:3; | ||
821 | |||
822 | u8 pc:2; /* page control */ | ||
823 | u8 page_code:6; | ||
824 | #else | ||
825 | u8 reserved2:3; | ||
826 | u8 dbd:1; /* disable block descriptors if set to | ||
827 | * 1 | ||
828 | */ | ||
829 | u8 LLBAA:1; /* long LBA accepted if set to 1 */ | ||
830 | u8 reserved1:3; | ||
831 | |||
832 | u8 page_code:6; | ||
833 | u8 pc:2; /* page control */ | ||
834 | #endif | ||
835 | u8 reserved3[4]; | ||
836 | u8 alloc_len_msb; | ||
837 | u8 alloc_len_lsb; | ||
838 | u8 control; | ||
839 | }; | ||
840 | |||
841 | #define SCSI_CDB10_GET_AL(cdb) \ | ||
842 | ((cdb)->alloc_len_msb << 8 | (cdb)->alloc_len_lsb) | ||
843 | |||
844 | #define SCSI_CDB10_SET_AL(cdb, al) { \ | ||
845 | (cdb)->alloc_len_msb = al >> 8; \ | ||
846 | (cdb)->alloc_len_lsb = al & 0xFF; \ | ||
847 | } | ||
848 | |||
849 | #define SCSI_CDB6_GET_AL(cdb) ((cdb)->alloc_len) | ||
850 | |||
851 | #define SCSI_CDB6_SET_AL(cdb, al) { \ | ||
852 | (cdb)->alloc_len = al; \ | ||
853 | } | ||
854 | |||
855 | /* | ||
856 | * page control field values | ||
857 | */ | ||
858 | #define SCSI_PC_CURRENT_VALUES 0x0 | ||
859 | #define SCSI_PC_CHANGEABLE_VALUES 0x1 | ||
860 | #define SCSI_PC_DEFAULT_VALUES 0x2 | ||
861 | #define SCSI_PC_SAVED_VALUES 0x3 | ||
862 | |||
863 | /* | ||
864 | * SCSI mode page codes | ||
865 | */ | ||
866 | #define SCSI_MP_VENDOR_SPEC 0x00 | ||
867 | #define SCSI_MP_DISC_RECN 0x02 /* disconnect-reconnect page */ | ||
868 | #define SCSI_MP_FORMAT_DEVICE 0x03 | ||
869 | #define SCSI_MP_RDG 0x04 /* rigid disk geometry page */ | ||
870 | #define SCSI_MP_FDP 0x05 /* flexible disk page */ | ||
871 | #define SCSI_MP_CACHING 0x08 /* caching page */ | ||
872 | #define SCSI_MP_CONTROL 0x0A /* control mode page */ | ||
873 | #define SCSI_MP_MED_TYPES_SUP 0x0B /* medium types supported page */ | ||
874 | #define SCSI_MP_INFO_EXCP_CNTL 0x1C /* informational exception control */ | ||
875 | #define SCSI_MP_ALL 0x3F /* return all pages - mode sense only */ | ||
876 | |||
877 | /* | ||
878 | * mode parameter header | ||
879 | */ | ||
880 | struct scsi_mode_param_header6_s{ | ||
881 | u8 mode_datalen; | ||
882 | u8 medium_type; | ||
883 | |||
884 | /* | ||
885 | * device specific parameters expanded for direct access devices | ||
886 | */ | ||
887 | #ifdef __BIGENDIAN | ||
888 | u32 wp:1; /* write protected */ | ||
889 | u32 reserved1:2; | ||
890 | u32 dpofua:1; /* disable page out + force unit access | ||
891 | */ | ||
892 | u32 reserved2:4; | ||
893 | #else | ||
894 | u32 reserved2:4; | ||
895 | u32 dpofua:1; /* disable page out + force unit access | ||
896 | */ | ||
897 | u32 reserved1:2; | ||
898 | u32 wp:1; /* write protected */ | ||
899 | #endif | ||
900 | |||
901 | u8 block_desclen; | ||
902 | }; | ||
903 | |||
904 | struct scsi_mode_param_header10_s{ | ||
905 | u32 mode_datalen:16; | ||
906 | u32 medium_type:8; | ||
907 | |||
908 | /* | ||
909 | * device specific parameters expanded for direct access devices | ||
910 | */ | ||
911 | #ifdef __BIGENDIAN | ||
912 | u32 wp:1; /* write protected */ | ||
913 | u32 reserved1:2; | ||
914 | u32 dpofua:1; /* disable page out + force unit access | ||
915 | */ | ||
916 | u32 reserved2:4; | ||
917 | #else | ||
918 | u32 reserved2:4; | ||
919 | u32 dpofua:1; /* disable page out + force unit access | ||
920 | */ | ||
921 | u32 reserved1:2; | ||
922 | u32 wp:1; /* write protected */ | ||
923 | #endif | ||
924 | |||
925 | #ifdef __BIGENDIAN | ||
926 | u32 reserved3:7; | ||
927 | u32 longlba:1; | ||
928 | #else | ||
929 | u32 longlba:1; | ||
930 | u32 reserved3:7; | ||
931 | #endif | ||
932 | u32 reserved4:8; | ||
933 | u32 block_desclen:16; | ||
934 | }; | ||
935 | |||
936 | /* | ||
937 | * mode parameter block descriptor | ||
938 | */ | ||
939 | struct scsi_mode_param_desc_s{ | ||
940 | u32 nblks; | ||
941 | u32 density_code:8; | ||
942 | u32 block_length:24; | ||
943 | }; | ||
944 | |||
945 | /* | ||
946 | * Disconnect-reconnect mode page format | ||
947 | */ | ||
948 | struct scsi_mp_disc_recn_s{ | ||
949 | #ifdef __BIGENDIAN | ||
950 | u8 ps:1; | ||
951 | u8 reserved1:1; | ||
952 | u8 page_code:6; | ||
953 | #else | ||
954 | u8 page_code:6; | ||
955 | u8 reserved1:1; | ||
956 | u8 ps:1; | ||
957 | #endif | ||
958 | u8 page_len; | ||
959 | u8 buf_full_ratio; | ||
960 | u8 buf_empty_ratio; | ||
961 | |||
962 | u8 bil_msb; /* bus inactivity limit -MSB */ | ||
963 | u8 bil_lsb; /* bus inactivity limit -LSB */ | ||
964 | |||
965 | u8 dtl_msb; /* disconnect time limit - MSB */ | ||
966 | u8 dtl_lsb; /* disconnect time limit - LSB */ | ||
967 | |||
968 | u8 ctl_msb; /* connect time limit - MSB */ | ||
969 | u8 ctl_lsb; /* connect time limit - LSB */ | ||
970 | |||
971 | u8 max_burst_len_msb; | ||
972 | u8 max_burst_len_lsb; | ||
973 | #ifdef __BIGENDIAN | ||
974 | u8 emdp:1; /* enable modify data pointers */ | ||
975 | u8 fa:3; /* fair arbitration */ | ||
976 | u8 dimm:1; /* disconnect immediate */ | ||
977 | u8 dtdc:3; /* data transfer disconnect control */ | ||
978 | #else | ||
979 | u8 dtdc:3; /* data transfer disconnect control */ | ||
980 | u8 dimm:1; /* disconnect immediate */ | ||
981 | u8 fa:3; /* fair arbitration */ | ||
982 | u8 emdp:1; /* enable modify data pointers */ | ||
983 | #endif | ||
984 | |||
985 | u8 reserved3; | ||
986 | |||
987 | u8 first_burst_len_msb; | ||
988 | u8 first_burst_len_lsb; | ||
989 | }; | ||
990 | |||
991 | /* | ||
992 | * SCSI format device mode page | ||
993 | */ | ||
994 | struct scsi_mp_format_device_s{ | ||
995 | #ifdef __BIGENDIAN | ||
996 | u32 ps:1; | ||
997 | u32 reserved1:1; | ||
998 | u32 page_code:6; | ||
999 | #else | ||
1000 | u32 page_code:6; | ||
1001 | u32 reserved1:1; | ||
1002 | u32 ps:1; | ||
1003 | #endif | ||
1004 | u32 page_len:8; | ||
1005 | u32 tracks_per_zone:16; | ||
1006 | |||
1007 | u32 a_sec_per_zone:16; | ||
1008 | u32 a_tracks_per_zone:16; | ||
1009 | |||
1010 | u32 a_tracks_per_lun:16; /* alternate tracks/lun-MSB */ | ||
1011 | u32 sec_per_track:16; /* sectors/track-MSB */ | ||
1012 | |||
1013 | u32 bytes_per_sector:16; | ||
1014 | u32 interleave:16; | ||
1015 | |||
1016 | u32 tsf:16; /* track skew factor-MSB */ | ||
1017 | u32 csf:16; /* cylinder skew factor-MSB */ | ||
1018 | |||
1019 | #ifdef __BIGENDIAN | ||
1020 | u32 ssec:1; /* soft sector formatting */ | ||
1021 | u32 hsec:1; /* hard sector formatting */ | ||
1022 | u32 rmb:1; /* removable media */ | ||
1023 | u32 surf:1; /* surface */ | ||
1024 | u32 reserved2:4; | ||
1025 | #else | ||
1026 | u32 reserved2:4; | ||
1027 | u32 surf:1; /* surface */ | ||
1028 | u32 rmb:1; /* removable media */ | ||
1029 | u32 hsec:1; /* hard sector formatting */ | ||
1030 | u32 ssec:1; /* soft sector formatting */ | ||
1031 | #endif | ||
1032 | u32 reserved3:24; | ||
1033 | }; | ||
1034 | |||
1035 | /* | ||
1036 | * SCSI rigid disk device geometry page | ||
1037 | */ | ||
1038 | struct scsi_mp_rigid_device_geometry_s{ | ||
1039 | #ifdef __BIGENDIAN | ||
1040 | u32 ps:1; | ||
1041 | u32 reserved1:1; | ||
1042 | u32 page_code:6; | ||
1043 | #else | ||
1044 | u32 page_code:6; | ||
1045 | u32 reserved1:1; | ||
1046 | u32 ps:1; | ||
1047 | #endif | ||
1048 | u32 page_len:8; | ||
1049 | u32 num_cylinders0:8; | ||
1050 | u32 num_cylinders1:8; | ||
1051 | |||
1052 | u32 num_cylinders2:8; | ||
1053 | u32 num_heads:8; | ||
1054 | u32 scwp0:8; | ||
1055 | u32 scwp1:8; | ||
1056 | |||
1057 | u32 scwp2:8; | ||
1058 | u32 scrwc0:8; | ||
1059 | u32 scrwc1:8; | ||
1060 | u32 scrwc2:8; | ||
1061 | |||
1062 | u32 dsr:16; | ||
1063 | u32 lscyl0:8; | ||
1064 | u32 lscyl1:8; | ||
1065 | |||
1066 | u32 lscyl2:8; | ||
1067 | #ifdef __BIGENDIAN | ||
1068 | u32 reserved2:6; | ||
1069 | u32 rpl:2; /* rotational position locking */ | ||
1070 | #else | ||
1071 | u32 rpl:2; /* rotational position locking */ | ||
1072 | u32 reserved2:6; | ||
1073 | #endif | ||
1074 | u32 rot_off:8; | ||
1075 | u32 reserved3:8; | ||
1076 | |||
1077 | u32 med_rot_rate:16; | ||
1078 | u32 reserved4:16; | ||
1079 | }; | ||
1080 | |||
1081 | /* | ||
1082 | * SCSI caching mode page | ||
1083 | */ | ||
1084 | struct scsi_mp_caching_s{ | ||
1085 | #ifdef __BIGENDIAN | ||
1086 | u8 ps:1; | ||
1087 | u8 res1:1; | ||
1088 | u8 page_code:6; | ||
1089 | #else | ||
1090 | u8 page_code:6; | ||
1091 | u8 res1:1; | ||
1092 | u8 ps:1; | ||
1093 | #endif | ||
1094 | u8 page_len; | ||
1095 | #ifdef __BIGENDIAN | ||
1096 | u8 ic:1; /* initiator control */ | ||
1097 | u8 abpf:1; /* abort pre-fetch */ | ||
1098 | u8 cap:1; /* caching analysis permitted */ | ||
1099 | u8 disc:1; /* discontinuity */ | ||
1100 | u8 size:1; /* size enable */ | ||
1101 | u8 wce:1; /* write cache enable */ | ||
1102 | u8 mf:1; /* multiplication factor */ | ||
1103 | u8 rcd:1; /* read cache disable */ | ||
1104 | |||
1105 | u8 drrp:4; /* demand read retention priority */ | ||
1106 | u8 wrp:4; /* write retention priority */ | ||
1107 | #else | ||
1108 | u8 rcd:1; /* read cache disable */ | ||
1109 | u8 mf:1; /* multiplication factor */ | ||
1110 | u8 wce:1; /* write cache enable */ | ||
1111 | u8 size:1; /* size enable */ | ||
1112 | u8 disc:1; /* discontinuity */ | ||
1113 | u8 cap:1; /* caching analysis permitted */ | ||
1114 | u8 abpf:1; /* abort pre-fetch */ | ||
1115 | u8 ic:1; /* initiator control */ | ||
1116 | |||
1117 | u8 wrp:4; /* write retention priority */ | ||
1118 | u8 drrp:4; /* demand read retention priority */ | ||
1119 | #endif | ||
1120 | u8 dptl[2];/* disable pre-fetch transfer length */ | ||
1121 | u8 min_prefetch[2]; | ||
1122 | u8 max_prefetch[2]; | ||
1123 | u8 max_prefetch_limit[2]; | ||
1124 | #ifdef __BIGENDIAN | ||
1125 | u8 fsw:1; /* force sequential write */ | ||
1126 | u8 lbcss:1;/* logical block cache segment size */ | ||
1127 | u8 dra:1; /* disable read ahead */ | ||
1128 | u8 vs:2; /* vendor specific */ | ||
1129 | u8 res2:3; | ||
1130 | #else | ||
1131 | u8 res2:3; | ||
1132 | u8 vs:2; /* vendor specific */ | ||
1133 | u8 dra:1; /* disable read ahead */ | ||
1134 | u8 lbcss:1;/* logical block cache segment size */ | ||
1135 | u8 fsw:1; /* force sequential write */ | ||
1136 | #endif | ||
1137 | u8 num_cache_segs; | ||
1138 | |||
1139 | u8 cache_seg_size[2]; | ||
1140 | u8 res3; | ||
1141 | u8 non_cache_seg_size[3]; | ||
1142 | }; | ||
1143 | |||
1144 | /* | ||
1145 | * SCSI control mode page | ||
1146 | */ | ||
1147 | struct scsi_mp_control_page_s{ | ||
1148 | #ifdef __BIGENDIAN | ||
1149 | u8 ps:1; | ||
1150 | u8 reserved1:1; | ||
1151 | u8 page_code:6; | ||
1152 | #else | ||
1153 | u8 page_code:6; | ||
1154 | u8 reserved1:1; | ||
1155 | u8 ps:1; | ||
1156 | #endif | ||
1157 | u8 page_len; | ||
1158 | #ifdef __BIGENDIAN | ||
1159 | u8 tst:3; /* task set type */ | ||
1160 | u8 reserved3:3; | ||
1161 | u8 gltsd:1; /* global logging target save disable */ | ||
1162 | u8 rlec:1; /* report log exception condition */ | ||
1163 | |||
1164 | u8 qalgo_mod:4; /* queue alogorithm modifier */ | ||
1165 | u8 reserved4:1; | ||
1166 | u8 qerr:2; /* queue error management */ | ||
1167 | u8 dque:1; /* disable queuing */ | ||
1168 | |||
1169 | u8 reserved5:1; | ||
1170 | u8 rac:1; /* report a check */ | ||
1171 | u8 reserved6:2; | ||
1172 | u8 swp:1; /* software write protect */ | ||
1173 | u8 raerp:1; /* ready AER permission */ | ||
1174 | u8 uaaerp:1; /* unit attenstion AER permission */ | ||
1175 | u8 eaerp:1; /* error AER permission */ | ||
1176 | |||
1177 | u8 reserved7:5; | ||
1178 | u8 autoload_mod:3; | ||
1179 | #else | ||
1180 | u8 rlec:1; /* report log exception condition */ | ||
1181 | u8 gltsd:1; /* global logging target save disable */ | ||
1182 | u8 reserved3:3; | ||
1183 | u8 tst:3; /* task set type */ | ||
1184 | |||
1185 | u8 dque:1; /* disable queuing */ | ||
1186 | u8 qerr:2; /* queue error management */ | ||
1187 | u8 reserved4:1; | ||
1188 | u8 qalgo_mod:4; /* queue alogorithm modifier */ | ||
1189 | |||
1190 | u8 eaerp:1; /* error AER permission */ | ||
1191 | u8 uaaerp:1; /* unit attenstion AER permission */ | ||
1192 | u8 raerp:1; /* ready AER permission */ | ||
1193 | u8 swp:1; /* software write protect */ | ||
1194 | u8 reserved6:2; | ||
1195 | u8 rac:1; /* report a check */ | ||
1196 | u8 reserved5:1; | ||
1197 | |||
1198 | u8 autoload_mod:3; | ||
1199 | u8 reserved7:5; | ||
1200 | #endif | ||
1201 | u8 rahp_msb; /* ready AER holdoff period - MSB */ | ||
1202 | u8 rahp_lsb; /* ready AER holdoff period - LSB */ | ||
1203 | |||
1204 | u8 busy_timeout_period_msb; | ||
1205 | u8 busy_timeout_period_lsb; | ||
1206 | |||
1207 | u8 ext_selftest_compl_time_msb; | ||
1208 | u8 ext_selftest_compl_time_lsb; | ||
1209 | }; | ||
1210 | |||
1211 | /* | ||
1212 | * SCSI medium types supported mode page | ||
1213 | */ | ||
1214 | struct scsi_mp_medium_types_sup_s{ | ||
1215 | #ifdef __BIGENDIAN | ||
1216 | u8 ps:1; | ||
1217 | u8 reserved1:1; | ||
1218 | u8 page_code:6; | ||
1219 | #else | ||
1220 | u8 page_code:6; | ||
1221 | u8 reserved1:1; | ||
1222 | u8 ps:1; | ||
1223 | #endif | ||
1224 | u8 page_len; | ||
1225 | |||
1226 | u8 reserved3[2]; | ||
1227 | u8 med_type1_sup; /* medium type one supported */ | ||
1228 | u8 med_type2_sup; /* medium type two supported */ | ||
1229 | u8 med_type3_sup; /* medium type three supported */ | ||
1230 | u8 med_type4_sup; /* medium type four supported */ | ||
1231 | }; | ||
1232 | |||
1233 | /* | ||
1234 | * SCSI informational exception control mode page | ||
1235 | */ | ||
1236 | struct scsi_mp_info_excpt_cntl_s{ | ||
1237 | #ifdef __BIGENDIAN | ||
1238 | u8 ps:1; | ||
1239 | u8 reserved1:1; | ||
1240 | u8 page_code:6; | ||
1241 | #else | ||
1242 | u8 page_code:6; | ||
1243 | u8 reserved1:1; | ||
1244 | u8 ps:1; | ||
1245 | #endif | ||
1246 | u8 page_len; | ||
1247 | #ifdef __BIGENDIAN | ||
1248 | u8 perf:1; /* performance */ | ||
1249 | u8 reserved3:1; | ||
1250 | u8 ebf:1; /* enable background fucntion */ | ||
1251 | u8 ewasc:1; /* enable warning */ | ||
1252 | u8 dexcpt:1; /* disable exception control */ | ||
1253 | u8 test:1; /* enable test device failure | ||
1254 | * notification | ||
1255 | */ | ||
1256 | u8 reserved4:1; | ||
1257 | u8 log_error:1; | ||
1258 | |||
1259 | u8 reserved5:4; | ||
1260 | u8 mrie:4; /* method of reporting info | ||
1261 | * exceptions | ||
1262 | */ | ||
1263 | #else | ||
1264 | u8 log_error:1; | ||
1265 | u8 reserved4:1; | ||
1266 | u8 test:1; /* enable test device failure | ||
1267 | * notification | ||
1268 | */ | ||
1269 | u8 dexcpt:1; /* disable exception control */ | ||
1270 | u8 ewasc:1; /* enable warning */ | ||
1271 | u8 ebf:1; /* enable background fucntion */ | ||
1272 | u8 reserved3:1; | ||
1273 | u8 perf:1; /* performance */ | ||
1274 | |||
1275 | u8 mrie:4; /* method of reporting info | ||
1276 | * exceptions | ||
1277 | */ | ||
1278 | u8 reserved5:4; | ||
1279 | #endif | ||
1280 | u8 interval_timer_msb; | ||
1281 | u8 interval_timer_lsb; | ||
1282 | |||
1283 | u8 report_count_msb; | ||
1284 | u8 report_count_lsb; | ||
1285 | }; | ||
1286 | |||
1287 | /* | ||
1288 | * Methods of reporting informational exceptions | ||
1289 | */ | ||
1290 | #define SCSI_MP_IEC_NO_REPORT 0x0 /* no reporting of exceptions */ | ||
1291 | #define SCSI_MP_IEC_AER 0x1 /* async event reporting */ | ||
1292 | #define SCSI_MP_IEC_UNIT_ATTN 0x2 /* generate unit attenstion */ | ||
1293 | #define SCSI_MO_IEC_COND_REC_ERR 0x3 /* conditionally generate recovered | ||
1294 | * error | ||
1295 | */ | ||
1296 | #define SCSI_MP_IEC_UNCOND_REC_ERR 0x4 /* unconditionally generate recovered | ||
1297 | * error | ||
1298 | */ | ||
1299 | #define SCSI_MP_IEC_NO_SENSE 0x5 /* generate no sense */ | ||
1300 | #define SCSI_MP_IEC_ON_REQUEST 0x6 /* only report exceptions on request */ | ||
1301 | |||
1302 | /* | ||
1303 | * SCSI flexible disk page | ||
1304 | */ | ||
1305 | struct scsi_mp_flexible_disk_s{ | ||
1306 | #ifdef __BIGENDIAN | ||
1307 | u8 ps:1; | ||
1308 | u8 reserved1:1; | ||
1309 | u8 page_code:6; | ||
1310 | #else | ||
1311 | u8 page_code:6; | ||
1312 | u8 reserved1:1; | ||
1313 | u8 ps:1; | ||
1314 | #endif | ||
1315 | u8 page_len; | ||
1316 | |||
1317 | u8 transfer_rate_msb; | ||
1318 | u8 transfer_rate_lsb; | ||
1319 | |||
1320 | u8 num_heads; | ||
1321 | u8 num_sectors; | ||
1322 | |||
1323 | u8 bytes_per_sector_msb; | ||
1324 | u8 bytes_per_sector_lsb; | ||
1325 | |||
1326 | u8 num_cylinders_msb; | ||
1327 | u8 num_cylinders_lsb; | ||
1328 | |||
1329 | u8 sc_wpc_msb; /* starting cylinder-write | ||
1330 | * precompensation msb | ||
1331 | */ | ||
1332 | u8 sc_wpc_lsb; /* starting cylinder-write | ||
1333 | * precompensation lsb | ||
1334 | */ | ||
1335 | u8 sc_rwc_msb; /* starting cylinder-reduced write | ||
1336 | * current msb | ||
1337 | */ | ||
1338 | u8 sc_rwc_lsb; /* starting cylinder-reduced write | ||
1339 | * current lsb | ||
1340 | */ | ||
1341 | |||
1342 | u8 dev_step_rate_msb; | ||
1343 | u8 dev_step_rate_lsb; | ||
1344 | |||
1345 | u8 dev_step_pulse_width; | ||
1346 | |||
1347 | u8 head_sd_msb; /* head settle delay msb */ | ||
1348 | u8 head_sd_lsb; /* head settle delay lsb */ | ||
1349 | |||
1350 | u8 motor_on_delay; | ||
1351 | u8 motor_off_delay; | ||
1352 | #ifdef __BIGENDIAN | ||
1353 | u8 trdy:1; /* true ready bit */ | ||
1354 | u8 ssn:1; /* start sector number bit */ | ||
1355 | u8 mo:1; /* motor on bit */ | ||
1356 | u8 reserved3:5; | ||
1357 | |||
1358 | u8 reserved4:4; | ||
1359 | u8 spc:4; /* step pulse per cylinder */ | ||
1360 | #else | ||
1361 | u8 reserved3:5; | ||
1362 | u8 mo:1; /* motor on bit */ | ||
1363 | u8 ssn:1; /* start sector number bit */ | ||
1364 | u8 trdy:1; /* true ready bit */ | ||
1365 | |||
1366 | u8 spc:4; /* step pulse per cylinder */ | ||
1367 | u8 reserved4:4; | ||
1368 | #endif | ||
1369 | u8 write_comp; | ||
1370 | u8 head_load_delay; | ||
1371 | u8 head_unload_delay; | ||
1372 | #ifdef __BIGENDIAN | ||
1373 | u8 pin34:4; /* pin34 usage */ | ||
1374 | u8 pin2:4; /* pin2 usage */ | ||
1375 | |||
1376 | u8 pin4:4; /* pin4 usage */ | ||
1377 | u8 pin1:4; /* pin1 usage */ | ||
1378 | #else | ||
1379 | u8 pin2:4; /* pin2 usage */ | ||
1380 | u8 pin34:4; /* pin34 usage */ | ||
1381 | |||
1382 | u8 pin1:4; /* pin1 usage */ | ||
1383 | u8 pin4:4; /* pin4 usage */ | ||
1384 | #endif | ||
1385 | u8 med_rot_rate_msb; | ||
1386 | u8 med_rot_rate_lsb; | ||
1387 | |||
1388 | u8 reserved5[2]; | ||
1389 | }; | ||
1390 | |||
1391 | struct scsi_mode_page_format_data6_s{ | ||
1392 | struct scsi_mode_param_header6_s mph; /* mode page header */ | ||
1393 | struct scsi_mode_param_desc_s desc; /* block descriptor */ | ||
1394 | struct scsi_mp_format_device_s format; /* format device data */ | ||
1395 | }; | ||
1396 | |||
1397 | struct scsi_mode_page_format_data10_s{ | ||
1398 | struct scsi_mode_param_header10_s mph; /* mode page header */ | ||
1399 | struct scsi_mode_param_desc_s desc; /* block descriptor */ | ||
1400 | struct scsi_mp_format_device_s format; /* format device data */ | ||
1401 | }; | ||
1402 | |||
1403 | struct scsi_mode_page_rdg_data6_s{ | ||
1404 | struct scsi_mode_param_header6_s mph; /* mode page header */ | ||
1405 | struct scsi_mode_param_desc_s desc; /* block descriptor */ | ||
1406 | struct scsi_mp_rigid_device_geometry_s rdg; | ||
1407 | /* rigid geometry data */ | ||
1408 | }; | ||
1409 | |||
1410 | struct scsi_mode_page_rdg_data10_s{ | ||
1411 | struct scsi_mode_param_header10_s mph; /* mode page header */ | ||
1412 | struct scsi_mode_param_desc_s desc; /* block descriptor */ | ||
1413 | struct scsi_mp_rigid_device_geometry_s rdg; | ||
1414 | /* rigid geometry data */ | ||
1415 | }; | ||
1416 | |||
1417 | struct scsi_mode_page_cache6_s{ | ||
1418 | struct scsi_mode_param_header6_s mph; /* mode page header */ | ||
1419 | struct scsi_mode_param_desc_s desc; /* block descriptor */ | ||
1420 | struct scsi_mp_caching_s cache; /* cache page data */ | ||
1421 | }; | ||
1422 | |||
1423 | struct scsi_mode_page_cache10_s{ | ||
1424 | struct scsi_mode_param_header10_s mph; /* mode page header */ | ||
1425 | struct scsi_mode_param_desc_s desc; /* block descriptor */ | ||
1426 | struct scsi_mp_caching_s cache; /* cache page data */ | ||
1427 | }; | ||
1428 | |||
1429 | /* -------------------------------------------------------------- | ||
1430 | * Format Unit command | ||
1431 | * ------------------------------------------------------------ | ||
1432 | */ | ||
1433 | |||
1434 | /* | ||
1435 | * Format Unit CDB | ||
1436 | */ | ||
1437 | struct scsi_format_unit_s{ | ||
1438 | u8 opcode; | ||
1439 | #ifdef __BIGENDIAN | ||
1440 | u8 res1:3; | ||
1441 | u8 fmtdata:1; /* if set, data out phase has format | ||
1442 | * data | ||
1443 | */ | ||
1444 | u8 cmplst:1; /* if set, defect list is complete */ | ||
1445 | u8 def_list:3; /* format of defect descriptor is | ||
1446 | * fmtdata =1 | ||
1447 | */ | ||
1448 | #else | ||
1449 | u8 def_list:3; /* format of defect descriptor is | ||
1450 | * fmtdata = 1 | ||
1451 | */ | ||
1452 | u8 cmplst:1; /* if set, defect list is complete */ | ||
1453 | u8 fmtdata:1; /* if set, data out phase has format | ||
1454 | * data | ||
1455 | */ | ||
1456 | u8 res1:3; | ||
1457 | #endif | ||
1458 | u8 interleave_msb; | ||
1459 | u8 interleave_lsb; | ||
1460 | u8 vendor_spec; | ||
1461 | u8 control; | ||
1462 | }; | ||
1463 | |||
1464 | /* | ||
1465 | * h | ||
1466 | */ | ||
1467 | struct scsi_reserve6_s{ | ||
1468 | u8 opcode; | ||
1469 | #ifdef __BIGENDIAN | ||
1470 | u8 reserved:3; | ||
1471 | u8 obsolete:4; | ||
1472 | u8 extent:1; | ||
1473 | #else | ||
1474 | u8 extent:1; | ||
1475 | u8 obsolete:4; | ||
1476 | u8 reserved:3; | ||
1477 | #endif | ||
1478 | u8 reservation_id; | ||
1479 | u16 param_list_len; | ||
1480 | u8 control; | ||
1481 | }; | ||
1482 | |||
1483 | /* | ||
1484 | * h | ||
1485 | */ | ||
1486 | struct scsi_release6_s{ | ||
1487 | u8 opcode; | ||
1488 | #ifdef __BIGENDIAN | ||
1489 | u8 reserved1:3; | ||
1490 | u8 obsolete:4; | ||
1491 | u8 extent:1; | ||
1492 | #else | ||
1493 | u8 extent:1; | ||
1494 | u8 obsolete:4; | ||
1495 | u8 reserved1:3; | ||
1496 | #endif | ||
1497 | u8 reservation_id; | ||
1498 | u16 reserved2; | ||
1499 | u8 control; | ||
1500 | }; | ||
1501 | |||
1502 | /* | ||
1503 | * h | ||
1504 | */ | ||
1505 | struct scsi_reserve10_s{ | ||
1506 | u8 opcode; | ||
1507 | #ifdef __BIGENDIAN | ||
1508 | u8 reserved1:3; | ||
1509 | u8 third_party:1; | ||
1510 | u8 reserved2:2; | ||
1511 | u8 long_id:1; | ||
1512 | u8 extent:1; | ||
1513 | #else | ||
1514 | u8 extent:1; | ||
1515 | u8 long_id:1; | ||
1516 | u8 reserved2:2; | ||
1517 | u8 third_party:1; | ||
1518 | u8 reserved1:3; | ||
1519 | #endif | ||
1520 | u8 reservation_id; | ||
1521 | u8 third_pty_dev_id; | ||
1522 | u8 reserved3; | ||
1523 | u8 reserved4; | ||
1524 | u8 reserved5; | ||
1525 | u16 param_list_len; | ||
1526 | u8 control; | ||
1527 | }; | ||
1528 | |||
1529 | struct scsi_release10_s{ | ||
1530 | u8 opcode; | ||
1531 | #ifdef __BIGENDIAN | ||
1532 | u8 reserved1:3; | ||
1533 | u8 third_party:1; | ||
1534 | u8 reserved2:2; | ||
1535 | u8 long_id:1; | ||
1536 | u8 extent:1; | ||
1537 | #else | ||
1538 | u8 extent:1; | ||
1539 | u8 long_id:1; | ||
1540 | u8 reserved2:2; | ||
1541 | u8 third_party:1; | ||
1542 | u8 reserved1:3; | ||
1543 | #endif | ||
1544 | u8 reservation_id; | ||
1545 | u8 third_pty_dev_id; | ||
1546 | u8 reserved3; | ||
1547 | u8 reserved4; | ||
1548 | u8 reserved5; | ||
1549 | u16 param_list_len; | ||
1550 | u8 control; | ||
1551 | }; | ||
1552 | |||
1553 | struct scsi_verify10_s{ | ||
1554 | u8 opcode; | ||
1555 | #ifdef __BIGENDIAN | ||
1556 | u8 lun:3; | ||
1557 | u8 dpo:1; | ||
1558 | u8 reserved:2; | ||
1559 | u8 bytchk:1; | ||
1560 | u8 reladdr:1; | ||
1561 | #else | ||
1562 | u8 reladdr:1; | ||
1563 | u8 bytchk:1; | ||
1564 | u8 reserved:2; | ||
1565 | u8 dpo:1; | ||
1566 | u8 lun:3; | ||
1567 | #endif | ||
1568 | u8 lba0; | ||
1569 | u8 lba1; | ||
1570 | u8 lba2; | ||
1571 | u8 lba3; | ||
1572 | u8 reserved1; | ||
1573 | u8 verification_len0; | ||
1574 | u8 verification_len1; | ||
1575 | u8 control_byte; | ||
1576 | }; | ||
1577 | |||
1578 | struct scsi_request_sense_s{ | ||
1579 | u8 opcode; | ||
1580 | #ifdef __BIGENDIAN | ||
1581 | u8 lun:3; | ||
1582 | u8 reserved:5; | ||
1583 | #else | ||
1584 | u8 reserved:5; | ||
1585 | u8 lun:3; | ||
1586 | #endif | ||
1587 | u8 reserved0; | ||
1588 | u8 reserved1; | ||
1589 | u8 alloc_len; | ||
1590 | u8 control_byte; | ||
1591 | }; | ||
1592 | |||
1593 | /* ------------------------------------------------------------ | ||
1594 | * SCSI status byte values | ||
1595 | * ------------------------------------------------------------ | ||
1596 | */ | ||
1597 | #define SCSI_STATUS_GOOD 0x00 | ||
1598 | #define SCSI_STATUS_CHECK_CONDITION 0x02 | ||
1599 | #define SCSI_STATUS_CONDITION_MET 0x04 | ||
1600 | #define SCSI_STATUS_BUSY 0x08 | ||
1601 | #define SCSI_STATUS_INTERMEDIATE 0x10 | ||
1602 | #define SCSI_STATUS_ICM 0x14 /* intermediate condition met */ | ||
1603 | #define SCSI_STATUS_RESERVATION_CONFLICT 0x18 | ||
1604 | #define SCSI_STATUS_COMMAND_TERMINATED 0x22 | ||
1605 | #define SCSI_STATUS_QUEUE_FULL 0x28 | ||
1606 | #define SCSI_STATUS_ACA_ACTIVE 0x30 | ||
1607 | |||
1608 | #define SCSI_MAX_ALLOC_LEN 0xFF /* maximum allocarion length | ||
1609 | * in CDBs | ||
1610 | */ | ||
1611 | |||
1612 | #define SCSI_OP_WRITE_VERIFY10 0x2E | ||
1613 | #define SCSI_OP_WRITE_VERIFY12 0xAE | ||
1614 | #define SCSI_OP_UNDEF 0xFF | ||
1615 | |||
1616 | /* | ||
1617 | * SCSI WRITE-VERIFY(10) command | ||
1618 | */ | ||
1619 | struct scsi_write_verify10_s{ | ||
1620 | u8 opcode; | ||
1621 | #ifdef __BIGENDIAN | ||
1622 | u8 reserved1:3; | ||
1623 | u8 dpo:1; /* Disable Page Out */ | ||
1624 | u8 reserved2:1; | ||
1625 | u8 ebp:1; /* erse by-pass */ | ||
1626 | u8 bytchk:1; /* byte check */ | ||
1627 | u8 rel_adr:1; /* relative address */ | ||
1628 | #else | ||
1629 | u8 rel_adr:1; /* relative address */ | ||
1630 | u8 bytchk:1; /* byte check */ | ||
1631 | u8 ebp:1; /* erse by-pass */ | ||
1632 | u8 reserved2:1; | ||
1633 | u8 dpo:1; /* Disable Page Out */ | ||
1634 | u8 reserved1:3; | ||
1635 | #endif | ||
1636 | u8 lba0; /* logical block address - MSB */ | ||
1637 | u8 lba1; | ||
1638 | u8 lba2; | ||
1639 | u8 lba3; /* LSB */ | ||
1640 | u8 reserved3; | ||
1641 | u8 xfer_length0; /* transfer length in blocks - MSB */ | ||
1642 | u8 xfer_length1; /* LSB */ | ||
1643 | u8 control; | ||
1644 | }; | ||
1645 | |||
1646 | #pragma pack() | ||
1647 | |||
1648 | #endif /* __SCSI_H__ */ | ||
diff --git a/drivers/scsi/bfa/include/protocol/types.h b/drivers/scsi/bfa/include/protocol/types.h new file mode 100644 index 000000000000..2875a6cced3b --- /dev/null +++ b/drivers/scsi/bfa/include/protocol/types.h | |||
@@ -0,0 +1,42 @@ | |||
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 | * types.h Protocol defined base types | ||
20 | */ | ||
21 | |||
22 | #ifndef __TYPES_H__ | ||
23 | #define __TYPES_H__ | ||
24 | |||
25 | #include <bfa_os_inc.h> | ||
26 | |||
27 | #define wwn_t u64 | ||
28 | #define lun_t u64 | ||
29 | |||
30 | #define WWN_NULL (0) | ||
31 | #define FC_SYMNAME_MAX 256 /* max name server symbolic name size */ | ||
32 | #define FC_ALPA_MAX 128 | ||
33 | |||
34 | #pragma pack(1) | ||
35 | |||
36 | #define MAC_ADDRLEN (6) | ||
37 | struct mac_s { u8 mac[MAC_ADDRLEN]; }; | ||
38 | #define mac_t struct mac_s | ||
39 | |||
40 | #pragma pack() | ||
41 | |||
42 | #endif | ||
diff --git a/drivers/scsi/bfa/loop.c b/drivers/scsi/bfa/loop.c new file mode 100644 index 000000000000..a418dedebe9e --- /dev/null +++ b/drivers/scsi/bfa/loop.c | |||
@@ -0,0 +1,422 @@ | |||
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_loop.c vport private loop implementation. | ||
20 | */ | ||
21 | #include <bfa.h> | ||
22 | #include <bfa_svc.h> | ||
23 | #include "fcs_lport.h" | ||
24 | #include "fcs_rport.h" | ||
25 | #include "fcs_trcmod.h" | ||
26 | #include "lport_priv.h" | ||
27 | |||
28 | BFA_TRC_FILE(FCS, LOOP); | ||
29 | |||
30 | /** | ||
31 | * ALPA to LIXA bitmap mapping | ||
32 | * | ||
33 | * ALPA 0x00 (Word 0, Bit 30) is invalid for N_Ports. Also Word 0 Bit 31 | ||
34 | * is for L_bit (login required) and is filled as ALPA 0x00 here. | ||
35 | */ | ||
36 | static const u8 port_loop_alpa_map[] = { | ||
37 | 0xEF, 0xE8, 0xE4, 0xE2, 0xE1, 0xE0, 0xDC, 0xDA, /* Word 3 Bits 0..7 */ | ||
38 | 0xD9, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xCE, /* Word 3 Bits 8..15 */ | ||
39 | 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC7, 0xC6, 0xC5, /* Word 3 Bits 16..23 */ | ||
40 | 0xC3, 0xBC, 0xBA, 0xB9, 0xB6, 0xB5, 0xB4, 0xB3, /* Word 3 Bits 24..31 */ | ||
41 | |||
42 | 0xB2, 0xB1, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, /* Word 2 Bits 0..7 */ | ||
43 | 0xA7, 0xA6, 0xA5, 0xA3, 0x9F, 0x9E, 0x9D, 0x9B, /* Word 2 Bits 8..15 */ | ||
44 | 0x98, 0x97, 0x90, 0x8F, 0x88, 0x84, 0x82, 0x81, /* Word 2 Bits 16..23 */ | ||
45 | 0x80, 0x7C, 0x7A, 0x79, 0x76, 0x75, 0x74, 0x73, /* Word 2 Bits 24..31 */ | ||
46 | |||
47 | 0x72, 0x71, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, /* Word 1 Bits 0..7 */ | ||
48 | 0x67, 0x66, 0x65, 0x63, 0x5C, 0x5A, 0x59, 0x56, /* Word 1 Bits 8..15 */ | ||
49 | 0x55, 0x54, 0x53, 0x52, 0x51, 0x4E, 0x4D, 0x4C, /* Word 1 Bits 16..23 */ | ||
50 | 0x4B, 0x4A, 0x49, 0x47, 0x46, 0x45, 0x43, 0x3C, /* Word 1 Bits 24..31 */ | ||
51 | |||
52 | 0x3A, 0x39, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, /* Word 0 Bits 0..7 */ | ||
53 | 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x27, 0x26, /* Word 0 Bits 8..15 */ | ||
54 | 0x25, 0x23, 0x1F, 0x1E, 0x1D, 0x1B, 0x18, 0x17, /* Word 0 Bits 16..23 */ | ||
55 | 0x10, 0x0F, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, /* Word 0 Bits 24..31 */ | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * Local Functions | ||
60 | */ | ||
61 | bfa_status_t bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, | ||
62 | u8 alpa); | ||
63 | |||
64 | void bfa_fcs_port_loop_plogi_response(void *fcsarg, | ||
65 | struct bfa_fcxp_s *fcxp, | ||
66 | void *cbarg, | ||
67 | bfa_status_t req_status, | ||
68 | u32 rsp_len, | ||
69 | u32 resid_len, | ||
70 | struct fchs_s *rsp_fchs); | ||
71 | |||
72 | bfa_status_t bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port, | ||
73 | u8 alpa); | ||
74 | |||
75 | void bfa_fcs_port_loop_adisc_response(void *fcsarg, | ||
76 | struct bfa_fcxp_s *fcxp, | ||
77 | void *cbarg, | ||
78 | bfa_status_t req_status, | ||
79 | u32 rsp_len, | ||
80 | u32 resid_len, | ||
81 | struct fchs_s *rsp_fchs); | ||
82 | |||
83 | bfa_status_t bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port, | ||
84 | u8 alpa); | ||
85 | |||
86 | void bfa_fcs_port_loop_plogi_acc_response(void *fcsarg, | ||
87 | struct bfa_fcxp_s *fcxp, | ||
88 | void *cbarg, | ||
89 | bfa_status_t req_status, | ||
90 | u32 rsp_len, | ||
91 | u32 resid_len, | ||
92 | struct fchs_s *rsp_fchs); | ||
93 | |||
94 | bfa_status_t bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port, | ||
95 | u8 alpa); | ||
96 | |||
97 | void bfa_fcs_port_loop_adisc_acc_response(void *fcsarg, | ||
98 | struct bfa_fcxp_s *fcxp, | ||
99 | void *cbarg, | ||
100 | bfa_status_t req_status, | ||
101 | u32 rsp_len, | ||
102 | u32 resid_len, | ||
103 | struct fchs_s *rsp_fchs); | ||
104 | /** | ||
105 | * Called by port to initializar in provate LOOP topology. | ||
106 | */ | ||
107 | void | ||
108 | bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port) | ||
109 | { | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * Called by port to notify transition to online state. | ||
114 | */ | ||
115 | void | ||
116 | bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port) | ||
117 | { | ||
118 | |||
119 | u8 num_alpa = port->port_topo.ploop.num_alpa; | ||
120 | u8 *alpa_pos_map = port->port_topo.ploop.alpa_pos_map; | ||
121 | struct bfa_fcs_rport_s *r_port; | ||
122 | int ii = 0; | ||
123 | |||
124 | /* | ||
125 | * If the port role is Initiator Mode, create Rports. | ||
126 | */ | ||
127 | if (port->port_cfg.roles == BFA_PORT_ROLE_FCP_IM) { | ||
128 | /* | ||
129 | * Check if the ALPA positional bitmap is available. | ||
130 | * if not, we send PLOGI to all possible ALPAs. | ||
131 | */ | ||
132 | if (num_alpa > 0) { | ||
133 | for (ii = 0; ii < num_alpa; ii++) { | ||
134 | /* | ||
135 | * ignore ALPA of bfa port | ||
136 | */ | ||
137 | if (alpa_pos_map[ii] != port->pid) { | ||
138 | r_port = bfa_fcs_rport_create(port, | ||
139 | alpa_pos_map[ii]); | ||
140 | } | ||
141 | } | ||
142 | } else { | ||
143 | for (ii = 0; ii < MAX_ALPA_COUNT; ii++) { | ||
144 | /* | ||
145 | * ignore ALPA of bfa port | ||
146 | */ | ||
147 | if ((port_loop_alpa_map[ii] > 0) | ||
148 | && (port_loop_alpa_map[ii] != port->pid)) | ||
149 | bfa_fcs_port_loop_send_plogi(port, | ||
150 | port_loop_alpa_map[ii]); | ||
151 | /**TBD */ | ||
152 | } | ||
153 | } | ||
154 | } else { | ||
155 | /* | ||
156 | * TBD Target Mode ?? | ||
157 | */ | ||
158 | } | ||
159 | |||
160 | } | ||
161 | |||
162 | /** | ||
163 | * Called by port to notify transition to offline state. | ||
164 | */ | ||
165 | void | ||
166 | bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port) | ||
167 | { | ||
168 | |||
169 | } | ||
170 | |||
171 | /** | ||
172 | * Called by port to notify a LIP on the loop. | ||
173 | */ | ||
174 | void | ||
175 | bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port) | ||
176 | { | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * Local Functions. | ||
181 | */ | ||
182 | bfa_status_t | ||
183 | bfa_fcs_port_loop_send_plogi(struct bfa_fcs_port_s *port, u8 alpa) | ||
184 | { | ||
185 | struct fchs_s fchs; | ||
186 | struct bfa_fcxp_s *fcxp = NULL; | ||
187 | int len; | ||
188 | |||
189 | bfa_trc(port->fcs, alpa); | ||
190 | |||
191 | fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL, | ||
192 | NULL); | ||
193 | bfa_assert(fcxp); | ||
194 | |||
195 | len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa, | ||
196 | bfa_fcs_port_get_fcid(port), 0, | ||
197 | port->port_cfg.pwwn, port->port_cfg.nwwn, | ||
198 | bfa_pport_get_maxfrsize(port->fcs->bfa)); | ||
199 | |||
200 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
201 | FC_CLASS_3, len, &fchs, | ||
202 | bfa_fcs_port_loop_plogi_response, (void *)port, | ||
203 | FC_MAX_PDUSZ, FC_RA_TOV); | ||
204 | |||
205 | return BFA_STATUS_OK; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * Called by fcxp to notify the Plogi response | ||
210 | */ | ||
211 | void | ||
212 | bfa_fcs_port_loop_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
213 | void *cbarg, bfa_status_t req_status, | ||
214 | u32 rsp_len, u32 resid_len, | ||
215 | struct fchs_s *rsp_fchs) | ||
216 | { | ||
217 | struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg; | ||
218 | struct fc_logi_s *plogi_resp; | ||
219 | struct fc_els_cmd_s *els_cmd; | ||
220 | |||
221 | bfa_trc(port->fcs, req_status); | ||
222 | |||
223 | /* | ||
224 | * Sanity Checks | ||
225 | */ | ||
226 | if (req_status != BFA_STATUS_OK) { | ||
227 | bfa_trc(port->fcs, req_status); | ||
228 | /* | ||
229 | * @todo | ||
230 | * This could mean that the device with this APLA does not | ||
231 | * exist on the loop. | ||
232 | */ | ||
233 | |||
234 | return; | ||
235 | } | ||
236 | |||
237 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
238 | plogi_resp = (struct fc_logi_s *) els_cmd; | ||
239 | |||
240 | if (els_cmd->els_code == FC_ELS_ACC) { | ||
241 | bfa_fcs_rport_start(port, rsp_fchs, plogi_resp); | ||
242 | } else { | ||
243 | bfa_trc(port->fcs, plogi_resp->els_cmd.els_code); | ||
244 | bfa_assert(0); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | bfa_status_t | ||
249 | bfa_fcs_port_loop_send_plogi_acc(struct bfa_fcs_port_s *port, u8 alpa) | ||
250 | { | ||
251 | struct fchs_s fchs; | ||
252 | struct bfa_fcxp_s *fcxp; | ||
253 | int len; | ||
254 | |||
255 | bfa_trc(port->fcs, alpa); | ||
256 | |||
257 | fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL, | ||
258 | NULL); | ||
259 | bfa_assert(fcxp); | ||
260 | |||
261 | len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa, | ||
262 | bfa_fcs_port_get_fcid(port), 0, | ||
263 | port->port_cfg.pwwn, port->port_cfg.nwwn, | ||
264 | bfa_pport_get_maxfrsize(port->fcs->bfa)); | ||
265 | |||
266 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
267 | FC_CLASS_3, len, &fchs, | ||
268 | bfa_fcs_port_loop_plogi_acc_response, | ||
269 | (void *)port, FC_MAX_PDUSZ, 0); /* No response | ||
270 | * expected | ||
271 | */ | ||
272 | |||
273 | return BFA_STATUS_OK; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Plogi Acc Response | ||
278 | * We donot do any processing here. | ||
279 | */ | ||
280 | void | ||
281 | bfa_fcs_port_loop_plogi_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
282 | void *cbarg, bfa_status_t req_status, | ||
283 | u32 rsp_len, u32 resid_len, | ||
284 | struct fchs_s *rsp_fchs) | ||
285 | { | ||
286 | |||
287 | struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg; | ||
288 | |||
289 | bfa_trc(port->fcs, port->pid); | ||
290 | |||
291 | /* | ||
292 | * Sanity Checks | ||
293 | */ | ||
294 | if (req_status != BFA_STATUS_OK) { | ||
295 | bfa_trc(port->fcs, req_status); | ||
296 | return; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | bfa_status_t | ||
301 | bfa_fcs_port_loop_send_adisc(struct bfa_fcs_port_s *port, u8 alpa) | ||
302 | { | ||
303 | struct fchs_s fchs; | ||
304 | struct bfa_fcxp_s *fcxp; | ||
305 | int len; | ||
306 | |||
307 | bfa_trc(port->fcs, alpa); | ||
308 | |||
309 | fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL, | ||
310 | NULL); | ||
311 | bfa_assert(fcxp); | ||
312 | |||
313 | len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa, | ||
314 | bfa_fcs_port_get_fcid(port), 0, | ||
315 | port->port_cfg.pwwn, port->port_cfg.nwwn); | ||
316 | |||
317 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
318 | FC_CLASS_3, len, &fchs, | ||
319 | bfa_fcs_port_loop_adisc_response, (void *)port, | ||
320 | FC_MAX_PDUSZ, FC_RA_TOV); | ||
321 | |||
322 | return BFA_STATUS_OK; | ||
323 | } | ||
324 | |||
325 | /** | ||
326 | * Called by fcxp to notify the ADISC response | ||
327 | */ | ||
328 | void | ||
329 | bfa_fcs_port_loop_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
330 | void *cbarg, bfa_status_t req_status, | ||
331 | u32 rsp_len, u32 resid_len, | ||
332 | struct fchs_s *rsp_fchs) | ||
333 | { | ||
334 | struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg; | ||
335 | struct bfa_fcs_rport_s *rport; | ||
336 | struct fc_adisc_s *adisc_resp; | ||
337 | struct fc_els_cmd_s *els_cmd; | ||
338 | u32 pid = rsp_fchs->s_id; | ||
339 | |||
340 | bfa_trc(port->fcs, req_status); | ||
341 | |||
342 | /* | ||
343 | * Sanity Checks | ||
344 | */ | ||
345 | if (req_status != BFA_STATUS_OK) { | ||
346 | /* | ||
347 | * TBD : we may need to retry certain requests | ||
348 | */ | ||
349 | bfa_fcxp_free(fcxp); | ||
350 | return; | ||
351 | } | ||
352 | |||
353 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
354 | adisc_resp = (struct fc_adisc_s *) els_cmd; | ||
355 | |||
356 | if (els_cmd->els_code == FC_ELS_ACC) { | ||
357 | } else { | ||
358 | bfa_trc(port->fcs, adisc_resp->els_cmd.els_code); | ||
359 | |||
360 | /* | ||
361 | * TBD: we may need to check for reject codes and retry | ||
362 | */ | ||
363 | rport = bfa_fcs_port_get_rport_by_pid(port, pid); | ||
364 | if (rport) { | ||
365 | list_del(&rport->qe); | ||
366 | bfa_fcs_rport_delete(rport); | ||
367 | } | ||
368 | |||
369 | } | ||
370 | return; | ||
371 | } | ||
372 | |||
373 | bfa_status_t | ||
374 | bfa_fcs_port_loop_send_adisc_acc(struct bfa_fcs_port_s *port, u8 alpa) | ||
375 | { | ||
376 | struct fchs_s fchs; | ||
377 | struct bfa_fcxp_s *fcxp; | ||
378 | int len; | ||
379 | |||
380 | bfa_trc(port->fcs, alpa); | ||
381 | |||
382 | fcxp = bfa_fcxp_alloc(NULL, port->fcs->bfa, 0, 0, NULL, NULL, NULL, | ||
383 | NULL); | ||
384 | bfa_assert(fcxp); | ||
385 | |||
386 | len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), alpa, | ||
387 | bfa_fcs_port_get_fcid(port), 0, | ||
388 | port->port_cfg.pwwn, port->port_cfg.nwwn); | ||
389 | |||
390 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
391 | FC_CLASS_3, len, &fchs, | ||
392 | bfa_fcs_port_loop_adisc_acc_response, | ||
393 | (void *)port, FC_MAX_PDUSZ, 0); /* no reponse | ||
394 | * expected | ||
395 | */ | ||
396 | |||
397 | return BFA_STATUS_OK; | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * Adisc Acc Response | ||
402 | * We donot do any processing here. | ||
403 | */ | ||
404 | void | ||
405 | bfa_fcs_port_loop_adisc_acc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
406 | void *cbarg, bfa_status_t req_status, | ||
407 | u32 rsp_len, u32 resid_len, | ||
408 | struct fchs_s *rsp_fchs) | ||
409 | { | ||
410 | |||
411 | struct bfa_fcs_port_s *port = (struct bfa_fcs_port_s *) cbarg; | ||
412 | |||
413 | bfa_trc(port->fcs, port->pid); | ||
414 | |||
415 | /* | ||
416 | * Sanity Checks | ||
417 | */ | ||
418 | if (req_status != BFA_STATUS_OK) { | ||
419 | bfa_trc(port->fcs, req_status); | ||
420 | return; | ||
421 | } | ||
422 | } | ||
diff --git a/drivers/scsi/bfa/lport_api.c b/drivers/scsi/bfa/lport_api.c new file mode 100644 index 000000000000..8f51a83f1834 --- /dev/null +++ b/drivers/scsi/bfa/lport_api.c | |||
@@ -0,0 +1,291 @@ | |||
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 | { | ||
46 | return (&fcs->fabric.bport); | ||
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); | ||
91 | if (rport) { | ||
92 | return rport->pwwn; | ||
93 | } else { | ||
94 | return (wwn_t) 0; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | void | ||
99 | bfa_fcs_port_get_rports(struct bfa_fcs_port_s *port, wwn_t rport_wwns[], | ||
100 | int *nrports) | ||
101 | { | ||
102 | struct list_head *qh, *qe; | ||
103 | struct bfa_fcs_rport_s *rport = NULL; | ||
104 | int i; | ||
105 | struct bfa_fcs_s *fcs; | ||
106 | |||
107 | if (port == NULL || rport_wwns == NULL || *nrports == 0) | ||
108 | return; | ||
109 | |||
110 | fcs = port->fcs; | ||
111 | bfa_trc(fcs, (u32) *nrports); | ||
112 | |||
113 | i = 0; | ||
114 | qh = &port->rport_q; | ||
115 | qe = bfa_q_first(qh); | ||
116 | |||
117 | while ((qe != qh) && (i < *nrports)) { | ||
118 | rport = (struct bfa_fcs_rport_s *)qe; | ||
119 | if (bfa_os_ntoh3b(rport->pid) > 0xFFF000) { | ||
120 | qe = bfa_q_next(qe); | ||
121 | bfa_trc(fcs, (u32) rport->pwwn); | ||
122 | bfa_trc(fcs, rport->pid); | ||
123 | bfa_trc(fcs, i); | ||
124 | continue; | ||
125 | } | ||
126 | |||
127 | rport_wwns[i] = rport->pwwn; | ||
128 | |||
129 | i++; | ||
130 | qe = bfa_q_next(qe); | ||
131 | } | ||
132 | |||
133 | bfa_trc(fcs, i); | ||
134 | *nrports = i; | ||
135 | return; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Iterate's through all the rport's in the given port to | ||
140 | * determine the maximum operating speed. | ||
141 | */ | ||
142 | enum bfa_pport_speed | ||
143 | bfa_fcs_port_get_rport_max_speed(struct bfa_fcs_port_s *port) | ||
144 | { | ||
145 | struct list_head *qh, *qe; | ||
146 | struct bfa_fcs_rport_s *rport = NULL; | ||
147 | struct bfa_fcs_s *fcs; | ||
148 | enum bfa_pport_speed max_speed = 0; | ||
149 | struct bfa_pport_attr_s pport_attr; | ||
150 | enum bfa_pport_speed pport_speed; | ||
151 | |||
152 | if (port == NULL) | ||
153 | return 0; | ||
154 | |||
155 | fcs = port->fcs; | ||
156 | |||
157 | /* | ||
158 | * Get Physical port's current speed | ||
159 | */ | ||
160 | bfa_pport_get_attr(port->fcs->bfa, &pport_attr); | ||
161 | pport_speed = pport_attr.speed; | ||
162 | bfa_trc(fcs, pport_speed); | ||
163 | |||
164 | qh = &port->rport_q; | ||
165 | qe = bfa_q_first(qh); | ||
166 | |||
167 | while (qe != qh) { | ||
168 | rport = (struct bfa_fcs_rport_s *)qe; | ||
169 | if ((bfa_os_ntoh3b(rport->pid) > 0xFFF000) | ||
170 | || (bfa_fcs_rport_get_state(rport) == BFA_RPORT_OFFLINE)) { | ||
171 | qe = bfa_q_next(qe); | ||
172 | continue; | ||
173 | } | ||
174 | |||
175 | if ((rport->rpf.rpsc_speed == BFA_PPORT_SPEED_8GBPS) | ||
176 | || (rport->rpf.rpsc_speed > pport_speed)) { | ||
177 | max_speed = rport->rpf.rpsc_speed; | ||
178 | break; | ||
179 | } else if (rport->rpf.rpsc_speed > max_speed) { | ||
180 | max_speed = rport->rpf.rpsc_speed; | ||
181 | } | ||
182 | |||
183 | qe = bfa_q_next(qe); | ||
184 | } | ||
185 | |||
186 | bfa_trc(fcs, max_speed); | ||
187 | return max_speed; | ||
188 | } | ||
189 | |||
190 | struct bfa_fcs_port_s * | ||
191 | bfa_fcs_lookup_port(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t lpwwn) | ||
192 | { | ||
193 | struct bfa_fcs_vport_s *vport; | ||
194 | bfa_fcs_vf_t *vf; | ||
195 | |||
196 | bfa_assert(fcs != NULL); | ||
197 | |||
198 | vf = bfa_fcs_vf_lookup(fcs, vf_id); | ||
199 | if (vf == NULL) { | ||
200 | bfa_trc(fcs, vf_id); | ||
201 | return (NULL); | ||
202 | } | ||
203 | |||
204 | if (!lpwwn || (vf->bport.port_cfg.pwwn == lpwwn)) | ||
205 | return (&vf->bport); | ||
206 | |||
207 | vport = bfa_fcs_fabric_vport_lookup(vf, lpwwn); | ||
208 | if (vport) | ||
209 | return (&vport->lport); | ||
210 | |||
211 | return (NULL); | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * API corresponding to VmWare's NPIV_VPORT_GETINFO. | ||
216 | */ | ||
217 | void | ||
218 | bfa_fcs_port_get_info(struct bfa_fcs_port_s *port, | ||
219 | struct bfa_port_info_s *port_info) | ||
220 | { | ||
221 | |||
222 | bfa_trc(port->fcs, port->fabric->fabric_name); | ||
223 | |||
224 | if (port->vport == NULL) { | ||
225 | /* | ||
226 | * This is a Physical port | ||
227 | */ | ||
228 | port_info->port_type = BFA_PORT_TYPE_PHYSICAL; | ||
229 | |||
230 | /* | ||
231 | * @todo : need to fix the state & reason | ||
232 | */ | ||
233 | port_info->port_state = 0; | ||
234 | port_info->offline_reason = 0; | ||
235 | |||
236 | port_info->port_wwn = bfa_fcs_port_get_pwwn(port); | ||
237 | port_info->node_wwn = bfa_fcs_port_get_nwwn(port); | ||
238 | |||
239 | port_info->max_vports_supp = bfa_fcs_vport_get_max(port->fcs); | ||
240 | port_info->num_vports_inuse = | ||
241 | bfa_fcs_fabric_vport_count(port->fabric); | ||
242 | port_info->max_rports_supp = BFA_FCS_MAX_RPORTS_SUPP; | ||
243 | port_info->num_rports_inuse = port->num_rports; | ||
244 | } else { | ||
245 | /* | ||
246 | * This is a virtual port | ||
247 | */ | ||
248 | port_info->port_type = BFA_PORT_TYPE_VIRTUAL; | ||
249 | |||
250 | /* | ||
251 | * @todo : need to fix the state & reason | ||
252 | */ | ||
253 | port_info->port_state = 0; | ||
254 | port_info->offline_reason = 0; | ||
255 | |||
256 | port_info->port_wwn = bfa_fcs_port_get_pwwn(port); | ||
257 | port_info->node_wwn = bfa_fcs_port_get_nwwn(port); | ||
258 | } | ||
259 | } | ||
260 | |||
261 | void | ||
262 | bfa_fcs_port_get_stats(struct bfa_fcs_port_s *fcs_port, | ||
263 | struct bfa_port_stats_s *port_stats) | ||
264 | { | ||
265 | bfa_os_memcpy(port_stats, &fcs_port->stats, | ||
266 | sizeof(struct bfa_port_stats_s)); | ||
267 | return; | ||
268 | } | ||
269 | |||
270 | void | ||
271 | bfa_fcs_port_clear_stats(struct bfa_fcs_port_s *fcs_port) | ||
272 | { | ||
273 | bfa_os_memset(&fcs_port->stats, 0, sizeof(struct bfa_port_stats_s)); | ||
274 | return; | ||
275 | } | ||
276 | |||
277 | void | ||
278 | bfa_fcs_port_enable_ipfc_roles(struct bfa_fcs_port_s *fcs_port) | ||
279 | { | ||
280 | fcs_port->port_cfg.roles |= BFA_PORT_ROLE_FCP_IPFC; | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | void | ||
285 | bfa_fcs_port_disable_ipfc_roles(struct bfa_fcs_port_s *fcs_port) | ||
286 | { | ||
287 | fcs_port->port_cfg.roles &= ~BFA_PORT_ROLE_FCP_IPFC; | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | |||
diff --git a/drivers/scsi/bfa/lport_priv.h b/drivers/scsi/bfa/lport_priv.h new file mode 100644 index 000000000000..dbae370a599a --- /dev/null +++ b/drivers/scsi/bfa/lport_priv.h | |||
@@ -0,0 +1,82 @@ | |||
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 | #ifndef __VP_PRIV_H__ | ||
19 | #define __VP_PRIV_H__ | ||
20 | |||
21 | #include <fcs/bfa_fcs_lport.h> | ||
22 | #include <fcs/bfa_fcs_vport.h> | ||
23 | |||
24 | /* | ||
25 | * Functions exported by vps | ||
26 | */ | ||
27 | void bfa_fcs_vport_init(struct bfa_fcs_vport_s *vport); | ||
28 | |||
29 | /* | ||
30 | * Functions exported by vps | ||
31 | */ | ||
32 | void bfa_fcs_vps_online(struct bfa_fcs_port_s *port); | ||
33 | void bfa_fcs_vps_offline(struct bfa_fcs_port_s *port); | ||
34 | void bfa_fcs_vps_lip(struct bfa_fcs_port_s *port); | ||
35 | |||
36 | /* | ||
37 | * Functions exported by port_fab | ||
38 | */ | ||
39 | void bfa_fcs_port_fab_init(struct bfa_fcs_port_s *vport); | ||
40 | void bfa_fcs_port_fab_online(struct bfa_fcs_port_s *vport); | ||
41 | void bfa_fcs_port_fab_offline(struct bfa_fcs_port_s *vport); | ||
42 | void bfa_fcs_port_fab_rx_frame(struct bfa_fcs_port_s *port, | ||
43 | u8 *rx_frame, u32 len); | ||
44 | |||
45 | /* | ||
46 | * Functions exported by VP-NS. | ||
47 | */ | ||
48 | void bfa_fcs_port_ns_init(struct bfa_fcs_port_s *vport); | ||
49 | void bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *vport); | ||
50 | void bfa_fcs_port_ns_online(struct bfa_fcs_port_s *vport); | ||
51 | void bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port); | ||
52 | |||
53 | /* | ||
54 | * Functions exported by VP-SCN | ||
55 | */ | ||
56 | void bfa_fcs_port_scn_init(struct bfa_fcs_port_s *vport); | ||
57 | void bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *vport); | ||
58 | void bfa_fcs_port_scn_online(struct bfa_fcs_port_s *vport); | ||
59 | void bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port, | ||
60 | struct fchs_s *rx_frame, u32 len); | ||
61 | |||
62 | /* | ||
63 | * Functions exported by VP-N2N | ||
64 | */ | ||
65 | |||
66 | void bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port); | ||
67 | void bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port); | ||
68 | void bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port); | ||
69 | void bfa_fcs_port_n2n_rx_frame(struct bfa_fcs_port_s *port, | ||
70 | u8 *rx_frame, u32 len); | ||
71 | |||
72 | /* | ||
73 | * Functions exported by VP-LOOP | ||
74 | */ | ||
75 | void bfa_fcs_port_loop_init(struct bfa_fcs_port_s *port); | ||
76 | void bfa_fcs_port_loop_online(struct bfa_fcs_port_s *port); | ||
77 | void bfa_fcs_port_loop_offline(struct bfa_fcs_port_s *port); | ||
78 | void bfa_fcs_port_loop_lip(struct bfa_fcs_port_s *port); | ||
79 | void bfa_fcs_port_loop_rx_frame(struct bfa_fcs_port_s *port, | ||
80 | u8 *rx_frame, u32 len); | ||
81 | |||
82 | #endif /* __VP_PRIV_H__ */ | ||
diff --git a/drivers/scsi/bfa/ms.c b/drivers/scsi/bfa/ms.c new file mode 100644 index 000000000000..c96b3ca007ae --- /dev/null +++ b/drivers/scsi/bfa/ms.c | |||
@@ -0,0 +1,759 @@ | |||
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 | #include <bfa.h> | ||
20 | #include <bfa_svc.h> | ||
21 | #include "fcs_lport.h" | ||
22 | #include "fcs_rport.h" | ||
23 | #include "fcs_trcmod.h" | ||
24 | #include "fcs_fcxp.h" | ||
25 | #include "lport_priv.h" | ||
26 | |||
27 | BFA_TRC_FILE(FCS, MS); | ||
28 | |||
29 | #define BFA_FCS_MS_CMD_MAX_RETRIES 2 | ||
30 | /* | ||
31 | * forward declarations | ||
32 | */ | ||
33 | static void bfa_fcs_port_ms_send_plogi(void *ms_cbarg, | ||
34 | struct bfa_fcxp_s *fcxp_alloced); | ||
35 | static void bfa_fcs_port_ms_timeout(void *arg); | ||
36 | static void bfa_fcs_port_ms_plogi_response(void *fcsarg, | ||
37 | struct bfa_fcxp_s *fcxp, | ||
38 | void *cbarg, | ||
39 | bfa_status_t req_status, | ||
40 | u32 rsp_len, | ||
41 | u32 resid_len, | ||
42 | struct fchs_s *rsp_fchs); | ||
43 | |||
44 | static void bfa_fcs_port_ms_send_gmal(void *ms_cbarg, | ||
45 | struct bfa_fcxp_s *fcxp_alloced); | ||
46 | static void bfa_fcs_port_ms_gmal_response(void *fcsarg, | ||
47 | struct bfa_fcxp_s *fcxp, | ||
48 | void *cbarg, | ||
49 | bfa_status_t req_status, | ||
50 | u32 rsp_len, | ||
51 | u32 resid_len, | ||
52 | struct fchs_s *rsp_fchs); | ||
53 | static void bfa_fcs_port_ms_send_gfn(void *ms_cbarg, | ||
54 | struct bfa_fcxp_s *fcxp_alloced); | ||
55 | static void bfa_fcs_port_ms_gfn_response(void *fcsarg, | ||
56 | struct bfa_fcxp_s *fcxp, | ||
57 | void *cbarg, | ||
58 | bfa_status_t req_status, | ||
59 | u32 rsp_len, | ||
60 | u32 resid_len, | ||
61 | struct fchs_s *rsp_fchs); | ||
62 | /** | ||
63 | * fcs_ms_sm FCS MS state machine | ||
64 | */ | ||
65 | |||
66 | /** | ||
67 | * MS State Machine events | ||
68 | */ | ||
69 | enum port_ms_event { | ||
70 | MSSM_EVENT_PORT_ONLINE = 1, | ||
71 | MSSM_EVENT_PORT_OFFLINE = 2, | ||
72 | MSSM_EVENT_RSP_OK = 3, | ||
73 | MSSM_EVENT_RSP_ERROR = 4, | ||
74 | MSSM_EVENT_TIMEOUT = 5, | ||
75 | MSSM_EVENT_FCXP_SENT = 6, | ||
76 | MSSM_EVENT_PORT_FABRIC_RSCN = 7 | ||
77 | }; | ||
78 | |||
79 | static void bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms, | ||
80 | enum port_ms_event event); | ||
81 | static void bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms, | ||
82 | enum port_ms_event event); | ||
83 | static void bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, | ||
84 | enum port_ms_event event); | ||
85 | static void bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms, | ||
86 | enum port_ms_event event); | ||
87 | static void bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms, | ||
88 | enum port_ms_event event); | ||
89 | static void bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, | ||
90 | enum port_ms_event event); | ||
91 | static void bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms, | ||
92 | enum port_ms_event event); | ||
93 | static void bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms, | ||
94 | enum port_ms_event event); | ||
95 | static void bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, | ||
96 | enum port_ms_event event); | ||
97 | static void bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms, | ||
98 | enum port_ms_event event); | ||
99 | static void bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms, | ||
100 | enum port_ms_event event); | ||
101 | /** | ||
102 | * Start in offline state - awaiting NS to send start. | ||
103 | */ | ||
104 | static void | ||
105 | bfa_fcs_port_ms_sm_offline(struct bfa_fcs_port_ms_s *ms, | ||
106 | enum port_ms_event event) | ||
107 | { | ||
108 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
109 | bfa_trc(ms->port->fcs, event); | ||
110 | |||
111 | switch (event) { | ||
112 | case MSSM_EVENT_PORT_ONLINE: | ||
113 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending); | ||
114 | bfa_fcs_port_ms_send_plogi(ms, NULL); | ||
115 | break; | ||
116 | |||
117 | case MSSM_EVENT_PORT_OFFLINE: | ||
118 | break; | ||
119 | |||
120 | default: | ||
121 | bfa_assert(0); | ||
122 | } | ||
123 | } | ||
124 | |||
125 | static void | ||
126 | bfa_fcs_port_ms_sm_plogi_sending(struct bfa_fcs_port_ms_s *ms, | ||
127 | enum port_ms_event event) | ||
128 | { | ||
129 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
130 | bfa_trc(ms->port->fcs, event); | ||
131 | |||
132 | switch (event) { | ||
133 | case MSSM_EVENT_FCXP_SENT: | ||
134 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi); | ||
135 | break; | ||
136 | |||
137 | case MSSM_EVENT_PORT_OFFLINE: | ||
138 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
139 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | ||
140 | &ms->fcxp_wqe); | ||
141 | break; | ||
142 | |||
143 | default: | ||
144 | bfa_assert(0); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | static void | ||
149 | bfa_fcs_port_ms_sm_plogi(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) | ||
150 | { | ||
151 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
152 | bfa_trc(ms->port->fcs, event); | ||
153 | |||
154 | switch (event) { | ||
155 | case MSSM_EVENT_RSP_ERROR: | ||
156 | /* | ||
157 | * Start timer for a delayed retry | ||
158 | */ | ||
159 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_retry); | ||
160 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), &ms->timer, | ||
161 | bfa_fcs_port_ms_timeout, ms, | ||
162 | BFA_FCS_RETRY_TIMEOUT); | ||
163 | break; | ||
164 | |||
165 | case MSSM_EVENT_RSP_OK: | ||
166 | /* | ||
167 | * since plogi is done, now invoke MS related sub-modules | ||
168 | */ | ||
169 | bfa_fcs_port_fdmi_online(ms); | ||
170 | |||
171 | /** | ||
172 | * if this is a Vport, go to online state. | ||
173 | */ | ||
174 | if (ms->port->vport) { | ||
175 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online); | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * For a base port we need to get the | ||
181 | * switch's IP address. | ||
182 | */ | ||
183 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending); | ||
184 | bfa_fcs_port_ms_send_gmal(ms, NULL); | ||
185 | break; | ||
186 | |||
187 | case MSSM_EVENT_PORT_OFFLINE: | ||
188 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
189 | bfa_fcxp_discard(ms->fcxp); | ||
190 | break; | ||
191 | |||
192 | default: | ||
193 | bfa_assert(0); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | static void | ||
198 | bfa_fcs_port_ms_sm_plogi_retry(struct bfa_fcs_port_ms_s *ms, | ||
199 | enum port_ms_event event) | ||
200 | { | ||
201 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
202 | bfa_trc(ms->port->fcs, event); | ||
203 | |||
204 | switch (event) { | ||
205 | case MSSM_EVENT_TIMEOUT: | ||
206 | /* | ||
207 | * Retry Timer Expired. Re-send | ||
208 | */ | ||
209 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_plogi_sending); | ||
210 | bfa_fcs_port_ms_send_plogi(ms, NULL); | ||
211 | break; | ||
212 | |||
213 | case MSSM_EVENT_PORT_OFFLINE: | ||
214 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
215 | bfa_timer_stop(&ms->timer); | ||
216 | break; | ||
217 | |||
218 | default: | ||
219 | bfa_assert(0); | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static void | ||
224 | bfa_fcs_port_ms_sm_online(struct bfa_fcs_port_ms_s *ms, | ||
225 | enum port_ms_event event) | ||
226 | { | ||
227 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
228 | bfa_trc(ms->port->fcs, event); | ||
229 | |||
230 | switch (event) { | ||
231 | case MSSM_EVENT_PORT_OFFLINE: | ||
232 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
233 | /* | ||
234 | * now invoke MS related sub-modules | ||
235 | */ | ||
236 | bfa_fcs_port_fdmi_offline(ms); | ||
237 | break; | ||
238 | |||
239 | case MSSM_EVENT_PORT_FABRIC_RSCN: | ||
240 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending); | ||
241 | ms->retry_cnt = 0; | ||
242 | bfa_fcs_port_ms_send_gfn(ms, NULL); | ||
243 | break; | ||
244 | |||
245 | default: | ||
246 | bfa_assert(0); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void | ||
251 | bfa_fcs_port_ms_sm_gmal_sending(struct bfa_fcs_port_ms_s *ms, | ||
252 | enum port_ms_event event) | ||
253 | { | ||
254 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
255 | bfa_trc(ms->port->fcs, event); | ||
256 | |||
257 | switch (event) { | ||
258 | case MSSM_EVENT_FCXP_SENT: | ||
259 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal); | ||
260 | break; | ||
261 | |||
262 | case MSSM_EVENT_PORT_OFFLINE: | ||
263 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
264 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | ||
265 | &ms->fcxp_wqe); | ||
266 | break; | ||
267 | |||
268 | default: | ||
269 | bfa_assert(0); | ||
270 | } | ||
271 | } | ||
272 | |||
273 | static void | ||
274 | bfa_fcs_port_ms_sm_gmal(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) | ||
275 | { | ||
276 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
277 | bfa_trc(ms->port->fcs, event); | ||
278 | |||
279 | switch (event) { | ||
280 | case MSSM_EVENT_RSP_ERROR: | ||
281 | /* | ||
282 | * Start timer for a delayed retry | ||
283 | */ | ||
284 | if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { | ||
285 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_retry); | ||
286 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | ||
287 | &ms->timer, bfa_fcs_port_ms_timeout, ms, | ||
288 | BFA_FCS_RETRY_TIMEOUT); | ||
289 | } else { | ||
290 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending); | ||
291 | bfa_fcs_port_ms_send_gfn(ms, NULL); | ||
292 | ms->retry_cnt = 0; | ||
293 | } | ||
294 | break; | ||
295 | |||
296 | case MSSM_EVENT_RSP_OK: | ||
297 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending); | ||
298 | bfa_fcs_port_ms_send_gfn(ms, NULL); | ||
299 | break; | ||
300 | |||
301 | case MSSM_EVENT_PORT_OFFLINE: | ||
302 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
303 | bfa_fcxp_discard(ms->fcxp); | ||
304 | break; | ||
305 | |||
306 | default: | ||
307 | bfa_assert(0); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | static void | ||
312 | bfa_fcs_port_ms_sm_gmal_retry(struct bfa_fcs_port_ms_s *ms, | ||
313 | enum port_ms_event event) | ||
314 | { | ||
315 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
316 | bfa_trc(ms->port->fcs, event); | ||
317 | |||
318 | switch (event) { | ||
319 | case MSSM_EVENT_TIMEOUT: | ||
320 | /* | ||
321 | * Retry Timer Expired. Re-send | ||
322 | */ | ||
323 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gmal_sending); | ||
324 | bfa_fcs_port_ms_send_gmal(ms, NULL); | ||
325 | break; | ||
326 | |||
327 | case MSSM_EVENT_PORT_OFFLINE: | ||
328 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
329 | bfa_timer_stop(&ms->timer); | ||
330 | break; | ||
331 | |||
332 | default: | ||
333 | bfa_assert(0); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | /** | ||
338 | * ms_pvt MS local functions | ||
339 | */ | ||
340 | |||
341 | static void | ||
342 | bfa_fcs_port_ms_send_gmal(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
343 | { | ||
344 | struct bfa_fcs_port_ms_s *ms = ms_cbarg; | ||
345 | struct bfa_fcs_port_s *port = ms->port; | ||
346 | struct fchs_s fchs; | ||
347 | int len; | ||
348 | struct bfa_fcxp_s *fcxp; | ||
349 | |||
350 | bfa_trc(port->fcs, port->pid); | ||
351 | |||
352 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
353 | if (!fcxp) { | ||
354 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, | ||
355 | bfa_fcs_port_ms_send_gmal, ms); | ||
356 | return; | ||
357 | } | ||
358 | ms->fcxp = fcxp; | ||
359 | |||
360 | len = fc_gmal_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
361 | bfa_fcs_port_get_fcid(port), | ||
362 | bfa_lps_get_peer_nwwn(port->fabric->lps)); | ||
363 | |||
364 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
365 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gmal_response, | ||
366 | (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV); | ||
367 | |||
368 | bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); | ||
369 | } | ||
370 | |||
371 | static void | ||
372 | bfa_fcs_port_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
373 | void *cbarg, bfa_status_t req_status, | ||
374 | u32 rsp_len, u32 resid_len, | ||
375 | struct fchs_s *rsp_fchs) | ||
376 | { | ||
377 | struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg; | ||
378 | struct bfa_fcs_port_s *port = ms->port; | ||
379 | struct ct_hdr_s *cthdr = NULL; | ||
380 | struct fcgs_gmal_resp_s *gmal_resp; | ||
381 | struct fc_gmal_entry_s *gmal_entry; | ||
382 | u32 num_entries; | ||
383 | u8 *rsp_str; | ||
384 | |||
385 | bfa_trc(port->fcs, req_status); | ||
386 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
387 | |||
388 | /* | ||
389 | * Sanity Checks | ||
390 | */ | ||
391 | if (req_status != BFA_STATUS_OK) { | ||
392 | bfa_trc(port->fcs, req_status); | ||
393 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
394 | return; | ||
395 | } | ||
396 | |||
397 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
398 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
399 | |||
400 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
401 | gmal_resp = (struct fcgs_gmal_resp_s *)(cthdr + 1); | ||
402 | num_entries = bfa_os_ntohl(gmal_resp->ms_len); | ||
403 | if (num_entries == 0) { | ||
404 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
405 | return; | ||
406 | } | ||
407 | /* | ||
408 | * The response could contain multiple Entries. | ||
409 | * Entries for SNMP interface, etc. | ||
410 | * We look for the entry with a telnet prefix. | ||
411 | * First "http://" entry refers to IP addr | ||
412 | */ | ||
413 | |||
414 | gmal_entry = (struct fc_gmal_entry_s *)gmal_resp->ms_ma; | ||
415 | while (num_entries > 0) { | ||
416 | if (strncmp | ||
417 | (gmal_entry->prefix, CT_GMAL_RESP_PREFIX_HTTP, | ||
418 | sizeof(gmal_entry->prefix)) == 0) { | ||
419 | |||
420 | /* | ||
421 | * if the IP address is terminating with a '/', | ||
422 | * remove it. *Byte 0 consists of the length | ||
423 | * of the string. | ||
424 | */ | ||
425 | rsp_str = &(gmal_entry->prefix[0]); | ||
426 | if (rsp_str[gmal_entry->len - 1] == '/') | ||
427 | rsp_str[gmal_entry->len - 1] = 0; | ||
428 | /* | ||
429 | * copy IP Address to fabric | ||
430 | */ | ||
431 | strncpy(bfa_fcs_port_get_fabric_ipaddr(port), | ||
432 | gmal_entry->ip_addr, | ||
433 | BFA_FCS_FABRIC_IPADDR_SZ); | ||
434 | break; | ||
435 | } else { | ||
436 | --num_entries; | ||
437 | ++gmal_entry; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); | ||
442 | return; | ||
443 | } | ||
444 | |||
445 | bfa_trc(port->fcs, cthdr->reason_code); | ||
446 | bfa_trc(port->fcs, cthdr->exp_code); | ||
447 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
448 | } | ||
449 | |||
450 | static void | ||
451 | bfa_fcs_port_ms_sm_gfn_sending(struct bfa_fcs_port_ms_s *ms, | ||
452 | enum port_ms_event event) | ||
453 | { | ||
454 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
455 | bfa_trc(ms->port->fcs, event); | ||
456 | |||
457 | switch (event) { | ||
458 | case MSSM_EVENT_FCXP_SENT: | ||
459 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn); | ||
460 | break; | ||
461 | |||
462 | case MSSM_EVENT_PORT_OFFLINE: | ||
463 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
464 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | ||
465 | &ms->fcxp_wqe); | ||
466 | break; | ||
467 | |||
468 | default: | ||
469 | bfa_assert(0); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | static void | ||
474 | bfa_fcs_port_ms_sm_gfn(struct bfa_fcs_port_ms_s *ms, enum port_ms_event event) | ||
475 | { | ||
476 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
477 | bfa_trc(ms->port->fcs, event); | ||
478 | |||
479 | switch (event) { | ||
480 | case MSSM_EVENT_RSP_ERROR: | ||
481 | /* | ||
482 | * Start timer for a delayed retry | ||
483 | */ | ||
484 | if (ms->retry_cnt++ < BFA_FCS_MS_CMD_MAX_RETRIES) { | ||
485 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_retry); | ||
486 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ms->port), | ||
487 | &ms->timer, bfa_fcs_port_ms_timeout, ms, | ||
488 | BFA_FCS_RETRY_TIMEOUT); | ||
489 | } else { | ||
490 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online); | ||
491 | ms->retry_cnt = 0; | ||
492 | } | ||
493 | break; | ||
494 | |||
495 | case MSSM_EVENT_RSP_OK: | ||
496 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_online); | ||
497 | break; | ||
498 | |||
499 | case MSSM_EVENT_PORT_OFFLINE: | ||
500 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
501 | bfa_fcxp_discard(ms->fcxp); | ||
502 | break; | ||
503 | |||
504 | default: | ||
505 | bfa_assert(0); | ||
506 | } | ||
507 | } | ||
508 | |||
509 | static void | ||
510 | bfa_fcs_port_ms_sm_gfn_retry(struct bfa_fcs_port_ms_s *ms, | ||
511 | enum port_ms_event event) | ||
512 | { | ||
513 | bfa_trc(ms->port->fcs, ms->port->port_cfg.pwwn); | ||
514 | bfa_trc(ms->port->fcs, event); | ||
515 | |||
516 | switch (event) { | ||
517 | case MSSM_EVENT_TIMEOUT: | ||
518 | /* | ||
519 | * Retry Timer Expired. Re-send | ||
520 | */ | ||
521 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_gfn_sending); | ||
522 | bfa_fcs_port_ms_send_gfn(ms, NULL); | ||
523 | break; | ||
524 | |||
525 | case MSSM_EVENT_PORT_OFFLINE: | ||
526 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
527 | bfa_timer_stop(&ms->timer); | ||
528 | break; | ||
529 | |||
530 | default: | ||
531 | bfa_assert(0); | ||
532 | } | ||
533 | } | ||
534 | |||
535 | /** | ||
536 | * ms_pvt MS local functions | ||
537 | */ | ||
538 | |||
539 | static void | ||
540 | bfa_fcs_port_ms_send_gfn(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
541 | { | ||
542 | struct bfa_fcs_port_ms_s *ms = ms_cbarg; | ||
543 | struct bfa_fcs_port_s *port = ms->port; | ||
544 | struct fchs_s fchs; | ||
545 | int len; | ||
546 | struct bfa_fcxp_s *fcxp; | ||
547 | |||
548 | bfa_trc(port->fcs, port->pid); | ||
549 | |||
550 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
551 | if (!fcxp) { | ||
552 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, | ||
553 | bfa_fcs_port_ms_send_gfn, ms); | ||
554 | return; | ||
555 | } | ||
556 | ms->fcxp = fcxp; | ||
557 | |||
558 | len = fc_gfn_req_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
559 | bfa_fcs_port_get_fcid(port), | ||
560 | bfa_lps_get_peer_nwwn(port->fabric->lps)); | ||
561 | |||
562 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
563 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_gfn_response, | ||
564 | (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV); | ||
565 | |||
566 | bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); | ||
567 | } | ||
568 | |||
569 | static void | ||
570 | bfa_fcs_port_ms_gfn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
571 | bfa_status_t req_status, u32 rsp_len, | ||
572 | u32 resid_len, struct fchs_s *rsp_fchs) | ||
573 | { | ||
574 | struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg; | ||
575 | struct bfa_fcs_port_s *port = ms->port; | ||
576 | struct ct_hdr_s *cthdr = NULL; | ||
577 | wwn_t *gfn_resp; | ||
578 | |||
579 | bfa_trc(port->fcs, req_status); | ||
580 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
581 | |||
582 | /* | ||
583 | * Sanity Checks | ||
584 | */ | ||
585 | if (req_status != BFA_STATUS_OK) { | ||
586 | bfa_trc(port->fcs, req_status); | ||
587 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
588 | return; | ||
589 | } | ||
590 | |||
591 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
592 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
593 | |||
594 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
595 | gfn_resp = (wwn_t *) (cthdr + 1); | ||
596 | /* | ||
597 | * check if it has actually changed | ||
598 | */ | ||
599 | if ((memcmp | ||
600 | ((void *)&bfa_fcs_port_get_fabric_name(port), gfn_resp, | ||
601 | sizeof(wwn_t)) != 0)) | ||
602 | bfa_fcs_fabric_set_fabric_name(port->fabric, *gfn_resp); | ||
603 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); | ||
604 | return; | ||
605 | } | ||
606 | |||
607 | bfa_trc(port->fcs, cthdr->reason_code); | ||
608 | bfa_trc(port->fcs, cthdr->exp_code); | ||
609 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
610 | } | ||
611 | |||
612 | /** | ||
613 | * ms_pvt MS local functions | ||
614 | */ | ||
615 | |||
616 | static void | ||
617 | bfa_fcs_port_ms_send_plogi(void *ms_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
618 | { | ||
619 | struct bfa_fcs_port_ms_s *ms = ms_cbarg; | ||
620 | struct bfa_fcs_port_s *port = ms->port; | ||
621 | struct fchs_s fchs; | ||
622 | int len; | ||
623 | struct bfa_fcxp_s *fcxp; | ||
624 | |||
625 | bfa_trc(port->fcs, port->pid); | ||
626 | |||
627 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
628 | if (!fcxp) { | ||
629 | port->stats.ms_plogi_alloc_wait++; | ||
630 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ms->fcxp_wqe, | ||
631 | bfa_fcs_port_ms_send_plogi, ms); | ||
632 | return; | ||
633 | } | ||
634 | ms->fcxp = fcxp; | ||
635 | |||
636 | len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
637 | bfa_os_hton3b(FC_MGMT_SERVER), | ||
638 | bfa_fcs_port_get_fcid(port), 0, | ||
639 | port->port_cfg.pwwn, port->port_cfg.nwwn, | ||
640 | bfa_pport_get_maxfrsize(port->fcs->bfa)); | ||
641 | |||
642 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
643 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ms_plogi_response, | ||
644 | (void *)ms, FC_MAX_PDUSZ, FC_RA_TOV); | ||
645 | |||
646 | port->stats.ms_plogi_sent++; | ||
647 | bfa_sm_send_event(ms, MSSM_EVENT_FCXP_SENT); | ||
648 | } | ||
649 | |||
650 | static void | ||
651 | bfa_fcs_port_ms_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
652 | void *cbarg, bfa_status_t req_status, | ||
653 | u32 rsp_len, u32 resid_len, | ||
654 | struct fchs_s *rsp_fchs) | ||
655 | { | ||
656 | struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)cbarg; | ||
657 | |||
658 | struct bfa_fcs_port_s *port = ms->port; | ||
659 | struct fc_els_cmd_s *els_cmd; | ||
660 | struct fc_ls_rjt_s *ls_rjt; | ||
661 | |||
662 | bfa_trc(port->fcs, req_status); | ||
663 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
664 | |||
665 | /* | ||
666 | * Sanity Checks | ||
667 | */ | ||
668 | if (req_status != BFA_STATUS_OK) { | ||
669 | port->stats.ms_plogi_rsp_err++; | ||
670 | bfa_trc(port->fcs, req_status); | ||
671 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
672 | return; | ||
673 | } | ||
674 | |||
675 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
676 | |||
677 | switch (els_cmd->els_code) { | ||
678 | |||
679 | case FC_ELS_ACC: | ||
680 | if (rsp_len < sizeof(struct fc_logi_s)) { | ||
681 | bfa_trc(port->fcs, rsp_len); | ||
682 | port->stats.ms_plogi_acc_err++; | ||
683 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
684 | break; | ||
685 | } | ||
686 | port->stats.ms_plogi_accepts++; | ||
687 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_OK); | ||
688 | break; | ||
689 | |||
690 | case FC_ELS_LS_RJT: | ||
691 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
692 | |||
693 | bfa_trc(port->fcs, ls_rjt->reason_code); | ||
694 | bfa_trc(port->fcs, ls_rjt->reason_code_expl); | ||
695 | |||
696 | port->stats.ms_rejects++; | ||
697 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
698 | break; | ||
699 | |||
700 | default: | ||
701 | port->stats.ms_plogi_unknown_rsp++; | ||
702 | bfa_trc(port->fcs, els_cmd->els_code); | ||
703 | bfa_sm_send_event(ms, MSSM_EVENT_RSP_ERROR); | ||
704 | } | ||
705 | } | ||
706 | |||
707 | static void | ||
708 | bfa_fcs_port_ms_timeout(void *arg) | ||
709 | { | ||
710 | struct bfa_fcs_port_ms_s *ms = (struct bfa_fcs_port_ms_s *)arg; | ||
711 | |||
712 | ms->port->stats.ms_timeouts++; | ||
713 | bfa_sm_send_event(ms, MSSM_EVENT_TIMEOUT); | ||
714 | } | ||
715 | |||
716 | |||
717 | void | ||
718 | bfa_fcs_port_ms_init(struct bfa_fcs_port_s *port) | ||
719 | { | ||
720 | struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | ||
721 | |||
722 | ms->port = port; | ||
723 | bfa_sm_set_state(ms, bfa_fcs_port_ms_sm_offline); | ||
724 | |||
725 | /* | ||
726 | * Invoke init routines of sub modules. | ||
727 | */ | ||
728 | bfa_fcs_port_fdmi_init(ms); | ||
729 | } | ||
730 | |||
731 | void | ||
732 | bfa_fcs_port_ms_offline(struct bfa_fcs_port_s *port) | ||
733 | { | ||
734 | struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | ||
735 | |||
736 | ms->port = port; | ||
737 | bfa_sm_send_event(ms, MSSM_EVENT_PORT_OFFLINE); | ||
738 | } | ||
739 | |||
740 | void | ||
741 | bfa_fcs_port_ms_online(struct bfa_fcs_port_s *port) | ||
742 | { | ||
743 | struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | ||
744 | |||
745 | ms->port = port; | ||
746 | bfa_sm_send_event(ms, MSSM_EVENT_PORT_ONLINE); | ||
747 | } | ||
748 | |||
749 | void | ||
750 | bfa_fcs_port_ms_fabric_rscn(struct bfa_fcs_port_s *port) | ||
751 | { | ||
752 | struct bfa_fcs_port_ms_s *ms = BFA_FCS_GET_MS_FROM_PORT(port); | ||
753 | |||
754 | /* | ||
755 | * @todo. Handle this only when in Online state | ||
756 | */ | ||
757 | if (bfa_sm_cmp_state(ms, bfa_fcs_port_ms_sm_online)) | ||
758 | bfa_sm_send_event(ms, MSSM_EVENT_PORT_FABRIC_RSCN); | ||
759 | } | ||
diff --git a/drivers/scsi/bfa/n2n.c b/drivers/scsi/bfa/n2n.c new file mode 100644 index 000000000000..735456824346 --- /dev/null +++ b/drivers/scsi/bfa/n2n.c | |||
@@ -0,0 +1,105 @@ | |||
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 | * n2n.c n2n implementation. | ||
20 | */ | ||
21 | #include <bfa.h> | ||
22 | #include <bfa_svc.h> | ||
23 | #include "fcs_lport.h" | ||
24 | #include "fcs_rport.h" | ||
25 | #include "fcs_trcmod.h" | ||
26 | #include "lport_priv.h" | ||
27 | |||
28 | BFA_TRC_FILE(FCS, N2N); | ||
29 | |||
30 | /** | ||
31 | * Called by fcs/port to initialize N2N topology. | ||
32 | */ | ||
33 | void | ||
34 | bfa_fcs_port_n2n_init(struct bfa_fcs_port_s *port) | ||
35 | { | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * Called by fcs/port to notify transition to online state. | ||
40 | */ | ||
41 | void | ||
42 | bfa_fcs_port_n2n_online(struct bfa_fcs_port_s *port) | ||
43 | { | ||
44 | struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n; | ||
45 | struct bfa_port_cfg_s *pcfg = &port->port_cfg; | ||
46 | struct bfa_fcs_rport_s *rport; | ||
47 | |||
48 | bfa_trc(port->fcs, pcfg->pwwn); | ||
49 | |||
50 | /* | ||
51 | * If our PWWN is > than that of the r-port, we have to initiate PLOGI | ||
52 | * and assign an Address. if not, we need to wait for its PLOGI. | ||
53 | * | ||
54 | * If our PWWN is < than that of the remote port, it will send a PLOGI | ||
55 | * with the PIDs assigned. The rport state machine take care of this | ||
56 | * incoming PLOGI. | ||
57 | */ | ||
58 | if (memcmp | ||
59 | ((void *)&pcfg->pwwn, (void *)&n2n_port->rem_port_wwn, | ||
60 | sizeof(wwn_t)) > 0) { | ||
61 | port->pid = N2N_LOCAL_PID; | ||
62 | /** | ||
63 | * First, check if we know the device by pwwn. | ||
64 | */ | ||
65 | rport = bfa_fcs_port_get_rport_by_pwwn(port, | ||
66 | n2n_port->rem_port_wwn); | ||
67 | if (rport) { | ||
68 | bfa_trc(port->fcs, rport->pid); | ||
69 | bfa_trc(port->fcs, rport->pwwn); | ||
70 | rport->pid = N2N_REMOTE_PID; | ||
71 | bfa_fcs_rport_online(rport); | ||
72 | return; | ||
73 | } | ||
74 | |||
75 | /* | ||
76 | * In n2n there can be only one rport. Delete the old one whose | ||
77 | * pid should be zero, because it is offline. | ||
78 | */ | ||
79 | if (port->num_rports > 0) { | ||
80 | rport = bfa_fcs_port_get_rport_by_pid(port, 0); | ||
81 | bfa_assert(rport != NULL); | ||
82 | if (rport) { | ||
83 | bfa_trc(port->fcs, rport->pwwn); | ||
84 | bfa_fcs_rport_delete(rport); | ||
85 | } | ||
86 | } | ||
87 | bfa_fcs_rport_create(port, N2N_REMOTE_PID); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Called by fcs/port to notify transition to offline state. | ||
93 | */ | ||
94 | void | ||
95 | bfa_fcs_port_n2n_offline(struct bfa_fcs_port_s *port) | ||
96 | { | ||
97 | struct bfa_fcs_port_n2n_s *n2n_port = &port->port_topo.pn2n; | ||
98 | |||
99 | bfa_trc(port->fcs, port->pid); | ||
100 | port->pid = 0; | ||
101 | n2n_port->rem_port_wwn = 0; | ||
102 | n2n_port->reply_oxid = 0; | ||
103 | } | ||
104 | |||
105 | |||
diff --git a/drivers/scsi/bfa/ns.c b/drivers/scsi/bfa/ns.c new file mode 100644 index 000000000000..59fea99d67a4 --- /dev/null +++ b/drivers/scsi/bfa/ns.c | |||
@@ -0,0 +1,1243 @@ | |||
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 | * @page ns_sm_info VPORT NS State Machine | ||
20 | * | ||
21 | * @section ns_sm_interactions VPORT NS State Machine Interactions | ||
22 | * | ||
23 | * @section ns_sm VPORT NS State Machine | ||
24 | * img ns_sm.jpg | ||
25 | */ | ||
26 | #include <bfa.h> | ||
27 | #include <bfa_svc.h> | ||
28 | #include <bfa_iocfc.h> | ||
29 | #include "fcs_lport.h" | ||
30 | #include "fcs_rport.h" | ||
31 | #include "fcs_trcmod.h" | ||
32 | #include "fcs_fcxp.h" | ||
33 | #include "fcs.h" | ||
34 | #include "lport_priv.h" | ||
35 | |||
36 | BFA_TRC_FILE(FCS, NS); | ||
37 | |||
38 | /* | ||
39 | * forward declarations | ||
40 | */ | ||
41 | static void bfa_fcs_port_ns_send_plogi(void *ns_cbarg, | ||
42 | struct bfa_fcxp_s *fcxp_alloced); | ||
43 | static void bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg, | ||
44 | struct bfa_fcxp_s *fcxp_alloced); | ||
45 | static void bfa_fcs_port_ns_send_rft_id(void *ns_cbarg, | ||
46 | struct bfa_fcxp_s *fcxp_alloced); | ||
47 | static void bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, | ||
48 | struct bfa_fcxp_s *fcxp_alloced); | ||
49 | static void bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg, | ||
50 | struct bfa_fcxp_s *fcxp_alloced); | ||
51 | static void bfa_fcs_port_ns_timeout(void *arg); | ||
52 | static void bfa_fcs_port_ns_plogi_response(void *fcsarg, | ||
53 | struct bfa_fcxp_s *fcxp, | ||
54 | void *cbarg, | ||
55 | bfa_status_t req_status, | ||
56 | u32 rsp_len, | ||
57 | u32 resid_len, | ||
58 | struct fchs_s *rsp_fchs); | ||
59 | static void bfa_fcs_port_ns_rspn_id_response(void *fcsarg, | ||
60 | struct bfa_fcxp_s *fcxp, | ||
61 | void *cbarg, | ||
62 | bfa_status_t req_status, | ||
63 | u32 rsp_len, | ||
64 | u32 resid_len, | ||
65 | struct fchs_s *rsp_fchs); | ||
66 | static void bfa_fcs_port_ns_rft_id_response(void *fcsarg, | ||
67 | struct bfa_fcxp_s *fcxp, | ||
68 | void *cbarg, | ||
69 | bfa_status_t req_status, | ||
70 | u32 rsp_len, | ||
71 | u32 resid_len, | ||
72 | struct fchs_s *rsp_fchs); | ||
73 | static void bfa_fcs_port_ns_rff_id_response(void *fcsarg, | ||
74 | struct bfa_fcxp_s *fcxp, | ||
75 | void *cbarg, | ||
76 | bfa_status_t req_status, | ||
77 | u32 rsp_len, | ||
78 | u32 resid_len, | ||
79 | struct fchs_s *rsp_fchs); | ||
80 | static void bfa_fcs_port_ns_gid_ft_response(void *fcsarg, | ||
81 | struct bfa_fcxp_s *fcxp, | ||
82 | void *cbarg, | ||
83 | bfa_status_t req_status, | ||
84 | u32 rsp_len, | ||
85 | u32 resid_len, | ||
86 | struct fchs_s *rsp_fchs); | ||
87 | static void bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port, | ||
88 | u32 *pid_buf, | ||
89 | u32 n_pids); | ||
90 | |||
91 | static void bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port); | ||
92 | /** | ||
93 | * fcs_ns_sm FCS nameserver interface state machine | ||
94 | */ | ||
95 | |||
96 | /** | ||
97 | * VPort NS State Machine events | ||
98 | */ | ||
99 | enum vport_ns_event { | ||
100 | NSSM_EVENT_PORT_ONLINE = 1, | ||
101 | NSSM_EVENT_PORT_OFFLINE = 2, | ||
102 | NSSM_EVENT_PLOGI_SENT = 3, | ||
103 | NSSM_EVENT_RSP_OK = 4, | ||
104 | NSSM_EVENT_RSP_ERROR = 5, | ||
105 | NSSM_EVENT_TIMEOUT = 6, | ||
106 | NSSM_EVENT_NS_QUERY = 7, | ||
107 | NSSM_EVENT_RSPNID_SENT = 8, | ||
108 | NSSM_EVENT_RFTID_SENT = 9, | ||
109 | NSSM_EVENT_RFFID_SENT = 10, | ||
110 | NSSM_EVENT_GIDFT_SENT = 11, | ||
111 | }; | ||
112 | |||
113 | static void bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns, | ||
114 | enum vport_ns_event event); | ||
115 | static void bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns, | ||
116 | enum vport_ns_event event); | ||
117 | static void bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns, | ||
118 | enum vport_ns_event event); | ||
119 | static void bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns, | ||
120 | enum vport_ns_event event); | ||
121 | static void bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns, | ||
122 | enum vport_ns_event event); | ||
123 | static void bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns, | ||
124 | enum vport_ns_event event); | ||
125 | static void bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns, | ||
126 | enum vport_ns_event event); | ||
127 | static void bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns, | ||
128 | enum vport_ns_event event); | ||
129 | static void bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns, | ||
130 | enum vport_ns_event event); | ||
131 | static void bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns, | ||
132 | enum vport_ns_event event); | ||
133 | static void bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns, | ||
134 | enum vport_ns_event event); | ||
135 | static void bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns, | ||
136 | enum vport_ns_event event); | ||
137 | static void bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns, | ||
138 | enum vport_ns_event event); | ||
139 | static void bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns, | ||
140 | enum vport_ns_event event); | ||
141 | static void bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns, | ||
142 | enum vport_ns_event event); | ||
143 | static void bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns, | ||
144 | enum vport_ns_event event); | ||
145 | static void bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns, | ||
146 | enum vport_ns_event event); | ||
147 | /** | ||
148 | * Start in offline state - awaiting linkup | ||
149 | */ | ||
150 | static void | ||
151 | bfa_fcs_port_ns_sm_offline(struct bfa_fcs_port_ns_s *ns, | ||
152 | enum vport_ns_event event) | ||
153 | { | ||
154 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
155 | bfa_trc(ns->port->fcs, event); | ||
156 | |||
157 | switch (event) { | ||
158 | case NSSM_EVENT_PORT_ONLINE: | ||
159 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending); | ||
160 | bfa_fcs_port_ns_send_plogi(ns, NULL); | ||
161 | break; | ||
162 | |||
163 | case NSSM_EVENT_PORT_OFFLINE: | ||
164 | break; | ||
165 | |||
166 | default: | ||
167 | bfa_assert(0); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static void | ||
172 | bfa_fcs_port_ns_sm_plogi_sending(struct bfa_fcs_port_ns_s *ns, | ||
173 | enum vport_ns_event event) | ||
174 | { | ||
175 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
176 | bfa_trc(ns->port->fcs, event); | ||
177 | |||
178 | switch (event) { | ||
179 | case NSSM_EVENT_PLOGI_SENT: | ||
180 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi); | ||
181 | break; | ||
182 | |||
183 | case NSSM_EVENT_PORT_OFFLINE: | ||
184 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
185 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | ||
186 | &ns->fcxp_wqe); | ||
187 | break; | ||
188 | |||
189 | default: | ||
190 | bfa_assert(0); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static void | ||
195 | bfa_fcs_port_ns_sm_plogi(struct bfa_fcs_port_ns_s *ns, | ||
196 | enum vport_ns_event event) | ||
197 | { | ||
198 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
199 | bfa_trc(ns->port->fcs, event); | ||
200 | |||
201 | switch (event) { | ||
202 | case NSSM_EVENT_RSP_ERROR: | ||
203 | /* | ||
204 | * Start timer for a delayed retry | ||
205 | */ | ||
206 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_retry); | ||
207 | ns->port->stats.ns_retries++; | ||
208 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, | ||
209 | bfa_fcs_port_ns_timeout, ns, | ||
210 | BFA_FCS_RETRY_TIMEOUT); | ||
211 | break; | ||
212 | |||
213 | case NSSM_EVENT_RSP_OK: | ||
214 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id); | ||
215 | bfa_fcs_port_ns_send_rspn_id(ns, NULL); | ||
216 | break; | ||
217 | |||
218 | case NSSM_EVENT_PORT_OFFLINE: | ||
219 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
220 | bfa_fcxp_discard(ns->fcxp); | ||
221 | break; | ||
222 | |||
223 | default: | ||
224 | bfa_assert(0); | ||
225 | } | ||
226 | } | ||
227 | |||
228 | static void | ||
229 | bfa_fcs_port_ns_sm_plogi_retry(struct bfa_fcs_port_ns_s *ns, | ||
230 | enum vport_ns_event event) | ||
231 | { | ||
232 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
233 | bfa_trc(ns->port->fcs, event); | ||
234 | |||
235 | switch (event) { | ||
236 | case NSSM_EVENT_TIMEOUT: | ||
237 | /* | ||
238 | * Retry Timer Expired. Re-send | ||
239 | */ | ||
240 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_plogi_sending); | ||
241 | bfa_fcs_port_ns_send_plogi(ns, NULL); | ||
242 | break; | ||
243 | |||
244 | case NSSM_EVENT_PORT_OFFLINE: | ||
245 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
246 | bfa_timer_stop(&ns->timer); | ||
247 | break; | ||
248 | |||
249 | default: | ||
250 | bfa_assert(0); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | static void | ||
255 | bfa_fcs_port_ns_sm_sending_rspn_id(struct bfa_fcs_port_ns_s *ns, | ||
256 | enum vport_ns_event event) | ||
257 | { | ||
258 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
259 | bfa_trc(ns->port->fcs, event); | ||
260 | |||
261 | switch (event) { | ||
262 | case NSSM_EVENT_RSPNID_SENT: | ||
263 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id); | ||
264 | break; | ||
265 | |||
266 | case NSSM_EVENT_PORT_OFFLINE: | ||
267 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
268 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | ||
269 | &ns->fcxp_wqe); | ||
270 | break; | ||
271 | |||
272 | default: | ||
273 | bfa_assert(0); | ||
274 | } | ||
275 | } | ||
276 | |||
277 | static void | ||
278 | bfa_fcs_port_ns_sm_rspn_id(struct bfa_fcs_port_ns_s *ns, | ||
279 | enum vport_ns_event event) | ||
280 | { | ||
281 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
282 | bfa_trc(ns->port->fcs, event); | ||
283 | |||
284 | switch (event) { | ||
285 | case NSSM_EVENT_RSP_ERROR: | ||
286 | /* | ||
287 | * Start timer for a delayed retry | ||
288 | */ | ||
289 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rspn_id_retry); | ||
290 | ns->port->stats.ns_retries++; | ||
291 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, | ||
292 | bfa_fcs_port_ns_timeout, ns, | ||
293 | BFA_FCS_RETRY_TIMEOUT); | ||
294 | break; | ||
295 | |||
296 | case NSSM_EVENT_RSP_OK: | ||
297 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id); | ||
298 | bfa_fcs_port_ns_send_rft_id(ns, NULL); | ||
299 | break; | ||
300 | |||
301 | case NSSM_EVENT_PORT_OFFLINE: | ||
302 | bfa_fcxp_discard(ns->fcxp); | ||
303 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
304 | break; | ||
305 | |||
306 | default: | ||
307 | bfa_assert(0); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | static void | ||
312 | bfa_fcs_port_ns_sm_rspn_id_retry(struct bfa_fcs_port_ns_s *ns, | ||
313 | enum vport_ns_event event) | ||
314 | { | ||
315 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
316 | bfa_trc(ns->port->fcs, event); | ||
317 | |||
318 | switch (event) { | ||
319 | case NSSM_EVENT_TIMEOUT: | ||
320 | /* | ||
321 | * Retry Timer Expired. Re-send | ||
322 | */ | ||
323 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rspn_id); | ||
324 | bfa_fcs_port_ns_send_rspn_id(ns, NULL); | ||
325 | break; | ||
326 | |||
327 | case NSSM_EVENT_PORT_OFFLINE: | ||
328 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
329 | bfa_timer_stop(&ns->timer); | ||
330 | break; | ||
331 | |||
332 | default: | ||
333 | bfa_assert(0); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | static void | ||
338 | bfa_fcs_port_ns_sm_sending_rft_id(struct bfa_fcs_port_ns_s *ns, | ||
339 | enum vport_ns_event event) | ||
340 | { | ||
341 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
342 | bfa_trc(ns->port->fcs, event); | ||
343 | |||
344 | switch (event) { | ||
345 | case NSSM_EVENT_RFTID_SENT: | ||
346 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id); | ||
347 | break; | ||
348 | |||
349 | case NSSM_EVENT_PORT_OFFLINE: | ||
350 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
351 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | ||
352 | &ns->fcxp_wqe); | ||
353 | break; | ||
354 | |||
355 | default: | ||
356 | bfa_assert(0); | ||
357 | } | ||
358 | } | ||
359 | |||
360 | static void | ||
361 | bfa_fcs_port_ns_sm_rft_id(struct bfa_fcs_port_ns_s *ns, | ||
362 | enum vport_ns_event event) | ||
363 | { | ||
364 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
365 | bfa_trc(ns->port->fcs, event); | ||
366 | |||
367 | switch (event) { | ||
368 | case NSSM_EVENT_RSP_OK: | ||
369 | /* | ||
370 | * Now move to register FC4 Features | ||
371 | */ | ||
372 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id); | ||
373 | bfa_fcs_port_ns_send_rff_id(ns, NULL); | ||
374 | break; | ||
375 | |||
376 | case NSSM_EVENT_RSP_ERROR: | ||
377 | /* | ||
378 | * Start timer for a delayed retry | ||
379 | */ | ||
380 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rft_id_retry); | ||
381 | ns->port->stats.ns_retries++; | ||
382 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, | ||
383 | bfa_fcs_port_ns_timeout, ns, | ||
384 | BFA_FCS_RETRY_TIMEOUT); | ||
385 | break; | ||
386 | |||
387 | case NSSM_EVENT_PORT_OFFLINE: | ||
388 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
389 | bfa_fcxp_discard(ns->fcxp); | ||
390 | break; | ||
391 | |||
392 | default: | ||
393 | bfa_assert(0); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | static void | ||
398 | bfa_fcs_port_ns_sm_rft_id_retry(struct bfa_fcs_port_ns_s *ns, | ||
399 | enum vport_ns_event event) | ||
400 | { | ||
401 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
402 | bfa_trc(ns->port->fcs, event); | ||
403 | |||
404 | switch (event) { | ||
405 | case NSSM_EVENT_TIMEOUT: | ||
406 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rft_id); | ||
407 | bfa_fcs_port_ns_send_rft_id(ns, NULL); | ||
408 | break; | ||
409 | |||
410 | case NSSM_EVENT_PORT_OFFLINE: | ||
411 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
412 | bfa_timer_stop(&ns->timer); | ||
413 | break; | ||
414 | |||
415 | default: | ||
416 | bfa_assert(0); | ||
417 | } | ||
418 | } | ||
419 | |||
420 | static void | ||
421 | bfa_fcs_port_ns_sm_sending_rff_id(struct bfa_fcs_port_ns_s *ns, | ||
422 | enum vport_ns_event event) | ||
423 | { | ||
424 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
425 | bfa_trc(ns->port->fcs, event); | ||
426 | |||
427 | switch (event) { | ||
428 | case NSSM_EVENT_RFFID_SENT: | ||
429 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id); | ||
430 | break; | ||
431 | |||
432 | case NSSM_EVENT_PORT_OFFLINE: | ||
433 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
434 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | ||
435 | &ns->fcxp_wqe); | ||
436 | break; | ||
437 | |||
438 | default: | ||
439 | bfa_assert(0); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | static void | ||
444 | bfa_fcs_port_ns_sm_rff_id(struct bfa_fcs_port_ns_s *ns, | ||
445 | enum vport_ns_event event) | ||
446 | { | ||
447 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
448 | bfa_trc(ns->port->fcs, event); | ||
449 | |||
450 | switch (event) { | ||
451 | case NSSM_EVENT_RSP_OK: | ||
452 | |||
453 | /* | ||
454 | * If min cfg mode is enabled, we donot initiate rport | ||
455 | * discovery with the fabric. Instead, we will retrieve the | ||
456 | * boot targets from HAL/FW. | ||
457 | */ | ||
458 | if (__fcs_min_cfg(ns->port->fcs)) { | ||
459 | bfa_fcs_port_ns_boot_target_disc(ns->port); | ||
460 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online); | ||
461 | return; | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * If the port role is Initiator Mode issue NS query. | ||
466 | * If it is Target Mode, skip this and go to online. | ||
467 | */ | ||
468 | if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { | ||
469 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft); | ||
470 | bfa_fcs_port_ns_send_gid_ft(ns, NULL); | ||
471 | } else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) { | ||
472 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online); | ||
473 | } | ||
474 | /* | ||
475 | * kick off mgmt srvr state machine | ||
476 | */ | ||
477 | bfa_fcs_port_ms_online(ns->port); | ||
478 | break; | ||
479 | |||
480 | case NSSM_EVENT_RSP_ERROR: | ||
481 | /* | ||
482 | * Start timer for a delayed retry | ||
483 | */ | ||
484 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_rff_id_retry); | ||
485 | ns->port->stats.ns_retries++; | ||
486 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, | ||
487 | bfa_fcs_port_ns_timeout, ns, | ||
488 | BFA_FCS_RETRY_TIMEOUT); | ||
489 | break; | ||
490 | |||
491 | case NSSM_EVENT_PORT_OFFLINE: | ||
492 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
493 | bfa_fcxp_discard(ns->fcxp); | ||
494 | break; | ||
495 | |||
496 | default: | ||
497 | bfa_assert(0); | ||
498 | } | ||
499 | } | ||
500 | |||
501 | static void | ||
502 | bfa_fcs_port_ns_sm_rff_id_retry(struct bfa_fcs_port_ns_s *ns, | ||
503 | enum vport_ns_event event) | ||
504 | { | ||
505 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
506 | bfa_trc(ns->port->fcs, event); | ||
507 | |||
508 | switch (event) { | ||
509 | case NSSM_EVENT_TIMEOUT: | ||
510 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_rff_id); | ||
511 | bfa_fcs_port_ns_send_rff_id(ns, NULL); | ||
512 | break; | ||
513 | |||
514 | case NSSM_EVENT_PORT_OFFLINE: | ||
515 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
516 | bfa_timer_stop(&ns->timer); | ||
517 | break; | ||
518 | |||
519 | default: | ||
520 | bfa_assert(0); | ||
521 | } | ||
522 | } | ||
523 | static void | ||
524 | bfa_fcs_port_ns_sm_sending_gid_ft(struct bfa_fcs_port_ns_s *ns, | ||
525 | enum vport_ns_event event) | ||
526 | { | ||
527 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
528 | bfa_trc(ns->port->fcs, event); | ||
529 | |||
530 | switch (event) { | ||
531 | case NSSM_EVENT_GIDFT_SENT: | ||
532 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft); | ||
533 | break; | ||
534 | |||
535 | case NSSM_EVENT_PORT_OFFLINE: | ||
536 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
537 | bfa_fcxp_walloc_cancel(BFA_FCS_GET_HAL_FROM_PORT(ns->port), | ||
538 | &ns->fcxp_wqe); | ||
539 | break; | ||
540 | |||
541 | default: | ||
542 | bfa_assert(0); | ||
543 | } | ||
544 | } | ||
545 | |||
546 | static void | ||
547 | bfa_fcs_port_ns_sm_gid_ft(struct bfa_fcs_port_ns_s *ns, | ||
548 | enum vport_ns_event event) | ||
549 | { | ||
550 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
551 | bfa_trc(ns->port->fcs, event); | ||
552 | |||
553 | switch (event) { | ||
554 | case NSSM_EVENT_RSP_OK: | ||
555 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_online); | ||
556 | break; | ||
557 | |||
558 | case NSSM_EVENT_RSP_ERROR: | ||
559 | /* | ||
560 | * TBD: for certain reject codes, we don't need to retry | ||
561 | */ | ||
562 | /* | ||
563 | * Start timer for a delayed retry | ||
564 | */ | ||
565 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_gid_ft_retry); | ||
566 | ns->port->stats.ns_retries++; | ||
567 | bfa_timer_start(BFA_FCS_GET_HAL_FROM_PORT(ns->port), &ns->timer, | ||
568 | bfa_fcs_port_ns_timeout, ns, | ||
569 | BFA_FCS_RETRY_TIMEOUT); | ||
570 | break; | ||
571 | |||
572 | case NSSM_EVENT_PORT_OFFLINE: | ||
573 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
574 | bfa_fcxp_discard(ns->fcxp); | ||
575 | break; | ||
576 | |||
577 | default: | ||
578 | bfa_assert(0); | ||
579 | } | ||
580 | } | ||
581 | |||
582 | static void | ||
583 | bfa_fcs_port_ns_sm_gid_ft_retry(struct bfa_fcs_port_ns_s *ns, | ||
584 | enum vport_ns_event event) | ||
585 | { | ||
586 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
587 | bfa_trc(ns->port->fcs, event); | ||
588 | |||
589 | switch (event) { | ||
590 | case NSSM_EVENT_TIMEOUT: | ||
591 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft); | ||
592 | bfa_fcs_port_ns_send_gid_ft(ns, NULL); | ||
593 | break; | ||
594 | |||
595 | case NSSM_EVENT_PORT_OFFLINE: | ||
596 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
597 | bfa_timer_stop(&ns->timer); | ||
598 | break; | ||
599 | |||
600 | default: | ||
601 | bfa_assert(0); | ||
602 | } | ||
603 | } | ||
604 | |||
605 | static void | ||
606 | bfa_fcs_port_ns_sm_online(struct bfa_fcs_port_ns_s *ns, | ||
607 | enum vport_ns_event event) | ||
608 | { | ||
609 | bfa_trc(ns->port->fcs, ns->port->port_cfg.pwwn); | ||
610 | bfa_trc(ns->port->fcs, event); | ||
611 | |||
612 | switch (event) { | ||
613 | case NSSM_EVENT_PORT_OFFLINE: | ||
614 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
615 | break; | ||
616 | |||
617 | case NSSM_EVENT_NS_QUERY: | ||
618 | /* | ||
619 | * If the port role is Initiator Mode issue NS query. | ||
620 | * If it is Target Mode, skip this and go to online. | ||
621 | */ | ||
622 | if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { | ||
623 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_sending_gid_ft); | ||
624 | bfa_fcs_port_ns_send_gid_ft(ns, NULL); | ||
625 | }; | ||
626 | break; | ||
627 | |||
628 | default: | ||
629 | bfa_assert(0); | ||
630 | } | ||
631 | } | ||
632 | |||
633 | |||
634 | |||
635 | /** | ||
636 | * ns_pvt Nameserver local functions | ||
637 | */ | ||
638 | |||
639 | static void | ||
640 | bfa_fcs_port_ns_send_plogi(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
641 | { | ||
642 | struct bfa_fcs_port_ns_s *ns = ns_cbarg; | ||
643 | struct bfa_fcs_port_s *port = ns->port; | ||
644 | struct fchs_s fchs; | ||
645 | int len; | ||
646 | struct bfa_fcxp_s *fcxp; | ||
647 | |||
648 | bfa_trc(port->fcs, port->pid); | ||
649 | |||
650 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
651 | if (!fcxp) { | ||
652 | port->stats.ns_plogi_alloc_wait++; | ||
653 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | ||
654 | bfa_fcs_port_ns_send_plogi, ns); | ||
655 | return; | ||
656 | } | ||
657 | ns->fcxp = fcxp; | ||
658 | |||
659 | len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
660 | bfa_os_hton3b(FC_NAME_SERVER), | ||
661 | bfa_fcs_port_get_fcid(port), 0, | ||
662 | port->port_cfg.pwwn, port->port_cfg.nwwn, | ||
663 | bfa_pport_get_maxfrsize(port->fcs->bfa)); | ||
664 | |||
665 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
666 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_plogi_response, | ||
667 | (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); | ||
668 | port->stats.ns_plogi_sent++; | ||
669 | |||
670 | bfa_sm_send_event(ns, NSSM_EVENT_PLOGI_SENT); | ||
671 | } | ||
672 | |||
673 | static void | ||
674 | bfa_fcs_port_ns_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
675 | void *cbarg, bfa_status_t req_status, | ||
676 | u32 rsp_len, u32 resid_len, | ||
677 | struct fchs_s *rsp_fchs) | ||
678 | { | ||
679 | struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg; | ||
680 | struct bfa_fcs_port_s *port = ns->port; | ||
681 | /* struct fc_logi_s *plogi_resp; */ | ||
682 | struct fc_els_cmd_s *els_cmd; | ||
683 | struct fc_ls_rjt_s *ls_rjt; | ||
684 | |||
685 | bfa_trc(port->fcs, req_status); | ||
686 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
687 | |||
688 | /* | ||
689 | * Sanity Checks | ||
690 | */ | ||
691 | if (req_status != BFA_STATUS_OK) { | ||
692 | bfa_trc(port->fcs, req_status); | ||
693 | port->stats.ns_plogi_rsp_err++; | ||
694 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
695 | return; | ||
696 | } | ||
697 | |||
698 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
699 | |||
700 | switch (els_cmd->els_code) { | ||
701 | |||
702 | case FC_ELS_ACC: | ||
703 | if (rsp_len < sizeof(struct fc_logi_s)) { | ||
704 | bfa_trc(port->fcs, rsp_len); | ||
705 | port->stats.ns_plogi_acc_err++; | ||
706 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
707 | break; | ||
708 | } | ||
709 | port->stats.ns_plogi_accepts++; | ||
710 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | ||
711 | break; | ||
712 | |||
713 | case FC_ELS_LS_RJT: | ||
714 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
715 | |||
716 | bfa_trc(port->fcs, ls_rjt->reason_code); | ||
717 | bfa_trc(port->fcs, ls_rjt->reason_code_expl); | ||
718 | |||
719 | port->stats.ns_rejects++; | ||
720 | |||
721 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
722 | break; | ||
723 | |||
724 | default: | ||
725 | port->stats.ns_plogi_unknown_rsp++; | ||
726 | bfa_trc(port->fcs, els_cmd->els_code); | ||
727 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
728 | } | ||
729 | } | ||
730 | |||
731 | /** | ||
732 | * Register the symbolic port name. | ||
733 | */ | ||
734 | static void | ||
735 | bfa_fcs_port_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
736 | { | ||
737 | struct bfa_fcs_port_ns_s *ns = ns_cbarg; | ||
738 | struct bfa_fcs_port_s *port = ns->port; | ||
739 | struct fchs_s fchs; | ||
740 | int len; | ||
741 | struct bfa_fcxp_s *fcxp; | ||
742 | u8 symbl[256]; | ||
743 | u8 *psymbl = &symbl[0]; | ||
744 | |||
745 | bfa_os_memset(symbl, 0, sizeof(symbl)); | ||
746 | |||
747 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
748 | |||
749 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
750 | if (!fcxp) { | ||
751 | port->stats.ns_rspnid_alloc_wait++; | ||
752 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | ||
753 | bfa_fcs_port_ns_send_rspn_id, ns); | ||
754 | return; | ||
755 | } | ||
756 | ns->fcxp = fcxp; | ||
757 | |||
758 | /* | ||
759 | * for V-Port, form a Port Symbolic Name | ||
760 | */ | ||
761 | if (port->vport) { | ||
762 | /**For Vports, | ||
763 | * we append the vport's port symbolic name to that of the base port. | ||
764 | */ | ||
765 | |||
766 | strncpy((char *)psymbl, | ||
767 | (char *) | ||
768 | &(bfa_fcs_port_get_psym_name | ||
769 | (bfa_fcs_get_base_port(port->fcs))), | ||
770 | strlen((char *) | ||
771 | &bfa_fcs_port_get_psym_name(bfa_fcs_get_base_port | ||
772 | (port->fcs)))); | ||
773 | |||
774 | /* | ||
775 | * Ensure we have a null terminating string. | ||
776 | */ | ||
777 | ((char *) | ||
778 | psymbl)[strlen((char *) | ||
779 | &bfa_fcs_port_get_psym_name | ||
780 | (bfa_fcs_get_base_port(port->fcs)))] = 0; | ||
781 | |||
782 | strncat((char *)psymbl, | ||
783 | (char *)&(bfa_fcs_port_get_psym_name(port)), | ||
784 | strlen((char *)&bfa_fcs_port_get_psym_name(port))); | ||
785 | } else { | ||
786 | psymbl = (u8 *) &(bfa_fcs_port_get_psym_name(port)); | ||
787 | } | ||
788 | |||
789 | len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
790 | bfa_fcs_port_get_fcid(port), 0, psymbl); | ||
791 | |||
792 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
793 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rspn_id_response, | ||
794 | (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); | ||
795 | |||
796 | port->stats.ns_rspnid_sent++; | ||
797 | |||
798 | bfa_sm_send_event(ns, NSSM_EVENT_RSPNID_SENT); | ||
799 | } | ||
800 | |||
801 | static void | ||
802 | bfa_fcs_port_ns_rspn_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
803 | void *cbarg, bfa_status_t req_status, | ||
804 | u32 rsp_len, u32 resid_len, | ||
805 | struct fchs_s *rsp_fchs) | ||
806 | { | ||
807 | struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg; | ||
808 | struct bfa_fcs_port_s *port = ns->port; | ||
809 | struct ct_hdr_s *cthdr = NULL; | ||
810 | |||
811 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
812 | |||
813 | /* | ||
814 | * Sanity Checks | ||
815 | */ | ||
816 | if (req_status != BFA_STATUS_OK) { | ||
817 | bfa_trc(port->fcs, req_status); | ||
818 | port->stats.ns_rspnid_rsp_err++; | ||
819 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
820 | return; | ||
821 | } | ||
822 | |||
823 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
824 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
825 | |||
826 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
827 | port->stats.ns_rspnid_accepts++; | ||
828 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | ||
829 | return; | ||
830 | } | ||
831 | |||
832 | port->stats.ns_rspnid_rejects++; | ||
833 | bfa_trc(port->fcs, cthdr->reason_code); | ||
834 | bfa_trc(port->fcs, cthdr->exp_code); | ||
835 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
836 | } | ||
837 | |||
838 | /** | ||
839 | * Register FC4-Types | ||
840 | * TBD, Need to retrieve this from the OS driver, in case IPFC is enabled ? | ||
841 | */ | ||
842 | static void | ||
843 | bfa_fcs_port_ns_send_rft_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
844 | { | ||
845 | struct bfa_fcs_port_ns_s *ns = ns_cbarg; | ||
846 | struct bfa_fcs_port_s *port = ns->port; | ||
847 | struct fchs_s fchs; | ||
848 | int len; | ||
849 | struct bfa_fcxp_s *fcxp; | ||
850 | |||
851 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
852 | |||
853 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
854 | if (!fcxp) { | ||
855 | port->stats.ns_rftid_alloc_wait++; | ||
856 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | ||
857 | bfa_fcs_port_ns_send_rft_id, ns); | ||
858 | return; | ||
859 | } | ||
860 | ns->fcxp = fcxp; | ||
861 | |||
862 | len = fc_rftid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
863 | bfa_fcs_port_get_fcid(port), 0, | ||
864 | port->port_cfg.roles); | ||
865 | |||
866 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
867 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rft_id_response, | ||
868 | (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); | ||
869 | |||
870 | port->stats.ns_rftid_sent++; | ||
871 | bfa_sm_send_event(ns, NSSM_EVENT_RFTID_SENT); | ||
872 | } | ||
873 | |||
874 | static void | ||
875 | bfa_fcs_port_ns_rft_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
876 | void *cbarg, bfa_status_t req_status, | ||
877 | u32 rsp_len, u32 resid_len, | ||
878 | struct fchs_s *rsp_fchs) | ||
879 | { | ||
880 | struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg; | ||
881 | struct bfa_fcs_port_s *port = ns->port; | ||
882 | struct ct_hdr_s *cthdr = NULL; | ||
883 | |||
884 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
885 | |||
886 | /* | ||
887 | * Sanity Checks | ||
888 | */ | ||
889 | if (req_status != BFA_STATUS_OK) { | ||
890 | bfa_trc(port->fcs, req_status); | ||
891 | port->stats.ns_rftid_rsp_err++; | ||
892 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
893 | return; | ||
894 | } | ||
895 | |||
896 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
897 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
898 | |||
899 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
900 | port->stats.ns_rftid_accepts++; | ||
901 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | ||
902 | return; | ||
903 | } | ||
904 | |||
905 | port->stats.ns_rftid_rejects++; | ||
906 | bfa_trc(port->fcs, cthdr->reason_code); | ||
907 | bfa_trc(port->fcs, cthdr->exp_code); | ||
908 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
909 | } | ||
910 | |||
911 | /** | ||
912 | * Register FC4-Features : Should be done after RFT_ID | ||
913 | */ | ||
914 | static void | ||
915 | bfa_fcs_port_ns_send_rff_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
916 | { | ||
917 | struct bfa_fcs_port_ns_s *ns = ns_cbarg; | ||
918 | struct bfa_fcs_port_s *port = ns->port; | ||
919 | struct fchs_s fchs; | ||
920 | int len; | ||
921 | struct bfa_fcxp_s *fcxp; | ||
922 | u8 fc4_ftrs = 0; | ||
923 | |||
924 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
925 | |||
926 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
927 | if (!fcxp) { | ||
928 | port->stats.ns_rffid_alloc_wait++; | ||
929 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | ||
930 | bfa_fcs_port_ns_send_rff_id, ns); | ||
931 | return; | ||
932 | } | ||
933 | ns->fcxp = fcxp; | ||
934 | |||
935 | if (BFA_FCS_VPORT_IS_INITIATOR_MODE(ns->port)) { | ||
936 | fc4_ftrs = FC_GS_FCP_FC4_FEATURE_INITIATOR; | ||
937 | } else if (BFA_FCS_VPORT_IS_TARGET_MODE(ns->port)) { | ||
938 | fc4_ftrs = FC_GS_FCP_FC4_FEATURE_TARGET; | ||
939 | } | ||
940 | |||
941 | len = fc_rffid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
942 | bfa_fcs_port_get_fcid(port), 0, FC_TYPE_FCP, | ||
943 | fc4_ftrs); | ||
944 | |||
945 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
946 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_rff_id_response, | ||
947 | (void *)ns, FC_MAX_PDUSZ, FC_RA_TOV); | ||
948 | |||
949 | port->stats.ns_rffid_sent++; | ||
950 | bfa_sm_send_event(ns, NSSM_EVENT_RFFID_SENT); | ||
951 | } | ||
952 | |||
953 | static void | ||
954 | bfa_fcs_port_ns_rff_id_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
955 | void *cbarg, bfa_status_t req_status, | ||
956 | u32 rsp_len, u32 resid_len, | ||
957 | struct fchs_s *rsp_fchs) | ||
958 | { | ||
959 | struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg; | ||
960 | struct bfa_fcs_port_s *port = ns->port; | ||
961 | struct ct_hdr_s *cthdr = NULL; | ||
962 | |||
963 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
964 | |||
965 | /* | ||
966 | * Sanity Checks | ||
967 | */ | ||
968 | if (req_status != BFA_STATUS_OK) { | ||
969 | bfa_trc(port->fcs, req_status); | ||
970 | port->stats.ns_rffid_rsp_err++; | ||
971 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
972 | return; | ||
973 | } | ||
974 | |||
975 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
976 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
977 | |||
978 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
979 | port->stats.ns_rffid_accepts++; | ||
980 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | ||
981 | return; | ||
982 | } | ||
983 | |||
984 | port->stats.ns_rffid_rejects++; | ||
985 | bfa_trc(port->fcs, cthdr->reason_code); | ||
986 | bfa_trc(port->fcs, cthdr->exp_code); | ||
987 | |||
988 | if (cthdr->reason_code == CT_RSN_NOT_SUPP) { | ||
989 | /* | ||
990 | * if this command is not supported, we don't retry | ||
991 | */ | ||
992 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | ||
993 | } else { | ||
994 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
995 | } | ||
996 | } | ||
997 | |||
998 | /** | ||
999 | * Query Fabric for FC4-Types Devices. | ||
1000 | * | ||
1001 | * TBD : Need to use a local (FCS private) response buffer, since the response | ||
1002 | * can be larger than 2K. | ||
1003 | */ | ||
1004 | static void | ||
1005 | bfa_fcs_port_ns_send_gid_ft(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
1006 | { | ||
1007 | struct bfa_fcs_port_ns_s *ns = ns_cbarg; | ||
1008 | struct bfa_fcs_port_s *port = ns->port; | ||
1009 | struct fchs_s fchs; | ||
1010 | int len; | ||
1011 | struct bfa_fcxp_s *fcxp; | ||
1012 | |||
1013 | bfa_trc(port->fcs, port->pid); | ||
1014 | |||
1015 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
1016 | if (!fcxp) { | ||
1017 | port->stats.ns_gidft_alloc_wait++; | ||
1018 | bfa_fcxp_alloc_wait(port->fcs->bfa, &ns->fcxp_wqe, | ||
1019 | bfa_fcs_port_ns_send_gid_ft, ns); | ||
1020 | return; | ||
1021 | } | ||
1022 | ns->fcxp = fcxp; | ||
1023 | |||
1024 | /* | ||
1025 | * This query is only initiated for FCP initiator mode. | ||
1026 | */ | ||
1027 | len = fc_gid_ft_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), ns->port->pid, | ||
1028 | FC_TYPE_FCP); | ||
1029 | |||
1030 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1031 | FC_CLASS_3, len, &fchs, bfa_fcs_port_ns_gid_ft_response, | ||
1032 | (void *)ns, bfa_fcxp_get_maxrsp(port->fcs->bfa), | ||
1033 | FC_RA_TOV); | ||
1034 | |||
1035 | port->stats.ns_gidft_sent++; | ||
1036 | |||
1037 | bfa_sm_send_event(ns, NSSM_EVENT_GIDFT_SENT); | ||
1038 | } | ||
1039 | |||
1040 | static void | ||
1041 | bfa_fcs_port_ns_gid_ft_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
1042 | void *cbarg, bfa_status_t req_status, | ||
1043 | u32 rsp_len, u32 resid_len, | ||
1044 | struct fchs_s *rsp_fchs) | ||
1045 | { | ||
1046 | struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)cbarg; | ||
1047 | struct bfa_fcs_port_s *port = ns->port; | ||
1048 | struct ct_hdr_s *cthdr = NULL; | ||
1049 | u32 n_pids; | ||
1050 | |||
1051 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
1052 | |||
1053 | /* | ||
1054 | * Sanity Checks | ||
1055 | */ | ||
1056 | if (req_status != BFA_STATUS_OK) { | ||
1057 | bfa_trc(port->fcs, req_status); | ||
1058 | port->stats.ns_gidft_rsp_err++; | ||
1059 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
1060 | return; | ||
1061 | } | ||
1062 | |||
1063 | if (resid_len != 0) { | ||
1064 | /* | ||
1065 | * TBD : we will need to allocate a larger buffer & retry the | ||
1066 | * command | ||
1067 | */ | ||
1068 | bfa_trc(port->fcs, rsp_len); | ||
1069 | bfa_trc(port->fcs, resid_len); | ||
1070 | return; | ||
1071 | } | ||
1072 | |||
1073 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
1074 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
1075 | |||
1076 | switch (cthdr->cmd_rsp_code) { | ||
1077 | |||
1078 | case CT_RSP_ACCEPT: | ||
1079 | |||
1080 | port->stats.ns_gidft_accepts++; | ||
1081 | n_pids = (fc_get_ctresp_pyld_len(rsp_len) / sizeof(u32)); | ||
1082 | bfa_trc(port->fcs, n_pids); | ||
1083 | bfa_fcs_port_ns_process_gidft_pids(port, | ||
1084 | (u32 *) (cthdr + 1), | ||
1085 | n_pids); | ||
1086 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | ||
1087 | break; | ||
1088 | |||
1089 | case CT_RSP_REJECT: | ||
1090 | |||
1091 | /* | ||
1092 | * Check the reason code & explanation. | ||
1093 | * There may not have been any FC4 devices in the fabric | ||
1094 | */ | ||
1095 | port->stats.ns_gidft_rejects++; | ||
1096 | bfa_trc(port->fcs, cthdr->reason_code); | ||
1097 | bfa_trc(port->fcs, cthdr->exp_code); | ||
1098 | |||
1099 | if ((cthdr->reason_code == CT_RSN_UNABLE_TO_PERF) | ||
1100 | && (cthdr->exp_code == CT_NS_EXP_FT_NOT_REG)) { | ||
1101 | |||
1102 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_OK); | ||
1103 | } else { | ||
1104 | /* | ||
1105 | * for all other errors, retry | ||
1106 | */ | ||
1107 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
1108 | } | ||
1109 | break; | ||
1110 | |||
1111 | default: | ||
1112 | port->stats.ns_gidft_unknown_rsp++; | ||
1113 | bfa_trc(port->fcs, cthdr->cmd_rsp_code); | ||
1114 | bfa_sm_send_event(ns, NSSM_EVENT_RSP_ERROR); | ||
1115 | } | ||
1116 | } | ||
1117 | |||
1118 | /** | ||
1119 | * This routine will be called by bfa_timer on timer timeouts. | ||
1120 | * | ||
1121 | * param[in] port - pointer to bfa_fcs_port_t. | ||
1122 | * | ||
1123 | * return | ||
1124 | * void | ||
1125 | * | ||
1126 | * Special Considerations: | ||
1127 | * | ||
1128 | * note | ||
1129 | */ | ||
1130 | static void | ||
1131 | bfa_fcs_port_ns_timeout(void *arg) | ||
1132 | { | ||
1133 | struct bfa_fcs_port_ns_s *ns = (struct bfa_fcs_port_ns_s *)arg; | ||
1134 | |||
1135 | ns->port->stats.ns_timeouts++; | ||
1136 | bfa_sm_send_event(ns, NSSM_EVENT_TIMEOUT); | ||
1137 | } | ||
1138 | |||
1139 | /* | ||
1140 | * Process the PID list in GID_FT response | ||
1141 | */ | ||
1142 | static void | ||
1143 | bfa_fcs_port_ns_process_gidft_pids(struct bfa_fcs_port_s *port, | ||
1144 | u32 *pid_buf, u32 n_pids) | ||
1145 | { | ||
1146 | struct fcgs_gidft_resp_s *gidft_entry; | ||
1147 | struct bfa_fcs_rport_s *rport; | ||
1148 | u32 ii; | ||
1149 | |||
1150 | for (ii = 0; ii < n_pids; ii++) { | ||
1151 | gidft_entry = (struct fcgs_gidft_resp_s *) &pid_buf[ii]; | ||
1152 | |||
1153 | if (gidft_entry->pid == port->pid) | ||
1154 | continue; | ||
1155 | |||
1156 | /* | ||
1157 | * Check if this rport already exists | ||
1158 | */ | ||
1159 | rport = bfa_fcs_port_get_rport_by_pid(port, gidft_entry->pid); | ||
1160 | if (rport == NULL) { | ||
1161 | /* | ||
1162 | * this is a new device. create rport | ||
1163 | */ | ||
1164 | rport = bfa_fcs_rport_create(port, gidft_entry->pid); | ||
1165 | } else { | ||
1166 | /* | ||
1167 | * this rport already exists | ||
1168 | */ | ||
1169 | bfa_fcs_rport_scn(rport); | ||
1170 | } | ||
1171 | |||
1172 | bfa_trc(port->fcs, gidft_entry->pid); | ||
1173 | |||
1174 | /* | ||
1175 | * if the last entry bit is set, bail out. | ||
1176 | */ | ||
1177 | if (gidft_entry->last) | ||
1178 | return; | ||
1179 | } | ||
1180 | } | ||
1181 | |||
1182 | /** | ||
1183 | * fcs_ns_public FCS nameserver public interfaces | ||
1184 | */ | ||
1185 | |||
1186 | /* | ||
1187 | * Functions called by port/fab. | ||
1188 | * These will send relevant Events to the ns state machine. | ||
1189 | */ | ||
1190 | void | ||
1191 | bfa_fcs_port_ns_init(struct bfa_fcs_port_s *port) | ||
1192 | { | ||
1193 | struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | ||
1194 | |||
1195 | ns->port = port; | ||
1196 | bfa_sm_set_state(ns, bfa_fcs_port_ns_sm_offline); | ||
1197 | } | ||
1198 | |||
1199 | void | ||
1200 | bfa_fcs_port_ns_offline(struct bfa_fcs_port_s *port) | ||
1201 | { | ||
1202 | struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | ||
1203 | |||
1204 | ns->port = port; | ||
1205 | bfa_sm_send_event(ns, NSSM_EVENT_PORT_OFFLINE); | ||
1206 | } | ||
1207 | |||
1208 | void | ||
1209 | bfa_fcs_port_ns_online(struct bfa_fcs_port_s *port) | ||
1210 | { | ||
1211 | struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | ||
1212 | |||
1213 | ns->port = port; | ||
1214 | bfa_sm_send_event(ns, NSSM_EVENT_PORT_ONLINE); | ||
1215 | } | ||
1216 | |||
1217 | void | ||
1218 | bfa_fcs_port_ns_query(struct bfa_fcs_port_s *port) | ||
1219 | { | ||
1220 | struct bfa_fcs_port_ns_s *ns = BFA_FCS_GET_NS_FROM_PORT(port); | ||
1221 | |||
1222 | bfa_trc(port->fcs, port->pid); | ||
1223 | bfa_sm_send_event(ns, NSSM_EVENT_NS_QUERY); | ||
1224 | } | ||
1225 | |||
1226 | static void | ||
1227 | bfa_fcs_port_ns_boot_target_disc(struct bfa_fcs_port_s *port) | ||
1228 | { | ||
1229 | |||
1230 | struct bfa_fcs_rport_s *rport; | ||
1231 | u8 nwwns; | ||
1232 | wwn_t *wwns; | ||
1233 | int ii; | ||
1234 | |||
1235 | bfa_iocfc_get_bootwwns(port->fcs->bfa, &nwwns, &wwns); | ||
1236 | |||
1237 | for (ii = 0; ii < nwwns; ++ii) { | ||
1238 | rport = bfa_fcs_rport_create_by_wwn(port, wwns[ii]); | ||
1239 | bfa_assert(rport); | ||
1240 | } | ||
1241 | } | ||
1242 | |||
1243 | |||
diff --git a/drivers/scsi/bfa/plog.c b/drivers/scsi/bfa/plog.c new file mode 100644 index 000000000000..86af818d17bb --- /dev/null +++ b/drivers/scsi/bfa/plog.c | |||
@@ -0,0 +1,184 @@ | |||
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 | #include <bfa_os_inc.h> | ||
19 | #include <cs/bfa_plog.h> | ||
20 | #include <cs/bfa_debug.h> | ||
21 | |||
22 | static int | ||
23 | plkd_validate_logrec(struct bfa_plog_rec_s *pl_rec) | ||
24 | { | ||
25 | if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) | ||
26 | && (pl_rec->log_type != BFA_PL_LOG_TYPE_STRING)) | ||
27 | return 1; | ||
28 | |||
29 | if ((pl_rec->log_type != BFA_PL_LOG_TYPE_INT) | ||
30 | && (pl_rec->log_num_ints > BFA_PL_INT_LOG_SZ)) | ||
31 | return 1; | ||
32 | |||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static void | ||
37 | bfa_plog_add(struct bfa_plog_s *plog, struct bfa_plog_rec_s *pl_rec) | ||
38 | { | ||
39 | u16 tail; | ||
40 | struct bfa_plog_rec_s *pl_recp; | ||
41 | |||
42 | if (plog->plog_enabled == 0) | ||
43 | return; | ||
44 | |||
45 | if (plkd_validate_logrec(pl_rec)) { | ||
46 | bfa_assert(0); | ||
47 | return; | ||
48 | } | ||
49 | |||
50 | tail = plog->tail; | ||
51 | |||
52 | pl_recp = &(plog->plog_recs[tail]); | ||
53 | |||
54 | bfa_os_memcpy(pl_recp, pl_rec, sizeof(struct bfa_plog_rec_s)); | ||
55 | |||
56 | pl_recp->tv = BFA_TRC_TS(plog); | ||
57 | BFA_PL_LOG_REC_INCR(plog->tail); | ||
58 | |||
59 | if (plog->head == plog->tail) | ||
60 | BFA_PL_LOG_REC_INCR(plog->head); | ||
61 | } | ||
62 | |||
63 | void | ||
64 | bfa_plog_init(struct bfa_plog_s *plog) | ||
65 | { | ||
66 | bfa_os_memset((char *)plog, 0, sizeof(struct bfa_plog_s)); | ||
67 | |||
68 | bfa_os_memcpy(plog->plog_sig, BFA_PL_SIG_STR, BFA_PL_SIG_LEN); | ||
69 | plog->head = plog->tail = 0; | ||
70 | plog->plog_enabled = 1; | ||
71 | } | ||
72 | |||
73 | void | ||
74 | bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
75 | enum bfa_plog_eid event, | ||
76 | u16 misc, char *log_str) | ||
77 | { | ||
78 | struct bfa_plog_rec_s lp; | ||
79 | |||
80 | if (plog->plog_enabled) { | ||
81 | bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s)); | ||
82 | lp.mid = mid; | ||
83 | lp.eid = event; | ||
84 | lp.log_type = BFA_PL_LOG_TYPE_STRING; | ||
85 | lp.misc = misc; | ||
86 | strncpy(lp.log_entry.string_log, log_str, | ||
87 | BFA_PL_STRING_LOG_SZ - 1); | ||
88 | lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0'; | ||
89 | bfa_plog_add(plog, &lp); | ||
90 | } | ||
91 | } | ||
92 | |||
93 | void | ||
94 | bfa_plog_intarr(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
95 | enum bfa_plog_eid event, | ||
96 | u16 misc, u32 *intarr, u32 num_ints) | ||
97 | { | ||
98 | struct bfa_plog_rec_s lp; | ||
99 | u32 i; | ||
100 | |||
101 | if (num_ints > BFA_PL_INT_LOG_SZ) | ||
102 | num_ints = BFA_PL_INT_LOG_SZ; | ||
103 | |||
104 | if (plog->plog_enabled) { | ||
105 | bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s)); | ||
106 | lp.mid = mid; | ||
107 | lp.eid = event; | ||
108 | lp.log_type = BFA_PL_LOG_TYPE_INT; | ||
109 | lp.misc = misc; | ||
110 | |||
111 | for (i = 0; i < num_ints; i++) | ||
112 | bfa_os_assign(lp.log_entry.int_log[i], | ||
113 | intarr[i]); | ||
114 | |||
115 | lp.log_num_ints = (u8) num_ints; | ||
116 | |||
117 | bfa_plog_add(plog, &lp); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | void | ||
122 | bfa_plog_fchdr(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
123 | enum bfa_plog_eid event, | ||
124 | u16 misc, struct fchs_s *fchdr) | ||
125 | { | ||
126 | struct bfa_plog_rec_s lp; | ||
127 | u32 *tmp_int = (u32 *) fchdr; | ||
128 | u32 ints[BFA_PL_INT_LOG_SZ]; | ||
129 | |||
130 | if (plog->plog_enabled) { | ||
131 | bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s)); | ||
132 | |||
133 | ints[0] = tmp_int[0]; | ||
134 | ints[1] = tmp_int[1]; | ||
135 | ints[2] = tmp_int[4]; | ||
136 | |||
137 | bfa_plog_intarr(plog, mid, event, misc, ints, 3); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | void | ||
142 | bfa_plog_fchdr_and_pl(struct bfa_plog_s *plog, enum bfa_plog_mid mid, | ||
143 | enum bfa_plog_eid event, u16 misc, struct fchs_s *fchdr, | ||
144 | u32 pld_w0) | ||
145 | { | ||
146 | struct bfa_plog_rec_s lp; | ||
147 | u32 *tmp_int = (u32 *) fchdr; | ||
148 | u32 ints[BFA_PL_INT_LOG_SZ]; | ||
149 | |||
150 | if (plog->plog_enabled) { | ||
151 | bfa_os_memset(&lp, 0, sizeof(struct bfa_plog_rec_s)); | ||
152 | |||
153 | ints[0] = tmp_int[0]; | ||
154 | ints[1] = tmp_int[1]; | ||
155 | ints[2] = tmp_int[4]; | ||
156 | ints[3] = pld_w0; | ||
157 | |||
158 | bfa_plog_intarr(plog, mid, event, misc, ints, 4); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | void | ||
163 | bfa_plog_clear(struct bfa_plog_s *plog) | ||
164 | { | ||
165 | plog->head = plog->tail = 0; | ||
166 | } | ||
167 | |||
168 | void | ||
169 | bfa_plog_enable(struct bfa_plog_s *plog) | ||
170 | { | ||
171 | plog->plog_enabled = 1; | ||
172 | } | ||
173 | |||
174 | void | ||
175 | bfa_plog_disable(struct bfa_plog_s *plog) | ||
176 | { | ||
177 | plog->plog_enabled = 0; | ||
178 | } | ||
179 | |||
180 | bfa_boolean_t | ||
181 | bfa_plog_get_setting(struct bfa_plog_s *plog) | ||
182 | { | ||
183 | return((bfa_boolean_t)plog->plog_enabled); | ||
184 | } | ||
diff --git a/drivers/scsi/bfa/rport.c b/drivers/scsi/bfa/rport.c new file mode 100644 index 000000000000..9cf58bb138dc --- /dev/null +++ b/drivers/scsi/bfa/rport.c | |||
@@ -0,0 +1,2618 @@ | |||
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 | * rport.c Remote port implementation. | ||
20 | */ | ||
21 | |||
22 | #include <bfa.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include "fcbuild.h" | ||
25 | #include "fcs_vport.h" | ||
26 | #include "fcs_lport.h" | ||
27 | #include "fcs_rport.h" | ||
28 | #include "fcs_fcpim.h" | ||
29 | #include "fcs_fcptm.h" | ||
30 | #include "fcs_trcmod.h" | ||
31 | #include "fcs_fcxp.h" | ||
32 | #include "fcs.h" | ||
33 | #include <fcb/bfa_fcb_rport.h> | ||
34 | #include <aen/bfa_aen_rport.h> | ||
35 | |||
36 | BFA_TRC_FILE(FCS, RPORT); | ||
37 | |||
38 | #define BFA_FCS_RPORT_MAX_RETRIES (5) | ||
39 | |||
40 | /* In millisecs */ | ||
41 | static u32 bfa_fcs_rport_del_timeout = | ||
42 | BFA_FCS_RPORT_DEF_DEL_TIMEOUT * 1000; | ||
43 | |||
44 | /* | ||
45 | * forward declarations | ||
46 | */ | ||
47 | static struct bfa_fcs_rport_s *bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, | ||
48 | wwn_t pwwn, u32 rpid); | ||
49 | static void bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport); | ||
50 | static void bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport); | ||
51 | static void bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport); | ||
52 | static void bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport); | ||
53 | static void bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, | ||
54 | struct fc_logi_s *plogi); | ||
55 | static void bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport); | ||
56 | static void bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport); | ||
57 | static void bfa_fcs_rport_timeout(void *arg); | ||
58 | static void bfa_fcs_rport_send_plogi(void *rport_cbarg, | ||
59 | struct bfa_fcxp_s *fcxp_alloced); | ||
60 | static void bfa_fcs_rport_send_plogiacc(void *rport_cbarg, | ||
61 | struct bfa_fcxp_s *fcxp_alloced); | ||
62 | static void bfa_fcs_rport_plogi_response(void *fcsarg, | ||
63 | struct bfa_fcxp_s *fcxp, | ||
64 | void *cbarg, | ||
65 | bfa_status_t req_status, | ||
66 | u32 rsp_len, | ||
67 | u32 resid_len, | ||
68 | struct fchs_s *rsp_fchs); | ||
69 | static void bfa_fcs_rport_send_adisc(void *rport_cbarg, | ||
70 | struct bfa_fcxp_s *fcxp_alloced); | ||
71 | static void bfa_fcs_rport_adisc_response(void *fcsarg, | ||
72 | struct bfa_fcxp_s *fcxp, | ||
73 | void *cbarg, | ||
74 | bfa_status_t req_status, | ||
75 | u32 rsp_len, | ||
76 | u32 resid_len, | ||
77 | struct fchs_s *rsp_fchs); | ||
78 | static void bfa_fcs_rport_send_gidpn(void *rport_cbarg, | ||
79 | struct bfa_fcxp_s *fcxp_alloced); | ||
80 | static void bfa_fcs_rport_gidpn_response(void *fcsarg, | ||
81 | struct bfa_fcxp_s *fcxp, | ||
82 | void *cbarg, | ||
83 | bfa_status_t req_status, | ||
84 | u32 rsp_len, | ||
85 | u32 resid_len, | ||
86 | struct fchs_s *rsp_fchs); | ||
87 | static void bfa_fcs_rport_send_logo(void *rport_cbarg, | ||
88 | struct bfa_fcxp_s *fcxp_alloced); | ||
89 | static void bfa_fcs_rport_send_logo_acc(void *rport_cbarg); | ||
90 | static void bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport, | ||
91 | struct fchs_s *rx_fchs, u16 len); | ||
92 | static void bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, | ||
93 | struct fchs_s *rx_fchs, u8 reason_code, | ||
94 | u8 reason_code_expl); | ||
95 | static void bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, | ||
96 | struct fchs_s *rx_fchs, u16 len); | ||
97 | /** | ||
98 | * fcs_rport_sm FCS rport state machine events | ||
99 | */ | ||
100 | |||
101 | enum rport_event { | ||
102 | RPSM_EVENT_PLOGI_SEND = 1, /* new rport; start with PLOGI */ | ||
103 | RPSM_EVENT_PLOGI_RCVD = 2, /* Inbound PLOGI from remote port */ | ||
104 | RPSM_EVENT_PLOGI_COMP = 3, /* PLOGI completed to rport */ | ||
105 | RPSM_EVENT_LOGO_RCVD = 4, /* LOGO from remote device */ | ||
106 | RPSM_EVENT_LOGO_IMP = 5, /* implicit logo for SLER */ | ||
107 | RPSM_EVENT_FCXP_SENT = 6, /* Frame from has been sent */ | ||
108 | RPSM_EVENT_DELETE = 7, /* RPORT delete request */ | ||
109 | RPSM_EVENT_SCN = 8, /* state change notification */ | ||
110 | RPSM_EVENT_ACCEPTED = 9,/* Good response from remote device */ | ||
111 | RPSM_EVENT_FAILED = 10, /* Request to rport failed. */ | ||
112 | RPSM_EVENT_TIMEOUT = 11, /* Rport SM timeout event */ | ||
113 | RPSM_EVENT_HCB_ONLINE = 12, /* BFA rport online callback */ | ||
114 | RPSM_EVENT_HCB_OFFLINE = 13, /* BFA rport offline callback */ | ||
115 | RPSM_EVENT_FC4_OFFLINE = 14, /* FC-4 offline complete */ | ||
116 | RPSM_EVENT_ADDRESS_CHANGE = 15, /* Rport's PID has changed */ | ||
117 | RPSM_EVENT_ADDRESS_DISC = 16 /* Need to Discover rport's PID */ | ||
118 | }; | ||
119 | |||
120 | static void bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, | ||
121 | enum rport_event event); | ||
122 | static void bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport, | ||
123 | enum rport_event event); | ||
124 | static void bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport, | ||
125 | enum rport_event event); | ||
126 | static void bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, | ||
127 | enum rport_event event); | ||
128 | static void bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, | ||
129 | enum rport_event event); | ||
130 | static void bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, | ||
131 | enum rport_event event); | ||
132 | static void bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, | ||
133 | enum rport_event event); | ||
134 | static void bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport, | ||
135 | enum rport_event event); | ||
136 | static void bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, | ||
137 | enum rport_event event); | ||
138 | static void bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, | ||
139 | enum rport_event event); | ||
140 | static void bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, | ||
141 | enum rport_event event); | ||
142 | static void bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, | ||
143 | enum rport_event event); | ||
144 | static void bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport, | ||
145 | enum rport_event event); | ||
146 | static void bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport, | ||
147 | enum rport_event event); | ||
148 | static void bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, | ||
149 | enum rport_event event); | ||
150 | static void bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, | ||
151 | enum rport_event event); | ||
152 | static void bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport, | ||
153 | enum rport_event event); | ||
154 | static void bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport, | ||
155 | enum rport_event event); | ||
156 | static void bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, | ||
157 | enum rport_event event); | ||
158 | static void bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport, | ||
159 | enum rport_event event); | ||
160 | static void bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport, | ||
161 | enum rport_event event); | ||
162 | static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, | ||
163 | enum rport_event event); | ||
164 | static void bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, | ||
165 | enum rport_event event); | ||
166 | |||
167 | static struct bfa_sm_table_s rport_sm_table[] = { | ||
168 | {BFA_SM(bfa_fcs_rport_sm_uninit), BFA_RPORT_UNINIT}, | ||
169 | {BFA_SM(bfa_fcs_rport_sm_plogi_sending), BFA_RPORT_PLOGI}, | ||
170 | {BFA_SM(bfa_fcs_rport_sm_plogiacc_sending), BFA_RPORT_ONLINE}, | ||
171 | {BFA_SM(bfa_fcs_rport_sm_plogi_retry), BFA_RPORT_PLOGI_RETRY}, | ||
172 | {BFA_SM(bfa_fcs_rport_sm_plogi), BFA_RPORT_PLOGI}, | ||
173 | {BFA_SM(bfa_fcs_rport_sm_hal_online), BFA_RPORT_ONLINE}, | ||
174 | {BFA_SM(bfa_fcs_rport_sm_online), BFA_RPORT_ONLINE}, | ||
175 | {BFA_SM(bfa_fcs_rport_sm_nsquery_sending), BFA_RPORT_NSQUERY}, | ||
176 | {BFA_SM(bfa_fcs_rport_sm_nsquery), BFA_RPORT_NSQUERY}, | ||
177 | {BFA_SM(bfa_fcs_rport_sm_adisc_sending), BFA_RPORT_ADISC}, | ||
178 | {BFA_SM(bfa_fcs_rport_sm_adisc), BFA_RPORT_ADISC}, | ||
179 | {BFA_SM(bfa_fcs_rport_sm_fc4_logorcv), BFA_RPORT_LOGORCV}, | ||
180 | {BFA_SM(bfa_fcs_rport_sm_fc4_logosend), BFA_RPORT_LOGO}, | ||
181 | {BFA_SM(bfa_fcs_rport_sm_fc4_offline), BFA_RPORT_OFFLINE}, | ||
182 | {BFA_SM(bfa_fcs_rport_sm_hcb_offline), BFA_RPORT_OFFLINE}, | ||
183 | {BFA_SM(bfa_fcs_rport_sm_hcb_logorcv), BFA_RPORT_LOGORCV}, | ||
184 | {BFA_SM(bfa_fcs_rport_sm_hcb_logosend), BFA_RPORT_LOGO}, | ||
185 | {BFA_SM(bfa_fcs_rport_sm_logo_sending), BFA_RPORT_LOGO}, | ||
186 | {BFA_SM(bfa_fcs_rport_sm_offline), BFA_RPORT_OFFLINE}, | ||
187 | {BFA_SM(bfa_fcs_rport_sm_nsdisc_sending), BFA_RPORT_NSDISC}, | ||
188 | {BFA_SM(bfa_fcs_rport_sm_nsdisc_retry), BFA_RPORT_NSDISC}, | ||
189 | {BFA_SM(bfa_fcs_rport_sm_nsdisc_sent), BFA_RPORT_NSDISC}, | ||
190 | }; | ||
191 | |||
192 | /** | ||
193 | * Beginning state. | ||
194 | */ | ||
195 | static void | ||
196 | bfa_fcs_rport_sm_uninit(struct bfa_fcs_rport_s *rport, enum rport_event event) | ||
197 | { | ||
198 | bfa_trc(rport->fcs, rport->pwwn); | ||
199 | bfa_trc(rport->fcs, rport->pid); | ||
200 | bfa_trc(rport->fcs, event); | ||
201 | |||
202 | switch (event) { | ||
203 | case RPSM_EVENT_PLOGI_SEND: | ||
204 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); | ||
205 | rport->plogi_retries = 0; | ||
206 | bfa_fcs_rport_send_plogi(rport, NULL); | ||
207 | break; | ||
208 | |||
209 | case RPSM_EVENT_PLOGI_RCVD: | ||
210 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
211 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
212 | break; | ||
213 | |||
214 | case RPSM_EVENT_PLOGI_COMP: | ||
215 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
216 | bfa_fcs_rport_hal_online(rport); | ||
217 | break; | ||
218 | |||
219 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
220 | case RPSM_EVENT_ADDRESS_DISC: | ||
221 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
222 | rport->ns_retries = 0; | ||
223 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
224 | break; | ||
225 | |||
226 | default: | ||
227 | bfa_assert(0); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | /** | ||
232 | * PLOGI is being sent. | ||
233 | */ | ||
234 | static void | ||
235 | bfa_fcs_rport_sm_plogi_sending(struct bfa_fcs_rport_s *rport, | ||
236 | enum rport_event event) | ||
237 | { | ||
238 | bfa_trc(rport->fcs, rport->pwwn); | ||
239 | bfa_trc(rport->fcs, rport->pid); | ||
240 | bfa_trc(rport->fcs, event); | ||
241 | |||
242 | switch (event) { | ||
243 | case RPSM_EVENT_FCXP_SENT: | ||
244 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi); | ||
245 | break; | ||
246 | |||
247 | case RPSM_EVENT_DELETE: | ||
248 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
249 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
250 | bfa_fcs_rport_free(rport); | ||
251 | break; | ||
252 | |||
253 | case RPSM_EVENT_PLOGI_RCVD: | ||
254 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
255 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
256 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
257 | break; | ||
258 | |||
259 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
260 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
261 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
262 | rport->ns_retries = 0; | ||
263 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
264 | break; | ||
265 | |||
266 | case RPSM_EVENT_LOGO_IMP: | ||
267 | rport->pid = 0; | ||
268 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
269 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
270 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
271 | bfa_fcs_rport_timeout, rport, | ||
272 | bfa_fcs_rport_del_timeout); | ||
273 | break; | ||
274 | |||
275 | case RPSM_EVENT_SCN: | ||
276 | break; | ||
277 | |||
278 | default: | ||
279 | bfa_assert(0); | ||
280 | } | ||
281 | } | ||
282 | |||
283 | /** | ||
284 | * PLOGI is being sent. | ||
285 | */ | ||
286 | static void | ||
287 | bfa_fcs_rport_sm_plogiacc_sending(struct bfa_fcs_rport_s *rport, | ||
288 | enum rport_event event) | ||
289 | { | ||
290 | bfa_trc(rport->fcs, rport->pwwn); | ||
291 | bfa_trc(rport->fcs, rport->pid); | ||
292 | bfa_trc(rport->fcs, event); | ||
293 | |||
294 | switch (event) { | ||
295 | case RPSM_EVENT_FCXP_SENT: | ||
296 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
297 | bfa_fcs_rport_hal_online(rport); | ||
298 | break; | ||
299 | |||
300 | case RPSM_EVENT_DELETE: | ||
301 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
302 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
303 | bfa_fcs_rport_free(rport); | ||
304 | break; | ||
305 | |||
306 | case RPSM_EVENT_SCN: | ||
307 | /** | ||
308 | * Ignore, SCN is possibly online notification. | ||
309 | */ | ||
310 | break; | ||
311 | |||
312 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
313 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
314 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
315 | rport->ns_retries = 0; | ||
316 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
317 | break; | ||
318 | |||
319 | case RPSM_EVENT_LOGO_IMP: | ||
320 | rport->pid = 0; | ||
321 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
322 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
323 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
324 | bfa_fcs_rport_timeout, rport, | ||
325 | bfa_fcs_rport_del_timeout); | ||
326 | break; | ||
327 | |||
328 | case RPSM_EVENT_HCB_OFFLINE: | ||
329 | /** | ||
330 | * Ignore BFA callback, on a PLOGI receive we call bfa offline. | ||
331 | */ | ||
332 | break; | ||
333 | |||
334 | default: | ||
335 | bfa_assert(0); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | /** | ||
340 | * PLOGI is sent. | ||
341 | */ | ||
342 | static void | ||
343 | bfa_fcs_rport_sm_plogi_retry(struct bfa_fcs_rport_s *rport, | ||
344 | enum rport_event event) | ||
345 | { | ||
346 | bfa_trc(rport->fcs, rport->pwwn); | ||
347 | bfa_trc(rport->fcs, rport->pid); | ||
348 | bfa_trc(rport->fcs, event); | ||
349 | |||
350 | switch (event) { | ||
351 | case RPSM_EVENT_SCN: | ||
352 | bfa_timer_stop(&rport->timer); | ||
353 | /* | ||
354 | * !! fall through !! | ||
355 | */ | ||
356 | |||
357 | case RPSM_EVENT_TIMEOUT: | ||
358 | rport->plogi_retries++; | ||
359 | if (rport->plogi_retries < BFA_FCS_RPORT_MAX_RETRIES) { | ||
360 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); | ||
361 | bfa_fcs_rport_send_plogi(rport, NULL); | ||
362 | } else { | ||
363 | rport->pid = 0; | ||
364 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
365 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
366 | bfa_fcs_rport_timeout, rport, | ||
367 | bfa_fcs_rport_del_timeout); | ||
368 | } | ||
369 | break; | ||
370 | |||
371 | case RPSM_EVENT_DELETE: | ||
372 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
373 | bfa_timer_stop(&rport->timer); | ||
374 | bfa_fcs_rport_free(rport); | ||
375 | break; | ||
376 | |||
377 | case RPSM_EVENT_LOGO_RCVD: | ||
378 | break; | ||
379 | |||
380 | case RPSM_EVENT_PLOGI_RCVD: | ||
381 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
382 | bfa_timer_stop(&rport->timer); | ||
383 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
384 | break; | ||
385 | |||
386 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
387 | bfa_timer_stop(&rport->timer); | ||
388 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
389 | rport->ns_retries = 0; | ||
390 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
391 | break; | ||
392 | |||
393 | case RPSM_EVENT_LOGO_IMP: | ||
394 | rport->pid = 0; | ||
395 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
396 | bfa_timer_stop(&rport->timer); | ||
397 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
398 | bfa_fcs_rport_timeout, rport, | ||
399 | bfa_fcs_rport_del_timeout); | ||
400 | break; | ||
401 | |||
402 | case RPSM_EVENT_PLOGI_COMP: | ||
403 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
404 | bfa_timer_stop(&rport->timer); | ||
405 | bfa_fcs_rport_hal_online(rport); | ||
406 | break; | ||
407 | |||
408 | default: | ||
409 | bfa_assert(0); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * PLOGI is sent. | ||
415 | */ | ||
416 | static void | ||
417 | bfa_fcs_rport_sm_plogi(struct bfa_fcs_rport_s *rport, enum rport_event event) | ||
418 | { | ||
419 | bfa_trc(rport->fcs, rport->pwwn); | ||
420 | bfa_trc(rport->fcs, rport->pid); | ||
421 | bfa_trc(rport->fcs, event); | ||
422 | |||
423 | switch (event) { | ||
424 | case RPSM_EVENT_ACCEPTED: | ||
425 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
426 | rport->plogi_retries = 0; | ||
427 | bfa_fcs_rport_hal_online(rport); | ||
428 | break; | ||
429 | |||
430 | case RPSM_EVENT_LOGO_RCVD: | ||
431 | bfa_fcs_rport_send_logo_acc(rport); | ||
432 | bfa_fcxp_discard(rport->fcxp); | ||
433 | /* | ||
434 | * !! fall through !! | ||
435 | */ | ||
436 | case RPSM_EVENT_FAILED: | ||
437 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_retry); | ||
438 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
439 | bfa_fcs_rport_timeout, rport, | ||
440 | BFA_FCS_RETRY_TIMEOUT); | ||
441 | break; | ||
442 | |||
443 | case RPSM_EVENT_LOGO_IMP: | ||
444 | rport->pid = 0; | ||
445 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
446 | bfa_fcxp_discard(rport->fcxp); | ||
447 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
448 | bfa_fcs_rport_timeout, rport, | ||
449 | bfa_fcs_rport_del_timeout); | ||
450 | break; | ||
451 | |||
452 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
453 | bfa_fcxp_discard(rport->fcxp); | ||
454 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
455 | rport->ns_retries = 0; | ||
456 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
457 | break; | ||
458 | |||
459 | case RPSM_EVENT_PLOGI_RCVD: | ||
460 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
461 | bfa_fcxp_discard(rport->fcxp); | ||
462 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
463 | break; | ||
464 | |||
465 | case RPSM_EVENT_SCN: | ||
466 | /** | ||
467 | * Ignore SCN - wait for PLOGI response. | ||
468 | */ | ||
469 | break; | ||
470 | |||
471 | case RPSM_EVENT_DELETE: | ||
472 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
473 | bfa_fcxp_discard(rport->fcxp); | ||
474 | bfa_fcs_rport_free(rport); | ||
475 | break; | ||
476 | |||
477 | case RPSM_EVENT_PLOGI_COMP: | ||
478 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
479 | bfa_fcxp_discard(rport->fcxp); | ||
480 | bfa_fcs_rport_hal_online(rport); | ||
481 | break; | ||
482 | |||
483 | default: | ||
484 | bfa_assert(0); | ||
485 | } | ||
486 | } | ||
487 | |||
488 | /** | ||
489 | * PLOGI is complete. Awaiting BFA rport online callback. FC-4s | ||
490 | * are offline. | ||
491 | */ | ||
492 | static void | ||
493 | bfa_fcs_rport_sm_hal_online(struct bfa_fcs_rport_s *rport, | ||
494 | enum rport_event event) | ||
495 | { | ||
496 | bfa_trc(rport->fcs, rport->pwwn); | ||
497 | bfa_trc(rport->fcs, rport->pid); | ||
498 | bfa_trc(rport->fcs, event); | ||
499 | |||
500 | switch (event) { | ||
501 | case RPSM_EVENT_HCB_ONLINE: | ||
502 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_online); | ||
503 | bfa_fcs_rport_online_action(rport); | ||
504 | break; | ||
505 | |||
506 | case RPSM_EVENT_LOGO_RCVD: | ||
507 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); | ||
508 | bfa_rport_offline(rport->bfa_rport); | ||
509 | break; | ||
510 | |||
511 | case RPSM_EVENT_LOGO_IMP: | ||
512 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
513 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); | ||
514 | bfa_rport_offline(rport->bfa_rport); | ||
515 | break; | ||
516 | |||
517 | case RPSM_EVENT_PLOGI_RCVD: | ||
518 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
519 | bfa_rport_offline(rport->bfa_rport); | ||
520 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
521 | break; | ||
522 | |||
523 | case RPSM_EVENT_DELETE: | ||
524 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); | ||
525 | bfa_rport_offline(rport->bfa_rport); | ||
526 | break; | ||
527 | |||
528 | case RPSM_EVENT_SCN: | ||
529 | /** | ||
530 | * @todo | ||
531 | * Ignore SCN - PLOGI just completed, FC-4 login should detect | ||
532 | * device failures. | ||
533 | */ | ||
534 | break; | ||
535 | |||
536 | default: | ||
537 | bfa_assert(0); | ||
538 | } | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * Rport is ONLINE. FC-4s active. | ||
543 | */ | ||
544 | static void | ||
545 | bfa_fcs_rport_sm_online(struct bfa_fcs_rport_s *rport, enum rport_event event) | ||
546 | { | ||
547 | bfa_trc(rport->fcs, rport->pwwn); | ||
548 | bfa_trc(rport->fcs, rport->pid); | ||
549 | bfa_trc(rport->fcs, event); | ||
550 | |||
551 | switch (event) { | ||
552 | case RPSM_EVENT_SCN: | ||
553 | /** | ||
554 | * Pause FC-4 activity till rport is authenticated. | ||
555 | * In switched fabrics, check presence of device in nameserver | ||
556 | * first. | ||
557 | */ | ||
558 | bfa_fcs_rport_fc4_pause(rport); | ||
559 | |||
560 | if (bfa_fcs_fabric_is_switched(rport->port->fabric)) { | ||
561 | bfa_sm_set_state(rport, | ||
562 | bfa_fcs_rport_sm_nsquery_sending); | ||
563 | rport->ns_retries = 0; | ||
564 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
565 | } else { | ||
566 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending); | ||
567 | bfa_fcs_rport_send_adisc(rport, NULL); | ||
568 | } | ||
569 | break; | ||
570 | |||
571 | case RPSM_EVENT_PLOGI_RCVD: | ||
572 | case RPSM_EVENT_LOGO_IMP: | ||
573 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
574 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
575 | bfa_fcs_rport_offline_action(rport); | ||
576 | break; | ||
577 | |||
578 | case RPSM_EVENT_DELETE: | ||
579 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); | ||
580 | bfa_fcs_rport_offline_action(rport); | ||
581 | break; | ||
582 | |||
583 | case RPSM_EVENT_LOGO_RCVD: | ||
584 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); | ||
585 | bfa_fcs_rport_offline_action(rport); | ||
586 | break; | ||
587 | |||
588 | case RPSM_EVENT_PLOGI_COMP: | ||
589 | break; | ||
590 | |||
591 | default: | ||
592 | bfa_assert(0); | ||
593 | } | ||
594 | } | ||
595 | |||
596 | /** | ||
597 | * An SCN event is received in ONLINE state. NS query is being sent | ||
598 | * prior to ADISC authentication with rport. FC-4s are paused. | ||
599 | */ | ||
600 | static void | ||
601 | bfa_fcs_rport_sm_nsquery_sending(struct bfa_fcs_rport_s *rport, | ||
602 | enum rport_event event) | ||
603 | { | ||
604 | bfa_trc(rport->fcs, rport->pwwn); | ||
605 | bfa_trc(rport->fcs, rport->pid); | ||
606 | bfa_trc(rport->fcs, event); | ||
607 | |||
608 | switch (event) { | ||
609 | case RPSM_EVENT_FCXP_SENT: | ||
610 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsquery); | ||
611 | break; | ||
612 | |||
613 | case RPSM_EVENT_DELETE: | ||
614 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); | ||
615 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
616 | bfa_fcs_rport_offline_action(rport); | ||
617 | break; | ||
618 | |||
619 | case RPSM_EVENT_SCN: | ||
620 | /** | ||
621 | * ignore SCN, wait for response to query itself | ||
622 | */ | ||
623 | break; | ||
624 | |||
625 | case RPSM_EVENT_LOGO_RCVD: | ||
626 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); | ||
627 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
628 | bfa_fcs_rport_offline_action(rport); | ||
629 | break; | ||
630 | |||
631 | case RPSM_EVENT_LOGO_IMP: | ||
632 | rport->pid = 0; | ||
633 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
634 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
635 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
636 | bfa_fcs_rport_timeout, rport, | ||
637 | bfa_fcs_rport_del_timeout); | ||
638 | break; | ||
639 | |||
640 | case RPSM_EVENT_PLOGI_RCVD: | ||
641 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
642 | case RPSM_EVENT_PLOGI_COMP: | ||
643 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
644 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
645 | bfa_fcs_rport_offline_action(rport); | ||
646 | break; | ||
647 | |||
648 | default: | ||
649 | bfa_assert(0); | ||
650 | } | ||
651 | } | ||
652 | |||
653 | /** | ||
654 | * An SCN event is received in ONLINE state. NS query is sent to rport. | ||
655 | * FC-4s are paused. | ||
656 | */ | ||
657 | static void | ||
658 | bfa_fcs_rport_sm_nsquery(struct bfa_fcs_rport_s *rport, enum rport_event event) | ||
659 | { | ||
660 | bfa_trc(rport->fcs, rport->pwwn); | ||
661 | bfa_trc(rport->fcs, rport->pid); | ||
662 | bfa_trc(rport->fcs, event); | ||
663 | |||
664 | switch (event) { | ||
665 | case RPSM_EVENT_ACCEPTED: | ||
666 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc_sending); | ||
667 | bfa_fcs_rport_send_adisc(rport, NULL); | ||
668 | break; | ||
669 | |||
670 | case RPSM_EVENT_FAILED: | ||
671 | rport->ns_retries++; | ||
672 | if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) { | ||
673 | bfa_sm_set_state(rport, | ||
674 | bfa_fcs_rport_sm_nsquery_sending); | ||
675 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
676 | } else { | ||
677 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
678 | bfa_fcs_rport_offline_action(rport); | ||
679 | } | ||
680 | break; | ||
681 | |||
682 | case RPSM_EVENT_DELETE: | ||
683 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); | ||
684 | bfa_fcxp_discard(rport->fcxp); | ||
685 | bfa_fcs_rport_offline_action(rport); | ||
686 | break; | ||
687 | |||
688 | case RPSM_EVENT_SCN: | ||
689 | break; | ||
690 | |||
691 | case RPSM_EVENT_LOGO_RCVD: | ||
692 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); | ||
693 | bfa_fcxp_discard(rport->fcxp); | ||
694 | bfa_fcs_rport_offline_action(rport); | ||
695 | break; | ||
696 | |||
697 | case RPSM_EVENT_PLOGI_COMP: | ||
698 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
699 | case RPSM_EVENT_PLOGI_RCVD: | ||
700 | case RPSM_EVENT_LOGO_IMP: | ||
701 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
702 | bfa_fcxp_discard(rport->fcxp); | ||
703 | bfa_fcs_rport_offline_action(rport); | ||
704 | break; | ||
705 | |||
706 | default: | ||
707 | bfa_assert(0); | ||
708 | } | ||
709 | } | ||
710 | |||
711 | /** | ||
712 | * An SCN event is received in ONLINE state. ADISC is being sent for | ||
713 | * authenticating with rport. FC-4s are paused. | ||
714 | */ | ||
715 | static void | ||
716 | bfa_fcs_rport_sm_adisc_sending(struct bfa_fcs_rport_s *rport, | ||
717 | enum rport_event event) | ||
718 | { | ||
719 | bfa_trc(rport->fcs, rport->pwwn); | ||
720 | bfa_trc(rport->fcs, rport->pid); | ||
721 | bfa_trc(rport->fcs, event); | ||
722 | |||
723 | switch (event) { | ||
724 | case RPSM_EVENT_FCXP_SENT: | ||
725 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_adisc); | ||
726 | break; | ||
727 | |||
728 | case RPSM_EVENT_DELETE: | ||
729 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); | ||
730 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
731 | bfa_fcs_rport_offline_action(rport); | ||
732 | break; | ||
733 | |||
734 | case RPSM_EVENT_LOGO_IMP: | ||
735 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
736 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
737 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
738 | bfa_fcs_rport_offline_action(rport); | ||
739 | break; | ||
740 | |||
741 | case RPSM_EVENT_LOGO_RCVD: | ||
742 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); | ||
743 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
744 | bfa_fcs_rport_offline_action(rport); | ||
745 | break; | ||
746 | |||
747 | case RPSM_EVENT_SCN: | ||
748 | break; | ||
749 | |||
750 | case RPSM_EVENT_PLOGI_RCVD: | ||
751 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
752 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
753 | bfa_fcs_rport_offline_action(rport); | ||
754 | break; | ||
755 | |||
756 | default: | ||
757 | bfa_assert(0); | ||
758 | } | ||
759 | } | ||
760 | |||
761 | /** | ||
762 | * An SCN event is received in ONLINE state. ADISC is to rport. | ||
763 | * FC-4s are paused. | ||
764 | */ | ||
765 | static void | ||
766 | bfa_fcs_rport_sm_adisc(struct bfa_fcs_rport_s *rport, enum rport_event event) | ||
767 | { | ||
768 | bfa_trc(rport->fcs, rport->pwwn); | ||
769 | bfa_trc(rport->fcs, rport->pid); | ||
770 | bfa_trc(rport->fcs, event); | ||
771 | |||
772 | switch (event) { | ||
773 | case RPSM_EVENT_ACCEPTED: | ||
774 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_online); | ||
775 | bfa_fcs_rport_fc4_resume(rport); | ||
776 | break; | ||
777 | |||
778 | case RPSM_EVENT_PLOGI_RCVD: | ||
779 | /** | ||
780 | * Too complex to cleanup FC-4 & rport and then acc to PLOGI. | ||
781 | * At least go offline when a PLOGI is received. | ||
782 | */ | ||
783 | bfa_fcxp_discard(rport->fcxp); | ||
784 | /* | ||
785 | * !!! fall through !!! | ||
786 | */ | ||
787 | |||
788 | case RPSM_EVENT_FAILED: | ||
789 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
790 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
791 | bfa_fcs_rport_offline_action(rport); | ||
792 | break; | ||
793 | |||
794 | case RPSM_EVENT_DELETE: | ||
795 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); | ||
796 | bfa_fcxp_discard(rport->fcxp); | ||
797 | bfa_fcs_rport_offline_action(rport); | ||
798 | break; | ||
799 | |||
800 | case RPSM_EVENT_SCN: | ||
801 | /** | ||
802 | * already processing RSCN | ||
803 | */ | ||
804 | break; | ||
805 | |||
806 | case RPSM_EVENT_LOGO_IMP: | ||
807 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_offline); | ||
808 | bfa_fcxp_discard(rport->fcxp); | ||
809 | bfa_fcs_rport_offline_action(rport); | ||
810 | break; | ||
811 | |||
812 | case RPSM_EVENT_LOGO_RCVD: | ||
813 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logorcv); | ||
814 | bfa_fcxp_discard(rport->fcxp); | ||
815 | bfa_fcs_rport_offline_action(rport); | ||
816 | break; | ||
817 | |||
818 | default: | ||
819 | bfa_assert(0); | ||
820 | } | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * Rport has sent LOGO. Awaiting FC-4 offline completion callback. | ||
825 | */ | ||
826 | static void | ||
827 | bfa_fcs_rport_sm_fc4_logorcv(struct bfa_fcs_rport_s *rport, | ||
828 | enum rport_event event) | ||
829 | { | ||
830 | bfa_trc(rport->fcs, rport->pwwn); | ||
831 | bfa_trc(rport->fcs, rport->pid); | ||
832 | bfa_trc(rport->fcs, event); | ||
833 | |||
834 | switch (event) { | ||
835 | case RPSM_EVENT_FC4_OFFLINE: | ||
836 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logorcv); | ||
837 | bfa_rport_offline(rport->bfa_rport); | ||
838 | break; | ||
839 | |||
840 | case RPSM_EVENT_DELETE: | ||
841 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); | ||
842 | break; | ||
843 | |||
844 | case RPSM_EVENT_LOGO_RCVD: | ||
845 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
846 | break; | ||
847 | |||
848 | default: | ||
849 | bfa_assert(0); | ||
850 | } | ||
851 | } | ||
852 | |||
853 | /** | ||
854 | * LOGO needs to be sent to rport. Awaiting FC-4 offline completion | ||
855 | * callback. | ||
856 | */ | ||
857 | static void | ||
858 | bfa_fcs_rport_sm_fc4_logosend(struct bfa_fcs_rport_s *rport, | ||
859 | enum rport_event event) | ||
860 | { | ||
861 | bfa_trc(rport->fcs, rport->pwwn); | ||
862 | bfa_trc(rport->fcs, rport->pid); | ||
863 | bfa_trc(rport->fcs, event); | ||
864 | |||
865 | switch (event) { | ||
866 | case RPSM_EVENT_FC4_OFFLINE: | ||
867 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); | ||
868 | bfa_rport_offline(rport->bfa_rport); | ||
869 | break; | ||
870 | |||
871 | default: | ||
872 | bfa_assert(0); | ||
873 | } | ||
874 | } | ||
875 | |||
876 | /** | ||
877 | * Rport is going offline. Awaiting FC-4 offline completion callback. | ||
878 | */ | ||
879 | static void | ||
880 | bfa_fcs_rport_sm_fc4_offline(struct bfa_fcs_rport_s *rport, | ||
881 | enum rport_event event) | ||
882 | { | ||
883 | bfa_trc(rport->fcs, rport->pwwn); | ||
884 | bfa_trc(rport->fcs, rport->pid); | ||
885 | bfa_trc(rport->fcs, event); | ||
886 | |||
887 | switch (event) { | ||
888 | case RPSM_EVENT_FC4_OFFLINE: | ||
889 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); | ||
890 | bfa_rport_offline(rport->bfa_rport); | ||
891 | break; | ||
892 | |||
893 | case RPSM_EVENT_SCN: | ||
894 | case RPSM_EVENT_LOGO_IMP: | ||
895 | case RPSM_EVENT_LOGO_RCVD: | ||
896 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
897 | /** | ||
898 | * rport is already going offline. | ||
899 | * SCN - ignore and wait till transitioning to offline state | ||
900 | */ | ||
901 | break; | ||
902 | |||
903 | case RPSM_EVENT_DELETE: | ||
904 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_fc4_logosend); | ||
905 | break; | ||
906 | |||
907 | default: | ||
908 | bfa_assert(0); | ||
909 | } | ||
910 | } | ||
911 | |||
912 | /** | ||
913 | * Rport is offline. FC-4s are offline. Awaiting BFA rport offline | ||
914 | * callback. | ||
915 | */ | ||
916 | static void | ||
917 | bfa_fcs_rport_sm_hcb_offline(struct bfa_fcs_rport_s *rport, | ||
918 | enum rport_event event) | ||
919 | { | ||
920 | bfa_trc(rport->fcs, rport->pwwn); | ||
921 | bfa_trc(rport->fcs, rport->pid); | ||
922 | bfa_trc(rport->fcs, event); | ||
923 | |||
924 | switch (event) { | ||
925 | case RPSM_EVENT_HCB_OFFLINE: | ||
926 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
927 | if (bfa_fcs_port_is_online(rport->port)) { | ||
928 | bfa_sm_set_state(rport, | ||
929 | bfa_fcs_rport_sm_nsdisc_sending); | ||
930 | rport->ns_retries = 0; | ||
931 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
932 | } else { | ||
933 | rport->pid = 0; | ||
934 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
935 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
936 | bfa_fcs_rport_timeout, rport, | ||
937 | bfa_fcs_rport_del_timeout); | ||
938 | } | ||
939 | break; | ||
940 | |||
941 | case RPSM_EVENT_DELETE: | ||
942 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
943 | bfa_fcs_rport_free(rport); | ||
944 | break; | ||
945 | |||
946 | case RPSM_EVENT_SCN: | ||
947 | case RPSM_EVENT_LOGO_RCVD: | ||
948 | /** | ||
949 | * Ignore, already offline. | ||
950 | */ | ||
951 | break; | ||
952 | |||
953 | default: | ||
954 | bfa_assert(0); | ||
955 | } | ||
956 | } | ||
957 | |||
958 | /** | ||
959 | * Rport is offline. FC-4s are offline. Awaiting BFA rport offline | ||
960 | * callback to send LOGO accept. | ||
961 | */ | ||
962 | static void | ||
963 | bfa_fcs_rport_sm_hcb_logorcv(struct bfa_fcs_rport_s *rport, | ||
964 | enum rport_event event) | ||
965 | { | ||
966 | bfa_trc(rport->fcs, rport->pwwn); | ||
967 | bfa_trc(rport->fcs, rport->pid); | ||
968 | bfa_trc(rport->fcs, event); | ||
969 | |||
970 | switch (event) { | ||
971 | case RPSM_EVENT_HCB_OFFLINE: | ||
972 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
973 | if (rport->pid) | ||
974 | bfa_fcs_rport_send_logo_acc(rport); | ||
975 | /* | ||
976 | * If the lport is online and if the rport is not a well known | ||
977 | * address port, we try to re-discover the r-port. | ||
978 | */ | ||
979 | if (bfa_fcs_port_is_online(rport->port) | ||
980 | && (!BFA_FCS_PID_IS_WKA(rport->pid))) { | ||
981 | bfa_sm_set_state(rport, | ||
982 | bfa_fcs_rport_sm_nsdisc_sending); | ||
983 | rport->ns_retries = 0; | ||
984 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
985 | } else { | ||
986 | /* | ||
987 | * if it is not a well known address, reset the pid to | ||
988 | * | ||
989 | */ | ||
990 | if (!BFA_FCS_PID_IS_WKA(rport->pid)) | ||
991 | rport->pid = 0; | ||
992 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
993 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
994 | bfa_fcs_rport_timeout, rport, | ||
995 | bfa_fcs_rport_del_timeout); | ||
996 | } | ||
997 | break; | ||
998 | |||
999 | case RPSM_EVENT_DELETE: | ||
1000 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_logosend); | ||
1001 | break; | ||
1002 | |||
1003 | case RPSM_EVENT_LOGO_IMP: | ||
1004 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hcb_offline); | ||
1005 | break; | ||
1006 | |||
1007 | case RPSM_EVENT_LOGO_RCVD: | ||
1008 | /** | ||
1009 | * Ignore - already processing a LOGO. | ||
1010 | */ | ||
1011 | break; | ||
1012 | |||
1013 | default: | ||
1014 | bfa_assert(0); | ||
1015 | } | ||
1016 | } | ||
1017 | |||
1018 | /** | ||
1019 | * Rport is being deleted. FC-4s are offline. Awaiting BFA rport offline | ||
1020 | * callback to send LOGO. | ||
1021 | */ | ||
1022 | static void | ||
1023 | bfa_fcs_rport_sm_hcb_logosend(struct bfa_fcs_rport_s *rport, | ||
1024 | enum rport_event event) | ||
1025 | { | ||
1026 | bfa_trc(rport->fcs, rport->pwwn); | ||
1027 | bfa_trc(rport->fcs, rport->pid); | ||
1028 | bfa_trc(rport->fcs, event); | ||
1029 | |||
1030 | switch (event) { | ||
1031 | case RPSM_EVENT_HCB_OFFLINE: | ||
1032 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_logo_sending); | ||
1033 | bfa_fcs_rport_send_logo(rport, NULL); | ||
1034 | break; | ||
1035 | |||
1036 | case RPSM_EVENT_LOGO_RCVD: | ||
1037 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
1038 | break; | ||
1039 | |||
1040 | default: | ||
1041 | bfa_assert(0); | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | /** | ||
1046 | * Rport is being deleted. FC-4s are offline. LOGO is being sent. | ||
1047 | */ | ||
1048 | static void | ||
1049 | bfa_fcs_rport_sm_logo_sending(struct bfa_fcs_rport_s *rport, | ||
1050 | enum rport_event event) | ||
1051 | { | ||
1052 | bfa_trc(rport->fcs, rport->pwwn); | ||
1053 | bfa_trc(rport->fcs, rport->pid); | ||
1054 | bfa_trc(rport->fcs, event); | ||
1055 | |||
1056 | switch (event) { | ||
1057 | case RPSM_EVENT_FCXP_SENT: | ||
1058 | /* | ||
1059 | * Once LOGO is sent, we donot wait for the response | ||
1060 | */ | ||
1061 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1062 | bfa_fcs_rport_free(rport); | ||
1063 | break; | ||
1064 | |||
1065 | case RPSM_EVENT_SCN: | ||
1066 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
1067 | break; | ||
1068 | |||
1069 | case RPSM_EVENT_LOGO_RCVD: | ||
1070 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1071 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
1072 | bfa_fcs_rport_free(rport); | ||
1073 | break; | ||
1074 | |||
1075 | default: | ||
1076 | bfa_assert(0); | ||
1077 | } | ||
1078 | } | ||
1079 | |||
1080 | /** | ||
1081 | * Rport is offline. FC-4s are offline. BFA rport is offline. | ||
1082 | * Timer active to delete stale rport. | ||
1083 | */ | ||
1084 | static void | ||
1085 | bfa_fcs_rport_sm_offline(struct bfa_fcs_rport_s *rport, enum rport_event event) | ||
1086 | { | ||
1087 | bfa_trc(rport->fcs, rport->pwwn); | ||
1088 | bfa_trc(rport->fcs, rport->pid); | ||
1089 | bfa_trc(rport->fcs, event); | ||
1090 | |||
1091 | switch (event) { | ||
1092 | case RPSM_EVENT_TIMEOUT: | ||
1093 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1094 | bfa_fcs_rport_free(rport); | ||
1095 | break; | ||
1096 | |||
1097 | case RPSM_EVENT_SCN: | ||
1098 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
1099 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
1100 | bfa_timer_stop(&rport->timer); | ||
1101 | rport->ns_retries = 0; | ||
1102 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
1103 | break; | ||
1104 | |||
1105 | case RPSM_EVENT_DELETE: | ||
1106 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1107 | bfa_timer_stop(&rport->timer); | ||
1108 | bfa_fcs_rport_free(rport); | ||
1109 | break; | ||
1110 | |||
1111 | case RPSM_EVENT_PLOGI_RCVD: | ||
1112 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
1113 | bfa_timer_stop(&rport->timer); | ||
1114 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
1115 | break; | ||
1116 | |||
1117 | case RPSM_EVENT_LOGO_RCVD: | ||
1118 | case RPSM_EVENT_LOGO_IMP: | ||
1119 | break; | ||
1120 | |||
1121 | case RPSM_EVENT_PLOGI_COMP: | ||
1122 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
1123 | bfa_timer_stop(&rport->timer); | ||
1124 | bfa_fcs_rport_hal_online(rport); | ||
1125 | break; | ||
1126 | |||
1127 | case RPSM_EVENT_PLOGI_SEND: | ||
1128 | bfa_timer_stop(&rport->timer); | ||
1129 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); | ||
1130 | rport->plogi_retries = 0; | ||
1131 | bfa_fcs_rport_send_plogi(rport, NULL); | ||
1132 | break; | ||
1133 | |||
1134 | default: | ||
1135 | bfa_assert(0); | ||
1136 | } | ||
1137 | } | ||
1138 | |||
1139 | /** | ||
1140 | * Rport address has changed. Nameserver discovery request is being sent. | ||
1141 | */ | ||
1142 | static void | ||
1143 | bfa_fcs_rport_sm_nsdisc_sending(struct bfa_fcs_rport_s *rport, | ||
1144 | enum rport_event event) | ||
1145 | { | ||
1146 | bfa_trc(rport->fcs, rport->pwwn); | ||
1147 | bfa_trc(rport->fcs, rport->pid); | ||
1148 | bfa_trc(rport->fcs, event); | ||
1149 | |||
1150 | switch (event) { | ||
1151 | case RPSM_EVENT_FCXP_SENT: | ||
1152 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sent); | ||
1153 | break; | ||
1154 | |||
1155 | case RPSM_EVENT_DELETE: | ||
1156 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1157 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
1158 | bfa_fcs_rport_free(rport); | ||
1159 | break; | ||
1160 | |||
1161 | case RPSM_EVENT_PLOGI_RCVD: | ||
1162 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
1163 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
1164 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
1165 | break; | ||
1166 | |||
1167 | case RPSM_EVENT_SCN: | ||
1168 | case RPSM_EVENT_LOGO_RCVD: | ||
1169 | case RPSM_EVENT_PLOGI_SEND: | ||
1170 | break; | ||
1171 | |||
1172 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
1173 | rport->ns_retries = 0; /* reset the retry count */ | ||
1174 | break; | ||
1175 | |||
1176 | case RPSM_EVENT_LOGO_IMP: | ||
1177 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
1178 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
1179 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
1180 | bfa_fcs_rport_timeout, rport, | ||
1181 | bfa_fcs_rport_del_timeout); | ||
1182 | break; | ||
1183 | |||
1184 | case RPSM_EVENT_PLOGI_COMP: | ||
1185 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
1186 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rport->fcxp_wqe); | ||
1187 | bfa_fcs_rport_hal_online(rport); | ||
1188 | break; | ||
1189 | |||
1190 | default: | ||
1191 | bfa_assert(0); | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | /** | ||
1196 | * Nameserver discovery failed. Waiting for timeout to retry. | ||
1197 | */ | ||
1198 | static void | ||
1199 | bfa_fcs_rport_sm_nsdisc_retry(struct bfa_fcs_rport_s *rport, | ||
1200 | enum rport_event event) | ||
1201 | { | ||
1202 | bfa_trc(rport->fcs, rport->pwwn); | ||
1203 | bfa_trc(rport->fcs, rport->pid); | ||
1204 | bfa_trc(rport->fcs, event); | ||
1205 | |||
1206 | switch (event) { | ||
1207 | case RPSM_EVENT_TIMEOUT: | ||
1208 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
1209 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
1210 | break; | ||
1211 | |||
1212 | case RPSM_EVENT_SCN: | ||
1213 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
1214 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_nsdisc_sending); | ||
1215 | bfa_timer_stop(&rport->timer); | ||
1216 | rport->ns_retries = 0; | ||
1217 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
1218 | break; | ||
1219 | |||
1220 | case RPSM_EVENT_DELETE: | ||
1221 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1222 | bfa_timer_stop(&rport->timer); | ||
1223 | bfa_fcs_rport_free(rport); | ||
1224 | break; | ||
1225 | |||
1226 | case RPSM_EVENT_PLOGI_RCVD: | ||
1227 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
1228 | bfa_timer_stop(&rport->timer); | ||
1229 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
1230 | break; | ||
1231 | |||
1232 | case RPSM_EVENT_LOGO_IMP: | ||
1233 | rport->pid = 0; | ||
1234 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
1235 | bfa_timer_stop(&rport->timer); | ||
1236 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
1237 | bfa_fcs_rport_timeout, rport, | ||
1238 | bfa_fcs_rport_del_timeout); | ||
1239 | break; | ||
1240 | |||
1241 | case RPSM_EVENT_LOGO_RCVD: | ||
1242 | bfa_fcs_rport_send_logo_acc(rport); | ||
1243 | break; | ||
1244 | |||
1245 | case RPSM_EVENT_PLOGI_COMP: | ||
1246 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
1247 | bfa_timer_stop(&rport->timer); | ||
1248 | bfa_fcs_rport_hal_online(rport); | ||
1249 | break; | ||
1250 | |||
1251 | default: | ||
1252 | bfa_assert(0); | ||
1253 | } | ||
1254 | } | ||
1255 | |||
1256 | /** | ||
1257 | * Rport address has changed. Nameserver discovery request is sent. | ||
1258 | */ | ||
1259 | static void | ||
1260 | bfa_fcs_rport_sm_nsdisc_sent(struct bfa_fcs_rport_s *rport, | ||
1261 | enum rport_event event) | ||
1262 | { | ||
1263 | bfa_trc(rport->fcs, rport->pwwn); | ||
1264 | bfa_trc(rport->fcs, rport->pid); | ||
1265 | bfa_trc(rport->fcs, event); | ||
1266 | |||
1267 | switch (event) { | ||
1268 | case RPSM_EVENT_ACCEPTED: | ||
1269 | case RPSM_EVENT_ADDRESS_CHANGE: | ||
1270 | if (rport->pid) { | ||
1271 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogi_sending); | ||
1272 | bfa_fcs_rport_send_plogi(rport, NULL); | ||
1273 | } else { | ||
1274 | bfa_sm_set_state(rport, | ||
1275 | bfa_fcs_rport_sm_nsdisc_sending); | ||
1276 | rport->ns_retries = 0; | ||
1277 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
1278 | } | ||
1279 | break; | ||
1280 | |||
1281 | case RPSM_EVENT_FAILED: | ||
1282 | rport->ns_retries++; | ||
1283 | if (rport->ns_retries < BFA_FCS_RPORT_MAX_RETRIES) { | ||
1284 | bfa_sm_set_state(rport, | ||
1285 | bfa_fcs_rport_sm_nsdisc_sending); | ||
1286 | bfa_fcs_rport_send_gidpn(rport, NULL); | ||
1287 | } else { | ||
1288 | rport->pid = 0; | ||
1289 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
1290 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
1291 | bfa_fcs_rport_timeout, rport, | ||
1292 | bfa_fcs_rport_del_timeout); | ||
1293 | }; | ||
1294 | break; | ||
1295 | |||
1296 | case RPSM_EVENT_DELETE: | ||
1297 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1298 | bfa_fcxp_discard(rport->fcxp); | ||
1299 | bfa_fcs_rport_free(rport); | ||
1300 | break; | ||
1301 | |||
1302 | case RPSM_EVENT_PLOGI_RCVD: | ||
1303 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_plogiacc_sending); | ||
1304 | bfa_fcxp_discard(rport->fcxp); | ||
1305 | bfa_fcs_rport_send_plogiacc(rport, NULL); | ||
1306 | break; | ||
1307 | |||
1308 | case RPSM_EVENT_LOGO_IMP: | ||
1309 | rport->pid = 0; | ||
1310 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_offline); | ||
1311 | bfa_fcxp_discard(rport->fcxp); | ||
1312 | bfa_timer_start(rport->fcs->bfa, &rport->timer, | ||
1313 | bfa_fcs_rport_timeout, rport, | ||
1314 | bfa_fcs_rport_del_timeout); | ||
1315 | break; | ||
1316 | |||
1317 | case RPSM_EVENT_SCN: | ||
1318 | /** | ||
1319 | * ignore, wait for NS query response | ||
1320 | */ | ||
1321 | break; | ||
1322 | |||
1323 | case RPSM_EVENT_LOGO_RCVD: | ||
1324 | /** | ||
1325 | * Not logged-in yet. Accept LOGO. | ||
1326 | */ | ||
1327 | bfa_fcs_rport_send_logo_acc(rport); | ||
1328 | break; | ||
1329 | |||
1330 | case RPSM_EVENT_PLOGI_COMP: | ||
1331 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_hal_online); | ||
1332 | bfa_fcxp_discard(rport->fcxp); | ||
1333 | bfa_fcs_rport_hal_online(rport); | ||
1334 | break; | ||
1335 | |||
1336 | default: | ||
1337 | bfa_assert(0); | ||
1338 | } | ||
1339 | } | ||
1340 | |||
1341 | |||
1342 | |||
1343 | /** | ||
1344 | * fcs_rport_private FCS RPORT provate functions | ||
1345 | */ | ||
1346 | |||
1347 | static void | ||
1348 | bfa_fcs_rport_send_plogi(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
1349 | { | ||
1350 | struct bfa_fcs_rport_s *rport = rport_cbarg; | ||
1351 | struct bfa_fcs_port_s *port = rport->port; | ||
1352 | struct fchs_s fchs; | ||
1353 | int len; | ||
1354 | struct bfa_fcxp_s *fcxp; | ||
1355 | |||
1356 | bfa_trc(rport->fcs, rport->pwwn); | ||
1357 | |||
1358 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
1359 | if (!fcxp) { | ||
1360 | bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, | ||
1361 | bfa_fcs_rport_send_plogi, rport); | ||
1362 | return; | ||
1363 | } | ||
1364 | rport->fcxp = fcxp; | ||
1365 | |||
1366 | len = fc_plogi_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, | ||
1367 | bfa_fcs_port_get_fcid(port), 0, | ||
1368 | port->port_cfg.pwwn, port->port_cfg.nwwn, | ||
1369 | bfa_pport_get_maxfrsize(port->fcs->bfa)); | ||
1370 | |||
1371 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1372 | FC_CLASS_3, len, &fchs, bfa_fcs_rport_plogi_response, | ||
1373 | (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV); | ||
1374 | |||
1375 | rport->stats.plogis++; | ||
1376 | bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); | ||
1377 | } | ||
1378 | |||
1379 | static void | ||
1380 | bfa_fcs_rport_plogi_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
1381 | bfa_status_t req_status, u32 rsp_len, | ||
1382 | u32 resid_len, struct fchs_s *rsp_fchs) | ||
1383 | { | ||
1384 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; | ||
1385 | struct fc_logi_s *plogi_rsp; | ||
1386 | struct fc_ls_rjt_s *ls_rjt; | ||
1387 | struct bfa_fcs_rport_s *twin; | ||
1388 | struct list_head *qe; | ||
1389 | |||
1390 | bfa_trc(rport->fcs, rport->pwwn); | ||
1391 | |||
1392 | /* | ||
1393 | * Sanity Checks | ||
1394 | */ | ||
1395 | if (req_status != BFA_STATUS_OK) { | ||
1396 | bfa_trc(rport->fcs, req_status); | ||
1397 | rport->stats.plogi_failed++; | ||
1398 | bfa_sm_send_event(rport, RPSM_EVENT_FAILED); | ||
1399 | return; | ||
1400 | } | ||
1401 | |||
1402 | plogi_rsp = (struct fc_logi_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
1403 | |||
1404 | /** | ||
1405 | * Check for failure first. | ||
1406 | */ | ||
1407 | if (plogi_rsp->els_cmd.els_code != FC_ELS_ACC) { | ||
1408 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
1409 | |||
1410 | bfa_trc(rport->fcs, ls_rjt->reason_code); | ||
1411 | bfa_trc(rport->fcs, ls_rjt->reason_code_expl); | ||
1412 | |||
1413 | rport->stats.plogi_rejects++; | ||
1414 | bfa_sm_send_event(rport, RPSM_EVENT_FAILED); | ||
1415 | return; | ||
1416 | } | ||
1417 | |||
1418 | /** | ||
1419 | * PLOGI is complete. Make sure this device is not one of the known | ||
1420 | * device with a new FC port address. | ||
1421 | */ | ||
1422 | list_for_each(qe, &rport->port->rport_q) { | ||
1423 | twin = (struct bfa_fcs_rport_s *)qe; | ||
1424 | if (twin == rport) | ||
1425 | continue; | ||
1426 | if (!rport->pwwn && (plogi_rsp->port_name == twin->pwwn)) { | ||
1427 | bfa_trc(rport->fcs, twin->pid); | ||
1428 | bfa_trc(rport->fcs, rport->pid); | ||
1429 | |||
1430 | /* | ||
1431 | * Update plogi stats in twin | ||
1432 | */ | ||
1433 | twin->stats.plogis += rport->stats.plogis; | ||
1434 | twin->stats.plogi_rejects += rport->stats.plogi_rejects; | ||
1435 | twin->stats.plogi_timeouts += | ||
1436 | rport->stats.plogi_timeouts; | ||
1437 | twin->stats.plogi_failed += rport->stats.plogi_failed; | ||
1438 | twin->stats.plogi_rcvd += rport->stats.plogi_rcvd; | ||
1439 | twin->stats.plogi_accs++; | ||
1440 | |||
1441 | bfa_fcs_rport_delete(rport); | ||
1442 | |||
1443 | bfa_fcs_rport_update(twin, plogi_rsp); | ||
1444 | twin->pid = rsp_fchs->s_id; | ||
1445 | bfa_sm_send_event(twin, RPSM_EVENT_PLOGI_COMP); | ||
1446 | return; | ||
1447 | } | ||
1448 | } | ||
1449 | |||
1450 | /** | ||
1451 | * Normal login path -- no evil twins. | ||
1452 | */ | ||
1453 | rport->stats.plogi_accs++; | ||
1454 | bfa_fcs_rport_update(rport, plogi_rsp); | ||
1455 | bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED); | ||
1456 | } | ||
1457 | |||
1458 | static void | ||
1459 | bfa_fcs_rport_send_plogiacc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
1460 | { | ||
1461 | struct bfa_fcs_rport_s *rport = rport_cbarg; | ||
1462 | struct bfa_fcs_port_s *port = rport->port; | ||
1463 | struct fchs_s fchs; | ||
1464 | int len; | ||
1465 | struct bfa_fcxp_s *fcxp; | ||
1466 | |||
1467 | bfa_trc(rport->fcs, rport->pwwn); | ||
1468 | bfa_trc(rport->fcs, rport->reply_oxid); | ||
1469 | |||
1470 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
1471 | if (!fcxp) { | ||
1472 | bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, | ||
1473 | bfa_fcs_rport_send_plogiacc, rport); | ||
1474 | return; | ||
1475 | } | ||
1476 | rport->fcxp = fcxp; | ||
1477 | |||
1478 | len = fc_plogi_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, | ||
1479 | bfa_fcs_port_get_fcid(port), rport->reply_oxid, | ||
1480 | port->port_cfg.pwwn, port->port_cfg.nwwn, | ||
1481 | bfa_pport_get_maxfrsize(port->fcs->bfa)); | ||
1482 | |||
1483 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1484 | FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); | ||
1485 | |||
1486 | bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); | ||
1487 | } | ||
1488 | |||
1489 | static void | ||
1490 | bfa_fcs_rport_send_adisc(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
1491 | { | ||
1492 | struct bfa_fcs_rport_s *rport = rport_cbarg; | ||
1493 | struct bfa_fcs_port_s *port = rport->port; | ||
1494 | struct fchs_s fchs; | ||
1495 | int len; | ||
1496 | struct bfa_fcxp_s *fcxp; | ||
1497 | |||
1498 | bfa_trc(rport->fcs, rport->pwwn); | ||
1499 | |||
1500 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
1501 | if (!fcxp) { | ||
1502 | bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, | ||
1503 | bfa_fcs_rport_send_adisc, rport); | ||
1504 | return; | ||
1505 | } | ||
1506 | rport->fcxp = fcxp; | ||
1507 | |||
1508 | len = fc_adisc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, | ||
1509 | bfa_fcs_port_get_fcid(port), 0, | ||
1510 | port->port_cfg.pwwn, port->port_cfg.nwwn); | ||
1511 | |||
1512 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1513 | FC_CLASS_3, len, &fchs, bfa_fcs_rport_adisc_response, | ||
1514 | rport, FC_MAX_PDUSZ, FC_RA_TOV); | ||
1515 | |||
1516 | rport->stats.adisc_sent++; | ||
1517 | bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); | ||
1518 | } | ||
1519 | |||
1520 | static void | ||
1521 | bfa_fcs_rport_adisc_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
1522 | bfa_status_t req_status, u32 rsp_len, | ||
1523 | u32 resid_len, struct fchs_s *rsp_fchs) | ||
1524 | { | ||
1525 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; | ||
1526 | void *pld = bfa_fcxp_get_rspbuf(fcxp); | ||
1527 | struct fc_ls_rjt_s *ls_rjt; | ||
1528 | |||
1529 | if (req_status != BFA_STATUS_OK) { | ||
1530 | bfa_trc(rport->fcs, req_status); | ||
1531 | rport->stats.adisc_failed++; | ||
1532 | bfa_sm_send_event(rport, RPSM_EVENT_FAILED); | ||
1533 | return; | ||
1534 | } | ||
1535 | |||
1536 | if (fc_adisc_rsp_parse((struct fc_adisc_s *)pld, rsp_len, rport->pwwn, | ||
1537 | rport->nwwn) == FC_PARSE_OK) { | ||
1538 | rport->stats.adisc_accs++; | ||
1539 | bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED); | ||
1540 | return; | ||
1541 | } | ||
1542 | |||
1543 | rport->stats.adisc_rejects++; | ||
1544 | ls_rjt = pld; | ||
1545 | bfa_trc(rport->fcs, ls_rjt->els_cmd.els_code); | ||
1546 | bfa_trc(rport->fcs, ls_rjt->reason_code); | ||
1547 | bfa_trc(rport->fcs, ls_rjt->reason_code_expl); | ||
1548 | bfa_sm_send_event(rport, RPSM_EVENT_FAILED); | ||
1549 | } | ||
1550 | |||
1551 | static void | ||
1552 | bfa_fcs_rport_send_gidpn(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
1553 | { | ||
1554 | struct bfa_fcs_rport_s *rport = rport_cbarg; | ||
1555 | struct bfa_fcs_port_s *port = rport->port; | ||
1556 | struct fchs_s fchs; | ||
1557 | struct bfa_fcxp_s *fcxp; | ||
1558 | int len; | ||
1559 | |||
1560 | bfa_trc(rport->fcs, rport->pid); | ||
1561 | |||
1562 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
1563 | if (!fcxp) { | ||
1564 | bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, | ||
1565 | bfa_fcs_rport_send_gidpn, rport); | ||
1566 | return; | ||
1567 | } | ||
1568 | rport->fcxp = fcxp; | ||
1569 | |||
1570 | len = fc_gidpn_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
1571 | bfa_fcs_port_get_fcid(port), 0, rport->pwwn); | ||
1572 | |||
1573 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1574 | FC_CLASS_3, len, &fchs, bfa_fcs_rport_gidpn_response, | ||
1575 | (void *)rport, FC_MAX_PDUSZ, FC_RA_TOV); | ||
1576 | |||
1577 | bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); | ||
1578 | } | ||
1579 | |||
1580 | static void | ||
1581 | bfa_fcs_rport_gidpn_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
1582 | bfa_status_t req_status, u32 rsp_len, | ||
1583 | u32 resid_len, struct fchs_s *rsp_fchs) | ||
1584 | { | ||
1585 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; | ||
1586 | struct bfa_fcs_rport_s *twin; | ||
1587 | struct list_head *qe; | ||
1588 | struct ct_hdr_s *cthdr; | ||
1589 | struct fcgs_gidpn_resp_s *gidpn_rsp; | ||
1590 | |||
1591 | bfa_trc(rport->fcs, rport->pwwn); | ||
1592 | |||
1593 | cthdr = (struct ct_hdr_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
1594 | cthdr->cmd_rsp_code = bfa_os_ntohs(cthdr->cmd_rsp_code); | ||
1595 | |||
1596 | if (cthdr->cmd_rsp_code == CT_RSP_ACCEPT) { | ||
1597 | /* | ||
1598 | * Check if the pid is the same as before. | ||
1599 | */ | ||
1600 | gidpn_rsp = (struct fcgs_gidpn_resp_s *) (cthdr + 1); | ||
1601 | |||
1602 | if (gidpn_rsp->dap == rport->pid) { | ||
1603 | /* | ||
1604 | * Device is online | ||
1605 | */ | ||
1606 | bfa_sm_send_event(rport, RPSM_EVENT_ACCEPTED); | ||
1607 | } else { | ||
1608 | /* | ||
1609 | * Device's PID has changed. We need to cleanup and | ||
1610 | * re-login. If there is another device with the the | ||
1611 | * newly discovered pid, send an scn notice so that its | ||
1612 | * new pid can be discovered. | ||
1613 | */ | ||
1614 | list_for_each(qe, &rport->port->rport_q) { | ||
1615 | twin = (struct bfa_fcs_rport_s *)qe; | ||
1616 | if (twin == rport) | ||
1617 | continue; | ||
1618 | if (gidpn_rsp->dap == twin->pid) { | ||
1619 | bfa_trc(rport->fcs, twin->pid); | ||
1620 | bfa_trc(rport->fcs, rport->pid); | ||
1621 | |||
1622 | twin->pid = 0; | ||
1623 | bfa_sm_send_event(twin, | ||
1624 | RPSM_EVENT_ADDRESS_CHANGE); | ||
1625 | } | ||
1626 | } | ||
1627 | rport->pid = gidpn_rsp->dap; | ||
1628 | bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_CHANGE); | ||
1629 | } | ||
1630 | return; | ||
1631 | } | ||
1632 | |||
1633 | /* | ||
1634 | * Reject Response | ||
1635 | */ | ||
1636 | switch (cthdr->reason_code) { | ||
1637 | case CT_RSN_LOGICAL_BUSY: | ||
1638 | /* | ||
1639 | * Need to retry | ||
1640 | */ | ||
1641 | bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT); | ||
1642 | break; | ||
1643 | |||
1644 | case CT_RSN_UNABLE_TO_PERF: | ||
1645 | /* | ||
1646 | * device doesn't exist : Start timer to cleanup this later. | ||
1647 | */ | ||
1648 | bfa_sm_send_event(rport, RPSM_EVENT_FAILED); | ||
1649 | break; | ||
1650 | |||
1651 | default: | ||
1652 | bfa_sm_send_event(rport, RPSM_EVENT_FAILED); | ||
1653 | break; | ||
1654 | } | ||
1655 | } | ||
1656 | |||
1657 | /** | ||
1658 | * Called to send a logout to the rport. | ||
1659 | */ | ||
1660 | static void | ||
1661 | bfa_fcs_rport_send_logo(void *rport_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
1662 | { | ||
1663 | struct bfa_fcs_rport_s *rport = rport_cbarg; | ||
1664 | struct bfa_fcs_port_s *port; | ||
1665 | struct fchs_s fchs; | ||
1666 | struct bfa_fcxp_s *fcxp; | ||
1667 | u16 len; | ||
1668 | |||
1669 | bfa_trc(rport->fcs, rport->pid); | ||
1670 | |||
1671 | port = rport->port; | ||
1672 | |||
1673 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
1674 | if (!fcxp) { | ||
1675 | bfa_fcxp_alloc_wait(port->fcs->bfa, &rport->fcxp_wqe, | ||
1676 | bfa_fcs_rport_send_logo, rport); | ||
1677 | return; | ||
1678 | } | ||
1679 | rport->fcxp = fcxp; | ||
1680 | |||
1681 | len = fc_logo_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, | ||
1682 | bfa_fcs_port_get_fcid(port), 0, | ||
1683 | bfa_fcs_port_get_pwwn(port)); | ||
1684 | |||
1685 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1686 | FC_CLASS_3, len, &fchs, NULL, rport, FC_MAX_PDUSZ, | ||
1687 | FC_ED_TOV); | ||
1688 | |||
1689 | rport->stats.logos++; | ||
1690 | bfa_fcxp_discard(rport->fcxp); | ||
1691 | bfa_sm_send_event(rport, RPSM_EVENT_FCXP_SENT); | ||
1692 | } | ||
1693 | |||
1694 | /** | ||
1695 | * Send ACC for a LOGO received. | ||
1696 | */ | ||
1697 | static void | ||
1698 | bfa_fcs_rport_send_logo_acc(void *rport_cbarg) | ||
1699 | { | ||
1700 | struct bfa_fcs_rport_s *rport = rport_cbarg; | ||
1701 | struct bfa_fcs_port_s *port; | ||
1702 | struct fchs_s fchs; | ||
1703 | struct bfa_fcxp_s *fcxp; | ||
1704 | u16 len; | ||
1705 | |||
1706 | bfa_trc(rport->fcs, rport->pid); | ||
1707 | |||
1708 | port = rport->port; | ||
1709 | |||
1710 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
1711 | if (!fcxp) | ||
1712 | return; | ||
1713 | |||
1714 | rport->stats.logo_rcvd++; | ||
1715 | len = fc_logo_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, | ||
1716 | bfa_fcs_port_get_fcid(port), rport->reply_oxid); | ||
1717 | |||
1718 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1719 | FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); | ||
1720 | } | ||
1721 | |||
1722 | /** | ||
1723 | * This routine will be called by bfa_timer on timer timeouts. | ||
1724 | * | ||
1725 | * param[in] rport - pointer to bfa_fcs_port_ns_t. | ||
1726 | * param[out] rport_status - pointer to return vport status in | ||
1727 | * | ||
1728 | * return | ||
1729 | * void | ||
1730 | * | ||
1731 | * Special Considerations: | ||
1732 | * | ||
1733 | * note | ||
1734 | */ | ||
1735 | static void | ||
1736 | bfa_fcs_rport_timeout(void *arg) | ||
1737 | { | ||
1738 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)arg; | ||
1739 | |||
1740 | rport->stats.plogi_timeouts++; | ||
1741 | bfa_sm_send_event(rport, RPSM_EVENT_TIMEOUT); | ||
1742 | } | ||
1743 | |||
1744 | static void | ||
1745 | bfa_fcs_rport_process_prli(struct bfa_fcs_rport_s *rport, | ||
1746 | struct fchs_s *rx_fchs, u16 len) | ||
1747 | { | ||
1748 | struct bfa_fcxp_s *fcxp; | ||
1749 | struct fchs_s fchs; | ||
1750 | struct bfa_fcs_port_s *port = rport->port; | ||
1751 | struct fc_prli_s *prli; | ||
1752 | |||
1753 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
1754 | bfa_trc(port->fcs, rx_fchs->d_id); | ||
1755 | |||
1756 | rport->stats.prli_rcvd++; | ||
1757 | |||
1758 | if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) { | ||
1759 | /* | ||
1760 | * Target Mode : Let the fcptm handle it | ||
1761 | */ | ||
1762 | bfa_fcs_tin_rx_prli(rport->tin, rx_fchs, len); | ||
1763 | return; | ||
1764 | } | ||
1765 | |||
1766 | /* | ||
1767 | * We are either in Initiator or ipfc Mode | ||
1768 | */ | ||
1769 | prli = (struct fc_prli_s *) (rx_fchs + 1); | ||
1770 | |||
1771 | if (prli->parampage.servparams.initiator) { | ||
1772 | bfa_trc(rport->fcs, prli->parampage.type); | ||
1773 | rport->scsi_function = BFA_RPORT_INITIATOR; | ||
1774 | bfa_fcs_itnim_is_initiator(rport->itnim); | ||
1775 | } else { | ||
1776 | /* | ||
1777 | * @todo: PRLI from a target ? | ||
1778 | */ | ||
1779 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
1780 | rport->scsi_function = BFA_RPORT_TARGET; | ||
1781 | } | ||
1782 | |||
1783 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
1784 | if (!fcxp) | ||
1785 | return; | ||
1786 | |||
1787 | len = fc_prli_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, | ||
1788 | bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, | ||
1789 | port->port_cfg.roles); | ||
1790 | |||
1791 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1792 | FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); | ||
1793 | } | ||
1794 | |||
1795 | static void | ||
1796 | bfa_fcs_rport_process_rpsc(struct bfa_fcs_rport_s *rport, | ||
1797 | struct fchs_s *rx_fchs, u16 len) | ||
1798 | { | ||
1799 | struct bfa_fcxp_s *fcxp; | ||
1800 | struct fchs_s fchs; | ||
1801 | struct bfa_fcs_port_s *port = rport->port; | ||
1802 | struct fc_rpsc_speed_info_s speeds; | ||
1803 | struct bfa_pport_attr_s pport_attr; | ||
1804 | |||
1805 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
1806 | bfa_trc(port->fcs, rx_fchs->d_id); | ||
1807 | |||
1808 | rport->stats.rpsc_rcvd++; | ||
1809 | speeds.port_speed_cap = | ||
1810 | RPSC_SPEED_CAP_1G | RPSC_SPEED_CAP_2G | RPSC_SPEED_CAP_4G | | ||
1811 | RPSC_SPEED_CAP_8G; | ||
1812 | |||
1813 | /* | ||
1814 | * get curent speed from pport attributes from BFA | ||
1815 | */ | ||
1816 | bfa_pport_get_attr(port->fcs->bfa, &pport_attr); | ||
1817 | |||
1818 | speeds.port_op_speed = fc_bfa_speed_to_rpsc_operspeed(pport_attr.speed); | ||
1819 | |||
1820 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
1821 | if (!fcxp) | ||
1822 | return; | ||
1823 | |||
1824 | len = fc_rpsc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, | ||
1825 | bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, | ||
1826 | &speeds); | ||
1827 | |||
1828 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
1829 | FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); | ||
1830 | } | ||
1831 | |||
1832 | static void | ||
1833 | bfa_fcs_rport_process_adisc(struct bfa_fcs_rport_s *rport, | ||
1834 | struct fchs_s *rx_fchs, u16 len) | ||
1835 | { | ||
1836 | struct bfa_fcxp_s *fcxp; | ||
1837 | struct fchs_s fchs; | ||
1838 | struct bfa_fcs_port_s *port = rport->port; | ||
1839 | struct fc_adisc_s *adisc; | ||
1840 | |||
1841 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
1842 | bfa_trc(port->fcs, rx_fchs->d_id); | ||
1843 | |||
1844 | rport->stats.adisc_rcvd++; | ||
1845 | |||
1846 | if (BFA_FCS_VPORT_IS_TARGET_MODE(port)) { | ||
1847 | /* | ||
1848 | * @todo : Target Mode handling | ||
1849 | */ | ||
1850 | bfa_trc(port->fcs, rx_fchs->d_id); | ||
1851 | bfa_assert(0); | ||
1852 | return; | ||
1853 | } | ||
1854 | |||
1855 | adisc = (struct fc_adisc_s *) (rx_fchs + 1); | ||
1856 | |||
1857 | /* | ||
1858 | * Accept if the itnim for this rport is online. Else reject the ADISC | ||
1859 | */ | ||
1860 | if (bfa_fcs_itnim_get_online_state(rport->itnim) == BFA_STATUS_OK) { | ||
1861 | |||
1862 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
1863 | if (!fcxp) | ||
1864 | return; | ||
1865 | |||
1866 | len = fc_adisc_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
1867 | rx_fchs->s_id, | ||
1868 | bfa_fcs_port_get_fcid(port), | ||
1869 | rx_fchs->ox_id, port->port_cfg.pwwn, | ||
1870 | port->port_cfg.nwwn); | ||
1871 | |||
1872 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, | ||
1873 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, | ||
1874 | FC_MAX_PDUSZ, 0); | ||
1875 | } else { | ||
1876 | rport->stats.adisc_rejected++; | ||
1877 | bfa_fcs_rport_send_ls_rjt(rport, rx_fchs, | ||
1878 | FC_LS_RJT_RSN_UNABLE_TO_PERF_CMD, | ||
1879 | FC_LS_RJT_EXP_LOGIN_REQUIRED); | ||
1880 | } | ||
1881 | |||
1882 | } | ||
1883 | |||
1884 | static void | ||
1885 | bfa_fcs_rport_hal_online(struct bfa_fcs_rport_s *rport) | ||
1886 | { | ||
1887 | struct bfa_fcs_port_s *port = rport->port; | ||
1888 | struct bfa_rport_info_s rport_info; | ||
1889 | |||
1890 | rport_info.pid = rport->pid; | ||
1891 | rport_info.local_pid = port->pid; | ||
1892 | rport_info.lp_tag = port->lp_tag; | ||
1893 | rport_info.vf_id = port->fabric->vf_id; | ||
1894 | rport_info.vf_en = port->fabric->is_vf; | ||
1895 | rport_info.fc_class = rport->fc_cos; | ||
1896 | rport_info.cisc = rport->cisc; | ||
1897 | rport_info.max_frmsz = rport->maxfrsize; | ||
1898 | bfa_rport_online(rport->bfa_rport, &rport_info); | ||
1899 | } | ||
1900 | |||
1901 | static void | ||
1902 | bfa_fcs_rport_fc4_pause(struct bfa_fcs_rport_s *rport) | ||
1903 | { | ||
1904 | if (bfa_fcs_port_is_initiator(rport->port)) | ||
1905 | bfa_fcs_itnim_pause(rport->itnim); | ||
1906 | |||
1907 | if (bfa_fcs_port_is_target(rport->port)) | ||
1908 | bfa_fcs_tin_pause(rport->tin); | ||
1909 | } | ||
1910 | |||
1911 | static void | ||
1912 | bfa_fcs_rport_fc4_resume(struct bfa_fcs_rport_s *rport) | ||
1913 | { | ||
1914 | if (bfa_fcs_port_is_initiator(rport->port)) | ||
1915 | bfa_fcs_itnim_resume(rport->itnim); | ||
1916 | |||
1917 | if (bfa_fcs_port_is_target(rport->port)) | ||
1918 | bfa_fcs_tin_resume(rport->tin); | ||
1919 | } | ||
1920 | |||
1921 | static struct bfa_fcs_rport_s * | ||
1922 | bfa_fcs_rport_alloc(struct bfa_fcs_port_s *port, wwn_t pwwn, u32 rpid) | ||
1923 | { | ||
1924 | struct bfa_fcs_s *fcs = port->fcs; | ||
1925 | struct bfa_fcs_rport_s *rport; | ||
1926 | struct bfad_rport_s *rport_drv; | ||
1927 | |||
1928 | /** | ||
1929 | * allocate rport | ||
1930 | */ | ||
1931 | if (bfa_fcb_rport_alloc(fcs->bfad, &rport, &rport_drv) | ||
1932 | != BFA_STATUS_OK) { | ||
1933 | bfa_trc(fcs, rpid); | ||
1934 | return NULL; | ||
1935 | } | ||
1936 | |||
1937 | /* | ||
1938 | * Initialize r-port | ||
1939 | */ | ||
1940 | rport->port = port; | ||
1941 | rport->fcs = fcs; | ||
1942 | rport->rp_drv = rport_drv; | ||
1943 | rport->pid = rpid; | ||
1944 | rport->pwwn = pwwn; | ||
1945 | |||
1946 | /** | ||
1947 | * allocate BFA rport | ||
1948 | */ | ||
1949 | rport->bfa_rport = bfa_rport_create(port->fcs->bfa, rport); | ||
1950 | if (!rport->bfa_rport) { | ||
1951 | bfa_trc(fcs, rpid); | ||
1952 | kfree(rport_drv); | ||
1953 | return NULL; | ||
1954 | } | ||
1955 | |||
1956 | /** | ||
1957 | * allocate FC-4s | ||
1958 | */ | ||
1959 | bfa_assert(bfa_fcs_port_is_initiator(port) ^ | ||
1960 | bfa_fcs_port_is_target(port)); | ||
1961 | |||
1962 | if (bfa_fcs_port_is_initiator(port)) { | ||
1963 | rport->itnim = bfa_fcs_itnim_create(rport); | ||
1964 | if (!rport->itnim) { | ||
1965 | bfa_trc(fcs, rpid); | ||
1966 | bfa_rport_delete(rport->bfa_rport); | ||
1967 | kfree(rport_drv); | ||
1968 | return NULL; | ||
1969 | } | ||
1970 | } | ||
1971 | |||
1972 | if (bfa_fcs_port_is_target(port)) { | ||
1973 | rport->tin = bfa_fcs_tin_create(rport); | ||
1974 | if (!rport->tin) { | ||
1975 | bfa_trc(fcs, rpid); | ||
1976 | bfa_rport_delete(rport->bfa_rport); | ||
1977 | kfree(rport_drv); | ||
1978 | return NULL; | ||
1979 | } | ||
1980 | } | ||
1981 | |||
1982 | bfa_fcs_port_add_rport(port, rport); | ||
1983 | |||
1984 | bfa_sm_set_state(rport, bfa_fcs_rport_sm_uninit); | ||
1985 | |||
1986 | /* | ||
1987 | * Initialize the Rport Features(RPF) Sub Module | ||
1988 | */ | ||
1989 | if (!BFA_FCS_PID_IS_WKA(rport->pid)) | ||
1990 | bfa_fcs_rpf_init(rport); | ||
1991 | |||
1992 | return rport; | ||
1993 | } | ||
1994 | |||
1995 | |||
1996 | static void | ||
1997 | bfa_fcs_rport_free(struct bfa_fcs_rport_s *rport) | ||
1998 | { | ||
1999 | struct bfa_fcs_port_s *port = rport->port; | ||
2000 | |||
2001 | /** | ||
2002 | * - delete FC-4s | ||
2003 | * - delete BFA rport | ||
2004 | * - remove from queue of rports | ||
2005 | */ | ||
2006 | if (bfa_fcs_port_is_initiator(port)) | ||
2007 | bfa_fcs_itnim_delete(rport->itnim); | ||
2008 | |||
2009 | if (bfa_fcs_port_is_target(port)) | ||
2010 | bfa_fcs_tin_delete(rport->tin); | ||
2011 | |||
2012 | bfa_rport_delete(rport->bfa_rport); | ||
2013 | bfa_fcs_port_del_rport(port, rport); | ||
2014 | kfree(rport->rp_drv); | ||
2015 | } | ||
2016 | |||
2017 | static void | ||
2018 | bfa_fcs_rport_aen_post(struct bfa_fcs_rport_s *rport, | ||
2019 | enum bfa_rport_aen_event event, | ||
2020 | struct bfa_rport_aen_data_s *data) | ||
2021 | { | ||
2022 | union bfa_aen_data_u aen_data; | ||
2023 | struct bfa_log_mod_s *logmod = rport->fcs->logm; | ||
2024 | wwn_t lpwwn = bfa_fcs_port_get_pwwn(rport->port); | ||
2025 | wwn_t rpwwn = rport->pwwn; | ||
2026 | char lpwwn_ptr[BFA_STRING_32]; | ||
2027 | char rpwwn_ptr[BFA_STRING_32]; | ||
2028 | char *prio_str[] = { "unknown", "high", "medium", "low" }; | ||
2029 | |||
2030 | wwn2str(lpwwn_ptr, lpwwn); | ||
2031 | wwn2str(rpwwn_ptr, rpwwn); | ||
2032 | |||
2033 | switch (event) { | ||
2034 | case BFA_RPORT_AEN_ONLINE: | ||
2035 | bfa_log(logmod, BFA_AEN_RPORT_ONLINE, rpwwn_ptr, lpwwn_ptr); | ||
2036 | break; | ||
2037 | case BFA_RPORT_AEN_OFFLINE: | ||
2038 | bfa_log(logmod, BFA_AEN_RPORT_OFFLINE, rpwwn_ptr, lpwwn_ptr); | ||
2039 | break; | ||
2040 | case BFA_RPORT_AEN_DISCONNECT: | ||
2041 | bfa_log(logmod, BFA_AEN_RPORT_DISCONNECT, rpwwn_ptr, lpwwn_ptr); | ||
2042 | break; | ||
2043 | case BFA_RPORT_AEN_QOS_PRIO: | ||
2044 | aen_data.rport.priv.qos = data->priv.qos; | ||
2045 | bfa_log(logmod, BFA_AEN_RPORT_QOS_PRIO, | ||
2046 | prio_str[aen_data.rport.priv.qos.qos_priority], | ||
2047 | rpwwn_ptr, lpwwn_ptr); | ||
2048 | break; | ||
2049 | case BFA_RPORT_AEN_QOS_FLOWID: | ||
2050 | aen_data.rport.priv.qos = data->priv.qos; | ||
2051 | bfa_log(logmod, BFA_AEN_RPORT_QOS_FLOWID, | ||
2052 | aen_data.rport.priv.qos.qos_flow_id, rpwwn_ptr, | ||
2053 | lpwwn_ptr); | ||
2054 | break; | ||
2055 | default: | ||
2056 | break; | ||
2057 | } | ||
2058 | |||
2059 | aen_data.rport.vf_id = rport->port->fabric->vf_id; | ||
2060 | aen_data.rport.ppwwn = | ||
2061 | bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(rport->fcs)); | ||
2062 | aen_data.rport.lpwwn = lpwwn; | ||
2063 | aen_data.rport.rpwwn = rpwwn; | ||
2064 | } | ||
2065 | |||
2066 | static void | ||
2067 | bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport) | ||
2068 | { | ||
2069 | struct bfa_fcs_port_s *port = rport->port; | ||
2070 | |||
2071 | rport->stats.onlines++; | ||
2072 | |||
2073 | if (bfa_fcs_port_is_initiator(port)) { | ||
2074 | bfa_fcs_itnim_rport_online(rport->itnim); | ||
2075 | if (!BFA_FCS_PID_IS_WKA(rport->pid)) | ||
2076 | bfa_fcs_rpf_rport_online(rport); | ||
2077 | }; | ||
2078 | |||
2079 | if (bfa_fcs_port_is_target(port)) | ||
2080 | bfa_fcs_tin_rport_online(rport->tin); | ||
2081 | |||
2082 | /* | ||
2083 | * Don't post events for well known addresses | ||
2084 | */ | ||
2085 | if (!BFA_FCS_PID_IS_WKA(rport->pid)) | ||
2086 | bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_ONLINE, NULL); | ||
2087 | } | ||
2088 | |||
2089 | static void | ||
2090 | bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport) | ||
2091 | { | ||
2092 | struct bfa_fcs_port_s *port = rport->port; | ||
2093 | |||
2094 | rport->stats.offlines++; | ||
2095 | |||
2096 | /* | ||
2097 | * Don't post events for well known addresses | ||
2098 | */ | ||
2099 | if (!BFA_FCS_PID_IS_WKA(rport->pid)) { | ||
2100 | if (bfa_fcs_port_is_online(rport->port) == BFA_TRUE) { | ||
2101 | bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_DISCONNECT, | ||
2102 | NULL); | ||
2103 | } else { | ||
2104 | bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_OFFLINE, | ||
2105 | NULL); | ||
2106 | } | ||
2107 | } | ||
2108 | |||
2109 | if (bfa_fcs_port_is_initiator(port)) { | ||
2110 | bfa_fcs_itnim_rport_offline(rport->itnim); | ||
2111 | if (!BFA_FCS_PID_IS_WKA(rport->pid)) | ||
2112 | bfa_fcs_rpf_rport_offline(rport); | ||
2113 | } | ||
2114 | |||
2115 | if (bfa_fcs_port_is_target(port)) | ||
2116 | bfa_fcs_tin_rport_offline(rport->tin); | ||
2117 | } | ||
2118 | |||
2119 | /** | ||
2120 | * Update rport parameters from PLOGI or PLOGI accept. | ||
2121 | */ | ||
2122 | static void | ||
2123 | bfa_fcs_rport_update(struct bfa_fcs_rport_s *rport, struct fc_logi_s *plogi) | ||
2124 | { | ||
2125 | struct bfa_fcs_port_s *port = rport->port; | ||
2126 | |||
2127 | /** | ||
2128 | * - port name | ||
2129 | * - node name | ||
2130 | */ | ||
2131 | rport->pwwn = plogi->port_name; | ||
2132 | rport->nwwn = plogi->node_name; | ||
2133 | |||
2134 | /** | ||
2135 | * - class of service | ||
2136 | */ | ||
2137 | rport->fc_cos = 0; | ||
2138 | if (plogi->class3.class_valid) | ||
2139 | rport->fc_cos = FC_CLASS_3; | ||
2140 | |||
2141 | if (plogi->class2.class_valid) | ||
2142 | rport->fc_cos |= FC_CLASS_2; | ||
2143 | |||
2144 | /** | ||
2145 | * - CISC | ||
2146 | * - MAX receive frame size | ||
2147 | */ | ||
2148 | rport->cisc = plogi->csp.cisc; | ||
2149 | rport->maxfrsize = bfa_os_ntohs(plogi->class3.rxsz); | ||
2150 | |||
2151 | bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred)); | ||
2152 | bfa_trc(port->fcs, port->fabric->bb_credit); | ||
2153 | /** | ||
2154 | * Direct Attach P2P mode : | ||
2155 | * This is to handle a bug (233476) in IBM targets in Direct Attach | ||
2156 | * Mode. Basically, in FLOGI Accept the target would have erroneously | ||
2157 | * set the BB Credit to the value used in the FLOGI sent by the HBA. | ||
2158 | * It uses the correct value (its own BB credit) in PLOGI. | ||
2159 | */ | ||
2160 | if ((!bfa_fcs_fabric_is_switched(port->fabric)) | ||
2161 | && (bfa_os_ntohs(plogi->csp.bbcred) < port->fabric->bb_credit)) { | ||
2162 | |||
2163 | bfa_trc(port->fcs, bfa_os_ntohs(plogi->csp.bbcred)); | ||
2164 | bfa_trc(port->fcs, port->fabric->bb_credit); | ||
2165 | |||
2166 | port->fabric->bb_credit = bfa_os_ntohs(plogi->csp.bbcred); | ||
2167 | bfa_pport_set_tx_bbcredit(port->fcs->bfa, | ||
2168 | port->fabric->bb_credit); | ||
2169 | } | ||
2170 | |||
2171 | } | ||
2172 | |||
2173 | /** | ||
2174 | * Called to handle LOGO received from an existing remote port. | ||
2175 | */ | ||
2176 | static void | ||
2177 | bfa_fcs_rport_process_logo(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs) | ||
2178 | { | ||
2179 | rport->reply_oxid = fchs->ox_id; | ||
2180 | bfa_trc(rport->fcs, rport->reply_oxid); | ||
2181 | |||
2182 | rport->stats.logo_rcvd++; | ||
2183 | bfa_sm_send_event(rport, RPSM_EVENT_LOGO_RCVD); | ||
2184 | } | ||
2185 | |||
2186 | |||
2187 | |||
2188 | /** | ||
2189 | * fcs_rport_public FCS rport public interfaces | ||
2190 | */ | ||
2191 | |||
2192 | /** | ||
2193 | * Called by bport/vport to create a remote port instance for a discovered | ||
2194 | * remote device. | ||
2195 | * | ||
2196 | * @param[in] port - base port or vport | ||
2197 | * @param[in] rpid - remote port ID | ||
2198 | * | ||
2199 | * @return None | ||
2200 | */ | ||
2201 | struct bfa_fcs_rport_s * | ||
2202 | bfa_fcs_rport_create(struct bfa_fcs_port_s *port, u32 rpid) | ||
2203 | { | ||
2204 | struct bfa_fcs_rport_s *rport; | ||
2205 | |||
2206 | bfa_trc(port->fcs, rpid); | ||
2207 | rport = bfa_fcs_rport_alloc(port, WWN_NULL, rpid); | ||
2208 | if (!rport) | ||
2209 | return NULL; | ||
2210 | |||
2211 | bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); | ||
2212 | return rport; | ||
2213 | } | ||
2214 | |||
2215 | /** | ||
2216 | * Called to create a rport for which only the wwn is known. | ||
2217 | * | ||
2218 | * @param[in] port - base port | ||
2219 | * @param[in] rpwwn - remote port wwn | ||
2220 | * | ||
2221 | * @return None | ||
2222 | */ | ||
2223 | struct bfa_fcs_rport_s * | ||
2224 | bfa_fcs_rport_create_by_wwn(struct bfa_fcs_port_s *port, wwn_t rpwwn) | ||
2225 | { | ||
2226 | struct bfa_fcs_rport_s *rport; | ||
2227 | |||
2228 | bfa_trc(port->fcs, rpwwn); | ||
2229 | rport = bfa_fcs_rport_alloc(port, rpwwn, 0); | ||
2230 | if (!rport) | ||
2231 | return NULL; | ||
2232 | |||
2233 | bfa_sm_send_event(rport, RPSM_EVENT_ADDRESS_DISC); | ||
2234 | return rport; | ||
2235 | } | ||
2236 | |||
2237 | /** | ||
2238 | * Called by bport in private loop topology to indicate that a | ||
2239 | * rport has been discovered and plogi has been completed. | ||
2240 | * | ||
2241 | * @param[in] port - base port or vport | ||
2242 | * @param[in] rpid - remote port ID | ||
2243 | */ | ||
2244 | void | ||
2245 | bfa_fcs_rport_start(struct bfa_fcs_port_s *port, struct fchs_s *fchs, | ||
2246 | struct fc_logi_s *plogi) | ||
2247 | { | ||
2248 | struct bfa_fcs_rport_s *rport; | ||
2249 | |||
2250 | rport = bfa_fcs_rport_alloc(port, WWN_NULL, fchs->s_id); | ||
2251 | if (!rport) | ||
2252 | return; | ||
2253 | |||
2254 | bfa_fcs_rport_update(rport, plogi); | ||
2255 | |||
2256 | bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_COMP); | ||
2257 | } | ||
2258 | |||
2259 | /** | ||
2260 | * Called by bport/vport to handle PLOGI received from a new remote port. | ||
2261 | * If an existing rport does a plogi, it will be handled separately. | ||
2262 | */ | ||
2263 | void | ||
2264 | bfa_fcs_rport_plogi_create(struct bfa_fcs_port_s *port, struct fchs_s *fchs, | ||
2265 | struct fc_logi_s *plogi) | ||
2266 | { | ||
2267 | struct bfa_fcs_rport_s *rport; | ||
2268 | |||
2269 | rport = bfa_fcs_rport_alloc(port, plogi->port_name, fchs->s_id); | ||
2270 | if (!rport) | ||
2271 | return; | ||
2272 | |||
2273 | bfa_fcs_rport_update(rport, plogi); | ||
2274 | |||
2275 | rport->reply_oxid = fchs->ox_id; | ||
2276 | bfa_trc(rport->fcs, rport->reply_oxid); | ||
2277 | |||
2278 | rport->stats.plogi_rcvd++; | ||
2279 | bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); | ||
2280 | } | ||
2281 | |||
2282 | static int | ||
2283 | wwn_compare(wwn_t wwn1, wwn_t wwn2) | ||
2284 | { | ||
2285 | u8 *b1 = (u8 *) &wwn1; | ||
2286 | u8 *b2 = (u8 *) &wwn2; | ||
2287 | int i; | ||
2288 | |||
2289 | for (i = 0; i < sizeof(wwn_t); i++) { | ||
2290 | if (b1[i] < b2[i]) | ||
2291 | return -1; | ||
2292 | if (b1[i] > b2[i]) | ||
2293 | return 1; | ||
2294 | } | ||
2295 | return 0; | ||
2296 | } | ||
2297 | |||
2298 | /** | ||
2299 | * Called by bport/vport to handle PLOGI received from an existing | ||
2300 | * remote port. | ||
2301 | */ | ||
2302 | void | ||
2303 | bfa_fcs_rport_plogi(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, | ||
2304 | struct fc_logi_s *plogi) | ||
2305 | { | ||
2306 | /** | ||
2307 | * @todo Handle P2P and initiator-initiator. | ||
2308 | */ | ||
2309 | |||
2310 | bfa_fcs_rport_update(rport, plogi); | ||
2311 | |||
2312 | rport->reply_oxid = rx_fchs->ox_id; | ||
2313 | bfa_trc(rport->fcs, rport->reply_oxid); | ||
2314 | |||
2315 | /** | ||
2316 | * In Switched fabric topology, | ||
2317 | * PLOGI to each other. If our pwwn is smaller, ignore it, | ||
2318 | * if it is not a well known address. | ||
2319 | * If the link topology is N2N, | ||
2320 | * this Plogi should be accepted. | ||
2321 | */ | ||
2322 | if ((wwn_compare(rport->port->port_cfg.pwwn, rport->pwwn) == -1) | ||
2323 | && (bfa_fcs_fabric_is_switched(rport->port->fabric)) | ||
2324 | && (!BFA_FCS_PID_IS_WKA(rport->pid))) { | ||
2325 | bfa_trc(rport->fcs, rport->pid); | ||
2326 | return; | ||
2327 | } | ||
2328 | |||
2329 | rport->stats.plogi_rcvd++; | ||
2330 | bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_RCVD); | ||
2331 | } | ||
2332 | |||
2333 | /** | ||
2334 | * Called by bport/vport to delete a remote port instance. | ||
2335 | * | ||
2336 | * Rport delete is called under the following conditions: | ||
2337 | * - vport is deleted | ||
2338 | * - vf is deleted | ||
2339 | * - explicit request from OS to delete rport (vmware) | ||
2340 | */ | ||
2341 | void | ||
2342 | bfa_fcs_rport_delete(struct bfa_fcs_rport_s *rport) | ||
2343 | { | ||
2344 | bfa_sm_send_event(rport, RPSM_EVENT_DELETE); | ||
2345 | } | ||
2346 | |||
2347 | /** | ||
2348 | * Called by bport/vport to when a target goes offline. | ||
2349 | * | ||
2350 | */ | ||
2351 | void | ||
2352 | bfa_fcs_rport_offline(struct bfa_fcs_rport_s *rport) | ||
2353 | { | ||
2354 | bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); | ||
2355 | } | ||
2356 | |||
2357 | /** | ||
2358 | * Called by bport in n2n when a target (attached port) becomes online. | ||
2359 | * | ||
2360 | */ | ||
2361 | void | ||
2362 | bfa_fcs_rport_online(struct bfa_fcs_rport_s *rport) | ||
2363 | { | ||
2364 | bfa_sm_send_event(rport, RPSM_EVENT_PLOGI_SEND); | ||
2365 | } | ||
2366 | |||
2367 | /** | ||
2368 | * Called by bport/vport to notify SCN for the remote port | ||
2369 | */ | ||
2370 | void | ||
2371 | bfa_fcs_rport_scn(struct bfa_fcs_rport_s *rport) | ||
2372 | { | ||
2373 | |||
2374 | rport->stats.rscns++; | ||
2375 | bfa_sm_send_event(rport, RPSM_EVENT_SCN); | ||
2376 | } | ||
2377 | |||
2378 | /** | ||
2379 | * Called by fcpim to notify that the ITN cleanup is done. | ||
2380 | */ | ||
2381 | void | ||
2382 | bfa_fcs_rport_itnim_ack(struct bfa_fcs_rport_s *rport) | ||
2383 | { | ||
2384 | bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); | ||
2385 | } | ||
2386 | |||
2387 | /** | ||
2388 | * Called by fcptm to notify that the ITN cleanup is done. | ||
2389 | */ | ||
2390 | void | ||
2391 | bfa_fcs_rport_tin_ack(struct bfa_fcs_rport_s *rport) | ||
2392 | { | ||
2393 | bfa_sm_send_event(rport, RPSM_EVENT_FC4_OFFLINE); | ||
2394 | } | ||
2395 | |||
2396 | /** | ||
2397 | * This routine BFA callback for bfa_rport_online() call. | ||
2398 | * | ||
2399 | * param[in] cb_arg - rport struct. | ||
2400 | * | ||
2401 | * return | ||
2402 | * void | ||
2403 | * | ||
2404 | * Special Considerations: | ||
2405 | * | ||
2406 | * note | ||
2407 | */ | ||
2408 | void | ||
2409 | bfa_cb_rport_online(void *cbarg) | ||
2410 | { | ||
2411 | |||
2412 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; | ||
2413 | |||
2414 | bfa_trc(rport->fcs, rport->pwwn); | ||
2415 | bfa_sm_send_event(rport, RPSM_EVENT_HCB_ONLINE); | ||
2416 | } | ||
2417 | |||
2418 | /** | ||
2419 | * This routine BFA callback for bfa_rport_offline() call. | ||
2420 | * | ||
2421 | * param[in] rport - | ||
2422 | * | ||
2423 | * return | ||
2424 | * void | ||
2425 | * | ||
2426 | * Special Considerations: | ||
2427 | * | ||
2428 | * note | ||
2429 | */ | ||
2430 | void | ||
2431 | bfa_cb_rport_offline(void *cbarg) | ||
2432 | { | ||
2433 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; | ||
2434 | |||
2435 | bfa_trc(rport->fcs, rport->pwwn); | ||
2436 | bfa_sm_send_event(rport, RPSM_EVENT_HCB_OFFLINE); | ||
2437 | } | ||
2438 | |||
2439 | /** | ||
2440 | * This routine is a static BFA callback when there is a QoS flow_id | ||
2441 | * change notification | ||
2442 | * | ||
2443 | * @param[in] rport - | ||
2444 | * | ||
2445 | * @return void | ||
2446 | * | ||
2447 | * Special Considerations: | ||
2448 | * | ||
2449 | * @note | ||
2450 | */ | ||
2451 | void | ||
2452 | bfa_cb_rport_qos_scn_flowid(void *cbarg, | ||
2453 | struct bfa_rport_qos_attr_s old_qos_attr, | ||
2454 | struct bfa_rport_qos_attr_s new_qos_attr) | ||
2455 | { | ||
2456 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; | ||
2457 | struct bfa_rport_aen_data_s aen_data; | ||
2458 | |||
2459 | bfa_trc(rport->fcs, rport->pwwn); | ||
2460 | aen_data.priv.qos = new_qos_attr; | ||
2461 | bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_FLOWID, &aen_data); | ||
2462 | } | ||
2463 | |||
2464 | /** | ||
2465 | * This routine is a static BFA callback when there is a QoS priority | ||
2466 | * change notification | ||
2467 | * | ||
2468 | * @param[in] rport - | ||
2469 | * | ||
2470 | * @return void | ||
2471 | * | ||
2472 | * Special Considerations: | ||
2473 | * | ||
2474 | * @note | ||
2475 | */ | ||
2476 | void | ||
2477 | bfa_cb_rport_qos_scn_prio(void *cbarg, struct bfa_rport_qos_attr_s old_qos_attr, | ||
2478 | struct bfa_rport_qos_attr_s new_qos_attr) | ||
2479 | { | ||
2480 | struct bfa_fcs_rport_s *rport = (struct bfa_fcs_rport_s *)cbarg; | ||
2481 | struct bfa_rport_aen_data_s aen_data; | ||
2482 | |||
2483 | bfa_trc(rport->fcs, rport->pwwn); | ||
2484 | aen_data.priv.qos = new_qos_attr; | ||
2485 | bfa_fcs_rport_aen_post(rport, BFA_RPORT_AEN_QOS_PRIO, &aen_data); | ||
2486 | } | ||
2487 | |||
2488 | /** | ||
2489 | * Called to process any unsolicted frames from this remote port | ||
2490 | */ | ||
2491 | void | ||
2492 | bfa_fcs_rport_logo_imp(struct bfa_fcs_rport_s *rport) | ||
2493 | { | ||
2494 | bfa_sm_send_event(rport, RPSM_EVENT_LOGO_IMP); | ||
2495 | } | ||
2496 | |||
2497 | /** | ||
2498 | * Called to process any unsolicted frames from this remote port | ||
2499 | */ | ||
2500 | void | ||
2501 | bfa_fcs_rport_uf_recv(struct bfa_fcs_rport_s *rport, struct fchs_s *fchs, | ||
2502 | u16 len) | ||
2503 | { | ||
2504 | struct bfa_fcs_port_s *port = rport->port; | ||
2505 | struct fc_els_cmd_s *els_cmd; | ||
2506 | |||
2507 | bfa_trc(rport->fcs, fchs->s_id); | ||
2508 | bfa_trc(rport->fcs, fchs->d_id); | ||
2509 | bfa_trc(rport->fcs, fchs->type); | ||
2510 | |||
2511 | if (fchs->type != FC_TYPE_ELS) | ||
2512 | return; | ||
2513 | |||
2514 | els_cmd = (struct fc_els_cmd_s *) (fchs + 1); | ||
2515 | |||
2516 | bfa_trc(rport->fcs, els_cmd->els_code); | ||
2517 | |||
2518 | switch (els_cmd->els_code) { | ||
2519 | case FC_ELS_LOGO: | ||
2520 | bfa_fcs_rport_process_logo(rport, fchs); | ||
2521 | break; | ||
2522 | |||
2523 | case FC_ELS_ADISC: | ||
2524 | bfa_fcs_rport_process_adisc(rport, fchs, len); | ||
2525 | break; | ||
2526 | |||
2527 | case FC_ELS_PRLO: | ||
2528 | if (bfa_fcs_port_is_initiator(port)) | ||
2529 | bfa_fcs_fcpim_uf_recv(rport->itnim, fchs, len); | ||
2530 | |||
2531 | if (bfa_fcs_port_is_target(port)) | ||
2532 | bfa_fcs_fcptm_uf_recv(rport->tin, fchs, len); | ||
2533 | break; | ||
2534 | |||
2535 | case FC_ELS_PRLI: | ||
2536 | bfa_fcs_rport_process_prli(rport, fchs, len); | ||
2537 | break; | ||
2538 | |||
2539 | case FC_ELS_RPSC: | ||
2540 | bfa_fcs_rport_process_rpsc(rport, fchs, len); | ||
2541 | break; | ||
2542 | |||
2543 | default: | ||
2544 | bfa_fcs_rport_send_ls_rjt(rport, fchs, | ||
2545 | FC_LS_RJT_RSN_CMD_NOT_SUPP, | ||
2546 | FC_LS_RJT_EXP_NO_ADDL_INFO); | ||
2547 | break; | ||
2548 | } | ||
2549 | } | ||
2550 | |||
2551 | /* | ||
2552 | * Send a LS reject | ||
2553 | */ | ||
2554 | static void | ||
2555 | bfa_fcs_rport_send_ls_rjt(struct bfa_fcs_rport_s *rport, struct fchs_s *rx_fchs, | ||
2556 | u8 reason_code, u8 reason_code_expl) | ||
2557 | { | ||
2558 | struct bfa_fcs_port_s *port = rport->port; | ||
2559 | struct fchs_s fchs; | ||
2560 | struct bfa_fcxp_s *fcxp; | ||
2561 | int len; | ||
2562 | |||
2563 | bfa_trc(rport->fcs, rx_fchs->s_id); | ||
2564 | |||
2565 | fcxp = bfa_fcs_fcxp_alloc(rport->fcs); | ||
2566 | if (!fcxp) | ||
2567 | return; | ||
2568 | |||
2569 | len = fc_ls_rjt_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, | ||
2570 | bfa_fcs_port_get_fcid(port), rx_fchs->ox_id, | ||
2571 | reason_code, reason_code_expl); | ||
2572 | |||
2573 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
2574 | FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); | ||
2575 | } | ||
2576 | |||
2577 | /** | ||
2578 | * Module initialization | ||
2579 | */ | ||
2580 | void | ||
2581 | bfa_fcs_rport_modinit(struct bfa_fcs_s *fcs) | ||
2582 | { | ||
2583 | } | ||
2584 | |||
2585 | /** | ||
2586 | * Module cleanup | ||
2587 | */ | ||
2588 | void | ||
2589 | bfa_fcs_rport_modexit(struct bfa_fcs_s *fcs) | ||
2590 | { | ||
2591 | bfa_fcs_modexit_comp(fcs); | ||
2592 | } | ||
2593 | |||
2594 | /** | ||
2595 | * Return state of rport. | ||
2596 | */ | ||
2597 | int | ||
2598 | bfa_fcs_rport_get_state(struct bfa_fcs_rport_s *rport) | ||
2599 | { | ||
2600 | return bfa_sm_to_state(rport_sm_table, rport->sm); | ||
2601 | } | ||
2602 | |||
2603 | /** | ||
2604 | * Called by the Driver to set rport delete/ageout timeout | ||
2605 | * | ||
2606 | * param[in] rport timeout value in seconds. | ||
2607 | * | ||
2608 | * return None | ||
2609 | */ | ||
2610 | void | ||
2611 | bfa_fcs_rport_set_del_timeout(u8 rport_tmo) | ||
2612 | { | ||
2613 | /* | ||
2614 | * convert to Millisecs | ||
2615 | */ | ||
2616 | if (rport_tmo > 0) | ||
2617 | bfa_fcs_rport_del_timeout = rport_tmo * 1000; | ||
2618 | } | ||
diff --git a/drivers/scsi/bfa/rport_api.c b/drivers/scsi/bfa/rport_api.c new file mode 100644 index 000000000000..3dae1774181e --- /dev/null +++ b/drivers/scsi/bfa/rport_api.c | |||
@@ -0,0 +1,180 @@ | |||
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 | #include <bfa.h> | ||
18 | #include <bfa_svc.h> | ||
19 | #include "fcs_vport.h" | ||
20 | #include "fcs_lport.h" | ||
21 | #include "fcs_rport.h" | ||
22 | #include "fcs_trcmod.h" | ||
23 | |||
24 | BFA_TRC_FILE(FCS, RPORT_API); | ||
25 | |||
26 | /** | ||
27 | * rport_api.c Remote port implementation. | ||
28 | */ | ||
29 | |||
30 | /** | ||
31 | * fcs_rport_api FCS rport API. | ||
32 | */ | ||
33 | |||
34 | /** | ||
35 | * Direct API to add a target by port wwn. This interface is used, for | ||
36 | * example, by bios when target pwwn is known from boot lun configuration. | ||
37 | */ | ||
38 | bfa_status_t | ||
39 | bfa_fcs_rport_add(struct bfa_fcs_port_s *port, wwn_t *pwwn, | ||
40 | struct bfa_fcs_rport_s *rport, | ||
41 | struct bfad_rport_s *rport_drv) | ||
42 | { | ||
43 | bfa_trc(port->fcs, *pwwn); | ||
44 | |||
45 | return BFA_STATUS_OK; | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Direct API to remove a target and its associated resources. This | ||
50 | * interface is used, for example, by vmware driver to remove target | ||
51 | * ports from the target list for a VM. | ||
52 | */ | ||
53 | bfa_status_t | ||
54 | bfa_fcs_rport_remove(struct bfa_fcs_rport_s *rport_in) | ||
55 | { | ||
56 | |||
57 | struct bfa_fcs_rport_s *rport; | ||
58 | |||
59 | bfa_trc(rport_in->fcs, rport_in->pwwn); | ||
60 | |||
61 | rport = bfa_fcs_port_get_rport_by_pwwn(rport_in->port, rport_in->pwwn); | ||
62 | if (rport == NULL) { | ||
63 | /* | ||
64 | * TBD Error handling | ||
65 | */ | ||
66 | bfa_trc(rport_in->fcs, rport_in->pid); | ||
67 | return BFA_STATUS_UNKNOWN_RWWN; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * TBD if this remote port is online, send a logo | ||
72 | */ | ||
73 | return BFA_STATUS_OK; | ||
74 | |||
75 | } | ||
76 | |||
77 | /** | ||
78 | * Remote device status for display/debug. | ||
79 | */ | ||
80 | void | ||
81 | bfa_fcs_rport_get_attr(struct bfa_fcs_rport_s *rport, | ||
82 | struct bfa_rport_attr_s *rport_attr) | ||
83 | { | ||
84 | struct bfa_rport_qos_attr_s qos_attr; | ||
85 | struct bfa_fcs_port_s *port = rport->port; | ||
86 | |||
87 | bfa_os_memset(rport_attr, 0, sizeof(struct bfa_rport_attr_s)); | ||
88 | |||
89 | rport_attr->pid = rport->pid; | ||
90 | rport_attr->pwwn = rport->pwwn; | ||
91 | rport_attr->nwwn = rport->nwwn; | ||
92 | rport_attr->cos_supported = rport->fc_cos; | ||
93 | rport_attr->df_sz = rport->maxfrsize; | ||
94 | rport_attr->state = bfa_fcs_rport_get_state(rport); | ||
95 | rport_attr->fc_cos = rport->fc_cos; | ||
96 | rport_attr->cisc = rport->cisc; | ||
97 | rport_attr->scsi_function = rport->scsi_function; | ||
98 | rport_attr->curr_speed = rport->rpf.rpsc_speed; | ||
99 | rport_attr->assigned_speed = rport->rpf.assigned_speed; | ||
100 | |||
101 | bfa_rport_get_qos_attr(rport->bfa_rport, &qos_attr); | ||
102 | rport_attr->qos_attr = qos_attr; | ||
103 | |||
104 | rport_attr->trl_enforced = BFA_FALSE; | ||
105 | if (bfa_pport_is_ratelim(port->fcs->bfa)) { | ||
106 | if ((rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN) || | ||
107 | (rport->rpf.rpsc_speed < | ||
108 | bfa_fcs_port_get_rport_max_speed(port))) | ||
109 | rport_attr->trl_enforced = BFA_TRUE; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | * TODO | ||
114 | * rport->symname | ||
115 | */ | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * Per remote device statistics. | ||
120 | */ | ||
121 | void | ||
122 | bfa_fcs_rport_get_stats(struct bfa_fcs_rport_s *rport, | ||
123 | struct bfa_rport_stats_s *stats) | ||
124 | { | ||
125 | *stats = rport->stats; | ||
126 | } | ||
127 | |||
128 | void | ||
129 | bfa_fcs_rport_clear_stats(struct bfa_fcs_rport_s *rport) | ||
130 | { | ||
131 | bfa_os_memset((char *)&rport->stats, 0, | ||
132 | sizeof(struct bfa_rport_stats_s)); | ||
133 | } | ||
134 | |||
135 | struct bfa_fcs_rport_s * | ||
136 | bfa_fcs_rport_lookup(struct bfa_fcs_port_s *port, wwn_t rpwwn) | ||
137 | { | ||
138 | struct bfa_fcs_rport_s *rport; | ||
139 | |||
140 | rport = bfa_fcs_port_get_rport_by_pwwn(port, rpwwn); | ||
141 | if (rport == NULL) { | ||
142 | /* | ||
143 | * TBD Error handling | ||
144 | */ | ||
145 | } | ||
146 | |||
147 | return rport; | ||
148 | } | ||
149 | |||
150 | struct bfa_fcs_rport_s * | ||
151 | bfa_fcs_rport_lookup_by_nwwn(struct bfa_fcs_port_s *port, wwn_t rnwwn) | ||
152 | { | ||
153 | struct bfa_fcs_rport_s *rport; | ||
154 | |||
155 | rport = bfa_fcs_port_get_rport_by_nwwn(port, rnwwn); | ||
156 | if (rport == NULL) { | ||
157 | /* | ||
158 | * TBD Error handling | ||
159 | */ | ||
160 | } | ||
161 | |||
162 | return rport; | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * This API is to set the Rport's speed. Should be used when RPSC is not | ||
167 | * supported by the rport. | ||
168 | */ | ||
169 | void | ||
170 | bfa_fcs_rport_set_speed(struct bfa_fcs_rport_s *rport, | ||
171 | enum bfa_pport_speed speed) | ||
172 | { | ||
173 | rport->rpf.assigned_speed = speed; | ||
174 | |||
175 | /* Set this speed in f/w only if the RPSC speed is not available */ | ||
176 | if (rport->rpf.rpsc_speed == BFA_PPORT_SPEED_UNKNOWN) | ||
177 | bfa_rport_speed(rport->bfa_rport, speed); | ||
178 | } | ||
179 | |||
180 | |||
diff --git a/drivers/scsi/bfa/rport_ftrs.c b/drivers/scsi/bfa/rport_ftrs.c new file mode 100644 index 000000000000..8a1f59d596c1 --- /dev/null +++ b/drivers/scsi/bfa/rport_ftrs.c | |||
@@ -0,0 +1,375 @@ | |||
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 | * rport_ftrs.c Remote port features (RPF) implementation. | ||
20 | */ | ||
21 | |||
22 | #include <bfa.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include "fcbuild.h" | ||
25 | #include "fcs_rport.h" | ||
26 | #include "fcs_lport.h" | ||
27 | #include "fcs_trcmod.h" | ||
28 | #include "fcs_fcxp.h" | ||
29 | #include "fcs.h" | ||
30 | |||
31 | BFA_TRC_FILE(FCS, RPORT_FTRS); | ||
32 | |||
33 | #define BFA_FCS_RPF_RETRIES (3) | ||
34 | #define BFA_FCS_RPF_RETRY_TIMEOUT (1000) /* 1 sec (In millisecs) */ | ||
35 | |||
36 | static void bfa_fcs_rpf_send_rpsc2(void *rport_cbarg, | ||
37 | struct bfa_fcxp_s *fcxp_alloced); | ||
38 | static void bfa_fcs_rpf_rpsc2_response(void *fcsarg, | ||
39 | struct bfa_fcxp_s *fcxp, void *cbarg, | ||
40 | bfa_status_t req_status, u32 rsp_len, | ||
41 | u32 resid_len, | ||
42 | struct fchs_s *rsp_fchs); | ||
43 | static void bfa_fcs_rpf_timeout(void *arg); | ||
44 | |||
45 | /** | ||
46 | * fcs_rport_ftrs_sm FCS rport state machine events | ||
47 | */ | ||
48 | |||
49 | enum rpf_event { | ||
50 | RPFSM_EVENT_RPORT_OFFLINE = 1, /* Rport offline */ | ||
51 | RPFSM_EVENT_RPORT_ONLINE = 2, /* Rport online */ | ||
52 | RPFSM_EVENT_FCXP_SENT = 3, /* Frame from has been sent */ | ||
53 | RPFSM_EVENT_TIMEOUT = 4, /* Rport SM timeout event */ | ||
54 | RPFSM_EVENT_RPSC_COMP = 5, | ||
55 | RPFSM_EVENT_RPSC_FAIL = 6, | ||
56 | RPFSM_EVENT_RPSC_ERROR = 7, | ||
57 | }; | ||
58 | |||
59 | static void bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, | ||
60 | enum rpf_event event); | ||
61 | static void bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, | ||
62 | enum rpf_event event); | ||
63 | static void bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, | ||
64 | enum rpf_event event); | ||
65 | static void bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, | ||
66 | enum rpf_event event); | ||
67 | static void bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, | ||
68 | enum rpf_event event); | ||
69 | static void bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, | ||
70 | enum rpf_event event); | ||
71 | |||
72 | static void | ||
73 | bfa_fcs_rpf_sm_uninit(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) | ||
74 | { | ||
75 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
76 | |||
77 | bfa_trc(rport->fcs, rport->pwwn); | ||
78 | bfa_trc(rport->fcs, rport->pid); | ||
79 | bfa_trc(rport->fcs, event); | ||
80 | |||
81 | switch (event) { | ||
82 | case RPFSM_EVENT_RPORT_ONLINE : | ||
83 | if (!BFA_FCS_PID_IS_WKA(rport->pid)) { | ||
84 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); | ||
85 | rpf->rpsc_retries = 0; | ||
86 | bfa_fcs_rpf_send_rpsc2(rpf, NULL); | ||
87 | break; | ||
88 | }; | ||
89 | |||
90 | case RPFSM_EVENT_RPORT_OFFLINE : | ||
91 | break; | ||
92 | |||
93 | default: | ||
94 | bfa_assert(0); | ||
95 | } | ||
96 | } | ||
97 | |||
98 | static void | ||
99 | bfa_fcs_rpf_sm_rpsc_sending(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) | ||
100 | { | ||
101 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
102 | |||
103 | bfa_trc(rport->fcs, event); | ||
104 | |||
105 | switch (event) { | ||
106 | case RPFSM_EVENT_FCXP_SENT: | ||
107 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc); | ||
108 | break; | ||
109 | |||
110 | case RPFSM_EVENT_RPORT_OFFLINE : | ||
111 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); | ||
112 | bfa_fcxp_walloc_cancel(rport->fcs->bfa, &rpf->fcxp_wqe); | ||
113 | rpf->rpsc_retries = 0; | ||
114 | break; | ||
115 | |||
116 | default: | ||
117 | bfa_assert(0); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | static void | ||
122 | bfa_fcs_rpf_sm_rpsc(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) | ||
123 | { | ||
124 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
125 | |||
126 | bfa_trc(rport->fcs, rport->pid); | ||
127 | bfa_trc(rport->fcs, event); | ||
128 | |||
129 | switch (event) { | ||
130 | case RPFSM_EVENT_RPSC_COMP: | ||
131 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); | ||
132 | /* Update speed info in f/w via BFA */ | ||
133 | if (rpf->rpsc_speed != BFA_PPORT_SPEED_UNKNOWN) { | ||
134 | bfa_rport_speed(rport->bfa_rport, rpf->rpsc_speed); | ||
135 | } else if (rpf->assigned_speed != BFA_PPORT_SPEED_UNKNOWN) { | ||
136 | bfa_rport_speed(rport->bfa_rport, rpf->assigned_speed); | ||
137 | } | ||
138 | break; | ||
139 | |||
140 | case RPFSM_EVENT_RPSC_FAIL: | ||
141 | /* RPSC not supported by rport */ | ||
142 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); | ||
143 | break; | ||
144 | |||
145 | case RPFSM_EVENT_RPSC_ERROR: | ||
146 | /* need to retry...delayed a bit. */ | ||
147 | if (rpf->rpsc_retries++ < BFA_FCS_RPF_RETRIES) { | ||
148 | bfa_timer_start(rport->fcs->bfa, &rpf->timer, | ||
149 | bfa_fcs_rpf_timeout, rpf, | ||
150 | BFA_FCS_RPF_RETRY_TIMEOUT); | ||
151 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_retry); | ||
152 | } else { | ||
153 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_online); | ||
154 | } | ||
155 | break; | ||
156 | |||
157 | case RPFSM_EVENT_RPORT_OFFLINE : | ||
158 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); | ||
159 | bfa_fcxp_discard(rpf->fcxp); | ||
160 | rpf->rpsc_retries = 0; | ||
161 | break; | ||
162 | |||
163 | default: | ||
164 | bfa_assert(0); | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static void | ||
169 | bfa_fcs_rpf_sm_rpsc_retry(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) | ||
170 | { | ||
171 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
172 | |||
173 | bfa_trc(rport->fcs, rport->pid); | ||
174 | bfa_trc(rport->fcs, event); | ||
175 | |||
176 | switch (event) { | ||
177 | case RPFSM_EVENT_TIMEOUT : | ||
178 | /* re-send the RPSC */ | ||
179 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); | ||
180 | bfa_fcs_rpf_send_rpsc2(rpf, NULL); | ||
181 | break; | ||
182 | |||
183 | case RPFSM_EVENT_RPORT_OFFLINE : | ||
184 | bfa_timer_stop(&rpf->timer); | ||
185 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); | ||
186 | rpf->rpsc_retries = 0; | ||
187 | break; | ||
188 | |||
189 | default: | ||
190 | bfa_assert(0); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static void | ||
195 | bfa_fcs_rpf_sm_online(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) | ||
196 | { | ||
197 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
198 | |||
199 | bfa_trc(rport->fcs, rport->pwwn); | ||
200 | bfa_trc(rport->fcs, rport->pid); | ||
201 | bfa_trc(rport->fcs, event); | ||
202 | |||
203 | switch (event) { | ||
204 | case RPFSM_EVENT_RPORT_OFFLINE : | ||
205 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_offline); | ||
206 | rpf->rpsc_retries = 0; | ||
207 | break; | ||
208 | |||
209 | default: | ||
210 | bfa_assert(0); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | static void | ||
215 | bfa_fcs_rpf_sm_offline(struct bfa_fcs_rpf_s *rpf, enum rpf_event event) | ||
216 | { | ||
217 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
218 | |||
219 | bfa_trc(rport->fcs, rport->pwwn); | ||
220 | bfa_trc(rport->fcs, rport->pid); | ||
221 | bfa_trc(rport->fcs, event); | ||
222 | |||
223 | switch (event) { | ||
224 | case RPFSM_EVENT_RPORT_ONLINE : | ||
225 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_rpsc_sending); | ||
226 | bfa_fcs_rpf_send_rpsc2(rpf, NULL); | ||
227 | break; | ||
228 | |||
229 | case RPFSM_EVENT_RPORT_OFFLINE : | ||
230 | break; | ||
231 | |||
232 | default: | ||
233 | bfa_assert(0); | ||
234 | } | ||
235 | } | ||
236 | /** | ||
237 | * Called when Rport is created. | ||
238 | */ | ||
239 | void bfa_fcs_rpf_init(struct bfa_fcs_rport_s *rport) | ||
240 | { | ||
241 | struct bfa_fcs_rpf_s *rpf = &rport->rpf; | ||
242 | |||
243 | bfa_trc(rport->fcs, rport->pid); | ||
244 | rpf->rport = rport; | ||
245 | |||
246 | bfa_sm_set_state(rpf, bfa_fcs_rpf_sm_uninit); | ||
247 | } | ||
248 | |||
249 | /** | ||
250 | * Called when Rport becomes online | ||
251 | */ | ||
252 | void bfa_fcs_rpf_rport_online(struct bfa_fcs_rport_s *rport) | ||
253 | { | ||
254 | bfa_trc(rport->fcs, rport->pid); | ||
255 | |||
256 | if (__fcs_min_cfg(rport->port->fcs)) | ||
257 | return; | ||
258 | |||
259 | if (bfa_fcs_fabric_is_switched(rport->port->fabric)) | ||
260 | bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_ONLINE); | ||
261 | } | ||
262 | |||
263 | /** | ||
264 | * Called when Rport becomes offline | ||
265 | */ | ||
266 | void bfa_fcs_rpf_rport_offline(struct bfa_fcs_rport_s *rport) | ||
267 | { | ||
268 | bfa_trc(rport->fcs, rport->pid); | ||
269 | |||
270 | if (__fcs_min_cfg(rport->port->fcs)) | ||
271 | return; | ||
272 | |||
273 | bfa_sm_send_event(&rport->rpf, RPFSM_EVENT_RPORT_OFFLINE); | ||
274 | } | ||
275 | |||
276 | static void | ||
277 | bfa_fcs_rpf_timeout(void *arg) | ||
278 | { | ||
279 | struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) arg; | ||
280 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
281 | |||
282 | bfa_trc(rport->fcs, rport->pid); | ||
283 | bfa_sm_send_event(rpf, RPFSM_EVENT_TIMEOUT); | ||
284 | } | ||
285 | |||
286 | static void | ||
287 | bfa_fcs_rpf_send_rpsc2(void *rpf_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
288 | { | ||
289 | struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *)rpf_cbarg; | ||
290 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
291 | struct bfa_fcs_port_s *port = rport->port; | ||
292 | struct fchs_s fchs; | ||
293 | int len; | ||
294 | struct bfa_fcxp_s *fcxp; | ||
295 | |||
296 | bfa_trc(rport->fcs, rport->pwwn); | ||
297 | |||
298 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
299 | if (!fcxp) { | ||
300 | bfa_fcxp_alloc_wait(port->fcs->bfa, &rpf->fcxp_wqe, | ||
301 | bfa_fcs_rpf_send_rpsc2, rpf); | ||
302 | return; | ||
303 | } | ||
304 | rpf->fcxp = fcxp; | ||
305 | |||
306 | len = fc_rpsc2_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rport->pid, | ||
307 | bfa_fcs_port_get_fcid(port), &rport->pid, 1); | ||
308 | |||
309 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
310 | FC_CLASS_3, len, &fchs, bfa_fcs_rpf_rpsc2_response, | ||
311 | rpf, FC_MAX_PDUSZ, FC_RA_TOV); | ||
312 | rport->stats.rpsc_sent++; | ||
313 | bfa_sm_send_event(rpf, RPFSM_EVENT_FCXP_SENT); | ||
314 | |||
315 | } | ||
316 | |||
317 | static void | ||
318 | bfa_fcs_rpf_rpsc2_response(void *fcsarg, struct bfa_fcxp_s *fcxp, void *cbarg, | ||
319 | bfa_status_t req_status, u32 rsp_len, | ||
320 | u32 resid_len, struct fchs_s *rsp_fchs) | ||
321 | { | ||
322 | struct bfa_fcs_rpf_s *rpf = (struct bfa_fcs_rpf_s *) cbarg; | ||
323 | struct bfa_fcs_rport_s *rport = rpf->rport; | ||
324 | struct fc_ls_rjt_s *ls_rjt; | ||
325 | struct fc_rpsc2_acc_s *rpsc2_acc; | ||
326 | u16 num_ents; | ||
327 | |||
328 | bfa_trc(rport->fcs, req_status); | ||
329 | |||
330 | if (req_status != BFA_STATUS_OK) { | ||
331 | bfa_trc(rport->fcs, req_status); | ||
332 | if (req_status == BFA_STATUS_ETIMER) | ||
333 | rport->stats.rpsc_failed++; | ||
334 | bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR); | ||
335 | return; | ||
336 | } | ||
337 | |||
338 | rpsc2_acc = (struct fc_rpsc2_acc_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
339 | if (rpsc2_acc->els_cmd == FC_ELS_ACC) { | ||
340 | rport->stats.rpsc_accs++; | ||
341 | num_ents = bfa_os_ntohs(rpsc2_acc->num_pids); | ||
342 | bfa_trc(rport->fcs, num_ents); | ||
343 | if (num_ents > 0) { | ||
344 | bfa_assert(rpsc2_acc->port_info[0].pid != rport->pid); | ||
345 | bfa_trc(rport->fcs, | ||
346 | bfa_os_ntohs(rpsc2_acc->port_info[0].pid)); | ||
347 | bfa_trc(rport->fcs, | ||
348 | bfa_os_ntohs(rpsc2_acc->port_info[0].speed)); | ||
349 | bfa_trc(rport->fcs, | ||
350 | bfa_os_ntohs(rpsc2_acc->port_info[0].index)); | ||
351 | bfa_trc(rport->fcs, | ||
352 | rpsc2_acc->port_info[0].type); | ||
353 | |||
354 | if (rpsc2_acc->port_info[0].speed == 0) { | ||
355 | bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | rpf->rpsc_speed = fc_rpsc_operspeed_to_bfa_speed( | ||
360 | bfa_os_ntohs(rpsc2_acc->port_info[0].speed)); | ||
361 | |||
362 | bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_COMP); | ||
363 | } | ||
364 | } else { | ||
365 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
366 | bfa_trc(rport->fcs, ls_rjt->reason_code); | ||
367 | bfa_trc(rport->fcs, ls_rjt->reason_code_expl); | ||
368 | rport->stats.rpsc_rejects++; | ||
369 | if (ls_rjt->reason_code == FC_LS_RJT_RSN_CMD_NOT_SUPP) { | ||
370 | bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_FAIL); | ||
371 | } else { | ||
372 | bfa_sm_send_event(rpf, RPFSM_EVENT_RPSC_ERROR); | ||
373 | } | ||
374 | } | ||
375 | } | ||
diff --git a/drivers/scsi/bfa/scn.c b/drivers/scsi/bfa/scn.c new file mode 100644 index 000000000000..bd4771ff62c8 --- /dev/null +++ b/drivers/scsi/bfa/scn.c | |||
@@ -0,0 +1,482 @@ | |||
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 | #include <bfa.h> | ||
19 | #include <bfa_svc.h> | ||
20 | #include "fcs_lport.h" | ||
21 | #include "fcs_rport.h" | ||
22 | #include "fcs_ms.h" | ||
23 | #include "fcs_trcmod.h" | ||
24 | #include "fcs_fcxp.h" | ||
25 | #include "fcs.h" | ||
26 | #include "lport_priv.h" | ||
27 | |||
28 | BFA_TRC_FILE(FCS, SCN); | ||
29 | |||
30 | #define FC_QOS_RSCN_EVENT 0x0c | ||
31 | #define FC_FABRIC_NAME_RSCN_EVENT 0x0d | ||
32 | |||
33 | /* | ||
34 | * forward declarations | ||
35 | */ | ||
36 | static void bfa_fcs_port_scn_send_scr(void *scn_cbarg, | ||
37 | struct bfa_fcxp_s *fcxp_alloced); | ||
38 | static void bfa_fcs_port_scn_scr_response(void *fcsarg, | ||
39 | struct bfa_fcxp_s *fcxp, | ||
40 | void *cbarg, | ||
41 | bfa_status_t req_status, | ||
42 | u32 rsp_len, | ||
43 | u32 resid_len, | ||
44 | struct fchs_s *rsp_fchs); | ||
45 | static void bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port, | ||
46 | struct fchs_s *rx_fchs); | ||
47 | static void bfa_fcs_port_scn_timeout(void *arg); | ||
48 | |||
49 | /** | ||
50 | * fcs_scm_sm FCS SCN state machine | ||
51 | */ | ||
52 | |||
53 | /** | ||
54 | * VPort SCN State Machine events | ||
55 | */ | ||
56 | enum port_scn_event { | ||
57 | SCNSM_EVENT_PORT_ONLINE = 1, | ||
58 | SCNSM_EVENT_PORT_OFFLINE = 2, | ||
59 | SCNSM_EVENT_RSP_OK = 3, | ||
60 | SCNSM_EVENT_RSP_ERROR = 4, | ||
61 | SCNSM_EVENT_TIMEOUT = 5, | ||
62 | SCNSM_EVENT_SCR_SENT = 6, | ||
63 | }; | ||
64 | |||
65 | static void bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn, | ||
66 | enum port_scn_event event); | ||
67 | static void bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn, | ||
68 | enum port_scn_event event); | ||
69 | static void bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn, | ||
70 | enum port_scn_event event); | ||
71 | static void bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn, | ||
72 | enum port_scn_event event); | ||
73 | static void bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn, | ||
74 | enum port_scn_event event); | ||
75 | |||
76 | /** | ||
77 | * Starting state - awaiting link up. | ||
78 | */ | ||
79 | static void | ||
80 | bfa_fcs_port_scn_sm_offline(struct bfa_fcs_port_scn_s *scn, | ||
81 | enum port_scn_event event) | ||
82 | { | ||
83 | switch (event) { | ||
84 | case SCNSM_EVENT_PORT_ONLINE: | ||
85 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr); | ||
86 | bfa_fcs_port_scn_send_scr(scn, NULL); | ||
87 | break; | ||
88 | |||
89 | case SCNSM_EVENT_PORT_OFFLINE: | ||
90 | break; | ||
91 | |||
92 | default: | ||
93 | bfa_assert(0); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static void | ||
98 | bfa_fcs_port_scn_sm_sending_scr(struct bfa_fcs_port_scn_s *scn, | ||
99 | enum port_scn_event event) | ||
100 | { | ||
101 | switch (event) { | ||
102 | case SCNSM_EVENT_SCR_SENT: | ||
103 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr); | ||
104 | break; | ||
105 | |||
106 | case SCNSM_EVENT_PORT_OFFLINE: | ||
107 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline); | ||
108 | bfa_fcxp_walloc_cancel(scn->port->fcs->bfa, &scn->fcxp_wqe); | ||
109 | break; | ||
110 | |||
111 | default: | ||
112 | bfa_assert(0); | ||
113 | } | ||
114 | } | ||
115 | |||
116 | static void | ||
117 | bfa_fcs_port_scn_sm_scr(struct bfa_fcs_port_scn_s *scn, | ||
118 | enum port_scn_event event) | ||
119 | { | ||
120 | struct bfa_fcs_port_s *port = scn->port; | ||
121 | |||
122 | switch (event) { | ||
123 | case SCNSM_EVENT_RSP_OK: | ||
124 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_online); | ||
125 | break; | ||
126 | |||
127 | case SCNSM_EVENT_RSP_ERROR: | ||
128 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_scr_retry); | ||
129 | bfa_timer_start(port->fcs->bfa, &scn->timer, | ||
130 | bfa_fcs_port_scn_timeout, scn, | ||
131 | BFA_FCS_RETRY_TIMEOUT); | ||
132 | break; | ||
133 | |||
134 | case SCNSM_EVENT_PORT_OFFLINE: | ||
135 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline); | ||
136 | bfa_fcxp_discard(scn->fcxp); | ||
137 | break; | ||
138 | |||
139 | default: | ||
140 | bfa_assert(0); | ||
141 | } | ||
142 | } | ||
143 | |||
144 | static void | ||
145 | bfa_fcs_port_scn_sm_scr_retry(struct bfa_fcs_port_scn_s *scn, | ||
146 | enum port_scn_event event) | ||
147 | { | ||
148 | switch (event) { | ||
149 | case SCNSM_EVENT_TIMEOUT: | ||
150 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_sending_scr); | ||
151 | bfa_fcs_port_scn_send_scr(scn, NULL); | ||
152 | break; | ||
153 | |||
154 | case SCNSM_EVENT_PORT_OFFLINE: | ||
155 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline); | ||
156 | bfa_timer_stop(&scn->timer); | ||
157 | break; | ||
158 | |||
159 | default: | ||
160 | bfa_assert(0); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | static void | ||
165 | bfa_fcs_port_scn_sm_online(struct bfa_fcs_port_scn_s *scn, | ||
166 | enum port_scn_event event) | ||
167 | { | ||
168 | switch (event) { | ||
169 | case SCNSM_EVENT_PORT_OFFLINE: | ||
170 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline); | ||
171 | break; | ||
172 | |||
173 | default: | ||
174 | bfa_assert(0); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | |||
179 | |||
180 | /** | ||
181 | * fcs_scn_private FCS SCN private functions | ||
182 | */ | ||
183 | |||
184 | /** | ||
185 | * This routine will be called to send a SCR command. | ||
186 | */ | ||
187 | static void | ||
188 | bfa_fcs_port_scn_send_scr(void *scn_cbarg, struct bfa_fcxp_s *fcxp_alloced) | ||
189 | { | ||
190 | struct bfa_fcs_port_scn_s *scn = scn_cbarg; | ||
191 | struct bfa_fcs_port_s *port = scn->port; | ||
192 | struct fchs_s fchs; | ||
193 | int len; | ||
194 | struct bfa_fcxp_s *fcxp; | ||
195 | |||
196 | bfa_trc(port->fcs, port->pid); | ||
197 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
198 | |||
199 | fcxp = fcxp_alloced ? fcxp_alloced : bfa_fcs_fcxp_alloc(port->fcs); | ||
200 | if (!fcxp) { | ||
201 | bfa_fcxp_alloc_wait(port->fcs->bfa, &scn->fcxp_wqe, | ||
202 | bfa_fcs_port_scn_send_scr, scn); | ||
203 | return; | ||
204 | } | ||
205 | scn->fcxp = fcxp; | ||
206 | |||
207 | /* | ||
208 | * Handle VU registrations for Base port only | ||
209 | */ | ||
210 | if ((!port->vport) && bfa_ioc_get_fcmode(&port->fcs->bfa->ioc)) { | ||
211 | len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), | ||
212 | bfa_lps_is_brcd_fabric(port->fabric->lps), | ||
213 | port->pid, 0); | ||
214 | } else { | ||
215 | len = fc_scr_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), BFA_FALSE, | ||
216 | port->pid, 0); | ||
217 | } | ||
218 | |||
219 | bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, | ||
220 | FC_CLASS_3, len, &fchs, bfa_fcs_port_scn_scr_response, | ||
221 | (void *)scn, FC_MAX_PDUSZ, FC_RA_TOV); | ||
222 | |||
223 | bfa_sm_send_event(scn, SCNSM_EVENT_SCR_SENT); | ||
224 | } | ||
225 | |||
226 | static void | ||
227 | bfa_fcs_port_scn_scr_response(void *fcsarg, struct bfa_fcxp_s *fcxp, | ||
228 | void *cbarg, bfa_status_t req_status, | ||
229 | u32 rsp_len, u32 resid_len, | ||
230 | struct fchs_s *rsp_fchs) | ||
231 | { | ||
232 | struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)cbarg; | ||
233 | struct bfa_fcs_port_s *port = scn->port; | ||
234 | struct fc_els_cmd_s *els_cmd; | ||
235 | struct fc_ls_rjt_s *ls_rjt; | ||
236 | |||
237 | bfa_trc(port->fcs, port->port_cfg.pwwn); | ||
238 | |||
239 | /* | ||
240 | * Sanity Checks | ||
241 | */ | ||
242 | if (req_status != BFA_STATUS_OK) { | ||
243 | bfa_trc(port->fcs, req_status); | ||
244 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); | ||
245 | return; | ||
246 | } | ||
247 | |||
248 | els_cmd = (struct fc_els_cmd_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
249 | |||
250 | switch (els_cmd->els_code) { | ||
251 | |||
252 | case FC_ELS_ACC: | ||
253 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_OK); | ||
254 | break; | ||
255 | |||
256 | case FC_ELS_LS_RJT: | ||
257 | |||
258 | ls_rjt = (struct fc_ls_rjt_s *) BFA_FCXP_RSP_PLD(fcxp); | ||
259 | |||
260 | bfa_trc(port->fcs, ls_rjt->reason_code); | ||
261 | bfa_trc(port->fcs, ls_rjt->reason_code_expl); | ||
262 | |||
263 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); | ||
264 | break; | ||
265 | |||
266 | default: | ||
267 | bfa_sm_send_event(scn, SCNSM_EVENT_RSP_ERROR); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * Send a LS Accept | ||
273 | */ | ||
274 | static void | ||
275 | bfa_fcs_port_scn_send_ls_acc(struct bfa_fcs_port_s *port, | ||
276 | struct fchs_s *rx_fchs) | ||
277 | { | ||
278 | struct fchs_s fchs; | ||
279 | struct bfa_fcxp_s *fcxp; | ||
280 | struct bfa_rport_s *bfa_rport = NULL; | ||
281 | int len; | ||
282 | |||
283 | bfa_trc(port->fcs, rx_fchs->s_id); | ||
284 | |||
285 | fcxp = bfa_fcs_fcxp_alloc(port->fcs); | ||
286 | if (!fcxp) | ||
287 | return; | ||
288 | |||
289 | len = fc_ls_acc_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), rx_fchs->s_id, | ||
290 | bfa_fcs_port_get_fcid(port), rx_fchs->ox_id); | ||
291 | |||
292 | bfa_fcxp_send(fcxp, bfa_rport, port->fabric->vf_id, port->lp_tag, | ||
293 | BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, | ||
294 | FC_MAX_PDUSZ, 0); | ||
295 | } | ||
296 | |||
297 | /** | ||
298 | * This routine will be called by bfa_timer on timer timeouts. | ||
299 | * | ||
300 | * param[in] vport - pointer to bfa_fcs_port_t. | ||
301 | * param[out] vport_status - pointer to return vport status in | ||
302 | * | ||
303 | * return | ||
304 | * void | ||
305 | * | ||
306 | * Special Considerations: | ||
307 | * | ||
308 | * note | ||
309 | */ | ||
310 | static void | ||
311 | bfa_fcs_port_scn_timeout(void *arg) | ||
312 | { | ||
313 | struct bfa_fcs_port_scn_s *scn = (struct bfa_fcs_port_scn_s *)arg; | ||
314 | |||
315 | bfa_sm_send_event(scn, SCNSM_EVENT_TIMEOUT); | ||
316 | } | ||
317 | |||
318 | |||
319 | |||
320 | /** | ||
321 | * fcs_scn_public FCS state change notification public interfaces | ||
322 | */ | ||
323 | |||
324 | /* | ||
325 | * Functions called by port/fab | ||
326 | */ | ||
327 | void | ||
328 | bfa_fcs_port_scn_init(struct bfa_fcs_port_s *port) | ||
329 | { | ||
330 | struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); | ||
331 | |||
332 | scn->port = port; | ||
333 | bfa_sm_set_state(scn, bfa_fcs_port_scn_sm_offline); | ||
334 | } | ||
335 | |||
336 | void | ||
337 | bfa_fcs_port_scn_offline(struct bfa_fcs_port_s *port) | ||
338 | { | ||
339 | struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); | ||
340 | |||
341 | scn->port = port; | ||
342 | bfa_sm_send_event(scn, SCNSM_EVENT_PORT_OFFLINE); | ||
343 | } | ||
344 | |||
345 | void | ||
346 | bfa_fcs_port_scn_online(struct bfa_fcs_port_s *port) | ||
347 | { | ||
348 | struct bfa_fcs_port_scn_s *scn = BFA_FCS_GET_SCN_FROM_PORT(port); | ||
349 | |||
350 | scn->port = port; | ||
351 | bfa_sm_send_event(scn, SCNSM_EVENT_PORT_ONLINE); | ||
352 | } | ||
353 | |||
354 | static void | ||
355 | bfa_fcs_port_scn_portid_rscn(struct bfa_fcs_port_s *port, u32 rpid) | ||
356 | { | ||
357 | struct bfa_fcs_rport_s *rport; | ||
358 | |||
359 | bfa_trc(port->fcs, rpid); | ||
360 | |||
361 | /** | ||
362 | * If this is an unknown device, then it just came online. | ||
363 | * Otherwise let rport handle the RSCN event. | ||
364 | */ | ||
365 | rport = bfa_fcs_port_get_rport_by_pid(port, rpid); | ||
366 | if (rport == NULL) { | ||
367 | /* | ||
368 | * If min cfg mode is enabled, we donot need to | ||
369 | * discover any new rports. | ||
370 | */ | ||
371 | if (!__fcs_min_cfg(port->fcs)) | ||
372 | rport = bfa_fcs_rport_create(port, rpid); | ||
373 | } else { | ||
374 | bfa_fcs_rport_scn(rport); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | /** | ||
379 | * rscn format based PID comparison | ||
380 | */ | ||
381 | #define __fc_pid_match(__c0, __c1, __fmt) \ | ||
382 | (((__fmt) == FC_RSCN_FORMAT_FABRIC) || \ | ||
383 | (((__fmt) == FC_RSCN_FORMAT_DOMAIN) && \ | ||
384 | ((__c0)[0] == (__c1)[0])) || \ | ||
385 | (((__fmt) == FC_RSCN_FORMAT_AREA) && \ | ||
386 | ((__c0)[0] == (__c1)[0]) && \ | ||
387 | ((__c0)[1] == (__c1)[1]))) | ||
388 | |||
389 | static void | ||
390 | bfa_fcs_port_scn_multiport_rscn(struct bfa_fcs_port_s *port, | ||
391 | enum fc_rscn_format format, u32 rscn_pid) | ||
392 | { | ||
393 | struct bfa_fcs_rport_s *rport; | ||
394 | struct list_head *qe, *qe_next; | ||
395 | u8 *c0, *c1; | ||
396 | |||
397 | bfa_trc(port->fcs, format); | ||
398 | bfa_trc(port->fcs, rscn_pid); | ||
399 | |||
400 | c0 = (u8 *) &rscn_pid; | ||
401 | |||
402 | list_for_each_safe(qe, qe_next, &port->rport_q) { | ||
403 | rport = (struct bfa_fcs_rport_s *)qe; | ||
404 | c1 = (u8 *) &rport->pid; | ||
405 | if (__fc_pid_match(c0, c1, format)) | ||
406 | bfa_fcs_rport_scn(rport); | ||
407 | } | ||
408 | } | ||
409 | |||
410 | void | ||
411 | bfa_fcs_port_scn_process_rscn(struct bfa_fcs_port_s *port, struct fchs_s *fchs, | ||
412 | u32 len) | ||
413 | { | ||
414 | struct fc_rscn_pl_s *rscn = (struct fc_rscn_pl_s *) (fchs + 1); | ||
415 | int num_entries; | ||
416 | u32 rscn_pid; | ||
417 | bfa_boolean_t nsquery = BFA_FALSE; | ||
418 | int i = 0; | ||
419 | |||
420 | num_entries = | ||
421 | (bfa_os_ntohs(rscn->payldlen) - | ||
422 | sizeof(u32)) / sizeof(rscn->event[0]); | ||
423 | |||
424 | bfa_trc(port->fcs, num_entries); | ||
425 | |||
426 | port->stats.num_rscn++; | ||
427 | |||
428 | bfa_fcs_port_scn_send_ls_acc(port, fchs); | ||
429 | |||
430 | for (i = 0; i < num_entries; i++) { | ||
431 | rscn_pid = rscn->event[i].portid; | ||
432 | |||
433 | bfa_trc(port->fcs, rscn->event[i].format); | ||
434 | bfa_trc(port->fcs, rscn_pid); | ||
435 | |||
436 | switch (rscn->event[i].format) { | ||
437 | case FC_RSCN_FORMAT_PORTID: | ||
438 | if (rscn->event[i].qualifier == FC_QOS_RSCN_EVENT) { | ||
439 | /* | ||
440 | * Ignore this event. f/w would have processed | ||
441 | * it | ||
442 | */ | ||
443 | bfa_trc(port->fcs, rscn_pid); | ||
444 | } else { | ||
445 | port->stats.num_portid_rscn++; | ||
446 | bfa_fcs_port_scn_portid_rscn(port, rscn_pid); | ||
447 | } | ||
448 | break; | ||
449 | |||
450 | case FC_RSCN_FORMAT_FABRIC: | ||
451 | if (rscn->event[i].qualifier == | ||
452 | FC_FABRIC_NAME_RSCN_EVENT) { | ||
453 | bfa_fcs_port_ms_fabric_rscn(port); | ||
454 | break; | ||
455 | } | ||
456 | /* | ||
457 | * !!!!!!!!! Fall Through !!!!!!!!!!!!! | ||
458 | */ | ||
459 | |||
460 | case FC_RSCN_FORMAT_AREA: | ||
461 | case FC_RSCN_FORMAT_DOMAIN: | ||
462 | nsquery = BFA_TRUE; | ||
463 | bfa_fcs_port_scn_multiport_rscn(port, | ||
464 | rscn->event[i].format, | ||
465 | rscn_pid); | ||
466 | break; | ||
467 | |||
468 | default: | ||
469 | bfa_assert(0); | ||
470 | nsquery = BFA_TRUE; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * If any of area, domain or fabric RSCN is received, do a fresh discovery | ||
476 | * to find new devices. | ||
477 | */ | ||
478 | if (nsquery) | ||
479 | bfa_fcs_port_ns_query(port); | ||
480 | } | ||
481 | |||
482 | |||
diff --git a/drivers/scsi/bfa/vfapi.c b/drivers/scsi/bfa/vfapi.c new file mode 100644 index 000000000000..31d81fe2fc48 --- /dev/null +++ b/drivers/scsi/bfa/vfapi.c | |||
@@ -0,0 +1,292 @@ | |||
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 | * vfapi.c Fabric module implementation. | ||
20 | */ | ||
21 | |||
22 | #include "fcs_fabric.h" | ||
23 | #include "fcs_trcmod.h" | ||
24 | |||
25 | BFA_TRC_FILE(FCS, VFAPI); | ||
26 | |||
27 | /** | ||
28 | * fcs_vf_api virtual fabrics API | ||
29 | */ | ||
30 | |||
31 | /** | ||
32 | * Enable VF mode. | ||
33 | * | ||
34 | * @param[in] fcs fcs module instance | ||
35 | * @param[in] vf_id default vf_id of port, FC_VF_ID_NULL | ||
36 | * to use standard default vf_id of 1. | ||
37 | * | ||
38 | * @retval BFA_STATUS_OK vf mode is enabled | ||
39 | * @retval BFA_STATUS_BUSY Port is active. Port must be disabled | ||
40 | * before VF mode can be enabled. | ||
41 | */ | ||
42 | bfa_status_t | ||
43 | bfa_fcs_vf_mode_enable(struct bfa_fcs_s *fcs, u16 vf_id) | ||
44 | { | ||
45 | return BFA_STATUS_OK; | ||
46 | } | ||
47 | |||
48 | /** | ||
49 | * Disable VF mode. | ||
50 | * | ||
51 | * @param[in] fcs fcs module instance | ||
52 | * | ||
53 | * @retval BFA_STATUS_OK vf mode is disabled | ||
54 | * @retval BFA_STATUS_BUSY VFs are present and being used. All | ||
55 | * VFs must be deleted before disabling | ||
56 | * VF mode. | ||
57 | */ | ||
58 | bfa_status_t | ||
59 | bfa_fcs_vf_mode_disable(struct bfa_fcs_s *fcs) | ||
60 | { | ||
61 | return BFA_STATUS_OK; | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * Create a new VF instance. | ||
66 | * | ||
67 | * A new VF is created using the given VF configuration. A VF is identified | ||
68 | * by VF id. No duplicate VF creation is allowed with the same VF id. Once | ||
69 | * a VF is created, VF is automatically started after link initialization | ||
70 | * and EVFP exchange is completed. | ||
71 | * | ||
72 | * param[in] vf - FCS vf data structure. Memory is | ||
73 | * allocated by caller (driver) | ||
74 | * param[in] fcs - FCS module | ||
75 | * param[in] vf_cfg - VF configuration | ||
76 | * param[in] vf_drv - Opaque handle back to the driver's | ||
77 | * virtual vf structure | ||
78 | * | ||
79 | * retval BFA_STATUS_OK VF creation is successful | ||
80 | * retval BFA_STATUS_FAILED VF creation failed | ||
81 | * retval BFA_STATUS_EEXIST A VF exists with the given vf_id | ||
82 | */ | ||
83 | bfa_status_t | ||
84 | bfa_fcs_vf_create(bfa_fcs_vf_t *vf, struct bfa_fcs_s *fcs, u16 vf_id, | ||
85 | struct bfa_port_cfg_s *port_cfg, struct bfad_vf_s *vf_drv) | ||
86 | { | ||
87 | bfa_trc(fcs, vf_id); | ||
88 | return BFA_STATUS_OK; | ||
89 | } | ||
90 | |||
91 | /** | ||
92 | * Use this function to delete a BFA VF object. VF object should | ||
93 | * be stopped before this function call. | ||
94 | * | ||
95 | * param[in] vf - pointer to bfa_vf_t. | ||
96 | * | ||
97 | * retval BFA_STATUS_OK On vf deletion success | ||
98 | * retval BFA_STATUS_BUSY VF is not in a stopped state | ||
99 | * retval BFA_STATUS_INPROGRESS VF deletion in in progress | ||
100 | */ | ||
101 | bfa_status_t | ||
102 | bfa_fcs_vf_delete(bfa_fcs_vf_t *vf) | ||
103 | { | ||
104 | bfa_trc(vf->fcs, vf->vf_id); | ||
105 | return BFA_STATUS_OK; | ||
106 | } | ||
107 | |||
108 | /** | ||
109 | * Start participation in VF. This triggers login to the virtual fabric. | ||
110 | * | ||
111 | * param[in] vf - pointer to bfa_vf_t. | ||
112 | * | ||
113 | * return None | ||
114 | */ | ||
115 | void | ||
116 | bfa_fcs_vf_start(bfa_fcs_vf_t *vf) | ||
117 | { | ||
118 | bfa_trc(vf->fcs, vf->vf_id); | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * Logout with the virtual fabric. | ||
123 | * | ||
124 | * param[in] vf - pointer to bfa_vf_t. | ||
125 | * | ||
126 | * retval BFA_STATUS_OK On success. | ||
127 | * retval BFA_STATUS_INPROGRESS VF is being stopped. | ||
128 | */ | ||
129 | bfa_status_t | ||
130 | bfa_fcs_vf_stop(bfa_fcs_vf_t *vf) | ||
131 | { | ||
132 | bfa_trc(vf->fcs, vf->vf_id); | ||
133 | return BFA_STATUS_OK; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * Returns attributes of the given VF. | ||
138 | * | ||
139 | * param[in] vf pointer to bfa_vf_t. | ||
140 | * param[out] vf_attr vf attributes returned | ||
141 | * | ||
142 | * return None | ||
143 | */ | ||
144 | void | ||
145 | bfa_fcs_vf_get_attr(bfa_fcs_vf_t *vf, struct bfa_vf_attr_s *vf_attr) | ||
146 | { | ||
147 | bfa_trc(vf->fcs, vf->vf_id); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Return statistics associated with the given vf. | ||
152 | * | ||
153 | * param[in] vf pointer to bfa_vf_t. | ||
154 | * param[out] vf_stats vf statistics returned | ||
155 | * | ||
156 | * @return None | ||
157 | */ | ||
158 | void | ||
159 | bfa_fcs_vf_get_stats(bfa_fcs_vf_t *vf, struct bfa_vf_stats_s *vf_stats) | ||
160 | { | ||
161 | bfa_os_memcpy(vf_stats, &vf->stats, sizeof(struct bfa_vf_stats_s)); | ||
162 | return; | ||
163 | } | ||
164 | |||
165 | void | ||
166 | /** | ||
167 | * clear statistics associated with the given vf. | ||
168 | * | ||
169 | * param[in] vf pointer to bfa_vf_t. | ||
170 | * | ||
171 | * @return None | ||
172 | */ | ||
173 | bfa_fcs_vf_clear_stats(bfa_fcs_vf_t *vf) | ||
174 | { | ||
175 | bfa_os_memset(&vf->stats, 0, sizeof(struct bfa_vf_stats_s)); | ||
176 | return; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * Returns FCS vf structure for a given vf_id. | ||
181 | * | ||
182 | * param[in] vf_id - VF_ID | ||
183 | * | ||
184 | * return | ||
185 | * If lookup succeeds, retuns fcs vf object, otherwise returns NULL | ||
186 | */ | ||
187 | bfa_fcs_vf_t * | ||
188 | bfa_fcs_vf_lookup(struct bfa_fcs_s *fcs, u16 vf_id) | ||
189 | { | ||
190 | bfa_trc(fcs, vf_id); | ||
191 | if (vf_id == FC_VF_ID_NULL) | ||
192 | return (&fcs->fabric); | ||
193 | |||
194 | /** | ||
195 | * @todo vf support | ||
196 | */ | ||
197 | |||
198 | return NULL; | ||
199 | } | ||
200 | |||
201 | /** | ||
202 | * Returns driver VF structure for a given FCS vf. | ||
203 | * | ||
204 | * param[in] vf - pointer to bfa_vf_t | ||
205 | * | ||
206 | * return Driver VF structure | ||
207 | */ | ||
208 | struct bfad_vf_s * | ||
209 | bfa_fcs_vf_get_drv_vf(bfa_fcs_vf_t *vf) | ||
210 | { | ||
211 | bfa_assert(vf); | ||
212 | bfa_trc(vf->fcs, vf->vf_id); | ||
213 | return vf->vf_drv; | ||
214 | } | ||
215 | |||
216 | /** | ||
217 | * Return the list of VFs configured. | ||
218 | * | ||
219 | * param[in] fcs fcs module instance | ||
220 | * param[out] vf_ids returned list of vf_ids | ||
221 | * param[in,out] nvfs in:size of vf_ids array, | ||
222 | * out:total elements present, | ||
223 | * actual elements returned is limited by the size | ||
224 | * | ||
225 | * return Driver VF structure | ||
226 | */ | ||
227 | void | ||
228 | bfa_fcs_vf_list(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs) | ||
229 | { | ||
230 | bfa_trc(fcs, *nvfs); | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * Return the list of all VFs visible from fabric. | ||
235 | * | ||
236 | * param[in] fcs fcs module instance | ||
237 | * param[out] vf_ids returned list of vf_ids | ||
238 | * param[in,out] nvfs in:size of vf_ids array, | ||
239 | * out:total elements present, | ||
240 | * actual elements returned is limited by the size | ||
241 | * | ||
242 | * return Driver VF structure | ||
243 | */ | ||
244 | void | ||
245 | bfa_fcs_vf_list_all(struct bfa_fcs_s *fcs, u16 *vf_ids, int *nvfs) | ||
246 | { | ||
247 | bfa_trc(fcs, *nvfs); | ||
248 | } | ||
249 | |||
250 | /** | ||
251 | * Return the list of local logical ports present in the given VF. | ||
252 | * | ||
253 | * param[in] vf vf for which logical ports are returned | ||
254 | * param[out] lpwwn returned logical port wwn list | ||
255 | * param[in,out] nlports in:size of lpwwn list; | ||
256 | * out:total elements present, | ||
257 | * actual elements returned is limited by the size | ||
258 | * | ||
259 | */ | ||
260 | void | ||
261 | bfa_fcs_vf_get_ports(bfa_fcs_vf_t *vf, wwn_t lpwwn[], int *nlports) | ||
262 | { | ||
263 | struct list_head *qe; | ||
264 | struct bfa_fcs_vport_s *vport; | ||
265 | int i; | ||
266 | struct bfa_fcs_s *fcs; | ||
267 | |||
268 | if (vf == NULL || lpwwn == NULL || *nlports == 0) | ||
269 | return; | ||
270 | |||
271 | fcs = vf->fcs; | ||
272 | |||
273 | bfa_trc(fcs, vf->vf_id); | ||
274 | bfa_trc(fcs, (u32) *nlports); | ||
275 | |||
276 | i = 0; | ||
277 | lpwwn[i++] = vf->bport.port_cfg.pwwn; | ||
278 | |||
279 | list_for_each(qe, &vf->vport_q) { | ||
280 | if (i >= *nlports) | ||
281 | break; | ||
282 | |||
283 | vport = (struct bfa_fcs_vport_s *) qe; | ||
284 | lpwwn[i++] = vport->lport.port_cfg.pwwn; | ||
285 | } | ||
286 | |||
287 | bfa_trc(fcs, i); | ||
288 | *nlports = i; | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | |||
diff --git a/drivers/scsi/bfa/vport.c b/drivers/scsi/bfa/vport.c new file mode 100644 index 000000000000..c10af06c5714 --- /dev/null +++ b/drivers/scsi/bfa/vport.c | |||
@@ -0,0 +1,891 @@ | |||
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 | * bfa_fcs_vport.c FCS virtual port state machine | ||
20 | */ | ||
21 | |||
22 | #include <bfa.h> | ||
23 | #include <bfa_svc.h> | ||
24 | #include <fcbuild.h> | ||
25 | #include "fcs_fabric.h" | ||
26 | #include "fcs_lport.h" | ||
27 | #include "fcs_vport.h" | ||
28 | #include "fcs_trcmod.h" | ||
29 | #include "fcs.h" | ||
30 | #include <aen/bfa_aen_lport.h> | ||
31 | |||
32 | BFA_TRC_FILE(FCS, VPORT); | ||
33 | |||
34 | #define __vport_fcs(__vp) (__vp)->lport.fcs | ||
35 | #define __vport_pwwn(__vp) (__vp)->lport.port_cfg.pwwn | ||
36 | #define __vport_nwwn(__vp) (__vp)->lport.port_cfg.nwwn | ||
37 | #define __vport_bfa(__vp) (__vp)->lport.fcs->bfa | ||
38 | #define __vport_fcid(__vp) (__vp)->lport.pid | ||
39 | #define __vport_fabric(__vp) (__vp)->lport.fabric | ||
40 | #define __vport_vfid(__vp) (__vp)->lport.fabric->vf_id | ||
41 | |||
42 | #define BFA_FCS_VPORT_MAX_RETRIES 5 | ||
43 | /* | ||
44 | * Forward declarations | ||
45 | */ | ||
46 | static void bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport); | ||
47 | static void bfa_fcs_vport_timeout(void *vport_arg); | ||
48 | static void bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport); | ||
49 | static void bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport); | ||
50 | |||
51 | /** | ||
52 | * fcs_vport_sm FCS virtual port state machine | ||
53 | */ | ||
54 | |||
55 | /** | ||
56 | * VPort State Machine events | ||
57 | */ | ||
58 | enum bfa_fcs_vport_event { | ||
59 | BFA_FCS_VPORT_SM_CREATE = 1, /* vport create event */ | ||
60 | BFA_FCS_VPORT_SM_DELETE = 2, /* vport delete event */ | ||
61 | BFA_FCS_VPORT_SM_START = 3, /* vport start request */ | ||
62 | BFA_FCS_VPORT_SM_STOP = 4, /* stop: unsupported */ | ||
63 | BFA_FCS_VPORT_SM_ONLINE = 5, /* fabric online */ | ||
64 | BFA_FCS_VPORT_SM_OFFLINE = 6, /* fabric offline event */ | ||
65 | BFA_FCS_VPORT_SM_FRMSENT = 7, /* fdisc/logo sent events */ | ||
66 | BFA_FCS_VPORT_SM_RSP_OK = 8, /* good response */ | ||
67 | BFA_FCS_VPORT_SM_RSP_ERROR = 9, /* error/bad response */ | ||
68 | BFA_FCS_VPORT_SM_TIMEOUT = 10, /* delay timer event */ | ||
69 | BFA_FCS_VPORT_SM_DELCOMP = 11, /* lport delete completion */ | ||
70 | BFA_FCS_VPORT_SM_RSP_DUP_WWN = 12, /* Dup wnn error */ | ||
71 | BFA_FCS_VPORT_SM_RSP_FAILED = 13, /* non-retryable failure */ | ||
72 | }; | ||
73 | |||
74 | static void bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, | ||
75 | enum bfa_fcs_vport_event event); | ||
76 | static void bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, | ||
77 | enum bfa_fcs_vport_event event); | ||
78 | static void bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, | ||
79 | enum bfa_fcs_vport_event event); | ||
80 | static void bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, | ||
81 | enum bfa_fcs_vport_event event); | ||
82 | static void bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, | ||
83 | enum bfa_fcs_vport_event event); | ||
84 | static void bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, | ||
85 | enum bfa_fcs_vport_event event); | ||
86 | static void bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, | ||
87 | enum bfa_fcs_vport_event event); | ||
88 | static void bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, | ||
89 | enum bfa_fcs_vport_event event); | ||
90 | static void bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, | ||
91 | enum bfa_fcs_vport_event event); | ||
92 | static void bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, | ||
93 | enum bfa_fcs_vport_event event); | ||
94 | |||
95 | static struct bfa_sm_table_s vport_sm_table[] = { | ||
96 | {BFA_SM(bfa_fcs_vport_sm_uninit), BFA_FCS_VPORT_UNINIT}, | ||
97 | {BFA_SM(bfa_fcs_vport_sm_created), BFA_FCS_VPORT_CREATED}, | ||
98 | {BFA_SM(bfa_fcs_vport_sm_offline), BFA_FCS_VPORT_OFFLINE}, | ||
99 | {BFA_SM(bfa_fcs_vport_sm_fdisc), BFA_FCS_VPORT_FDISC}, | ||
100 | {BFA_SM(bfa_fcs_vport_sm_fdisc_retry), BFA_FCS_VPORT_FDISC_RETRY}, | ||
101 | {BFA_SM(bfa_fcs_vport_sm_online), BFA_FCS_VPORT_ONLINE}, | ||
102 | {BFA_SM(bfa_fcs_vport_sm_deleting), BFA_FCS_VPORT_DELETING}, | ||
103 | {BFA_SM(bfa_fcs_vport_sm_cleanup), BFA_FCS_VPORT_CLEANUP}, | ||
104 | {BFA_SM(bfa_fcs_vport_sm_logo), BFA_FCS_VPORT_LOGO}, | ||
105 | {BFA_SM(bfa_fcs_vport_sm_error), BFA_FCS_VPORT_ERROR} | ||
106 | }; | ||
107 | |||
108 | /** | ||
109 | * Beginning state. | ||
110 | */ | ||
111 | static void | ||
112 | bfa_fcs_vport_sm_uninit(struct bfa_fcs_vport_s *vport, | ||
113 | enum bfa_fcs_vport_event event) | ||
114 | { | ||
115 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
116 | bfa_trc(__vport_fcs(vport), event); | ||
117 | |||
118 | switch (event) { | ||
119 | case BFA_FCS_VPORT_SM_CREATE: | ||
120 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_created); | ||
121 | bfa_fcs_fabric_addvport(__vport_fabric(vport), vport); | ||
122 | break; | ||
123 | |||
124 | default: | ||
125 | bfa_assert(0); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * Created state - a start event is required to start up the state machine. | ||
131 | */ | ||
132 | static void | ||
133 | bfa_fcs_vport_sm_created(struct bfa_fcs_vport_s *vport, | ||
134 | enum bfa_fcs_vport_event event) | ||
135 | { | ||
136 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
137 | bfa_trc(__vport_fcs(vport), event); | ||
138 | |||
139 | switch (event) { | ||
140 | case BFA_FCS_VPORT_SM_START: | ||
141 | if (bfa_fcs_fabric_is_online(__vport_fabric(vport)) | ||
142 | && bfa_fcs_fabric_npiv_capable(__vport_fabric(vport))) { | ||
143 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); | ||
144 | bfa_fcs_vport_do_fdisc(vport); | ||
145 | } else { | ||
146 | /** | ||
147 | * Fabric is offline or not NPIV capable, stay in | ||
148 | * offline state. | ||
149 | */ | ||
150 | vport->vport_stats.fab_no_npiv++; | ||
151 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | ||
152 | } | ||
153 | break; | ||
154 | |||
155 | case BFA_FCS_VPORT_SM_DELETE: | ||
156 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | ||
157 | bfa_fcs_port_delete(&vport->lport); | ||
158 | break; | ||
159 | |||
160 | case BFA_FCS_VPORT_SM_ONLINE: | ||
161 | case BFA_FCS_VPORT_SM_OFFLINE: | ||
162 | /** | ||
163 | * Ignore ONLINE/OFFLINE events from fabric till vport is started. | ||
164 | */ | ||
165 | break; | ||
166 | |||
167 | default: | ||
168 | bfa_assert(0); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | /** | ||
173 | * Offline state - awaiting ONLINE event from fabric SM. | ||
174 | */ | ||
175 | static void | ||
176 | bfa_fcs_vport_sm_offline(struct bfa_fcs_vport_s *vport, | ||
177 | enum bfa_fcs_vport_event event) | ||
178 | { | ||
179 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
180 | bfa_trc(__vport_fcs(vport), event); | ||
181 | |||
182 | switch (event) { | ||
183 | case BFA_FCS_VPORT_SM_DELETE: | ||
184 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | ||
185 | bfa_fcs_port_delete(&vport->lport); | ||
186 | break; | ||
187 | |||
188 | case BFA_FCS_VPORT_SM_ONLINE: | ||
189 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); | ||
190 | vport->fdisc_retries = 0; | ||
191 | bfa_fcs_vport_do_fdisc(vport); | ||
192 | break; | ||
193 | |||
194 | case BFA_FCS_VPORT_SM_OFFLINE: | ||
195 | /* | ||
196 | * This can happen if the vport couldn't be initialzied due | ||
197 | * the fact that the npiv was not enabled on the switch. In | ||
198 | * that case we will put the vport in offline state. However, | ||
199 | * the link can go down and cause the this event to be sent when | ||
200 | * we are already offline. Ignore it. | ||
201 | */ | ||
202 | break; | ||
203 | |||
204 | default: | ||
205 | bfa_assert(0); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | /** | ||
210 | * FDISC is sent and awaiting reply from fabric. | ||
211 | */ | ||
212 | static void | ||
213 | bfa_fcs_vport_sm_fdisc(struct bfa_fcs_vport_s *vport, | ||
214 | enum bfa_fcs_vport_event event) | ||
215 | { | ||
216 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
217 | bfa_trc(__vport_fcs(vport), event); | ||
218 | |||
219 | switch (event) { | ||
220 | case BFA_FCS_VPORT_SM_DELETE: | ||
221 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); | ||
222 | bfa_lps_discard(vport->lps); | ||
223 | bfa_fcs_vport_do_logo(vport); | ||
224 | break; | ||
225 | |||
226 | case BFA_FCS_VPORT_SM_OFFLINE: | ||
227 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | ||
228 | bfa_lps_discard(vport->lps); | ||
229 | break; | ||
230 | |||
231 | case BFA_FCS_VPORT_SM_RSP_OK: | ||
232 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_online); | ||
233 | bfa_fcs_port_online(&vport->lport); | ||
234 | break; | ||
235 | |||
236 | case BFA_FCS_VPORT_SM_RSP_ERROR: | ||
237 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc_retry); | ||
238 | bfa_timer_start(__vport_bfa(vport), &vport->timer, | ||
239 | bfa_fcs_vport_timeout, vport, | ||
240 | BFA_FCS_RETRY_TIMEOUT); | ||
241 | break; | ||
242 | |||
243 | case BFA_FCS_VPORT_SM_RSP_FAILED: | ||
244 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | ||
245 | break; | ||
246 | |||
247 | case BFA_FCS_VPORT_SM_RSP_DUP_WWN: | ||
248 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_error); | ||
249 | break; | ||
250 | |||
251 | default: | ||
252 | bfa_assert(0); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | /** | ||
257 | * FDISC attempt failed - a timer is active to retry FDISC. | ||
258 | */ | ||
259 | static void | ||
260 | bfa_fcs_vport_sm_fdisc_retry(struct bfa_fcs_vport_s *vport, | ||
261 | enum bfa_fcs_vport_event event) | ||
262 | { | ||
263 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
264 | bfa_trc(__vport_fcs(vport), event); | ||
265 | |||
266 | switch (event) { | ||
267 | case BFA_FCS_VPORT_SM_DELETE: | ||
268 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | ||
269 | bfa_timer_stop(&vport->timer); | ||
270 | bfa_fcs_port_delete(&vport->lport); | ||
271 | break; | ||
272 | |||
273 | case BFA_FCS_VPORT_SM_OFFLINE: | ||
274 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | ||
275 | bfa_timer_stop(&vport->timer); | ||
276 | break; | ||
277 | |||
278 | case BFA_FCS_VPORT_SM_TIMEOUT: | ||
279 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_fdisc); | ||
280 | vport->vport_stats.fdisc_retries++; | ||
281 | vport->fdisc_retries++; | ||
282 | bfa_fcs_vport_do_fdisc(vport); | ||
283 | break; | ||
284 | |||
285 | default: | ||
286 | bfa_assert(0); | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * Vport is online (FDISC is complete). | ||
292 | */ | ||
293 | static void | ||
294 | bfa_fcs_vport_sm_online(struct bfa_fcs_vport_s *vport, | ||
295 | enum bfa_fcs_vport_event event) | ||
296 | { | ||
297 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
298 | bfa_trc(__vport_fcs(vport), event); | ||
299 | |||
300 | switch (event) { | ||
301 | case BFA_FCS_VPORT_SM_DELETE: | ||
302 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_deleting); | ||
303 | bfa_fcs_port_delete(&vport->lport); | ||
304 | break; | ||
305 | |||
306 | case BFA_FCS_VPORT_SM_OFFLINE: | ||
307 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_offline); | ||
308 | bfa_lps_discard(vport->lps); | ||
309 | bfa_fcs_port_offline(&vport->lport); | ||
310 | break; | ||
311 | |||
312 | default: | ||
313 | bfa_assert(0); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | /** | ||
318 | * Vport is being deleted - awaiting lport delete completion to send | ||
319 | * LOGO to fabric. | ||
320 | */ | ||
321 | static void | ||
322 | bfa_fcs_vport_sm_deleting(struct bfa_fcs_vport_s *vport, | ||
323 | enum bfa_fcs_vport_event event) | ||
324 | { | ||
325 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
326 | bfa_trc(__vport_fcs(vport), event); | ||
327 | |||
328 | switch (event) { | ||
329 | case BFA_FCS_VPORT_SM_DELETE: | ||
330 | break; | ||
331 | |||
332 | case BFA_FCS_VPORT_SM_DELCOMP: | ||
333 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_logo); | ||
334 | bfa_fcs_vport_do_logo(vport); | ||
335 | break; | ||
336 | |||
337 | case BFA_FCS_VPORT_SM_OFFLINE: | ||
338 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_cleanup); | ||
339 | break; | ||
340 | |||
341 | default: | ||
342 | bfa_assert(0); | ||
343 | } | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * Error State. | ||
348 | * This state will be set when the Vport Creation fails due to errors like | ||
349 | * Dup WWN. In this state only operation allowed is a Vport Delete. | ||
350 | */ | ||
351 | static void | ||
352 | bfa_fcs_vport_sm_error(struct bfa_fcs_vport_s *vport, | ||
353 | enum bfa_fcs_vport_event event) | ||
354 | { | ||
355 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
356 | bfa_trc(__vport_fcs(vport), event); | ||
357 | |||
358 | switch (event) { | ||
359 | case BFA_FCS_VPORT_SM_DELETE: | ||
360 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); | ||
361 | bfa_fcs_vport_free(vport); | ||
362 | break; | ||
363 | |||
364 | default: | ||
365 | bfa_trc(__vport_fcs(vport), event); | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /** | ||
370 | * Lport cleanup is in progress since vport is being deleted. Fabric is | ||
371 | * offline, so no LOGO is needed to complete vport deletion. | ||
372 | */ | ||
373 | static void | ||
374 | bfa_fcs_vport_sm_cleanup(struct bfa_fcs_vport_s *vport, | ||
375 | enum bfa_fcs_vport_event event) | ||
376 | { | ||
377 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
378 | bfa_trc(__vport_fcs(vport), event); | ||
379 | |||
380 | switch (event) { | ||
381 | case BFA_FCS_VPORT_SM_DELCOMP: | ||
382 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); | ||
383 | bfa_fcs_vport_free(vport); | ||
384 | break; | ||
385 | |||
386 | case BFA_FCS_VPORT_SM_DELETE: | ||
387 | break; | ||
388 | |||
389 | default: | ||
390 | bfa_assert(0); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | /** | ||
395 | * LOGO is sent to fabric. Vport delete is in progress. Lport delete cleanup | ||
396 | * is done. | ||
397 | */ | ||
398 | static void | ||
399 | bfa_fcs_vport_sm_logo(struct bfa_fcs_vport_s *vport, | ||
400 | enum bfa_fcs_vport_event event) | ||
401 | { | ||
402 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
403 | bfa_trc(__vport_fcs(vport), event); | ||
404 | |||
405 | switch (event) { | ||
406 | case BFA_FCS_VPORT_SM_OFFLINE: | ||
407 | bfa_lps_discard(vport->lps); | ||
408 | /* | ||
409 | * !!! fall through !!! | ||
410 | */ | ||
411 | |||
412 | case BFA_FCS_VPORT_SM_RSP_OK: | ||
413 | case BFA_FCS_VPORT_SM_RSP_ERROR: | ||
414 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); | ||
415 | bfa_fcs_vport_free(vport); | ||
416 | break; | ||
417 | |||
418 | case BFA_FCS_VPORT_SM_DELETE: | ||
419 | break; | ||
420 | |||
421 | default: | ||
422 | bfa_assert(0); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | |||
427 | |||
428 | /** | ||
429 | * fcs_vport_private FCS virtual port private functions | ||
430 | */ | ||
431 | |||
432 | /** | ||
433 | * Send AEN notification | ||
434 | */ | ||
435 | static void | ||
436 | bfa_fcs_vport_aen_post(bfa_fcs_lport_t *port, enum bfa_lport_aen_event event) | ||
437 | { | ||
438 | union bfa_aen_data_u aen_data; | ||
439 | struct bfa_log_mod_s *logmod = port->fcs->logm; | ||
440 | enum bfa_port_role role = port->port_cfg.roles; | ||
441 | wwn_t lpwwn = bfa_fcs_port_get_pwwn(port); | ||
442 | char lpwwn_ptr[BFA_STRING_32]; | ||
443 | char *role_str[BFA_PORT_ROLE_FCP_MAX / 2 + 1] = | ||
444 | { "Initiator", "Target", "IPFC" }; | ||
445 | |||
446 | wwn2str(lpwwn_ptr, lpwwn); | ||
447 | |||
448 | bfa_assert(role <= BFA_PORT_ROLE_FCP_MAX); | ||
449 | |||
450 | switch (event) { | ||
451 | case BFA_LPORT_AEN_NPIV_DUP_WWN: | ||
452 | bfa_log(logmod, BFA_AEN_LPORT_NPIV_DUP_WWN, lpwwn_ptr, | ||
453 | role_str[role / 2]); | ||
454 | break; | ||
455 | case BFA_LPORT_AEN_NPIV_FABRIC_MAX: | ||
456 | bfa_log(logmod, BFA_AEN_LPORT_NPIV_FABRIC_MAX, lpwwn_ptr, | ||
457 | role_str[role / 2]); | ||
458 | break; | ||
459 | case BFA_LPORT_AEN_NPIV_UNKNOWN: | ||
460 | bfa_log(logmod, BFA_AEN_LPORT_NPIV_UNKNOWN, lpwwn_ptr, | ||
461 | role_str[role / 2]); | ||
462 | break; | ||
463 | default: | ||
464 | break; | ||
465 | } | ||
466 | |||
467 | aen_data.lport.vf_id = port->fabric->vf_id; | ||
468 | aen_data.lport.roles = role; | ||
469 | aen_data.lport.ppwwn = | ||
470 | bfa_fcs_port_get_pwwn(bfa_fcs_get_base_port(port->fcs)); | ||
471 | aen_data.lport.lpwwn = lpwwn; | ||
472 | } | ||
473 | |||
474 | /** | ||
475 | * This routine will be called to send a FDISC command. | ||
476 | */ | ||
477 | static void | ||
478 | bfa_fcs_vport_do_fdisc(struct bfa_fcs_vport_s *vport) | ||
479 | { | ||
480 | bfa_lps_fdisc(vport->lps, vport, | ||
481 | bfa_pport_get_maxfrsize(__vport_bfa(vport)), | ||
482 | __vport_pwwn(vport), __vport_nwwn(vport)); | ||
483 | vport->vport_stats.fdisc_sent++; | ||
484 | } | ||
485 | |||
486 | static void | ||
487 | bfa_fcs_vport_fdisc_rejected(struct bfa_fcs_vport_s *vport) | ||
488 | { | ||
489 | u8 lsrjt_rsn = bfa_lps_get_lsrjt_rsn(vport->lps); | ||
490 | u8 lsrjt_expl = bfa_lps_get_lsrjt_expl(vport->lps); | ||
491 | |||
492 | bfa_trc(__vport_fcs(vport), lsrjt_rsn); | ||
493 | bfa_trc(__vport_fcs(vport), lsrjt_expl); | ||
494 | |||
495 | /* | ||
496 | * For certain reason codes, we don't want to retry. | ||
497 | */ | ||
498 | switch (bfa_lps_get_lsrjt_expl(vport->lps)) { | ||
499 | case FC_LS_RJT_EXP_INV_PORT_NAME: /* by brocade */ | ||
500 | case FC_LS_RJT_EXP_INVALID_NPORT_ID: /* by Cisco */ | ||
501 | if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) | ||
502 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | ||
503 | else { | ||
504 | bfa_fcs_vport_aen_post(&vport->lport, | ||
505 | BFA_LPORT_AEN_NPIV_DUP_WWN); | ||
506 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_DUP_WWN); | ||
507 | } | ||
508 | break; | ||
509 | |||
510 | case FC_LS_RJT_EXP_INSUFF_RES: | ||
511 | /* | ||
512 | * This means max logins per port/switch setting on the | ||
513 | * switch was exceeded. | ||
514 | */ | ||
515 | if (vport->fdisc_retries < BFA_FCS_VPORT_MAX_RETRIES) | ||
516 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | ||
517 | else { | ||
518 | bfa_fcs_vport_aen_post(&vport->lport, | ||
519 | BFA_LPORT_AEN_NPIV_FABRIC_MAX); | ||
520 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_FAILED); | ||
521 | } | ||
522 | break; | ||
523 | |||
524 | default: | ||
525 | if (vport->fdisc_retries == 0) /* Print only once */ | ||
526 | bfa_fcs_vport_aen_post(&vport->lport, | ||
527 | BFA_LPORT_AEN_NPIV_UNKNOWN); | ||
528 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | ||
529 | } | ||
530 | } | ||
531 | |||
532 | /** | ||
533 | * Called to send a logout to the fabric. Used when a V-Port is | ||
534 | * deleted/stopped. | ||
535 | */ | ||
536 | static void | ||
537 | bfa_fcs_vport_do_logo(struct bfa_fcs_vport_s *vport) | ||
538 | { | ||
539 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
540 | |||
541 | vport->vport_stats.logo_sent++; | ||
542 | bfa_lps_fdisclogo(vport->lps); | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * This routine will be called by bfa_timer on timer timeouts. | ||
547 | * | ||
548 | * param[in] vport - pointer to bfa_fcs_vport_t. | ||
549 | * param[out] vport_status - pointer to return vport status in | ||
550 | * | ||
551 | * return | ||
552 | * void | ||
553 | * | ||
554 | * Special Considerations: | ||
555 | * | ||
556 | * note | ||
557 | */ | ||
558 | static void | ||
559 | bfa_fcs_vport_timeout(void *vport_arg) | ||
560 | { | ||
561 | struct bfa_fcs_vport_s *vport = (struct bfa_fcs_vport_s *)vport_arg; | ||
562 | |||
563 | vport->vport_stats.fdisc_timeouts++; | ||
564 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_TIMEOUT); | ||
565 | } | ||
566 | |||
567 | static void | ||
568 | bfa_fcs_vport_free(struct bfa_fcs_vport_s *vport) | ||
569 | { | ||
570 | bfa_fcs_fabric_delvport(__vport_fabric(vport), vport); | ||
571 | bfa_fcb_vport_delete(vport->vport_drv); | ||
572 | bfa_lps_delete(vport->lps); | ||
573 | } | ||
574 | |||
575 | |||
576 | |||
577 | /** | ||
578 | * fcs_vport_public FCS virtual port public interfaces | ||
579 | */ | ||
580 | |||
581 | /** | ||
582 | * Online notification from fabric SM. | ||
583 | */ | ||
584 | void | ||
585 | bfa_fcs_vport_online(struct bfa_fcs_vport_s *vport) | ||
586 | { | ||
587 | vport->vport_stats.fab_online++; | ||
588 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_ONLINE); | ||
589 | } | ||
590 | |||
591 | /** | ||
592 | * Offline notification from fabric SM. | ||
593 | */ | ||
594 | void | ||
595 | bfa_fcs_vport_offline(struct bfa_fcs_vport_s *vport) | ||
596 | { | ||
597 | vport->vport_stats.fab_offline++; | ||
598 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_OFFLINE); | ||
599 | } | ||
600 | |||
601 | /** | ||
602 | * Cleanup notification from fabric SM on link timer expiry. | ||
603 | */ | ||
604 | void | ||
605 | bfa_fcs_vport_cleanup(struct bfa_fcs_vport_s *vport) | ||
606 | { | ||
607 | vport->vport_stats.fab_cleanup++; | ||
608 | } | ||
609 | |||
610 | /** | ||
611 | * Delete completion callback from associated lport | ||
612 | */ | ||
613 | void | ||
614 | bfa_fcs_vport_delete_comp(struct bfa_fcs_vport_s *vport) | ||
615 | { | ||
616 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELCOMP); | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * Module initialization | ||
621 | */ | ||
622 | void | ||
623 | bfa_fcs_vport_modinit(struct bfa_fcs_s *fcs) | ||
624 | { | ||
625 | } | ||
626 | |||
627 | /** | ||
628 | * Module cleanup | ||
629 | */ | ||
630 | void | ||
631 | bfa_fcs_vport_modexit(struct bfa_fcs_s *fcs) | ||
632 | { | ||
633 | bfa_fcs_modexit_comp(fcs); | ||
634 | } | ||
635 | |||
636 | u32 | ||
637 | bfa_fcs_vport_get_max(struct bfa_fcs_s *fcs) | ||
638 | { | ||
639 | struct bfa_ioc_attr_s ioc_attr; | ||
640 | |||
641 | bfa_get_attr(fcs->bfa, &ioc_attr); | ||
642 | |||
643 | if (ioc_attr.pci_attr.device_id == BFA_PCI_DEVICE_ID_CT) | ||
644 | return (BFA_FCS_MAX_VPORTS_SUPP_CT); | ||
645 | else | ||
646 | return (BFA_FCS_MAX_VPORTS_SUPP_CB); | ||
647 | } | ||
648 | |||
649 | |||
650 | |||
651 | /** | ||
652 | * fcs_vport_api Virtual port API | ||
653 | */ | ||
654 | |||
655 | /** | ||
656 | * Use this function to instantiate a new FCS vport object. This | ||
657 | * function will not trigger any HW initialization process (which will be | ||
658 | * done in vport_start() call) | ||
659 | * | ||
660 | * param[in] vport - pointer to bfa_fcs_vport_t. This space | ||
661 | * needs to be allocated by the driver. | ||
662 | * param[in] fcs - FCS instance | ||
663 | * param[in] vport_cfg - vport configuration | ||
664 | * param[in] vf_id - VF_ID if vport is created within a VF. | ||
665 | * FC_VF_ID_NULL to specify base fabric. | ||
666 | * param[in] vport_drv - Opaque handle back to the driver's vport | ||
667 | * structure | ||
668 | * | ||
669 | * retval BFA_STATUS_OK - on success. | ||
670 | * retval BFA_STATUS_FAILED - on failure. | ||
671 | */ | ||
672 | bfa_status_t | ||
673 | bfa_fcs_vport_create(struct bfa_fcs_vport_s *vport, struct bfa_fcs_s *fcs, | ||
674 | u16 vf_id, struct bfa_port_cfg_s *vport_cfg, | ||
675 | struct bfad_vport_s *vport_drv) | ||
676 | { | ||
677 | if (vport_cfg->pwwn == 0) | ||
678 | return (BFA_STATUS_INVALID_WWN); | ||
679 | |||
680 | if (bfa_fcs_port_get_pwwn(&fcs->fabric.bport) == vport_cfg->pwwn) | ||
681 | return BFA_STATUS_VPORT_WWN_BP; | ||
682 | |||
683 | if (bfa_fcs_vport_lookup(fcs, vf_id, vport_cfg->pwwn) != NULL) | ||
684 | return BFA_STATUS_VPORT_EXISTS; | ||
685 | |||
686 | if (bfa_fcs_fabric_vport_count(&fcs->fabric) == | ||
687 | bfa_fcs_vport_get_max(fcs)) | ||
688 | return BFA_STATUS_VPORT_MAX; | ||
689 | |||
690 | vport->lps = bfa_lps_alloc(fcs->bfa); | ||
691 | if (!vport->lps) | ||
692 | return BFA_STATUS_VPORT_MAX; | ||
693 | |||
694 | vport->vport_drv = vport_drv; | ||
695 | bfa_sm_set_state(vport, bfa_fcs_vport_sm_uninit); | ||
696 | |||
697 | bfa_fcs_lport_init(&vport->lport, fcs, vf_id, vport_cfg, vport); | ||
698 | |||
699 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_CREATE); | ||
700 | |||
701 | return BFA_STATUS_OK; | ||
702 | } | ||
703 | |||
704 | /** | ||
705 | * Use this function initialize the vport. | ||
706 | * | ||
707 | * @param[in] vport - pointer to bfa_fcs_vport_t. | ||
708 | * | ||
709 | * @returns None | ||
710 | */ | ||
711 | bfa_status_t | ||
712 | bfa_fcs_vport_start(struct bfa_fcs_vport_s *vport) | ||
713 | { | ||
714 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_START); | ||
715 | |||
716 | return BFA_STATUS_OK; | ||
717 | } | ||
718 | |||
719 | /** | ||
720 | * Use this function quiese the vport object. This function will return | ||
721 | * immediately, when the vport is actually stopped, the | ||
722 | * bfa_drv_vport_stop_cb() will be called. | ||
723 | * | ||
724 | * param[in] vport - pointer to bfa_fcs_vport_t. | ||
725 | * | ||
726 | * return None | ||
727 | */ | ||
728 | bfa_status_t | ||
729 | bfa_fcs_vport_stop(struct bfa_fcs_vport_s *vport) | ||
730 | { | ||
731 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_STOP); | ||
732 | |||
733 | return BFA_STATUS_OK; | ||
734 | } | ||
735 | |||
736 | /** | ||
737 | * Use this function to delete a vport object. Fabric object should | ||
738 | * be stopped before this function call. | ||
739 | * | ||
740 | * param[in] vport - pointer to bfa_fcs_vport_t. | ||
741 | * | ||
742 | * return None | ||
743 | */ | ||
744 | bfa_status_t | ||
745 | bfa_fcs_vport_delete(struct bfa_fcs_vport_s *vport) | ||
746 | { | ||
747 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_DELETE); | ||
748 | |||
749 | return BFA_STATUS_OK; | ||
750 | } | ||
751 | |||
752 | /** | ||
753 | * Use this function to get vport's current status info. | ||
754 | * | ||
755 | * param[in] vport pointer to bfa_fcs_vport_t. | ||
756 | * param[out] attr pointer to return vport attributes | ||
757 | * | ||
758 | * return None | ||
759 | */ | ||
760 | void | ||
761 | bfa_fcs_vport_get_attr(struct bfa_fcs_vport_s *vport, | ||
762 | struct bfa_vport_attr_s *attr) | ||
763 | { | ||
764 | if (vport == NULL || attr == NULL) | ||
765 | return; | ||
766 | |||
767 | bfa_os_memset(attr, 0, sizeof(struct bfa_vport_attr_s)); | ||
768 | |||
769 | bfa_fcs_port_get_attr(&vport->lport, &attr->port_attr); | ||
770 | attr->vport_state = bfa_sm_to_state(vport_sm_table, vport->sm); | ||
771 | } | ||
772 | |||
773 | /** | ||
774 | * Use this function to get vport's statistics. | ||
775 | * | ||
776 | * param[in] vport pointer to bfa_fcs_vport_t. | ||
777 | * param[out] stats pointer to return vport statistics in | ||
778 | * | ||
779 | * return None | ||
780 | */ | ||
781 | void | ||
782 | bfa_fcs_vport_get_stats(struct bfa_fcs_vport_s *vport, | ||
783 | struct bfa_vport_stats_s *stats) | ||
784 | { | ||
785 | *stats = vport->vport_stats; | ||
786 | } | ||
787 | |||
788 | /** | ||
789 | * Use this function to clear vport's statistics. | ||
790 | * | ||
791 | * param[in] vport pointer to bfa_fcs_vport_t. | ||
792 | * | ||
793 | * return None | ||
794 | */ | ||
795 | void | ||
796 | bfa_fcs_vport_clr_stats(struct bfa_fcs_vport_s *vport) | ||
797 | { | ||
798 | bfa_os_memset(&vport->vport_stats, 0, sizeof(struct bfa_vport_stats_s)); | ||
799 | } | ||
800 | |||
801 | /** | ||
802 | * Lookup a virtual port. Excludes base port from lookup. | ||
803 | */ | ||
804 | struct bfa_fcs_vport_s * | ||
805 | bfa_fcs_vport_lookup(struct bfa_fcs_s *fcs, u16 vf_id, wwn_t vpwwn) | ||
806 | { | ||
807 | struct bfa_fcs_vport_s *vport; | ||
808 | struct bfa_fcs_fabric_s *fabric; | ||
809 | |||
810 | bfa_trc(fcs, vf_id); | ||
811 | bfa_trc(fcs, vpwwn); | ||
812 | |||
813 | fabric = bfa_fcs_vf_lookup(fcs, vf_id); | ||
814 | if (!fabric) { | ||
815 | bfa_trc(fcs, vf_id); | ||
816 | return NULL; | ||
817 | } | ||
818 | |||
819 | vport = bfa_fcs_fabric_vport_lookup(fabric, vpwwn); | ||
820 | return vport; | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * FDISC Response | ||
825 | */ | ||
826 | void | ||
827 | bfa_cb_lps_fdisc_comp(void *bfad, void *uarg, bfa_status_t status) | ||
828 | { | ||
829 | struct bfa_fcs_vport_s *vport = uarg; | ||
830 | |||
831 | bfa_trc(__vport_fcs(vport), __vport_pwwn(vport)); | ||
832 | bfa_trc(__vport_fcs(vport), status); | ||
833 | |||
834 | switch (status) { | ||
835 | case BFA_STATUS_OK: | ||
836 | /* | ||
837 | * Initialiaze the V-Port fields | ||
838 | */ | ||
839 | __vport_fcid(vport) = bfa_lps_get_pid(vport->lps); | ||
840 | vport->vport_stats.fdisc_accepts++; | ||
841 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); | ||
842 | break; | ||
843 | |||
844 | case BFA_STATUS_INVALID_MAC: | ||
845 | /* | ||
846 | * Only for CNA | ||
847 | */ | ||
848 | vport->vport_stats.fdisc_acc_bad++; | ||
849 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | ||
850 | |||
851 | break; | ||
852 | |||
853 | case BFA_STATUS_EPROTOCOL: | ||
854 | switch (bfa_lps_get_extstatus(vport->lps)) { | ||
855 | case BFA_EPROTO_BAD_ACCEPT: | ||
856 | vport->vport_stats.fdisc_acc_bad++; | ||
857 | break; | ||
858 | |||
859 | case BFA_EPROTO_UNKNOWN_RSP: | ||
860 | vport->vport_stats.fdisc_unknown_rsp++; | ||
861 | break; | ||
862 | |||
863 | default: | ||
864 | break; | ||
865 | } | ||
866 | |||
867 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | ||
868 | break; | ||
869 | |||
870 | case BFA_STATUS_FABRIC_RJT: | ||
871 | vport->vport_stats.fdisc_rejects++; | ||
872 | bfa_fcs_vport_fdisc_rejected(vport); | ||
873 | break; | ||
874 | |||
875 | default: | ||
876 | vport->vport_stats.fdisc_rsp_err++; | ||
877 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_ERROR); | ||
878 | } | ||
879 | } | ||
880 | |||
881 | /** | ||
882 | * LOGO response | ||
883 | */ | ||
884 | void | ||
885 | bfa_cb_lps_fdisclogo_comp(void *bfad, void *uarg) | ||
886 | { | ||
887 | struct bfa_fcs_vport_s *vport = uarg; | ||
888 | bfa_sm_send_event(vport, BFA_FCS_VPORT_SM_RSP_OK); | ||
889 | } | ||
890 | |||
891 | |||
diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index d7576f28c6e9..5edde1a8c04d 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h | |||
@@ -100,6 +100,8 @@ | |||
100 | #define CTX_OFFSET 0x10000 | 100 | #define CTX_OFFSET 0x10000 |
101 | #define MAX_CID_CNT 0x4000 | 101 | #define MAX_CID_CNT 0x4000 |
102 | 102 | ||
103 | #define BNX2I_570X_PAGE_SIZE_DEFAULT 4096 | ||
104 | |||
103 | /* 5709 context registers */ | 105 | /* 5709 context registers */ |
104 | #define BNX2_MQ_CONFIG2 0x00003d00 | 106 | #define BNX2_MQ_CONFIG2 0x00003d00 |
105 | #define BNX2_MQ_CONFIG2_CONT_SZ (0x7L<<4) | 107 | #define BNX2_MQ_CONFIG2_CONT_SZ (0x7L<<4) |
diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index 41e1b0e7e2ef..5c8d7630c13e 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c | |||
@@ -2386,7 +2386,7 @@ int bnx2i_map_ep_dbell_regs(struct bnx2i_endpoint *ep) | |||
2386 | ctx_sz = (config2 & BNX2_MQ_CONFIG2_CONT_SZ) >> 3; | 2386 | ctx_sz = (config2 & BNX2_MQ_CONFIG2_CONT_SZ) >> 3; |
2387 | if (ctx_sz) | 2387 | if (ctx_sz) |
2388 | reg_off = CTX_OFFSET + MAX_CID_CNT * MB_KERNEL_CTX_SIZE | 2388 | reg_off = CTX_OFFSET + MAX_CID_CNT * MB_KERNEL_CTX_SIZE |
2389 | + PAGE_SIZE * | 2389 | + BNX2I_570X_PAGE_SIZE_DEFAULT * |
2390 | (((cid_num - first_l4l5) / ctx_sz) + 256); | 2390 | (((cid_num - first_l4l5) / ctx_sz) + 256); |
2391 | else | 2391 | else |
2392 | reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num); | 2392 | reg_off = CTX_OFFSET + (MB_KERNEL_CTX_SIZE * cid_num); |
diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 9a7ba71f1af4..cafb888c2376 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c | |||
@@ -1243,7 +1243,7 @@ bnx2i_session_create(struct iscsi_endpoint *ep, | |||
1243 | cmds_max = BNX2I_SQ_WQES_MIN; | 1243 | cmds_max = BNX2I_SQ_WQES_MIN; |
1244 | 1244 | ||
1245 | cls_session = iscsi_session_setup(&bnx2i_iscsi_transport, shost, | 1245 | cls_session = iscsi_session_setup(&bnx2i_iscsi_transport, shost, |
1246 | cmds_max, sizeof(struct bnx2i_cmd), | 1246 | cmds_max, 0, sizeof(struct bnx2i_cmd), |
1247 | initial_cmdsn, ISCSI_MAX_TARGET); | 1247 | initial_cmdsn, ISCSI_MAX_TARGET); |
1248 | if (!cls_session) | 1248 | if (!cls_session) |
1249 | return NULL; | 1249 | return NULL; |
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index c399f485aa7d..2631bddd255e 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
@@ -422,7 +422,7 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, | |||
422 | BUG_ON(hba != iscsi_host_priv(shost)); | 422 | BUG_ON(hba != iscsi_host_priv(shost)); |
423 | 423 | ||
424 | cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, | 424 | cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, |
425 | cmds_max, | 425 | cmds_max, 0, |
426 | sizeof(struct iscsi_tcp_task) + | 426 | sizeof(struct iscsi_tcp_task) + |
427 | sizeof(struct cxgb3i_task_data), | 427 | sizeof(struct cxgb3i_task_data), |
428 | initial_cmdsn, ISCSI_MAX_TARGET); | 428 | initial_cmdsn, ISCSI_MAX_TARGET); |
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 11c89311427e..268189d31d9c 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c | |||
@@ -500,8 +500,6 @@ static int mode_select_handle_sense(struct scsi_device *sdev, | |||
500 | if (!ret) | 500 | if (!ret) |
501 | goto done; | 501 | goto done; |
502 | 502 | ||
503 | err = SCSI_DH_OK; | ||
504 | |||
505 | switch (sense_hdr.sense_key) { | 503 | switch (sense_hdr.sense_key) { |
506 | case NO_SENSE: | 504 | case NO_SENSE: |
507 | case ABORTED_COMMAND: | 505 | case ABORTED_COMMAND: |
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index b6af63ca980b..496764349c41 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c | |||
@@ -1918,6 +1918,10 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg) | |||
1918 | } | 1918 | } |
1919 | size = size>>16; | 1919 | size = size>>16; |
1920 | size *= 4; | 1920 | size *= 4; |
1921 | if (size > MAX_MESSAGE_SIZE) { | ||
1922 | rcode = -EINVAL; | ||
1923 | goto cleanup; | ||
1924 | } | ||
1921 | /* Copy in the user's I2O command */ | 1925 | /* Copy in the user's I2O command */ |
1922 | if (copy_from_user (msg, user_msg, size)) { | 1926 | if (copy_from_user (msg, user_msg, size)) { |
1923 | rcode = -EFAULT; | 1927 | rcode = -EFAULT; |
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index c596ab5f05c3..a0e7e711ff9d 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * HighPoint RR3xxx/4xxx controller driver for Linux | 2 | * HighPoint RR3xxx/4xxx controller driver for Linux |
3 | * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. | 3 | * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -41,7 +41,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver"); | |||
41 | 41 | ||
42 | static char driver_name[] = "hptiop"; | 42 | static char driver_name[] = "hptiop"; |
43 | static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver"; | 43 | static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver"; |
44 | static const char driver_ver[] = "v1.3 (071203)"; | 44 | static const char driver_ver[] = "v1.6 (090910)"; |
45 | 45 | ||
46 | static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec); | 46 | static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec); |
47 | static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, | 47 | static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, |
@@ -115,9 +115,13 @@ static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba) | |||
115 | static int iop_intr_itl(struct hptiop_hba *hba) | 115 | static int iop_intr_itl(struct hptiop_hba *hba) |
116 | { | 116 | { |
117 | struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop; | 117 | struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop; |
118 | void __iomem *plx = hba->u.itl.plx; | ||
118 | u32 status; | 119 | u32 status; |
119 | int ret = 0; | 120 | int ret = 0; |
120 | 121 | ||
122 | if (plx && readl(plx + 0x11C5C) & 0xf) | ||
123 | writel(1, plx + 0x11C60); | ||
124 | |||
121 | status = readl(&iop->outbound_intstatus); | 125 | status = readl(&iop->outbound_intstatus); |
122 | 126 | ||
123 | if (status & IOPMU_OUTBOUND_INT_MSG0) { | 127 | if (status & IOPMU_OUTBOUND_INT_MSG0) { |
@@ -460,15 +464,25 @@ static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index) | |||
460 | 464 | ||
461 | static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba) | 465 | static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba) |
462 | { | 466 | { |
467 | struct pci_dev *pcidev = hba->pcidev; | ||
463 | hba->u.itl.iop = hptiop_map_pci_bar(hba, 0); | 468 | hba->u.itl.iop = hptiop_map_pci_bar(hba, 0); |
464 | if (hba->u.itl.iop) | 469 | if (hba->u.itl.iop == NULL) |
465 | return 0; | ||
466 | else | ||
467 | return -1; | 470 | return -1; |
471 | if ((pcidev->device & 0xff00) == 0x4400) { | ||
472 | hba->u.itl.plx = hba->u.itl.iop; | ||
473 | hba->u.itl.iop = hptiop_map_pci_bar(hba, 2); | ||
474 | if (hba->u.itl.iop == NULL) { | ||
475 | iounmap(hba->u.itl.plx); | ||
476 | return -1; | ||
477 | } | ||
478 | } | ||
479 | return 0; | ||
468 | } | 480 | } |
469 | 481 | ||
470 | static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba) | 482 | static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba) |
471 | { | 483 | { |
484 | if (hba->u.itl.plx) | ||
485 | iounmap(hba->u.itl.plx); | ||
472 | iounmap(hba->u.itl.iop); | 486 | iounmap(hba->u.itl.iop); |
473 | } | 487 | } |
474 | 488 | ||
@@ -1239,22 +1253,23 @@ static struct hptiop_adapter_ops hptiop_mv_ops = { | |||
1239 | static struct pci_device_id hptiop_id_table[] = { | 1253 | static struct pci_device_id hptiop_id_table[] = { |
1240 | { PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops }, | 1254 | { PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops }, |
1241 | { PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops }, | 1255 | { PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops }, |
1242 | { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops }, | 1256 | { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops }, |
1243 | { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1244 | { PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops }, | 1257 | { PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops }, |
1245 | { PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops }, | 1258 | { PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops }, |
1259 | { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1246 | { PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops }, | 1260 | { PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops }, |
1247 | { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops }, | 1261 | { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops }, |
1248 | { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1249 | { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1250 | { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, | 1262 | { PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops }, |
1263 | { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1251 | { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, | 1264 | { PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops }, |
1252 | { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1253 | { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1254 | { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, | 1265 | { PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops }, |
1255 | { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, | 1266 | { PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops }, |
1256 | { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, | 1267 | { PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops }, |
1257 | { PCI_VDEVICE(TTI, 0x4311), (kernel_ulong_t)&hptiop_itl_ops }, | 1268 | { PCI_VDEVICE(TTI, 0x4311), (kernel_ulong_t)&hptiop_itl_ops }, |
1269 | { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1270 | { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1271 | { PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1272 | { PCI_VDEVICE(TTI, 0x4400), (kernel_ulong_t)&hptiop_itl_ops }, | ||
1258 | { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops }, | 1273 | { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops }, |
1259 | { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops }, | 1274 | { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops }, |
1260 | { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops }, | 1275 | { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops }, |
diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h index a0289f219752..0b871c0ae568 100644 --- a/drivers/scsi/hptiop.h +++ b/drivers/scsi/hptiop.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * HighPoint RR3xxx/4xxx controller driver for Linux | 2 | * HighPoint RR3xxx/4xxx controller driver for Linux |
3 | * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. | 3 | * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 6 | * it under the terms of the GNU General Public License as published by |
@@ -228,6 +228,7 @@ struct hptiop_hba { | |||
228 | union { | 228 | union { |
229 | struct { | 229 | struct { |
230 | struct hpt_iopmu_itl __iomem *iop; | 230 | struct hpt_iopmu_itl __iomem *iop; |
231 | void __iomem *plx; | ||
231 | } itl; | 232 | } itl; |
232 | struct { | 233 | struct { |
233 | struct hpt_iopmv_regs *regs; | 234 | struct hpt_iopmv_regs *regs; |
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 2b1b834a098b..edc49ca49cea 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -811,7 +811,7 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max, | |||
811 | goto free_host; | 811 | goto free_host; |
812 | 812 | ||
813 | cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost, | 813 | cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost, |
814 | cmds_max, | 814 | cmds_max, 0, |
815 | sizeof(struct iscsi_tcp_task) + | 815 | sizeof(struct iscsi_tcp_task) + |
816 | sizeof(struct iscsi_sw_tcp_hdrbuf), | 816 | sizeof(struct iscsi_sw_tcp_hdrbuf), |
817 | initial_cmdsn, 0); | 817 | initial_cmdsn, 0); |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 8dc73c489a17..f1a4246f890c 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -2436,7 +2436,7 @@ static void iscsi_host_dec_session_cnt(struct Scsi_Host *shost) | |||
2436 | */ | 2436 | */ |
2437 | struct iscsi_cls_session * | 2437 | struct iscsi_cls_session * |
2438 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | 2438 | iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, |
2439 | uint16_t cmds_max, int cmd_task_size, | 2439 | uint16_t cmds_max, int dd_size, int cmd_task_size, |
2440 | uint32_t initial_cmdsn, unsigned int id) | 2440 | uint32_t initial_cmdsn, unsigned int id) |
2441 | { | 2441 | { |
2442 | struct iscsi_host *ihost = shost_priv(shost); | 2442 | struct iscsi_host *ihost = shost_priv(shost); |
@@ -2486,7 +2486,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
2486 | scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX; | 2486 | scsi_cmds = total_cmds - ISCSI_MGMT_CMDS_MAX; |
2487 | 2487 | ||
2488 | cls_session = iscsi_alloc_session(shost, iscsit, | 2488 | cls_session = iscsi_alloc_session(shost, iscsit, |
2489 | sizeof(struct iscsi_session)); | 2489 | sizeof(struct iscsi_session) + |
2490 | dd_size); | ||
2490 | if (!cls_session) | 2491 | if (!cls_session) |
2491 | goto dec_session_count; | 2492 | goto dec_session_count; |
2492 | session = cls_session->dd_data; | 2493 | session = cls_session->dd_data; |
@@ -2503,6 +2504,7 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, | |||
2503 | session->max_cmdsn = initial_cmdsn + 1; | 2504 | session->max_cmdsn = initial_cmdsn + 1; |
2504 | session->max_r2t = 1; | 2505 | session->max_r2t = 1; |
2505 | session->tt = iscsit; | 2506 | session->tt = iscsit; |
2507 | session->dd_data = cls_session->dd_data + sizeof(*session); | ||
2506 | mutex_init(&session->eh_mutex); | 2508 | mutex_init(&session->eh_mutex); |
2507 | spin_lock_init(&session->lock); | 2509 | spin_lock_init(&session->lock); |
2508 | 2510 | ||
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 61d089703806..c88f59f0ce30 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -56,8 +56,6 @@ static char *dif_op_str[] = { | |||
56 | "SCSI_PROT_WRITE_INSERT", | 56 | "SCSI_PROT_WRITE_INSERT", |
57 | "SCSI_PROT_READ_PASS", | 57 | "SCSI_PROT_READ_PASS", |
58 | "SCSI_PROT_WRITE_PASS", | 58 | "SCSI_PROT_WRITE_PASS", |
59 | "SCSI_PROT_READ_CONVERT", | ||
60 | "SCSI_PROT_WRITE_CONVERT" | ||
61 | }; | 59 | }; |
62 | static void | 60 | static void |
63 | lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); | 61 | lpfc_release_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb); |
@@ -1131,13 +1129,11 @@ lpfc_sc_to_sli_prof(struct scsi_cmnd *sc) | |||
1131 | ret_prof = LPFC_PROF_A1; | 1129 | ret_prof = LPFC_PROF_A1; |
1132 | break; | 1130 | break; |
1133 | 1131 | ||
1134 | case SCSI_PROT_READ_CONVERT: | 1132 | case SCSI_PROT_READ_PASS: |
1135 | case SCSI_PROT_WRITE_CONVERT: | 1133 | case SCSI_PROT_WRITE_PASS: |
1136 | ret_prof = LPFC_PROF_AST1; | 1134 | ret_prof = LPFC_PROF_AST1; |
1137 | break; | 1135 | break; |
1138 | 1136 | ||
1139 | case SCSI_PROT_READ_PASS: | ||
1140 | case SCSI_PROT_WRITE_PASS: | ||
1141 | case SCSI_PROT_NORMAL: | 1137 | case SCSI_PROT_NORMAL: |
1142 | default: | 1138 | default: |
1143 | printk(KERN_ERR "Bad op/guard:%d/%d combination\n", | 1139 | printk(KERN_ERR "Bad op/guard:%d/%d combination\n", |
@@ -1157,8 +1153,6 @@ lpfc_sc_to_sli_prof(struct scsi_cmnd *sc) | |||
1157 | ret_prof = LPFC_PROF_C1; | 1153 | ret_prof = LPFC_PROF_C1; |
1158 | break; | 1154 | break; |
1159 | 1155 | ||
1160 | case SCSI_PROT_READ_CONVERT: | ||
1161 | case SCSI_PROT_WRITE_CONVERT: | ||
1162 | case SCSI_PROT_READ_INSERT: | 1156 | case SCSI_PROT_READ_INSERT: |
1163 | case SCSI_PROT_WRITE_STRIP: | 1157 | case SCSI_PROT_WRITE_STRIP: |
1164 | case SCSI_PROT_NORMAL: | 1158 | case SCSI_PROT_NORMAL: |
@@ -1209,8 +1203,7 @@ lpfc_get_cmd_dif_parms(struct scsi_cmnd *sc, uint16_t *apptagmask, | |||
1209 | static int cnt; | 1203 | static int cnt; |
1210 | 1204 | ||
1211 | if (protcnt && (op == SCSI_PROT_WRITE_STRIP || | 1205 | if (protcnt && (op == SCSI_PROT_WRITE_STRIP || |
1212 | op == SCSI_PROT_WRITE_PASS || | 1206 | op == SCSI_PROT_WRITE_PASS)) { |
1213 | op == SCSI_PROT_WRITE_CONVERT)) { | ||
1214 | 1207 | ||
1215 | cnt++; | 1208 | cnt++; |
1216 | spt = page_address(sg_page(scsi_prot_sglist(sc))) + | 1209 | spt = page_address(sg_page(scsi_prot_sglist(sc))) + |
@@ -1501,8 +1494,6 @@ lpfc_prot_group_type(struct lpfc_hba *phba, struct scsi_cmnd *sc) | |||
1501 | case SCSI_PROT_WRITE_STRIP: | 1494 | case SCSI_PROT_WRITE_STRIP: |
1502 | case SCSI_PROT_READ_PASS: | 1495 | case SCSI_PROT_READ_PASS: |
1503 | case SCSI_PROT_WRITE_PASS: | 1496 | case SCSI_PROT_WRITE_PASS: |
1504 | case SCSI_PROT_WRITE_CONVERT: | ||
1505 | case SCSI_PROT_READ_CONVERT: | ||
1506 | ret = LPFC_PG_TYPE_DIF_BUF; | 1497 | ret = LPFC_PG_TYPE_DIF_BUF; |
1507 | break; | 1498 | break; |
1508 | default: | 1499 | default: |
diff --git a/drivers/scsi/mpt2sas/Kconfig b/drivers/scsi/mpt2sas/Kconfig index 4a86855c23b3..70c4c2467dd8 100644 --- a/drivers/scsi/mpt2sas/Kconfig +++ b/drivers/scsi/mpt2sas/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # Kernel configuration file for the MPT2SAS | 2 | # Kernel configuration file for the MPT2SAS |
3 | # | 3 | # |
4 | # This code is based on drivers/scsi/mpt2sas/Kconfig | 4 | # This code is based on drivers/scsi/mpt2sas/Kconfig |
5 | # Copyright (C) 2007-2008 LSI Corporation | 5 | # Copyright (C) 2007-2009 LSI Corporation |
6 | # (mailto:DL-MPTFusionLinux@lsi.com) | 6 | # (mailto:DL-MPTFusionLinux@lsi.com) |
7 | 7 | ||
8 | # This program is free software; you can redistribute it and/or | 8 | # This program is free software; you can redistribute it and/or |
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h index 7bb2ece8b2e4..f9f6c0839276 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2.h | |||
@@ -8,7 +8,7 @@ | |||
8 | * scatter/gather formats. | 8 | * scatter/gather formats. |
9 | * Creation Date: June 21, 2006 | 9 | * Creation Date: June 21, 2006 |
10 | * | 10 | * |
11 | * mpi2.h Version: 02.00.11 | 11 | * mpi2.h Version: 02.00.12 |
12 | * | 12 | * |
13 | * Version History | 13 | * Version History |
14 | * --------------- | 14 | * --------------- |
@@ -45,6 +45,13 @@ | |||
45 | * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. | 45 | * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. |
46 | * Moved LUN field defines from mpi2_init.h. | 46 | * Moved LUN field defines from mpi2_init.h. |
47 | * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. | 47 | * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. |
48 | * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT. | ||
49 | * In all request and reply descriptors, replaced VF_ID | ||
50 | * field with MSIxIndex field. | ||
51 | * Removed DevHandle field from | ||
52 | * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those | ||
53 | * bytes reserved. | ||
54 | * Added RAID Accelerator functionality. | ||
48 | * -------------------------------------------------------------------------- | 55 | * -------------------------------------------------------------------------- |
49 | */ | 56 | */ |
50 | 57 | ||
@@ -70,7 +77,7 @@ | |||
70 | #define MPI2_VERSION_02_00 (0x0200) | 77 | #define MPI2_VERSION_02_00 (0x0200) |
71 | 78 | ||
72 | /* versioning for this MPI header set */ | 79 | /* versioning for this MPI header set */ |
73 | #define MPI2_HEADER_VERSION_UNIT (0x0B) | 80 | #define MPI2_HEADER_VERSION_UNIT (0x0C) |
74 | #define MPI2_HEADER_VERSION_DEV (0x00) | 81 | #define MPI2_HEADER_VERSION_DEV (0x00) |
75 | #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) | 82 | #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) |
76 | #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) | 83 | #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) |
@@ -257,7 +264,7 @@ typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS | |||
257 | typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR | 264 | typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR |
258 | { | 265 | { |
259 | U8 RequestFlags; /* 0x00 */ | 266 | U8 RequestFlags; /* 0x00 */ |
260 | U8 VF_ID; /* 0x01 */ | 267 | U8 MSIxIndex; /* 0x01 */ |
261 | U16 SMID; /* 0x02 */ | 268 | U16 SMID; /* 0x02 */ |
262 | U16 LMID; /* 0x04 */ | 269 | U16 LMID; /* 0x04 */ |
263 | U16 DescriptorTypeDependent; /* 0x06 */ | 270 | U16 DescriptorTypeDependent; /* 0x06 */ |
@@ -271,6 +278,7 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR | |||
271 | #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) | 278 | #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) |
272 | #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) | 279 | #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) |
273 | #define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08) | 280 | #define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08) |
281 | #define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A) | ||
274 | 282 | ||
275 | #define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01) | 283 | #define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01) |
276 | 284 | ||
@@ -279,7 +287,7 @@ typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR | |||
279 | typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR | 287 | typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR |
280 | { | 288 | { |
281 | U8 RequestFlags; /* 0x00 */ | 289 | U8 RequestFlags; /* 0x00 */ |
282 | U8 VF_ID; /* 0x01 */ | 290 | U8 MSIxIndex; /* 0x01 */ |
283 | U16 SMID; /* 0x02 */ | 291 | U16 SMID; /* 0x02 */ |
284 | U16 LMID; /* 0x04 */ | 292 | U16 LMID; /* 0x04 */ |
285 | U16 Reserved1; /* 0x06 */ | 293 | U16 Reserved1; /* 0x06 */ |
@@ -293,7 +301,7 @@ typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR | |||
293 | typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR | 301 | typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR |
294 | { | 302 | { |
295 | U8 RequestFlags; /* 0x00 */ | 303 | U8 RequestFlags; /* 0x00 */ |
296 | U8 VF_ID; /* 0x01 */ | 304 | U8 MSIxIndex; /* 0x01 */ |
297 | U16 SMID; /* 0x02 */ | 305 | U16 SMID; /* 0x02 */ |
298 | U16 LMID; /* 0x04 */ | 306 | U16 LMID; /* 0x04 */ |
299 | U16 DevHandle; /* 0x06 */ | 307 | U16 DevHandle; /* 0x06 */ |
@@ -306,7 +314,7 @@ typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR | |||
306 | typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR | 314 | typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR |
307 | { | 315 | { |
308 | U8 RequestFlags; /* 0x00 */ | 316 | U8 RequestFlags; /* 0x00 */ |
309 | U8 VF_ID; /* 0x01 */ | 317 | U8 MSIxIndex; /* 0x01 */ |
310 | U16 SMID; /* 0x02 */ | 318 | U16 SMID; /* 0x02 */ |
311 | U16 LMID; /* 0x04 */ | 319 | U16 LMID; /* 0x04 */ |
312 | U16 IoIndex; /* 0x06 */ | 320 | U16 IoIndex; /* 0x06 */ |
@@ -315,14 +323,29 @@ typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR | |||
315 | Mpi2SCSITargetRequestDescriptor_t, | 323 | Mpi2SCSITargetRequestDescriptor_t, |
316 | MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t; | 324 | MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t; |
317 | 325 | ||
326 | |||
327 | /* RAID Accelerator Request Descriptor */ | ||
328 | typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR { | ||
329 | U8 RequestFlags; /* 0x00 */ | ||
330 | U8 MSIxIndex; /* 0x01 */ | ||
331 | U16 SMID; /* 0x02 */ | ||
332 | U16 LMID; /* 0x04 */ | ||
333 | U16 Reserved; /* 0x06 */ | ||
334 | } MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, | ||
335 | MPI2_POINTER PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, | ||
336 | Mpi2RAIDAcceleratorRequestDescriptor_t, | ||
337 | MPI2_POINTER pMpi2RAIDAcceleratorRequestDescriptor_t; | ||
338 | |||
339 | |||
318 | /* union of Request Descriptors */ | 340 | /* union of Request Descriptors */ |
319 | typedef union _MPI2_REQUEST_DESCRIPTOR_UNION | 341 | typedef union _MPI2_REQUEST_DESCRIPTOR_UNION |
320 | { | 342 | { |
321 | MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; | 343 | MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; |
322 | MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; | 344 | MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; |
323 | MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; | 345 | MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; |
324 | MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; | 346 | MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; |
325 | U64 Words; | 347 | MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator; |
348 | U64 Words; | ||
326 | } MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION, | 349 | } MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION, |
327 | Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t; | 350 | Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t; |
328 | 351 | ||
@@ -333,19 +356,20 @@ typedef union _MPI2_REQUEST_DESCRIPTOR_UNION | |||
333 | typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR | 356 | typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR |
334 | { | 357 | { |
335 | U8 ReplyFlags; /* 0x00 */ | 358 | U8 ReplyFlags; /* 0x00 */ |
336 | U8 VF_ID; /* 0x01 */ | 359 | U8 MSIxIndex; /* 0x01 */ |
337 | U16 DescriptorTypeDependent1; /* 0x02 */ | 360 | U16 DescriptorTypeDependent1; /* 0x02 */ |
338 | U32 DescriptorTypeDependent2; /* 0x04 */ | 361 | U32 DescriptorTypeDependent2; /* 0x04 */ |
339 | } MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR, | 362 | } MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR, |
340 | Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t; | 363 | Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t; |
341 | 364 | ||
342 | /* defines for the ReplyFlags field */ | 365 | /* defines for the ReplyFlags field */ |
343 | #define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) | 366 | #define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) |
344 | #define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) | 367 | #define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) |
345 | #define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01) | 368 | #define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01) |
346 | #define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02) | 369 | #define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02) |
347 | #define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03) | 370 | #define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03) |
348 | #define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) | 371 | #define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05) |
372 | #define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) | ||
349 | 373 | ||
350 | /* values for marking a reply descriptor as unused */ | 374 | /* values for marking a reply descriptor as unused */ |
351 | #define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF) | 375 | #define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF) |
@@ -355,7 +379,7 @@ typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR | |||
355 | typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR | 379 | typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR |
356 | { | 380 | { |
357 | U8 ReplyFlags; /* 0x00 */ | 381 | U8 ReplyFlags; /* 0x00 */ |
358 | U8 VF_ID; /* 0x01 */ | 382 | U8 MSIxIndex; /* 0x01 */ |
359 | U16 SMID; /* 0x02 */ | 383 | U16 SMID; /* 0x02 */ |
360 | U32 ReplyFrameAddress; /* 0x04 */ | 384 | U32 ReplyFrameAddress; /* 0x04 */ |
361 | } MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR, | 385 | } MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR, |
@@ -368,10 +392,10 @@ typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR | |||
368 | typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR | 392 | typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR |
369 | { | 393 | { |
370 | U8 ReplyFlags; /* 0x00 */ | 394 | U8 ReplyFlags; /* 0x00 */ |
371 | U8 VF_ID; /* 0x01 */ | 395 | U8 MSIxIndex; /* 0x01 */ |
372 | U16 SMID; /* 0x02 */ | 396 | U16 SMID; /* 0x02 */ |
373 | U16 TaskTag; /* 0x04 */ | 397 | U16 TaskTag; /* 0x04 */ |
374 | U16 DevHandle; /* 0x06 */ | 398 | U16 Reserved1; /* 0x06 */ |
375 | } MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, | 399 | } MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, |
376 | MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, | 400 | MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, |
377 | Mpi2SCSIIOSuccessReplyDescriptor_t, | 401 | Mpi2SCSIIOSuccessReplyDescriptor_t, |
@@ -382,7 +406,7 @@ typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR | |||
382 | typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR | 406 | typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR |
383 | { | 407 | { |
384 | U8 ReplyFlags; /* 0x00 */ | 408 | U8 ReplyFlags; /* 0x00 */ |
385 | U8 VF_ID; /* 0x01 */ | 409 | U8 MSIxIndex; /* 0x01 */ |
386 | U16 SMID; /* 0x02 */ | 410 | U16 SMID; /* 0x02 */ |
387 | U8 SequenceNumber; /* 0x04 */ | 411 | U8 SequenceNumber; /* 0x04 */ |
388 | U8 Reserved1; /* 0x05 */ | 412 | U8 Reserved1; /* 0x05 */ |
@@ -397,7 +421,7 @@ typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR | |||
397 | typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR | 421 | typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR |
398 | { | 422 | { |
399 | U8 ReplyFlags; /* 0x00 */ | 423 | U8 ReplyFlags; /* 0x00 */ |
400 | U8 VF_ID; /* 0x01 */ | 424 | U8 MSIxIndex; /* 0x01 */ |
401 | U8 VP_ID; /* 0x02 */ | 425 | U8 VP_ID; /* 0x02 */ |
402 | U8 Flags; /* 0x03 */ | 426 | U8 Flags; /* 0x03 */ |
403 | U16 InitiatorDevHandle; /* 0x04 */ | 427 | U16 InitiatorDevHandle; /* 0x04 */ |
@@ -411,15 +435,28 @@ typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR | |||
411 | #define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F) | 435 | #define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F) |
412 | 436 | ||
413 | 437 | ||
438 | /* RAID Accelerator Success Reply Descriptor */ | ||
439 | typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR { | ||
440 | U8 ReplyFlags; /* 0x00 */ | ||
441 | U8 MSIxIndex; /* 0x01 */ | ||
442 | U16 SMID; /* 0x02 */ | ||
443 | U32 Reserved; /* 0x04 */ | ||
444 | } MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, | ||
445 | MPI2_POINTER PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, | ||
446 | Mpi2RAIDAcceleratorSuccessReplyDescriptor_t, | ||
447 | MPI2_POINTER pMpi2RAIDAcceleratorSuccessReplyDescriptor_t; | ||
448 | |||
449 | |||
414 | /* union of Reply Descriptors */ | 450 | /* union of Reply Descriptors */ |
415 | typedef union _MPI2_REPLY_DESCRIPTORS_UNION | 451 | typedef union _MPI2_REPLY_DESCRIPTORS_UNION |
416 | { | 452 | { |
417 | MPI2_DEFAULT_REPLY_DESCRIPTOR Default; | 453 | MPI2_DEFAULT_REPLY_DESCRIPTOR Default; |
418 | MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; | 454 | MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; |
419 | MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; | 455 | MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; |
420 | MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; | 456 | MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; |
421 | MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; | 457 | MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; |
422 | U64 Words; | 458 | MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess; |
459 | U64 Words; | ||
423 | } MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION, | 460 | } MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION, |
424 | Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t; | 461 | Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t; |
425 | 462 | ||
@@ -458,6 +495,7 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION | |||
458 | #define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */ | 495 | #define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */ |
459 | #define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */ | 496 | #define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */ |
460 | #define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */ | 497 | #define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */ |
498 | #define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) /* RAID Accelerator*/ | ||
461 | 499 | ||
462 | 500 | ||
463 | 501 | ||
@@ -555,12 +593,17 @@ typedef union _MPI2_REPLY_DESCRIPTORS_UNION | |||
555 | 593 | ||
556 | #define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) | 594 | #define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) |
557 | 595 | ||
596 | /**************************************************************************** | ||
597 | * RAID Accelerator values | ||
598 | ****************************************************************************/ | ||
599 | |||
600 | #define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0) | ||
558 | 601 | ||
559 | /**************************************************************************** | 602 | /**************************************************************************** |
560 | * IOCStatus flag to indicate that log info is available | 603 | * IOCStatus flag to indicate that log info is available |
561 | ****************************************************************************/ | 604 | ****************************************************************************/ |
562 | 605 | ||
563 | #define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) | 606 | #define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) |
564 | 607 | ||
565 | /**************************************************************************** | 608 | /**************************************************************************** |
566 | * IOCLogInfo Types | 609 | * IOCLogInfo Types |
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h index 2f27cf6d6c65..ab47c4679640 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Title: MPI Configuration messages and pages | 6 | * Title: MPI Configuration messages and pages |
7 | * Creation Date: November 10, 2006 | 7 | * Creation Date: November 10, 2006 |
8 | * | 8 | * |
9 | * mpi2_cnfg.h Version: 02.00.10 | 9 | * mpi2_cnfg.h Version: 02.00.11 |
10 | * | 10 | * |
11 | * Version History | 11 | * Version History |
12 | * --------------- | 12 | * --------------- |
@@ -95,6 +95,11 @@ | |||
95 | * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. | 95 | * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. |
96 | * Added PortGroups, DmaGroup, and ControlGroup fields to | 96 | * Added PortGroups, DmaGroup, and ControlGroup fields to |
97 | * SAS Device Page 0. | 97 | * SAS Device Page 0. |
98 | * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO | ||
99 | * Unit Page 6. | ||
100 | * Added expander reduced functionality data to SAS | ||
101 | * Expander Page 0. | ||
102 | * Added SAS PHY Page 2 and SAS PHY Page 3. | ||
98 | * -------------------------------------------------------------------------- | 103 | * -------------------------------------------------------------------------- |
99 | */ | 104 | */ |
100 | 105 | ||
@@ -723,6 +728,65 @@ typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 | |||
723 | #define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001) | 728 | #define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001) |
724 | 729 | ||
725 | 730 | ||
731 | /* IO Unit Page 5 */ | ||
732 | |||
733 | /* | ||
734 | * Upper layer code (drivers, utilities, etc.) should leave this define set to | ||
735 | * one and check Header.PageLength or NumDmaEngines at runtime. | ||
736 | */ | ||
737 | #ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES | ||
738 | #define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1) | ||
739 | #endif | ||
740 | |||
741 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 { | ||
742 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
743 | U64 RaidAcceleratorBufferBaseAddress; /* 0x04 */ | ||
744 | U64 RaidAcceleratorBufferSize; /* 0x0C */ | ||
745 | U64 RaidAcceleratorControlBaseAddress; /* 0x14 */ | ||
746 | U8 RAControlSize; /* 0x1C */ | ||
747 | U8 NumDmaEngines; /* 0x1D */ | ||
748 | U8 RAMinControlSize; /* 0x1E */ | ||
749 | U8 RAMaxControlSize; /* 0x1F */ | ||
750 | U32 Reserved1; /* 0x20 */ | ||
751 | U32 Reserved2; /* 0x24 */ | ||
752 | U32 Reserved3; /* 0x28 */ | ||
753 | U32 DmaEngineCapabilities | ||
754 | [MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /* 0x2C */ | ||
755 | } MPI2_CONFIG_PAGE_IO_UNIT_5, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_5, | ||
756 | Mpi2IOUnitPage5_t, MPI2_POINTER pMpi2IOUnitPage5_t; | ||
757 | |||
758 | #define MPI2_IOUNITPAGE5_PAGEVERSION (0x00) | ||
759 | |||
760 | /* defines for IO Unit Page 5 DmaEngineCapabilities field */ | ||
761 | #define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS (0xFF00) | ||
762 | #define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS (16) | ||
763 | |||
764 | #define MPI2_IOUNITPAGE5_DMA_CAP_EEDP (0x0008) | ||
765 | #define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION (0x0004) | ||
766 | #define MPI2_IOUNITPAGE5_DMA_CAP_HASHING (0x0002) | ||
767 | #define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION (0x0001) | ||
768 | |||
769 | |||
770 | /* IO Unit Page 6 */ | ||
771 | |||
772 | typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 { | ||
773 | MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */ | ||
774 | U16 Flags; /* 0x04 */ | ||
775 | U8 RAHostControlSize; /* 0x06 */ | ||
776 | U8 Reserved0; /* 0x07 */ | ||
777 | U64 RaidAcceleratorHostControlBaseAddress; /* 0x08 */ | ||
778 | U32 Reserved1; /* 0x10 */ | ||
779 | U32 Reserved2; /* 0x14 */ | ||
780 | U32 Reserved3; /* 0x18 */ | ||
781 | } MPI2_CONFIG_PAGE_IO_UNIT_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_6, | ||
782 | Mpi2IOUnitPage6_t, MPI2_POINTER pMpi2IOUnitPage6_t; | ||
783 | |||
784 | #define MPI2_IOUNITPAGE6_PAGEVERSION (0x00) | ||
785 | |||
786 | /* defines for IO Unit Page 6 Flags field */ | ||
787 | #define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR (0x0001) | ||
788 | |||
789 | |||
726 | /**************************************************************************** | 790 | /**************************************************************************** |
727 | * IOC Config Pages | 791 | * IOC Config Pages |
728 | ****************************************************************************/ | 792 | ****************************************************************************/ |
@@ -1709,10 +1773,14 @@ typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 | |||
1709 | U64 ActiveZoneManagerSASAddress;/* 0x2C */ | 1773 | U64 ActiveZoneManagerSASAddress;/* 0x2C */ |
1710 | U16 ZoneLockInactivityLimit; /* 0x34 */ | 1774 | U16 ZoneLockInactivityLimit; /* 0x34 */ |
1711 | U16 Reserved1; /* 0x36 */ | 1775 | U16 Reserved1; /* 0x36 */ |
1776 | U8 TimeToReducedFunc; /* 0x38 */ | ||
1777 | U8 InitialTimeToReducedFunc; /* 0x39 */ | ||
1778 | U8 MaxReducedFuncTime; /* 0x3A */ | ||
1779 | U8 Reserved2; /* 0x3B */ | ||
1712 | } MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0, | 1780 | } MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0, |
1713 | Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t; | 1781 | Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t; |
1714 | 1782 | ||
1715 | #define MPI2_SASEXPANDER0_PAGEVERSION (0x05) | 1783 | #define MPI2_SASEXPANDER0_PAGEVERSION (0x06) |
1716 | 1784 | ||
1717 | /* values for SAS Expander Page 0 DiscoveryStatus field */ | 1785 | /* values for SAS Expander Page 0 DiscoveryStatus field */ |
1718 | #define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) | 1786 | #define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) |
@@ -1737,6 +1805,7 @@ typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 | |||
1737 | #define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) | 1805 | #define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) |
1738 | 1806 | ||
1739 | /* values for SAS Expander Page 0 Flags field */ | 1807 | /* values for SAS Expander Page 0 Flags field */ |
1808 | #define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000) | ||
1740 | #define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000) | 1809 | #define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000) |
1741 | #define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) | 1810 | #define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) |
1742 | #define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) | 1811 | #define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) |
@@ -1944,6 +2013,133 @@ typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 | |||
1944 | #define MPI2_SASPHY1_PAGEVERSION (0x01) | 2013 | #define MPI2_SASPHY1_PAGEVERSION (0x01) |
1945 | 2014 | ||
1946 | 2015 | ||
2016 | /* SAS PHY Page 2 */ | ||
2017 | |||
2018 | typedef struct _MPI2_SASPHY2_PHY_EVENT { | ||
2019 | U8 PhyEventCode; /* 0x00 */ | ||
2020 | U8 Reserved1; /* 0x01 */ | ||
2021 | U16 Reserved2; /* 0x02 */ | ||
2022 | U32 PhyEventInfo; /* 0x04 */ | ||
2023 | } MPI2_SASPHY2_PHY_EVENT, MPI2_POINTER PTR_MPI2_SASPHY2_PHY_EVENT, | ||
2024 | Mpi2SasPhy2PhyEvent_t, MPI2_POINTER pMpi2SasPhy2PhyEvent_t; | ||
2025 | |||
2026 | /* use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */ | ||
2027 | |||
2028 | |||
2029 | /* | ||
2030 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
2031 | * one and check Header.ExtPageLength or NumPhyEvents at runtime. | ||
2032 | */ | ||
2033 | #ifndef MPI2_SASPHY2_PHY_EVENT_MAX | ||
2034 | #define MPI2_SASPHY2_PHY_EVENT_MAX (1) | ||
2035 | #endif | ||
2036 | |||
2037 | typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 { | ||
2038 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
2039 | U32 Reserved1; /* 0x08 */ | ||
2040 | U8 NumPhyEvents; /* 0x0C */ | ||
2041 | U8 Reserved2; /* 0x0D */ | ||
2042 | U16 Reserved3; /* 0x0E */ | ||
2043 | MPI2_SASPHY2_PHY_EVENT PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; | ||
2044 | /* 0x10 */ | ||
2045 | } MPI2_CONFIG_PAGE_SAS_PHY_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_2, | ||
2046 | Mpi2SasPhyPage2_t, MPI2_POINTER pMpi2SasPhyPage2_t; | ||
2047 | |||
2048 | #define MPI2_SASPHY2_PAGEVERSION (0x00) | ||
2049 | |||
2050 | |||
2051 | /* SAS PHY Page 3 */ | ||
2052 | |||
2053 | typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG { | ||
2054 | U8 PhyEventCode; /* 0x00 */ | ||
2055 | U8 Reserved1; /* 0x01 */ | ||
2056 | U16 Reserved2; /* 0x02 */ | ||
2057 | U8 CounterType; /* 0x04 */ | ||
2058 | U8 ThresholdWindow; /* 0x05 */ | ||
2059 | U8 TimeUnits; /* 0x06 */ | ||
2060 | U8 Reserved3; /* 0x07 */ | ||
2061 | U32 EventThreshold; /* 0x08 */ | ||
2062 | U16 ThresholdFlags; /* 0x0C */ | ||
2063 | U16 Reserved4; /* 0x0E */ | ||
2064 | } MPI2_SASPHY3_PHY_EVENT_CONFIG, MPI2_POINTER PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG, | ||
2065 | Mpi2SasPhy3PhyEventConfig_t, MPI2_POINTER pMpi2SasPhy3PhyEventConfig_t; | ||
2066 | |||
2067 | /* values for PhyEventCode field */ | ||
2068 | #define MPI2_SASPHY3_EVENT_CODE_NO_EVENT (0x00) | ||
2069 | #define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01) | ||
2070 | #define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02) | ||
2071 | #define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03) | ||
2072 | #define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04) | ||
2073 | #define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05) | ||
2074 | #define MPI2_SASPHY3_EVENT_CODE_RX_ERROR (0x06) | ||
2075 | #define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20) | ||
2076 | #define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21) | ||
2077 | #define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22) | ||
2078 | #define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23) | ||
2079 | #define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24) | ||
2080 | #define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25) | ||
2081 | #define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26) | ||
2082 | #define MPI2_SASPHY3_EVENT_CODE_TX_BREAK (0x27) | ||
2083 | #define MPI2_SASPHY3_EVENT_CODE_RX_BREAK (0x28) | ||
2084 | #define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29) | ||
2085 | #define MPI2_SASPHY3_EVENT_CODE_CONNECTION (0x2A) | ||
2086 | #define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B) | ||
2087 | #define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C) | ||
2088 | #define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D) | ||
2089 | #define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E) | ||
2090 | #define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40) | ||
2091 | #define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41) | ||
2092 | #define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42) | ||
2093 | #define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43) | ||
2094 | #define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44) | ||
2095 | #define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45) | ||
2096 | #define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50) | ||
2097 | #define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51) | ||
2098 | #define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52) | ||
2099 | #define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60) | ||
2100 | #define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61) | ||
2101 | #define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63) | ||
2102 | #define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0) | ||
2103 | #define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) | ||
2104 | #define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2) | ||
2105 | |||
2106 | /* values for the CounterType field */ | ||
2107 | #define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) | ||
2108 | #define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01) | ||
2109 | #define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02) | ||
2110 | |||
2111 | /* values for the TimeUnits field */ | ||
2112 | #define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00) | ||
2113 | #define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01) | ||
2114 | #define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02) | ||
2115 | #define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03) | ||
2116 | |||
2117 | /* values for the ThresholdFlags field */ | ||
2118 | #define MPI2_SASPHY3_TFLAGS_PHY_RESET (0x0002) | ||
2119 | #define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001) | ||
2120 | |||
2121 | /* | ||
2122 | * Host code (drivers, BIOS, utilities, etc.) should leave this define set to | ||
2123 | * one and check Header.ExtPageLength or NumPhyEvents at runtime. | ||
2124 | */ | ||
2125 | #ifndef MPI2_SASPHY3_PHY_EVENT_MAX | ||
2126 | #define MPI2_SASPHY3_PHY_EVENT_MAX (1) | ||
2127 | #endif | ||
2128 | |||
2129 | typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 { | ||
2130 | MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */ | ||
2131 | U32 Reserved1; /* 0x08 */ | ||
2132 | U8 NumPhyEvents; /* 0x0C */ | ||
2133 | U8 Reserved2; /* 0x0D */ | ||
2134 | U16 Reserved3; /* 0x0E */ | ||
2135 | MPI2_SASPHY3_PHY_EVENT_CONFIG PhyEventConfig | ||
2136 | [MPI2_SASPHY3_PHY_EVENT_MAX]; /* 0x10 */ | ||
2137 | } MPI2_CONFIG_PAGE_SAS_PHY_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_3, | ||
2138 | Mpi2SasPhyPage3_t, MPI2_POINTER pMpi2SasPhyPage3_t; | ||
2139 | |||
2140 | #define MPI2_SASPHY3_PAGEVERSION (0x00) | ||
2141 | |||
2142 | |||
1947 | /**************************************************************************** | 2143 | /**************************************************************************** |
1948 | * SAS Port Config Pages | 2144 | * SAS Port Config Pages |
1949 | ****************************************************************************/ | 2145 | ****************************************************************************/ |
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_history.txt b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt new file mode 100644 index 000000000000..65fcaa31cb30 --- /dev/null +++ b/drivers/scsi/mpt2sas/mpi/mpi2_history.txt | |||
@@ -0,0 +1,334 @@ | |||
1 | ============================== | ||
2 | Fusion-MPT MPI 2.0 Header File Change History | ||
3 | ============================== | ||
4 | |||
5 | Copyright (c) 2000-2009 LSI Corporation. | ||
6 | |||
7 | --------------------------------------- | ||
8 | Header Set Release Version: 02.00.12 | ||
9 | Header Set Release Date: 05-06-09 | ||
10 | --------------------------------------- | ||
11 | |||
12 | Filename Current version Prior version | ||
13 | ---------- --------------- ------------- | ||
14 | mpi2.h 02.00.12 02.00.11 | ||
15 | mpi2_cnfg.h 02.00.11 02.00.10 | ||
16 | mpi2_init.h 02.00.07 02.00.06 | ||
17 | mpi2_ioc.h 02.00.11 02.00.10 | ||
18 | mpi2_raid.h 02.00.03 02.00.03 | ||
19 | mpi2_sas.h 02.00.02 02.00.02 | ||
20 | mpi2_targ.h 02.00.03 02.00.03 | ||
21 | mpi2_tool.h 02.00.03 02.00.02 | ||
22 | mpi2_type.h 02.00.00 02.00.00 | ||
23 | mpi2_ra.h 02.00.00 | ||
24 | mpi2_history.txt 02.00.11 02.00.12 | ||
25 | |||
26 | |||
27 | * Date Version Description | ||
28 | * -------- -------- ------------------------------------------------------ | ||
29 | |||
30 | mpi2.h | ||
31 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
32 | * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT. | ||
33 | * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT. | ||
34 | * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT. | ||
35 | * Moved ReplyPostHostIndex register to offset 0x6C of the | ||
36 | * MPI2_SYSTEM_INTERFACE_REGS and modified the define for | ||
37 | * MPI2_REPLY_POST_HOST_INDEX_OFFSET. | ||
38 | * Added union of request descriptors. | ||
39 | * Added union of reply descriptors. | ||
40 | * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT. | ||
41 | * Added define for MPI2_VERSION_02_00. | ||
42 | * Fixed the size of the FunctionDependent5 field in the | ||
43 | * MPI2_DEFAULT_REPLY structure. | ||
44 | * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT. | ||
45 | * Removed the MPI-defined Fault Codes and extended the | ||
46 | * product specific codes up to 0xEFFF. | ||
47 | * Added a sixth key value for the WriteSequence register | ||
48 | * and changed the flush value to 0x0. | ||
49 | * Added message function codes for Diagnostic Buffer Post | ||
50 | * and Diagnsotic Release. | ||
51 | * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED | ||
52 | * Moved MPI2_VERSION_UNION from mpi2_ioc.h. | ||
53 | * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT. | ||
54 | * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT. | ||
55 | * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT. | ||
56 | * Added #defines for marking a reply descriptor as unused. | ||
57 | * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT. | ||
58 | * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. | ||
59 | * Moved LUN field defines from mpi2_init.h. | ||
60 | * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. | ||
61 | * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT. | ||
62 | * In all request and reply descriptors, replaced VF_ID | ||
63 | * field with MSIxIndex field. | ||
64 | * Removed DevHandle field from | ||
65 | * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those | ||
66 | * bytes reserved. | ||
67 | * Added RAID Accelerator functionality. | ||
68 | * -------------------------------------------------------------------------- | ||
69 | |||
70 | mpi2_cnfg.h | ||
71 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
72 | * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags. | ||
73 | * Added Manufacturing Page 11. | ||
74 | * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE | ||
75 | * define. | ||
76 | * 06-26-07 02.00.02 Adding generic structure for product-specific | ||
77 | * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS. | ||
78 | * Rework of BIOS Page 2 configuration page. | ||
79 | * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the | ||
80 | * forms. | ||
81 | * Added configuration pages IOC Page 8 and Driver | ||
82 | * Persistent Mapping Page 0. | ||
83 | * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated | ||
84 | * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1, | ||
85 | * RAID Physical Disk Pages 0 and 1, RAID Configuration | ||
86 | * Page 0). | ||
87 | * Added new value for AccessStatus field of SAS Device | ||
88 | * Page 0 (_SATA_NEEDS_INITIALIZATION). | ||
89 | * 10-31-07 02.00.04 Added missing SEPDevHandle field to | ||
90 | * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. | ||
91 | * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for | ||
92 | * NVDATA. | ||
93 | * Modified IOC Page 7 to use masks and added field for | ||
94 | * SASBroadcastPrimitiveMasks. | ||
95 | * Added MPI2_CONFIG_PAGE_BIOS_4. | ||
96 | * Added MPI2_CONFIG_PAGE_LOG_0. | ||
97 | * 02-29-08 02.00.06 Modified various names to make them 32-character unique. | ||
98 | * Added SAS Device IDs. | ||
99 | * Updated Integrated RAID configuration pages including | ||
100 | * Manufacturing Page 4, IOC Page 6, and RAID Configuration | ||
101 | * Page 0. | ||
102 | * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA. | ||
103 | * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION. | ||
104 | * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING. | ||
105 | * Added missing MaxNumRoutedSasAddresses field to | ||
106 | * MPI2_CONFIG_PAGE_EXPANDER_0. | ||
107 | * Added SAS Port Page 0. | ||
108 | * Modified structure layout for | ||
109 | * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0. | ||
110 | * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use | ||
111 | * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array. | ||
112 | * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF | ||
113 | * to 0x000000FF. | ||
114 | * Added two new values for the Physical Disk Coercion Size | ||
115 | * bits in the Flags field of Manufacturing Page 4. | ||
116 | * Added product-specific Manufacturing pages 16 to 31. | ||
117 | * Modified Flags bits for controlling write cache on SATA | ||
118 | * drives in IO Unit Page 1. | ||
119 | * Added new bit to AdditionalControlFlags of SAS IO Unit | ||
120 | * Page 1 to control Invalid Topology Correction. | ||
121 | * Added SupportedPhysDisks field to RAID Volume Page 1 and | ||
122 | * added related defines. | ||
123 | * Added additional defines for RAID Volume Page 0 | ||
124 | * VolumeStatusFlags field. | ||
125 | * Modified meaning of RAID Volume Page 0 VolumeSettings | ||
126 | * define for auto-configure of hot-swap drives. | ||
127 | * Added PhysDiskAttributes field (and related defines) to | ||
128 | * RAID Physical Disk Page 0. | ||
129 | * Added MPI2_SAS_PHYINFO_PHY_VACANT define. | ||
130 | * Added three new DiscoveryStatus bits for SAS IO Unit | ||
131 | * Page 0 and SAS Expander Page 0. | ||
132 | * Removed multiplexing information from SAS IO Unit pages. | ||
133 | * Added BootDeviceWaitTime field to SAS IO Unit Page 4. | ||
134 | * Removed Zone Address Resolved bit from PhyInfo and from | ||
135 | * Expander Page 0 Flags field. | ||
136 | * Added two new AccessStatus values to SAS Device Page 0 | ||
137 | * for indicating routing problems. Added 3 reserved words | ||
138 | * to this page. | ||
139 | * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3. | ||
140 | * Inserted missing reserved field into structure for IOC | ||
141 | * Page 6. | ||
142 | * Added more pending task bits to RAID Volume Page 0 | ||
143 | * VolumeStatusFlags defines. | ||
144 | * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define. | ||
145 | * Added a new DiscoveryStatus bit for SAS IO Unit Page 0 | ||
146 | * and SAS Expander Page 0 to flag a downstream initiator | ||
147 | * when in simplified routing mode. | ||
148 | * Removed SATA Init Failure defines for DiscoveryStatus | ||
149 | * fields of SAS IO Unit Page 0 and SAS Expander Page 0. | ||
150 | * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. | ||
151 | * Added PortGroups, DmaGroup, and ControlGroup fields to | ||
152 | * SAS Device Page 0. | ||
153 | * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO | ||
154 | * Unit Page 6. | ||
155 | * Added expander reduced functionality data to SAS | ||
156 | * Expander Page 0. | ||
157 | * Added SAS PHY Page 2 and SAS PHY Page 3. | ||
158 | * -------------------------------------------------------------------------- | ||
159 | |||
160 | mpi2_init.h | ||
161 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
162 | * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t. | ||
163 | * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines. | ||
164 | * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention. | ||
165 | * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY. | ||
166 | * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. | ||
167 | * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO | ||
168 | * Control field Task Attribute flags. | ||
169 | * Moved LUN field defines to mpi2.h becasue they are | ||
170 | * common to many structures. | ||
171 | * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to | ||
172 | * Query Asynchronous Event. | ||
173 | * Defined two new bits in the SlotStatus field of the SCSI | ||
174 | * Enclosure Processor Request and Reply. | ||
175 | * -------------------------------------------------------------------------- | ||
176 | |||
177 | mpi2_ioc.h | ||
178 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
179 | * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to | ||
180 | * MaxTargets. | ||
181 | * Added TotalImageSize field to FWDownload Request. | ||
182 | * Added reserved words to FWUpload Request. | ||
183 | * 06-26-07 02.00.02 Added IR Configuration Change List Event. | ||
184 | * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit | ||
185 | * request and replaced it with | ||
186 | * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. | ||
187 | * Replaced the MinReplyQueueDepth field of the IOCFacts | ||
188 | * reply with MaxReplyDescriptorPostQueueDepth. | ||
189 | * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum | ||
190 | * depth for the Reply Descriptor Post Queue. | ||
191 | * Added SASAddress field to Initiator Device Table | ||
192 | * Overflow Event data. | ||
193 | * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING | ||
194 | * for SAS Initiator Device Status Change Event data. | ||
195 | * Modified Reason Code defines for SAS Topology Change | ||
196 | * List Event data, including adding a bit for PHY Vacant | ||
197 | * status, and adding a mask for the Reason Code. | ||
198 | * Added define for | ||
199 | * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. | ||
200 | * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. | ||
201 | * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of | ||
202 | * the IOCFacts Reply. | ||
203 | * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. | ||
204 | * Moved MPI2_VERSION_UNION to mpi2.h. | ||
205 | * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks | ||
206 | * instead of enables, and added SASBroadcastPrimitiveMasks | ||
207 | * field. | ||
208 | * Added Log Entry Added Event and related structure. | ||
209 | * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. | ||
210 | * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. | ||
211 | * Added MaxVolumes and MaxPersistentEntries fields to | ||
212 | * IOCFacts reply. | ||
213 | * Added ProtocalFlags and IOCCapabilities fields to | ||
214 | * MPI2_FW_IMAGE_HEADER. | ||
215 | * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. | ||
216 | * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to | ||
217 | * a U16 (from a U32). | ||
218 | * Removed extra 's' from EventMasks name. | ||
219 | * 06-27-08 02.00.08 Fixed an offset in a comment. | ||
220 | * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. | ||
221 | * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and | ||
222 | * renamed MinReplyFrameSize to ReplyFrameSize. | ||
223 | * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. | ||
224 | * Added two new RAIDOperation values for Integrated RAID | ||
225 | * Operations Status Event data. | ||
226 | * Added four new IR Configuration Change List Event data | ||
227 | * ReasonCode values. | ||
228 | * Added two new ReasonCode defines for SAS Device Status | ||
229 | * Change Event data. | ||
230 | * Added three new DiscoveryStatus bits for the SAS | ||
231 | * Discovery event data. | ||
232 | * Added Multiplexing Status Change bit to the PhyStatus | ||
233 | * field of the SAS Topology Change List event data. | ||
234 | * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. | ||
235 | * BootFlags are now product-specific. | ||
236 | * Added defines for the indivdual signature bytes | ||
237 | * for MPI2_INIT_IMAGE_FOOTER. | ||
238 | * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. | ||
239 | * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR | ||
240 | * define. | ||
241 | * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE | ||
242 | * define. | ||
243 | * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. | ||
244 | * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. | ||
245 | * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. | ||
246 | * Added two new reason codes for SAS Device Status Change | ||
247 | * Event. | ||
248 | * Added new event: SAS PHY Counter. | ||
249 | * -------------------------------------------------------------------------- | ||
250 | |||
251 | mpi2_raid.h | ||
252 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
253 | * 08-31-07 02.00.01 Modifications to RAID Action request and reply, | ||
254 | * including the Actions and ActionData. | ||
255 | * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD. | ||
256 | * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that | ||
257 | * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT | ||
258 | * can be sized by the build environment. | ||
259 | * -------------------------------------------------------------------------- | ||
260 | |||
261 | mpi2_sas.h | ||
262 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
263 | * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit | ||
264 | * Control Request. | ||
265 | * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control | ||
266 | * Request. | ||
267 | * -------------------------------------------------------------------------- | ||
268 | |||
269 | mpi2_targ.h | ||
270 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
271 | * 08-31-07 02.00.01 Added Command Buffer Data Location Address Space bits to | ||
272 | * BufferPostFlags field of CommandBufferPostBase Request. | ||
273 | * 02-29-08 02.00.02 Modified various names to make them 32-character unique. | ||
274 | * 10-02-08 02.00.03 Removed NextCmdBufferOffset from | ||
275 | * MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST. | ||
276 | * Target Status Send Request only takes a single SGE for | ||
277 | * response data. | ||
278 | * -------------------------------------------------------------------------- | ||
279 | |||
280 | mpi2_tool.h | ||
281 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
282 | * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release | ||
283 | * structures and defines. | ||
284 | * 02-29-08 02.00.02 Modified various names to make them 32-character unique. | ||
285 | * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool. | ||
286 | * -------------------------------------------------------------------------- | ||
287 | |||
288 | mpi2_type.h | ||
289 | * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. | ||
290 | * -------------------------------------------------------------------------- | ||
291 | |||
292 | mpi2_ra.h | ||
293 | * 05-06-09 02.00.00 Initial version. | ||
294 | * -------------------------------------------------------------------------- | ||
295 | |||
296 | mpi2_history.txt Parts list history | ||
297 | |||
298 | Filename 02.00.12 | ||
299 | ---------- -------- | ||
300 | mpi2.h 02.00.12 | ||
301 | mpi2_cnfg.h 02.00.11 | ||
302 | mpi2_init.h 02.00.07 | ||
303 | mpi2_ioc.h 02.00.11 | ||
304 | mpi2_raid.h 02.00.03 | ||
305 | mpi2_sas.h 02.00.02 | ||
306 | mpi2_targ.h 02.00.03 | ||
307 | mpi2_tool.h 02.00.03 | ||
308 | mpi2_type.h 02.00.00 | ||
309 | mpi2_ra.h 02.00.00 | ||
310 | |||
311 | Filename 02.00.11 02.00.10 02.00.09 02.00.08 02.00.07 02.00.06 | ||
312 | ---------- -------- -------- -------- -------- -------- -------- | ||
313 | mpi2.h 02.00.11 02.00.10 02.00.09 02.00.08 02.00.07 02.00.06 | ||
314 | mpi2_cnfg.h 02.00.10 02.00.09 02.00.08 02.00.07 02.00.06 02.00.06 | ||
315 | mpi2_init.h 02.00.06 02.00.06 02.00.05 02.00.05 02.00.04 02.00.03 | ||
316 | mpi2_ioc.h 02.00.10 02.00.09 02.00.08 02.00.07 02.00.07 02.00.06 | ||
317 | mpi2_raid.h 02.00.03 02.00.03 02.00.03 02.00.03 02.00.02 02.00.02 | ||
318 | mpi2_sas.h 02.00.02 02.00.02 02.00.01 02.00.01 02.00.01 02.00.01 | ||
319 | mpi2_targ.h 02.00.03 02.00.03 02.00.02 02.00.02 02.00.02 02.00.02 | ||
320 | mpi2_tool.h 02.00.02 02.00.02 02.00.02 02.00.02 02.00.02 02.00.02 | ||
321 | mpi2_type.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 | ||
322 | |||
323 | Filename 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 | ||
324 | ---------- -------- -------- -------- -------- -------- -------- | ||
325 | mpi2.h 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 | ||
326 | mpi2_cnfg.h 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 | ||
327 | mpi2_init.h 02.00.02 02.00.01 02.00.00 02.00.00 02.00.00 02.00.00 | ||
328 | mpi2_ioc.h 02.00.05 02.00.04 02.00.03 02.00.02 02.00.01 02.00.00 | ||
329 | mpi2_raid.h 02.00.01 02.00.01 02.00.01 02.00.00 02.00.00 02.00.00 | ||
330 | mpi2_sas.h 02.00.01 02.00.01 02.00.01 02.00.01 02.00.00 02.00.00 | ||
331 | mpi2_targ.h 02.00.01 02.00.01 02.00.01 02.00.00 02.00.00 02.00.00 | ||
332 | mpi2_tool.h 02.00.01 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 | ||
333 | mpi2_type.h 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 02.00.00 | ||
334 | |||
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h index f1115f0f0eb2..563e56d2e945 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_init.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h | |||
@@ -1,12 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2008 LSI Corporation. | 2 | * Copyright (c) 2000-2009 LSI Corporation. |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * Name: mpi2_init.h | 5 | * Name: mpi2_init.h |
6 | * Title: MPI SCSI initiator mode messages and structures | 6 | * Title: MPI SCSI initiator mode messages and structures |
7 | * Creation Date: June 23, 2006 | 7 | * Creation Date: June 23, 2006 |
8 | * | 8 | * |
9 | * mpi2_init.h Version: 02.00.06 | 9 | * mpi2_init.h Version: 02.00.07 |
10 | * | 10 | * |
11 | * Version History | 11 | * Version History |
12 | * --------------- | 12 | * --------------- |
@@ -23,6 +23,10 @@ | |||
23 | * Control field Task Attribute flags. | 23 | * Control field Task Attribute flags. |
24 | * Moved LUN field defines to mpi2.h becasue they are | 24 | * Moved LUN field defines to mpi2.h becasue they are |
25 | * common to many structures. | 25 | * common to many structures. |
26 | * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to | ||
27 | * Query Asynchronous Event. | ||
28 | * Defined two new bits in the SlotStatus field of the SCSI | ||
29 | * Enclosure Processor Request and Reply. | ||
26 | * -------------------------------------------------------------------------- | 30 | * -------------------------------------------------------------------------- |
27 | */ | 31 | */ |
28 | 32 | ||
@@ -289,7 +293,11 @@ typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST | |||
289 | #define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) | 293 | #define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) |
290 | #define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) | 294 | #define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) |
291 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09) | 295 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09) |
292 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION (0x0A) | 296 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A) |
297 | |||
298 | /* obsolete TaskType name */ | ||
299 | #define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION \ | ||
300 | (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT) | ||
293 | 301 | ||
294 | /* MsgFlags bits */ | 302 | /* MsgFlags bits */ |
295 | 303 | ||
@@ -375,6 +383,8 @@ typedef struct _MPI2_SEP_REQUEST | |||
375 | #define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) | 383 | #define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) |
376 | #define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) | 384 | #define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) |
377 | #define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) | 385 | #define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) |
386 | #define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) | ||
387 | #define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) | ||
378 | #define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) | 388 | #define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) |
379 | #define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) | 389 | #define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) |
380 | #define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) | 390 | #define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) |
@@ -410,6 +420,8 @@ typedef struct _MPI2_SEP_REPLY | |||
410 | #define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) | 420 | #define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) |
411 | #define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) | 421 | #define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) |
412 | #define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) | 422 | #define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) |
423 | #define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) | ||
424 | #define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) | ||
413 | #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) | 425 | #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) |
414 | #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) | 426 | #define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) |
415 | #define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) | 427 | #define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) |
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h index 8c5d81870c03..c294128bdeb4 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h | |||
@@ -6,7 +6,7 @@ | |||
6 | * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages | 6 | * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages |
7 | * Creation Date: October 11, 2006 | 7 | * Creation Date: October 11, 2006 |
8 | * | 8 | * |
9 | * mpi2_ioc.h Version: 02.00.10 | 9 | * mpi2_ioc.h Version: 02.00.11 |
10 | * | 10 | * |
11 | * Version History | 11 | * Version History |
12 | * --------------- | 12 | * --------------- |
@@ -79,6 +79,11 @@ | |||
79 | * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE | 79 | * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE |
80 | * define. | 80 | * define. |
81 | * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. | 81 | * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. |
82 | * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. | ||
83 | * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. | ||
84 | * Added two new reason codes for SAS Device Status Change | ||
85 | * Event. | ||
86 | * Added new event: SAS PHY Counter. | ||
82 | * -------------------------------------------------------------------------- | 87 | * -------------------------------------------------------------------------- |
83 | */ | 88 | */ |
84 | 89 | ||
@@ -261,6 +266,8 @@ typedef struct _MPI2_IOC_FACTS_REPLY | |||
261 | /* ProductID field uses MPI2_FW_HEADER_PID_ */ | 266 | /* ProductID field uses MPI2_FW_HEADER_PID_ */ |
262 | 267 | ||
263 | /* IOCCapabilities */ | 268 | /* IOCCapabilities */ |
269 | #define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000) | ||
270 | #define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000) | ||
264 | #define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) | 271 | #define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) |
265 | #define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) | 272 | #define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) |
266 | #define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) | 273 | #define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) |
@@ -440,6 +447,7 @@ typedef struct _MPI2_EVENT_NOTIFICATION_REPLY | |||
440 | #define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) | 447 | #define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) |
441 | #define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) | 448 | #define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) |
442 | #define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) | 449 | #define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) |
450 | #define MPI2_EVENT_SAS_PHY_COUNTER (0x0022) | ||
443 | 451 | ||
444 | 452 | ||
445 | /* Log Entry Added Event data */ | 453 | /* Log Entry Added Event data */ |
@@ -502,17 +510,19 @@ typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE | |||
502 | MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t; | 510 | MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t; |
503 | 511 | ||
504 | /* SAS Device Status Change Event data ReasonCode values */ | 512 | /* SAS Device Status Change Event data ReasonCode values */ |
505 | #define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) | 513 | #define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) |
506 | #define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) | 514 | #define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) |
507 | #define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) | 515 | #define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) |
508 | #define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) | 516 | #define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) |
509 | #define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) | 517 | #define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) |
510 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) | 518 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) |
511 | #define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) | 519 | #define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) |
512 | #define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) | 520 | #define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) |
513 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) | 521 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) |
514 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) | 522 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) |
515 | #define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) | 523 | #define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) |
524 | #define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11) | ||
525 | #define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12) | ||
516 | 526 | ||
517 | 527 | ||
518 | /* Integrated RAID Operation Status Event data */ | 528 | /* Integrated RAID Operation Status Event data */ |
@@ -822,6 +832,37 @@ typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE | |||
822 | #define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) | 832 | #define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) |
823 | 833 | ||
824 | 834 | ||
835 | /* SAS PHY Counter Event data */ | ||
836 | |||
837 | typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER { | ||
838 | U64 TimeStamp; /* 0x00 */ | ||
839 | U32 Reserved1; /* 0x08 */ | ||
840 | U8 PhyEventCode; /* 0x0C */ | ||
841 | U8 PhyNum; /* 0x0D */ | ||
842 | U16 Reserved2; /* 0x0E */ | ||
843 | U32 PhyEventInfo; /* 0x10 */ | ||
844 | U8 CounterType; /* 0x14 */ | ||
845 | U8 ThresholdWindow; /* 0x15 */ | ||
846 | U8 TimeUnits; /* 0x16 */ | ||
847 | U8 Reserved3; /* 0x17 */ | ||
848 | U32 EventThreshold; /* 0x18 */ | ||
849 | U16 ThresholdFlags; /* 0x1C */ | ||
850 | U16 Reserved4; /* 0x1E */ | ||
851 | } MPI2_EVENT_DATA_SAS_PHY_COUNTER, | ||
852 | MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER, | ||
853 | Mpi2EventDataSasPhyCounter_t, MPI2_POINTER pMpi2EventDataSasPhyCounter_t; | ||
854 | |||
855 | /* use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h for the | ||
856 | * PhyEventCode field | ||
857 | * use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h for the | ||
858 | * CounterType field | ||
859 | * use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h for the | ||
860 | * TimeUnits field | ||
861 | * use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h for the | ||
862 | * ThresholdFlags field | ||
863 | * */ | ||
864 | |||
865 | |||
825 | /**************************************************************************** | 866 | /**************************************************************************** |
826 | * EventAck message | 867 | * EventAck message |
827 | ****************************************************************************/ | 868 | ****************************************************************************/ |
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h index 2ff4e936bd39..007e950f7bfa 100644 --- a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h +++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h | |||
@@ -1,12 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2008 LSI Corporation. | 2 | * Copyright (c) 2000-2009 LSI Corporation. |
3 | * | 3 | * |
4 | * | 4 | * |
5 | * Name: mpi2_tool.h | 5 | * Name: mpi2_tool.h |
6 | * Title: MPI diagnostic tool structures and definitions | 6 | * Title: MPI diagnostic tool structures and definitions |
7 | * Creation Date: March 26, 2007 | 7 | * Creation Date: March 26, 2007 |
8 | * | 8 | * |
9 | * mpi2_tool.h Version: 02.00.02 | 9 | * mpi2_tool.h Version: 02.00.03 |
10 | * | 10 | * |
11 | * Version History | 11 | * Version History |
12 | * --------------- | 12 | * --------------- |
@@ -17,6 +17,7 @@ | |||
17 | * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release | 17 | * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release |
18 | * structures and defines. | 18 | * structures and defines. |
19 | * 02-29-08 02.00.02 Modified various names to make them 32-character unique. | 19 | * 02-29-08 02.00.02 Modified various names to make them 32-character unique. |
20 | * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool. | ||
20 | * -------------------------------------------------------------------------- | 21 | * -------------------------------------------------------------------------- |
21 | */ | 22 | */ |
22 | 23 | ||
@@ -32,7 +33,10 @@ | |||
32 | /* defines for the Tools */ | 33 | /* defines for the Tools */ |
33 | #define MPI2_TOOLBOX_CLEAN_TOOL (0x00) | 34 | #define MPI2_TOOLBOX_CLEAN_TOOL (0x00) |
34 | #define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) | 35 | #define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) |
36 | #define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) | ||
35 | #define MPI2_TOOLBOX_BEACON_TOOL (0x05) | 37 | #define MPI2_TOOLBOX_BEACON_TOOL (0x05) |
38 | #define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06) | ||
39 | |||
36 | 40 | ||
37 | /**************************************************************************** | 41 | /**************************************************************************** |
38 | * Toolbox reply | 42 | * Toolbox reply |
@@ -112,6 +116,77 @@ typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST | |||
112 | 116 | ||
113 | 117 | ||
114 | /**************************************************************************** | 118 | /**************************************************************************** |
119 | * Toolbox ISTWI Read Write Tool | ||
120 | ****************************************************************************/ | ||
121 | |||
122 | /* Toolbox ISTWI Read Write Tool request message */ | ||
123 | typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { | ||
124 | U8 Tool; /* 0x00 */ | ||
125 | U8 Reserved1; /* 0x01 */ | ||
126 | U8 ChainOffset; /* 0x02 */ | ||
127 | U8 Function; /* 0x03 */ | ||
128 | U16 Reserved2; /* 0x04 */ | ||
129 | U8 Reserved3; /* 0x06 */ | ||
130 | U8 MsgFlags; /* 0x07 */ | ||
131 | U8 VP_ID; /* 0x08 */ | ||
132 | U8 VF_ID; /* 0x09 */ | ||
133 | U16 Reserved4; /* 0x0A */ | ||
134 | U32 Reserved5; /* 0x0C */ | ||
135 | U32 Reserved6; /* 0x10 */ | ||
136 | U8 DevIndex; /* 0x14 */ | ||
137 | U8 Action; /* 0x15 */ | ||
138 | U8 SGLFlags; /* 0x16 */ | ||
139 | U8 Reserved7; /* 0x17 */ | ||
140 | U16 TxDataLength; /* 0x18 */ | ||
141 | U16 RxDataLength; /* 0x1A */ | ||
142 | U32 Reserved8; /* 0x1C */ | ||
143 | U32 Reserved9; /* 0x20 */ | ||
144 | U32 Reserved10; /* 0x24 */ | ||
145 | U32 Reserved11; /* 0x28 */ | ||
146 | U32 Reserved12; /* 0x2C */ | ||
147 | MPI2_SGE_SIMPLE_UNION SGL; /* 0x30 */ | ||
148 | } MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, | ||
149 | MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, | ||
150 | Mpi2ToolboxIstwiReadWriteRequest_t, | ||
151 | MPI2_POINTER pMpi2ToolboxIstwiReadWriteRequest_t; | ||
152 | |||
153 | /* values for the Action field */ | ||
154 | #define MPI2_TOOL_ISTWI_ACTION_READ_DATA (0x01) | ||
155 | #define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA (0x02) | ||
156 | #define MPI2_TOOL_ISTWI_ACTION_SEQUENCE (0x03) | ||
157 | #define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS (0x10) | ||
158 | #define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11) | ||
159 | #define MPI2_TOOL_ISTWI_ACTION_RESET (0x12) | ||
160 | |||
161 | /* values for SGLFlags field are in the SGL section of mpi2.h */ | ||
162 | |||
163 | |||
164 | /* Toolbox ISTWI Read Write Tool reply message */ | ||
165 | typedef struct _MPI2_TOOLBOX_ISTWI_REPLY { | ||
166 | U8 Tool; /* 0x00 */ | ||
167 | U8 Reserved1; /* 0x01 */ | ||
168 | U8 MsgLength; /* 0x02 */ | ||
169 | U8 Function; /* 0x03 */ | ||
170 | U16 Reserved2; /* 0x04 */ | ||
171 | U8 Reserved3; /* 0x06 */ | ||
172 | U8 MsgFlags; /* 0x07 */ | ||
173 | U8 VP_ID; /* 0x08 */ | ||
174 | U8 VF_ID; /* 0x09 */ | ||
175 | U16 Reserved4; /* 0x0A */ | ||
176 | U16 Reserved5; /* 0x0C */ | ||
177 | U16 IOCStatus; /* 0x0E */ | ||
178 | U32 IOCLogInfo; /* 0x10 */ | ||
179 | U8 DevIndex; /* 0x14 */ | ||
180 | U8 Action; /* 0x15 */ | ||
181 | U8 IstwiStatus; /* 0x16 */ | ||
182 | U8 Reserved6; /* 0x17 */ | ||
183 | U16 TxDataCount; /* 0x18 */ | ||
184 | U16 RxDataCount; /* 0x1A */ | ||
185 | } MPI2_TOOLBOX_ISTWI_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_ISTWI_REPLY, | ||
186 | Mpi2ToolboxIstwiReply_t, MPI2_POINTER pMpi2ToolboxIstwiReply_t; | ||
187 | |||
188 | |||
189 | /**************************************************************************** | ||
115 | * Toolbox Beacon Tool request | 190 | * Toolbox Beacon Tool request |
116 | ****************************************************************************/ | 191 | ****************************************************************************/ |
117 | 192 | ||
@@ -139,6 +214,61 @@ typedef struct _MPI2_TOOLBOX_BEACON_REQUEST | |||
139 | #define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01) | 214 | #define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01) |
140 | 215 | ||
141 | 216 | ||
217 | /**************************************************************************** | ||
218 | * Toolbox Diagnostic CLI Tool | ||
219 | ****************************************************************************/ | ||
220 | |||
221 | #define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C) | ||
222 | |||
223 | /* Toolbox Diagnostic CLI Tool request message */ | ||
224 | typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { | ||
225 | U8 Tool; /* 0x00 */ | ||
226 | U8 Reserved1; /* 0x01 */ | ||
227 | U8 ChainOffset; /* 0x02 */ | ||
228 | U8 Function; /* 0x03 */ | ||
229 | U16 Reserved2; /* 0x04 */ | ||
230 | U8 Reserved3; /* 0x06 */ | ||
231 | U8 MsgFlags; /* 0x07 */ | ||
232 | U8 VP_ID; /* 0x08 */ | ||
233 | U8 VF_ID; /* 0x09 */ | ||
234 | U16 Reserved4; /* 0x0A */ | ||
235 | U8 SGLFlags; /* 0x0C */ | ||
236 | U8 Reserved5; /* 0x0D */ | ||
237 | U16 Reserved6; /* 0x0E */ | ||
238 | U32 DataLength; /* 0x10 */ | ||
239 | U8 DiagnosticCliCommand | ||
240 | [MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH]; /* 0x14 */ | ||
241 | MPI2_SGE_SIMPLE_UNION SGL; /* 0x70 */ | ||
242 | } MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, | ||
243 | MPI2_POINTER PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, | ||
244 | Mpi2ToolboxDiagnosticCliRequest_t, | ||
245 | MPI2_POINTER pMpi2ToolboxDiagnosticCliRequest_t; | ||
246 | |||
247 | /* values for SGLFlags field are in the SGL section of mpi2.h */ | ||
248 | |||
249 | |||
250 | /* Toolbox Diagnostic CLI Tool reply message */ | ||
251 | typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY { | ||
252 | U8 Tool; /* 0x00 */ | ||
253 | U8 Reserved1; /* 0x01 */ | ||
254 | U8 MsgLength; /* 0x02 */ | ||
255 | U8 Function; /* 0x03 */ | ||
256 | U16 Reserved2; /* 0x04 */ | ||
257 | U8 Reserved3; /* 0x06 */ | ||
258 | U8 MsgFlags; /* 0x07 */ | ||
259 | U8 VP_ID; /* 0x08 */ | ||
260 | U8 VF_ID; /* 0x09 */ | ||
261 | U16 Reserved4; /* 0x0A */ | ||
262 | U16 Reserved5; /* 0x0C */ | ||
263 | U16 IOCStatus; /* 0x0E */ | ||
264 | U32 IOCLogInfo; /* 0x10 */ | ||
265 | U32 ReturnedDataLength; /* 0x14 */ | ||
266 | } MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY, | ||
267 | MPI2_POINTER PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY, | ||
268 | Mpi2ToolboxDiagnosticCliReply_t, | ||
269 | MPI2_POINTER pMpi2ToolboxDiagnosticCliReply_t; | ||
270 | |||
271 | |||
142 | /***************************************************************************** | 272 | /***************************************************************************** |
143 | * | 273 | * |
144 | * Diagnostic Buffer Messages | 274 | * Diagnostic Buffer Messages |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index d95d2f274cb3..670241efa4b5 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * for access to MPT (Message Passing Technology) firmware. | 3 | * for access to MPT (Message Passing Technology) firmware. |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c | 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c |
6 | * Copyright (C) 2007-2008 LSI Corporation | 6 | * Copyright (C) 2007-2009 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -63,7 +63,7 @@ | |||
63 | static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; | 63 | static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; |
64 | 64 | ||
65 | #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ | 65 | #define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ |
66 | #define MPT2SAS_MAX_REQUEST_QUEUE 500 /* maximum controller queue depth */ | 66 | #define MPT2SAS_MAX_REQUEST_QUEUE 600 /* maximum controller queue depth */ |
67 | 67 | ||
68 | static int max_queue_depth = -1; | 68 | static int max_queue_depth = -1; |
69 | module_param(max_queue_depth, int, 0); | 69 | module_param(max_queue_depth, int, 0); |
@@ -543,13 +543,13 @@ mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code) | |||
543 | * _base_display_reply_info - | 543 | * _base_display_reply_info - |
544 | * @ioc: pointer to scsi command object | 544 | * @ioc: pointer to scsi command object |
545 | * @smid: system request message index | 545 | * @smid: system request message index |
546 | * @VF_ID: virtual function id | 546 | * @msix_index: MSIX table index supplied by the OS |
547 | * @reply: reply message frame(lower 32bit addr) | 547 | * @reply: reply message frame(lower 32bit addr) |
548 | * | 548 | * |
549 | * Return nothing. | 549 | * Return nothing. |
550 | */ | 550 | */ |
551 | static void | 551 | static void |
552 | _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | 552 | _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
553 | u32 reply) | 553 | u32 reply) |
554 | { | 554 | { |
555 | MPI2DefaultReply_t *mpi_reply; | 555 | MPI2DefaultReply_t *mpi_reply; |
@@ -572,22 +572,24 @@ _base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | |||
572 | * mpt2sas_base_done - base internal command completion routine | 572 | * mpt2sas_base_done - base internal command completion routine |
573 | * @ioc: pointer to scsi command object | 573 | * @ioc: pointer to scsi command object |
574 | * @smid: system request message index | 574 | * @smid: system request message index |
575 | * @VF_ID: virtual function id | 575 | * @msix_index: MSIX table index supplied by the OS |
576 | * @reply: reply message frame(lower 32bit addr) | 576 | * @reply: reply message frame(lower 32bit addr) |
577 | * | 577 | * |
578 | * Return nothing. | 578 | * Return 1 meaning mf should be freed from _base_interrupt |
579 | * 0 means the mf is freed from this function. | ||
579 | */ | 580 | */ |
580 | void | 581 | u8 |
581 | mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | 582 | mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
583 | u32 reply) | ||
582 | { | 584 | { |
583 | MPI2DefaultReply_t *mpi_reply; | 585 | MPI2DefaultReply_t *mpi_reply; |
584 | 586 | ||
585 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 587 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
586 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) | 588 | if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) |
587 | return; | 589 | return 1; |
588 | 590 | ||
589 | if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) | 591 | if (ioc->base_cmds.status == MPT2_CMD_NOT_USED) |
590 | return; | 592 | return 1; |
591 | 593 | ||
592 | ioc->base_cmds.status |= MPT2_CMD_COMPLETE; | 594 | ioc->base_cmds.status |= MPT2_CMD_COMPLETE; |
593 | if (mpi_reply) { | 595 | if (mpi_reply) { |
@@ -596,18 +598,20 @@ mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
596 | } | 598 | } |
597 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; | 599 | ioc->base_cmds.status &= ~MPT2_CMD_PENDING; |
598 | complete(&ioc->base_cmds.done); | 600 | complete(&ioc->base_cmds.done); |
601 | return 1; | ||
599 | } | 602 | } |
600 | 603 | ||
601 | /** | 604 | /** |
602 | * _base_async_event - main callback handler for firmware asyn events | 605 | * _base_async_event - main callback handler for firmware asyn events |
603 | * @ioc: pointer to scsi command object | 606 | * @ioc: pointer to scsi command object |
604 | * @VF_ID: virtual function id | 607 | * @msix_index: MSIX table index supplied by the OS |
605 | * @reply: reply message frame(lower 32bit addr) | 608 | * @reply: reply message frame(lower 32bit addr) |
606 | * | 609 | * |
607 | * Return nothing. | 610 | * Return 1 meaning mf should be freed from _base_interrupt |
611 | * 0 means the mf is freed from this function. | ||
608 | */ | 612 | */ |
609 | static void | 613 | static u8 |
610 | _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | 614 | _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, u32 reply) |
611 | { | 615 | { |
612 | Mpi2EventNotificationReply_t *mpi_reply; | 616 | Mpi2EventNotificationReply_t *mpi_reply; |
613 | Mpi2EventAckRequest_t *ack_request; | 617 | Mpi2EventAckRequest_t *ack_request; |
@@ -615,9 +619,9 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
615 | 619 | ||
616 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 620 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
617 | if (!mpi_reply) | 621 | if (!mpi_reply) |
618 | return; | 622 | return 1; |
619 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) | 623 | if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) |
620 | return; | 624 | return 1; |
621 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 625 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
622 | _base_display_event_data(ioc, mpi_reply); | 626 | _base_display_event_data(ioc, mpi_reply); |
623 | #endif | 627 | #endif |
@@ -635,16 +639,47 @@ _base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
635 | ack_request->Function = MPI2_FUNCTION_EVENT_ACK; | 639 | ack_request->Function = MPI2_FUNCTION_EVENT_ACK; |
636 | ack_request->Event = mpi_reply->Event; | 640 | ack_request->Event = mpi_reply->Event; |
637 | ack_request->EventContext = mpi_reply->EventContext; | 641 | ack_request->EventContext = mpi_reply->EventContext; |
638 | ack_request->VF_ID = VF_ID; | 642 | ack_request->VF_ID = 0; /* TODO */ |
639 | mpt2sas_base_put_smid_default(ioc, smid, VF_ID); | 643 | ack_request->VP_ID = 0; |
644 | mpt2sas_base_put_smid_default(ioc, smid); | ||
640 | 645 | ||
641 | out: | 646 | out: |
642 | 647 | ||
643 | /* scsih callback handler */ | 648 | /* scsih callback handler */ |
644 | mpt2sas_scsih_event_callback(ioc, VF_ID, reply); | 649 | mpt2sas_scsih_event_callback(ioc, msix_index, reply); |
645 | 650 | ||
646 | /* ctl callback handler */ | 651 | /* ctl callback handler */ |
647 | mpt2sas_ctl_event_callback(ioc, VF_ID, reply); | 652 | mpt2sas_ctl_event_callback(ioc, msix_index, reply); |
653 | |||
654 | return 1; | ||
655 | } | ||
656 | |||
657 | /** | ||
658 | * _base_get_cb_idx - obtain the callback index | ||
659 | * @ioc: per adapter object | ||
660 | * @smid: system request message index | ||
661 | * | ||
662 | * Return callback index. | ||
663 | */ | ||
664 | static u8 | ||
665 | _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
666 | { | ||
667 | int i; | ||
668 | u8 cb_idx = 0xFF; | ||
669 | |||
670 | if (smid >= ioc->hi_priority_smid) { | ||
671 | if (smid < ioc->internal_smid) { | ||
672 | i = smid - ioc->hi_priority_smid; | ||
673 | cb_idx = ioc->hpr_lookup[i].cb_idx; | ||
674 | } else { | ||
675 | i = smid - ioc->internal_smid; | ||
676 | cb_idx = ioc->internal_lookup[i].cb_idx; | ||
677 | } | ||
678 | } else { | ||
679 | i = smid - 1; | ||
680 | cb_idx = ioc->scsi_lookup[i].cb_idx; | ||
681 | } | ||
682 | return cb_idx; | ||
648 | } | 683 | } |
649 | 684 | ||
650 | /** | 685 | /** |
@@ -680,7 +715,6 @@ _base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc) | |||
680 | { | 715 | { |
681 | u32 him_register; | 716 | u32 him_register; |
682 | 717 | ||
683 | writel(0, &ioc->chip->HostInterruptStatus); | ||
684 | him_register = readl(&ioc->chip->HostInterruptMask); | 718 | him_register = readl(&ioc->chip->HostInterruptMask); |
685 | him_register &= ~MPI2_HIM_RIM; | 719 | him_register &= ~MPI2_HIM_RIM; |
686 | writel(him_register, &ioc->chip->HostInterruptMask); | 720 | writel(him_register, &ioc->chip->HostInterruptMask); |
@@ -712,9 +746,10 @@ _base_interrupt(int irq, void *bus_id) | |||
712 | u16 smid; | 746 | u16 smid; |
713 | u8 cb_idx; | 747 | u8 cb_idx; |
714 | u32 reply; | 748 | u32 reply; |
715 | u8 VF_ID; | 749 | u8 msix_index; |
716 | struct MPT2SAS_ADAPTER *ioc = bus_id; | 750 | struct MPT2SAS_ADAPTER *ioc = bus_id; |
717 | Mpi2ReplyDescriptorsUnion_t *rpf; | 751 | Mpi2ReplyDescriptorsUnion_t *rpf; |
752 | u8 rc; | ||
718 | 753 | ||
719 | if (ioc->mask_interrupts) | 754 | if (ioc->mask_interrupts) |
720 | return IRQ_NONE; | 755 | return IRQ_NONE; |
@@ -733,7 +768,7 @@ _base_interrupt(int irq, void *bus_id) | |||
733 | reply = 0; | 768 | reply = 0; |
734 | cb_idx = 0xFF; | 769 | cb_idx = 0xFF; |
735 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); | 770 | smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); |
736 | VF_ID = rpf->Default.VF_ID; | 771 | msix_index = rpf->Default.MSIxIndex; |
737 | if (request_desript_type == | 772 | if (request_desript_type == |
738 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { | 773 | MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { |
739 | reply = le32_to_cpu | 774 | reply = le32_to_cpu |
@@ -745,16 +780,18 @@ _base_interrupt(int irq, void *bus_id) | |||
745 | MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS) | 780 | MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS) |
746 | goto next; | 781 | goto next; |
747 | if (smid) | 782 | if (smid) |
748 | cb_idx = ioc->scsi_lookup[smid - 1].cb_idx; | 783 | cb_idx = _base_get_cb_idx(ioc, smid); |
749 | if (smid && cb_idx != 0xFF) { | 784 | if (smid && cb_idx != 0xFF) { |
750 | mpt_callbacks[cb_idx](ioc, smid, VF_ID, reply); | 785 | rc = mpt_callbacks[cb_idx](ioc, smid, msix_index, |
786 | reply); | ||
751 | if (reply) | 787 | if (reply) |
752 | _base_display_reply_info(ioc, smid, VF_ID, | 788 | _base_display_reply_info(ioc, smid, msix_index, |
753 | reply); | 789 | reply); |
754 | mpt2sas_base_free_smid(ioc, smid); | 790 | if (rc) |
791 | mpt2sas_base_free_smid(ioc, smid); | ||
755 | } | 792 | } |
756 | if (!smid) | 793 | if (!smid) |
757 | _base_async_event(ioc, VF_ID, reply); | 794 | _base_async_event(ioc, msix_index, reply); |
758 | 795 | ||
759 | /* reply free queue handling */ | 796 | /* reply free queue handling */ |
760 | if (reply) { | 797 | if (reply) { |
@@ -1191,19 +1228,6 @@ mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc) | |||
1191 | } | 1228 | } |
1192 | 1229 | ||
1193 | /** | 1230 | /** |
1194 | * mpt2sas_base_get_msg_frame_dma - obtain request mf pointer phys addr | ||
1195 | * @ioc: per adapter object | ||
1196 | * @smid: system request message index(smid zero is invalid) | ||
1197 | * | ||
1198 | * Returns phys pointer to message frame. | ||
1199 | */ | ||
1200 | dma_addr_t | ||
1201 | mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
1202 | { | ||
1203 | return ioc->request_dma + (smid * ioc->request_sz); | ||
1204 | } | ||
1205 | |||
1206 | /** | ||
1207 | * mpt2sas_base_get_msg_frame - obtain request mf pointer | 1231 | * mpt2sas_base_get_msg_frame - obtain request mf pointer |
1208 | * @ioc: per adapter object | 1232 | * @ioc: per adapter object |
1209 | * @smid: system request message index(smid zero is invalid) | 1233 | * @smid: system request message index(smid zero is invalid) |
@@ -1258,7 +1282,7 @@ mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr) | |||
1258 | } | 1282 | } |
1259 | 1283 | ||
1260 | /** | 1284 | /** |
1261 | * mpt2sas_base_get_smid - obtain a free smid | 1285 | * mpt2sas_base_get_smid - obtain a free smid from internal queue |
1262 | * @ioc: per adapter object | 1286 | * @ioc: per adapter object |
1263 | * @cb_idx: callback index | 1287 | * @cb_idx: callback index |
1264 | * | 1288 | * |
@@ -1272,6 +1296,39 @@ mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | |||
1272 | u16 smid; | 1296 | u16 smid; |
1273 | 1297 | ||
1274 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 1298 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
1299 | if (list_empty(&ioc->internal_free_list)) { | ||
1300 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1301 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", | ||
1302 | ioc->name, __func__); | ||
1303 | return 0; | ||
1304 | } | ||
1305 | |||
1306 | request = list_entry(ioc->internal_free_list.next, | ||
1307 | struct request_tracker, tracker_list); | ||
1308 | request->cb_idx = cb_idx; | ||
1309 | smid = request->smid; | ||
1310 | list_del(&request->tracker_list); | ||
1311 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1312 | return smid; | ||
1313 | } | ||
1314 | |||
1315 | /** | ||
1316 | * mpt2sas_base_get_smid_scsiio - obtain a free smid from scsiio queue | ||
1317 | * @ioc: per adapter object | ||
1318 | * @cb_idx: callback index | ||
1319 | * @scmd: pointer to scsi command object | ||
1320 | * | ||
1321 | * Returns smid (zero is invalid) | ||
1322 | */ | ||
1323 | u16 | ||
1324 | mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx, | ||
1325 | struct scsi_cmnd *scmd) | ||
1326 | { | ||
1327 | unsigned long flags; | ||
1328 | struct request_tracker *request; | ||
1329 | u16 smid; | ||
1330 | |||
1331 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
1275 | if (list_empty(&ioc->free_list)) { | 1332 | if (list_empty(&ioc->free_list)) { |
1276 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 1333 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
1277 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", | 1334 | printk(MPT2SAS_ERR_FMT "%s: smid not available\n", |
@@ -1281,6 +1338,36 @@ mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | |||
1281 | 1338 | ||
1282 | request = list_entry(ioc->free_list.next, | 1339 | request = list_entry(ioc->free_list.next, |
1283 | struct request_tracker, tracker_list); | 1340 | struct request_tracker, tracker_list); |
1341 | request->scmd = scmd; | ||
1342 | request->cb_idx = cb_idx; | ||
1343 | smid = request->smid; | ||
1344 | list_del(&request->tracker_list); | ||
1345 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1346 | return smid; | ||
1347 | } | ||
1348 | |||
1349 | /** | ||
1350 | * mpt2sas_base_get_smid_hpr - obtain a free smid from hi-priority queue | ||
1351 | * @ioc: per adapter object | ||
1352 | * @cb_idx: callback index | ||
1353 | * | ||
1354 | * Returns smid (zero is invalid) | ||
1355 | */ | ||
1356 | u16 | ||
1357 | mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx) | ||
1358 | { | ||
1359 | unsigned long flags; | ||
1360 | struct request_tracker *request; | ||
1361 | u16 smid; | ||
1362 | |||
1363 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
1364 | if (list_empty(&ioc->hpr_free_list)) { | ||
1365 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1369 | request = list_entry(ioc->hpr_free_list.next, | ||
1370 | struct request_tracker, tracker_list); | ||
1284 | request->cb_idx = cb_idx; | 1371 | request->cb_idx = cb_idx; |
1285 | smid = request->smid; | 1372 | smid = request->smid; |
1286 | list_del(&request->tracker_list); | 1373 | list_del(&request->tracker_list); |
@@ -1300,10 +1387,32 @@ void | |||
1300 | mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) | 1387 | mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
1301 | { | 1388 | { |
1302 | unsigned long flags; | 1389 | unsigned long flags; |
1390 | int i; | ||
1303 | 1391 | ||
1304 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 1392 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
1305 | ioc->scsi_lookup[smid - 1].cb_idx = 0xFF; | 1393 | if (smid >= ioc->hi_priority_smid) { |
1306 | list_add_tail(&ioc->scsi_lookup[smid - 1].tracker_list, | 1394 | if (smid < ioc->internal_smid) { |
1395 | /* hi-priority */ | ||
1396 | i = smid - ioc->hi_priority_smid; | ||
1397 | ioc->hpr_lookup[i].cb_idx = 0xFF; | ||
1398 | list_add_tail(&ioc->hpr_lookup[i].tracker_list, | ||
1399 | &ioc->hpr_free_list); | ||
1400 | } else { | ||
1401 | /* internal queue */ | ||
1402 | i = smid - ioc->internal_smid; | ||
1403 | ioc->internal_lookup[i].cb_idx = 0xFF; | ||
1404 | list_add_tail(&ioc->internal_lookup[i].tracker_list, | ||
1405 | &ioc->internal_free_list); | ||
1406 | } | ||
1407 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
1408 | return; | ||
1409 | } | ||
1410 | |||
1411 | /* scsiio queue */ | ||
1412 | i = smid - 1; | ||
1413 | ioc->scsi_lookup[i].cb_idx = 0xFF; | ||
1414 | ioc->scsi_lookup[i].scmd = NULL; | ||
1415 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, | ||
1307 | &ioc->free_list); | 1416 | &ioc->free_list); |
1308 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 1417 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
1309 | 1418 | ||
@@ -1352,21 +1461,19 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr, | |||
1352 | * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware | 1461 | * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware |
1353 | * @ioc: per adapter object | 1462 | * @ioc: per adapter object |
1354 | * @smid: system request message index | 1463 | * @smid: system request message index |
1355 | * @vf_id: virtual function id | ||
1356 | * @handle: device handle | 1464 | * @handle: device handle |
1357 | * | 1465 | * |
1358 | * Return nothing. | 1466 | * Return nothing. |
1359 | */ | 1467 | */ |
1360 | void | 1468 | void |
1361 | mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id, | 1469 | mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u16 handle) |
1362 | u16 handle) | ||
1363 | { | 1470 | { |
1364 | Mpi2RequestDescriptorUnion_t descriptor; | 1471 | Mpi2RequestDescriptorUnion_t descriptor; |
1365 | u64 *request = (u64 *)&descriptor; | 1472 | u64 *request = (u64 *)&descriptor; |
1366 | 1473 | ||
1367 | 1474 | ||
1368 | descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; | 1475 | descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; |
1369 | descriptor.SCSIIO.VF_ID = vf_id; | 1476 | descriptor.SCSIIO.MSIxIndex = 0; /* TODO */ |
1370 | descriptor.SCSIIO.SMID = cpu_to_le16(smid); | 1477 | descriptor.SCSIIO.SMID = cpu_to_le16(smid); |
1371 | descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); | 1478 | descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); |
1372 | descriptor.SCSIIO.LMID = 0; | 1479 | descriptor.SCSIIO.LMID = 0; |
@@ -1379,20 +1486,18 @@ mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id, | |||
1379 | * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware | 1486 | * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware |
1380 | * @ioc: per adapter object | 1487 | * @ioc: per adapter object |
1381 | * @smid: system request message index | 1488 | * @smid: system request message index |
1382 | * @vf_id: virtual function id | ||
1383 | * | 1489 | * |
1384 | * Return nothing. | 1490 | * Return nothing. |
1385 | */ | 1491 | */ |
1386 | void | 1492 | void |
1387 | mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 1493 | mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
1388 | u8 vf_id) | ||
1389 | { | 1494 | { |
1390 | Mpi2RequestDescriptorUnion_t descriptor; | 1495 | Mpi2RequestDescriptorUnion_t descriptor; |
1391 | u64 *request = (u64 *)&descriptor; | 1496 | u64 *request = (u64 *)&descriptor; |
1392 | 1497 | ||
1393 | descriptor.HighPriority.RequestFlags = | 1498 | descriptor.HighPriority.RequestFlags = |
1394 | MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; | 1499 | MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; |
1395 | descriptor.HighPriority.VF_ID = vf_id; | 1500 | descriptor.HighPriority.MSIxIndex = 0; /* TODO */ |
1396 | descriptor.HighPriority.SMID = cpu_to_le16(smid); | 1501 | descriptor.HighPriority.SMID = cpu_to_le16(smid); |
1397 | descriptor.HighPriority.LMID = 0; | 1502 | descriptor.HighPriority.LMID = 0; |
1398 | descriptor.HighPriority.Reserved1 = 0; | 1503 | descriptor.HighPriority.Reserved1 = 0; |
@@ -1404,18 +1509,17 @@ mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
1404 | * mpt2sas_base_put_smid_default - Default, primarily used for config pages | 1509 | * mpt2sas_base_put_smid_default - Default, primarily used for config pages |
1405 | * @ioc: per adapter object | 1510 | * @ioc: per adapter object |
1406 | * @smid: system request message index | 1511 | * @smid: system request message index |
1407 | * @vf_id: virtual function id | ||
1408 | * | 1512 | * |
1409 | * Return nothing. | 1513 | * Return nothing. |
1410 | */ | 1514 | */ |
1411 | void | 1515 | void |
1412 | mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id) | 1516 | mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
1413 | { | 1517 | { |
1414 | Mpi2RequestDescriptorUnion_t descriptor; | 1518 | Mpi2RequestDescriptorUnion_t descriptor; |
1415 | u64 *request = (u64 *)&descriptor; | 1519 | u64 *request = (u64 *)&descriptor; |
1416 | 1520 | ||
1417 | descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; | 1521 | descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; |
1418 | descriptor.Default.VF_ID = vf_id; | 1522 | descriptor.Default.MSIxIndex = 0; /* TODO */ |
1419 | descriptor.Default.SMID = cpu_to_le16(smid); | 1523 | descriptor.Default.SMID = cpu_to_le16(smid); |
1420 | descriptor.Default.LMID = 0; | 1524 | descriptor.Default.LMID = 0; |
1421 | descriptor.Default.DescriptorTypeDependent = 0; | 1525 | descriptor.Default.DescriptorTypeDependent = 0; |
@@ -1427,21 +1531,20 @@ mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id) | |||
1427 | * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware | 1531 | * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware |
1428 | * @ioc: per adapter object | 1532 | * @ioc: per adapter object |
1429 | * @smid: system request message index | 1533 | * @smid: system request message index |
1430 | * @vf_id: virtual function id | ||
1431 | * @io_index: value used to track the IO | 1534 | * @io_index: value used to track the IO |
1432 | * | 1535 | * |
1433 | * Return nothing. | 1536 | * Return nothing. |
1434 | */ | 1537 | */ |
1435 | void | 1538 | void |
1436 | mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 1539 | mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, |
1437 | u8 vf_id, u16 io_index) | 1540 | u16 io_index) |
1438 | { | 1541 | { |
1439 | Mpi2RequestDescriptorUnion_t descriptor; | 1542 | Mpi2RequestDescriptorUnion_t descriptor; |
1440 | u64 *request = (u64 *)&descriptor; | 1543 | u64 *request = (u64 *)&descriptor; |
1441 | 1544 | ||
1442 | descriptor.SCSITarget.RequestFlags = | 1545 | descriptor.SCSITarget.RequestFlags = |
1443 | MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; | 1546 | MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET; |
1444 | descriptor.SCSITarget.VF_ID = vf_id; | 1547 | descriptor.SCSITarget.MSIxIndex = 0; /* TODO */ |
1445 | descriptor.SCSITarget.SMID = cpu_to_le16(smid); | 1548 | descriptor.SCSITarget.SMID = cpu_to_le16(smid); |
1446 | descriptor.SCSITarget.LMID = 0; | 1549 | descriptor.SCSITarget.LMID = 0; |
1447 | descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); | 1550 | descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index); |
@@ -1717,6 +1820,8 @@ _base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc) | |||
1717 | } | 1820 | } |
1718 | 1821 | ||
1719 | kfree(ioc->scsi_lookup); | 1822 | kfree(ioc->scsi_lookup); |
1823 | kfree(ioc->hpr_lookup); | ||
1824 | kfree(ioc->internal_lookup); | ||
1720 | } | 1825 | } |
1721 | 1826 | ||
1722 | 1827 | ||
@@ -1736,7 +1841,6 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1736 | u16 num_of_reply_frames; | 1841 | u16 num_of_reply_frames; |
1737 | u16 chains_needed_per_io; | 1842 | u16 chains_needed_per_io; |
1738 | u32 sz, total_sz; | 1843 | u32 sz, total_sz; |
1739 | u16 i; | ||
1740 | u32 retry_sz; | 1844 | u32 retry_sz; |
1741 | u16 max_request_credit; | 1845 | u16 max_request_credit; |
1742 | 1846 | ||
@@ -1764,7 +1868,10 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1764 | MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE : | 1868 | MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE : |
1765 | facts->RequestCredit; | 1869 | facts->RequestCredit; |
1766 | } | 1870 | } |
1767 | ioc->request_depth = max_request_credit; | 1871 | |
1872 | ioc->hba_queue_depth = max_request_credit; | ||
1873 | ioc->hi_priority_depth = facts->HighPriorityCredit; | ||
1874 | ioc->internal_depth = ioc->hi_priority_depth + 5; | ||
1768 | 1875 | ||
1769 | /* request frame size */ | 1876 | /* request frame size */ |
1770 | ioc->request_sz = facts->IOCRequestFrameSize * 4; | 1877 | ioc->request_sz = facts->IOCRequestFrameSize * 4; |
@@ -1802,7 +1909,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1802 | ioc->chains_needed_per_io = chains_needed_per_io; | 1909 | ioc->chains_needed_per_io = chains_needed_per_io; |
1803 | 1910 | ||
1804 | /* reply free queue sizing - taking into account for events */ | 1911 | /* reply free queue sizing - taking into account for events */ |
1805 | num_of_reply_frames = ioc->request_depth + 32; | 1912 | num_of_reply_frames = ioc->hba_queue_depth + 32; |
1806 | 1913 | ||
1807 | /* number of replies frames can't be a multiple of 16 */ | 1914 | /* number of replies frames can't be a multiple of 16 */ |
1808 | /* decrease number of reply frames by 1 */ | 1915 | /* decrease number of reply frames by 1 */ |
@@ -1823,7 +1930,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1823 | * frames | 1930 | * frames |
1824 | */ | 1931 | */ |
1825 | 1932 | ||
1826 | queue_size = ioc->request_depth + num_of_reply_frames + 1; | 1933 | queue_size = ioc->hba_queue_depth + num_of_reply_frames + 1; |
1827 | /* round up to 16 byte boundary */ | 1934 | /* round up to 16 byte boundary */ |
1828 | if (queue_size % 16) | 1935 | if (queue_size % 16) |
1829 | queue_size += 16 - (queue_size % 16); | 1936 | queue_size += 16 - (queue_size % 16); |
@@ -1837,60 +1944,85 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1837 | if (queue_diff % 16) | 1944 | if (queue_diff % 16) |
1838 | queue_diff += 16 - (queue_diff % 16); | 1945 | queue_diff += 16 - (queue_diff % 16); |
1839 | 1946 | ||
1840 | /* adjust request_depth, reply_free_queue_depth, | 1947 | /* adjust hba_queue_depth, reply_free_queue_depth, |
1841 | * and queue_size | 1948 | * and queue_size |
1842 | */ | 1949 | */ |
1843 | ioc->request_depth -= queue_diff; | 1950 | ioc->hba_queue_depth -= queue_diff; |
1844 | ioc->reply_free_queue_depth -= queue_diff; | 1951 | ioc->reply_free_queue_depth -= queue_diff; |
1845 | queue_size -= queue_diff; | 1952 | queue_size -= queue_diff; |
1846 | } | 1953 | } |
1847 | ioc->reply_post_queue_depth = queue_size; | 1954 | ioc->reply_post_queue_depth = queue_size; |
1848 | 1955 | ||
1849 | /* max scsi host queue depth */ | ||
1850 | ioc->shost->can_queue = ioc->request_depth - INTERNAL_CMDS_COUNT; | ||
1851 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host queue: depth" | ||
1852 | "(%d)\n", ioc->name, ioc->shost->can_queue)); | ||
1853 | |||
1854 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " | 1956 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: " |
1855 | "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " | 1957 | "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " |
1856 | "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, | 1958 | "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, |
1857 | ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, | 1959 | ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, |
1858 | ioc->chains_needed_per_io)); | 1960 | ioc->chains_needed_per_io)); |
1859 | 1961 | ||
1962 | ioc->scsiio_depth = ioc->hba_queue_depth - | ||
1963 | ioc->hi_priority_depth - ioc->internal_depth; | ||
1964 | |||
1965 | /* set the scsi host can_queue depth | ||
1966 | * with some internal commands that could be outstanding | ||
1967 | */ | ||
1968 | ioc->shost->can_queue = ioc->scsiio_depth - (2); | ||
1969 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " | ||
1970 | "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); | ||
1971 | |||
1860 | /* contiguous pool for request and chains, 16 byte align, one extra " | 1972 | /* contiguous pool for request and chains, 16 byte align, one extra " |
1861 | * "frame for smid=0 | 1973 | * "frame for smid=0 |
1862 | */ | 1974 | */ |
1863 | ioc->chain_depth = ioc->chains_needed_per_io * ioc->request_depth; | 1975 | ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; |
1864 | sz = ((ioc->request_depth + 1 + ioc->chain_depth) * ioc->request_sz); | 1976 | sz = ((ioc->scsiio_depth + 1 + ioc->chain_depth) * ioc->request_sz); |
1977 | |||
1978 | /* hi-priority queue */ | ||
1979 | sz += (ioc->hi_priority_depth * ioc->request_sz); | ||
1980 | |||
1981 | /* internal queue */ | ||
1982 | sz += (ioc->internal_depth * ioc->request_sz); | ||
1865 | 1983 | ||
1866 | ioc->request_dma_sz = sz; | 1984 | ioc->request_dma_sz = sz; |
1867 | ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); | 1985 | ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); |
1868 | if (!ioc->request) { | 1986 | if (!ioc->request) { |
1869 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " | 1987 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " |
1870 | "failed: req_depth(%d), chains_per_io(%d), frame_sz(%d), " | 1988 | "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " |
1871 | "total(%d kB)\n", ioc->name, ioc->request_depth, | 1989 | "total(%d kB)\n", ioc->name, ioc->hba_queue_depth, |
1872 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); | 1990 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); |
1873 | if (ioc->request_depth < MPT2SAS_SAS_QUEUE_DEPTH) | 1991 | if (ioc->scsiio_depth < MPT2SAS_SAS_QUEUE_DEPTH) |
1874 | goto out; | 1992 | goto out; |
1875 | retry_sz += 64; | 1993 | retry_sz += 64; |
1876 | ioc->request_depth = max_request_credit - retry_sz; | 1994 | ioc->hba_queue_depth = max_request_credit - retry_sz; |
1877 | goto retry_allocation; | 1995 | goto retry_allocation; |
1878 | } | 1996 | } |
1879 | 1997 | ||
1880 | if (retry_sz) | 1998 | if (retry_sz) |
1881 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " | 1999 | printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent " |
1882 | "succeed: req_depth(%d), chains_per_io(%d), frame_sz(%d), " | 2000 | "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " |
1883 | "total(%d kb)\n", ioc->name, ioc->request_depth, | 2001 | "total(%d kb)\n", ioc->name, ioc->hba_queue_depth, |
1884 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); | 2002 | ioc->chains_needed_per_io, ioc->request_sz, sz/1024); |
1885 | 2003 | ||
1886 | ioc->chain = ioc->request + ((ioc->request_depth + 1) * | 2004 | |
2005 | /* hi-priority queue */ | ||
2006 | ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) * | ||
2007 | ioc->request_sz); | ||
2008 | ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) * | ||
2009 | ioc->request_sz); | ||
2010 | |||
2011 | /* internal queue */ | ||
2012 | ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth * | ||
2013 | ioc->request_sz); | ||
2014 | ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * | ||
2015 | ioc->request_sz); | ||
2016 | |||
2017 | ioc->chain = ioc->internal + (ioc->internal_depth * | ||
1887 | ioc->request_sz); | 2018 | ioc->request_sz); |
1888 | ioc->chain_dma = ioc->request_dma + ((ioc->request_depth + 1) * | 2019 | ioc->chain_dma = ioc->internal_dma + (ioc->internal_depth * |
1889 | ioc->request_sz); | 2020 | ioc->request_sz); |
2021 | |||
1890 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " | 2022 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): " |
1891 | "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, | 2023 | "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, |
1892 | ioc->request, ioc->request_depth, ioc->request_sz, | 2024 | ioc->request, ioc->hba_queue_depth, ioc->request_sz, |
1893 | ((ioc->request_depth + 1) * ioc->request_sz)/1024)); | 2025 | (ioc->hba_queue_depth * ioc->request_sz)/1024)); |
1894 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth" | 2026 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth" |
1895 | "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain, | 2027 | "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain, |
1896 | ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * | 2028 | ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth * |
@@ -1899,7 +2031,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1899 | ioc->name, (unsigned long long) ioc->request_dma)); | 2031 | ioc->name, (unsigned long long) ioc->request_dma)); |
1900 | total_sz += sz; | 2032 | total_sz += sz; |
1901 | 2033 | ||
1902 | ioc->scsi_lookup = kcalloc(ioc->request_depth, | 2034 | ioc->scsi_lookup = kcalloc(ioc->scsiio_depth, |
1903 | sizeof(struct request_tracker), GFP_KERNEL); | 2035 | sizeof(struct request_tracker), GFP_KERNEL); |
1904 | if (!ioc->scsi_lookup) { | 2036 | if (!ioc->scsi_lookup) { |
1905 | printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n", | 2037 | printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n", |
@@ -1907,12 +2039,38 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1907 | goto out; | 2039 | goto out; |
1908 | } | 2040 | } |
1909 | 2041 | ||
1910 | /* initialize some bits */ | 2042 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsiio(0x%p): " |
1911 | for (i = 0; i < ioc->request_depth; i++) | 2043 | "depth(%d)\n", ioc->name, ioc->request, |
1912 | ioc->scsi_lookup[i].smid = i + 1; | 2044 | ioc->scsiio_depth)); |
2045 | |||
2046 | /* initialize hi-priority queue smid's */ | ||
2047 | ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, | ||
2048 | sizeof(struct request_tracker), GFP_KERNEL); | ||
2049 | if (!ioc->hpr_lookup) { | ||
2050 | printk(MPT2SAS_ERR_FMT "hpr_lookup: kcalloc failed\n", | ||
2051 | ioc->name); | ||
2052 | goto out; | ||
2053 | } | ||
2054 | ioc->hi_priority_smid = ioc->scsiio_depth + 1; | ||
2055 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hi_priority(0x%p): " | ||
2056 | "depth(%d), start smid(%d)\n", ioc->name, ioc->hi_priority, | ||
2057 | ioc->hi_priority_depth, ioc->hi_priority_smid)); | ||
2058 | |||
2059 | /* initialize internal queue smid's */ | ||
2060 | ioc->internal_lookup = kcalloc(ioc->internal_depth, | ||
2061 | sizeof(struct request_tracker), GFP_KERNEL); | ||
2062 | if (!ioc->internal_lookup) { | ||
2063 | printk(MPT2SAS_ERR_FMT "internal_lookup: kcalloc failed\n", | ||
2064 | ioc->name); | ||
2065 | goto out; | ||
2066 | } | ||
2067 | ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth; | ||
2068 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "internal(0x%p): " | ||
2069 | "depth(%d), start smid(%d)\n", ioc->name, ioc->internal, | ||
2070 | ioc->internal_depth, ioc->internal_smid)); | ||
1913 | 2071 | ||
1914 | /* sense buffers, 4 byte align */ | 2072 | /* sense buffers, 4 byte align */ |
1915 | sz = ioc->request_depth * SCSI_SENSE_BUFFERSIZE; | 2073 | sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE; |
1916 | ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, | 2074 | ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, |
1917 | 0); | 2075 | 0); |
1918 | if (!ioc->sense_dma_pool) { | 2076 | if (!ioc->sense_dma_pool) { |
@@ -1929,7 +2087,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
1929 | } | 2087 | } |
1930 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT | 2088 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT |
1931 | "sense pool(0x%p): depth(%d), element_size(%d), pool_size" | 2089 | "sense pool(0x%p): depth(%d), element_size(%d), pool_size" |
1932 | "(%d kB)\n", ioc->name, ioc->sense, ioc->request_depth, | 2090 | "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth, |
1933 | SCSI_SENSE_BUFFERSIZE, sz/1024)); | 2091 | SCSI_SENSE_BUFFERSIZE, sz/1024)); |
1934 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n", | 2092 | dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n", |
1935 | ioc->name, (unsigned long long)ioc->sense_dma)); | 2093 | ioc->name, (unsigned long long)ioc->sense_dma)); |
@@ -2304,7 +2462,7 @@ _base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes, | |||
2304 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), | 2462 | ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)), |
2305 | &ioc->chip->Doorbell); | 2463 | &ioc->chip->Doorbell); |
2306 | 2464 | ||
2307 | if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { | 2465 | if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) { |
2308 | printk(MPT2SAS_ERR_FMT "doorbell handshake " | 2466 | printk(MPT2SAS_ERR_FMT "doorbell handshake " |
2309 | "int failed (line=%d)\n", ioc->name, __LINE__); | 2467 | "int failed (line=%d)\n", ioc->name, __LINE__); |
2310 | return -EFAULT; | 2468 | return -EFAULT; |
@@ -2454,7 +2612,8 @@ mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc, | |||
2454 | if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || | 2612 | if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || |
2455 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) | 2613 | mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) |
2456 | ioc->ioc_link_reset_in_progress = 1; | 2614 | ioc->ioc_link_reset_in_progress = 1; |
2457 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 2615 | mpt2sas_base_put_smid_default(ioc, smid); |
2616 | init_completion(&ioc->base_cmds.done); | ||
2458 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 2617 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, |
2459 | msecs_to_jiffies(10000)); | 2618 | msecs_to_jiffies(10000)); |
2460 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || | 2619 | if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || |
@@ -2555,7 +2714,8 @@ mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, | |||
2555 | request = mpt2sas_base_get_msg_frame(ioc, smid); | 2714 | request = mpt2sas_base_get_msg_frame(ioc, smid); |
2556 | ioc->base_cmds.smid = smid; | 2715 | ioc->base_cmds.smid = smid; |
2557 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); | 2716 | memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); |
2558 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 2717 | mpt2sas_base_put_smid_default(ioc, smid); |
2718 | init_completion(&ioc->base_cmds.done); | ||
2559 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 2719 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, |
2560 | msecs_to_jiffies(10000)); | 2720 | msecs_to_jiffies(10000)); |
2561 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | 2721 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { |
@@ -2701,13 +2861,12 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
2701 | /** | 2861 | /** |
2702 | * _base_send_ioc_init - send ioc_init to firmware | 2862 | * _base_send_ioc_init - send ioc_init to firmware |
2703 | * @ioc: per adapter object | 2863 | * @ioc: per adapter object |
2704 | * @VF_ID: virtual function id | ||
2705 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 2864 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
2706 | * | 2865 | * |
2707 | * Returns 0 for success, non-zero for failure. | 2866 | * Returns 0 for success, non-zero for failure. |
2708 | */ | 2867 | */ |
2709 | static int | 2868 | static int |
2710 | _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | 2869 | _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
2711 | { | 2870 | { |
2712 | Mpi2IOCInitRequest_t mpi_request; | 2871 | Mpi2IOCInitRequest_t mpi_request; |
2713 | Mpi2IOCInitReply_t mpi_reply; | 2872 | Mpi2IOCInitReply_t mpi_reply; |
@@ -2719,7 +2878,8 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2719 | memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); | 2878 | memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); |
2720 | mpi_request.Function = MPI2_FUNCTION_IOC_INIT; | 2879 | mpi_request.Function = MPI2_FUNCTION_IOC_INIT; |
2721 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; | 2880 | mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; |
2722 | mpi_request.VF_ID = VF_ID; | 2881 | mpi_request.VF_ID = 0; /* TODO */ |
2882 | mpi_request.VP_ID = 0; | ||
2723 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); | 2883 | mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); |
2724 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); | 2884 | mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); |
2725 | 2885 | ||
@@ -2795,13 +2955,12 @@ _base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2795 | /** | 2955 | /** |
2796 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware | 2956 | * _base_send_port_enable - send port_enable(discovery stuff) to firmware |
2797 | * @ioc: per adapter object | 2957 | * @ioc: per adapter object |
2798 | * @VF_ID: virtual function id | ||
2799 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 2958 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
2800 | * | 2959 | * |
2801 | * Returns 0 for success, non-zero for failure. | 2960 | * Returns 0 for success, non-zero for failure. |
2802 | */ | 2961 | */ |
2803 | static int | 2962 | static int |
2804 | _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | 2963 | _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
2805 | { | 2964 | { |
2806 | Mpi2PortEnableRequest_t *mpi_request; | 2965 | Mpi2PortEnableRequest_t *mpi_request; |
2807 | u32 ioc_state; | 2966 | u32 ioc_state; |
@@ -2829,9 +2988,11 @@ _base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2829 | ioc->base_cmds.smid = smid; | 2988 | ioc->base_cmds.smid = smid; |
2830 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); | 2989 | memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); |
2831 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; | 2990 | mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; |
2832 | mpi_request->VF_ID = VF_ID; | 2991 | mpi_request->VF_ID = 0; /* TODO */ |
2992 | mpi_request->VP_ID = 0; | ||
2833 | 2993 | ||
2834 | mpt2sas_base_put_smid_default(ioc, smid, VF_ID); | 2994 | mpt2sas_base_put_smid_default(ioc, smid); |
2995 | init_completion(&ioc->base_cmds.done); | ||
2835 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, | 2996 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, |
2836 | 300*HZ); | 2997 | 300*HZ); |
2837 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | 2998 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { |
@@ -2892,13 +3053,12 @@ _base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event) | |||
2892 | /** | 3053 | /** |
2893 | * _base_event_notification - send event notification | 3054 | * _base_event_notification - send event notification |
2894 | * @ioc: per adapter object | 3055 | * @ioc: per adapter object |
2895 | * @VF_ID: virtual function id | ||
2896 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 3056 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
2897 | * | 3057 | * |
2898 | * Returns 0 for success, non-zero for failure. | 3058 | * Returns 0 for success, non-zero for failure. |
2899 | */ | 3059 | */ |
2900 | static int | 3060 | static int |
2901 | _base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | 3061 | _base_event_notification(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
2902 | { | 3062 | { |
2903 | Mpi2EventNotificationRequest_t *mpi_request; | 3063 | Mpi2EventNotificationRequest_t *mpi_request; |
2904 | unsigned long timeleft; | 3064 | unsigned long timeleft; |
@@ -2926,11 +3086,13 @@ _base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag) | |||
2926 | ioc->base_cmds.smid = smid; | 3086 | ioc->base_cmds.smid = smid; |
2927 | memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); | 3087 | memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); |
2928 | mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; | 3088 | mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; |
2929 | mpi_request->VF_ID = VF_ID; | 3089 | mpi_request->VF_ID = 0; /* TODO */ |
3090 | mpi_request->VP_ID = 0; | ||
2930 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | 3091 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) |
2931 | mpi_request->EventMasks[i] = | 3092 | mpi_request->EventMasks[i] = |
2932 | le32_to_cpu(ioc->event_masks[i]); | 3093 | le32_to_cpu(ioc->event_masks[i]); |
2933 | mpt2sas_base_put_smid_default(ioc, smid, VF_ID); | 3094 | mpt2sas_base_put_smid_default(ioc, smid); |
3095 | init_completion(&ioc->base_cmds.done); | ||
2934 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); | 3096 | timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); |
2935 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { | 3097 | if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) { |
2936 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", | 3098 | printk(MPT2SAS_ERR_FMT "%s: timeout\n", |
@@ -2981,7 +3143,7 @@ mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type) | |||
2981 | return; | 3143 | return; |
2982 | 3144 | ||
2983 | mutex_lock(&ioc->base_cmds.mutex); | 3145 | mutex_lock(&ioc->base_cmds.mutex); |
2984 | _base_event_notification(ioc, 0, CAN_SLEEP); | 3146 | _base_event_notification(ioc, CAN_SLEEP); |
2985 | mutex_unlock(&ioc->base_cmds.mutex); | 3147 | mutex_unlock(&ioc->base_cmds.mutex); |
2986 | } | 3148 | } |
2987 | 3149 | ||
@@ -3006,7 +3168,6 @@ _base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3006 | 3168 | ||
3007 | drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n", | 3169 | drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n", |
3008 | ioc->name)); | 3170 | ioc->name)); |
3009 | writel(0, &ioc->chip->HostInterruptStatus); | ||
3010 | 3171 | ||
3011 | count = 0; | 3172 | count = 0; |
3012 | do { | 3173 | do { |
@@ -3160,30 +3321,60 @@ _base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
3160 | /** | 3321 | /** |
3161 | * _base_make_ioc_operational - put controller in OPERATIONAL state | 3322 | * _base_make_ioc_operational - put controller in OPERATIONAL state |
3162 | * @ioc: per adapter object | 3323 | * @ioc: per adapter object |
3163 | * @VF_ID: virtual function id | ||
3164 | * @sleep_flag: CAN_SLEEP or NO_SLEEP | 3324 | * @sleep_flag: CAN_SLEEP or NO_SLEEP |
3165 | * | 3325 | * |
3166 | * Returns 0 for success, non-zero for failure. | 3326 | * Returns 0 for success, non-zero for failure. |
3167 | */ | 3327 | */ |
3168 | static int | 3328 | static int |
3169 | _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 3329 | _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) |
3170 | int sleep_flag) | ||
3171 | { | 3330 | { |
3172 | int r, i; | 3331 | int r, i; |
3173 | unsigned long flags; | 3332 | unsigned long flags; |
3174 | u32 reply_address; | 3333 | u32 reply_address; |
3334 | u16 smid; | ||
3335 | struct _tr_list *delayed_tr, *delayed_tr_next; | ||
3175 | 3336 | ||
3176 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, | 3337 | dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name, |
3177 | __func__)); | 3338 | __func__)); |
3178 | 3339 | ||
3340 | /* clean the delayed target reset list */ | ||
3341 | list_for_each_entry_safe(delayed_tr, delayed_tr_next, | ||
3342 | &ioc->delayed_tr_list, list) { | ||
3343 | list_del(&delayed_tr->list); | ||
3344 | kfree(delayed_tr); | ||
3345 | } | ||
3346 | |||
3179 | /* initialize the scsi lookup free list */ | 3347 | /* initialize the scsi lookup free list */ |
3180 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 3348 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
3181 | INIT_LIST_HEAD(&ioc->free_list); | 3349 | INIT_LIST_HEAD(&ioc->free_list); |
3182 | for (i = 0; i < ioc->request_depth; i++) { | 3350 | smid = 1; |
3351 | for (i = 0; i < ioc->scsiio_depth; i++, smid++) { | ||
3183 | ioc->scsi_lookup[i].cb_idx = 0xFF; | 3352 | ioc->scsi_lookup[i].cb_idx = 0xFF; |
3353 | ioc->scsi_lookup[i].smid = smid; | ||
3354 | ioc->scsi_lookup[i].scmd = NULL; | ||
3184 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, | 3355 | list_add_tail(&ioc->scsi_lookup[i].tracker_list, |
3185 | &ioc->free_list); | 3356 | &ioc->free_list); |
3186 | } | 3357 | } |
3358 | |||
3359 | /* hi-priority queue */ | ||
3360 | INIT_LIST_HEAD(&ioc->hpr_free_list); | ||
3361 | smid = ioc->hi_priority_smid; | ||
3362 | for (i = 0; i < ioc->hi_priority_depth; i++, smid++) { | ||
3363 | ioc->hpr_lookup[i].cb_idx = 0xFF; | ||
3364 | ioc->hpr_lookup[i].smid = smid; | ||
3365 | list_add_tail(&ioc->hpr_lookup[i].tracker_list, | ||
3366 | &ioc->hpr_free_list); | ||
3367 | } | ||
3368 | |||
3369 | /* internal queue */ | ||
3370 | INIT_LIST_HEAD(&ioc->internal_free_list); | ||
3371 | smid = ioc->internal_smid; | ||
3372 | for (i = 0; i < ioc->internal_depth; i++, smid++) { | ||
3373 | ioc->internal_lookup[i].cb_idx = 0xFF; | ||
3374 | ioc->internal_lookup[i].smid = smid; | ||
3375 | list_add_tail(&ioc->internal_lookup[i].tracker_list, | ||
3376 | &ioc->internal_free_list); | ||
3377 | } | ||
3187 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 3378 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
3188 | 3379 | ||
3189 | /* initialize Reply Free Queue */ | 3380 | /* initialize Reply Free Queue */ |
@@ -3196,7 +3387,7 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3196 | for (i = 0; i < ioc->reply_post_queue_depth; i++) | 3387 | for (i = 0; i < ioc->reply_post_queue_depth; i++) |
3197 | ioc->reply_post_free[i].Words = ULLONG_MAX; | 3388 | ioc->reply_post_free[i].Words = ULLONG_MAX; |
3198 | 3389 | ||
3199 | r = _base_send_ioc_init(ioc, VF_ID, sleep_flag); | 3390 | r = _base_send_ioc_init(ioc, sleep_flag); |
3200 | if (r) | 3391 | if (r) |
3201 | return r; | 3392 | return r; |
3202 | 3393 | ||
@@ -3207,14 +3398,14 @@ _base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3207 | writel(0, &ioc->chip->ReplyPostHostIndex); | 3398 | writel(0, &ioc->chip->ReplyPostHostIndex); |
3208 | 3399 | ||
3209 | _base_unmask_interrupts(ioc); | 3400 | _base_unmask_interrupts(ioc); |
3210 | r = _base_event_notification(ioc, VF_ID, sleep_flag); | 3401 | r = _base_event_notification(ioc, sleep_flag); |
3211 | if (r) | 3402 | if (r) |
3212 | return r; | 3403 | return r; |
3213 | 3404 | ||
3214 | if (sleep_flag == CAN_SLEEP) | 3405 | if (sleep_flag == CAN_SLEEP) |
3215 | _base_static_config_pages(ioc); | 3406 | _base_static_config_pages(ioc); |
3216 | 3407 | ||
3217 | r = _base_send_port_enable(ioc, VF_ID, sleep_flag); | 3408 | r = _base_send_port_enable(ioc, sleep_flag); |
3218 | if (r) | 3409 | if (r) |
3219 | return r; | 3410 | return r; |
3220 | 3411 | ||
@@ -3278,6 +3469,17 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3278 | if (r) | 3469 | if (r) |
3279 | goto out_free_resources; | 3470 | goto out_free_resources; |
3280 | 3471 | ||
3472 | ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, | ||
3473 | sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); | ||
3474 | if (!ioc->pfacts) | ||
3475 | goto out_free_resources; | ||
3476 | |||
3477 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { | ||
3478 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); | ||
3479 | if (r) | ||
3480 | goto out_free_resources; | ||
3481 | } | ||
3482 | |||
3281 | r = _base_allocate_memory_pools(ioc, CAN_SLEEP); | 3483 | r = _base_allocate_memory_pools(ioc, CAN_SLEEP); |
3282 | if (r) | 3484 | if (r) |
3283 | goto out_free_resources; | 3485 | goto out_free_resources; |
@@ -3286,7 +3488,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3286 | 3488 | ||
3287 | /* base internal command bits */ | 3489 | /* base internal command bits */ |
3288 | mutex_init(&ioc->base_cmds.mutex); | 3490 | mutex_init(&ioc->base_cmds.mutex); |
3289 | init_completion(&ioc->base_cmds.done); | ||
3290 | ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3491 | ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3291 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; | 3492 | ioc->base_cmds.status = MPT2_CMD_NOT_USED; |
3292 | 3493 | ||
@@ -3294,7 +3495,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3294 | ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3495 | ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3295 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; | 3496 | ioc->transport_cmds.status = MPT2_CMD_NOT_USED; |
3296 | mutex_init(&ioc->transport_cmds.mutex); | 3497 | mutex_init(&ioc->transport_cmds.mutex); |
3297 | init_completion(&ioc->transport_cmds.done); | ||
3298 | 3498 | ||
3299 | /* task management internal command bits */ | 3499 | /* task management internal command bits */ |
3300 | ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3500 | ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
@@ -3310,7 +3510,6 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3310 | ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); | 3510 | ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); |
3311 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; | 3511 | ioc->ctl_cmds.status = MPT2_CMD_NOT_USED; |
3312 | mutex_init(&ioc->ctl_cmds.mutex); | 3512 | mutex_init(&ioc->ctl_cmds.mutex); |
3313 | init_completion(&ioc->ctl_cmds.done); | ||
3314 | 3513 | ||
3315 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) | 3514 | for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) |
3316 | ioc->event_masks[i] = -1; | 3515 | ioc->event_masks[i] = -1; |
@@ -3327,18 +3526,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) | |||
3327 | _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); | 3526 | _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); |
3328 | _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL); | 3527 | _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL); |
3329 | _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); | 3528 | _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); |
3330 | 3529 | r = _base_make_ioc_operational(ioc, CAN_SLEEP); | |
3331 | ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, | ||
3332 | sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); | ||
3333 | if (!ioc->pfacts) | ||
3334 | goto out_free_resources; | ||
3335 | |||
3336 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { | ||
3337 | r = _base_get_port_facts(ioc, i, CAN_SLEEP); | ||
3338 | if (r) | ||
3339 | goto out_free_resources; | ||
3340 | } | ||
3341 | r = _base_make_ioc_operational(ioc, 0, CAN_SLEEP); | ||
3342 | if (r) | 3530 | if (r) |
3343 | goto out_free_resources; | 3531 | goto out_free_resources; |
3344 | 3532 | ||
@@ -3466,7 +3654,7 @@ _wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) | |||
3466 | 3654 | ||
3467 | /* pending command count */ | 3655 | /* pending command count */ |
3468 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 3656 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
3469 | for (i = 0; i < ioc->request_depth; i++) | 3657 | for (i = 0; i < ioc->scsiio_depth; i++) |
3470 | if (ioc->scsi_lookup[i].cb_idx != 0xFF) | 3658 | if (ioc->scsi_lookup[i].cb_idx != 0xFF) |
3471 | ioc->pending_io_count++; | 3659 | ioc->pending_io_count++; |
3472 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | 3660 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); |
@@ -3490,7 +3678,7 @@ int | |||
3490 | mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | 3678 | mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, |
3491 | enum reset_type type) | 3679 | enum reset_type type) |
3492 | { | 3680 | { |
3493 | int r, i; | 3681 | int r; |
3494 | unsigned long flags; | 3682 | unsigned long flags; |
3495 | 3683 | ||
3496 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 3684 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, |
@@ -3513,9 +3701,7 @@ mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
3513 | if (r) | 3701 | if (r) |
3514 | goto out; | 3702 | goto out; |
3515 | _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); | 3703 | _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET); |
3516 | for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) | 3704 | r = _base_make_ioc_operational(ioc, sleep_flag); |
3517 | r = _base_make_ioc_operational(ioc, ioc->pfacts[i].VF_ID, | ||
3518 | sleep_flag); | ||
3519 | if (!r) | 3705 | if (!r) |
3520 | _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); | 3706 | _base_reset_handler(ioc, MPT2_IOC_DONE_RESET); |
3521 | out: | 3707 | out: |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index 2faab1e690e9..0cf6bc236e4d 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * for access to MPT (Message Passing Technology) firmware. | 3 | * for access to MPT (Message Passing Technology) firmware. |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.h | 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.h |
6 | * Copyright (C) 2007-2008 LSI Corporation | 6 | * Copyright (C) 2007-2009 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -69,10 +69,10 @@ | |||
69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" | 69 | #define MPT2SAS_DRIVER_NAME "mpt2sas" |
70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" | 70 | #define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>" |
71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" | 71 | #define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" |
72 | #define MPT2SAS_DRIVER_VERSION "01.100.06.00" | 72 | #define MPT2SAS_DRIVER_VERSION "02.100.03.00" |
73 | #define MPT2SAS_MAJOR_VERSION 01 | 73 | #define MPT2SAS_MAJOR_VERSION 02 |
74 | #define MPT2SAS_MINOR_VERSION 100 | 74 | #define MPT2SAS_MINOR_VERSION 100 |
75 | #define MPT2SAS_BUILD_VERSION 06 | 75 | #define MPT2SAS_BUILD_VERSION 03 |
76 | #define MPT2SAS_RELEASE_VERSION 00 | 76 | #define MPT2SAS_RELEASE_VERSION 00 |
77 | 77 | ||
78 | /* | 78 | /* |
@@ -264,6 +264,13 @@ struct _internal_cmd { | |||
264 | * SAS Topology Structures | 264 | * SAS Topology Structures |
265 | */ | 265 | */ |
266 | 266 | ||
267 | #define MPTSAS_STATE_TR_SEND 0x0001 | ||
268 | #define MPTSAS_STATE_TR_COMPLETE 0x0002 | ||
269 | #define MPTSAS_STATE_CNTRL_SEND 0x0004 | ||
270 | #define MPTSAS_STATE_CNTRL_COMPLETE 0x0008 | ||
271 | |||
272 | #define MPT2SAS_REQ_SAS_CNTRL 0x0010 | ||
273 | |||
267 | /** | 274 | /** |
268 | * struct _sas_device - attached device information | 275 | * struct _sas_device - attached device information |
269 | * @list: sas device list | 276 | * @list: sas device list |
@@ -300,6 +307,7 @@ struct _sas_device { | |||
300 | u16 slot; | 307 | u16 slot; |
301 | u8 hidden_raid_component; | 308 | u8 hidden_raid_component; |
302 | u8 responding; | 309 | u8 responding; |
310 | u16 state; | ||
303 | }; | 311 | }; |
304 | 312 | ||
305 | /** | 313 | /** |
@@ -436,6 +444,17 @@ struct request_tracker { | |||
436 | struct list_head tracker_list; | 444 | struct list_head tracker_list; |
437 | }; | 445 | }; |
438 | 446 | ||
447 | /** | ||
448 | * struct _tr_list - target reset list | ||
449 | * @handle: device handle | ||
450 | * @state: state machine | ||
451 | */ | ||
452 | struct _tr_list { | ||
453 | struct list_head list; | ||
454 | u16 handle; | ||
455 | u16 state; | ||
456 | }; | ||
457 | |||
439 | typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | 458 | typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); |
440 | 459 | ||
441 | /** | 460 | /** |
@@ -510,8 +529,9 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | |||
510 | * @config_page_sz: config page size | 529 | * @config_page_sz: config page size |
511 | * @config_page: reserve memory for config page payload | 530 | * @config_page: reserve memory for config page payload |
512 | * @config_page_dma: | 531 | * @config_page_dma: |
532 | * @hba_queue_depth: hba request queue depth | ||
513 | * @sge_size: sg element size for either 32/64 bit | 533 | * @sge_size: sg element size for either 32/64 bit |
514 | * @request_depth: hba request queue depth | 534 | * @scsiio_depth: SCSI_IO queue depth |
515 | * @request_sz: per request frame size | 535 | * @request_sz: per request frame size |
516 | * @request: pool of request frames | 536 | * @request: pool of request frames |
517 | * @request_dma: | 537 | * @request_dma: |
@@ -528,6 +548,18 @@ typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); | |||
528 | * @chains_needed_per_io: max chains per io | 548 | * @chains_needed_per_io: max chains per io |
529 | * @chain_offset_value_for_main_message: location 1st sg in main | 549 | * @chain_offset_value_for_main_message: location 1st sg in main |
530 | * @chain_depth: total chains allocated | 550 | * @chain_depth: total chains allocated |
551 | * @hi_priority_smid: | ||
552 | * @hi_priority: | ||
553 | * @hi_priority_dma: | ||
554 | * @hi_priority_depth: | ||
555 | * @hpr_lookup: | ||
556 | * @hpr_free_list: | ||
557 | * @internal_smid: | ||
558 | * @internal: | ||
559 | * @internal_dma: | ||
560 | * @internal_depth: | ||
561 | * @internal_lookup: | ||
562 | * @internal_free_list: | ||
531 | * @sense: pool of sense | 563 | * @sense: pool of sense |
532 | * @sense_dma: | 564 | * @sense_dma: |
533 | * @sense_dma_pool: | 565 | * @sense_dma_pool: |
@@ -597,6 +629,8 @@ struct MPT2SAS_ADAPTER { | |||
597 | u8 ctl_cb_idx; | 629 | u8 ctl_cb_idx; |
598 | u8 base_cb_idx; | 630 | u8 base_cb_idx; |
599 | u8 config_cb_idx; | 631 | u8 config_cb_idx; |
632 | u8 tm_tr_cb_idx; | ||
633 | u8 tm_sas_control_cb_idx; | ||
600 | struct _internal_cmd base_cmds; | 634 | struct _internal_cmd base_cmds; |
601 | struct _internal_cmd transport_cmds; | 635 | struct _internal_cmd transport_cmds; |
602 | struct _internal_cmd tm_cmds; | 636 | struct _internal_cmd tm_cmds; |
@@ -643,9 +677,10 @@ struct MPT2SAS_ADAPTER { | |||
643 | void *config_page; | 677 | void *config_page; |
644 | dma_addr_t config_page_dma; | 678 | dma_addr_t config_page_dma; |
645 | 679 | ||
646 | /* request */ | 680 | /* scsiio request */ |
681 | u16 hba_queue_depth; | ||
647 | u16 sge_size; | 682 | u16 sge_size; |
648 | u16 request_depth; | 683 | u16 scsiio_depth; |
649 | u16 request_sz; | 684 | u16 request_sz; |
650 | u8 *request; | 685 | u8 *request; |
651 | dma_addr_t request_dma; | 686 | dma_addr_t request_dma; |
@@ -665,6 +700,22 @@ struct MPT2SAS_ADAPTER { | |||
665 | u16 chain_offset_value_for_main_message; | 700 | u16 chain_offset_value_for_main_message; |
666 | u16 chain_depth; | 701 | u16 chain_depth; |
667 | 702 | ||
703 | /* hi-priority queue */ | ||
704 | u16 hi_priority_smid; | ||
705 | u8 *hi_priority; | ||
706 | dma_addr_t hi_priority_dma; | ||
707 | u16 hi_priority_depth; | ||
708 | struct request_tracker *hpr_lookup; | ||
709 | struct list_head hpr_free_list; | ||
710 | |||
711 | /* internal queue */ | ||
712 | u16 internal_smid; | ||
713 | u8 *internal; | ||
714 | dma_addr_t internal_dma; | ||
715 | u16 internal_depth; | ||
716 | struct request_tracker *internal_lookup; | ||
717 | struct list_head internal_free_list; | ||
718 | |||
668 | /* sense */ | 719 | /* sense */ |
669 | u8 *sense; | 720 | u8 *sense; |
670 | dma_addr_t sense_dma; | 721 | dma_addr_t sense_dma; |
@@ -690,6 +741,8 @@ struct MPT2SAS_ADAPTER { | |||
690 | struct dma_pool *reply_post_free_dma_pool; | 741 | struct dma_pool *reply_post_free_dma_pool; |
691 | u32 reply_post_host_index; | 742 | u32 reply_post_host_index; |
692 | 743 | ||
744 | struct list_head delayed_tr_list; | ||
745 | |||
693 | /* diag buffer support */ | 746 | /* diag buffer support */ |
694 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; | 747 | u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; |
695 | u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; | 748 | u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; |
@@ -701,7 +754,7 @@ struct MPT2SAS_ADAPTER { | |||
701 | u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; | 754 | u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; |
702 | }; | 755 | }; |
703 | 756 | ||
704 | typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | 757 | typedef u8 (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
705 | u32 reply); | 758 | u32 reply); |
706 | 759 | ||
707 | 760 | ||
@@ -720,22 +773,28 @@ int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag, | |||
720 | void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 773 | void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
721 | void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 774 | void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
722 | void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr); | 775 | void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr); |
723 | dma_addr_t mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 776 | dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, |
724 | dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 777 | u16 smid); |
778 | |||
779 | /* hi-priority queue */ | ||
780 | u16 mpt2sas_base_get_smid_hpr(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); | ||
781 | u16 mpt2sas_base_get_smid_scsiio(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx, | ||
782 | struct scsi_cmnd *scmd); | ||
725 | 783 | ||
726 | u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); | 784 | u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx); |
727 | void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid); | 785 | void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
728 | void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id, | 786 | void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, |
729 | u16 handle); | 787 | u16 handle); |
730 | void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id); | 788 | void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
731 | void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, | 789 | void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid, |
732 | u8 vf_id, u16 io_index); | 790 | u16 io_index); |
733 | void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id); | 791 | void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid); |
734 | void mpt2sas_base_initialize_callback_handler(void); | 792 | void mpt2sas_base_initialize_callback_handler(void); |
735 | u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func); | 793 | u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func); |
736 | void mpt2sas_base_release_callback_handler(u8 cb_idx); | 794 | void mpt2sas_base_release_callback_handler(u8 cb_idx); |
737 | 795 | ||
738 | void mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); | 796 | u8 mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
797 | u32 reply); | ||
739 | void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr); | 798 | void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr); |
740 | 799 | ||
741 | u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked); | 800 | u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked); |
@@ -749,6 +808,8 @@ int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc, | |||
749 | void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type); | 808 | void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type); |
750 | 809 | ||
751 | /* scsih shared API */ | 810 | /* scsih shared API */ |
811 | u8 mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, | ||
812 | u32 reply); | ||
752 | void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | 813 | void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, |
753 | u8 type, u16 smid_task, ulong timeout); | 814 | u8 type, u16 smid_task, ulong timeout); |
754 | void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); | 815 | void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle); |
@@ -760,11 +821,11 @@ struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAP | |||
760 | struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address( | 821 | struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address( |
761 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); | 822 | struct MPT2SAS_ADAPTER *ioc, u64 sas_address); |
762 | 823 | ||
763 | void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply); | ||
764 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | 824 | void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); |
765 | 825 | ||
766 | /* config shared API */ | 826 | /* config shared API */ |
767 | void mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); | 827 | u8 mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
828 | u32 reply); | ||
768 | int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys); | 829 | int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys); |
769 | int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, | 830 | int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc, |
770 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page); | 831 | Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page); |
@@ -817,14 +878,17 @@ extern struct device_attribute *mpt2sas_host_attrs[]; | |||
817 | extern struct device_attribute *mpt2sas_dev_attrs[]; | 878 | extern struct device_attribute *mpt2sas_dev_attrs[]; |
818 | void mpt2sas_ctl_init(void); | 879 | void mpt2sas_ctl_init(void); |
819 | void mpt2sas_ctl_exit(void); | 880 | void mpt2sas_ctl_exit(void); |
820 | void mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); | 881 | u8 mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
882 | u32 reply); | ||
821 | void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); | 883 | void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase); |
822 | void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply); | 884 | u8 mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, |
885 | u32 reply); | ||
823 | void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, | 886 | void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, |
824 | Mpi2EventNotificationReply_t *mpi_reply); | 887 | Mpi2EventNotificationReply_t *mpi_reply); |
825 | 888 | ||
826 | /* transport shared API */ | 889 | /* transport shared API */ |
827 | void mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply); | 890 | u8 mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
891 | u32 reply); | ||
828 | struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, | 892 | struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, |
829 | u16 handle, u16 parent_handle); | 893 | u16 handle, u16 parent_handle); |
830 | void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | 894 | void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, |
@@ -838,6 +902,8 @@ void mpt2sas_transport_update_links(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |||
838 | extern struct sas_function_template mpt2sas_transport_functions; | 902 | extern struct sas_function_template mpt2sas_transport_functions; |
839 | extern struct scsi_transport_template *mpt2sas_transport_template; | 903 | extern struct scsi_transport_template *mpt2sas_transport_template; |
840 | extern int scsi_internal_device_block(struct scsi_device *sdev); | 904 | extern int scsi_internal_device_block(struct scsi_device *sdev); |
905 | extern u8 mpt2sas_stm_zero_smid_handler(struct MPT2SAS_ADAPTER *ioc, | ||
906 | u8 msix_index, u32 reply); | ||
841 | extern int scsi_internal_device_unblock(struct scsi_device *sdev); | 907 | extern int scsi_internal_device_unblock(struct scsi_device *sdev); |
842 | 908 | ||
843 | #endif /* MPT2SAS_BASE_H_INCLUDED */ | 909 | #endif /* MPT2SAS_BASE_H_INCLUDED */ |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c index ab8c560865d8..594a389c6526 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_config.c +++ b/drivers/scsi/mpt2sas/mpt2sas_config.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * This module provides common API for accessing firmware configuration pages | 2 | * This module provides common API for accessing firmware configuration pages |
3 | * | 3 | * |
4 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c | 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_base.c |
5 | * Copyright (C) 2007-2008 LSI Corporation | 5 | * Copyright (C) 2007-2009 LSI Corporation |
6 | * (mailto:DL-MPTFusionLinux@lsi.com) | 6 | * (mailto:DL-MPTFusionLinux@lsi.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
@@ -227,23 +227,25 @@ _config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc, | |||
227 | * mpt2sas_config_done - config page completion routine | 227 | * mpt2sas_config_done - config page completion routine |
228 | * @ioc: per adapter object | 228 | * @ioc: per adapter object |
229 | * @smid: system request message index | 229 | * @smid: system request message index |
230 | * @VF_ID: virtual function id | 230 | * @msix_index: MSIX table index supplied by the OS |
231 | * @reply: reply message frame(lower 32bit addr) | 231 | * @reply: reply message frame(lower 32bit addr) |
232 | * Context: none. | 232 | * Context: none. |
233 | * | 233 | * |
234 | * The callback handler when using _config_request. | 234 | * The callback handler when using _config_request. |
235 | * | 235 | * |
236 | * Return nothing. | 236 | * Return 1 meaning mf should be freed from _base_interrupt |
237 | * 0 means the mf is freed from this function. | ||
237 | */ | 238 | */ |
238 | void | 239 | u8 |
239 | mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | 240 | mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
241 | u32 reply) | ||
240 | { | 242 | { |
241 | MPI2DefaultReply_t *mpi_reply; | 243 | MPI2DefaultReply_t *mpi_reply; |
242 | 244 | ||
243 | if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) | 245 | if (ioc->config_cmds.status == MPT2_CMD_NOT_USED) |
244 | return; | 246 | return 1; |
245 | if (ioc->config_cmds.smid != smid) | 247 | if (ioc->config_cmds.smid != smid) |
246 | return; | 248 | return 1; |
247 | ioc->config_cmds.status |= MPT2_CMD_COMPLETE; | 249 | ioc->config_cmds.status |= MPT2_CMD_COMPLETE; |
248 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 250 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
249 | if (mpi_reply) { | 251 | if (mpi_reply) { |
@@ -257,6 +259,7 @@ mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
257 | #endif | 259 | #endif |
258 | ioc->config_cmds.smid = USHORT_MAX; | 260 | ioc->config_cmds.smid = USHORT_MAX; |
259 | complete(&ioc->config_cmds.done); | 261 | complete(&ioc->config_cmds.done); |
262 | return 1; | ||
260 | } | 263 | } |
261 | 264 | ||
262 | /** | 265 | /** |
@@ -303,6 +306,9 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
303 | retry_count = 0; | 306 | retry_count = 0; |
304 | memset(&mem, 0, sizeof(struct config_request)); | 307 | memset(&mem, 0, sizeof(struct config_request)); |
305 | 308 | ||
309 | mpi_request->VF_ID = 0; /* TODO */ | ||
310 | mpi_request->VP_ID = 0; | ||
311 | |||
306 | if (config_page) { | 312 | if (config_page) { |
307 | mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion; | 313 | mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion; |
308 | mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber; | 314 | mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber; |
@@ -380,7 +386,7 @@ _config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t | |||
380 | _config_display_some_debug(ioc, smid, "config_request", NULL); | 386 | _config_display_some_debug(ioc, smid, "config_request", NULL); |
381 | #endif | 387 | #endif |
382 | init_completion(&ioc->config_cmds.done); | 388 | init_completion(&ioc->config_cmds.done); |
383 | mpt2sas_base_put_smid_default(ioc, smid, config_request->VF_ID); | 389 | mpt2sas_base_put_smid_default(ioc, smid); |
384 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, | 390 | timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, |
385 | timeout*HZ); | 391 | timeout*HZ); |
386 | if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) { | 392 | if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) { |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c index c2a51018910f..57d724633906 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.c +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * controllers | 3 | * controllers |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c | 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c |
6 | * Copyright (C) 2007-2008 LSI Corporation | 6 | * Copyright (C) 2007-2009 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
@@ -219,23 +219,25 @@ _ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid, | |||
219 | * mpt2sas_ctl_done - ctl module completion routine | 219 | * mpt2sas_ctl_done - ctl module completion routine |
220 | * @ioc: per adapter object | 220 | * @ioc: per adapter object |
221 | * @smid: system request message index | 221 | * @smid: system request message index |
222 | * @VF_ID: virtual function id | 222 | * @msix_index: MSIX table index supplied by the OS |
223 | * @reply: reply message frame(lower 32bit addr) | 223 | * @reply: reply message frame(lower 32bit addr) |
224 | * Context: none. | 224 | * Context: none. |
225 | * | 225 | * |
226 | * The callback handler when using ioc->ctl_cb_idx. | 226 | * The callback handler when using ioc->ctl_cb_idx. |
227 | * | 227 | * |
228 | * Return nothing. | 228 | * Return 1 meaning mf should be freed from _base_interrupt |
229 | * 0 means the mf is freed from this function. | ||
229 | */ | 230 | */ |
230 | void | 231 | u8 |
231 | mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | 232 | mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
233 | u32 reply) | ||
232 | { | 234 | { |
233 | MPI2DefaultReply_t *mpi_reply; | 235 | MPI2DefaultReply_t *mpi_reply; |
234 | 236 | ||
235 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) | 237 | if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED) |
236 | return; | 238 | return 1; |
237 | if (ioc->ctl_cmds.smid != smid) | 239 | if (ioc->ctl_cmds.smid != smid) |
238 | return; | 240 | return 1; |
239 | ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; | 241 | ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE; |
240 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 242 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
241 | if (mpi_reply) { | 243 | if (mpi_reply) { |
@@ -247,6 +249,7 @@ mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
247 | #endif | 249 | #endif |
248 | ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; | 250 | ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING; |
249 | complete(&ioc->ctl_cmds.done); | 251 | complete(&ioc->ctl_cmds.done); |
252 | return 1; | ||
250 | } | 253 | } |
251 | 254 | ||
252 | /** | 255 | /** |
@@ -328,22 +331,25 @@ mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc, | |||
328 | /** | 331 | /** |
329 | * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time) | 332 | * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time) |
330 | * @ioc: per adapter object | 333 | * @ioc: per adapter object |
331 | * @VF_ID: virtual function id | 334 | * @msix_index: MSIX table index supplied by the OS |
332 | * @reply: reply message frame(lower 32bit addr) | 335 | * @reply: reply message frame(lower 32bit addr) |
333 | * Context: interrupt. | 336 | * Context: interrupt. |
334 | * | 337 | * |
335 | * This function merely adds a new work task into ioc->firmware_event_thread. | 338 | * This function merely adds a new work task into ioc->firmware_event_thread. |
336 | * The tasks are worked from _firmware_event_work in user context. | 339 | * The tasks are worked from _firmware_event_work in user context. |
337 | * | 340 | * |
338 | * Return nothing. | 341 | * Return 1 meaning mf should be freed from _base_interrupt |
342 | * 0 means the mf is freed from this function. | ||
339 | */ | 343 | */ |
340 | void | 344 | u8 |
341 | mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | 345 | mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, |
346 | u32 reply) | ||
342 | { | 347 | { |
343 | Mpi2EventNotificationReply_t *mpi_reply; | 348 | Mpi2EventNotificationReply_t *mpi_reply; |
344 | 349 | ||
345 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 350 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
346 | mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); | 351 | mpt2sas_ctl_add_to_event_log(ioc, mpi_reply); |
352 | return 1; | ||
347 | } | 353 | } |
348 | 354 | ||
349 | /** | 355 | /** |
@@ -507,7 +513,7 @@ _ctl_set_task_mid(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg, | |||
507 | 513 | ||
508 | handle = le16_to_cpu(tm_request->DevHandle); | 514 | handle = le16_to_cpu(tm_request->DevHandle); |
509 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 515 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
510 | for (i = ioc->request_depth; i && !found; i--) { | 516 | for (i = ioc->scsiio_depth; i && !found; i--) { |
511 | scmd = ioc->scsi_lookup[i - 1].scmd; | 517 | scmd = ioc->scsi_lookup[i - 1].scmd; |
512 | if (scmd == NULL || scmd->device == NULL || | 518 | if (scmd == NULL || scmd->device == NULL || |
513 | scmd->device->hostdata == NULL) | 519 | scmd->device->hostdata == NULL) |
@@ -614,7 +620,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
614 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", | 620 | printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n", |
615 | ioc->name, __func__); | 621 | ioc->name, __func__); |
616 | 622 | ||
617 | smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx); | 623 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); |
618 | if (!smid) { | 624 | if (!smid) { |
619 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 625 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
620 | ioc->name, __func__); | 626 | ioc->name, __func__); |
@@ -737,7 +743,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
737 | (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); | 743 | (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid); |
738 | priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); | 744 | priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid); |
739 | memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); | 745 | memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE); |
740 | mpt2sas_base_put_smid_scsi_io(ioc, smid, 0, | 746 | mpt2sas_base_put_smid_scsi_io(ioc, smid, |
741 | le16_to_cpu(mpi_request->FunctionDependent1)); | 747 | le16_to_cpu(mpi_request->FunctionDependent1)); |
742 | break; | 748 | break; |
743 | } | 749 | } |
@@ -759,8 +765,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
759 | mutex_lock(&ioc->tm_cmds.mutex); | 765 | mutex_lock(&ioc->tm_cmds.mutex); |
760 | mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu( | 766 | mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu( |
761 | tm_request->DevHandle)); | 767 | tm_request->DevHandle)); |
762 | mpt2sas_base_put_smid_hi_priority(ioc, smid, | 768 | mpt2sas_base_put_smid_hi_priority(ioc, smid); |
763 | mpi_request->VF_ID); | ||
764 | break; | 769 | break; |
765 | } | 770 | } |
766 | case MPI2_FUNCTION_SMP_PASSTHROUGH: | 771 | case MPI2_FUNCTION_SMP_PASSTHROUGH: |
@@ -781,7 +786,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
781 | ioc->ioc_link_reset_in_progress = 1; | 786 | ioc->ioc_link_reset_in_progress = 1; |
782 | ioc->ignore_loginfos = 1; | 787 | ioc->ignore_loginfos = 1; |
783 | } | 788 | } |
784 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 789 | mpt2sas_base_put_smid_default(ioc, smid); |
785 | break; | 790 | break; |
786 | } | 791 | } |
787 | case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: | 792 | case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: |
@@ -795,11 +800,11 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
795 | ioc->ioc_link_reset_in_progress = 1; | 800 | ioc->ioc_link_reset_in_progress = 1; |
796 | ioc->ignore_loginfos = 1; | 801 | ioc->ignore_loginfos = 1; |
797 | } | 802 | } |
798 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 803 | mpt2sas_base_put_smid_default(ioc, smid); |
799 | break; | 804 | break; |
800 | } | 805 | } |
801 | default: | 806 | default: |
802 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 807 | mpt2sas_base_put_smid_default(ioc, smid); |
803 | break; | 808 | break; |
804 | } | 809 | } |
805 | 810 | ||
@@ -807,6 +812,7 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc, | |||
807 | timeout = MPT2_IOCTL_DEFAULT_TIMEOUT; | 812 | timeout = MPT2_IOCTL_DEFAULT_TIMEOUT; |
808 | else | 813 | else |
809 | timeout = karg.timeout; | 814 | timeout = karg.timeout; |
815 | init_completion(&ioc->ctl_cmds.done); | ||
810 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 816 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
811 | timeout*HZ); | 817 | timeout*HZ); |
812 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { | 818 | if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { |
@@ -1371,6 +1377,8 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1371 | mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags); | 1377 | mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags); |
1372 | mpi_request->BufferAddress = cpu_to_le64(request_data_dma); | 1378 | mpi_request->BufferAddress = cpu_to_le64(request_data_dma); |
1373 | mpi_request->BufferLength = cpu_to_le32(request_data_sz); | 1379 | mpi_request->BufferLength = cpu_to_le32(request_data_sz); |
1380 | mpi_request->VF_ID = 0; /* TODO */ | ||
1381 | mpi_request->VP_ID = 0; | ||
1374 | 1382 | ||
1375 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), " | 1383 | dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), " |
1376 | "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, | 1384 | "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data, |
@@ -1380,7 +1388,8 @@ _ctl_diag_register(void __user *arg, enum block_state state) | |||
1380 | mpi_request->ProductSpecific[i] = | 1388 | mpi_request->ProductSpecific[i] = |
1381 | cpu_to_le32(ioc->product_specific[buffer_type][i]); | 1389 | cpu_to_le32(ioc->product_specific[buffer_type][i]); |
1382 | 1390 | ||
1383 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 1391 | mpt2sas_base_put_smid_default(ioc, smid); |
1392 | init_completion(&ioc->ctl_cmds.done); | ||
1384 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1393 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
1385 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | 1394 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); |
1386 | 1395 | ||
@@ -1643,8 +1652,11 @@ _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset) | |||
1643 | 1652 | ||
1644 | mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; | 1653 | mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; |
1645 | mpi_request->BufferType = buffer_type; | 1654 | mpi_request->BufferType = buffer_type; |
1655 | mpi_request->VF_ID = 0; /* TODO */ | ||
1656 | mpi_request->VP_ID = 0; | ||
1646 | 1657 | ||
1647 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 1658 | mpt2sas_base_put_smid_default(ioc, smid); |
1659 | init_completion(&ioc->ctl_cmds.done); | ||
1648 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1660 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
1649 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | 1661 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); |
1650 | 1662 | ||
@@ -1902,8 +1914,11 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state) | |||
1902 | for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) | 1914 | for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++) |
1903 | mpi_request->ProductSpecific[i] = | 1915 | mpi_request->ProductSpecific[i] = |
1904 | cpu_to_le32(ioc->product_specific[buffer_type][i]); | 1916 | cpu_to_le32(ioc->product_specific[buffer_type][i]); |
1917 | mpi_request->VF_ID = 0; /* TODO */ | ||
1918 | mpi_request->VP_ID = 0; | ||
1905 | 1919 | ||
1906 | mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID); | 1920 | mpt2sas_base_put_smid_default(ioc, smid); |
1921 | init_completion(&ioc->ctl_cmds.done); | ||
1907 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, | 1922 | timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, |
1908 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); | 1923 | MPT2_IOCTL_DEFAULT_TIMEOUT*HZ); |
1909 | 1924 | ||
@@ -2069,6 +2084,7 @@ static long | |||
2069 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 2084 | _ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
2070 | { | 2085 | { |
2071 | long ret; | 2086 | long ret; |
2087 | |||
2072 | lock_kernel(); | 2088 | lock_kernel(); |
2073 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg); | 2089 | ret = _ctl_ioctl_main(file, cmd, (void __user *)arg); |
2074 | unlock_kernel(); | 2090 | unlock_kernel(); |
@@ -2143,6 +2159,7 @@ static long | |||
2143 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) | 2159 | _ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) |
2144 | { | 2160 | { |
2145 | long ret; | 2161 | long ret; |
2162 | |||
2146 | lock_kernel(); | 2163 | lock_kernel(); |
2147 | if (cmd == MPT2COMMAND32) | 2164 | if (cmd == MPT2COMMAND32) |
2148 | ret = _ctl_compat_mpt_command(file, cmd, arg); | 2165 | ret = _ctl_compat_mpt_command(file, cmd, arg); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h index 4da11435533f..211f296dd191 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_ctl.h +++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h | |||
@@ -3,7 +3,7 @@ | |||
3 | * controllers | 3 | * controllers |
4 | * | 4 | * |
5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h | 5 | * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h |
6 | * Copyright (C) 2007-2008 LSI Corporation | 6 | * Copyright (C) 2007-2009 LSI Corporation |
7 | * (mailto:DL-MPTFusionLinux@lsi.com) | 7 | * (mailto:DL-MPTFusionLinux@lsi.com) |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h index ad325096e842..5308a25cb307 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_debug.h +++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h | |||
@@ -2,7 +2,7 @@ | |||
2 | * Logging Support for MPT (Message Passing Technology) based controllers | 2 | * Logging Support for MPT (Message Passing Technology) based controllers |
3 | * | 3 | * |
4 | * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c | 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c |
5 | * Copyright (C) 2007-2008 LSI Corporation | 5 | * Copyright (C) 2007-2009 LSI Corporation |
6 | * (mailto:DL-MPTFusionLinux@lsi.com) | 6 | * (mailto:DL-MPTFusionLinux@lsi.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 774b34525bba..86ab32d7ab15 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Scsi Host Layer for MPT (Message Passing Technology) based controllers | 2 | * Scsi Host Layer for MPT (Message Passing Technology) based controllers |
3 | * | 3 | * |
4 | * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c | 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c |
5 | * Copyright (C) 2007-2008 LSI Corporation | 5 | * Copyright (C) 2007-2009 LSI Corporation |
6 | * (mailto:DL-MPTFusionLinux@lsi.com) | 6 | * (mailto:DL-MPTFusionLinux@lsi.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
@@ -79,6 +79,9 @@ static u8 transport_cb_idx = -1; | |||
79 | static u8 config_cb_idx = -1; | 79 | static u8 config_cb_idx = -1; |
80 | static int mpt_ids; | 80 | static int mpt_ids; |
81 | 81 | ||
82 | static u8 tm_tr_cb_idx = -1 ; | ||
83 | static u8 tm_sas_control_cb_idx = -1; | ||
84 | |||
82 | /* command line options */ | 85 | /* command line options */ |
83 | static u32 logging_level; | 86 | static u32 logging_level; |
84 | MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " | 87 | MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info " |
@@ -109,6 +112,7 @@ struct sense_info { | |||
109 | * @work: work object (ioc->fault_reset_work_q) | 112 | * @work: work object (ioc->fault_reset_work_q) |
110 | * @ioc: per adapter object | 113 | * @ioc: per adapter object |
111 | * @VF_ID: virtual function id | 114 | * @VF_ID: virtual function id |
115 | * @VP_ID: virtual port id | ||
112 | * @host_reset_handling: handling events during host reset | 116 | * @host_reset_handling: handling events during host reset |
113 | * @ignore: flag meaning this event has been marked to ignore | 117 | * @ignore: flag meaning this event has been marked to ignore |
114 | * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h | 118 | * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h |
@@ -121,6 +125,7 @@ struct fw_event_work { | |||
121 | struct work_struct work; | 125 | struct work_struct work; |
122 | struct MPT2SAS_ADAPTER *ioc; | 126 | struct MPT2SAS_ADAPTER *ioc; |
123 | u8 VF_ID; | 127 | u8 VF_ID; |
128 | u8 VP_ID; | ||
124 | u8 host_reset_handling; | 129 | u8 host_reset_handling; |
125 | u8 ignore; | 130 | u8 ignore; |
126 | u16 event; | 131 | u16 event; |
@@ -138,8 +143,10 @@ struct fw_event_work { | |||
138 | * @lun: lun number | 143 | * @lun: lun number |
139 | * @cdb_length: cdb length | 144 | * @cdb_length: cdb length |
140 | * @cdb: cdb contents | 145 | * @cdb: cdb contents |
141 | * @valid_reply: flag set for reply message | ||
142 | * @timeout: timeout for this command | 146 | * @timeout: timeout for this command |
147 | * @VF_ID: virtual function id | ||
148 | * @VP_ID: virtual port id | ||
149 | * @valid_reply: flag set for reply message | ||
143 | * @sense_length: sense length | 150 | * @sense_length: sense length |
144 | * @ioc_status: ioc status | 151 | * @ioc_status: ioc status |
145 | * @scsi_state: scsi state | 152 | * @scsi_state: scsi state |
@@ -161,6 +168,8 @@ struct _scsi_io_transfer { | |||
161 | u8 cdb_length; | 168 | u8 cdb_length; |
162 | u8 cdb[32]; | 169 | u8 cdb[32]; |
163 | u8 timeout; | 170 | u8 timeout; |
171 | u8 VF_ID; | ||
172 | u8 VP_ID; | ||
164 | u8 valid_reply; | 173 | u8 valid_reply; |
165 | /* the following bits are only valid when 'valid_reply = 1' */ | 174 | /* the following bits are only valid when 'valid_reply = 1' */ |
166 | u32 sense_length; | 175 | u32 sense_length; |
@@ -756,66 +765,16 @@ _scsih_is_end_device(u32 device_info) | |||
756 | } | 765 | } |
757 | 766 | ||
758 | /** | 767 | /** |
759 | * _scsih_scsi_lookup_get - returns scmd entry | 768 | * mptscsih_get_scsi_lookup - returns scmd entry |
760 | * @ioc: per adapter object | 769 | * @ioc: per adapter object |
761 | * @smid: system request message index | 770 | * @smid: system request message index |
762 | * Context: This function will acquire ioc->scsi_lookup_lock. | ||
763 | * | 771 | * |
764 | * Returns the smid stored scmd pointer. | 772 | * Returns the smid stored scmd pointer. |
765 | */ | 773 | */ |
766 | static struct scsi_cmnd * | 774 | static struct scsi_cmnd * |
767 | _scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) | 775 | _scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid) |
768 | { | 776 | { |
769 | unsigned long flags; | 777 | return ioc->scsi_lookup[smid - 1].scmd; |
770 | struct scsi_cmnd *scmd; | ||
771 | |||
772 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
773 | scmd = ioc->scsi_lookup[smid - 1].scmd; | ||
774 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
775 | return scmd; | ||
776 | } | ||
777 | |||
778 | /** | ||
779 | * mptscsih_getclear_scsi_lookup - returns scmd entry | ||
780 | * @ioc: per adapter object | ||
781 | * @smid: system request message index | ||
782 | * Context: This function will acquire ioc->scsi_lookup_lock. | ||
783 | * | ||
784 | * Returns the smid stored scmd pointer, as well as clearing the scmd pointer. | ||
785 | */ | ||
786 | static struct scsi_cmnd * | ||
787 | _scsih_scsi_lookup_getclear(struct MPT2SAS_ADAPTER *ioc, u16 smid) | ||
788 | { | ||
789 | unsigned long flags; | ||
790 | struct scsi_cmnd *scmd; | ||
791 | |||
792 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
793 | scmd = ioc->scsi_lookup[smid - 1].scmd; | ||
794 | ioc->scsi_lookup[smid - 1].scmd = NULL; | ||
795 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
796 | return scmd; | ||
797 | } | ||
798 | |||
799 | /** | ||
800 | * _scsih_scsi_lookup_set - updates scmd entry in lookup | ||
801 | * @ioc: per adapter object | ||
802 | * @smid: system request message index | ||
803 | * @scmd: pointer to scsi command object | ||
804 | * Context: This function will acquire ioc->scsi_lookup_lock. | ||
805 | * | ||
806 | * This will save scmd pointer in the scsi_lookup array. | ||
807 | * | ||
808 | * Return nothing. | ||
809 | */ | ||
810 | static void | ||
811 | _scsih_scsi_lookup_set(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
812 | struct scsi_cmnd *scmd) | ||
813 | { | ||
814 | unsigned long flags; | ||
815 | |||
816 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | ||
817 | ioc->scsi_lookup[smid - 1].scmd = scmd; | ||
818 | spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); | ||
819 | } | 778 | } |
820 | 779 | ||
821 | /** | 780 | /** |
@@ -838,9 +797,9 @@ _scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd | |||
838 | 797 | ||
839 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 798 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
840 | smid = 0; | 799 | smid = 0; |
841 | for (i = 0; i < ioc->request_depth; i++) { | 800 | for (i = 0; i < ioc->scsiio_depth; i++) { |
842 | if (ioc->scsi_lookup[i].scmd == scmd) { | 801 | if (ioc->scsi_lookup[i].scmd == scmd) { |
843 | smid = i + 1; | 802 | smid = ioc->scsi_lookup[i].smid; |
844 | goto out; | 803 | goto out; |
845 | } | 804 | } |
846 | } | 805 | } |
@@ -869,7 +828,7 @@ _scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id, | |||
869 | 828 | ||
870 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 829 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
871 | found = 0; | 830 | found = 0; |
872 | for (i = 0 ; i < ioc->request_depth; i++) { | 831 | for (i = 0 ; i < ioc->scsiio_depth; i++) { |
873 | if (ioc->scsi_lookup[i].scmd && | 832 | if (ioc->scsi_lookup[i].scmd && |
874 | (ioc->scsi_lookup[i].scmd->device->id == id && | 833 | (ioc->scsi_lookup[i].scmd->device->id == id && |
875 | ioc->scsi_lookup[i].scmd->device->channel == channel)) { | 834 | ioc->scsi_lookup[i].scmd->device->channel == channel)) { |
@@ -903,7 +862,7 @@ _scsih_scsi_lookup_find_by_lun(struct MPT2SAS_ADAPTER *ioc, int id, | |||
903 | 862 | ||
904 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); | 863 | spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); |
905 | found = 0; | 864 | found = 0; |
906 | for (i = 0 ; i < ioc->request_depth; i++) { | 865 | for (i = 0 ; i < ioc->scsiio_depth; i++) { |
907 | if (ioc->scsi_lookup[i].scmd && | 866 | if (ioc->scsi_lookup[i].scmd && |
908 | (ioc->scsi_lookup[i].scmd->device->id == id && | 867 | (ioc->scsi_lookup[i].scmd->device->id == id && |
909 | ioc->scsi_lookup[i].scmd->device->channel == channel && | 868 | ioc->scsi_lookup[i].scmd->device->channel == channel && |
@@ -1113,7 +1072,7 @@ _scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) | |||
1113 | } | 1072 | } |
1114 | 1073 | ||
1115 | /** | 1074 | /** |
1116 | * _scsih_change_queue_depth - changing device queue tag type | 1075 | * _scsih_change_queue_type - changing device queue tag type |
1117 | * @sdev: scsi device struct | 1076 | * @sdev: scsi device struct |
1118 | * @tag_type: requested tag type | 1077 | * @tag_type: requested tag type |
1119 | * | 1078 | * |
@@ -1679,23 +1638,24 @@ _scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code) | |||
1679 | * _scsih_tm_done - tm completion routine | 1638 | * _scsih_tm_done - tm completion routine |
1680 | * @ioc: per adapter object | 1639 | * @ioc: per adapter object |
1681 | * @smid: system request message index | 1640 | * @smid: system request message index |
1682 | * @VF_ID: virtual function id | 1641 | * @msix_index: MSIX table index supplied by the OS |
1683 | * @reply: reply message frame(lower 32bit addr) | 1642 | * @reply: reply message frame(lower 32bit addr) |
1684 | * Context: none. | 1643 | * Context: none. |
1685 | * | 1644 | * |
1686 | * The callback handler when using scsih_issue_tm. | 1645 | * The callback handler when using scsih_issue_tm. |
1687 | * | 1646 | * |
1688 | * Return nothing. | 1647 | * Return 1 meaning mf should be freed from _base_interrupt |
1648 | * 0 means the mf is freed from this function. | ||
1689 | */ | 1649 | */ |
1690 | static void | 1650 | static u8 |
1691 | _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | 1651 | _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) |
1692 | { | 1652 | { |
1693 | MPI2DefaultReply_t *mpi_reply; | 1653 | MPI2DefaultReply_t *mpi_reply; |
1694 | 1654 | ||
1695 | if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED) | 1655 | if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED) |
1696 | return; | 1656 | return 1; |
1697 | if (ioc->tm_cmds.smid != smid) | 1657 | if (ioc->tm_cmds.smid != smid) |
1698 | return; | 1658 | return 1; |
1699 | ioc->tm_cmds.status |= MPT2_CMD_COMPLETE; | 1659 | ioc->tm_cmds.status |= MPT2_CMD_COMPLETE; |
1700 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 1660 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
1701 | if (mpi_reply) { | 1661 | if (mpi_reply) { |
@@ -1704,6 +1664,7 @@ _scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
1704 | } | 1664 | } |
1705 | ioc->tm_cmds.status &= ~MPT2_CMD_PENDING; | 1665 | ioc->tm_cmds.status &= ~MPT2_CMD_PENDING; |
1706 | complete(&ioc->tm_cmds.done); | 1666 | complete(&ioc->tm_cmds.done); |
1667 | return 1; | ||
1707 | } | 1668 | } |
1708 | 1669 | ||
1709 | /** | 1670 | /** |
@@ -1790,7 +1751,6 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | |||
1790 | u16 smid = 0; | 1751 | u16 smid = 0; |
1791 | u32 ioc_state; | 1752 | u32 ioc_state; |
1792 | unsigned long timeleft; | 1753 | unsigned long timeleft; |
1793 | u8 VF_ID = 0; | ||
1794 | 1754 | ||
1795 | if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) { | 1755 | if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED) { |
1796 | printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n", | 1756 | printk(MPT2SAS_INFO_FMT "%s: tm_cmd busy!!!\n", |
@@ -1817,7 +1777,7 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | |||
1817 | goto issue_host_reset; | 1777 | goto issue_host_reset; |
1818 | } | 1778 | } |
1819 | 1779 | ||
1820 | smid = mpt2sas_base_get_smid(ioc, ioc->tm_cb_idx); | 1780 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx); |
1821 | if (!smid) { | 1781 | if (!smid) { |
1822 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 1782 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
1823 | ioc->name, __func__); | 1783 | ioc->name, __func__); |
@@ -1825,7 +1785,8 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | |||
1825 | } | 1785 | } |
1826 | 1786 | ||
1827 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x)," | 1787 | dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x)," |
1828 | " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, smid)); | 1788 | " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, |
1789 | smid_task)); | ||
1829 | ioc->tm_cmds.status = MPT2_CMD_PENDING; | 1790 | ioc->tm_cmds.status = MPT2_CMD_PENDING; |
1830 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 1791 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
1831 | ioc->tm_cmds.smid = smid; | 1792 | ioc->tm_cmds.smid = smid; |
@@ -1834,10 +1795,12 @@ mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun, | |||
1834 | mpi_request->DevHandle = cpu_to_le16(handle); | 1795 | mpi_request->DevHandle = cpu_to_le16(handle); |
1835 | mpi_request->TaskType = type; | 1796 | mpi_request->TaskType = type; |
1836 | mpi_request->TaskMID = cpu_to_le16(smid_task); | 1797 | mpi_request->TaskMID = cpu_to_le16(smid_task); |
1798 | mpi_request->VP_ID = 0; /* TODO */ | ||
1799 | mpi_request->VF_ID = 0; | ||
1837 | int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); | 1800 | int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); |
1838 | mpt2sas_scsih_set_tm_flag(ioc, handle); | 1801 | mpt2sas_scsih_set_tm_flag(ioc, handle); |
1839 | init_completion(&ioc->tm_cmds.done); | 1802 | init_completion(&ioc->tm_cmds.done); |
1840 | mpt2sas_base_put_smid_hi_priority(ioc, smid, VF_ID); | 1803 | mpt2sas_base_put_smid_hi_priority(ioc, smid); |
1841 | timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); | 1804 | timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); |
1842 | mpt2sas_scsih_clear_tm_flag(ioc, handle); | 1805 | mpt2sas_scsih_clear_tm_flag(ioc, handle); |
1843 | if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) { | 1806 | if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) { |
@@ -2075,7 +2038,7 @@ _scsih_target_reset(struct scsi_cmnd *scmd) | |||
2075 | } | 2038 | } |
2076 | 2039 | ||
2077 | /** | 2040 | /** |
2078 | * _scsih_abort - eh threads main host reset routine | 2041 | * _scsih_host_reset - eh threads main host reset routine |
2079 | * @sdev: scsi device struct | 2042 | * @sdev: scsi device struct |
2080 | * | 2043 | * |
2081 | * Returns SUCCESS if command aborted else FAILED | 2044 | * Returns SUCCESS if command aborted else FAILED |
@@ -2354,6 +2317,231 @@ _scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc, | |||
2354 | } | 2317 | } |
2355 | 2318 | ||
2356 | /** | 2319 | /** |
2320 | * _scsih_tm_tr_send - send task management request | ||
2321 | * @ioc: per adapter object | ||
2322 | * @handle: device handle | ||
2323 | * Context: interrupt time. | ||
2324 | * | ||
2325 | * This code is to initiate the device removal handshake protocal | ||
2326 | * with controller firmware. This function will issue target reset | ||
2327 | * using high priority request queue. It will send a sas iounit | ||
2328 | * controll request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. | ||
2329 | * | ||
2330 | * This is designed to send muliple task management request at the same | ||
2331 | * time to the fifo. If the fifo is full, we will append the request, | ||
2332 | * and process it in a future completion. | ||
2333 | */ | ||
2334 | static void | ||
2335 | _scsih_tm_tr_send(struct MPT2SAS_ADAPTER *ioc, u16 handle) | ||
2336 | { | ||
2337 | Mpi2SCSITaskManagementRequest_t *mpi_request; | ||
2338 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
2339 | u16 smid; | ||
2340 | struct _sas_device *sas_device; | ||
2341 | unsigned long flags; | ||
2342 | struct _tr_list *delayed_tr; | ||
2343 | |||
2344 | if (ioc->shost_recovery) { | ||
2345 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
2346 | __func__, ioc->name); | ||
2347 | return; | ||
2348 | } | ||
2349 | |||
2350 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
2351 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
2352 | if (!sas_device) { | ||
2353 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2354 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2355 | ioc->name, __func__); | ||
2356 | return; | ||
2357 | } | ||
2358 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2359 | |||
2360 | /* skip is hidden raid component */ | ||
2361 | if (sas_device->hidden_raid_component) | ||
2362 | return; | ||
2363 | |||
2364 | smid = mpt2sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); | ||
2365 | if (!smid) { | ||
2366 | delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); | ||
2367 | if (!delayed_tr) | ||
2368 | return; | ||
2369 | INIT_LIST_HEAD(&delayed_tr->list); | ||
2370 | delayed_tr->handle = handle; | ||
2371 | delayed_tr->state = MPT2SAS_REQ_SAS_CNTRL; | ||
2372 | list_add_tail(&delayed_tr->list, | ||
2373 | &ioc->delayed_tr_list); | ||
2374 | if (sas_device->starget) | ||
2375 | dewtprintk(ioc, starget_printk(KERN_INFO, | ||
2376 | sas_device->starget, "DELAYED:tr:handle(0x%04x), " | ||
2377 | "(open)\n", sas_device->handle)); | ||
2378 | return; | ||
2379 | } | ||
2380 | |||
2381 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
2382 | sas_target_priv_data = sas_device->starget->hostdata; | ||
2383 | sas_target_priv_data->tm_busy = 1; | ||
2384 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | ||
2385 | "tr:handle(0x%04x), (open)\n", sas_device->handle)); | ||
2386 | } | ||
2387 | |||
2388 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | ||
2389 | memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); | ||
2390 | mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; | ||
2391 | mpi_request->DevHandle = cpu_to_le16(handle); | ||
2392 | mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; | ||
2393 | sas_device->state |= MPTSAS_STATE_TR_SEND; | ||
2394 | sas_device->state |= MPT2SAS_REQ_SAS_CNTRL; | ||
2395 | mpt2sas_base_put_smid_hi_priority(ioc, smid); | ||
2396 | } | ||
2397 | |||
2398 | |||
2399 | |||
2400 | /** | ||
2401 | * _scsih_sas_control_complete - completion routine | ||
2402 | * @ioc: per adapter object | ||
2403 | * @smid: system request message index | ||
2404 | * @msix_index: MSIX table index supplied by the OS | ||
2405 | * @reply: reply message frame(lower 32bit addr) | ||
2406 | * Context: interrupt time. | ||
2407 | * | ||
2408 | * This is the sas iounit controll completion routine. | ||
2409 | * This code is part of the code to initiate the device removal | ||
2410 | * handshake protocal with controller firmware. | ||
2411 | * | ||
2412 | * Return 1 meaning mf should be freed from _base_interrupt | ||
2413 | * 0 means the mf is freed from this function. | ||
2414 | */ | ||
2415 | static u8 | ||
2416 | _scsih_sas_control_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, | ||
2417 | u8 msix_index, u32 reply) | ||
2418 | { | ||
2419 | unsigned long flags; | ||
2420 | u16 handle; | ||
2421 | struct _sas_device *sas_device; | ||
2422 | Mpi2SasIoUnitControlReply_t *mpi_reply = | ||
2423 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
2424 | |||
2425 | handle = le16_to_cpu(mpi_reply->DevHandle); | ||
2426 | |||
2427 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
2428 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
2429 | if (!sas_device) { | ||
2430 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2431 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2432 | ioc->name, __func__); | ||
2433 | return 1; | ||
2434 | } | ||
2435 | sas_device->state |= MPTSAS_STATE_CNTRL_COMPLETE; | ||
2436 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2437 | |||
2438 | if (sas_device->starget) | ||
2439 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | ||
2440 | "sc_complete:handle(0x%04x), " | ||
2441 | "ioc_status(0x%04x), loginfo(0x%08x)\n", | ||
2442 | handle, le16_to_cpu(mpi_reply->IOCStatus), | ||
2443 | le32_to_cpu(mpi_reply->IOCLogInfo))); | ||
2444 | return 1; | ||
2445 | } | ||
2446 | |||
2447 | /** | ||
2448 | * _scsih_tm_tr_complete - | ||
2449 | * @ioc: per adapter object | ||
2450 | * @smid: system request message index | ||
2451 | * @msix_index: MSIX table index supplied by the OS | ||
2452 | * @reply: reply message frame(lower 32bit addr) | ||
2453 | * Context: interrupt time. | ||
2454 | * | ||
2455 | * This is the target reset completion routine. | ||
2456 | * This code is part of the code to initiate the device removal | ||
2457 | * handshake protocal with controller firmware. | ||
2458 | * It will send a sas iounit controll request (MPI2_SAS_OP_REMOVE_DEVICE) | ||
2459 | * | ||
2460 | * Return 1 meaning mf should be freed from _base_interrupt | ||
2461 | * 0 means the mf is freed from this function. | ||
2462 | */ | ||
2463 | static u8 | ||
2464 | _scsih_tm_tr_complete(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, | ||
2465 | u32 reply) | ||
2466 | { | ||
2467 | unsigned long flags; | ||
2468 | u16 handle; | ||
2469 | struct _sas_device *sas_device; | ||
2470 | Mpi2SCSITaskManagementReply_t *mpi_reply = | ||
2471 | mpt2sas_base_get_reply_virt_addr(ioc, reply); | ||
2472 | Mpi2SasIoUnitControlRequest_t *mpi_request; | ||
2473 | u16 smid_sas_ctrl; | ||
2474 | struct MPT2SAS_TARGET *sas_target_priv_data; | ||
2475 | struct _tr_list *delayed_tr; | ||
2476 | u8 rc; | ||
2477 | |||
2478 | handle = le16_to_cpu(mpi_reply->DevHandle); | ||
2479 | spin_lock_irqsave(&ioc->sas_device_lock, flags); | ||
2480 | sas_device = _scsih_sas_device_find_by_handle(ioc, handle); | ||
2481 | if (!sas_device) { | ||
2482 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2483 | printk(MPT2SAS_ERR_FMT "%s: failed finding sas_device\n", | ||
2484 | ioc->name, __func__); | ||
2485 | return 1; | ||
2486 | } | ||
2487 | sas_device->state |= MPTSAS_STATE_TR_COMPLETE; | ||
2488 | spin_unlock_irqrestore(&ioc->sas_device_lock, flags); | ||
2489 | |||
2490 | if (sas_device->starget) | ||
2491 | dewtprintk(ioc, starget_printk(KERN_INFO, sas_device->starget, | ||
2492 | "tr_complete:handle(0x%04x), (%s) ioc_status(0x%04x), " | ||
2493 | "loginfo(0x%08x), completed(%d)\n", | ||
2494 | sas_device->handle, (sas_device->state & | ||
2495 | MPT2SAS_REQ_SAS_CNTRL) ? "open" : "active", | ||
2496 | le16_to_cpu(mpi_reply->IOCStatus), | ||
2497 | le32_to_cpu(mpi_reply->IOCLogInfo), | ||
2498 | le32_to_cpu(mpi_reply->TerminationCount))); | ||
2499 | |||
2500 | if (sas_device->starget && sas_device->starget->hostdata) { | ||
2501 | sas_target_priv_data = sas_device->starget->hostdata; | ||
2502 | sas_target_priv_data->tm_busy = 0; | ||
2503 | } | ||
2504 | |||
2505 | if (!list_empty(&ioc->delayed_tr_list)) { | ||
2506 | delayed_tr = list_entry(ioc->delayed_tr_list.next, | ||
2507 | struct _tr_list, list); | ||
2508 | mpt2sas_base_free_smid(ioc, smid); | ||
2509 | if (delayed_tr->state & MPT2SAS_REQ_SAS_CNTRL) | ||
2510 | _scsih_tm_tr_send(ioc, delayed_tr->handle); | ||
2511 | list_del(&delayed_tr->list); | ||
2512 | kfree(delayed_tr); | ||
2513 | rc = 0; /* tells base_interrupt not to free mf */ | ||
2514 | } else | ||
2515 | rc = 1; | ||
2516 | |||
2517 | |||
2518 | if (!(sas_device->state & MPT2SAS_REQ_SAS_CNTRL)) | ||
2519 | return rc; | ||
2520 | |||
2521 | if (ioc->shost_recovery) { | ||
2522 | printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n", | ||
2523 | __func__, ioc->name); | ||
2524 | return rc; | ||
2525 | } | ||
2526 | |||
2527 | smid_sas_ctrl = mpt2sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx); | ||
2528 | if (!smid_sas_ctrl) { | ||
2529 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | ||
2530 | ioc->name, __func__); | ||
2531 | return rc; | ||
2532 | } | ||
2533 | |||
2534 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid_sas_ctrl); | ||
2535 | memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); | ||
2536 | mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | ||
2537 | mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; | ||
2538 | mpi_request->DevHandle = mpi_reply->DevHandle; | ||
2539 | sas_device->state |= MPTSAS_STATE_CNTRL_SEND; | ||
2540 | mpt2sas_base_put_smid_default(ioc, smid_sas_ctrl); | ||
2541 | return rc; | ||
2542 | } | ||
2543 | |||
2544 | /** | ||
2357 | * _scsih_check_topo_delete_events - sanity check on topo events | 2545 | * _scsih_check_topo_delete_events - sanity check on topo events |
2358 | * @ioc: per adapter object | 2546 | * @ioc: per adapter object |
2359 | * @event_data: the event data payload | 2547 | * @event_data: the event data payload |
@@ -2375,6 +2563,21 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, | |||
2375 | u16 expander_handle; | 2563 | u16 expander_handle; |
2376 | struct _sas_node *sas_expander; | 2564 | struct _sas_node *sas_expander; |
2377 | unsigned long flags; | 2565 | unsigned long flags; |
2566 | int i, reason_code; | ||
2567 | u16 handle; | ||
2568 | |||
2569 | for (i = 0 ; i < event_data->NumEntries; i++) { | ||
2570 | if (event_data->PHY[i].PhyStatus & | ||
2571 | MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) | ||
2572 | continue; | ||
2573 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | ||
2574 | if (!handle) | ||
2575 | continue; | ||
2576 | reason_code = event_data->PHY[i].PhyStatus & | ||
2577 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
2578 | if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING) | ||
2579 | _scsih_tm_tr_send(ioc, handle); | ||
2580 | } | ||
2378 | 2581 | ||
2379 | expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); | 2582 | expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); |
2380 | if (expander_handle < ioc->sas_hba.num_phys) { | 2583 | if (expander_handle < ioc->sas_hba.num_phys) { |
@@ -2433,8 +2636,8 @@ _scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc) | |||
2433 | u16 smid; | 2636 | u16 smid; |
2434 | u16 count = 0; | 2637 | u16 count = 0; |
2435 | 2638 | ||
2436 | for (smid = 1; smid <= ioc->request_depth; smid++) { | 2639 | for (smid = 1; smid <= ioc->scsiio_depth; smid++) { |
2437 | scmd = _scsih_scsi_lookup_getclear(ioc, smid); | 2640 | scmd = _scsih_scsi_lookup_get(ioc, smid); |
2438 | if (!scmd) | 2641 | if (!scmd) |
2439 | continue; | 2642 | continue; |
2440 | count++; | 2643 | count++; |
@@ -2616,7 +2819,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2616 | if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON)) | 2819 | if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON)) |
2617 | mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; | 2820 | mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; |
2618 | 2821 | ||
2619 | smid = mpt2sas_base_get_smid(ioc, ioc->scsi_io_cb_idx); | 2822 | smid = mpt2sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); |
2620 | if (!smid) { | 2823 | if (!smid) { |
2621 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", | 2824 | printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n", |
2622 | ioc->name, __func__); | 2825 | ioc->name, __func__); |
@@ -2643,7 +2846,8 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2643 | mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; | 2846 | mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; |
2644 | mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + | 2847 | mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI + |
2645 | MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); | 2848 | MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR); |
2646 | 2849 | mpi_request->VF_ID = 0; /* TODO */ | |
2850 | mpi_request->VP_ID = 0; | ||
2647 | int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *) | 2851 | int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *) |
2648 | mpi_request->LUN); | 2852 | mpi_request->LUN); |
2649 | memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); | 2853 | memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); |
@@ -2657,8 +2861,7 @@ _scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) | |||
2657 | } | 2861 | } |
2658 | } | 2862 | } |
2659 | 2863 | ||
2660 | _scsih_scsi_lookup_set(ioc, smid, scmd); | 2864 | mpt2sas_base_put_smid_scsi_io(ioc, smid, |
2661 | mpt2sas_base_put_smid_scsi_io(ioc, smid, 0, | ||
2662 | sas_device_priv_data->sas_target->handle); | 2865 | sas_device_priv_data->sas_target->handle); |
2663 | return 0; | 2866 | return 0; |
2664 | 2867 | ||
@@ -2954,15 +3157,16 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
2954 | * _scsih_io_done - scsi request callback | 3157 | * _scsih_io_done - scsi request callback |
2955 | * @ioc: per adapter object | 3158 | * @ioc: per adapter object |
2956 | * @smid: system request message index | 3159 | * @smid: system request message index |
2957 | * @VF_ID: virtual function id | 3160 | * @msix_index: MSIX table index supplied by the OS |
2958 | * @reply: reply message frame(lower 32bit addr) | 3161 | * @reply: reply message frame(lower 32bit addr) |
2959 | * | 3162 | * |
2960 | * Callback handler when using scsih_qcmd. | 3163 | * Callback handler when using _scsih_qcmd. |
2961 | * | 3164 | * |
2962 | * Return nothing. | 3165 | * Return 1 meaning mf should be freed from _base_interrupt |
3166 | * 0 means the mf is freed from this function. | ||
2963 | */ | 3167 | */ |
2964 | static void | 3168 | static u8 |
2965 | _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | 3169 | _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) |
2966 | { | 3170 | { |
2967 | Mpi2SCSIIORequest_t *mpi_request; | 3171 | Mpi2SCSIIORequest_t *mpi_request; |
2968 | Mpi2SCSIIOReply_t *mpi_reply; | 3172 | Mpi2SCSIIOReply_t *mpi_reply; |
@@ -2976,9 +3180,9 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
2976 | u32 response_code; | 3180 | u32 response_code; |
2977 | 3181 | ||
2978 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 3182 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
2979 | scmd = _scsih_scsi_lookup_getclear(ioc, smid); | 3183 | scmd = _scsih_scsi_lookup_get(ioc, smid); |
2980 | if (scmd == NULL) | 3184 | if (scmd == NULL) |
2981 | return; | 3185 | return 1; |
2982 | 3186 | ||
2983 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); | 3187 | mpi_request = mpt2sas_base_get_msg_frame(ioc, smid); |
2984 | 3188 | ||
@@ -3134,6 +3338,7 @@ _scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply) | |||
3134 | out: | 3338 | out: |
3135 | scsi_dma_unmap(scmd); | 3339 | scsi_dma_unmap(scmd); |
3136 | scmd->scsi_done(scmd); | 3340 | scmd->scsi_done(scmd); |
3341 | return 1; | ||
3137 | } | 3342 | } |
3138 | 3343 | ||
3139 | /** | 3344 | /** |
@@ -3398,9 +3603,8 @@ _scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3398 | } | 3603 | } |
3399 | } | 3604 | } |
3400 | 3605 | ||
3401 | sas_address = le64_to_cpu(expander_pg0.SASAddress); | ||
3402 | |||
3403 | spin_lock_irqsave(&ioc->sas_node_lock, flags); | 3606 | spin_lock_irqsave(&ioc->sas_node_lock, flags); |
3607 | sas_address = le64_to_cpu(expander_pg0.SASAddress); | ||
3404 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, | 3608 | sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc, |
3405 | sas_address); | 3609 | sas_address); |
3406 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); | 3610 | spin_unlock_irqrestore(&ioc->sas_node_lock, flags); |
@@ -3666,6 +3870,12 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3666 | if (ioc->remove_host) | 3870 | if (ioc->remove_host) |
3667 | goto out; | 3871 | goto out; |
3668 | 3872 | ||
3873 | if ((sas_device->state & MPTSAS_STATE_TR_COMPLETE)) { | ||
3874 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " | ||
3875 | "target_reset handle(0x%04x)\n", ioc->name, handle)); | ||
3876 | goto skip_tr; | ||
3877 | } | ||
3878 | |||
3669 | /* Target Reset to flush out all the outstanding IO */ | 3879 | /* Target Reset to flush out all the outstanding IO */ |
3670 | device_handle = (sas_device->hidden_raid_component) ? | 3880 | device_handle = (sas_device->hidden_raid_component) ? |
3671 | sas_device->volume_handle : handle; | 3881 | sas_device->volume_handle : handle; |
@@ -3682,6 +3892,13 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3682 | if (ioc->shost_recovery) | 3892 | if (ioc->shost_recovery) |
3683 | goto out; | 3893 | goto out; |
3684 | } | 3894 | } |
3895 | skip_tr: | ||
3896 | |||
3897 | if ((sas_device->state & MPTSAS_STATE_CNTRL_COMPLETE)) { | ||
3898 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "\tskip " | ||
3899 | "sas_cntrl handle(0x%04x)\n", ioc->name, handle)); | ||
3900 | goto out; | ||
3901 | } | ||
3685 | 3902 | ||
3686 | /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ | 3903 | /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */ |
3687 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle" | 3904 | dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle" |
@@ -3690,7 +3907,8 @@ _scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle) | |||
3690 | mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; | 3907 | mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; |
3691 | mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE; | 3908 | mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE; |
3692 | mpi_request.DevHandle = handle; | 3909 | mpi_request.DevHandle = handle; |
3693 | mpi_request.VF_ID = 0; | 3910 | mpi_request.VF_ID = 0; /* TODO */ |
3911 | mpi_request.VP_ID = 0; | ||
3694 | if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, | 3912 | if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, |
3695 | &mpi_request)) != 0) { | 3913 | &mpi_request)) != 0) { |
3696 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 3914 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
@@ -3800,15 +4018,12 @@ _scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
3800 | /** | 4018 | /** |
3801 | * _scsih_sas_topology_change_event - handle topology changes | 4019 | * _scsih_sas_topology_change_event - handle topology changes |
3802 | * @ioc: per adapter object | 4020 | * @ioc: per adapter object |
3803 | * @VF_ID: | 4021 | * @fw_event: The fw_event_work object |
3804 | * @event_data: event data payload | ||
3805 | * fw_event: | ||
3806 | * Context: user. | 4022 | * Context: user. |
3807 | * | 4023 | * |
3808 | */ | 4024 | */ |
3809 | static void | 4025 | static void |
3810 | _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4026 | _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, |
3811 | Mpi2EventDataSasTopologyChangeList_t *event_data, | ||
3812 | struct fw_event_work *fw_event) | 4027 | struct fw_event_work *fw_event) |
3813 | { | 4028 | { |
3814 | int i; | 4029 | int i; |
@@ -3818,6 +4033,7 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3818 | struct _sas_node *sas_expander; | 4033 | struct _sas_node *sas_expander; |
3819 | unsigned long flags; | 4034 | unsigned long flags; |
3820 | u8 link_rate_; | 4035 | u8 link_rate_; |
4036 | Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; | ||
3821 | 4037 | ||
3822 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4038 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
3823 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4039 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
@@ -3851,15 +4067,16 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
3851 | } | 4067 | } |
3852 | if (ioc->shost_recovery) | 4068 | if (ioc->shost_recovery) |
3853 | return; | 4069 | return; |
3854 | if (event_data->PHY[i].PhyStatus & | 4070 | phy_number = event_data->StartPhyNum + i; |
3855 | MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) | 4071 | reason_code = event_data->PHY[i].PhyStatus & |
4072 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
4073 | if ((event_data->PHY[i].PhyStatus & | ||
4074 | MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code != | ||
4075 | MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) | ||
3856 | continue; | 4076 | continue; |
3857 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); | 4077 | handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); |
3858 | if (!handle) | 4078 | if (!handle) |
3859 | continue; | 4079 | continue; |
3860 | phy_number = event_data->StartPhyNum + i; | ||
3861 | reason_code = event_data->PHY[i].PhyStatus & | ||
3862 | MPI2_EVENT_SAS_TOPO_RC_MASK; | ||
3863 | link_rate_ = event_data->PHY[i].LinkRate >> 4; | 4080 | link_rate_ = event_data->PHY[i].LinkRate >> 4; |
3864 | switch (reason_code) { | 4081 | switch (reason_code) { |
3865 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: | 4082 | case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: |
@@ -3971,19 +4188,19 @@ _scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
3971 | /** | 4188 | /** |
3972 | * _scsih_sas_device_status_change_event - handle device status change | 4189 | * _scsih_sas_device_status_change_event - handle device status change |
3973 | * @ioc: per adapter object | 4190 | * @ioc: per adapter object |
3974 | * @VF_ID: | 4191 | * @fw_event: The fw_event_work object |
3975 | * @event_data: event data payload | ||
3976 | * Context: user. | 4192 | * Context: user. |
3977 | * | 4193 | * |
3978 | * Return nothing. | 4194 | * Return nothing. |
3979 | */ | 4195 | */ |
3980 | static void | 4196 | static void |
3981 | _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4197 | _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, |
3982 | Mpi2EventDataSasDeviceStatusChange_t *event_data) | 4198 | struct fw_event_work *fw_event) |
3983 | { | 4199 | { |
3984 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4200 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
3985 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4201 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
3986 | _scsih_sas_device_status_change_event_debug(ioc, event_data); | 4202 | _scsih_sas_device_status_change_event_debug(ioc, |
4203 | fw_event->event_data); | ||
3987 | #endif | 4204 | #endif |
3988 | } | 4205 | } |
3989 | 4206 | ||
@@ -4026,34 +4243,33 @@ _scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
4026 | /** | 4243 | /** |
4027 | * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events | 4244 | * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events |
4028 | * @ioc: per adapter object | 4245 | * @ioc: per adapter object |
4029 | * @VF_ID: | 4246 | * @fw_event: The fw_event_work object |
4030 | * @event_data: event data payload | ||
4031 | * Context: user. | 4247 | * Context: user. |
4032 | * | 4248 | * |
4033 | * Return nothing. | 4249 | * Return nothing. |
4034 | */ | 4250 | */ |
4035 | static void | 4251 | static void |
4036 | _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc, | 4252 | _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc, |
4037 | u8 VF_ID, Mpi2EventDataSasEnclDevStatusChange_t *event_data) | 4253 | struct fw_event_work *fw_event) |
4038 | { | 4254 | { |
4039 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4255 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4040 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4256 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
4041 | _scsih_sas_enclosure_dev_status_change_event_debug(ioc, | 4257 | _scsih_sas_enclosure_dev_status_change_event_debug(ioc, |
4042 | event_data); | 4258 | fw_event->event_data); |
4043 | #endif | 4259 | #endif |
4044 | } | 4260 | } |
4045 | 4261 | ||
4046 | /** | 4262 | /** |
4047 | * _scsih_sas_broadcast_primative_event - handle broadcast events | 4263 | * _scsih_sas_broadcast_primative_event - handle broadcast events |
4048 | * @ioc: per adapter object | 4264 | * @ioc: per adapter object |
4049 | * @event_data: event data payload | 4265 | * @fw_event: The fw_event_work object |
4050 | * Context: user. | 4266 | * Context: user. |
4051 | * | 4267 | * |
4052 | * Return nothing. | 4268 | * Return nothing. |
4053 | */ | 4269 | */ |
4054 | static void | 4270 | static void |
4055 | _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4271 | _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, |
4056 | Mpi2EventDataSasBroadcastPrimitive_t *event_data) | 4272 | struct fw_event_work *fw_event) |
4057 | { | 4273 | { |
4058 | struct scsi_cmnd *scmd; | 4274 | struct scsi_cmnd *scmd; |
4059 | u16 smid, handle; | 4275 | u16 smid, handle; |
@@ -4062,11 +4278,12 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4062 | u32 termination_count; | 4278 | u32 termination_count; |
4063 | u32 query_count; | 4279 | u32 query_count; |
4064 | Mpi2SCSITaskManagementReply_t *mpi_reply; | 4280 | Mpi2SCSITaskManagementReply_t *mpi_reply; |
4065 | 4281 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | |
4282 | Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; | ||
4283 | #endif | ||
4066 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " | 4284 | dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: " |
4067 | "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, | 4285 | "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum, |
4068 | event_data->PortWidth)); | 4286 | event_data->PortWidth)); |
4069 | |||
4070 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, | 4287 | dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name, |
4071 | __func__)); | 4288 | __func__)); |
4072 | 4289 | ||
@@ -4074,7 +4291,7 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4074 | termination_count = 0; | 4291 | termination_count = 0; |
4075 | query_count = 0; | 4292 | query_count = 0; |
4076 | mpi_reply = ioc->tm_cmds.reply; | 4293 | mpi_reply = ioc->tm_cmds.reply; |
4077 | for (smid = 1; smid <= ioc->request_depth; smid++) { | 4294 | for (smid = 1; smid <= ioc->scsiio_depth; smid++) { |
4078 | scmd = _scsih_scsi_lookup_get(ioc, smid); | 4295 | scmd = _scsih_scsi_lookup_get(ioc, smid); |
4079 | if (!scmd) | 4296 | if (!scmd) |
4080 | continue; | 4297 | continue; |
@@ -4121,23 +4338,25 @@ _scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4121 | /** | 4338 | /** |
4122 | * _scsih_sas_discovery_event - handle discovery events | 4339 | * _scsih_sas_discovery_event - handle discovery events |
4123 | * @ioc: per adapter object | 4340 | * @ioc: per adapter object |
4124 | * @event_data: event data payload | 4341 | * @fw_event: The fw_event_work object |
4125 | * Context: user. | 4342 | * Context: user. |
4126 | * | 4343 | * |
4127 | * Return nothing. | 4344 | * Return nothing. |
4128 | */ | 4345 | */ |
4129 | static void | 4346 | static void |
4130 | _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4347 | _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, |
4131 | Mpi2EventDataSasDiscovery_t *event_data) | 4348 | struct fw_event_work *fw_event) |
4132 | { | 4349 | { |
4350 | Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data; | ||
4351 | |||
4133 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4352 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4134 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { | 4353 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { |
4135 | printk(MPT2SAS_DEBUG_FMT "discovery event: (%s)", ioc->name, | 4354 | printk(MPT2SAS_DEBUG_FMT "discovery event: (%s)", ioc->name, |
4136 | (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? | 4355 | (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? |
4137 | "start" : "stop"); | 4356 | "start" : "stop"); |
4138 | if (event_data->DiscoveryStatus) | 4357 | if (event_data->DiscoveryStatus) |
4139 | printk(MPT2SAS_DEBUG_FMT ", discovery_status(0x%08x)", | 4358 | printk("discovery_status(0x%08x)", |
4140 | ioc->name, le32_to_cpu(event_data->DiscoveryStatus)); | 4359 | le32_to_cpu(event_data->DiscoveryStatus)); |
4141 | printk("\n"); | 4360 | printk("\n"); |
4142 | } | 4361 | } |
4143 | #endif | 4362 | #endif |
@@ -4488,19 +4707,19 @@ _scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
4488 | /** | 4707 | /** |
4489 | * _scsih_sas_ir_config_change_event - handle ir configuration change events | 4708 | * _scsih_sas_ir_config_change_event - handle ir configuration change events |
4490 | * @ioc: per adapter object | 4709 | * @ioc: per adapter object |
4491 | * @VF_ID: | 4710 | * @fw_event: The fw_event_work object |
4492 | * @event_data: event data payload | ||
4493 | * Context: user. | 4711 | * Context: user. |
4494 | * | 4712 | * |
4495 | * Return nothing. | 4713 | * Return nothing. |
4496 | */ | 4714 | */ |
4497 | static void | 4715 | static void |
4498 | _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4716 | _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, |
4499 | Mpi2EventDataIrConfigChangeList_t *event_data) | 4717 | struct fw_event_work *fw_event) |
4500 | { | 4718 | { |
4501 | Mpi2EventIrConfigElement_t *element; | 4719 | Mpi2EventIrConfigElement_t *element; |
4502 | int i; | 4720 | int i; |
4503 | u8 foreign_config; | 4721 | u8 foreign_config; |
4722 | Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data; | ||
4504 | 4723 | ||
4505 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4724 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4506 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4725 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
@@ -4543,14 +4762,14 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4543 | /** | 4762 | /** |
4544 | * _scsih_sas_ir_volume_event - IR volume event | 4763 | * _scsih_sas_ir_volume_event - IR volume event |
4545 | * @ioc: per adapter object | 4764 | * @ioc: per adapter object |
4546 | * @event_data: event data payload | 4765 | * @fw_event: The fw_event_work object |
4547 | * Context: user. | 4766 | * Context: user. |
4548 | * | 4767 | * |
4549 | * Return nothing. | 4768 | * Return nothing. |
4550 | */ | 4769 | */ |
4551 | static void | 4770 | static void |
4552 | _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4771 | _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, |
4553 | Mpi2EventDataIrVolume_t *event_data) | 4772 | struct fw_event_work *fw_event) |
4554 | { | 4773 | { |
4555 | u64 wwid; | 4774 | u64 wwid; |
4556 | unsigned long flags; | 4775 | unsigned long flags; |
@@ -4559,6 +4778,7 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4559 | u32 state; | 4778 | u32 state; |
4560 | int rc; | 4779 | int rc; |
4561 | struct MPT2SAS_TARGET *sas_target_priv_data; | 4780 | struct MPT2SAS_TARGET *sas_target_priv_data; |
4781 | Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; | ||
4562 | 4782 | ||
4563 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) | 4783 | if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) |
4564 | return; | 4784 | return; |
@@ -4628,14 +4848,14 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4628 | /** | 4848 | /** |
4629 | * _scsih_sas_ir_physical_disk_event - PD event | 4849 | * _scsih_sas_ir_physical_disk_event - PD event |
4630 | * @ioc: per adapter object | 4850 | * @ioc: per adapter object |
4631 | * @event_data: event data payload | 4851 | * @fw_event: The fw_event_work object |
4632 | * Context: user. | 4852 | * Context: user. |
4633 | * | 4853 | * |
4634 | * Return nothing. | 4854 | * Return nothing. |
4635 | */ | 4855 | */ |
4636 | static void | 4856 | static void |
4637 | _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4857 | _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, |
4638 | Mpi2EventDataIrPhysicalDisk_t *event_data) | 4858 | struct fw_event_work *fw_event) |
4639 | { | 4859 | { |
4640 | u16 handle; | 4860 | u16 handle; |
4641 | u32 state; | 4861 | u32 state; |
@@ -4644,6 +4864,7 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4644 | Mpi2ConfigReply_t mpi_reply; | 4864 | Mpi2ConfigReply_t mpi_reply; |
4645 | Mpi2SasDevicePage0_t sas_device_pg0; | 4865 | Mpi2SasDevicePage0_t sas_device_pg0; |
4646 | u32 ioc_status; | 4866 | u32 ioc_status; |
4867 | Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; | ||
4647 | 4868 | ||
4648 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) | 4869 | if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) |
4649 | return; | 4870 | return; |
@@ -4743,33 +4964,33 @@ _scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc, | |||
4743 | /** | 4964 | /** |
4744 | * _scsih_sas_ir_operation_status_event - handle RAID operation events | 4965 | * _scsih_sas_ir_operation_status_event - handle RAID operation events |
4745 | * @ioc: per adapter object | 4966 | * @ioc: per adapter object |
4746 | * @VF_ID: | 4967 | * @fw_event: The fw_event_work object |
4747 | * @event_data: event data payload | ||
4748 | * Context: user. | 4968 | * Context: user. |
4749 | * | 4969 | * |
4750 | * Return nothing. | 4970 | * Return nothing. |
4751 | */ | 4971 | */ |
4752 | static void | 4972 | static void |
4753 | _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4973 | _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, |
4754 | Mpi2EventDataIrOperationStatus_t *event_data) | 4974 | struct fw_event_work *fw_event) |
4755 | { | 4975 | { |
4756 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING | 4976 | #ifdef CONFIG_SCSI_MPT2SAS_LOGGING |
4757 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) | 4977 | if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) |
4758 | _scsih_sas_ir_operation_status_event_debug(ioc, event_data); | 4978 | _scsih_sas_ir_operation_status_event_debug(ioc, |
4979 | fw_event->event_data); | ||
4759 | #endif | 4980 | #endif |
4760 | } | 4981 | } |
4761 | 4982 | ||
4762 | /** | 4983 | /** |
4763 | * _scsih_task_set_full - handle task set full | 4984 | * _scsih_task_set_full - handle task set full |
4764 | * @ioc: per adapter object | 4985 | * @ioc: per adapter object |
4765 | * @event_data: event data payload | 4986 | * @fw_event: The fw_event_work object |
4766 | * Context: user. | 4987 | * Context: user. |
4767 | * | 4988 | * |
4768 | * Throttle back qdepth. | 4989 | * Throttle back qdepth. |
4769 | */ | 4990 | */ |
4770 | static void | 4991 | static void |
4771 | _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | 4992 | _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work |
4772 | Mpi2EventDataTaskSetFull_t *event_data) | 4993 | *fw_event) |
4773 | { | 4994 | { |
4774 | unsigned long flags; | 4995 | unsigned long flags; |
4775 | struct _sas_device *sas_device; | 4996 | struct _sas_device *sas_device; |
@@ -4780,6 +5001,7 @@ _scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, | |||
4780 | u16 handle; | 5001 | u16 handle; |
4781 | int id, channel; | 5002 | int id, channel; |
4782 | u64 sas_address; | 5003 | u64 sas_address; |
5004 | Mpi2EventDataTaskSetFull_t *event_data = fw_event->event_data; | ||
4783 | 5005 | ||
4784 | current_depth = le16_to_cpu(event_data->CurrentDepth); | 5006 | current_depth = le16_to_cpu(event_data->CurrentDepth); |
4785 | handle = le16_to_cpu(event_data->DevHandle); | 5007 | handle = le16_to_cpu(event_data->DevHandle); |
@@ -4868,6 +5090,10 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | |||
4868 | if (sas_device->sas_address == sas_address && | 5090 | if (sas_device->sas_address == sas_address && |
4869 | sas_device->slot == slot && sas_device->starget) { | 5091 | sas_device->slot == slot && sas_device->starget) { |
4870 | sas_device->responding = 1; | 5092 | sas_device->responding = 1; |
5093 | sas_device->state = 0; | ||
5094 | starget = sas_device->starget; | ||
5095 | sas_target_priv_data = starget->hostdata; | ||
5096 | sas_target_priv_data->tm_busy = 0; | ||
4871 | starget_printk(KERN_INFO, sas_device->starget, | 5097 | starget_printk(KERN_INFO, sas_device->starget, |
4872 | "handle(0x%04x), sas_addr(0x%016llx), enclosure " | 5098 | "handle(0x%04x), sas_addr(0x%016llx), enclosure " |
4873 | "logical id(0x%016llx), slot(%d)\n", handle, | 5099 | "logical id(0x%016llx), slot(%d)\n", handle, |
@@ -4880,8 +5106,6 @@ _scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address, | |||
4880 | printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", | 5106 | printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n", |
4881 | sas_device->handle); | 5107 | sas_device->handle); |
4882 | sas_device->handle = handle; | 5108 | sas_device->handle = handle; |
4883 | starget = sas_device->starget; | ||
4884 | sas_target_priv_data = starget->hostdata; | ||
4885 | sas_target_priv_data->handle = handle; | 5109 | sas_target_priv_data->handle = handle; |
4886 | goto out; | 5110 | goto out; |
4887 | } | 5111 | } |
@@ -5227,44 +5451,38 @@ _firmware_event_work(struct work_struct *work) | |||
5227 | 5451 | ||
5228 | switch (fw_event->event) { | 5452 | switch (fw_event->event) { |
5229 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: | 5453 | case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: |
5230 | _scsih_sas_topology_change_event(ioc, fw_event->VF_ID, | 5454 | _scsih_sas_topology_change_event(ioc, fw_event); |
5231 | fw_event->event_data, fw_event); | ||
5232 | break; | 5455 | break; |
5233 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: | 5456 | case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: |
5234 | _scsih_sas_device_status_change_event(ioc, fw_event->VF_ID, | 5457 | _scsih_sas_device_status_change_event(ioc, |
5235 | fw_event->event_data); | 5458 | fw_event); |
5236 | break; | 5459 | break; |
5237 | case MPI2_EVENT_SAS_DISCOVERY: | 5460 | case MPI2_EVENT_SAS_DISCOVERY: |
5238 | _scsih_sas_discovery_event(ioc, fw_event->VF_ID, | 5461 | _scsih_sas_discovery_event(ioc, |
5239 | fw_event->event_data); | 5462 | fw_event); |
5240 | break; | 5463 | break; |
5241 | case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: | 5464 | case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: |
5242 | _scsih_sas_broadcast_primative_event(ioc, fw_event->VF_ID, | 5465 | _scsih_sas_broadcast_primative_event(ioc, |
5243 | fw_event->event_data); | 5466 | fw_event); |
5244 | break; | 5467 | break; |
5245 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: | 5468 | case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: |
5246 | _scsih_sas_enclosure_dev_status_change_event(ioc, | 5469 | _scsih_sas_enclosure_dev_status_change_event(ioc, |
5247 | fw_event->VF_ID, fw_event->event_data); | 5470 | fw_event); |
5248 | break; | 5471 | break; |
5249 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: | 5472 | case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: |
5250 | _scsih_sas_ir_config_change_event(ioc, fw_event->VF_ID, | 5473 | _scsih_sas_ir_config_change_event(ioc, fw_event); |
5251 | fw_event->event_data); | ||
5252 | break; | 5474 | break; |
5253 | case MPI2_EVENT_IR_VOLUME: | 5475 | case MPI2_EVENT_IR_VOLUME: |
5254 | _scsih_sas_ir_volume_event(ioc, fw_event->VF_ID, | 5476 | _scsih_sas_ir_volume_event(ioc, fw_event); |
5255 | fw_event->event_data); | ||
5256 | break; | 5477 | break; |
5257 | case MPI2_EVENT_IR_PHYSICAL_DISK: | 5478 | case MPI2_EVENT_IR_PHYSICAL_DISK: |
5258 | _scsih_sas_ir_physical_disk_event(ioc, fw_event->VF_ID, | 5479 | _scsih_sas_ir_physical_disk_event(ioc, fw_event); |
5259 | fw_event->event_data); | ||
5260 | break; | 5480 | break; |
5261 | case MPI2_EVENT_IR_OPERATION_STATUS: | 5481 | case MPI2_EVENT_IR_OPERATION_STATUS: |
5262 | _scsih_sas_ir_operation_status_event(ioc, fw_event->VF_ID, | 5482 | _scsih_sas_ir_operation_status_event(ioc, fw_event); |
5263 | fw_event->event_data); | ||
5264 | break; | 5483 | break; |
5265 | case MPI2_EVENT_TASK_SET_FULL: | 5484 | case MPI2_EVENT_TASK_SET_FULL: |
5266 | _scsih_task_set_full(ioc, fw_event->VF_ID, | 5485 | _scsih_task_set_full(ioc, fw_event); |
5267 | fw_event->event_data); | ||
5268 | break; | 5486 | break; |
5269 | } | 5487 | } |
5270 | _scsih_fw_event_free(ioc, fw_event); | 5488 | _scsih_fw_event_free(ioc, fw_event); |
@@ -5273,17 +5491,19 @@ _firmware_event_work(struct work_struct *work) | |||
5273 | /** | 5491 | /** |
5274 | * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time) | 5492 | * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time) |
5275 | * @ioc: per adapter object | 5493 | * @ioc: per adapter object |
5276 | * @VF_ID: virtual function id | 5494 | * @msix_index: MSIX table index supplied by the OS |
5277 | * @reply: reply message frame(lower 32bit addr) | 5495 | * @reply: reply message frame(lower 32bit addr) |
5278 | * Context: interrupt. | 5496 | * Context: interrupt. |
5279 | * | 5497 | * |
5280 | * This function merely adds a new work task into ioc->firmware_event_thread. | 5498 | * This function merely adds a new work task into ioc->firmware_event_thread. |
5281 | * The tasks are worked from _firmware_event_work in user context. | 5499 | * The tasks are worked from _firmware_event_work in user context. |
5282 | * | 5500 | * |
5283 | * Return nothing. | 5501 | * Return 1 meaning mf should be freed from _base_interrupt |
5502 | * 0 means the mf is freed from this function. | ||
5284 | */ | 5503 | */ |
5285 | void | 5504 | u8 |
5286 | mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | 5505 | mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, |
5506 | u32 reply) | ||
5287 | { | 5507 | { |
5288 | struct fw_event_work *fw_event; | 5508 | struct fw_event_work *fw_event; |
5289 | Mpi2EventNotificationReply_t *mpi_reply; | 5509 | Mpi2EventNotificationReply_t *mpi_reply; |
@@ -5294,11 +5514,11 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
5294 | spin_lock_irqsave(&ioc->fw_event_lock, flags); | 5514 | spin_lock_irqsave(&ioc->fw_event_lock, flags); |
5295 | if (ioc->fw_events_off || ioc->remove_host) { | 5515 | if (ioc->fw_events_off || ioc->remove_host) { |
5296 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 5516 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
5297 | return; | 5517 | return 1; |
5298 | } | 5518 | } |
5299 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); | 5519 | spin_unlock_irqrestore(&ioc->fw_event_lock, flags); |
5300 | 5520 | ||
5301 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 5521 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
5302 | event = le16_to_cpu(mpi_reply->Event); | 5522 | event = le16_to_cpu(mpi_reply->Event); |
5303 | 5523 | ||
5304 | switch (event) { | 5524 | switch (event) { |
@@ -5312,7 +5532,7 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
5312 | if (baen_data->Primitive != | 5532 | if (baen_data->Primitive != |
5313 | MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT || | 5533 | MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT || |
5314 | ioc->broadcast_aen_busy) | 5534 | ioc->broadcast_aen_busy) |
5315 | return; | 5535 | return 1; |
5316 | ioc->broadcast_aen_busy = 1; | 5536 | ioc->broadcast_aen_busy = 1; |
5317 | break; | 5537 | break; |
5318 | } | 5538 | } |
@@ -5334,14 +5554,14 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
5334 | break; | 5554 | break; |
5335 | 5555 | ||
5336 | default: /* ignore the rest */ | 5556 | default: /* ignore the rest */ |
5337 | return; | 5557 | return 1; |
5338 | } | 5558 | } |
5339 | 5559 | ||
5340 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); | 5560 | fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); |
5341 | if (!fw_event) { | 5561 | if (!fw_event) { |
5342 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 5562 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
5343 | ioc->name, __FILE__, __LINE__, __func__); | 5563 | ioc->name, __FILE__, __LINE__, __func__); |
5344 | return; | 5564 | return 1; |
5345 | } | 5565 | } |
5346 | fw_event->event_data = | 5566 | fw_event->event_data = |
5347 | kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC); | 5567 | kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC); |
@@ -5349,15 +5569,17 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply) | |||
5349 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", | 5569 | printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", |
5350 | ioc->name, __FILE__, __LINE__, __func__); | 5570 | ioc->name, __FILE__, __LINE__, __func__); |
5351 | kfree(fw_event); | 5571 | kfree(fw_event); |
5352 | return; | 5572 | return 1; |
5353 | } | 5573 | } |
5354 | 5574 | ||
5355 | memcpy(fw_event->event_data, mpi_reply->EventData, | 5575 | memcpy(fw_event->event_data, mpi_reply->EventData, |
5356 | mpi_reply->EventDataLength*4); | 5576 | mpi_reply->EventDataLength*4); |
5357 | fw_event->ioc = ioc; | 5577 | fw_event->ioc = ioc; |
5358 | fw_event->VF_ID = VF_ID; | 5578 | fw_event->VF_ID = mpi_reply->VF_ID; |
5579 | fw_event->VP_ID = mpi_reply->VP_ID; | ||
5359 | fw_event->event = event; | 5580 | fw_event->event = event; |
5360 | _scsih_fw_event_add(ioc, fw_event); | 5581 | _scsih_fw_event_add(ioc, fw_event); |
5582 | return 1; | ||
5361 | } | 5583 | } |
5362 | 5584 | ||
5363 | /* shost template */ | 5585 | /* shost template */ |
@@ -5617,7 +5839,7 @@ _scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc) | |||
5617 | } | 5839 | } |
5618 | 5840 | ||
5619 | /** | 5841 | /** |
5620 | * _scsih_probe_sas - reporting raid volumes to sas transport | 5842 | * _scsih_probe_sas - reporting sas devices to sas transport |
5621 | * @ioc: per adapter object | 5843 | * @ioc: per adapter object |
5622 | * | 5844 | * |
5623 | * Called during initial loading of the driver. | 5845 | * Called during initial loading of the driver. |
@@ -5714,6 +5936,8 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5714 | ioc->base_cb_idx = base_cb_idx; | 5936 | ioc->base_cb_idx = base_cb_idx; |
5715 | ioc->transport_cb_idx = transport_cb_idx; | 5937 | ioc->transport_cb_idx = transport_cb_idx; |
5716 | ioc->config_cb_idx = config_cb_idx; | 5938 | ioc->config_cb_idx = config_cb_idx; |
5939 | ioc->tm_tr_cb_idx = tm_tr_cb_idx; | ||
5940 | ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; | ||
5717 | ioc->logging_level = logging_level; | 5941 | ioc->logging_level = logging_level; |
5718 | /* misc semaphores and spin locks */ | 5942 | /* misc semaphores and spin locks */ |
5719 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); | 5943 | spin_lock_init(&ioc->ioc_reset_in_progress_lock); |
@@ -5729,6 +5953,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5729 | INIT_LIST_HEAD(&ioc->fw_event_list); | 5953 | INIT_LIST_HEAD(&ioc->fw_event_list); |
5730 | INIT_LIST_HEAD(&ioc->raid_device_list); | 5954 | INIT_LIST_HEAD(&ioc->raid_device_list); |
5731 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); | 5955 | INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); |
5956 | INIT_LIST_HEAD(&ioc->delayed_tr_list); | ||
5732 | 5957 | ||
5733 | /* init shost parameters */ | 5958 | /* init shost parameters */ |
5734 | shost->max_cmd_len = 16; | 5959 | shost->max_cmd_len = 16; |
@@ -5745,6 +5970,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
5745 | 5970 | ||
5746 | scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION | 5971 | scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION |
5747 | | SHOST_DIF_TYPE3_PROTECTION); | 5972 | | SHOST_DIF_TYPE3_PROTECTION); |
5973 | scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); | ||
5748 | 5974 | ||
5749 | /* event thread */ | 5975 | /* event thread */ |
5750 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), | 5976 | snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), |
@@ -5894,6 +6120,11 @@ _scsih_init(void) | |||
5894 | /* ctl module callback handler */ | 6120 | /* ctl module callback handler */ |
5895 | ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done); | 6121 | ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done); |
5896 | 6122 | ||
6123 | tm_tr_cb_idx = mpt2sas_base_register_callback_handler( | ||
6124 | _scsih_tm_tr_complete); | ||
6125 | tm_sas_control_cb_idx = mpt2sas_base_register_callback_handler( | ||
6126 | _scsih_sas_control_complete); | ||
6127 | |||
5897 | mpt2sas_ctl_init(); | 6128 | mpt2sas_ctl_init(); |
5898 | 6129 | ||
5899 | error = pci_register_driver(&scsih_driver); | 6130 | error = pci_register_driver(&scsih_driver); |
@@ -5924,6 +6155,9 @@ _scsih_exit(void) | |||
5924 | mpt2sas_base_release_callback_handler(config_cb_idx); | 6155 | mpt2sas_base_release_callback_handler(config_cb_idx); |
5925 | mpt2sas_base_release_callback_handler(ctl_cb_idx); | 6156 | mpt2sas_base_release_callback_handler(ctl_cb_idx); |
5926 | 6157 | ||
6158 | mpt2sas_base_release_callback_handler(tm_tr_cb_idx); | ||
6159 | mpt2sas_base_release_callback_handler(tm_sas_control_cb_idx); | ||
6160 | |||
5927 | mpt2sas_ctl_exit(); | 6161 | mpt2sas_ctl_exit(); |
5928 | } | 6162 | } |
5929 | 6163 | ||
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index 742324a0a11e..eb98188c7f3f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * SAS Transport Layer for MPT (Message Passing Technology) based controllers | 2 | * SAS Transport Layer for MPT (Message Passing Technology) based controllers |
3 | * | 3 | * |
4 | * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c | 4 | * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c |
5 | * Copyright (C) 2007-2008 LSI Corporation | 5 | * Copyright (C) 2007-2009 LSI Corporation |
6 | * (mailto:DL-MPTFusionLinux@lsi.com) | 6 | * (mailto:DL-MPTFusionLinux@lsi.com) |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or | 8 | * This program is free software; you can redistribute it and/or |
@@ -212,25 +212,26 @@ _transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle, | |||
212 | * mpt2sas_transport_done - internal transport layer callback handler. | 212 | * mpt2sas_transport_done - internal transport layer callback handler. |
213 | * @ioc: per adapter object | 213 | * @ioc: per adapter object |
214 | * @smid: system request message index | 214 | * @smid: system request message index |
215 | * @VF_ID: virtual function id | 215 | * @msix_index: MSIX table index supplied by the OS |
216 | * @reply: reply message frame(lower 32bit addr) | 216 | * @reply: reply message frame(lower 32bit addr) |
217 | * | 217 | * |
218 | * Callback handler when sending internal generated transport cmds. | 218 | * Callback handler when sending internal generated transport cmds. |
219 | * The callback index passed is `ioc->transport_cb_idx` | 219 | * The callback index passed is `ioc->transport_cb_idx` |
220 | * | 220 | * |
221 | * Return nothing. | 221 | * Return 1 meaning mf should be freed from _base_interrupt |
222 | * 0 means the mf is freed from this function. | ||
222 | */ | 223 | */ |
223 | void | 224 | u8 |
224 | mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | 225 | mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 msix_index, |
225 | u32 reply) | 226 | u32 reply) |
226 | { | 227 | { |
227 | MPI2DefaultReply_t *mpi_reply; | 228 | MPI2DefaultReply_t *mpi_reply; |
228 | 229 | ||
229 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); | 230 | mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply); |
230 | if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED) | 231 | if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED) |
231 | return; | 232 | return 1; |
232 | if (ioc->transport_cmds.smid != smid) | 233 | if (ioc->transport_cmds.smid != smid) |
233 | return; | 234 | return 1; |
234 | ioc->transport_cmds.status |= MPT2_CMD_COMPLETE; | 235 | ioc->transport_cmds.status |= MPT2_CMD_COMPLETE; |
235 | if (mpi_reply) { | 236 | if (mpi_reply) { |
236 | memcpy(ioc->transport_cmds.reply, mpi_reply, | 237 | memcpy(ioc->transport_cmds.reply, mpi_reply, |
@@ -239,6 +240,7 @@ mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, | |||
239 | } | 240 | } |
240 | ioc->transport_cmds.status &= ~MPT2_CMD_PENDING; | 241 | ioc->transport_cmds.status &= ~MPT2_CMD_PENDING; |
241 | complete(&ioc->transport_cmds.done); | 242 | complete(&ioc->transport_cmds.done); |
243 | return 1; | ||
242 | } | 244 | } |
243 | 245 | ||
244 | /* report manufacture request structure */ | 246 | /* report manufacture request structure */ |
@@ -369,6 +371,8 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, | |||
369 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); | 371 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); |
370 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | 372 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; |
371 | mpi_request->PhysicalPort = 0xFF; | 373 | mpi_request->PhysicalPort = 0xFF; |
374 | mpi_request->VF_ID = 0; /* TODO */ | ||
375 | mpi_request->VP_ID = 0; | ||
372 | sas_address_le = (u64 *)&mpi_request->SASAddress; | 376 | sas_address_le = (u64 *)&mpi_request->SASAddress; |
373 | *sas_address_le = cpu_to_le64(sas_address); | 377 | *sas_address_le = cpu_to_le64(sas_address); |
374 | mpi_request->RequestDataLength = sizeof(struct rep_manu_request); | 378 | mpi_request->RequestDataLength = sizeof(struct rep_manu_request); |
@@ -396,7 +400,8 @@ _transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc, | |||
396 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - " | 400 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - " |
397 | "send to sas_addr(0x%016llx)\n", ioc->name, | 401 | "send to sas_addr(0x%016llx)\n", ioc->name, |
398 | (unsigned long long)sas_address)); | 402 | (unsigned long long)sas_address)); |
399 | mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */); | 403 | mpt2sas_base_put_smid_default(ioc, smid); |
404 | init_completion(&ioc->transport_cmds.done); | ||
400 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | 405 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, |
401 | 10*HZ); | 406 | 10*HZ); |
402 | 407 | ||
@@ -1106,6 +1111,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1106 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); | 1111 | memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); |
1107 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; | 1112 | mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; |
1108 | mpi_request->PhysicalPort = 0xFF; | 1113 | mpi_request->PhysicalPort = 0xFF; |
1114 | mpi_request->VF_ID = 0; /* TODO */ | ||
1115 | mpi_request->VP_ID = 0; | ||
1109 | *((u64 *)&mpi_request->SASAddress) = (rphy) ? | 1116 | *((u64 *)&mpi_request->SASAddress) = (rphy) ? |
1110 | cpu_to_le64(rphy->identify.sas_address) : | 1117 | cpu_to_le64(rphy->identify.sas_address) : |
1111 | cpu_to_le64(ioc->sas_hba.sas_address); | 1118 | cpu_to_le64(ioc->sas_hba.sas_address); |
@@ -1147,7 +1154,8 @@ _transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
1147 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " | 1154 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " |
1148 | "sending smp request\n", ioc->name, __func__)); | 1155 | "sending smp request\n", ioc->name, __func__)); |
1149 | 1156 | ||
1150 | mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */); | 1157 | mpt2sas_base_put_smid_default(ioc, smid); |
1158 | init_completion(&ioc->transport_cmds.done); | ||
1151 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, | 1159 | timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, |
1152 | 10*HZ); | 1160 | 10*HZ); |
1153 | 1161 | ||
diff --git a/drivers/scsi/mvsas/mv_defs.h b/drivers/scsi/mvsas/mv_defs.h index f8cb9defb961..1849da1f030d 100644 --- a/drivers/scsi/mvsas/mv_defs.h +++ b/drivers/scsi/mvsas/mv_defs.h | |||
@@ -25,6 +25,8 @@ | |||
25 | #ifndef _MV_DEFS_H_ | 25 | #ifndef _MV_DEFS_H_ |
26 | #define _MV_DEFS_H_ | 26 | #define _MV_DEFS_H_ |
27 | 27 | ||
28 | #define PCI_DEVICE_ID_ARECA_1300 0x1300 | ||
29 | #define PCI_DEVICE_ID_ARECA_1320 0x1320 | ||
28 | 30 | ||
29 | enum chip_flavors { | 31 | enum chip_flavors { |
30 | chip_6320, | 32 | chip_6320, |
@@ -32,6 +34,8 @@ enum chip_flavors { | |||
32 | chip_6485, | 34 | chip_6485, |
33 | chip_9480, | 35 | chip_9480, |
34 | chip_9180, | 36 | chip_9180, |
37 | chip_1300, | ||
38 | chip_1320 | ||
35 | }; | 39 | }; |
36 | 40 | ||
37 | /* driver compile-time configuration */ | 41 | /* driver compile-time configuration */ |
diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c index 8646a19f999d..c790d45876c4 100644 --- a/drivers/scsi/mvsas/mv_init.c +++ b/drivers/scsi/mvsas/mv_init.c | |||
@@ -32,6 +32,8 @@ static const struct mvs_chip_info mvs_chips[] = { | |||
32 | [chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, }, | 32 | [chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, }, |
33 | [chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, | 33 | [chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, |
34 | [chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, | 34 | [chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, |
35 | [chip_1300] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, }, | ||
36 | [chip_1320] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, }, | ||
35 | }; | 37 | }; |
36 | 38 | ||
37 | #define SOC_SAS_NUM 2 | 39 | #define SOC_SAS_NUM 2 |
@@ -653,6 +655,8 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = { | |||
653 | { PCI_VDEVICE(MARVELL, 0x6485), chip_6485 }, | 655 | { PCI_VDEVICE(MARVELL, 0x6485), chip_6485 }, |
654 | { PCI_VDEVICE(MARVELL, 0x9480), chip_9480 }, | 656 | { PCI_VDEVICE(MARVELL, 0x9480), chip_9480 }, |
655 | { PCI_VDEVICE(MARVELL, 0x9180), chip_9180 }, | 657 | { PCI_VDEVICE(MARVELL, 0x9180), chip_9180 }, |
658 | { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 }, | ||
659 | { PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 }, | ||
656 | 660 | ||
657 | { } /* terminate list */ | 661 | { } /* terminate list */ |
658 | }; | 662 | }; |
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index 4302f06e4ec9..f7c70e2a8224 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c | |||
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
47 | #include <scsi/scsi.h> | 47 | #include <scsi/scsi.h> |
48 | #include <scsi/scsi_host.h> | 48 | #include <scsi/scsi_host.h> |
49 | #include <scsi/scsi_device.h> | ||
49 | #include <scsi/scsi_tcq.h> | 50 | #include <scsi/scsi_tcq.h> |
50 | #include <scsi/scsi_eh.h> | 51 | #include <scsi/scsi_eh.h> |
51 | #include <scsi/scsi_cmnd.h> | 52 | #include <scsi/scsi_cmnd.h> |
@@ -684,7 +685,7 @@ static void pmcraid_timeout_handler(struct pmcraid_cmd *cmd) | |||
684 | struct pmcraid_instance *pinstance = cmd->drv_inst; | 685 | struct pmcraid_instance *pinstance = cmd->drv_inst; |
685 | unsigned long lock_flags; | 686 | unsigned long lock_flags; |
686 | 687 | ||
687 | dev_err(&pinstance->pdev->dev, | 688 | dev_info(&pinstance->pdev->dev, |
688 | "Adapter being reset due to command timeout.\n"); | 689 | "Adapter being reset due to command timeout.\n"); |
689 | 690 | ||
690 | /* Command timeouts result in hard reset sequence. The command that got | 691 | /* Command timeouts result in hard reset sequence. The command that got |
@@ -815,8 +816,9 @@ static void pmcraid_erp_done(struct pmcraid_cmd *cmd) | |||
815 | 816 | ||
816 | if (PMCRAID_IOASC_SENSE_KEY(ioasc) > 0) { | 817 | if (PMCRAID_IOASC_SENSE_KEY(ioasc) > 0) { |
817 | scsi_cmd->result |= (DID_ERROR << 16); | 818 | scsi_cmd->result |= (DID_ERROR << 16); |
818 | pmcraid_err("command CDB[0] = %x failed with IOASC: 0x%08X\n", | 819 | scmd_printk(KERN_INFO, scsi_cmd, |
819 | cmd->ioa_cb->ioarcb.cdb[0], ioasc); | 820 | "command CDB[0] = %x failed with IOASC: 0x%08X\n", |
821 | cmd->ioa_cb->ioarcb.cdb[0], ioasc); | ||
820 | } | 822 | } |
821 | 823 | ||
822 | /* if we had allocated sense buffers for request sense, copy the sense | 824 | /* if we had allocated sense buffers for request sense, copy the sense |
@@ -1541,13 +1543,13 @@ static void pmcraid_handle_error_log(struct pmcraid_instance *pinstance) | |||
1541 | 1543 | ||
1542 | if (pinstance->ldn.hcam->notification_lost == | 1544 | if (pinstance->ldn.hcam->notification_lost == |
1543 | HOSTRCB_NOTIFICATIONS_LOST) | 1545 | HOSTRCB_NOTIFICATIONS_LOST) |
1544 | dev_err(&pinstance->pdev->dev, "Error notifications lost\n"); | 1546 | dev_info(&pinstance->pdev->dev, "Error notifications lost\n"); |
1545 | 1547 | ||
1546 | ioasc = le32_to_cpu(hcam_ldn->error_log.fd_ioasc); | 1548 | ioasc = le32_to_cpu(hcam_ldn->error_log.fd_ioasc); |
1547 | 1549 | ||
1548 | if (ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET || | 1550 | if (ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET || |
1549 | ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER) { | 1551 | ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET_BY_OTHER) { |
1550 | dev_err(&pinstance->pdev->dev, | 1552 | dev_info(&pinstance->pdev->dev, |
1551 | "UnitAttention due to IOA Bus Reset\n"); | 1553 | "UnitAttention due to IOA Bus Reset\n"); |
1552 | scsi_report_bus_reset( | 1554 | scsi_report_bus_reset( |
1553 | pinstance->host, | 1555 | pinstance->host, |
@@ -1584,7 +1586,7 @@ static void pmcraid_process_ccn(struct pmcraid_cmd *cmd) | |||
1584 | atomic_read(&pinstance->ccn.ignore) == 1) { | 1586 | atomic_read(&pinstance->ccn.ignore) == 1) { |
1585 | return; | 1587 | return; |
1586 | } else if (ioasc) { | 1588 | } else if (ioasc) { |
1587 | dev_err(&pinstance->pdev->dev, | 1589 | dev_info(&pinstance->pdev->dev, |
1588 | "Host RCB (CCN) failed with IOASC: 0x%08X\n", ioasc); | 1590 | "Host RCB (CCN) failed with IOASC: 0x%08X\n", ioasc); |
1589 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); | 1591 | spin_lock_irqsave(pinstance->host->host_lock, lock_flags); |
1590 | pmcraid_send_hcam(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE); | 1592 | pmcraid_send_hcam(pinstance, PMCRAID_HCAM_CODE_CONFIG_CHANGE); |
@@ -1634,7 +1636,7 @@ static void pmcraid_process_ldn(struct pmcraid_cmd *cmd) | |||
1634 | return; | 1636 | return; |
1635 | } | 1637 | } |
1636 | } else { | 1638 | } else { |
1637 | dev_err(&pinstance->pdev->dev, | 1639 | dev_info(&pinstance->pdev->dev, |
1638 | "Host RCB(LDN) failed with IOASC: 0x%08X\n", ioasc); | 1640 | "Host RCB(LDN) failed with IOASC: 0x%08X\n", ioasc); |
1639 | } | 1641 | } |
1640 | /* send netlink message for HCAM notification if enabled */ | 1642 | /* send netlink message for HCAM notification if enabled */ |
@@ -1822,7 +1824,6 @@ static void pmcraid_fail_outstanding_cmds(struct pmcraid_instance *pinstance) | |||
1822 | scsi_dma_unmap(scsi_cmd); | 1824 | scsi_dma_unmap(scsi_cmd); |
1823 | pmcraid_return_cmd(cmd); | 1825 | pmcraid_return_cmd(cmd); |
1824 | 1826 | ||
1825 | |||
1826 | pmcraid_info("failing(%d) CDB[0] = %x result: %x\n", | 1827 | pmcraid_info("failing(%d) CDB[0] = %x result: %x\n", |
1827 | le32_to_cpu(resp) >> 2, | 1828 | le32_to_cpu(resp) >> 2, |
1828 | cmd->ioa_cb->ioarcb.cdb[0], | 1829 | cmd->ioa_cb->ioarcb.cdb[0], |
@@ -2514,7 +2515,8 @@ static int pmcraid_reset_device( | |||
2514 | res = scsi_cmd->device->hostdata; | 2515 | res = scsi_cmd->device->hostdata; |
2515 | 2516 | ||
2516 | if (!res) { | 2517 | if (!res) { |
2517 | pmcraid_err("reset_device: NULL resource pointer\n"); | 2518 | sdev_printk(KERN_ERR, scsi_cmd->device, |
2519 | "reset_device: NULL resource pointer\n"); | ||
2518 | return FAILED; | 2520 | return FAILED; |
2519 | } | 2521 | } |
2520 | 2522 | ||
@@ -2752,8 +2754,8 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd) | |||
2752 | pinstance = | 2754 | pinstance = |
2753 | (struct pmcraid_instance *)scsi_cmd->device->host->hostdata; | 2755 | (struct pmcraid_instance *)scsi_cmd->device->host->hostdata; |
2754 | 2756 | ||
2755 | dev_err(&pinstance->pdev->dev, | 2757 | scmd_printk(KERN_INFO, scsi_cmd, |
2756 | "I/O command timed out, aborting it.\n"); | 2758 | "I/O command timed out, aborting it.\n"); |
2757 | 2759 | ||
2758 | res = scsi_cmd->device->hostdata; | 2760 | res = scsi_cmd->device->hostdata; |
2759 | 2761 | ||
@@ -2824,7 +2826,8 @@ static int pmcraid_eh_abort_handler(struct scsi_cmnd *scsi_cmd) | |||
2824 | */ | 2826 | */ |
2825 | static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd) | 2827 | static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd) |
2826 | { | 2828 | { |
2827 | pmcraid_err("Doing device reset due to an I/O command timeout.\n"); | 2829 | scmd_printk(KERN_INFO, scmd, |
2830 | "resetting device due to an I/O command timeout.\n"); | ||
2828 | return pmcraid_reset_device(scmd, | 2831 | return pmcraid_reset_device(scmd, |
2829 | PMCRAID_INTERNAL_TIMEOUT, | 2832 | PMCRAID_INTERNAL_TIMEOUT, |
2830 | RESET_DEVICE_LUN); | 2833 | RESET_DEVICE_LUN); |
@@ -2832,7 +2835,8 @@ static int pmcraid_eh_device_reset_handler(struct scsi_cmnd *scmd) | |||
2832 | 2835 | ||
2833 | static int pmcraid_eh_bus_reset_handler(struct scsi_cmnd *scmd) | 2836 | static int pmcraid_eh_bus_reset_handler(struct scsi_cmnd *scmd) |
2834 | { | 2837 | { |
2835 | pmcraid_err("Doing bus reset due to an I/O command timeout.\n"); | 2838 | scmd_printk(KERN_INFO, scmd, |
2839 | "Doing bus reset due to an I/O command timeout.\n"); | ||
2836 | return pmcraid_reset_device(scmd, | 2840 | return pmcraid_reset_device(scmd, |
2837 | PMCRAID_RESET_BUS_TIMEOUT, | 2841 | PMCRAID_RESET_BUS_TIMEOUT, |
2838 | RESET_DEVICE_BUS); | 2842 | RESET_DEVICE_BUS); |
@@ -2840,7 +2844,8 @@ static int pmcraid_eh_bus_reset_handler(struct scsi_cmnd *scmd) | |||
2840 | 2844 | ||
2841 | static int pmcraid_eh_target_reset_handler(struct scsi_cmnd *scmd) | 2845 | static int pmcraid_eh_target_reset_handler(struct scsi_cmnd *scmd) |
2842 | { | 2846 | { |
2843 | pmcraid_err("Doing target reset due to an I/O command timeout.\n"); | 2847 | scmd_printk(KERN_INFO, scmd, |
2848 | "Doing target reset due to an I/O command timeout.\n"); | ||
2844 | return pmcraid_reset_device(scmd, | 2849 | return pmcraid_reset_device(scmd, |
2845 | PMCRAID_INTERNAL_TIMEOUT, | 2850 | PMCRAID_INTERNAL_TIMEOUT, |
2846 | RESET_DEVICE_TARGET); | 2851 | RESET_DEVICE_TARGET); |
@@ -2988,11 +2993,11 @@ static int pmcraid_build_ioadl( | |||
2988 | nseg = scsi_dma_map(scsi_cmd); | 2993 | nseg = scsi_dma_map(scsi_cmd); |
2989 | 2994 | ||
2990 | if (nseg < 0) { | 2995 | if (nseg < 0) { |
2991 | dev_err(&pinstance->pdev->dev, "scsi_map_dma failed!\n"); | 2996 | scmd_printk(KERN_ERR, scsi_cmd, "scsi_map_dma failed!\n"); |
2992 | return -1; | 2997 | return -1; |
2993 | } else if (nseg > PMCRAID_MAX_IOADLS) { | 2998 | } else if (nseg > PMCRAID_MAX_IOADLS) { |
2994 | scsi_dma_unmap(scsi_cmd); | 2999 | scsi_dma_unmap(scsi_cmd); |
2995 | dev_err(&pinstance->pdev->dev, | 3000 | scmd_printk(KERN_ERR, scsi_cmd, |
2996 | "sg count is (%d) more than allowed!\n", nseg); | 3001 | "sg count is (%d) more than allowed!\n", nseg); |
2997 | return -1; | 3002 | return -1; |
2998 | } | 3003 | } |
@@ -5040,7 +5045,7 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5040 | rc = pci_enable_device(pdev); | 5045 | rc = pci_enable_device(pdev); |
5041 | 5046 | ||
5042 | if (rc) { | 5047 | if (rc) { |
5043 | pmcraid_err("pmcraid: Enable device failed\n"); | 5048 | dev_err(&pdev->dev, "resume: Enable device failed\n"); |
5044 | return rc; | 5049 | return rc; |
5045 | } | 5050 | } |
5046 | 5051 | ||
@@ -5054,7 +5059,7 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5054 | rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); | 5059 | rc = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); |
5055 | 5060 | ||
5056 | if (rc != 0) { | 5061 | if (rc != 0) { |
5057 | dev_err(&pdev->dev, "Failed to set PCI DMA mask\n"); | 5062 | dev_err(&pdev->dev, "resume: Failed to set PCI DMA mask\n"); |
5058 | goto disable_device; | 5063 | goto disable_device; |
5059 | } | 5064 | } |
5060 | 5065 | ||
@@ -5063,7 +5068,8 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5063 | rc = pmcraid_register_interrupt_handler(pinstance); | 5068 | rc = pmcraid_register_interrupt_handler(pinstance); |
5064 | 5069 | ||
5065 | if (rc) { | 5070 | if (rc) { |
5066 | pmcraid_err("resume: couldn't register interrupt handlers\n"); | 5071 | dev_err(&pdev->dev, |
5072 | "resume: couldn't register interrupt handlers\n"); | ||
5067 | rc = -ENODEV; | 5073 | rc = -ENODEV; |
5068 | goto release_host; | 5074 | goto release_host; |
5069 | } | 5075 | } |
@@ -5080,7 +5086,7 @@ static int pmcraid_resume(struct pci_dev *pdev) | |||
5080 | * state. | 5086 | * state. |
5081 | */ | 5087 | */ |
5082 | if (pmcraid_reset_bringup(pinstance)) { | 5088 | if (pmcraid_reset_bringup(pinstance)) { |
5083 | pmcraid_err("couldn't initialize IOA \n"); | 5089 | dev_err(&pdev->dev, "couldn't initialize IOA \n"); |
5084 | rc = -ENODEV; | 5090 | rc = -ENODEV; |
5085 | goto release_tasklets; | 5091 | goto release_tasklets; |
5086 | } | 5092 | } |
@@ -5187,7 +5193,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
5187 | LIST_HEAD(old_res); | 5193 | LIST_HEAD(old_res); |
5188 | 5194 | ||
5189 | if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED) | 5195 | if (pinstance->cfg_table->flags & MICROCODE_UPDATE_REQUIRED) |
5190 | dev_err(&pinstance->pdev->dev, "Require microcode download\n"); | 5196 | pmcraid_err("IOA requires microcode download\n"); |
5191 | 5197 | ||
5192 | /* resource list is protected by pinstance->resource_lock. | 5198 | /* resource list is protected by pinstance->resource_lock. |
5193 | * init_res_table can be called from probe (user-thread) or runtime | 5199 | * init_res_table can be called from probe (user-thread) or runtime |
@@ -5224,8 +5230,7 @@ static void pmcraid_init_res_table(struct pmcraid_cmd *cmd) | |||
5224 | if (!found) { | 5230 | if (!found) { |
5225 | 5231 | ||
5226 | if (list_empty(&pinstance->free_res_q)) { | 5232 | if (list_empty(&pinstance->free_res_q)) { |
5227 | dev_err(&pinstance->pdev->dev, | 5233 | pmcraid_err("Too many devices attached\n"); |
5228 | "Too many devices attached\n"); | ||
5229 | break; | 5234 | break; |
5230 | } | 5235 | } |
5231 | 5236 | ||
@@ -5442,7 +5447,7 @@ static int __devinit pmcraid_probe( | |||
5442 | rc = pmcraid_register_interrupt_handler(pinstance); | 5447 | rc = pmcraid_register_interrupt_handler(pinstance); |
5443 | 5448 | ||
5444 | if (rc) { | 5449 | if (rc) { |
5445 | pmcraid_err("couldn't register interrupt handler\n"); | 5450 | dev_err(&pdev->dev, "couldn't register interrupt handler\n"); |
5446 | goto out_scsi_host_put; | 5451 | goto out_scsi_host_put; |
5447 | } | 5452 | } |
5448 | 5453 | ||
@@ -5466,7 +5471,7 @@ static int __devinit pmcraid_probe( | |||
5466 | */ | 5471 | */ |
5467 | pmcraid_info("starting IOA initialization sequence\n"); | 5472 | pmcraid_info("starting IOA initialization sequence\n"); |
5468 | if (pmcraid_reset_bringup(pinstance)) { | 5473 | if (pmcraid_reset_bringup(pinstance)) { |
5469 | pmcraid_err("couldn't initialize IOA \n"); | 5474 | dev_err(&pdev->dev, "couldn't initialize IOA \n"); |
5470 | rc = 1; | 5475 | rc = 1; |
5471 | goto out_release_bufs; | 5476 | goto out_release_bufs; |
5472 | } | 5477 | } |
@@ -5534,7 +5539,6 @@ static struct pci_driver pmcraid_driver = { | |||
5534 | .shutdown = pmcraid_shutdown | 5539 | .shutdown = pmcraid_shutdown |
5535 | }; | 5540 | }; |
5536 | 5541 | ||
5537 | |||
5538 | /** | 5542 | /** |
5539 | * pmcraid_init - module load entry point | 5543 | * pmcraid_init - module load entry point |
5540 | */ | 5544 | */ |
@@ -5566,7 +5570,6 @@ static int __init pmcraid_init(void) | |||
5566 | goto out_unreg_chrdev; | 5570 | goto out_unreg_chrdev; |
5567 | } | 5571 | } |
5568 | 5572 | ||
5569 | |||
5570 | error = pmcraid_netlink_init(); | 5573 | error = pmcraid_netlink_init(); |
5571 | 5574 | ||
5572 | if (error) | 5575 | if (error) |
@@ -5584,6 +5587,7 @@ static int __init pmcraid_init(void) | |||
5584 | 5587 | ||
5585 | out_unreg_chrdev: | 5588 | out_unreg_chrdev: |
5586 | unregister_chrdev_region(MKDEV(pmcraid_major, 0), PMCRAID_MAX_ADAPTERS); | 5589 | unregister_chrdev_region(MKDEV(pmcraid_major, 0), PMCRAID_MAX_ADAPTERS); |
5590 | |||
5587 | out_init: | 5591 | out_init: |
5588 | return error; | 5592 | return error; |
5589 | } | 5593 | } |
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 42b799abba57..e07b3617f019 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -568,7 +568,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options, | |||
568 | if (req == NULL) { | 568 | if (req == NULL) { |
569 | qla_printk(KERN_WARNING, ha, "could not allocate memory" | 569 | qla_printk(KERN_WARNING, ha, "could not allocate memory" |
570 | "for request que\n"); | 570 | "for request que\n"); |
571 | goto que_failed; | 571 | goto failed; |
572 | } | 572 | } |
573 | 573 | ||
574 | req->length = REQUEST_ENTRY_CNT_24XX; | 574 | req->length = REQUEST_ENTRY_CNT_24XX; |
@@ -632,6 +632,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options, | |||
632 | 632 | ||
633 | que_failed: | 633 | que_failed: |
634 | qla25xx_free_req_que(base_vha, req); | 634 | qla25xx_free_req_que(base_vha, req); |
635 | failed: | ||
635 | return 0; | 636 | return 0; |
636 | } | 637 | } |
637 | 638 | ||
@@ -659,7 +660,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | |||
659 | if (rsp == NULL) { | 660 | if (rsp == NULL) { |
660 | qla_printk(KERN_WARNING, ha, "could not allocate memory for" | 661 | qla_printk(KERN_WARNING, ha, "could not allocate memory for" |
661 | " response que\n"); | 662 | " response que\n"); |
662 | goto que_failed; | 663 | goto failed; |
663 | } | 664 | } |
664 | 665 | ||
665 | rsp->length = RESPONSE_ENTRY_CNT_MQ; | 666 | rsp->length = RESPONSE_ENTRY_CNT_MQ; |
@@ -728,6 +729,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options, | |||
728 | 729 | ||
729 | que_failed: | 730 | que_failed: |
730 | qla25xx_free_rsp_que(base_vha, rsp); | 731 | qla25xx_free_rsp_que(base_vha, rsp); |
732 | failed: | ||
731 | return 0; | 733 | return 0; |
732 | } | 734 | } |
733 | 735 | ||
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index b6e03074cb8f..dd098cad337b 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -241,10 +241,7 @@ scsi_host_alloc_command(struct Scsi_Host *shost, gfp_t gfp_mask) | |||
241 | */ | 241 | */ |
242 | struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) | 242 | struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) |
243 | { | 243 | { |
244 | struct scsi_cmnd *cmd; | 244 | struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask); |
245 | unsigned char *buf; | ||
246 | |||
247 | cmd = scsi_host_alloc_command(shost, gfp_mask); | ||
248 | 245 | ||
249 | if (unlikely(!cmd)) { | 246 | if (unlikely(!cmd)) { |
250 | unsigned long flags; | 247 | unsigned long flags; |
@@ -258,9 +255,15 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) | |||
258 | spin_unlock_irqrestore(&shost->free_list_lock, flags); | 255 | spin_unlock_irqrestore(&shost->free_list_lock, flags); |
259 | 256 | ||
260 | if (cmd) { | 257 | if (cmd) { |
258 | void *buf, *prot; | ||
259 | |||
261 | buf = cmd->sense_buffer; | 260 | buf = cmd->sense_buffer; |
261 | prot = cmd->prot_sdb; | ||
262 | |||
262 | memset(cmd, 0, sizeof(*cmd)); | 263 | memset(cmd, 0, sizeof(*cmd)); |
264 | |||
263 | cmd->sense_buffer = buf; | 265 | cmd->sense_buffer = buf; |
266 | cmd->prot_sdb = prot; | ||
264 | } | 267 | } |
265 | } | 268 | } |
266 | 269 | ||
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index fb9af207d61d..c4103bef41b5 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <scsi/scsi_host.h> | 50 | #include <scsi/scsi_host.h> |
51 | #include <scsi/scsicam.h> | 51 | #include <scsi/scsicam.h> |
52 | #include <scsi/scsi_eh.h> | 52 | #include <scsi/scsi_eh.h> |
53 | #include <scsi/scsi_dbg.h> | ||
53 | 54 | ||
54 | #include "sd.h" | 55 | #include "sd.h" |
55 | #include "scsi_logging.h" | 56 | #include "scsi_logging.h" |
@@ -64,6 +65,7 @@ static const char * scsi_debug_version_date = "20070104"; | |||
64 | #define PARAMETER_LIST_LENGTH_ERR 0x1a | 65 | #define PARAMETER_LIST_LENGTH_ERR 0x1a |
65 | #define INVALID_OPCODE 0x20 | 66 | #define INVALID_OPCODE 0x20 |
66 | #define ADDR_OUT_OF_RANGE 0x21 | 67 | #define ADDR_OUT_OF_RANGE 0x21 |
68 | #define INVALID_COMMAND_OPCODE 0x20 | ||
67 | #define INVALID_FIELD_IN_CDB 0x24 | 69 | #define INVALID_FIELD_IN_CDB 0x24 |
68 | #define INVALID_FIELD_IN_PARAM_LIST 0x26 | 70 | #define INVALID_FIELD_IN_PARAM_LIST 0x26 |
69 | #define POWERON_RESET 0x29 | 71 | #define POWERON_RESET 0x29 |
@@ -180,7 +182,7 @@ static int sdebug_sectors_per; /* sectors per cylinder */ | |||
180 | #define SDEBUG_SENSE_LEN 32 | 182 | #define SDEBUG_SENSE_LEN 32 |
181 | 183 | ||
182 | #define SCSI_DEBUG_CANQUEUE 255 | 184 | #define SCSI_DEBUG_CANQUEUE 255 |
183 | #define SCSI_DEBUG_MAX_CMD_LEN 16 | 185 | #define SCSI_DEBUG_MAX_CMD_LEN 32 |
184 | 186 | ||
185 | struct sdebug_dev_info { | 187 | struct sdebug_dev_info { |
186 | struct list_head dev_list; | 188 | struct list_head dev_list; |
@@ -296,9 +298,25 @@ static void mk_sense_buffer(struct sdebug_dev_info *devip, int key, | |||
296 | } | 298 | } |
297 | 299 | ||
298 | static void get_data_transfer_info(unsigned char *cmd, | 300 | static void get_data_transfer_info(unsigned char *cmd, |
299 | unsigned long long *lba, unsigned int *num) | 301 | unsigned long long *lba, unsigned int *num, |
302 | u32 *ei_lba) | ||
300 | { | 303 | { |
304 | *ei_lba = 0; | ||
305 | |||
301 | switch (*cmd) { | 306 | switch (*cmd) { |
307 | case VARIABLE_LENGTH_CMD: | ||
308 | *lba = (u64)cmd[19] | (u64)cmd[18] << 8 | | ||
309 | (u64)cmd[17] << 16 | (u64)cmd[16] << 24 | | ||
310 | (u64)cmd[15] << 32 | (u64)cmd[14] << 40 | | ||
311 | (u64)cmd[13] << 48 | (u64)cmd[12] << 56; | ||
312 | |||
313 | *ei_lba = (u32)cmd[23] | (u32)cmd[22] << 8 | | ||
314 | (u32)cmd[21] << 16 | (u32)cmd[20] << 24; | ||
315 | |||
316 | *num = (u32)cmd[31] | (u32)cmd[30] << 8 | (u32)cmd[29] << 16 | | ||
317 | (u32)cmd[28] << 24; | ||
318 | break; | ||
319 | |||
302 | case WRITE_16: | 320 | case WRITE_16: |
303 | case READ_16: | 321 | case READ_16: |
304 | *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | | 322 | *lba = (u64)cmd[9] | (u64)cmd[8] << 8 | |
@@ -1589,7 +1607,7 @@ static int do_device_access(struct scsi_cmnd *scmd, | |||
1589 | } | 1607 | } |
1590 | 1608 | ||
1591 | static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, | 1609 | static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, |
1592 | unsigned int sectors) | 1610 | unsigned int sectors, u32 ei_lba) |
1593 | { | 1611 | { |
1594 | unsigned int i, resid; | 1612 | unsigned int i, resid; |
1595 | struct scatterlist *psgl; | 1613 | struct scatterlist *psgl; |
@@ -1636,13 +1654,23 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1636 | return 0x01; | 1654 | return 0x01; |
1637 | } | 1655 | } |
1638 | 1656 | ||
1639 | if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && | 1657 | if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && |
1640 | be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) { | 1658 | be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) { |
1641 | printk(KERN_ERR "%s: REF check failed on sector %lu\n", | 1659 | printk(KERN_ERR "%s: REF check failed on sector %lu\n", |
1642 | __func__, (unsigned long)sector); | 1660 | __func__, (unsigned long)sector); |
1643 | dif_errors++; | 1661 | dif_errors++; |
1644 | return 0x03; | 1662 | return 0x03; |
1645 | } | 1663 | } |
1664 | |||
1665 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
1666 | be32_to_cpu(sdt[i].ref_tag) != ei_lba) { | ||
1667 | printk(KERN_ERR "%s: REF check failed on sector %lu\n", | ||
1668 | __func__, (unsigned long)sector); | ||
1669 | dif_errors++; | ||
1670 | return 0x03; | ||
1671 | } | ||
1672 | |||
1673 | ei_lba++; | ||
1646 | } | 1674 | } |
1647 | 1675 | ||
1648 | resid = sectors * 8; /* Bytes of protection data to copy into sgl */ | 1676 | resid = sectors * 8; /* Bytes of protection data to copy into sgl */ |
@@ -1670,7 +1698,8 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1670 | } | 1698 | } |
1671 | 1699 | ||
1672 | static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, | 1700 | static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, |
1673 | unsigned int num, struct sdebug_dev_info *devip) | 1701 | unsigned int num, struct sdebug_dev_info *devip, |
1702 | u32 ei_lba) | ||
1674 | { | 1703 | { |
1675 | unsigned long iflags; | 1704 | unsigned long iflags; |
1676 | int ret; | 1705 | int ret; |
@@ -1699,7 +1728,7 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, | |||
1699 | 1728 | ||
1700 | /* DIX + T10 DIF */ | 1729 | /* DIX + T10 DIF */ |
1701 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { | 1730 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { |
1702 | int prot_ret = prot_verify_read(SCpnt, lba, num); | 1731 | int prot_ret = prot_verify_read(SCpnt, lba, num, ei_lba); |
1703 | 1732 | ||
1704 | if (prot_ret) { | 1733 | if (prot_ret) { |
1705 | mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); | 1734 | mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); |
@@ -1735,7 +1764,7 @@ void dump_sector(unsigned char *buf, int len) | |||
1735 | } | 1764 | } |
1736 | 1765 | ||
1737 | static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | 1766 | static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, |
1738 | unsigned int sectors) | 1767 | unsigned int sectors, u32 ei_lba) |
1739 | { | 1768 | { |
1740 | int i, j, ret; | 1769 | int i, j, ret; |
1741 | struct sd_dif_tuple *sdt; | 1770 | struct sd_dif_tuple *sdt; |
@@ -1749,11 +1778,6 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1749 | 1778 | ||
1750 | sector = do_div(tmp_sec, sdebug_store_sectors); | 1779 | sector = do_div(tmp_sec, sdebug_store_sectors); |
1751 | 1780 | ||
1752 | if (((SCpnt->cmnd[1] >> 5) & 7) != 1) { | ||
1753 | printk(KERN_WARNING "scsi_debug: WRPROTECT != 1\n"); | ||
1754 | return 0; | ||
1755 | } | ||
1756 | |||
1757 | BUG_ON(scsi_sg_count(SCpnt) == 0); | 1781 | BUG_ON(scsi_sg_count(SCpnt) == 0); |
1758 | BUG_ON(scsi_prot_sg_count(SCpnt) == 0); | 1782 | BUG_ON(scsi_prot_sg_count(SCpnt) == 0); |
1759 | 1783 | ||
@@ -1808,7 +1832,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1808 | goto out; | 1832 | goto out; |
1809 | } | 1833 | } |
1810 | 1834 | ||
1811 | if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION && | 1835 | if (scsi_debug_dif == SD_DIF_TYPE1_PROTECTION && |
1812 | be32_to_cpu(sdt->ref_tag) | 1836 | be32_to_cpu(sdt->ref_tag) |
1813 | != (start_sec & 0xffffffff)) { | 1837 | != (start_sec & 0xffffffff)) { |
1814 | printk(KERN_ERR | 1838 | printk(KERN_ERR |
@@ -1819,6 +1843,16 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1819 | goto out; | 1843 | goto out; |
1820 | } | 1844 | } |
1821 | 1845 | ||
1846 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
1847 | be32_to_cpu(sdt->ref_tag) != ei_lba) { | ||
1848 | printk(KERN_ERR | ||
1849 | "%s: REF check failed on sector %lu\n", | ||
1850 | __func__, (unsigned long)sector); | ||
1851 | ret = 0x03; | ||
1852 | dump_sector(daddr, scsi_debug_sector_size); | ||
1853 | goto out; | ||
1854 | } | ||
1855 | |||
1822 | /* Would be great to copy this in bigger | 1856 | /* Would be great to copy this in bigger |
1823 | * chunks. However, for the sake of | 1857 | * chunks. However, for the sake of |
1824 | * correctness we need to verify each sector | 1858 | * correctness we need to verify each sector |
@@ -1832,6 +1866,7 @@ static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec, | |||
1832 | sector = 0; /* Force wrap */ | 1866 | sector = 0; /* Force wrap */ |
1833 | 1867 | ||
1834 | start_sec++; | 1868 | start_sec++; |
1869 | ei_lba++; | ||
1835 | daddr += scsi_debug_sector_size; | 1870 | daddr += scsi_debug_sector_size; |
1836 | ppage_offset += sizeof(struct sd_dif_tuple); | 1871 | ppage_offset += sizeof(struct sd_dif_tuple); |
1837 | } | 1872 | } |
@@ -1853,7 +1888,8 @@ out: | |||
1853 | } | 1888 | } |
1854 | 1889 | ||
1855 | static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, | 1890 | static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, |
1856 | unsigned int num, struct sdebug_dev_info *devip) | 1891 | unsigned int num, struct sdebug_dev_info *devip, |
1892 | u32 ei_lba) | ||
1857 | { | 1893 | { |
1858 | unsigned long iflags; | 1894 | unsigned long iflags; |
1859 | int ret; | 1895 | int ret; |
@@ -1864,7 +1900,7 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, | |||
1864 | 1900 | ||
1865 | /* DIX + T10 DIF */ | 1901 | /* DIX + T10 DIF */ |
1866 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { | 1902 | if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) { |
1867 | int prot_ret = prot_verify_write(SCpnt, lba, num); | 1903 | int prot_ret = prot_verify_write(SCpnt, lba, num, ei_lba); |
1868 | 1904 | ||
1869 | if (prot_ret) { | 1905 | if (prot_ret) { |
1870 | mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); | 1906 | mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); |
@@ -2872,11 +2908,12 @@ static int __init scsi_debug_init(void) | |||
2872 | 2908 | ||
2873 | case SD_DIF_TYPE0_PROTECTION: | 2909 | case SD_DIF_TYPE0_PROTECTION: |
2874 | case SD_DIF_TYPE1_PROTECTION: | 2910 | case SD_DIF_TYPE1_PROTECTION: |
2911 | case SD_DIF_TYPE2_PROTECTION: | ||
2875 | case SD_DIF_TYPE3_PROTECTION: | 2912 | case SD_DIF_TYPE3_PROTECTION: |
2876 | break; | 2913 | break; |
2877 | 2914 | ||
2878 | default: | 2915 | default: |
2879 | printk(KERN_ERR "scsi_debug_init: dif must be 0, 1 or 3\n"); | 2916 | printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n"); |
2880 | return -EINVAL; | 2917 | return -EINVAL; |
2881 | } | 2918 | } |
2882 | 2919 | ||
@@ -3121,6 +3158,7 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) | |||
3121 | int len, k; | 3158 | int len, k; |
3122 | unsigned int num; | 3159 | unsigned int num; |
3123 | unsigned long long lba; | 3160 | unsigned long long lba; |
3161 | u32 ei_lba; | ||
3124 | int errsts = 0; | 3162 | int errsts = 0; |
3125 | int target = SCpnt->device->id; | 3163 | int target = SCpnt->device->id; |
3126 | struct sdebug_dev_info *devip = NULL; | 3164 | struct sdebug_dev_info *devip = NULL; |
@@ -3254,14 +3292,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) | |||
3254 | case READ_16: | 3292 | case READ_16: |
3255 | case READ_12: | 3293 | case READ_12: |
3256 | case READ_10: | 3294 | case READ_10: |
3295 | /* READ{10,12,16} and DIF Type 2 are natural enemies */ | ||
3296 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
3297 | cmd[1] & 0xe0) { | ||
3298 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
3299 | INVALID_COMMAND_OPCODE, 0); | ||
3300 | errsts = check_condition_result; | ||
3301 | break; | ||
3302 | } | ||
3303 | |||
3304 | if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || | ||
3305 | scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && | ||
3306 | (cmd[1] & 0xe0) == 0) | ||
3307 | printk(KERN_ERR "Unprotected RD/WR to DIF device\n"); | ||
3308 | |||
3309 | /* fall through */ | ||
3257 | case READ_6: | 3310 | case READ_6: |
3311 | read: | ||
3258 | errsts = check_readiness(SCpnt, 0, devip); | 3312 | errsts = check_readiness(SCpnt, 0, devip); |
3259 | if (errsts) | 3313 | if (errsts) |
3260 | break; | 3314 | break; |
3261 | if (scsi_debug_fake_rw) | 3315 | if (scsi_debug_fake_rw) |
3262 | break; | 3316 | break; |
3263 | get_data_transfer_info(cmd, &lba, &num); | 3317 | get_data_transfer_info(cmd, &lba, &num, &ei_lba); |
3264 | errsts = resp_read(SCpnt, lba, num, devip); | 3318 | errsts = resp_read(SCpnt, lba, num, devip, ei_lba); |
3265 | if (inj_recovered && (0 == errsts)) { | 3319 | if (inj_recovered && (0 == errsts)) { |
3266 | mk_sense_buffer(devip, RECOVERED_ERROR, | 3320 | mk_sense_buffer(devip, RECOVERED_ERROR, |
3267 | THRESHOLD_EXCEEDED, 0); | 3321 | THRESHOLD_EXCEEDED, 0); |
@@ -3288,14 +3342,30 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) | |||
3288 | case WRITE_16: | 3342 | case WRITE_16: |
3289 | case WRITE_12: | 3343 | case WRITE_12: |
3290 | case WRITE_10: | 3344 | case WRITE_10: |
3345 | /* WRITE{10,12,16} and DIF Type 2 are natural enemies */ | ||
3346 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && | ||
3347 | cmd[1] & 0xe0) { | ||
3348 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
3349 | INVALID_COMMAND_OPCODE, 0); | ||
3350 | errsts = check_condition_result; | ||
3351 | break; | ||
3352 | } | ||
3353 | |||
3354 | if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION || | ||
3355 | scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) && | ||
3356 | (cmd[1] & 0xe0) == 0) | ||
3357 | printk(KERN_ERR "Unprotected RD/WR to DIF device\n"); | ||
3358 | |||
3359 | /* fall through */ | ||
3291 | case WRITE_6: | 3360 | case WRITE_6: |
3361 | write: | ||
3292 | errsts = check_readiness(SCpnt, 0, devip); | 3362 | errsts = check_readiness(SCpnt, 0, devip); |
3293 | if (errsts) | 3363 | if (errsts) |
3294 | break; | 3364 | break; |
3295 | if (scsi_debug_fake_rw) | 3365 | if (scsi_debug_fake_rw) |
3296 | break; | 3366 | break; |
3297 | get_data_transfer_info(cmd, &lba, &num); | 3367 | get_data_transfer_info(cmd, &lba, &num, &ei_lba); |
3298 | errsts = resp_write(SCpnt, lba, num, devip); | 3368 | errsts = resp_write(SCpnt, lba, num, devip, ei_lba); |
3299 | if (inj_recovered && (0 == errsts)) { | 3369 | if (inj_recovered && (0 == errsts)) { |
3300 | mk_sense_buffer(devip, RECOVERED_ERROR, | 3370 | mk_sense_buffer(devip, RECOVERED_ERROR, |
3301 | THRESHOLD_EXCEEDED, 0); | 3371 | THRESHOLD_EXCEEDED, 0); |
@@ -3341,15 +3411,38 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done) | |||
3341 | break; | 3411 | break; |
3342 | if (scsi_debug_fake_rw) | 3412 | if (scsi_debug_fake_rw) |
3343 | break; | 3413 | break; |
3344 | get_data_transfer_info(cmd, &lba, &num); | 3414 | get_data_transfer_info(cmd, &lba, &num, &ei_lba); |
3345 | errsts = resp_read(SCpnt, lba, num, devip); | 3415 | errsts = resp_read(SCpnt, lba, num, devip, ei_lba); |
3346 | if (errsts) | 3416 | if (errsts) |
3347 | break; | 3417 | break; |
3348 | errsts = resp_write(SCpnt, lba, num, devip); | 3418 | errsts = resp_write(SCpnt, lba, num, devip, ei_lba); |
3349 | if (errsts) | 3419 | if (errsts) |
3350 | break; | 3420 | break; |
3351 | errsts = resp_xdwriteread(SCpnt, lba, num, devip); | 3421 | errsts = resp_xdwriteread(SCpnt, lba, num, devip); |
3352 | break; | 3422 | break; |
3423 | case VARIABLE_LENGTH_CMD: | ||
3424 | if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) { | ||
3425 | |||
3426 | if ((cmd[10] & 0xe0) == 0) | ||
3427 | printk(KERN_ERR | ||
3428 | "Unprotected RD/WR to DIF device\n"); | ||
3429 | |||
3430 | if (cmd[9] == READ_32) { | ||
3431 | BUG_ON(SCpnt->cmd_len < 32); | ||
3432 | goto read; | ||
3433 | } | ||
3434 | |||
3435 | if (cmd[9] == WRITE_32) { | ||
3436 | BUG_ON(SCpnt->cmd_len < 32); | ||
3437 | goto write; | ||
3438 | } | ||
3439 | } | ||
3440 | |||
3441 | mk_sense_buffer(devip, ILLEGAL_REQUEST, | ||
3442 | INVALID_FIELD_IN_CDB, 0); | ||
3443 | errsts = check_condition_result; | ||
3444 | break; | ||
3445 | |||
3353 | default: | 3446 | default: |
3354 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) | 3447 | if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) |
3355 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " | 3448 | printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 877204daf549..1b0060b791e8 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -725,6 +725,9 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, | |||
725 | case NEEDS_RETRY: | 725 | case NEEDS_RETRY: |
726 | case FAILED: | 726 | case FAILED: |
727 | break; | 727 | break; |
728 | case ADD_TO_MLQUEUE: | ||
729 | rtn = NEEDS_RETRY; | ||
730 | break; | ||
728 | default: | 731 | default: |
729 | rtn = FAILED; | 732 | rtn = FAILED; |
730 | break; | 733 | break; |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index c44783801402..0547a7f44d42 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -317,6 +317,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, | |||
317 | out_device_destroy: | 317 | out_device_destroy: |
318 | scsi_device_set_state(sdev, SDEV_DEL); | 318 | scsi_device_set_state(sdev, SDEV_DEL); |
319 | transport_destroy_device(&sdev->sdev_gendev); | 319 | transport_destroy_device(&sdev->sdev_gendev); |
320 | put_device(&sdev->sdev_dev); | ||
320 | put_device(&sdev->sdev_gendev); | 321 | put_device(&sdev->sdev_gendev); |
321 | out: | 322 | out: |
322 | if (display_failure_msg) | 323 | if (display_failure_msg) |
@@ -957,6 +958,7 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev) | |||
957 | if (sdev->host->hostt->slave_destroy) | 958 | if (sdev->host->hostt->slave_destroy) |
958 | sdev->host->hostt->slave_destroy(sdev); | 959 | sdev->host->hostt->slave_destroy(sdev); |
959 | transport_destroy_device(&sdev->sdev_gendev); | 960 | transport_destroy_device(&sdev->sdev_gendev); |
961 | put_device(&sdev->sdev_dev); | ||
960 | put_device(&sdev->sdev_gendev); | 962 | put_device(&sdev->sdev_gendev); |
961 | } | 963 | } |
962 | 964 | ||
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index fde54537d715..5c7eb63a19d1 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -864,10 +864,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
864 | goto clean_device; | 864 | goto clean_device; |
865 | } | 865 | } |
866 | 866 | ||
867 | /* take a reference for the sdev_dev; this is | ||
868 | * released by the sdev_class .release */ | ||
869 | get_device(&sdev->sdev_gendev); | ||
870 | |||
871 | /* create queue files, which may be writable, depending on the host */ | 867 | /* create queue files, which may be writable, depending on the host */ |
872 | if (sdev->host->hostt->change_queue_depth) | 868 | if (sdev->host->hostt->change_queue_depth) |
873 | error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw); | 869 | error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw); |
@@ -917,6 +913,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) | |||
917 | 913 | ||
918 | device_del(&sdev->sdev_gendev); | 914 | device_del(&sdev->sdev_gendev); |
919 | transport_destroy_device(&sdev->sdev_gendev); | 915 | transport_destroy_device(&sdev->sdev_gendev); |
916 | put_device(&sdev->sdev_dev); | ||
920 | put_device(&sdev->sdev_gendev); | 917 | put_device(&sdev->sdev_gendev); |
921 | 918 | ||
922 | return error; | 919 | return error; |
@@ -1065,7 +1062,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) | |||
1065 | sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); | 1062 | sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); |
1066 | 1063 | ||
1067 | device_initialize(&sdev->sdev_dev); | 1064 | device_initialize(&sdev->sdev_dev); |
1068 | sdev->sdev_dev.parent = &sdev->sdev_gendev; | 1065 | sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev); |
1069 | sdev->sdev_dev.class = &sdev_class; | 1066 | sdev->sdev_dev.class = &sdev_class; |
1070 | dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d", | 1067 | dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d", |
1071 | sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); | 1068 | sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); |
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index b98885de6876..a67fed10598a 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -3586,6 +3586,7 @@ enum fc_dispatch_result { | |||
3586 | 3586 | ||
3587 | /** | 3587 | /** |
3588 | * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD | 3588 | * fc_bsg_host_dispatch - process fc host bsg requests and dispatch to LLDD |
3589 | * @q: fc host request queue | ||
3589 | * @shost: scsi host rport attached to | 3590 | * @shost: scsi host rport attached to |
3590 | * @job: bsg job to be processed | 3591 | * @job: bsg job to be processed |
3591 | */ | 3592 | */ |
@@ -3693,6 +3694,7 @@ fc_bsg_goose_queue(struct fc_rport *rport) | |||
3693 | 3694 | ||
3694 | /** | 3695 | /** |
3695 | * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD | 3696 | * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD |
3697 | * @q: rport request queue | ||
3696 | * @shost: scsi host rport attached to | 3698 | * @shost: scsi host rport attached to |
3697 | * @rport: rport request destined to | 3699 | * @rport: rport request destined to |
3698 | * @job: bsg job to be processed | 3700 | * @job: bsg job to be processed |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8dd96dcd716c..9093c7261f33 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -116,6 +116,9 @@ static DEFINE_IDA(sd_index_ida); | |||
116 | * object after last put) */ | 116 | * object after last put) */ |
117 | static DEFINE_MUTEX(sd_ref_mutex); | 117 | static DEFINE_MUTEX(sd_ref_mutex); |
118 | 118 | ||
119 | struct kmem_cache *sd_cdb_cache; | ||
120 | mempool_t *sd_cdb_pool; | ||
121 | |||
119 | static const char *sd_cache_types[] = { | 122 | static const char *sd_cache_types[] = { |
120 | "write through", "none", "write back", | 123 | "write through", "none", "write back", |
121 | "write back, no read (daft)" | 124 | "write back, no read (daft)" |
@@ -370,6 +373,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
370 | mutex_unlock(&sd_ref_mutex); | 373 | mutex_unlock(&sd_ref_mutex); |
371 | } | 374 | } |
372 | 375 | ||
376 | static void sd_prot_op(struct scsi_cmnd *scmd, unsigned int dif) | ||
377 | { | ||
378 | unsigned int prot_op = SCSI_PROT_NORMAL; | ||
379 | unsigned int dix = scsi_prot_sg_count(scmd); | ||
380 | |||
381 | if (scmd->sc_data_direction == DMA_FROM_DEVICE) { | ||
382 | if (dif && dix) | ||
383 | prot_op = SCSI_PROT_READ_PASS; | ||
384 | else if (dif && !dix) | ||
385 | prot_op = SCSI_PROT_READ_STRIP; | ||
386 | else if (!dif && dix) | ||
387 | prot_op = SCSI_PROT_READ_INSERT; | ||
388 | } else { | ||
389 | if (dif && dix) | ||
390 | prot_op = SCSI_PROT_WRITE_PASS; | ||
391 | else if (dif && !dix) | ||
392 | prot_op = SCSI_PROT_WRITE_INSERT; | ||
393 | else if (!dif && dix) | ||
394 | prot_op = SCSI_PROT_WRITE_STRIP; | ||
395 | } | ||
396 | |||
397 | scsi_set_prot_op(scmd, prot_op); | ||
398 | scsi_set_prot_type(scmd, dif); | ||
399 | } | ||
400 | |||
373 | /** | 401 | /** |
374 | * sd_init_command - build a scsi (read or write) command from | 402 | * sd_init_command - build a scsi (read or write) command from |
375 | * information in the request structure. | 403 | * information in the request structure. |
@@ -388,6 +416,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
388 | sector_t threshold; | 416 | sector_t threshold; |
389 | unsigned int this_count = blk_rq_sectors(rq); | 417 | unsigned int this_count = blk_rq_sectors(rq); |
390 | int ret, host_dif; | 418 | int ret, host_dif; |
419 | unsigned char protect; | ||
391 | 420 | ||
392 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { | 421 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { |
393 | ret = scsi_setup_blk_pc_cmnd(sdp, rq); | 422 | ret = scsi_setup_blk_pc_cmnd(sdp, rq); |
@@ -520,13 +549,49 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
520 | /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */ | 549 | /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */ |
521 | host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); | 550 | host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); |
522 | if (host_dif) | 551 | if (host_dif) |
523 | SCpnt->cmnd[1] = 1 << 5; | 552 | protect = 1 << 5; |
524 | else | 553 | else |
525 | SCpnt->cmnd[1] = 0; | 554 | protect = 0; |
526 | 555 | ||
527 | if (block > 0xffffffff) { | 556 | if (host_dif == SD_DIF_TYPE2_PROTECTION) { |
557 | SCpnt->cmnd = mempool_alloc(sd_cdb_pool, GFP_ATOMIC); | ||
558 | |||
559 | if (unlikely(SCpnt->cmnd == NULL)) { | ||
560 | ret = BLKPREP_DEFER; | ||
561 | goto out; | ||
562 | } | ||
563 | |||
564 | SCpnt->cmd_len = SD_EXT_CDB_SIZE; | ||
565 | memset(SCpnt->cmnd, 0, SCpnt->cmd_len); | ||
566 | SCpnt->cmnd[0] = VARIABLE_LENGTH_CMD; | ||
567 | SCpnt->cmnd[7] = 0x18; | ||
568 | SCpnt->cmnd[9] = (rq_data_dir(rq) == READ) ? READ_32 : WRITE_32; | ||
569 | SCpnt->cmnd[10] = protect | (blk_fua_rq(rq) ? 0x8 : 0); | ||
570 | |||
571 | /* LBA */ | ||
572 | SCpnt->cmnd[12] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; | ||
573 | SCpnt->cmnd[13] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; | ||
574 | SCpnt->cmnd[14] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; | ||
575 | SCpnt->cmnd[15] = sizeof(block) > 4 ? (unsigned char) (block >> 32) & 0xff : 0; | ||
576 | SCpnt->cmnd[16] = (unsigned char) (block >> 24) & 0xff; | ||
577 | SCpnt->cmnd[17] = (unsigned char) (block >> 16) & 0xff; | ||
578 | SCpnt->cmnd[18] = (unsigned char) (block >> 8) & 0xff; | ||
579 | SCpnt->cmnd[19] = (unsigned char) block & 0xff; | ||
580 | |||
581 | /* Expected Indirect LBA */ | ||
582 | SCpnt->cmnd[20] = (unsigned char) (block >> 24) & 0xff; | ||
583 | SCpnt->cmnd[21] = (unsigned char) (block >> 16) & 0xff; | ||
584 | SCpnt->cmnd[22] = (unsigned char) (block >> 8) & 0xff; | ||
585 | SCpnt->cmnd[23] = (unsigned char) block & 0xff; | ||
586 | |||
587 | /* Transfer length */ | ||
588 | SCpnt->cmnd[28] = (unsigned char) (this_count >> 24) & 0xff; | ||
589 | SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff; | ||
590 | SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff; | ||
591 | SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; | ||
592 | } else if (block > 0xffffffff) { | ||
528 | SCpnt->cmnd[0] += READ_16 - READ_6; | 593 | SCpnt->cmnd[0] += READ_16 - READ_6; |
529 | SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0; | 594 | SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); |
530 | SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; | 595 | SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; |
531 | SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; | 596 | SCpnt->cmnd[3] = sizeof(block) > 4 ? (unsigned char) (block >> 48) & 0xff : 0; |
532 | SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; | 597 | SCpnt->cmnd[4] = sizeof(block) > 4 ? (unsigned char) (block >> 40) & 0xff : 0; |
@@ -547,7 +612,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
547 | this_count = 0xffff; | 612 | this_count = 0xffff; |
548 | 613 | ||
549 | SCpnt->cmnd[0] += READ_10 - READ_6; | 614 | SCpnt->cmnd[0] += READ_10 - READ_6; |
550 | SCpnt->cmnd[1] |= blk_fua_rq(rq) ? 0x8 : 0; | 615 | SCpnt->cmnd[1] = protect | (blk_fua_rq(rq) ? 0x8 : 0); |
551 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; | 616 | SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; |
552 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; | 617 | SCpnt->cmnd[3] = (unsigned char) (block >> 16) & 0xff; |
553 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; | 618 | SCpnt->cmnd[4] = (unsigned char) (block >> 8) & 0xff; |
@@ -578,8 +643,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
578 | 643 | ||
579 | /* If DIF or DIX is enabled, tell HBA how to handle request */ | 644 | /* If DIF or DIX is enabled, tell HBA how to handle request */ |
580 | if (host_dif || scsi_prot_sg_count(SCpnt)) | 645 | if (host_dif || scsi_prot_sg_count(SCpnt)) |
581 | sd_dif_op(SCpnt, host_dif, scsi_prot_sg_count(SCpnt), | 646 | sd_prot_op(SCpnt, host_dif); |
582 | sdkp->protection_type); | ||
583 | 647 | ||
584 | /* | 648 | /* |
585 | * We shouldn't disconnect in the middle of a sector, so with a dumb | 649 | * We shouldn't disconnect in the middle of a sector, so with a dumb |
@@ -1023,6 +1087,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) | |||
1023 | int result = SCpnt->result; | 1087 | int result = SCpnt->result; |
1024 | unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); | 1088 | unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt); |
1025 | struct scsi_sense_hdr sshdr; | 1089 | struct scsi_sense_hdr sshdr; |
1090 | struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk); | ||
1026 | int sense_valid = 0; | 1091 | int sense_valid = 0; |
1027 | int sense_deferred = 0; | 1092 | int sense_deferred = 0; |
1028 | 1093 | ||
@@ -1084,6 +1149,10 @@ static int sd_done(struct scsi_cmnd *SCpnt) | |||
1084 | if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt)) | 1149 | if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt)) |
1085 | sd_dif_complete(SCpnt, good_bytes); | 1150 | sd_dif_complete(SCpnt, good_bytes); |
1086 | 1151 | ||
1152 | if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type) | ||
1153 | == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) | ||
1154 | mempool_free(SCpnt->cmnd, sd_cdb_pool); | ||
1155 | |||
1087 | return good_bytes; | 1156 | return good_bytes; |
1088 | } | 1157 | } |
1089 | 1158 | ||
@@ -1238,34 +1307,28 @@ void sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer) | |||
1238 | u8 type; | 1307 | u8 type; |
1239 | 1308 | ||
1240 | if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) | 1309 | if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) |
1241 | type = 0; | 1310 | return; |
1242 | else | ||
1243 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ | ||
1244 | 1311 | ||
1245 | sdkp->protection_type = type; | 1312 | type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */ |
1246 | 1313 | ||
1247 | switch (type) { | 1314 | if (type == sdkp->protection_type || !sdkp->first_scan) |
1248 | case SD_DIF_TYPE0_PROTECTION: | 1315 | return; |
1249 | case SD_DIF_TYPE1_PROTECTION: | ||
1250 | case SD_DIF_TYPE3_PROTECTION: | ||
1251 | break; | ||
1252 | 1316 | ||
1253 | case SD_DIF_TYPE2_PROTECTION: | 1317 | sdkp->protection_type = type; |
1254 | sd_printk(KERN_ERR, sdkp, "formatted with DIF Type 2 " \ | ||
1255 | "protection which is currently unsupported. " \ | ||
1256 | "Disabling disk!\n"); | ||
1257 | goto disable; | ||
1258 | 1318 | ||
1259 | default: | 1319 | if (type > SD_DIF_TYPE3_PROTECTION) { |
1260 | sd_printk(KERN_ERR, sdkp, "formatted with unknown " \ | 1320 | sd_printk(KERN_ERR, sdkp, "formatted with unsupported " \ |
1261 | "protection type %d. Disabling disk!\n", type); | 1321 | "protection type %u. Disabling disk!\n", type); |
1262 | goto disable; | 1322 | sdkp->capacity = 0; |
1323 | return; | ||
1263 | } | 1324 | } |
1264 | 1325 | ||
1265 | return; | 1326 | if (scsi_host_dif_capable(sdp->host, type)) |
1266 | 1327 | sd_printk(KERN_NOTICE, sdkp, | |
1267 | disable: | 1328 | "Enabling DIF Type %u protection\n", type); |
1268 | sdkp->capacity = 0; | 1329 | else |
1330 | sd_printk(KERN_NOTICE, sdkp, | ||
1331 | "Disabling DIF Type %u protection\n", type); | ||
1269 | } | 1332 | } |
1270 | 1333 | ||
1271 | static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, | 1334 | static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp, |
@@ -2300,8 +2363,24 @@ static int __init init_sd(void) | |||
2300 | if (err) | 2363 | if (err) |
2301 | goto err_out_class; | 2364 | goto err_out_class; |
2302 | 2365 | ||
2366 | sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE, | ||
2367 | 0, 0, NULL); | ||
2368 | if (!sd_cdb_cache) { | ||
2369 | printk(KERN_ERR "sd: can't init extended cdb cache\n"); | ||
2370 | goto err_out_class; | ||
2371 | } | ||
2372 | |||
2373 | sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache); | ||
2374 | if (!sd_cdb_pool) { | ||
2375 | printk(KERN_ERR "sd: can't init extended cdb pool\n"); | ||
2376 | goto err_out_cache; | ||
2377 | } | ||
2378 | |||
2303 | return 0; | 2379 | return 0; |
2304 | 2380 | ||
2381 | err_out_cache: | ||
2382 | kmem_cache_destroy(sd_cdb_cache); | ||
2383 | |||
2305 | err_out_class: | 2384 | err_out_class: |
2306 | class_unregister(&sd_disk_class); | 2385 | class_unregister(&sd_disk_class); |
2307 | err_out: | 2386 | err_out: |
@@ -2321,6 +2400,9 @@ static void __exit exit_sd(void) | |||
2321 | 2400 | ||
2322 | SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); | 2401 | SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); |
2323 | 2402 | ||
2403 | mempool_destroy(sd_cdb_pool); | ||
2404 | kmem_cache_destroy(sd_cdb_cache); | ||
2405 | |||
2324 | scsi_unregister_driver(&sd_template.gendrv); | 2406 | scsi_unregister_driver(&sd_template.gendrv); |
2325 | class_unregister(&sd_disk_class); | 2407 | class_unregister(&sd_disk_class); |
2326 | 2408 | ||
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 8474b5bad3fe..e374804d26fb 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h | |||
@@ -37,6 +37,11 @@ | |||
37 | */ | 37 | */ |
38 | #define SD_LAST_BUGGY_SECTORS 8 | 38 | #define SD_LAST_BUGGY_SECTORS 8 |
39 | 39 | ||
40 | enum { | ||
41 | SD_EXT_CDB_SIZE = 32, /* Extended CDB size */ | ||
42 | SD_MEMPOOL_SIZE = 2, /* CDB pool size */ | ||
43 | }; | ||
44 | |||
40 | struct scsi_disk { | 45 | struct scsi_disk { |
41 | struct scsi_driver *driver; /* always &sd_template */ | 46 | struct scsi_driver *driver; /* always &sd_template */ |
42 | struct scsi_device *device; | 47 | struct scsi_device *device; |
@@ -101,16 +106,12 @@ struct sd_dif_tuple { | |||
101 | 106 | ||
102 | #ifdef CONFIG_BLK_DEV_INTEGRITY | 107 | #ifdef CONFIG_BLK_DEV_INTEGRITY |
103 | 108 | ||
104 | extern void sd_dif_op(struct scsi_cmnd *, unsigned int, unsigned int, unsigned int); | ||
105 | extern void sd_dif_config_host(struct scsi_disk *); | 109 | extern void sd_dif_config_host(struct scsi_disk *); |
106 | extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); | 110 | extern int sd_dif_prepare(struct request *rq, sector_t, unsigned int); |
107 | extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); | 111 | extern void sd_dif_complete(struct scsi_cmnd *, unsigned int); |
108 | 112 | ||
109 | #else /* CONFIG_BLK_DEV_INTEGRITY */ | 113 | #else /* CONFIG_BLK_DEV_INTEGRITY */ |
110 | 114 | ||
111 | static inline void sd_dif_op(struct scsi_cmnd *cmd, unsigned int a, unsigned int b, unsigned int c) | ||
112 | { | ||
113 | } | ||
114 | static inline void sd_dif_config_host(struct scsi_disk *disk) | 115 | static inline void sd_dif_config_host(struct scsi_disk *disk) |
115 | { | 116 | { |
116 | } | 117 | } |
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 82f14a9482d0..88da97745710 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c | |||
@@ -320,15 +320,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp) | |||
320 | dif = 0; dix = 1; | 320 | dif = 0; dix = 1; |
321 | } | 321 | } |
322 | 322 | ||
323 | if (type) { | ||
324 | if (dif) | ||
325 | sd_printk(KERN_NOTICE, sdkp, | ||
326 | "Enabling DIF Type %d protection\n", type); | ||
327 | else | ||
328 | sd_printk(KERN_NOTICE, sdkp, | ||
329 | "Disabling DIF Type %d protection\n", type); | ||
330 | } | ||
331 | |||
332 | if (!dix) | 323 | if (!dix) |
333 | return; | 324 | return; |
334 | 325 | ||
@@ -360,62 +351,6 @@ void sd_dif_config_host(struct scsi_disk *sdkp) | |||
360 | } | 351 | } |
361 | 352 | ||
362 | /* | 353 | /* |
363 | * DIF DMA operation magic decoder ring. | ||
364 | */ | ||
365 | void sd_dif_op(struct scsi_cmnd *scmd, unsigned int dif, unsigned int dix, unsigned int type) | ||
366 | { | ||
367 | int csum_convert, prot_op; | ||
368 | |||
369 | prot_op = 0; | ||
370 | |||
371 | /* Convert checksum? */ | ||
372 | if (scsi_host_get_guard(scmd->device->host) != SHOST_DIX_GUARD_CRC) | ||
373 | csum_convert = 1; | ||
374 | else | ||
375 | csum_convert = 0; | ||
376 | |||
377 | BUG_ON(dif && (scmd->cmnd[0] == READ_6 || scmd->cmnd[0] == WRITE_6)); | ||
378 | |||
379 | switch (scmd->cmnd[0]) { | ||
380 | case READ_6: | ||
381 | case READ_10: | ||
382 | case READ_12: | ||
383 | case READ_16: | ||
384 | if (dif && dix) | ||
385 | if (csum_convert) | ||
386 | prot_op = SCSI_PROT_READ_CONVERT; | ||
387 | else | ||
388 | prot_op = SCSI_PROT_READ_PASS; | ||
389 | else if (dif && !dix) | ||
390 | prot_op = SCSI_PROT_READ_STRIP; | ||
391 | else if (!dif && dix) | ||
392 | prot_op = SCSI_PROT_READ_INSERT; | ||
393 | |||
394 | break; | ||
395 | |||
396 | case WRITE_6: | ||
397 | case WRITE_10: | ||
398 | case WRITE_12: | ||
399 | case WRITE_16: | ||
400 | if (dif && dix) | ||
401 | if (csum_convert) | ||
402 | prot_op = SCSI_PROT_WRITE_CONVERT; | ||
403 | else | ||
404 | prot_op = SCSI_PROT_WRITE_PASS; | ||
405 | else if (dif && !dix) | ||
406 | prot_op = SCSI_PROT_WRITE_INSERT; | ||
407 | else if (!dif && dix) | ||
408 | prot_op = SCSI_PROT_WRITE_STRIP; | ||
409 | |||
410 | break; | ||
411 | } | ||
412 | |||
413 | scsi_set_prot_op(scmd, prot_op); | ||
414 | if (dif) | ||
415 | scsi_set_prot_type(scmd, type); | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * The virtual start sector is the one that was originally submitted | 354 | * The virtual start sector is the one that was originally submitted |
420 | * by the block layer. Due to partitioning, MD/DM cloning, etc. the | 355 | * by the block layer. Due to partitioning, MD/DM cloning, etc. the |
421 | * actual physical start sector is likely to be different. Remap | 356 | * actual physical start sector is likely to be different. Remap |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 747a5e5c1276..040f751809ea 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1708,11 +1708,6 @@ static int sg_finish_rem_req(Sg_request * srp) | |||
1708 | Sg_scatter_hold *req_schp = &srp->data; | 1708 | Sg_scatter_hold *req_schp = &srp->data; |
1709 | 1709 | ||
1710 | SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used)); | 1710 | SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used)); |
1711 | if (srp->res_used) | ||
1712 | sg_unlink_reserve(sfp, srp); | ||
1713 | else | ||
1714 | sg_remove_scat(req_schp); | ||
1715 | |||
1716 | if (srp->rq) { | 1711 | if (srp->rq) { |
1717 | if (srp->bio) | 1712 | if (srp->bio) |
1718 | ret = blk_rq_unmap_user(srp->bio); | 1713 | ret = blk_rq_unmap_user(srp->bio); |
@@ -1720,6 +1715,11 @@ static int sg_finish_rem_req(Sg_request * srp) | |||
1720 | blk_put_request(srp->rq); | 1715 | blk_put_request(srp->rq); |
1721 | } | 1716 | } |
1722 | 1717 | ||
1718 | if (srp->res_used) | ||
1719 | sg_unlink_reserve(sfp, srp); | ||
1720 | else | ||
1721 | sg_remove_scat(req_schp); | ||
1722 | |||
1723 | sg_remove_request(sfp, srp); | 1723 | sg_remove_request(sfp, srp); |
1724 | 1724 | ||
1725 | return ret; | 1725 | return ret; |
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index eb61f7a70e1d..d6f340f48a3b 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
@@ -684,14 +684,20 @@ static void get_sectorsize(struct scsi_cd *cd) | |||
684 | cd->capacity = 0x1fffff; | 684 | cd->capacity = 0x1fffff; |
685 | sector_size = 2048; /* A guess, just in case */ | 685 | sector_size = 2048; /* A guess, just in case */ |
686 | } else { | 686 | } else { |
687 | #if 0 | 687 | long last_written; |
688 | if (cdrom_get_last_written(&cd->cdi, | 688 | |
689 | &cd->capacity)) | 689 | cd->capacity = 1 + ((buffer[0] << 24) | (buffer[1] << 16) | |
690 | #endif | 690 | (buffer[2] << 8) | buffer[3]); |
691 | cd->capacity = 1 + ((buffer[0] << 24) | | 691 | /* |
692 | (buffer[1] << 16) | | 692 | * READ_CAPACITY doesn't return the correct size on |
693 | (buffer[2] << 8) | | 693 | * certain UDF media. If last_written is larger, use |
694 | buffer[3]); | 694 | * it instead. |
695 | * | ||
696 | * http://bugzilla.kernel.org/show_bug.cgi?id=9668 | ||
697 | */ | ||
698 | if (!cdrom_get_last_written(&cd->cdi, &last_written)) | ||
699 | cd->capacity = max_t(long, cd->capacity, last_written); | ||
700 | |||
695 | sector_size = (buffer[4] << 24) | | 701 | sector_size = (buffer[4] << 24) | |
696 | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; | 702 | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; |
697 | switch (sector_size) { | 703 | switch (sector_size) { |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index b33d04250bbc..12d58a7ed6bc 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -2859,11 +2859,8 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon | |||
2859 | ioctl_result = st_int_ioctl(STp, MTBSF, 1); | 2859 | ioctl_result = st_int_ioctl(STp, MTBSF, 1); |
2860 | 2860 | ||
2861 | if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) { | 2861 | if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) { |
2862 | int old_block_size = STp->block_size; | ||
2863 | STp->block_size = arg & MT_ST_BLKSIZE_MASK; | 2862 | STp->block_size = arg & MT_ST_BLKSIZE_MASK; |
2864 | if (STp->block_size != 0) { | 2863 | if (STp->block_size != 0) { |
2865 | if (old_block_size == 0) | ||
2866 | normalize_buffer(STp->buffer); | ||
2867 | (STp->buffer)->buffer_blocks = | 2864 | (STp->buffer)->buffer_blocks = |
2868 | (STp->buffer)->buffer_size / STp->block_size; | 2865 | (STp->buffer)->buffer_size / STp->block_size; |
2869 | } | 2866 | } |