[SCSI] mpt fusion : Setting intial period to 0xFF instead of 0xA
[linux-2.6-block.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
2 * linux/drivers/message/fusion/mptsas.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
0c33b27d 5 *
cddc0ab7 6 * Copyright (c) 1999-2008 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
0c33b27d
CH
8 */
9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10/*
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; version 2 of the License.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 NO WARRANTY
21 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 solely responsible for determining the appropriateness of using and
26 distributing the Program and assumes all risks associated with its
27 exercise of rights under this Agreement, including but not limited to
28 the risks and costs of program errors, damage to or loss of data,
29 programs or equipment, and unavailability or interruption of operations.
30
31 DISCLAIMER OF LIABILITY
32 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43*/
44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
45
46#include <linux/module.h>
47#include <linux/kernel.h>
48#include <linux/init.h>
49#include <linux/errno.h>
cd354f1a 50#include <linux/jiffies.h>
0c33b27d 51#include <linux/workqueue.h>
547f9a21 52#include <linux/delay.h> /* for mdelay */
0c33b27d 53
547f9a21 54#include <scsi/scsi.h>
0c33b27d
CH
55#include <scsi/scsi_cmnd.h>
56#include <scsi/scsi_device.h>
57#include <scsi/scsi_host.h>
58#include <scsi/scsi_transport_sas.h>
547f9a21 59#include <scsi/scsi_dbg.h>
0c33b27d
CH
60
61#include "mptbase.h"
62#include "mptscsih.h"
56af97ae 63#include "mptsas.h"
0c33b27d
CH
64
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
e8bf3941
JB
70/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
0c33b27d
CH
75MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
9f4203b3 78MODULE_VERSION(my_VERSION);
0c33b27d 79
0c33b27d
CH
80static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
ba856d32 83 " Clear persistency table: enable=1 "
0c33b27d
CH
84 "(default=MPTSCSIH_PT_CLEAR=0)");
85
793955f5
EM
86/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
87#define MPTSAS_MAX_LUN (16895)
88static int max_lun = MPTSAS_MAX_LUN;
89module_param(max_lun, int, 0);
90MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
91
f606f571
PS
92static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
93static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
0c33b27d 96
b506ade9 97static void mptsas_hotplug_work(struct work_struct *work);
0c33b27d 98
d6ecdd63
PS
99static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
100 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
101{
29dd3609
EM
102 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
103 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
104 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
105 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
106 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
107 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
108 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
109 ioc->name, phy_data->Port));
110 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
111 ioc->name, phy_data->PortFlags));
112 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
113 ioc->name, phy_data->PhyFlags));
114 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
115 ioc->name, phy_data->NegotiatedLinkRate));
116 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
117 "Controller PHY Device Info=0x%X\n", ioc->name,
118 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
119 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
120 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
b5141128
CH
121}
122
d6ecdd63 123static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
b5141128
CH
124{
125 __le64 sas_address;
126
127 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
128
29dd3609
EM
129 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
130 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
131 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
132 "Attached Device Handle=0x%X\n", ioc->name,
133 le16_to_cpu(pg0->AttachedDevHandle)));
134 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
135 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
136 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
137 "Attached PHY Identifier=0x%X\n", ioc->name,
138 pg0->AttachedPhyIdentifier));
139 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
140 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
141 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
142 ioc->name, pg0->ProgrammedLinkRate));
143 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
144 ioc->name, pg0->ChangeCount));
145 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
146 ioc->name, le32_to_cpu(pg0->PhyInfo)));
b5141128
CH
147}
148
d6ecdd63 149static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
b5141128 150{
29dd3609
EM
151 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
152 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
153 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
154 ioc->name, pg1->InvalidDwordCount));
155 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
156 "Running Disparity Error Count=0x%x\n", ioc->name,
157 pg1->RunningDisparityErrorCount));
158 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
159 "Loss Dword Synch Count=0x%x\n", ioc->name,
160 pg1->LossDwordSynchCount));
161 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
162 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
163 pg1->PhyResetProblemCount));
b5141128
CH
164}
165
d6ecdd63 166static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
b5141128
CH
167{
168 __le64 sas_address;
169
170 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
171
29dd3609
EM
172 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
173 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
174 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
175 ioc->name, le16_to_cpu(pg0->DevHandle)));
176 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
177 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
178 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
179 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
180 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
181 ioc->name, le16_to_cpu(pg0->Slot)));
182 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
183 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
184 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
185 ioc->name, pg0->TargetID));
186 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
187 ioc->name, pg0->Bus));
188 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
189 ioc->name, pg0->PhyNum));
190 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
191 ioc->name, le16_to_cpu(pg0->AccessStatus)));
192 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
193 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
194 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
195 ioc->name, le16_to_cpu(pg0->Flags)));
196 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
197 ioc->name, pg0->PhysicalPort));
b5141128
CH
198}
199
d6ecdd63
PS
200static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
201{
29dd3609
EM
202 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
203 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
204 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
205 ioc->name, pg1->PhysicalPort));
206 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
207 ioc->name, pg1->PhyIdentifier));
208 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
209 ioc->name, pg1->NegotiatedLinkRate));
210 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
211 ioc->name, pg1->ProgrammedLinkRate));
212 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
213 ioc->name, pg1->HwLinkRate));
214 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
215 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
216 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
217 "Attached Device Handle=0x%X\n\n", ioc->name,
218 le16_to_cpu(pg1->AttachedDevHandle)));
b5141128 219}
b5141128 220
e3094447
CH
221static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
222{
223 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
224 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
225}
226
227static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
228{
229 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
230 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
231}
232
7748369f
MR
233static struct mptsas_portinfo *
234mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
235{
236 struct list_head *head = &ioc->sas_topology;
237 struct mptsas_portinfo *pi = NULL;
238
239 /* always the first entry on sas_topology list */
240
241 if (!list_empty(head))
242 pi = list_entry(head->next, struct mptsas_portinfo, list);
243
244 return pi;
245}
246
e6b2d76a
ME
247/*
248 * mptsas_find_portinfo_by_handle
249 *
250 * This function should be called with the sas_topology_mutex already held
251 */
252static struct mptsas_portinfo *
253mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
254{
255 struct mptsas_portinfo *port_info, *rc=NULL;
256 int i;
257
258 list_for_each_entry(port_info, &ioc->sas_topology, list)
259 for (i = 0; i < port_info->num_phys; i++)
260 if (port_info->phy_info[i].identify.handle == handle) {
261 rc = port_info;
262 goto out;
263 }
264 out:
265 return rc;
266}
267
bd23e94c
ME
268/*
269 * Returns true if there is a scsi end device
270 */
271static inline int
272mptsas_is_end_device(struct mptsas_devinfo * attached)
273{
547f9a21 274 if ((attached->sas_address) &&
bd23e94c
ME
275 (attached->device_info &
276 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
277 ((attached->device_info &
278 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
279 (attached->device_info &
280 MPI_SAS_DEVICE_INFO_STP_TARGET) |
281 (attached->device_info &
282 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
283 return 1;
284 else
285 return 0;
286}
287
547f9a21 288/* no mutex */
376ac830 289static void
d6ecdd63 290mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
547f9a21
EM
291{
292 struct mptsas_portinfo *port_info;
293 struct mptsas_phyinfo *phy_info;
294 u8 i;
295
296 if (!port_details)
297 return;
298
299 port_info = port_details->port_info;
300 phy_info = port_info->phy_info;
301
29dd3609
EM
302 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
303 "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details,
f99be43b
EM
304 port_details->num_phys, (unsigned long long)
305 port_details->phy_bitmask));
547f9a21
EM
306
307 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
308 if(phy_info->port_details != port_details)
309 continue;
310 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
311 phy_info->port_details = NULL;
312 }
313 kfree(port_details);
314}
315
316static inline struct sas_rphy *
317mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
318{
319 if (phy_info->port_details)
320 return phy_info->port_details->rphy;
321 else
322 return NULL;
323}
324
325static inline void
d6ecdd63 326mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
547f9a21
EM
327{
328 if (phy_info->port_details) {
329 phy_info->port_details->rphy = rphy;
29dd3609
EM
330 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
331 ioc->name, rphy));
547f9a21
EM
332 }
333
547f9a21 334 if (rphy) {
c51d0bea
EM
335 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
336 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
337 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
338 ioc->name, rphy, rphy->dev.release));
547f9a21 339 }
547f9a21
EM
340}
341
342static inline struct sas_port *
343mptsas_get_port(struct mptsas_phyinfo *phy_info)
344{
345 if (phy_info->port_details)
346 return phy_info->port_details->port;
347 else
348 return NULL;
349}
350
351static inline void
d6ecdd63 352mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
547f9a21
EM
353{
354 if (phy_info->port_details)
355 phy_info->port_details->port = port;
356
547f9a21 357 if (port) {
c51d0bea
EM
358 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
359 &port->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
360 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
361 ioc->name, port, port->dev.release));
547f9a21 362 }
547f9a21
EM
363}
364
365static inline struct scsi_target *
366mptsas_get_starget(struct mptsas_phyinfo *phy_info)
367{
368 if (phy_info->port_details)
369 return phy_info->port_details->starget;
370 else
371 return NULL;
372}
373
374static inline void
375mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
376starget)
377{
378 if (phy_info->port_details)
379 phy_info->port_details->starget = starget;
380}
381
382
383/*
384 * mptsas_setup_wide_ports
385 *
386 * Updates for new and existing narrow/wide port configuration
387 * in the sas_topology
388 */
376ac830 389static void
547f9a21
EM
390mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
391{
392 struct mptsas_portinfo_details * port_details;
393 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
394 u64 sas_address;
395 int i, j;
396
397 mutex_lock(&ioc->sas_topology_mutex);
398
399 phy_info = port_info->phy_info;
400 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
401 if (phy_info->attached.handle)
402 continue;
403 port_details = phy_info->port_details;
404 if (!port_details)
405 continue;
406 if (port_details->num_phys < 2)
407 continue;
408 /*
409 * Removing a phy from a port, letting the last
410 * phy be removed by firmware events.
411 */
29dd3609
EM
412 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
413 "%s: [%p]: deleting phy = %d\n",
414 ioc->name, __FUNCTION__, port_details, i));
547f9a21
EM
415 port_details->num_phys--;
416 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
417 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
418 sas_port_delete_phy(port_details->port, phy_info->phy);
419 phy_info->port_details = NULL;
420 }
421
422 /*
423 * Populate and refresh the tree
424 */
425 phy_info = port_info->phy_info;
426 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
427 sas_address = phy_info->attached.sas_address;
29dd3609
EM
428 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
429 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
430 if (!sas_address)
431 continue;
432 port_details = phy_info->port_details;
433 /*
434 * Forming a port
435 */
436 if (!port_details) {
437 port_details = kzalloc(sizeof(*port_details),
438 GFP_KERNEL);
439 if (!port_details)
440 goto out;
441 port_details->num_phys = 1;
442 port_details->port_info = port_info;
547f9a21
EM
443 if (phy_info->phy_id < 64 )
444 port_details->phy_bitmask |=
445 (1 << phy_info->phy_id);
446 phy_info->sas_port_add_phy=1;
29dd3609 447 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
f99be43b 448 "phy_id=%d sas_address=0x%018llX\n",
29dd3609 449 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
450 phy_info->port_details = port_details;
451 }
452
453 if (i == port_info->num_phys - 1)
454 continue;
455 phy_info_cmp = &port_info->phy_info[i + 1];
456 for (j = i + 1 ; j < port_info->num_phys ; j++,
457 phy_info_cmp++) {
458 if (!phy_info_cmp->attached.sas_address)
459 continue;
460 if (sas_address != phy_info_cmp->attached.sas_address)
461 continue;
462 if (phy_info_cmp->port_details == port_details )
463 continue;
29dd3609 464 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 465 "\t\tphy_id=%d sas_address=0x%018llX\n",
29dd3609 466 ioc->name, j, (unsigned long long)
f99be43b 467 phy_info_cmp->attached.sas_address));
547f9a21
EM
468 if (phy_info_cmp->port_details) {
469 port_details->rphy =
470 mptsas_get_rphy(phy_info_cmp);
471 port_details->port =
472 mptsas_get_port(phy_info_cmp);
473 port_details->starget =
474 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
475 port_details->num_phys =
476 phy_info_cmp->port_details->num_phys;
547f9a21
EM
477 if (!phy_info_cmp->port_details->num_phys)
478 kfree(phy_info_cmp->port_details);
479 } else
480 phy_info_cmp->sas_port_add_phy=1;
481 /*
482 * Adding a phy to a port
483 */
484 phy_info_cmp->port_details = port_details;
485 if (phy_info_cmp->phy_id < 64 )
486 port_details->phy_bitmask |=
487 (1 << phy_info_cmp->phy_id);
488 port_details->num_phys++;
489 }
490 }
491
492 out:
493
547f9a21
EM
494 for (i = 0; i < port_info->num_phys; i++) {
495 port_details = port_info->phy_info[i].port_details;
496 if (!port_details)
497 continue;
29dd3609 498 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 499 "%s: [%p]: phy_id=%02d num_phys=%02d "
29dd3609 500 "bitmask=0x%016llX\n", ioc->name, __FUNCTION__,
f99be43b
EM
501 port_details, i, port_details->num_phys,
502 (unsigned long long)port_details->phy_bitmask));
29dd3609
EM
503 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
504 ioc->name, port_details->port, port_details->rphy));
547f9a21 505 }
29dd3609 506 dsaswideprintk(ioc, printk("\n"));
547f9a21
EM
507 mutex_unlock(&ioc->sas_topology_mutex);
508}
509
df9e062a
EM
510/**
511 * csmisas_find_vtarget
512 *
513 * @ioc
514 * @volume_id
515 * @volume_bus
516 *
517 **/
518static VirtTarget *
519mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
520{
521 struct scsi_device *sdev;
a69de507 522 VirtDevice *vdevice;
df9e062a
EM
523 VirtTarget *vtarget = NULL;
524
525 shost_for_each_device(sdev, ioc->sh) {
a69de507 526 if ((vdevice = sdev->hostdata) == NULL)
df9e062a 527 continue;
a69de507
EM
528 if (vdevice->vtarget->id == id &&
529 vdevice->vtarget->channel == channel)
530 vtarget = vdevice->vtarget;
df9e062a
EM
531 }
532 return vtarget;
533}
534
535/**
536 * mptsas_target_reset
537 *
538 * Issues TARGET_RESET to end device using handshaking method
539 *
540 * @ioc
541 * @channel
542 * @id
543 *
544 * Returns (1) success
545 * (0) failure
546 *
547 **/
548static int
549mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
550{
551 MPT_FRAME_HDR *mf;
552 SCSITaskMgmt_t *pScsiTm;
553
554 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
d6ecdd63 555 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
df9e062a
EM
556 ioc->name,__FUNCTION__, __LINE__));
557 return 0;
558 }
559
560 /* Format the Request
561 */
562 pScsiTm = (SCSITaskMgmt_t *) mf;
563 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
564 pScsiTm->TargetID = id;
565 pScsiTm->Bus = channel;
566 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
567 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
568 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
569
d6ecdd63 570 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
df9e062a 571
7a195f46 572 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
df9e062a
EM
573
574 return 1;
575}
576
577/**
578 * mptsas_target_reset_queue
579 *
580 * Receive request for TARGET_RESET after recieving an firmware
581 * event NOT_RESPONDING_EVENT, then put command in link list
582 * and queue if task_queue already in use.
583 *
584 * @ioc
585 * @sas_event_data
586 *
587 **/
547f9a21 588static void
df9e062a
EM
589mptsas_target_reset_queue(MPT_ADAPTER *ioc,
590 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
547f9a21 591{
e7eae9f6 592 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
593 VirtTarget *vtarget = NULL;
594 struct mptsas_target_reset_event *target_reset_list;
595 u8 id, channel;
547f9a21 596
df9e062a
EM
597 id = sas_event_data->TargetID;
598 channel = sas_event_data->Bus;
599
600 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
601 return;
602
603 vtarget->deleted = 1; /* block IO */
604
605 target_reset_list = kzalloc(sizeof(*target_reset_list),
606 GFP_ATOMIC);
607 if (!target_reset_list) {
d6ecdd63 608 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
df9e062a
EM
609 ioc->name,__FUNCTION__, __LINE__));
610 return;
611 }
612
613 memcpy(&target_reset_list->sas_event_data, sas_event_data,
614 sizeof(*sas_event_data));
615 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
616
617 if (hd->resetPending)
618 return;
619
620 if (mptsas_target_reset(ioc, channel, id)) {
621 target_reset_list->target_reset_issued = 1;
622 hd->resetPending = 1;
623 }
624}
625
626/**
627 * mptsas_dev_reset_complete
628 *
629 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
630 * enable work queue to finish off removing device from upper layers.
631 * then send next TARGET_RESET in the queue.
632 *
633 * @ioc
634 *
635 **/
636static void
637mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
638{
e7eae9f6 639 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
640 struct list_head *head = &hd->target_reset_list;
641 struct mptsas_target_reset_event *target_reset_list;
642 struct mptsas_hotplug_event *ev;
643 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
644 u8 id, channel;
645 __le64 sas_address;
646
647 if (list_empty(head))
648 return;
649
650 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
651
652 sas_event_data = &target_reset_list->sas_event_data;
653 id = sas_event_data->TargetID;
654 channel = sas_event_data->Bus;
655 hd->resetPending = 0;
656
657 /*
658 * retry target reset
659 */
660 if (!target_reset_list->target_reset_issued) {
661 if (mptsas_target_reset(ioc, channel, id)) {
662 target_reset_list->target_reset_issued = 1;
663 hd->resetPending = 1;
664 }
665 return;
666 }
667
668 /*
669 * enable work queue to remove device from upper layers
670 */
671 list_del(&target_reset_list->list);
672
673 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
674 if (!ev) {
d6ecdd63 675 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
df9e062a
EM
676 ioc->name,__FUNCTION__, __LINE__));
677 return;
678 }
679
680 INIT_WORK(&ev->work, mptsas_hotplug_work);
681 ev->ioc = ioc;
682 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
683 ev->parent_handle =
684 le16_to_cpu(sas_event_data->ParentDevHandle);
685 ev->channel = channel;
686 ev->id =id;
687 ev->phy_id = sas_event_data->PhyNum;
688 memcpy(&sas_address, &sas_event_data->SASAddress,
689 sizeof(__le64));
690 ev->sas_address = le64_to_cpu(sas_address);
691 ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
692 ev->event_type = MPTSAS_DEL_DEVICE;
693 schedule_work(&ev->work);
694 kfree(target_reset_list);
695
696 /*
697 * issue target reset to next device in the queue
698 */
699
700 head = &hd->target_reset_list;
701 if (list_empty(head))
702 return;
703
704 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
705 list);
706
707 sas_event_data = &target_reset_list->sas_event_data;
708 id = sas_event_data->TargetID;
709 channel = sas_event_data->Bus;
710
711 if (mptsas_target_reset(ioc, channel, id)) {
712 target_reset_list->target_reset_issued = 1;
713 hd->resetPending = 1;
714 }
715}
716
717/**
718 * mptsas_taskmgmt_complete
719 *
720 * @ioc
721 * @mf
722 * @mr
723 *
724 **/
725static int
726mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
727{
728 mptsas_dev_reset_complete(ioc);
729 return mptscsih_taskmgmt_complete(ioc, mf, mr);
730}
731
732/**
733 * mptscsih_ioc_reset
734 *
735 * @ioc
736 * @reset_phase
737 *
738 **/
739static int
740mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
741{
ba76ef24 742 MPT_SCSI_HOST *hd;
df9e062a
EM
743 struct mptsas_target_reset_event *target_reset_list, *n;
744 int rc;
745
746 rc = mptscsih_ioc_reset(ioc, reset_phase);
747
748 if (ioc->bus_type != SAS)
749 goto out;
750
751 if (reset_phase != MPT_IOC_POST_RESET)
752 goto out;
753
ba76ef24
JL
754 if (!ioc->sh || !ioc->sh->hostdata)
755 goto out;
e7eae9f6 756 hd = shost_priv(ioc->sh);
ba76ef24 757 if (!hd->ioc)
df9e062a
EM
758 goto out;
759
760 if (list_empty(&hd->target_reset_list))
761 goto out;
762
763 /* flush the target_reset_list */
764 list_for_each_entry_safe(target_reset_list, n,
765 &hd->target_reset_list, list) {
766 list_del(&target_reset_list->list);
767 kfree(target_reset_list);
547f9a21 768 }
df9e062a
EM
769
770 out:
771 return rc;
547f9a21
EM
772}
773
e3094447 774static int
52435430 775mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
776 u32 form, u32 form_specific)
777{
778 ConfigExtendedPageHeader_t hdr;
779 CONFIGPARMS cfg;
780 SasEnclosurePage0_t *buffer;
781 dma_addr_t dma_handle;
782 int error;
783 __le64 le_identifier;
784
785 memset(&hdr, 0, sizeof(hdr));
786 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
787 hdr.PageNumber = 0;
788 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
789 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
790
791 cfg.cfghdr.ehdr = &hdr;
792 cfg.physAddr = -1;
793 cfg.pageAddr = form + form_specific;
794 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
795 cfg.dir = 0; /* read */
796 cfg.timeout = 10;
797
798 error = mpt_config(ioc, &cfg);
799 if (error)
800 goto out;
801 if (!hdr.ExtPageLength) {
802 error = -ENXIO;
803 goto out;
804 }
805
806 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
807 &dma_handle);
808 if (!buffer) {
809 error = -ENOMEM;
810 goto out;
811 }
812
813 cfg.physAddr = dma_handle;
814 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
815
816 error = mpt_config(ioc, &cfg);
817 if (error)
818 goto out_free_consistent;
819
820 /* save config data */
821 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
822 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
823 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
824 enclosure->flags = le16_to_cpu(buffer->Flags);
825 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
826 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
827 enclosure->start_id = buffer->StartTargetID;
828 enclosure->start_channel = buffer->StartBus;
829 enclosure->sep_id = buffer->SEPTargetID;
830 enclosure->sep_channel = buffer->SEPBus;
831
832 out_free_consistent:
833 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
834 buffer, dma_handle);
835 out:
836 return error;
837}
b5141128 838
f013db32
JB
839static int
840mptsas_slave_configure(struct scsi_device *sdev)
841{
3c0c25b9 842
e8bf3941
JB
843 if (sdev->channel == MPTSAS_RAID_CHANNEL)
844 goto out;
845
846 sas_read_port_mode_page(sdev);
f013db32 847
e8bf3941 848 out:
f013db32
JB
849 return mptscsih_slave_configure(sdev);
850}
851
547f9a21
EM
852static int
853mptsas_target_alloc(struct scsi_target *starget)
854{
855 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 856 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21 857 VirtTarget *vtarget;
793955f5 858 u8 id, channel;
547f9a21
EM
859 struct sas_rphy *rphy;
860 struct mptsas_portinfo *p;
861 int i;
e80b002b 862 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
863
864 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
865 if (!vtarget)
866 return -ENOMEM;
867
868 vtarget->starget = starget;
e80b002b 869 vtarget->ioc_id = ioc->id;
793955f5
EM
870 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
871 id = starget->id;
547f9a21
EM
872 channel = 0;
873
793955f5
EM
874 /*
875 * RAID volumes placed beyond the last expected port.
876 */
877 if (starget->channel == MPTSAS_RAID_CHANNEL) {
e80b002b
EM
878 for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
879 if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
880 channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
547f9a21 881 goto out;
793955f5 882 }
547f9a21
EM
883
884 rphy = dev_to_rphy(starget->dev.parent);
e80b002b
EM
885 mutex_lock(&ioc->sas_topology_mutex);
886 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
887 for (i = 0; i < p->num_phys; i++) {
888 if (p->phy_info[i].attached.sas_address !=
889 rphy->identify.sas_address)
890 continue;
793955f5 891 id = p->phy_info[i].attached.id;
547f9a21
EM
892 channel = p->phy_info[i].attached.channel;
893 mptsas_set_starget(&p->phy_info[i], starget);
894
895 /*
896 * Exposing hidden raid components
897 */
e80b002b
EM
898 if (mptscsih_is_phys_disk(ioc, channel, id)) {
899 id = mptscsih_raid_id_to_num(ioc,
793955f5 900 channel, id);
547f9a21
EM
901 vtarget->tflags |=
902 MPT_TARGET_FLAGS_RAID_COMPONENT;
b506ade9 903 p->phy_info[i].attached.phys_disk_num = id;
547f9a21 904 }
e80b002b 905 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
906 goto out;
907 }
908 }
e80b002b 909 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
910
911 kfree(vtarget);
912 return -ENXIO;
913
914 out:
793955f5
EM
915 vtarget->id = id;
916 vtarget->channel = channel;
547f9a21
EM
917 starget->hostdata = vtarget;
918 return 0;
919}
920
921static void
922mptsas_target_destroy(struct scsi_target *starget)
923{
924 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 925 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21
EM
926 struct sas_rphy *rphy;
927 struct mptsas_portinfo *p;
928 int i;
e80b002b 929 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
930
931 if (!starget->hostdata)
932 return;
933
e8bf3941 934 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
935 goto out;
936
937 rphy = dev_to_rphy(starget->dev.parent);
e80b002b 938 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
939 for (i = 0; i < p->num_phys; i++) {
940 if (p->phy_info[i].attached.sas_address !=
941 rphy->identify.sas_address)
942 continue;
943 mptsas_set_starget(&p->phy_info[i], NULL);
944 goto out;
945 }
946 }
947
948 out:
949 kfree(starget->hostdata);
950 starget->hostdata = NULL;
951}
952
953
0c33b27d 954static int
c7c82987 955mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 956{
c7c82987 957 struct Scsi_Host *host = sdev->host;
e7eae9f6 958 MPT_SCSI_HOST *hd = shost_priv(host);
0c33b27d
CH
959 struct sas_rphy *rphy;
960 struct mptsas_portinfo *p;
a69de507 961 VirtDevice *vdevice;
c7c82987 962 struct scsi_target *starget;
547f9a21 963 int i;
e80b002b 964 MPT_ADAPTER *ioc = hd->ioc;
0c33b27d 965
a69de507
EM
966 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
967 if (!vdevice) {
547f9a21 968 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
e80b002b 969 ioc->name, sizeof(VirtDevice));
0c33b27d
CH
970 return -ENOMEM;
971 }
c7c82987 972 starget = scsi_target(sdev);
a69de507 973 vdevice->vtarget = starget->hostdata;
0c33b27d 974
e8bf3941 975 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 976 goto out;
816aa907 977
c7c82987 978 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
e80b002b
EM
979 mutex_lock(&ioc->sas_topology_mutex);
980 list_for_each_entry(p, &ioc->sas_topology, list) {
0c33b27d 981 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
982 if (p->phy_info[i].attached.sas_address !=
983 rphy->identify.sas_address)
984 continue;
a69de507 985 vdevice->lun = sdev->lun;
547f9a21
EM
986 /*
987 * Exposing hidden raid components
988 */
e80b002b 989 if (mptscsih_is_phys_disk(ioc,
793955f5
EM
990 p->phy_info[i].attached.channel,
991 p->phy_info[i].attached.id))
547f9a21 992 sdev->no_uld_attach = 1;
e80b002b 993 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21 994 goto out;
0c33b27d
CH
995 }
996 }
e80b002b 997 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d 998
a69de507 999 kfree(vdevice);
23f236ed 1000 return -ENXIO;
0c33b27d
CH
1001
1002 out:
a69de507
EM
1003 vdevice->vtarget->num_luns++;
1004 sdev->hostdata = vdevice;
0c33b27d
CH
1005 return 0;
1006}
1007
547f9a21
EM
1008static int
1009mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 1010{
a69de507 1011 VirtDevice *vdevice = SCpnt->device->hostdata;
7d3eecf7 1012
a69de507 1013 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
547f9a21
EM
1014 SCpnt->result = DID_NO_CONNECT << 16;
1015 done(SCpnt);
1016 return 0;
7d3eecf7 1017 }
547f9a21 1018
793955f5
EM
1019// scsi_print_command(SCpnt);
1020
547f9a21 1021 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
1022}
1023
547f9a21 1024
0c33b27d 1025static struct scsi_host_template mptsas_driver_template = {
f78496da 1026 .module = THIS_MODULE,
0c33b27d
CH
1027 .proc_name = "mptsas",
1028 .proc_info = mptscsih_proc_info,
1029 .name = "MPT SPI Host",
1030 .info = mptscsih_info,
547f9a21
EM
1031 .queuecommand = mptsas_qcmd,
1032 .target_alloc = mptsas_target_alloc,
0c33b27d 1033 .slave_alloc = mptsas_slave_alloc,
f013db32 1034 .slave_configure = mptsas_slave_configure,
547f9a21
EM
1035 .target_destroy = mptsas_target_destroy,
1036 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
1037 .change_queue_depth = mptscsih_change_queue_depth,
1038 .eh_abort_handler = mptscsih_abort,
1039 .eh_device_reset_handler = mptscsih_dev_reset,
1040 .eh_bus_reset_handler = mptscsih_bus_reset,
1041 .eh_host_reset_handler = mptscsih_host_reset,
1042 .bios_param = mptscsih_bios_param,
1043 .can_queue = MPT_FC_CAN_QUEUE,
1044 .this_id = -1,
1045 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1046 .max_sectors = 8192,
1047 .cmd_per_lun = 7,
1048 .use_clustering = ENABLE_CLUSTERING,
edb9068d 1049 .shost_attrs = mptscsih_host_attrs,
0c33b27d
CH
1050};
1051
b5141128 1052static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 1053{
b5141128
CH
1054 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1055 ConfigExtendedPageHeader_t hdr;
1056 CONFIGPARMS cfg;
1057 SasPhyPage1_t *buffer;
1058 dma_addr_t dma_handle;
1059 int error;
0c33b27d 1060
f4ad7b58
JB
1061 /* FIXME: only have link errors on local phys */
1062 if (!scsi_is_sas_phy_local(phy))
1063 return -EINVAL;
1064
b5141128
CH
1065 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1066 hdr.ExtPageLength = 0;
1067 hdr.PageNumber = 1 /* page number 1*/;
1068 hdr.Reserved1 = 0;
1069 hdr.Reserved2 = 0;
1070 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1071 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 1072
b5141128
CH
1073 cfg.cfghdr.ehdr = &hdr;
1074 cfg.physAddr = -1;
1075 cfg.pageAddr = phy->identify.phy_identifier;
1076 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1077 cfg.dir = 0; /* read */
1078 cfg.timeout = 10;
0c33b27d 1079
b5141128
CH
1080 error = mpt_config(ioc, &cfg);
1081 if (error)
1082 return error;
1083 if (!hdr.ExtPageLength)
1084 return -ENXIO;
0c33b27d 1085
b5141128
CH
1086 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1087 &dma_handle);
1088 if (!buffer)
1089 return -ENOMEM;
0c33b27d 1090
b5141128
CH
1091 cfg.physAddr = dma_handle;
1092 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1093
1094 error = mpt_config(ioc, &cfg);
1095 if (error)
1096 goto out_free_consistent;
1097
d6ecdd63 1098 mptsas_print_phy_pg1(ioc, buffer);
b5141128
CH
1099
1100 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1101 phy->running_disparity_error_count =
1102 le32_to_cpu(buffer->RunningDisparityErrorCount);
1103 phy->loss_of_dword_sync_count =
1104 le32_to_cpu(buffer->LossDwordSynchCount);
1105 phy->phy_reset_problem_count =
1106 le32_to_cpu(buffer->PhyResetProblemCount);
1107
1108 out_free_consistent:
1109 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1110 buffer, dma_handle);
1111 return error;
0c33b27d
CH
1112}
1113
da4fa655
CH
1114static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1115 MPT_FRAME_HDR *reply)
1116{
1117 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
1118 if (reply != NULL) {
1119 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
1120 memcpy(ioc->sas_mgmt.reply, reply,
1121 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1122 }
1123 complete(&ioc->sas_mgmt.done);
1124 return 1;
1125}
1126
1127static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1128{
1129 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1130 SasIoUnitControlRequest_t *req;
1131 SasIoUnitControlReply_t *reply;
1132 MPT_FRAME_HDR *mf;
1133 MPIHeader_t *hdr;
1134 unsigned long timeleft;
1135 int error = -ERESTARTSYS;
1136
f4ad7b58
JB
1137 /* FIXME: fusion doesn't allow non-local phy reset */
1138 if (!scsi_is_sas_phy_local(phy))
1139 return -EINVAL;
1140
da4fa655
CH
1141 /* not implemented for expanders */
1142 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1143 return -ENXIO;
1144
eeb846ce 1145 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
1146 goto out;
1147
1148 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1149 if (!mf) {
1150 error = -ENOMEM;
1151 goto out_unlock;
1152 }
1153
1154 hdr = (MPIHeader_t *) mf;
1155 req = (SasIoUnitControlRequest_t *)mf;
1156 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
1157 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
1158 req->MsgContext = hdr->MsgContext;
1159 req->Operation = hard_reset ?
1160 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
1161 req->PhyNum = phy->identify.phy_identifier;
1162
1163 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1164
1165 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
1166 10 * HZ);
1167 if (!timeleft) {
1168 /* On timeout reset the board */
1169 mpt_free_msg_frame(ioc, mf);
1170 mpt_HardResetHandler(ioc, CAN_SLEEP);
1171 error = -ETIMEDOUT;
1172 goto out_unlock;
1173 }
1174
1175 /* a reply frame is expected */
1176 if ((ioc->sas_mgmt.status &
1177 MPT_IOCTL_STATUS_RF_VALID) == 0) {
1178 error = -ENXIO;
1179 goto out_unlock;
1180 }
1181
1182 /* process the completed Reply Message Frame */
1183 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
1184 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
29dd3609
EM
1185 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
1186 ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo);
da4fa655
CH
1187 error = -ENXIO;
1188 goto out_unlock;
1189 }
1190
1191 error = 0;
1192
1193 out_unlock:
eeb846ce 1194 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
1195 out:
1196 return error;
1197}
0c33b27d 1198
e3094447
CH
1199static int
1200mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1201{
1202 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1203 int i, error;
1204 struct mptsas_portinfo *p;
1205 struct mptsas_enclosure enclosure_info;
1206 u64 enclosure_handle;
1207
1208 mutex_lock(&ioc->sas_topology_mutex);
1209 list_for_each_entry(p, &ioc->sas_topology, list) {
1210 for (i = 0; i < p->num_phys; i++) {
1211 if (p->phy_info[i].attached.sas_address ==
1212 rphy->identify.sas_address) {
1213 enclosure_handle = p->phy_info[i].
1214 attached.handle_enclosure;
1215 goto found_info;
1216 }
1217 }
1218 }
1219 mutex_unlock(&ioc->sas_topology_mutex);
1220 return -ENXIO;
1221
1222 found_info:
1223 mutex_unlock(&ioc->sas_topology_mutex);
1224 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 1225 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
1226 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1227 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1228 if (!error)
1229 *identifier = enclosure_info.enclosure_logical_id;
1230 return error;
1231}
1232
1233static int
1234mptsas_get_bay_identifier(struct sas_rphy *rphy)
1235{
1236 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1237 struct mptsas_portinfo *p;
1238 int i, rc;
1239
1240 mutex_lock(&ioc->sas_topology_mutex);
1241 list_for_each_entry(p, &ioc->sas_topology, list) {
1242 for (i = 0; i < p->num_phys; i++) {
1243 if (p->phy_info[i].attached.sas_address ==
1244 rphy->identify.sas_address) {
1245 rc = p->phy_info[i].attached.slot;
1246 goto out;
1247 }
1248 }
1249 }
1250 rc = -ENXIO;
1251 out:
1252 mutex_unlock(&ioc->sas_topology_mutex);
1253 return rc;
1254}
1255
159e36fe
FT
1256static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1257 struct request *req)
1258{
1259 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
1260 MPT_FRAME_HDR *mf;
1261 SmpPassthroughRequest_t *smpreq;
1262 struct request *rsp = req->next_rq;
1263 int ret;
1264 int flagsLength;
1265 unsigned long timeleft;
1266 char *psge;
1267 dma_addr_t dma_addr_in = 0;
1268 dma_addr_t dma_addr_out = 0;
1269 u64 sas_address = 0;
1270
1271 if (!rsp) {
29dd3609
EM
1272 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
1273 ioc->name, __FUNCTION__);
159e36fe
FT
1274 return -EINVAL;
1275 }
1276
1277 /* do we need to support multiple segments? */
1278 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
29dd3609
EM
1279 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
1280 ioc->name, __FUNCTION__, req->bio->bi_vcnt, req->data_len,
1281 rsp->bio->bi_vcnt, rsp->data_len);
159e36fe
FT
1282 return -EINVAL;
1283 }
1284
1285 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
1286 if (ret)
1287 goto out;
1288
1289 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1290 if (!mf) {
1291 ret = -ENOMEM;
1292 goto out_unlock;
1293 }
1294
1295 smpreq = (SmpPassthroughRequest_t *)mf;
1296 memset(smpreq, 0, sizeof(*smpreq));
1297
1298 smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
1299 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
1300
1301 if (rphy)
1302 sas_address = rphy->identify.sas_address;
1303 else {
1304 struct mptsas_portinfo *port_info;
1305
1306 mutex_lock(&ioc->sas_topology_mutex);
7748369f 1307 port_info = mptsas_get_hba_portinfo(ioc);
159e36fe
FT
1308 if (port_info && port_info->phy_info)
1309 sas_address =
1310 port_info->phy_info[0].phy->identify.sas_address;
1311 mutex_unlock(&ioc->sas_topology_mutex);
1312 }
1313
1314 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
1315
1316 psge = (char *)
1317 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
1318
1319 /* request */
1320 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1321 MPI_SGE_FLAGS_END_OF_BUFFER |
1322 MPI_SGE_FLAGS_DIRECTION |
1323 mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
1324 flagsLength |= (req->data_len - 4);
1325
1326 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
1327 req->data_len, PCI_DMA_BIDIRECTIONAL);
1328 if (!dma_addr_out)
1329 goto put_mf;
1330 mpt_add_sge(psge, flagsLength, dma_addr_out);
1331 psge += (sizeof(u32) + sizeof(dma_addr_t));
1332
1333 /* response */
1334 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
1335 flagsLength |= rsp->data_len + 4;
1336 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
1337 rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1338 if (!dma_addr_in)
1339 goto unmap;
1340 mpt_add_sge(psge, flagsLength, dma_addr_in);
1341
1342 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1343
1344 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
1345 if (!timeleft) {
29dd3609 1346 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__);
159e36fe
FT
1347 /* On timeout reset the board */
1348 mpt_HardResetHandler(ioc, CAN_SLEEP);
1349 ret = -ETIMEDOUT;
1350 goto unmap;
1351 }
1352 mf = NULL;
1353
1354 if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
1355 SmpPassthroughReply_t *smprep;
1356
1357 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
1358 memcpy(req->sense, smprep, sizeof(*smprep));
1359 req->sense_len = sizeof(*smprep);
38b3167f
FT
1360 req->data_len = 0;
1361 rsp->data_len -= smprep->ResponseDataLength;
159e36fe 1362 } else {
29dd3609
EM
1363 printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
1364 ioc->name, __FUNCTION__);
159e36fe
FT
1365 ret = -ENXIO;
1366 }
1367unmap:
1368 if (dma_addr_out)
1369 pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
1370 PCI_DMA_BIDIRECTIONAL);
1371 if (dma_addr_in)
1372 pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
1373 PCI_DMA_BIDIRECTIONAL);
1374put_mf:
1375 if (mf)
1376 mpt_free_msg_frame(ioc, mf);
1377out_unlock:
1378 mutex_unlock(&ioc->sas_mgmt.mutex);
1379out:
1380 return ret;
1381}
1382
b5141128
CH
1383static struct sas_function_template mptsas_transport_functions = {
1384 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
1385 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1386 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 1387 .phy_reset = mptsas_phy_reset,
159e36fe 1388 .smp_handler = mptsas_smp_handler,
b5141128
CH
1389};
1390
1391static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
1392
1393static int
1394mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1395{
1396 ConfigExtendedPageHeader_t hdr;
1397 CONFIGPARMS cfg;
1398 SasIOUnitPage0_t *buffer;
1399 dma_addr_t dma_handle;
1400 int error, i;
1401
1402 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1403 hdr.ExtPageLength = 0;
1404 hdr.PageNumber = 0;
1405 hdr.Reserved1 = 0;
1406 hdr.Reserved2 = 0;
1407 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1408 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1409
1410 cfg.cfghdr.ehdr = &hdr;
1411 cfg.physAddr = -1;
1412 cfg.pageAddr = 0;
1413 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1414 cfg.dir = 0; /* read */
1415 cfg.timeout = 10;
1416
1417 error = mpt_config(ioc, &cfg);
1418 if (error)
1419 goto out;
1420 if (!hdr.ExtPageLength) {
1421 error = -ENXIO;
1422 goto out;
1423 }
1424
1425 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1426 &dma_handle);
1427 if (!buffer) {
1428 error = -ENOMEM;
1429 goto out;
1430 }
1431
1432 cfg.physAddr = dma_handle;
1433 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1434
1435 error = mpt_config(ioc, &cfg);
1436 if (error)
1437 goto out_free_consistent;
1438
1439 port_info->num_phys = buffer->NumPhys;
1440 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1441 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1442 if (!port_info->phy_info) {
1443 error = -ENOMEM;
1444 goto out_free_consistent;
1445 }
1446
edb9068d
PS
1447 ioc->nvdata_version_persistent =
1448 le16_to_cpu(buffer->NvdataVersionPersistent);
1449 ioc->nvdata_version_default =
1450 le16_to_cpu(buffer->NvdataVersionDefault);
1451
0c33b27d 1452 for (i = 0; i < port_info->num_phys; i++) {
d6ecdd63 1453 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
0c33b27d
CH
1454 port_info->phy_info[i].phy_id = i;
1455 port_info->phy_info[i].port_id =
1456 buffer->PhyData[i].Port;
1457 port_info->phy_info[i].negotiated_link_rate =
1458 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 1459 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
1460 port_info->phy_info[i].handle =
1461 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
0c33b27d
CH
1462 }
1463
1464 out_free_consistent:
1465 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1466 buffer, dma_handle);
1467 out:
1468 return error;
1469}
1470
edb9068d
PS
1471static int
1472mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
1473{
1474 ConfigExtendedPageHeader_t hdr;
1475 CONFIGPARMS cfg;
1476 SasIOUnitPage1_t *buffer;
1477 dma_addr_t dma_handle;
1478 int error;
1479 u16 device_missing_delay;
1480
1481 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
1482 memset(&cfg, 0, sizeof(CONFIGPARMS));
1483
1484 cfg.cfghdr.ehdr = &hdr;
1485 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1486 cfg.timeout = 10;
1487 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1488 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1489 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
1490 cfg.cfghdr.ehdr->PageNumber = 1;
1491
1492 error = mpt_config(ioc, &cfg);
1493 if (error)
1494 goto out;
1495 if (!hdr.ExtPageLength) {
1496 error = -ENXIO;
1497 goto out;
1498 }
1499
1500 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1501 &dma_handle);
1502 if (!buffer) {
1503 error = -ENOMEM;
1504 goto out;
1505 }
1506
1507 cfg.physAddr = dma_handle;
1508 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1509
1510 error = mpt_config(ioc, &cfg);
1511 if (error)
1512 goto out_free_consistent;
1513
1514 ioc->io_missing_delay =
1515 le16_to_cpu(buffer->IODeviceMissingDelay);
1516 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
1517 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
1518 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
1519 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1520
1521 out_free_consistent:
1522 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1523 buffer, dma_handle);
1524 out:
1525 return error;
1526}
1527
0c33b27d
CH
1528static int
1529mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1530 u32 form, u32 form_specific)
1531{
1532 ConfigExtendedPageHeader_t hdr;
1533 CONFIGPARMS cfg;
1534 SasPhyPage0_t *buffer;
1535 dma_addr_t dma_handle;
1536 int error;
1537
1538 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1539 hdr.ExtPageLength = 0;
1540 hdr.PageNumber = 0;
1541 hdr.Reserved1 = 0;
1542 hdr.Reserved2 = 0;
1543 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1544 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1545
1546 cfg.cfghdr.ehdr = &hdr;
1547 cfg.dir = 0; /* read */
1548 cfg.timeout = 10;
1549
1550 /* Get Phy Pg 0 for each Phy. */
1551 cfg.physAddr = -1;
1552 cfg.pageAddr = form + form_specific;
1553 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1554
1555 error = mpt_config(ioc, &cfg);
1556 if (error)
1557 goto out;
1558
1559 if (!hdr.ExtPageLength) {
1560 error = -ENXIO;
1561 goto out;
1562 }
1563
1564 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1565 &dma_handle);
1566 if (!buffer) {
1567 error = -ENOMEM;
1568 goto out;
1569 }
1570
1571 cfg.physAddr = dma_handle;
1572 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1573
1574 error = mpt_config(ioc, &cfg);
1575 if (error)
1576 goto out_free_consistent;
1577
d6ecdd63 1578 mptsas_print_phy_pg0(ioc, buffer);
0c33b27d
CH
1579
1580 phy_info->hw_link_rate = buffer->HwLinkRate;
1581 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1582 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1583 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1584
1585 out_free_consistent:
1586 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1587 buffer, dma_handle);
1588 out:
1589 return error;
1590}
1591
1592static int
1593mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1594 u32 form, u32 form_specific)
1595{
1596 ConfigExtendedPageHeader_t hdr;
1597 CONFIGPARMS cfg;
1598 SasDevicePage0_t *buffer;
1599 dma_addr_t dma_handle;
1600 __le64 sas_address;
bd23e94c
ME
1601 int error=0;
1602
1603 if (ioc->sas_discovery_runtime &&
1604 mptsas_is_end_device(device_info))
1605 goto out;
0c33b27d
CH
1606
1607 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1608 hdr.ExtPageLength = 0;
1609 hdr.PageNumber = 0;
1610 hdr.Reserved1 = 0;
1611 hdr.Reserved2 = 0;
1612 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1613 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1614
1615 cfg.cfghdr.ehdr = &hdr;
1616 cfg.pageAddr = form + form_specific;
1617 cfg.physAddr = -1;
1618 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1619 cfg.dir = 0; /* read */
1620 cfg.timeout = 10;
1621
db9c9174 1622 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
1623 error = mpt_config(ioc, &cfg);
1624 if (error)
1625 goto out;
1626 if (!hdr.ExtPageLength) {
1627 error = -ENXIO;
1628 goto out;
1629 }
1630
1631 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1632 &dma_handle);
1633 if (!buffer) {
1634 error = -ENOMEM;
1635 goto out;
1636 }
1637
1638 cfg.physAddr = dma_handle;
1639 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1640
1641 error = mpt_config(ioc, &cfg);
1642 if (error)
1643 goto out_free_consistent;
1644
d6ecdd63 1645 mptsas_print_device_pg0(ioc, buffer);
0c33b27d
CH
1646
1647 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 1648 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
1649 device_info->handle_enclosure =
1650 le16_to_cpu(buffer->EnclosureHandle);
1651 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
1652 device_info->phy_id = buffer->PhyNum;
1653 device_info->port_id = buffer->PhysicalPort;
9a28f49a 1654 device_info->id = buffer->TargetID;
b506ade9 1655 device_info->phys_disk_num = ~0;
9a28f49a 1656 device_info->channel = buffer->Bus;
0c33b27d
CH
1657 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1658 device_info->sas_address = le64_to_cpu(sas_address);
1659 device_info->device_info =
1660 le32_to_cpu(buffer->DeviceInfo);
1661
1662 out_free_consistent:
1663 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1664 buffer, dma_handle);
1665 out:
1666 return error;
1667}
1668
1669static int
1670mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1671 u32 form, u32 form_specific)
1672{
1673 ConfigExtendedPageHeader_t hdr;
1674 CONFIGPARMS cfg;
1675 SasExpanderPage0_t *buffer;
1676 dma_addr_t dma_handle;
547f9a21 1677 int i, error;
0c33b27d
CH
1678
1679 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1680 hdr.ExtPageLength = 0;
1681 hdr.PageNumber = 0;
1682 hdr.Reserved1 = 0;
1683 hdr.Reserved2 = 0;
1684 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1685 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1686
1687 cfg.cfghdr.ehdr = &hdr;
1688 cfg.physAddr = -1;
1689 cfg.pageAddr = form + form_specific;
1690 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1691 cfg.dir = 0; /* read */
1692 cfg.timeout = 10;
1693
db9c9174 1694 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
1695 error = mpt_config(ioc, &cfg);
1696 if (error)
1697 goto out;
1698
1699 if (!hdr.ExtPageLength) {
1700 error = -ENXIO;
1701 goto out;
1702 }
1703
1704 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1705 &dma_handle);
1706 if (!buffer) {
1707 error = -ENOMEM;
1708 goto out;
1709 }
1710
1711 cfg.physAddr = dma_handle;
1712 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1713
1714 error = mpt_config(ioc, &cfg);
1715 if (error)
1716 goto out_free_consistent;
1717
51f39eae
KO
1718 if (!buffer->NumPhys) {
1719 error = -ENODEV;
1720 goto out_free_consistent;
1721 }
1722
0c33b27d
CH
1723 /* save config data */
1724 port_info->num_phys = buffer->NumPhys;
0c33b27d 1725 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1726 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1727 if (!port_info->phy_info) {
1728 error = -ENOMEM;
1729 goto out_free_consistent;
1730 }
1731
2ecce492 1732 for (i = 0; i < port_info->num_phys; i++) {
547f9a21 1733 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
1734 port_info->phy_info[i].handle =
1735 le16_to_cpu(buffer->DevHandle);
1736 }
547f9a21 1737
0c33b27d
CH
1738 out_free_consistent:
1739 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1740 buffer, dma_handle);
1741 out:
1742 return error;
1743}
1744
1745static int
1746mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1747 u32 form, u32 form_specific)
1748{
1749 ConfigExtendedPageHeader_t hdr;
1750 CONFIGPARMS cfg;
1751 SasExpanderPage1_t *buffer;
1752 dma_addr_t dma_handle;
bd23e94c
ME
1753 int error=0;
1754
1755 if (ioc->sas_discovery_runtime &&
1756 mptsas_is_end_device(&phy_info->attached))
1757 goto out;
0c33b27d
CH
1758
1759 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1760 hdr.ExtPageLength = 0;
1761 hdr.PageNumber = 1;
1762 hdr.Reserved1 = 0;
1763 hdr.Reserved2 = 0;
1764 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1765 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1766
1767 cfg.cfghdr.ehdr = &hdr;
1768 cfg.physAddr = -1;
1769 cfg.pageAddr = form + form_specific;
1770 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1771 cfg.dir = 0; /* read */
1772 cfg.timeout = 10;
1773
1774 error = mpt_config(ioc, &cfg);
1775 if (error)
1776 goto out;
1777
1778 if (!hdr.ExtPageLength) {
1779 error = -ENXIO;
1780 goto out;
1781 }
1782
1783 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1784 &dma_handle);
1785 if (!buffer) {
1786 error = -ENOMEM;
1787 goto out;
1788 }
1789
1790 cfg.physAddr = dma_handle;
1791 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1792
1793 error = mpt_config(ioc, &cfg);
1794 if (error)
1795 goto out_free_consistent;
1796
1797
d6ecdd63 1798 mptsas_print_expander_pg1(ioc, buffer);
0c33b27d
CH
1799
1800 /* save config data */
024358ee 1801 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
1802 phy_info->port_id = buffer->PhysicalPort;
1803 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1804 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1805 phy_info->hw_link_rate = buffer->HwLinkRate;
1806 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1807 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1808
0c33b27d
CH
1809 out_free_consistent:
1810 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1811 buffer, dma_handle);
1812 out:
1813 return error;
1814}
1815
1816static void
1817mptsas_parse_device_info(struct sas_identify *identify,
1818 struct mptsas_devinfo *device_info)
1819{
1820 u16 protocols;
1821
1822 identify->sas_address = device_info->sas_address;
1823 identify->phy_identifier = device_info->phy_id;
1824
1825 /*
1826 * Fill in Phy Initiator Port Protocol.
1827 * Bits 6:3, more than one bit can be set, fall through cases.
1828 */
1829 protocols = device_info->device_info & 0x78;
1830 identify->initiator_port_protocols = 0;
1831 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1832 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1833 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1834 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1835 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1836 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1837 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1838 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1839
1840 /*
1841 * Fill in Phy Target Port Protocol.
1842 * Bits 10:7, more than one bit can be set, fall through cases.
1843 */
1844 protocols = device_info->device_info & 0x780;
1845 identify->target_port_protocols = 0;
1846 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1847 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1848 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1849 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1850 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1851 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1852 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1853 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1854
1855 /*
1856 * Fill in Attached device type.
1857 */
1858 switch (device_info->device_info &
1859 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1860 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1861 identify->device_type = SAS_PHY_UNUSED;
1862 break;
1863 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1864 identify->device_type = SAS_END_DEVICE;
1865 break;
1866 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1867 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1868 break;
1869 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1870 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1871 break;
1872 }
1873}
1874
1875static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 1876 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 1877{
e6b2d76a 1878 MPT_ADAPTER *ioc;
9a28f49a 1879 struct sas_phy *phy;
547f9a21
EM
1880 struct sas_port *port;
1881 int error = 0;
0c33b27d 1882
547f9a21
EM
1883 if (!dev) {
1884 error = -ENODEV;
1885 goto out;
1886 }
e6b2d76a
ME
1887
1888 if (!phy_info->phy) {
1889 phy = sas_phy_alloc(dev, index);
547f9a21
EM
1890 if (!phy) {
1891 error = -ENOMEM;
1892 goto out;
1893 }
e6b2d76a
ME
1894 } else
1895 phy = phy_info->phy;
0c33b27d 1896
9a28f49a 1897 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
1898
1899 /*
1900 * Set Negotiated link rate.
1901 */
1902 switch (phy_info->negotiated_link_rate) {
1903 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 1904 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
1905 break;
1906 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 1907 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
1908 break;
1909 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 1910 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1911 break;
1912 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 1913 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1914 break;
1915 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1916 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1917 default:
9a28f49a 1918 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
1919 break;
1920 }
1921
1922 /*
1923 * Set Max hardware link rate.
1924 */
1925 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1926 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 1927 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1928 break;
1929 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1930 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1931 break;
1932 default:
1933 break;
1934 }
1935
1936 /*
1937 * Set Max programmed link rate.
1938 */
1939 switch (phy_info->programmed_link_rate &
1940 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1941 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 1942 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1943 break;
1944 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1945 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1946 break;
1947 default:
1948 break;
1949 }
1950
1951 /*
1952 * Set Min hardware link rate.
1953 */
1954 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1955 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 1956 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1957 break;
1958 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1959 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1960 break;
1961 default:
1962 break;
1963 }
1964
1965 /*
1966 * Set Min programmed link rate.
1967 */
1968 switch (phy_info->programmed_link_rate &
1969 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1970 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 1971 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1972 break;
1973 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 1974 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1975 break;
1976 default:
1977 break;
1978 }
1979
e6b2d76a 1980 if (!phy_info->phy) {
ac01bbbd 1981
e6b2d76a
ME
1982 error = sas_phy_add(phy);
1983 if (error) {
1984 sas_phy_free(phy);
547f9a21 1985 goto out;
e6b2d76a
ME
1986 }
1987 phy_info->phy = phy;
0c33b27d
CH
1988 }
1989
547f9a21
EM
1990 if (!phy_info->attached.handle ||
1991 !phy_info->port_details)
1992 goto out;
1993
1994 port = mptsas_get_port(phy_info);
1995 ioc = phy_to_ioc(phy_info->phy);
1996
1997 if (phy_info->sas_port_add_phy) {
1998
1999 if (!port) {
dc22f16d 2000 port = sas_port_alloc_num(dev);
547f9a21
EM
2001 if (!port) {
2002 error = -ENOMEM;
2003 goto out;
2004 }
2005 error = sas_port_add(port);
2006 if (error) {
d6ecdd63 2007 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2008 "%s: exit at line=%d\n", ioc->name,
2009 __FUNCTION__, __LINE__));
2010 goto out;
2011 }
d6ecdd63 2012 mptsas_set_port(ioc, phy_info, port);
29dd3609 2013 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
dc22f16d 2014 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
29dd3609 2015 ioc->name, port, dev, port->port_identifier));
547f9a21 2016 }
29dd3609
EM
2017 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
2018 ioc->name, phy_info->phy_id));
547f9a21
EM
2019 sas_port_add_phy(port, phy_info->phy);
2020 phy_info->sas_port_add_phy = 0;
2021 }
2022
2023 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 2024
0c33b27d 2025 struct sas_rphy *rphy;
2686de27 2026 struct device *parent;
f013db32 2027 struct sas_identify identify;
0c33b27d 2028
2686de27 2029 parent = dev->parent->parent;
e6b2d76a
ME
2030 /*
2031 * Let the hotplug_work thread handle processing
2032 * the adding/removing of devices that occur
2033 * after start of day.
2034 */
2035 if (ioc->sas_discovery_runtime &&
2036 mptsas_is_end_device(&phy_info->attached))
547f9a21 2037 goto out;
e6b2d76a 2038
f013db32 2039 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
2040 if (scsi_is_host_device(parent)) {
2041 struct mptsas_portinfo *port_info;
2042 int i;
2043
2044 mutex_lock(&ioc->sas_topology_mutex);
7748369f 2045 port_info = mptsas_get_hba_portinfo(ioc);
2686de27
JB
2046 mutex_unlock(&ioc->sas_topology_mutex);
2047
2048 for (i = 0; i < port_info->num_phys; i++)
2049 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
2050 identify.sas_address) {
2051 sas_port_mark_backlink(port);
2686de27 2052 goto out;
0c269e6d 2053 }
2686de27
JB
2054
2055 } else if (scsi_is_sas_rphy(parent)) {
2056 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2057 if (identify.sas_address ==
0c269e6d
JB
2058 parent_rphy->identify.sas_address) {
2059 sas_port_mark_backlink(port);
2686de27 2060 goto out;
0c269e6d 2061 }
2686de27
JB
2062 }
2063
f013db32
JB
2064 switch (identify.device_type) {
2065 case SAS_END_DEVICE:
547f9a21 2066 rphy = sas_end_device_alloc(port);
f013db32
JB
2067 break;
2068 case SAS_EDGE_EXPANDER_DEVICE:
2069 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 2070 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
2071 break;
2072 default:
2073 rphy = NULL;
2074 break;
2075 }
547f9a21 2076 if (!rphy) {
d6ecdd63 2077 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2078 "%s: exit at line=%d\n", ioc->name,
2079 __FUNCTION__, __LINE__));
2080 goto out;
2081 }
0c33b27d 2082
f013db32 2083 rphy->identify = identify;
0c33b27d
CH
2084 error = sas_rphy_add(rphy);
2085 if (error) {
d6ecdd63 2086 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2087 "%s: exit at line=%d\n", ioc->name,
2088 __FUNCTION__, __LINE__));
0c33b27d 2089 sas_rphy_free(rphy);
547f9a21 2090 goto out;
0c33b27d 2091 }
d6ecdd63 2092 mptsas_set_rphy(ioc, phy_info, rphy);
0c33b27d
CH
2093 }
2094
547f9a21
EM
2095 out:
2096 return error;
0c33b27d
CH
2097}
2098
2099static int
e6b2d76a 2100mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 2101{
e6b2d76a 2102 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
2103 int error = -ENOMEM, i;
2104
e6b2d76a
ME
2105 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
2106 if (! hba)
0c33b27d 2107 goto out;
0c33b27d 2108
e6b2d76a 2109 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
2110 if (error)
2111 goto out_free_port_info;
2112
edb9068d 2113 mptsas_sas_io_unit_pg1(ioc);
9a28f49a 2114 mutex_lock(&ioc->sas_topology_mutex);
7748369f 2115 port_info = mptsas_get_hba_portinfo(ioc);
e6b2d76a
ME
2116 if (!port_info) {
2117 port_info = hba;
2118 list_add_tail(&port_info->list, &ioc->sas_topology);
2119 } else {
2ecce492 2120 for (i = 0; i < hba->num_phys; i++) {
e6b2d76a
ME
2121 port_info->phy_info[i].negotiated_link_rate =
2122 hba->phy_info[i].negotiated_link_rate;
2ecce492
EM
2123 port_info->phy_info[i].handle =
2124 hba->phy_info[i].handle;
2125 port_info->phy_info[i].port_id =
2126 hba->phy_info[i].port_id;
2127 }
547f9a21 2128 kfree(hba->phy_info);
e6b2d76a
ME
2129 kfree(hba);
2130 hba = NULL;
2131 }
9a28f49a 2132 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
2133 for (i = 0; i < port_info->num_phys; i++) {
2134 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2135 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2136 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2137
2138 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2ecce492
EM
2139 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2140 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2141 port_info->phy_info[i].handle);
024358ee 2142 port_info->phy_info[i].identify.phy_id =
2ecce492 2143 port_info->phy_info[i].phy_id = i;
547f9a21 2144 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
2145 mptsas_sas_device_pg0(ioc,
2146 &port_info->phy_info[i].attached,
2147 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2148 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2149 port_info->phy_info[i].attached.handle);
547f9a21 2150 }
0c33b27d 2151
547f9a21
EM
2152 mptsas_setup_wide_ports(ioc, port_info);
2153
2154 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 2155 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 2156 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
2157
2158 return 0;
2159
2160 out_free_port_info:
547f9a21 2161 kfree(hba);
0c33b27d
CH
2162 out:
2163 return error;
2164}
2165
2166static int
e6b2d76a 2167mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
0c33b27d 2168{
e6b2d76a 2169 struct mptsas_portinfo *port_info, *p, *ex;
547f9a21
EM
2170 struct device *parent;
2171 struct sas_rphy *rphy;
0c33b27d
CH
2172 int error = -ENOMEM, i, j;
2173
e6b2d76a
ME
2174 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
2175 if (!ex)
0c33b27d 2176 goto out;
0c33b27d 2177
e6b2d76a 2178 error = mptsas_sas_expander_pg0(ioc, ex,
2ecce492
EM
2179 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2180 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
0c33b27d
CH
2181 if (error)
2182 goto out_free_port_info;
2183
2ecce492 2184 *handle = ex->phy_info[0].handle;
0c33b27d 2185
9a28f49a 2186 mutex_lock(&ioc->sas_topology_mutex);
e6b2d76a
ME
2187 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2188 if (!port_info) {
2189 port_info = ex;
2190 list_add_tail(&port_info->list, &ioc->sas_topology);
2191 } else {
2ecce492
EM
2192 for (i = 0; i < ex->num_phys; i++) {
2193 port_info->phy_info[i].handle =
2194 ex->phy_info[i].handle;
2195 port_info->phy_info[i].port_id =
2196 ex->phy_info[i].port_id;
2197 }
547f9a21 2198 kfree(ex->phy_info);
e6b2d76a
ME
2199 kfree(ex);
2200 ex = NULL;
2201 }
9a28f49a
CH
2202 mutex_unlock(&ioc->sas_topology_mutex);
2203
0c33b27d 2204 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d
CH
2205 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2206 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2207 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
2208
2209 if (port_info->phy_info[i].identify.handle) {
2210 mptsas_sas_device_pg0(ioc,
2211 &port_info->phy_info[i].identify,
2212 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2213 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2214 port_info->phy_info[i].identify.handle);
024358ee
EM
2215 port_info->phy_info[i].identify.phy_id =
2216 port_info->phy_info[i].phy_id;
0c33b27d
CH
2217 }
2218
2219 if (port_info->phy_info[i].attached.handle) {
2220 mptsas_sas_device_pg0(ioc,
2221 &port_info->phy_info[i].attached,
2222 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2223 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2224 port_info->phy_info[i].attached.handle);
db9c9174
ME
2225 port_info->phy_info[i].attached.phy_id =
2226 port_info->phy_info[i].phy_id;
0c33b27d 2227 }
547f9a21 2228 }
0c33b27d 2229
547f9a21
EM
2230 parent = &ioc->sh->shost_gendev;
2231 for (i = 0; i < port_info->num_phys; i++) {
9a28f49a 2232 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
2233 list_for_each_entry(p, &ioc->sas_topology, list) {
2234 for (j = 0; j < p->num_phys; j++) {
547f9a21 2235 if (port_info->phy_info[i].identify.handle !=
0c33b27d 2236 p->phy_info[j].attached.handle)
547f9a21
EM
2237 continue;
2238 rphy = mptsas_get_rphy(&p->phy_info[j]);
2239 parent = &rphy->dev;
0c33b27d
CH
2240 }
2241 }
9a28f49a 2242 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
2243 }
2244
2245 mptsas_setup_wide_ports(ioc, port_info);
0c33b27d 2246
547f9a21 2247 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
ac01bbbd 2248 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
e6b2d76a 2249 ioc->sas_index, 0);
0c33b27d
CH
2250
2251 return 0;
2252
2253 out_free_port_info:
e6b2d76a 2254 if (ex) {
547f9a21 2255 kfree(ex->phy_info);
e6b2d76a
ME
2256 kfree(ex);
2257 }
0c33b27d
CH
2258 out:
2259 return error;
2260}
2261
e6b2d76a
ME
2262/*
2263 * mptsas_delete_expander_phys
2264 *
2265 *
2266 * This will traverse topology, and remove expanders
2267 * that are no longer present
2268 */
2269static void
2270mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
2271{
2272 struct mptsas_portinfo buffer;
2273 struct mptsas_portinfo *port_info, *n, *parent;
547f9a21 2274 struct mptsas_phyinfo *phy_info;
547f9a21 2275 struct sas_port * port;
e6b2d76a 2276 int i;
547f9a21 2277 u64 expander_sas_address;
e6b2d76a
ME
2278
2279 mutex_lock(&ioc->sas_topology_mutex);
2280 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
2281
2282 if (port_info->phy_info &&
2283 (!(port_info->phy_info[0].identify.device_info &
2284 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
2285 continue;
2286
2287 if (mptsas_sas_expander_pg0(ioc, &buffer,
2288 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
2ecce492
EM
2289 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2290 port_info->phy_info[0].handle)) {
e6b2d76a
ME
2291
2292 /*
2293 * Obtain the port_info instance to the parent port
2294 */
2295 parent = mptsas_find_portinfo_by_handle(ioc,
2296 port_info->phy_info[0].identify.handle_parent);
2297
2298 if (!parent)
2299 goto next_port;
2300
547f9a21
EM
2301 expander_sas_address =
2302 port_info->phy_info[0].identify.sas_address;
2303
e6b2d76a
ME
2304 /*
2305 * Delete rphys in the parent that point
2306 * to this expander. The transport layer will
2307 * cleanup all the children.
2308 */
547f9a21
EM
2309 phy_info = parent->phy_info;
2310 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2311 port = mptsas_get_port(phy_info);
2312 if (!port)
2313 continue;
2314 if (phy_info->attached.sas_address !=
2315 expander_sas_address)
e6b2d76a 2316 continue;
d6ecdd63 2317 dsaswideprintk(ioc,
c51d0bea
EM
2318 dev_printk(KERN_DEBUG, &port->dev,
2319 MYIOC_s_FMT "delete port (%d)\n", ioc->name,
2320 port->port_identifier));
547f9a21 2321 sas_port_delete(port);
d6ecdd63 2322 mptsas_port_delete(ioc, phy_info->port_details);
e6b2d76a
ME
2323 }
2324 next_port:
547f9a21
EM
2325
2326 phy_info = port_info->phy_info;
2327 for (i = 0; i < port_info->num_phys; i++, phy_info++)
d6ecdd63 2328 mptsas_port_delete(ioc, phy_info->port_details);
547f9a21 2329
e6b2d76a 2330 list_del(&port_info->list);
547f9a21 2331 kfree(port_info->phy_info);
e6b2d76a
ME
2332 kfree(port_info);
2333 }
2334 /*
2335 * Free this memory allocated from inside
2336 * mptsas_sas_expander_pg0
2337 */
547f9a21 2338 kfree(buffer.phy_info);
e6b2d76a
ME
2339 }
2340 mutex_unlock(&ioc->sas_topology_mutex);
2341}
2342
2343/*
2344 * Start of day discovery
2345 */
0c33b27d
CH
2346static void
2347mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
2348{
2349 u32 handle = 0xFFFF;
f44e5461 2350 int i;
0c33b27d 2351
e6b2d76a
ME
2352 mutex_lock(&ioc->sas_discovery_mutex);
2353 mptsas_probe_hba_phys(ioc);
2354 while (!mptsas_probe_expander_phys(ioc, &handle))
0c33b27d 2355 ;
f44e5461
ME
2356 /*
2357 Reporting RAID volumes.
2358 */
b506ade9
EM
2359 if (!ioc->ir_firmware)
2360 goto out;
f44e5461
ME
2361 if (!ioc->raid_data.pIocPg2)
2362 goto out;
2363 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
2364 goto out;
793955f5 2365 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
e8bf3941 2366 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
f44e5461
ME
2367 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
2368 }
2369 out:
e6b2d76a
ME
2370 mutex_unlock(&ioc->sas_discovery_mutex);
2371}
2372
2373/*
2374 * Work queue thread to handle Runtime discovery
2375 * Mere purpose is the hot add/delete of expanders
547f9a21 2376 *(Mutex UNLOCKED)
e6b2d76a
ME
2377 */
2378static void
547f9a21 2379__mptsas_discovery_work(MPT_ADAPTER *ioc)
e6b2d76a 2380{
e6b2d76a
ME
2381 u32 handle = 0xFFFF;
2382
e6b2d76a
ME
2383 ioc->sas_discovery_runtime=1;
2384 mptsas_delete_expander_phys(ioc);
2385 mptsas_probe_hba_phys(ioc);
2386 while (!mptsas_probe_expander_phys(ioc, &handle))
2387 ;
e6b2d76a 2388 ioc->sas_discovery_runtime=0;
547f9a21
EM
2389}
2390
2391/*
2392 * Work queue thread to handle Runtime discovery
2393 * Mere purpose is the hot add/delete of expanders
2394 *(Mutex LOCKED)
2395 */
2396static void
c4028958 2397mptsas_discovery_work(struct work_struct *work)
547f9a21 2398{
c4028958
DH
2399 struct mptsas_discovery_event *ev =
2400 container_of(work, struct mptsas_discovery_event, work);
547f9a21
EM
2401 MPT_ADAPTER *ioc = ev->ioc;
2402
2403 mutex_lock(&ioc->sas_discovery_mutex);
2404 __mptsas_discovery_work(ioc);
e6b2d76a 2405 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2406 kfree(ev);
0c33b27d
CH
2407}
2408
9a28f49a 2409static struct mptsas_phyinfo *
547f9a21 2410mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
2411{
2412 struct mptsas_portinfo *port_info;
9a28f49a 2413 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 2414 int i;
9a28f49a 2415
9a28f49a
CH
2416 mutex_lock(&ioc->sas_topology_mutex);
2417 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2418 for (i = 0; i < port_info->num_phys; i++) {
b506ade9
EM
2419 if (!mptsas_is_end_device(
2420 &port_info->phy_info[i].attached))
2421 continue;
547f9a21
EM
2422 if (port_info->phy_info[i].attached.sas_address
2423 != sas_address)
2424 continue;
b506ade9
EM
2425 phy_info = &port_info->phy_info[i];
2426 break;
2427 }
2428 }
2429 mutex_unlock(&ioc->sas_topology_mutex);
2430 return phy_info;
2431}
2432
2433static struct mptsas_phyinfo *
2434mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
2435{
2436 struct mptsas_portinfo *port_info;
2437 struct mptsas_phyinfo *phy_info = NULL;
2438 int i;
2439
2440 mutex_lock(&ioc->sas_topology_mutex);
2441 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2442 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2443 if (!mptsas_is_end_device(
2444 &port_info->phy_info[i].attached))
2445 continue;
b506ade9
EM
2446 if (port_info->phy_info[i].attached.id != id)
2447 continue;
2448 if (port_info->phy_info[i].attached.channel != channel)
2449 continue;
547f9a21
EM
2450 phy_info = &port_info->phy_info[i];
2451 break;
9a28f49a
CH
2452 }
2453 }
2454 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2455 return phy_info;
2456}
2457
2458static struct mptsas_phyinfo *
b506ade9 2459mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
9a28f49a
CH
2460{
2461 struct mptsas_portinfo *port_info;
2462 struct mptsas_phyinfo *phy_info = NULL;
2463 int i;
2464
9a28f49a
CH
2465 mutex_lock(&ioc->sas_topology_mutex);
2466 list_for_each_entry(port_info, &ioc->sas_topology, list) {
547f9a21 2467 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2468 if (!mptsas_is_end_device(
2469 &port_info->phy_info[i].attached))
2470 continue;
b506ade9
EM
2471 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
2472 continue;
2473 if (port_info->phy_info[i].attached.phys_disk_num != id)
2474 continue;
2475 if (port_info->phy_info[i].attached.channel != channel)
2476 continue;
547f9a21
EM
2477 phy_info = &port_info->phy_info[i];
2478 break;
2479 }
9a28f49a
CH
2480 }
2481 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2482 return phy_info;
2483}
2484
4b766471
ME
2485/*
2486 * Work queue thread to clear the persitency table
2487 */
2488static void
c4028958 2489mptsas_persist_clear_table(struct work_struct *work)
4b766471 2490{
c4028958 2491 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
4b766471
ME
2492
2493 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2494}
2495
f44e5461
ME
2496static void
2497mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2498{
f99be43b
EM
2499 int rc;
2500
f44e5461 2501 sdev->no_uld_attach = data ? 1 : 0;
f99be43b 2502 rc = scsi_device_reprobe(sdev);
f44e5461
ME
2503}
2504
2505static void
2506mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2507{
2508 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2509 mptsas_reprobe_lun);
2510}
2511
b506ade9
EM
2512static void
2513mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2514{
2515 CONFIGPARMS cfg;
2516 ConfigPageHeader_t hdr;
2517 dma_addr_t dma_handle;
2518 pRaidVolumePage0_t buffer = NULL;
2519 RaidPhysDiskPage0_t phys_disk;
2520 int i;
2521 struct mptsas_hotplug_event *ev;
2522
2523 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2524 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
2525 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
2526 cfg.pageAddr = (channel << 8) + id;
2527 cfg.cfghdr.hdr = &hdr;
2528 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2529
2530 if (mpt_config(ioc, &cfg) != 0)
2531 goto out;
2532
2533 if (!hdr.PageLength)
2534 goto out;
2535
2536 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
2537 &dma_handle);
2538
2539 if (!buffer)
2540 goto out;
2541
2542 cfg.physAddr = dma_handle;
2543 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2544
2545 if (mpt_config(ioc, &cfg) != 0)
2546 goto out;
2547
2548 if (!(buffer->VolumeStatus.Flags &
2549 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
2550 goto out;
2551
2552 if (!buffer->NumPhysDisks)
2553 goto out;
2554
2555 for (i = 0; i < buffer->NumPhysDisks; i++) {
2556
2557 if (mpt_raid_phys_disk_pg0(ioc,
2558 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2559 continue;
2560
2561 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2562 if (!ev) {
29dd3609 2563 printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
b506ade9
EM
2564 goto out;
2565 }
2566
2567 INIT_WORK(&ev->work, mptsas_hotplug_work);
2568 ev->ioc = ioc;
2569 ev->id = phys_disk.PhysDiskID;
2570 ev->channel = phys_disk.PhysDiskBus;
2571 ev->phys_disk_num_valid = 1;
2572 ev->phys_disk_num = phys_disk.PhysDiskNum;
2573 ev->event_type = MPTSAS_ADD_DEVICE;
2574 schedule_work(&ev->work);
2575 }
2576
2577 out:
2578 if (buffer)
2579 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
2580 dma_handle);
2581}
e6b2d76a
ME
2582/*
2583 * Work queue thread to handle SAS hotplug events
2584 */
9a28f49a 2585static void
c4028958 2586mptsas_hotplug_work(struct work_struct *work)
9a28f49a 2587{
c4028958
DH
2588 struct mptsas_hotplug_event *ev =
2589 container_of(work, struct mptsas_hotplug_event, work);
b506ade9 2590
9a28f49a
CH
2591 MPT_ADAPTER *ioc = ev->ioc;
2592 struct mptsas_phyinfo *phy_info;
2593 struct sas_rphy *rphy;
547f9a21 2594 struct sas_port *port;
c73787ee 2595 struct scsi_device *sdev;
547f9a21 2596 struct scsi_target * starget;
f013db32 2597 struct sas_identify identify;
9a28f49a 2598 char *ds = NULL;
c73787ee 2599 struct mptsas_devinfo sas_device;
f44e5461 2600 VirtTarget *vtarget;
547f9a21 2601 VirtDevice *vdevice;
9a28f49a 2602
547f9a21 2603 mutex_lock(&ioc->sas_discovery_mutex);
9a28f49a
CH
2604 switch (ev->event_type) {
2605 case MPTSAS_DEL_DEVICE:
9a28f49a 2606
b506ade9
EM
2607 phy_info = NULL;
2608 if (ev->phys_disk_num_valid) {
2609 if (ev->hidden_raid_component){
2610 if (mptsas_sas_device_pg0(ioc, &sas_device,
2611 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2612 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2613 (ev->channel << 8) + ev->id)) {
d6ecdd63 2614 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
b506ade9
EM
2615 "%s: exit at line=%d\n", ioc->name,
2616 __FUNCTION__, __LINE__));
2617 break;
2618 }
2619 phy_info = mptsas_find_phyinfo_by_sas_address(
2620 ioc, sas_device.sas_address);
2621 }else
2622 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2623 ioc, ev->channel, ev->phys_disk_num);
2624 }
2625
2626 if (!phy_info)
2627 phy_info = mptsas_find_phyinfo_by_target(ioc,
2628 ev->channel, ev->id);
e6b2d76a 2629
f44e5461
ME
2630 /*
2631 * Sanity checks, for non-existing phys and remote rphys.
2632 */
b506ade9 2633 if (!phy_info){
d6ecdd63 2634 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
b506ade9
EM
2635 "%s: exit at line=%d\n", ioc->name,
2636 __FUNCTION__, __LINE__));
2637 break;
2638 }
2639 if (!phy_info->port_details) {
d6ecdd63 2640 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2641 "%s: exit at line=%d\n", ioc->name,
2642 __FUNCTION__, __LINE__));
9a28f49a 2643 break;
547f9a21
EM
2644 }
2645 rphy = mptsas_get_rphy(phy_info);
2646 if (!rphy) {
d6ecdd63 2647 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2648 "%s: exit at line=%d\n", ioc->name,
2649 __FUNCTION__, __LINE__));
2650 break;
2651 }
b506ade9 2652
547f9a21
EM
2653 port = mptsas_get_port(phy_info);
2654 if (!port) {
d6ecdd63 2655 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2656 "%s: exit at line=%d\n", ioc->name,
2657 __FUNCTION__, __LINE__));
f44e5461 2658 break;
547f9a21
EM
2659 }
2660
2661 starget = mptsas_get_starget(phy_info);
2662 if (starget) {
2663 vtarget = starget->hostdata;
f44e5461 2664
547f9a21 2665 if (!vtarget) {
d6ecdd63 2666 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2667 "%s: exit at line=%d\n", ioc->name,
2668 __FUNCTION__, __LINE__));
f44e5461 2669 break;
547f9a21
EM
2670 }
2671
f44e5461
ME
2672 /*
2673 * Handling RAID components
2674 */
b506ade9
EM
2675 if (ev->phys_disk_num_valid &&
2676 ev->hidden_raid_component) {
2677 printk(MYIOC_s_INFO_FMT
2678 "RAID Hidding: channel=%d, id=%d, "
2679 "physdsk %d \n", ioc->name, ev->channel,
2680 ev->id, ev->phys_disk_num);
793955f5 2681 vtarget->id = ev->phys_disk_num;
b506ade9
EM
2682 vtarget->tflags |=
2683 MPT_TARGET_FLAGS_RAID_COMPONENT;
547f9a21 2684 mptsas_reprobe_target(starget, 1);
b506ade9
EM
2685 phy_info->attached.phys_disk_num =
2686 ev->phys_disk_num;
2687 break;
f44e5461 2688 }
9a28f49a
CH
2689 }
2690
b506ade9
EM
2691 if (phy_info->attached.device_info &
2692 MPI_SAS_DEVICE_INFO_SSP_TARGET)
c73787ee 2693 ds = "ssp";
b506ade9
EM
2694 if (phy_info->attached.device_info &
2695 MPI_SAS_DEVICE_INFO_STP_TARGET)
c73787ee 2696 ds = "stp";
b506ade9
EM
2697 if (phy_info->attached.device_info &
2698 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
c73787ee
ME
2699 ds = "sata";
2700
2701 printk(MYIOC_s_INFO_FMT
2702 "removing %s device, channel %d, id %d, phy %d\n",
2703 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
c51d0bea 2704 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
29dd3609 2705 "delete port (%d)\n", ioc->name, port->port_identifier);
547f9a21 2706 sas_port_delete(port);
d6ecdd63 2707 mptsas_port_delete(ioc, phy_info->port_details);
9a28f49a
CH
2708 break;
2709 case MPTSAS_ADD_DEVICE:
c73787ee 2710
bd23e94c
ME
2711 if (ev->phys_disk_num_valid)
2712 mpt_findImVolumes(ioc);
2713
c73787ee 2714 /*
e3094447 2715 * Refresh sas device pg0 data
c73787ee 2716 */
e3094447
CH
2717 if (mptsas_sas_device_pg0(ioc, &sas_device,
2718 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
b506ade9
EM
2719 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2720 (ev->channel << 8) + ev->id)) {
d6ecdd63 2721 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2722 "%s: exit at line=%d\n", ioc->name,
2723 __FUNCTION__, __LINE__));
e3094447 2724 break;
547f9a21 2725 }
9a28f49a 2726
547f9a21 2727 __mptsas_discovery_work(ioc);
e6b2d76a 2728
547f9a21
EM
2729 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2730 sas_device.sas_address);
e6b2d76a 2731
547f9a21 2732 if (!phy_info || !phy_info->port_details) {
d6ecdd63 2733 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2734 "%s: exit at line=%d\n", ioc->name,
2735 __FUNCTION__, __LINE__));
2736 break;
e6b2d76a
ME
2737 }
2738
547f9a21 2739 starget = mptsas_get_starget(phy_info);
b506ade9
EM
2740 if (starget && (!ev->hidden_raid_component)){
2741
547f9a21 2742 vtarget = starget->hostdata;
9a28f49a 2743
547f9a21 2744 if (!vtarget) {
d6ecdd63 2745 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
29dd3609
EM
2746 "%s: exit at line=%d\n", ioc->name,
2747 __FUNCTION__, __LINE__));
f44e5461 2748 break;
547f9a21 2749 }
f44e5461
ME
2750 /*
2751 * Handling RAID components
2752 */
2753 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
b506ade9
EM
2754 printk(MYIOC_s_INFO_FMT
2755 "RAID Exposing: channel=%d, id=%d, "
2756 "physdsk %d \n", ioc->name, ev->channel,
2757 ev->id, ev->phys_disk_num);
2758 vtarget->tflags &=
2759 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
793955f5 2760 vtarget->id = ev->id;
547f9a21 2761 mptsas_reprobe_target(starget, 0);
b506ade9 2762 phy_info->attached.phys_disk_num = ~0;
f44e5461 2763 }
9a28f49a
CH
2764 break;
2765 }
2766
547f9a21 2767 if (mptsas_get_rphy(phy_info)) {
d6ecdd63 2768 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2769 "%s: exit at line=%d\n", ioc->name,
2770 __FUNCTION__, __LINE__));
b506ade9 2771 if (ev->channel) printk("%d\n", __LINE__);
f44e5461 2772 break;
547f9a21 2773 }
b506ade9 2774
547f9a21
EM
2775 port = mptsas_get_port(phy_info);
2776 if (!port) {
d6ecdd63 2777 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2778 "%s: exit at line=%d\n", ioc->name,
2779 __FUNCTION__, __LINE__));
2780 break;
2781 }
e3094447
CH
2782 memcpy(&phy_info->attached, &sas_device,
2783 sizeof(struct mptsas_devinfo));
9a28f49a 2784
b506ade9
EM
2785 if (phy_info->attached.device_info &
2786 MPI_SAS_DEVICE_INFO_SSP_TARGET)
c73787ee 2787 ds = "ssp";
b506ade9
EM
2788 if (phy_info->attached.device_info &
2789 MPI_SAS_DEVICE_INFO_STP_TARGET)
c73787ee 2790 ds = "stp";
b506ade9
EM
2791 if (phy_info->attached.device_info &
2792 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
c73787ee
ME
2793 ds = "sata";
2794
2795 printk(MYIOC_s_INFO_FMT
2796 "attaching %s device, channel %d, id %d, phy %d\n",
2797 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2798
f013db32 2799 mptsas_parse_device_info(&identify, &phy_info->attached);
547f9a21
EM
2800 rphy = sas_end_device_alloc(port);
2801 if (!rphy) {
d6ecdd63 2802 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2803 "%s: exit at line=%d\n", ioc->name,
2804 __FUNCTION__, __LINE__));
9a28f49a 2805 break; /* non-fatal: an rphy can be added later */
547f9a21 2806 }
9a28f49a 2807
f013db32 2808 rphy->identify = identify;
9a28f49a 2809 if (sas_rphy_add(rphy)) {
d6ecdd63 2810 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2811 "%s: exit at line=%d\n", ioc->name,
2812 __FUNCTION__, __LINE__));
9a28f49a
CH
2813 sas_rphy_free(rphy);
2814 break;
2815 }
d6ecdd63 2816 mptsas_set_rphy(ioc, phy_info, rphy);
9a28f49a 2817 break;
c73787ee 2818 case MPTSAS_ADD_RAID:
e8bf3941
JB
2819 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2820 ev->id, 0);
c73787ee
ME
2821 if (sdev) {
2822 scsi_device_put(sdev);
2823 break;
2824 }
2825 printk(MYIOC_s_INFO_FMT
4b766471 2826 "attaching raid volume, channel %d, id %d\n",
e8bf3941
JB
2827 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2828 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
c73787ee
ME
2829 mpt_findImVolumes(ioc);
2830 break;
2831 case MPTSAS_DEL_RAID:
e8bf3941 2832 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
b506ade9 2833 ev->id, 0);
c73787ee
ME
2834 if (!sdev)
2835 break;
2836 printk(MYIOC_s_INFO_FMT
4b766471 2837 "removing raid volume, channel %d, id %d\n",
e8bf3941 2838 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
b506ade9 2839 vdevice = sdev->hostdata;
c73787ee
ME
2840 scsi_remove_device(sdev);
2841 scsi_device_put(sdev);
2842 mpt_findImVolumes(ioc);
2843 break;
b506ade9
EM
2844 case MPTSAS_ADD_INACTIVE_VOLUME:
2845 mptsas_adding_inactive_raid_components(ioc,
2846 ev->channel, ev->id);
2847 break;
bd23e94c
ME
2848 case MPTSAS_IGNORE_EVENT:
2849 default:
2850 break;
9a28f49a
CH
2851 }
2852
e6b2d76a 2853 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2854 kfree(ev);
9a28f49a
CH
2855}
2856
2857static void
547f9a21 2858mptsas_send_sas_event(MPT_ADAPTER *ioc,
9a28f49a
CH
2859 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2860{
2861 struct mptsas_hotplug_event *ev;
2862 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2863 __le64 sas_address;
2864
2865 if ((device_info &
2866 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2867 MPI_SAS_DEVICE_INFO_STP_TARGET |
2868 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2869 return;
2870
4b766471 2871 switch (sas_event_data->ReasonCode) {
4b766471 2872 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
df9e062a
EM
2873
2874 mptsas_target_reset_queue(ioc, sas_event_data);
2875 break;
2876
2877 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
547f9a21 2878 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
4b766471 2879 if (!ev) {
29dd3609 2880 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
4b766471
ME
2881 break;
2882 }
9a28f49a 2883
c4028958 2884 INIT_WORK(&ev->work, mptsas_hotplug_work);
4b766471
ME
2885 ev->ioc = ioc;
2886 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2887 ev->parent_handle =
2888 le16_to_cpu(sas_event_data->ParentDevHandle);
2889 ev->channel = sas_event_data->Bus;
2890 ev->id = sas_event_data->TargetID;
2891 ev->phy_id = sas_event_data->PhyNum;
2892 memcpy(&sas_address, &sas_event_data->SASAddress,
2893 sizeof(__le64));
2894 ev->sas_address = le64_to_cpu(sas_address);
2895 ev->device_info = device_info;
2896
2897 if (sas_event_data->ReasonCode &
2898 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2899 ev->event_type = MPTSAS_ADD_DEVICE;
2900 else
2901 ev->event_type = MPTSAS_DEL_DEVICE;
2902 schedule_work(&ev->work);
2903 break;
2904 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2905 /*
2906 * Persistent table is full.
2907 */
547f9a21 2908 INIT_WORK(&ioc->sas_persist_task,
c4028958 2909 mptsas_persist_clear_table);
547f9a21 2910 schedule_work(&ioc->sas_persist_task);
4b766471 2911 break;
b506ade9
EM
2912 /*
2913 * TODO, handle other events
2914 */
4b766471 2915 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
b506ade9 2916 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
4b766471 2917 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
b506ade9
EM
2918 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
2919 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2920 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2921 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
4b766471
ME
2922 default:
2923 break;
9a28f49a 2924 }
9a28f49a 2925}
c73787ee 2926static void
547f9a21 2927mptsas_send_raid_event(MPT_ADAPTER *ioc,
c73787ee
ME
2928 EVENT_DATA_RAID *raid_event_data)
2929{
2930 struct mptsas_hotplug_event *ev;
bd23e94c
ME
2931 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2932 int state = (status >> 8) & 0xff;
c73787ee
ME
2933
2934 if (ioc->bus_type != SAS)
2935 return;
2936
547f9a21 2937 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
c73787ee 2938 if (!ev) {
29dd3609 2939 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
c73787ee
ME
2940 return;
2941 }
2942
c4028958 2943 INIT_WORK(&ev->work, mptsas_hotplug_work);
c73787ee
ME
2944 ev->ioc = ioc;
2945 ev->id = raid_event_data->VolumeID;
b506ade9 2946 ev->channel = raid_event_data->VolumeBus;
bd23e94c 2947 ev->event_type = MPTSAS_IGNORE_EVENT;
c73787ee
ME
2948
2949 switch (raid_event_data->ReasonCode) {
2950 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
b506ade9
EM
2951 ev->phys_disk_num_valid = 1;
2952 ev->phys_disk_num = raid_event_data->PhysDiskNum;
c73787ee
ME
2953 ev->event_type = MPTSAS_ADD_DEVICE;
2954 break;
2955 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
f44e5461
ME
2956 ev->phys_disk_num_valid = 1;
2957 ev->phys_disk_num = raid_event_data->PhysDiskNum;
b506ade9 2958 ev->hidden_raid_component = 1;
c73787ee
ME
2959 ev->event_type = MPTSAS_DEL_DEVICE;
2960 break;
bd23e94c
ME
2961 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2962 switch (state) {
2963 case MPI_PD_STATE_ONLINE:
b506ade9 2964 case MPI_PD_STATE_NOT_COMPATIBLE:
bd23e94c
ME
2965 ev->phys_disk_num_valid = 1;
2966 ev->phys_disk_num = raid_event_data->PhysDiskNum;
b506ade9 2967 ev->hidden_raid_component = 1;
bd23e94c
ME
2968 ev->event_type = MPTSAS_ADD_DEVICE;
2969 break;
2970 case MPI_PD_STATE_MISSING:
bd23e94c
ME
2971 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2972 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2973 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
b506ade9
EM
2974 ev->phys_disk_num_valid = 1;
2975 ev->phys_disk_num = raid_event_data->PhysDiskNum;
bd23e94c
ME
2976 ev->event_type = MPTSAS_DEL_DEVICE;
2977 break;
2978 default:
2979 break;
2980 }
2981 break;
c73787ee
ME
2982 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2983 ev->event_type = MPTSAS_DEL_RAID;
2984 break;
2985 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2986 ev->event_type = MPTSAS_ADD_RAID;
2987 break;
2988 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
bd23e94c
ME
2989 switch (state) {
2990 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2991 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2992 ev->event_type = MPTSAS_DEL_RAID;
2993 break;
2994 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2995 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2996 ev->event_type = MPTSAS_ADD_RAID;
2997 break;
2998 default:
2999 break;
3000 }
c73787ee
ME
3001 break;
3002 default:
3003 break;
3004 }
3005 schedule_work(&ev->work);
3006}
3007
e6b2d76a 3008static void
547f9a21 3009mptsas_send_discovery_event(MPT_ADAPTER *ioc,
e6b2d76a
ME
3010 EVENT_DATA_SAS_DISCOVERY *discovery_data)
3011{
3012 struct mptsas_discovery_event *ev;
3013
3014 /*
3015 * DiscoveryStatus
3016 *
3017 * This flag will be non-zero when firmware
3018 * kicks off discovery, and return to zero
3019 * once its completed.
3020 */
3021 if (discovery_data->DiscoveryStatus)
3022 return;
3023
547f9a21 3024 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
e6b2d76a
ME
3025 if (!ev)
3026 return;
c4028958 3027 INIT_WORK(&ev->work, mptsas_discovery_work);
e6b2d76a
ME
3028 ev->ioc = ioc;
3029 schedule_work(&ev->work);
3030};
3031
b506ade9
EM
3032/*
3033 * mptsas_send_ir2_event - handle exposing hidden disk when
3034 * an inactive raid volume is added
3035 *
3036 * @ioc: Pointer to MPT_ADAPTER structure
3037 * @ir2_data
3038 *
3039 */
3040static void
3041mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
3042{
3043 struct mptsas_hotplug_event *ev;
3044
3045 if (ir2_data->ReasonCode !=
3046 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
3047 return;
3048
3049 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
3050 if (!ev)
3051 return;
3052
3053 INIT_WORK(&ev->work, mptsas_hotplug_work);
3054 ev->ioc = ioc;
3055 ev->id = ir2_data->TargetID;
3056 ev->channel = ir2_data->Bus;
3057 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3058
3059 schedule_work(&ev->work);
3060};
e6b2d76a 3061
9a28f49a
CH
3062static int
3063mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3064{
c73787ee 3065 int rc=1;
9a28f49a
CH
3066 u8 event = le32_to_cpu(reply->Event) & 0xFF;
3067
3068 if (!ioc->sh)
c73787ee 3069 goto out;
9a28f49a 3070
e6b2d76a
ME
3071 /*
3072 * sas_discovery_ignore_events
3073 *
3074 * This flag is to prevent anymore processing of
3075 * sas events once mptsas_remove function is called.
3076 */
3077 if (ioc->sas_discovery_ignore_events) {
3078 rc = mptscsih_event_process(ioc, reply);
3079 goto out;
3080 }
3081
9a28f49a
CH
3082 switch (event) {
3083 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
547f9a21 3084 mptsas_send_sas_event(ioc,
9a28f49a 3085 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
c73787ee
ME
3086 break;
3087 case MPI_EVENT_INTEGRATED_RAID:
547f9a21 3088 mptsas_send_raid_event(ioc,
c73787ee
ME
3089 (EVENT_DATA_RAID *)reply->Data);
3090 break;
79de278e 3091 case MPI_EVENT_PERSISTENT_TABLE_FULL:
547f9a21 3092 INIT_WORK(&ioc->sas_persist_task,
c4028958 3093 mptsas_persist_clear_table);
547f9a21 3094 schedule_work(&ioc->sas_persist_task);
79de278e 3095 break;
4b766471 3096 case MPI_EVENT_SAS_DISCOVERY:
547f9a21 3097 mptsas_send_discovery_event(ioc,
e6b2d76a
ME
3098 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
3099 break;
b506ade9
EM
3100 case MPI_EVENT_IR2:
3101 mptsas_send_ir2_event(ioc,
3102 (PTR_MPI_EVENT_DATA_IR2)reply->Data);
3103 break;
9a28f49a 3104 default:
c73787ee
ME
3105 rc = mptscsih_event_process(ioc, reply);
3106 break;
9a28f49a 3107 }
c73787ee
ME
3108 out:
3109
3110 return rc;
9a28f49a
CH
3111}
3112
0c33b27d
CH
3113static int
3114mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3115{
3116 struct Scsi_Host *sh;
3117 MPT_SCSI_HOST *hd;
3118 MPT_ADAPTER *ioc;
3119 unsigned long flags;
1ca00bb7 3120 int ii;
0c33b27d
CH
3121 int numSGE = 0;
3122 int scale;
3123 int ioc_cap;
0c33b27d
CH
3124 int error=0;
3125 int r;
3126
3127 r = mpt_attach(pdev,id);
3128 if (r)
3129 return r;
3130
3131 ioc = pci_get_drvdata(pdev);
3132 ioc->DoneCtx = mptsasDoneCtx;
3133 ioc->TaskCtx = mptsasTaskCtx;
3134 ioc->InternalCtx = mptsasInternalCtx;
3135
3136 /* Added sanity check on readiness of the MPT adapter.
3137 */
3138 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3139 printk(MYIOC_s_WARN_FMT
3140 "Skipping because it's not operational!\n",
3141 ioc->name);
7acec1e7
MED
3142 error = -ENODEV;
3143 goto out_mptsas_probe;
0c33b27d
CH
3144 }
3145
3146 if (!ioc->active) {
3147 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3148 ioc->name);
7acec1e7
MED
3149 error = -ENODEV;
3150 goto out_mptsas_probe;
0c33b27d
CH
3151 }
3152
3153 /* Sanity check - ensure at least 1 port is INITIATOR capable
3154 */
3155 ioc_cap = 0;
3156 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3157 if (ioc->pfacts[ii].ProtocolFlags &
3158 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3159 ioc_cap++;
3160 }
3161
3162 if (!ioc_cap) {
3163 printk(MYIOC_s_WARN_FMT
3164 "Skipping ioc=%p because SCSI Initiator mode "
3165 "is NOT enabled!\n", ioc->name, ioc);
466544d8 3166 return 0;
0c33b27d
CH
3167 }
3168
3169 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3170 if (!sh) {
3171 printk(MYIOC_s_WARN_FMT
3172 "Unable to register controller with SCSI subsystem\n",
3173 ioc->name);
7acec1e7
MED
3174 error = -1;
3175 goto out_mptsas_probe;
0c33b27d
CH
3176 }
3177
3178 spin_lock_irqsave(&ioc->FreeQlock, flags);
3179
3180 /* Attach the SCSI Host to the IOC structure
3181 */
3182 ioc->sh = sh;
3183
3184 sh->io_port = 0;
3185 sh->n_io_port = 0;
3186 sh->irq = 0;
3187
3188 /* set 16 byte cdb's */
3189 sh->max_cmd_len = 16;
3190
793955f5
EM
3191 sh->max_id = ioc->pfacts[0].PortSCSIID;
3192 sh->max_lun = max_lun;
0c33b27d
CH
3193
3194 sh->transportt = mptsas_transport_template;
3195
0c33b27d
CH
3196 /* Required entry.
3197 */
3198 sh->unique_id = ioc->id;
3199
3200 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 3201 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 3202 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 3203 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 3204 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
3205
3206 /* Verify that we won't exceed the maximum
3207 * number of chain buffers
3208 * We can optimize: ZZ = req_sz/sizeof(SGE)
3209 * For 32bit SGE's:
3210 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
3211 * + (req_sz - 64)/sizeof(SGE)
3212 * A slightly different algorithm is required for
3213 * 64bit SGEs.
3214 */
3215 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3216 if (sizeof(dma_addr_t) == sizeof(u64)) {
3217 numSGE = (scale - 1) *
3218 (ioc->facts.MaxChainDepth-1) + scale +
3219 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
3220 sizeof(u32));
3221 } else {
3222 numSGE = 1 + (scale - 1) *
3223 (ioc->facts.MaxChainDepth-1) + scale +
3224 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
3225 sizeof(u32));
3226 }
3227
3228 if (numSGE < sh->sg_tablesize) {
3229 /* Reset this value */
d6ecdd63 3230 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0c33b27d
CH
3231 "Resetting sg_tablesize to %d from %d\n",
3232 ioc->name, numSGE, sh->sg_tablesize));
3233 sh->sg_tablesize = numSGE;
3234 }
3235
e7eae9f6 3236 hd = shost_priv(sh);
0c33b27d
CH
3237 hd->ioc = ioc;
3238
3239 /* SCSI needs scsi_cmnd lookup table!
3240 * (with size equal to req_depth*PtrSz!)
3241 */
e8206381
EM
3242 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
3243 if (!ioc->ScsiLookup) {
0c33b27d 3244 error = -ENOMEM;
bc6e089a 3245 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
7acec1e7 3246 goto out_mptsas_probe;
0c33b27d 3247 }
e8206381 3248 spin_lock_init(&ioc->scsi_lookup_lock);
0c33b27d 3249
d6ecdd63 3250 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
e8206381 3251 ioc->name, ioc->ScsiLookup));
0c33b27d 3252
0c33b27d
CH
3253 /* Clear the TM flags
3254 */
3255 hd->tmPending = 0;
3256 hd->tmState = TM_STATE_NONE;
3257 hd->resetPending = 0;
3258 hd->abortSCpnt = NULL;
3259
3260 /* Clear the pointer used to store
3261 * single-threaded commands, i.e., those
3262 * issued during a bus scan, dv and
3263 * configuration pages.
3264 */
3265 hd->cmdPtr = NULL;
3266
3267 /* Initialize this SCSI Hosts' timers
3268 * To use, set the timer expires field
3269 * and add_timer
3270 */
3271 init_timer(&hd->timer);
3272 hd->timer.data = (unsigned long) hd;
3273 hd->timer.function = mptscsih_timer_expired;
3274
0c33b27d
CH
3275 ioc->sas_data.ptClear = mpt_pt_clear;
3276
df9e062a
EM
3277 init_waitqueue_head(&hd->scandv_waitq);
3278 hd->scandv_wait_done = 0;
3279 hd->last_queue_full = 0;
3280 INIT_LIST_HEAD(&hd->target_reset_list);
3281 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3282
0c33b27d
CH
3283 if (ioc->sas_data.ptClear==1) {
3284 mptbase_sas_persist_operation(
3285 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
3286 }
3287
0c33b27d
CH
3288 error = scsi_add_host(sh, &ioc->pcidev->dev);
3289 if (error) {
29dd3609
EM
3290 dprintk(ioc, printk(MYIOC_s_ERR_FMT
3291 "scsi_add_host failed\n", ioc->name));
7acec1e7 3292 goto out_mptsas_probe;
0c33b27d
CH
3293 }
3294
3295 mptsas_scan_sas_topology(ioc);
3296
3297 return 0;
3298
547f9a21 3299 out_mptsas_probe:
0c33b27d
CH
3300
3301 mptscsih_remove(pdev);
3302 return error;
3303}
3304
3305static void __devexit mptsas_remove(struct pci_dev *pdev)
3306{
3307 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3308 struct mptsas_portinfo *p, *n;
547f9a21 3309 int i;
0c33b27d 3310
b506ade9 3311 ioc->sas_discovery_ignore_events = 1;
0c33b27d
CH
3312 sas_remove_host(ioc->sh);
3313
9a28f49a 3314 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
3315 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
3316 list_del(&p->list);
547f9a21 3317 for (i = 0 ; i < p->num_phys ; i++)
d6ecdd63 3318 mptsas_port_delete(ioc, p->phy_info[i].port_details);
547f9a21 3319 kfree(p->phy_info);
0c33b27d
CH
3320 kfree(p);
3321 }
9a28f49a 3322 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
3323
3324 mptscsih_remove(pdev);
3325}
3326
3327static struct pci_device_id mptsas_pci_table[] = {
87cf8986 3328 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 3329 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3330 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 3331 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3332 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 3333 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3334 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 3335 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3336 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
3337 PCI_ANY_ID, PCI_ANY_ID },
3338 {0} /* Terminating entry */
3339};
3340MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
3341
3342
3343static struct pci_driver mptsas_driver = {
3344 .name = "mptsas",
3345 .id_table = mptsas_pci_table,
3346 .probe = mptsas_probe,
3347 .remove = __devexit_p(mptsas_remove),
3348 .shutdown = mptscsih_shutdown,
3349#ifdef CONFIG_PM
3350 .suspend = mptscsih_suspend,
3351 .resume = mptscsih_resume,
3352#endif
3353};
3354
3355static int __init
3356mptsas_init(void)
3357{
57ce21bf
PS
3358 int error;
3359
0c33b27d
CH
3360 show_mptmod_ver(my_NAME, my_VERSION);
3361
3362 mptsas_transport_template =
3363 sas_attach_transport(&mptsas_transport_functions);
3364 if (!mptsas_transport_template)
3365 return -ENODEV;
3366
3367 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
df9e062a 3368 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d
CH
3369 mptsasInternalCtx =
3370 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 3371 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
0c33b27d 3372
d6ecdd63
PS
3373 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
3374 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
0c33b27d 3375
57ce21bf
PS
3376 error = pci_register_driver(&mptsas_driver);
3377 if (error)
3378 sas_release_transport(mptsas_transport_template);
3379
3380 return error;
0c33b27d
CH
3381}
3382
3383static void __exit
3384mptsas_exit(void)
3385{
3386 pci_unregister_driver(&mptsas_driver);
3387 sas_release_transport(mptsas_transport_template);
3388
3389 mpt_reset_deregister(mptsasDoneCtx);
3390 mpt_event_deregister(mptsasDoneCtx);
3391
da4fa655 3392 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
3393 mpt_deregister(mptsasInternalCtx);
3394 mpt_deregister(mptsasTaskCtx);
3395 mpt_deregister(mptsasDoneCtx);
3396}
3397
3398module_init(mptsas_init);
3399module_exit(mptsas_exit);