blob: 289fcdbe89ba1277555fbb49877b83911e634d4e [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01008 * Copyright (c) 2005-2006 Dell
Christoph Hellwig0c33b272005-09-09 16:27:19 +02009 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
53
54#include <scsi/scsi_cmnd.h>
55#include <scsi/scsi_device.h>
56#include <scsi/scsi_host.h>
57#include <scsi/scsi_transport_sas.h>
58
59#include "mptbase.h"
60#include "mptscsih.h"
61
62
63#define my_NAME "Fusion MPT SAS Host driver"
64#define my_VERSION MPT_LINUX_VERSION_COMMON
65#define MYNAM "mptsas"
66
67MODULE_AUTHOR(MODULEAUTHOR);
68MODULE_DESCRIPTION(my_NAME);
69MODULE_LICENSE("GPL");
70
71static int mpt_pq_filter;
72module_param(mpt_pq_filter, int, 0);
73MODULE_PARM_DESC(mpt_pq_filter,
74 "Enable peripheral qualifier filter: enable=1 "
75 "(default=0)");
76
77static int mpt_pt_clear;
78module_param(mpt_pt_clear, int, 0);
79MODULE_PARM_DESC(mpt_pt_clear,
80 "Clear persistency table: enable=1 "
81 "(default=MPTSCSIH_PT_CLEAR=0)");
82
83static int mptsasDoneCtx = -1;
84static int mptsasTaskCtx = -1;
85static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020086static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020087
88
Christoph Hellwig9a28f492006-01-13 18:04:41 +010089enum mptsas_hotplug_action {
90 MPTSAS_ADD_DEVICE,
91 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -070092 MPTSAS_ADD_RAID,
93 MPTSAS_DEL_RAID,
Christoph Hellwig9a28f492006-01-13 18:04:41 +010094};
95
96struct mptsas_hotplug_event {
97 struct work_struct work;
98 MPT_ADAPTER *ioc;
99 enum mptsas_hotplug_action event_type;
100 u64 sas_address;
101 u32 channel;
102 u32 id;
103 u32 device_info;
104 u16 handle;
105 u16 parent_handle;
106 u8 phy_id;
Moore, Ericf44e5462006-03-14 09:14:21 -0700107 u8 phys_disk_num;
108 u8 phys_disk_num_valid;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100109};
110
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200111/*
112 * SAS topology structures
113 *
114 * The MPT Fusion firmware interface spreads information about the
115 * SAS topology over many manufacture pages, thus we need some data
116 * structure to collect it and process it for the SAS transport class.
117 */
118
119struct mptsas_devinfo {
120 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700121 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100122 u16 handle_enclosure; /* enclosure identifier of the enclosure */
123 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200124 u8 phy_id; /* phy number of parent device */
125 u8 port_id; /* sas physical port this device
126 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100127 u8 id; /* logical target id of this device */
128 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200129 u64 sas_address; /* WWN of this device,
130 SATA is assigned by HBA,expander */
131 u32 device_info; /* bitfield detailed info about this device */
132};
133
134struct mptsas_phyinfo {
135 u8 phy_id; /* phy index */
136 u8 port_id; /* port number this phy is part of */
137 u8 negotiated_link_rate; /* nego'd link rate for this phy */
138 u8 hw_link_rate; /* hardware max/min phys link rate */
139 u8 programmed_link_rate; /* programmed max/min phy link rate */
140 struct mptsas_devinfo identify; /* point to phy device info */
141 struct mptsas_devinfo attached; /* point to attached device info */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100142 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200143 struct sas_rphy *rphy;
Moore, Ericf44e5462006-03-14 09:14:21 -0700144 struct scsi_target *starget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200145};
146
147struct mptsas_portinfo {
148 struct list_head list;
149 u16 handle; /* unique id to address this */
150 u8 num_phys; /* number of phys */
151 struct mptsas_phyinfo *phy_info;
152};
153
Christoph Hellwige3094442006-02-16 13:25:36 +0100154struct mptsas_enclosure {
155 u64 enclosure_logical_id; /* The WWN for the enclosure */
156 u16 enclosure_handle; /* unique id to address this */
157 u16 flags; /* details enclosure management */
158 u16 num_slot; /* num slots */
159 u16 start_slot; /* first slot */
160 u8 start_id; /* starting logical target id */
161 u8 start_channel; /* starting logical channel id */
162 u8 sep_id; /* SEP device logical target id */
163 u8 sep_channel; /* SEP channel logical channel id */
164};
165
Christoph Hellwigb5141122005-10-28 22:07:41 +0200166
167#ifdef SASDEBUG
168static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
169{
170 printk("---- IO UNIT PAGE 0 ------------\n");
171 printk("Handle=0x%X\n",
172 le16_to_cpu(phy_data->AttachedDeviceHandle));
173 printk("Controller Handle=0x%X\n",
174 le16_to_cpu(phy_data->ControllerDevHandle));
175 printk("Port=0x%X\n", phy_data->Port);
176 printk("Port Flags=0x%X\n", phy_data->PortFlags);
177 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
178 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
179 printk("Controller PHY Device Info=0x%X\n",
180 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
181 printk("DiscoveryStatus=0x%X\n",
182 le32_to_cpu(phy_data->DiscoveryStatus));
183 printk("\n");
184}
185
186static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
187{
188 __le64 sas_address;
189
190 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
191
192 printk("---- SAS PHY PAGE 0 ------------\n");
193 printk("Attached Device Handle=0x%X\n",
194 le16_to_cpu(pg0->AttachedDevHandle));
195 printk("SAS Address=0x%llX\n",
196 (unsigned long long)le64_to_cpu(sas_address));
197 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
198 printk("Attached Device Info=0x%X\n",
199 le32_to_cpu(pg0->AttachedDeviceInfo));
200 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
201 printk("Change Count=0x%X\n", pg0->ChangeCount);
202 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
203 printk("\n");
204}
205
206static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
207{
208 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200209 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
210 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200211 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200212 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
213 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
214 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200215}
216
217static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
218{
219 __le64 sas_address;
220
221 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
222
223 printk("---- SAS DEVICE PAGE 0 ---------\n");
224 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100225 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200226 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
227 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
228 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
229 printk("Target ID=0x%X\n", pg0->TargetID);
230 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200231 /* The PhyNum field specifies the PHY number of the parent
232 * device this device is linked to
233 */
234 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
235 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200236 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
237 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
238 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
239 printk("\n");
240}
241
242static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
243{
244 printk("---- SAS EXPANDER PAGE 1 ------------\n");
245
246 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200247 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200248 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
249 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
250 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
251 printk("Owner Device Handle=0x%X\n",
252 le16_to_cpu(pg1->OwnerDevHandle));
253 printk("Attached Device Handle=0x%X\n",
254 le16_to_cpu(pg1->AttachedDevHandle));
255}
256#else
257#define mptsas_print_phy_data(phy_data) do { } while (0)
258#define mptsas_print_phy_pg0(pg0) do { } while (0)
259#define mptsas_print_phy_pg1(pg1) do { } while (0)
260#define mptsas_print_device_pg0(pg0) do { } while (0)
261#define mptsas_print_expander_pg1(pg1) do { } while (0)
262#endif
263
Christoph Hellwige3094442006-02-16 13:25:36 +0100264static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
265{
266 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
267 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
268}
269
270static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
271{
272 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
273 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
274}
275
276static int
Moore, Eric52435432006-03-14 09:14:15 -0700277mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100278 u32 form, u32 form_specific)
279{
280 ConfigExtendedPageHeader_t hdr;
281 CONFIGPARMS cfg;
282 SasEnclosurePage0_t *buffer;
283 dma_addr_t dma_handle;
284 int error;
285 __le64 le_identifier;
286
287 memset(&hdr, 0, sizeof(hdr));
288 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
289 hdr.PageNumber = 0;
290 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
291 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
292
293 cfg.cfghdr.ehdr = &hdr;
294 cfg.physAddr = -1;
295 cfg.pageAddr = form + form_specific;
296 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
297 cfg.dir = 0; /* read */
298 cfg.timeout = 10;
299
300 error = mpt_config(ioc, &cfg);
301 if (error)
302 goto out;
303 if (!hdr.ExtPageLength) {
304 error = -ENXIO;
305 goto out;
306 }
307
308 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
309 &dma_handle);
310 if (!buffer) {
311 error = -ENOMEM;
312 goto out;
313 }
314
315 cfg.physAddr = dma_handle;
316 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
317
318 error = mpt_config(ioc, &cfg);
319 if (error)
320 goto out_free_consistent;
321
322 /* save config data */
323 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
324 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
325 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
326 enclosure->flags = le16_to_cpu(buffer->Flags);
327 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
328 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
329 enclosure->start_id = buffer->StartTargetID;
330 enclosure->start_channel = buffer->StartBus;
331 enclosure->sep_id = buffer->SEPTargetID;
332 enclosure->sep_channel = buffer->SEPBus;
333
334 out_free_consistent:
335 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
336 buffer, dma_handle);
337 out:
338 return error;
339}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200340
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200341/*
342 * This is pretty ugly. We will be able to seriously clean it up
343 * once the DV code in mptscsih goes away and we can properly
344 * implement ->target_alloc.
345 */
346static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700347mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200348{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700349 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200350 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
351 struct sas_rphy *rphy;
352 struct mptsas_portinfo *p;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700353 VirtTarget *vtarget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200354 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700355 struct scsi_target *starget;
Moore, Eric914c2d82006-03-14 09:19:36 -0700356 u32 target_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200357 int i;
358
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100359 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200360 if (!vdev) {
361 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
362 hd->ioc->name, sizeof(VirtDevice));
363 return -ENOMEM;
364 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700365 sdev->hostdata = vdev;
366 starget = scsi_target(sdev);
367 vtarget = starget->hostdata;
Moore, Eric914c2d82006-03-14 09:19:36 -0700368 vtarget->ioc_id = hd->ioc->id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700369 vdev->vtarget = vtarget;
370 if (vtarget->num_luns == 0) {
371 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
372 hd->Targets[sdev->id] = vtarget;
373 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200374
Moore, Eric816aa902006-01-13 16:25:20 -0700375 /*
376 RAID volumes placed beyond the last expected port.
377 */
378 if (sdev->channel == hd->ioc->num_ports) {
Moore, Eric914c2d82006-03-14 09:19:36 -0700379 target_id = sdev->id;
380 vtarget->bus_id = 0;
Moore, Eric816aa902006-01-13 16:25:20 -0700381 vdev->lun = 0;
382 goto out;
383 }
384
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700385 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100386 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200387 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
388 for (i = 0; i < p->num_phys; i++) {
389 if (p->phy_info[i].attached.sas_address ==
390 rphy->identify.sas_address) {
Moore, Eric914c2d82006-03-14 09:19:36 -0700391 target_id = p->phy_info[i].attached.id;
392 vtarget->bus_id = p->phy_info[i].attached.channel;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700393 vdev->lun = sdev->lun;
Moore, Ericf44e5462006-03-14 09:14:21 -0700394 p->phy_info[i].starget = sdev->sdev_target;
395 /*
396 * Exposing hidden disk (RAID)
397 */
398 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
399 target_id = mptscsih_raid_id_to_num(hd,
400 target_id);
401 vdev->vtarget->tflags |=
402 MPT_TARGET_FLAGS_RAID_COMPONENT;
403 sdev->no_uld_attach = 1;
404 }
Moore, Eric914c2d82006-03-14 09:19:36 -0700405 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200406 goto out;
407 }
408 }
409 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100410 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200411
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200412 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100413 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200414
415 out:
Moore, Eric914c2d82006-03-14 09:19:36 -0700416 vtarget->target_id = target_id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700417 vtarget->num_luns++;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200418 return 0;
419}
420
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100421static void
422mptsas_slave_destroy(struct scsi_device *sdev)
423{
424 struct Scsi_Host *host = sdev->host;
425 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
426 struct sas_rphy *rphy;
427 struct mptsas_portinfo *p;
428 int i;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700429 VirtDevice *vdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100430
431 /*
432 * Handle hotplug removal case.
433 * We need to clear out attached data structure.
434 */
435 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
436
437 mutex_lock(&hd->ioc->sas_topology_mutex);
438 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
439 for (i = 0; i < p->num_phys; i++) {
440 if (p->phy_info[i].attached.sas_address ==
441 rphy->identify.sas_address) {
442 memset(&p->phy_info[i].attached, 0,
443 sizeof(struct mptsas_devinfo));
444 p->phy_info[i].rphy = NULL;
445 goto out;
446 }
447 }
448 }
449
450 out:
451 mutex_unlock(&hd->ioc->sas_topology_mutex);
452 /*
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700453 * Issue target reset to flush firmware outstanding commands.
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100454 */
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700455 vdev = sdev->hostdata;
456 if (vdev->configured_lun){
457 if (mptscsih_TMHandler(hd,
458 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
Moore, Eric914c2d82006-03-14 09:19:36 -0700459 vdev->vtarget->bus_id,
460 vdev->vtarget->target_id,
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700461 0, 0, 5 /* 5 second timeout */)
462 < 0){
463
464 /* The TM request failed!
465 * Fatal error case.
466 */
467 printk(MYIOC_s_WARN_FMT
468 "Error processing TaskMgmt id=%d TARGET_RESET\n",
469 hd->ioc->name,
Moore, Eric914c2d82006-03-14 09:19:36 -0700470 vdev->vtarget->target_id);
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700471
472 hd->tmPending = 0;
473 hd->tmState = TM_STATE_NONE;
474 }
475 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100476 mptscsih_slave_destroy(sdev);
477}
478
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200479static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700480 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200481 .proc_name = "mptsas",
482 .proc_info = mptscsih_proc_info,
483 .name = "MPT SPI Host",
484 .info = mptscsih_info,
485 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700486 .target_alloc = mptscsih_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200487 .slave_alloc = mptsas_slave_alloc,
488 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700489 .target_destroy = mptscsih_target_destroy,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100490 .slave_destroy = mptsas_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200491 .change_queue_depth = mptscsih_change_queue_depth,
492 .eh_abort_handler = mptscsih_abort,
493 .eh_device_reset_handler = mptscsih_dev_reset,
494 .eh_bus_reset_handler = mptscsih_bus_reset,
495 .eh_host_reset_handler = mptscsih_host_reset,
496 .bios_param = mptscsih_bios_param,
497 .can_queue = MPT_FC_CAN_QUEUE,
498 .this_id = -1,
499 .sg_tablesize = MPT_SCSI_SG_DEPTH,
500 .max_sectors = 8192,
501 .cmd_per_lun = 7,
502 .use_clustering = ENABLE_CLUSTERING,
503};
504
Christoph Hellwigb5141122005-10-28 22:07:41 +0200505static int mptsas_get_linkerrors(struct sas_phy *phy)
506{
507 MPT_ADAPTER *ioc = phy_to_ioc(phy);
508 ConfigExtendedPageHeader_t hdr;
509 CONFIGPARMS cfg;
510 SasPhyPage1_t *buffer;
511 dma_addr_t dma_handle;
512 int error;
513
514 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
515 hdr.ExtPageLength = 0;
516 hdr.PageNumber = 1 /* page number 1*/;
517 hdr.Reserved1 = 0;
518 hdr.Reserved2 = 0;
519 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
520 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
521
522 cfg.cfghdr.ehdr = &hdr;
523 cfg.physAddr = -1;
524 cfg.pageAddr = phy->identify.phy_identifier;
525 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
526 cfg.dir = 0; /* read */
527 cfg.timeout = 10;
528
529 error = mpt_config(ioc, &cfg);
530 if (error)
531 return error;
532 if (!hdr.ExtPageLength)
533 return -ENXIO;
534
535 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
536 &dma_handle);
537 if (!buffer)
538 return -ENOMEM;
539
540 cfg.physAddr = dma_handle;
541 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
542
543 error = mpt_config(ioc, &cfg);
544 if (error)
545 goto out_free_consistent;
546
547 mptsas_print_phy_pg1(buffer);
548
549 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
550 phy->running_disparity_error_count =
551 le32_to_cpu(buffer->RunningDisparityErrorCount);
552 phy->loss_of_dword_sync_count =
553 le32_to_cpu(buffer->LossDwordSynchCount);
554 phy->phy_reset_problem_count =
555 le32_to_cpu(buffer->PhyResetProblemCount);
556
557 out_free_consistent:
558 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
559 buffer, dma_handle);
560 return error;
561}
562
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200563static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
564 MPT_FRAME_HDR *reply)
565{
566 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
567 if (reply != NULL) {
568 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
569 memcpy(ioc->sas_mgmt.reply, reply,
570 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
571 }
572 complete(&ioc->sas_mgmt.done);
573 return 1;
574}
575
576static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
577{
578 MPT_ADAPTER *ioc = phy_to_ioc(phy);
579 SasIoUnitControlRequest_t *req;
580 SasIoUnitControlReply_t *reply;
581 MPT_FRAME_HDR *mf;
582 MPIHeader_t *hdr;
583 unsigned long timeleft;
584 int error = -ERESTARTSYS;
585
586 /* not implemented for expanders */
587 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
588 return -ENXIO;
589
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100590 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200591 goto out;
592
593 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
594 if (!mf) {
595 error = -ENOMEM;
596 goto out_unlock;
597 }
598
599 hdr = (MPIHeader_t *) mf;
600 req = (SasIoUnitControlRequest_t *)mf;
601 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
602 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
603 req->MsgContext = hdr->MsgContext;
604 req->Operation = hard_reset ?
605 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
606 req->PhyNum = phy->identify.phy_identifier;
607
608 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
609
610 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
611 10 * HZ);
612 if (!timeleft) {
613 /* On timeout reset the board */
614 mpt_free_msg_frame(ioc, mf);
615 mpt_HardResetHandler(ioc, CAN_SLEEP);
616 error = -ETIMEDOUT;
617 goto out_unlock;
618 }
619
620 /* a reply frame is expected */
621 if ((ioc->sas_mgmt.status &
622 MPT_IOCTL_STATUS_RF_VALID) == 0) {
623 error = -ENXIO;
624 goto out_unlock;
625 }
626
627 /* process the completed Reply Message Frame */
628 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
629 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
630 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
631 __FUNCTION__,
632 reply->IOCStatus,
633 reply->IOCLogInfo);
634 error = -ENXIO;
635 goto out_unlock;
636 }
637
638 error = 0;
639
640 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100641 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200642 out:
643 return error;
644}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200645
Christoph Hellwige3094442006-02-16 13:25:36 +0100646static int
647mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
648{
649 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
650 int i, error;
651 struct mptsas_portinfo *p;
652 struct mptsas_enclosure enclosure_info;
653 u64 enclosure_handle;
654
655 mutex_lock(&ioc->sas_topology_mutex);
656 list_for_each_entry(p, &ioc->sas_topology, list) {
657 for (i = 0; i < p->num_phys; i++) {
658 if (p->phy_info[i].attached.sas_address ==
659 rphy->identify.sas_address) {
660 enclosure_handle = p->phy_info[i].
661 attached.handle_enclosure;
662 goto found_info;
663 }
664 }
665 }
666 mutex_unlock(&ioc->sas_topology_mutex);
667 return -ENXIO;
668
669 found_info:
670 mutex_unlock(&ioc->sas_topology_mutex);
671 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -0700672 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +0100673 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
674 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
675 if (!error)
676 *identifier = enclosure_info.enclosure_logical_id;
677 return error;
678}
679
680static int
681mptsas_get_bay_identifier(struct sas_rphy *rphy)
682{
683 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
684 struct mptsas_portinfo *p;
685 int i, rc;
686
687 mutex_lock(&ioc->sas_topology_mutex);
688 list_for_each_entry(p, &ioc->sas_topology, list) {
689 for (i = 0; i < p->num_phys; i++) {
690 if (p->phy_info[i].attached.sas_address ==
691 rphy->identify.sas_address) {
692 rc = p->phy_info[i].attached.slot;
693 goto out;
694 }
695 }
696 }
697 rc = -ENXIO;
698 out:
699 mutex_unlock(&ioc->sas_topology_mutex);
700 return rc;
701}
702
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200703static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200704 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +0100705 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
706 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200707 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200708};
709
710static struct scsi_transport_template *mptsas_transport_template;
711
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200712static int
713mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
714{
715 ConfigExtendedPageHeader_t hdr;
716 CONFIGPARMS cfg;
717 SasIOUnitPage0_t *buffer;
718 dma_addr_t dma_handle;
719 int error, i;
720
721 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
722 hdr.ExtPageLength = 0;
723 hdr.PageNumber = 0;
724 hdr.Reserved1 = 0;
725 hdr.Reserved2 = 0;
726 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
727 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
728
729 cfg.cfghdr.ehdr = &hdr;
730 cfg.physAddr = -1;
731 cfg.pageAddr = 0;
732 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
733 cfg.dir = 0; /* read */
734 cfg.timeout = 10;
735
736 error = mpt_config(ioc, &cfg);
737 if (error)
738 goto out;
739 if (!hdr.ExtPageLength) {
740 error = -ENXIO;
741 goto out;
742 }
743
744 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
745 &dma_handle);
746 if (!buffer) {
747 error = -ENOMEM;
748 goto out;
749 }
750
751 cfg.physAddr = dma_handle;
752 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
753
754 error = mpt_config(ioc, &cfg);
755 if (error)
756 goto out_free_consistent;
757
758 port_info->num_phys = buffer->NumPhys;
759 port_info->phy_info = kcalloc(port_info->num_phys,
760 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
761 if (!port_info->phy_info) {
762 error = -ENOMEM;
763 goto out_free_consistent;
764 }
765
Moore, Ericdb9c9172006-03-14 09:14:18 -0700766 if (port_info->num_phys)
767 port_info->handle =
768 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200769 for (i = 0; i < port_info->num_phys; i++) {
770 mptsas_print_phy_data(&buffer->PhyData[i]);
771 port_info->phy_info[i].phy_id = i;
772 port_info->phy_info[i].port_id =
773 buffer->PhyData[i].Port;
774 port_info->phy_info[i].negotiated_link_rate =
775 buffer->PhyData[i].NegotiatedLinkRate;
776 }
777
778 out_free_consistent:
779 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
780 buffer, dma_handle);
781 out:
782 return error;
783}
784
785static int
786mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
787 u32 form, u32 form_specific)
788{
789 ConfigExtendedPageHeader_t hdr;
790 CONFIGPARMS cfg;
791 SasPhyPage0_t *buffer;
792 dma_addr_t dma_handle;
793 int error;
794
795 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
796 hdr.ExtPageLength = 0;
797 hdr.PageNumber = 0;
798 hdr.Reserved1 = 0;
799 hdr.Reserved2 = 0;
800 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
801 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
802
803 cfg.cfghdr.ehdr = &hdr;
804 cfg.dir = 0; /* read */
805 cfg.timeout = 10;
806
807 /* Get Phy Pg 0 for each Phy. */
808 cfg.physAddr = -1;
809 cfg.pageAddr = form + form_specific;
810 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
811
812 error = mpt_config(ioc, &cfg);
813 if (error)
814 goto out;
815
816 if (!hdr.ExtPageLength) {
817 error = -ENXIO;
818 goto out;
819 }
820
821 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
822 &dma_handle);
823 if (!buffer) {
824 error = -ENOMEM;
825 goto out;
826 }
827
828 cfg.physAddr = dma_handle;
829 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
830
831 error = mpt_config(ioc, &cfg);
832 if (error)
833 goto out_free_consistent;
834
835 mptsas_print_phy_pg0(buffer);
836
837 phy_info->hw_link_rate = buffer->HwLinkRate;
838 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
839 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
840 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
841
842 out_free_consistent:
843 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
844 buffer, dma_handle);
845 out:
846 return error;
847}
848
849static int
850mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
851 u32 form, u32 form_specific)
852{
853 ConfigExtendedPageHeader_t hdr;
854 CONFIGPARMS cfg;
855 SasDevicePage0_t *buffer;
856 dma_addr_t dma_handle;
857 __le64 sas_address;
858 int error;
859
860 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
861 hdr.ExtPageLength = 0;
862 hdr.PageNumber = 0;
863 hdr.Reserved1 = 0;
864 hdr.Reserved2 = 0;
865 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
866 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
867
868 cfg.cfghdr.ehdr = &hdr;
869 cfg.pageAddr = form + form_specific;
870 cfg.physAddr = -1;
871 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
872 cfg.dir = 0; /* read */
873 cfg.timeout = 10;
874
Moore, Ericdb9c9172006-03-14 09:14:18 -0700875 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200876 error = mpt_config(ioc, &cfg);
877 if (error)
878 goto out;
879 if (!hdr.ExtPageLength) {
880 error = -ENXIO;
881 goto out;
882 }
883
884 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
885 &dma_handle);
886 if (!buffer) {
887 error = -ENOMEM;
888 goto out;
889 }
890
891 cfg.physAddr = dma_handle;
892 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
893
894 error = mpt_config(ioc, &cfg);
895 if (error)
896 goto out_free_consistent;
897
898 mptsas_print_device_pg0(buffer);
899
900 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -0700901 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +0100902 device_info->handle_enclosure =
903 le16_to_cpu(buffer->EnclosureHandle);
904 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200905 device_info->phy_id = buffer->PhyNum;
906 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100907 device_info->id = buffer->TargetID;
908 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200909 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
910 device_info->sas_address = le64_to_cpu(sas_address);
911 device_info->device_info =
912 le32_to_cpu(buffer->DeviceInfo);
913
914 out_free_consistent:
915 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
916 buffer, dma_handle);
917 out:
918 return error;
919}
920
921static int
922mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
923 u32 form, u32 form_specific)
924{
925 ConfigExtendedPageHeader_t hdr;
926 CONFIGPARMS cfg;
927 SasExpanderPage0_t *buffer;
928 dma_addr_t dma_handle;
929 int error;
930
931 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
932 hdr.ExtPageLength = 0;
933 hdr.PageNumber = 0;
934 hdr.Reserved1 = 0;
935 hdr.Reserved2 = 0;
936 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
937 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
938
939 cfg.cfghdr.ehdr = &hdr;
940 cfg.physAddr = -1;
941 cfg.pageAddr = form + form_specific;
942 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
943 cfg.dir = 0; /* read */
944 cfg.timeout = 10;
945
Moore, Ericdb9c9172006-03-14 09:14:18 -0700946 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200947 error = mpt_config(ioc, &cfg);
948 if (error)
949 goto out;
950
951 if (!hdr.ExtPageLength) {
952 error = -ENXIO;
953 goto out;
954 }
955
956 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
957 &dma_handle);
958 if (!buffer) {
959 error = -ENOMEM;
960 goto out;
961 }
962
963 cfg.physAddr = dma_handle;
964 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
965
966 error = mpt_config(ioc, &cfg);
967 if (error)
968 goto out_free_consistent;
969
970 /* save config data */
971 port_info->num_phys = buffer->NumPhys;
972 port_info->handle = le16_to_cpu(buffer->DevHandle);
973 port_info->phy_info = kcalloc(port_info->num_phys,
974 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
975 if (!port_info->phy_info) {
976 error = -ENOMEM;
977 goto out_free_consistent;
978 }
979
980 out_free_consistent:
981 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
982 buffer, dma_handle);
983 out:
984 return error;
985}
986
987static int
988mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
989 u32 form, u32 form_specific)
990{
991 ConfigExtendedPageHeader_t hdr;
992 CONFIGPARMS cfg;
993 SasExpanderPage1_t *buffer;
994 dma_addr_t dma_handle;
995 int error;
996
997 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
998 hdr.ExtPageLength = 0;
999 hdr.PageNumber = 1;
1000 hdr.Reserved1 = 0;
1001 hdr.Reserved2 = 0;
1002 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1003 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1004
1005 cfg.cfghdr.ehdr = &hdr;
1006 cfg.physAddr = -1;
1007 cfg.pageAddr = form + form_specific;
1008 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1009 cfg.dir = 0; /* read */
1010 cfg.timeout = 10;
1011
1012 error = mpt_config(ioc, &cfg);
1013 if (error)
1014 goto out;
1015
1016 if (!hdr.ExtPageLength) {
1017 error = -ENXIO;
1018 goto out;
1019 }
1020
1021 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1022 &dma_handle);
1023 if (!buffer) {
1024 error = -ENOMEM;
1025 goto out;
1026 }
1027
1028 cfg.physAddr = dma_handle;
1029 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1030
1031 error = mpt_config(ioc, &cfg);
1032 if (error)
1033 goto out_free_consistent;
1034
1035
1036 mptsas_print_expander_pg1(buffer);
1037
1038 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001039 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001040 phy_info->port_id = buffer->PhysicalPort;
1041 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1042 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1043 phy_info->hw_link_rate = buffer->HwLinkRate;
1044 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1045 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1046
1047
1048 out_free_consistent:
1049 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1050 buffer, dma_handle);
1051 out:
1052 return error;
1053}
1054
Moore, Ericc73787ee2006-01-26 16:20:06 -07001055/*
1056 * Returns true if there is a scsi end device
1057 */
1058static inline int
1059mptsas_is_end_device(struct mptsas_devinfo * attached)
1060{
1061 if ((attached->handle) &&
1062 (attached->device_info &
1063 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
1064 ((attached->device_info &
1065 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
1066 (attached->device_info &
1067 MPI_SAS_DEVICE_INFO_STP_TARGET) |
1068 (attached->device_info &
1069 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
1070 return 1;
1071 else
1072 return 0;
1073}
1074
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001075static void
1076mptsas_parse_device_info(struct sas_identify *identify,
1077 struct mptsas_devinfo *device_info)
1078{
1079 u16 protocols;
1080
1081 identify->sas_address = device_info->sas_address;
1082 identify->phy_identifier = device_info->phy_id;
1083
1084 /*
1085 * Fill in Phy Initiator Port Protocol.
1086 * Bits 6:3, more than one bit can be set, fall through cases.
1087 */
1088 protocols = device_info->device_info & 0x78;
1089 identify->initiator_port_protocols = 0;
1090 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1091 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1092 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1093 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1094 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1095 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1096 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1097 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1098
1099 /*
1100 * Fill in Phy Target Port Protocol.
1101 * Bits 10:7, more than one bit can be set, fall through cases.
1102 */
1103 protocols = device_info->device_info & 0x780;
1104 identify->target_port_protocols = 0;
1105 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1106 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1107 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1108 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1109 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1110 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1111 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1112 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1113
1114 /*
1115 * Fill in Attached device type.
1116 */
1117 switch (device_info->device_info &
1118 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1119 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1120 identify->device_type = SAS_PHY_UNUSED;
1121 break;
1122 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1123 identify->device_type = SAS_END_DEVICE;
1124 break;
1125 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1126 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1127 break;
1128 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1129 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1130 break;
1131 }
1132}
1133
1134static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001135 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001136{
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001137 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001138 int error;
1139
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001140 phy = sas_phy_alloc(dev, index);
1141 if (!phy)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001142 return -ENOMEM;
1143
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001144 phy->port_identifier = phy_info->port_id;
1145 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001146
1147 /*
1148 * Set Negotiated link rate.
1149 */
1150 switch (phy_info->negotiated_link_rate) {
1151 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001152 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001153 break;
1154 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001155 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001156 break;
1157 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001158 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001159 break;
1160 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001161 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001162 break;
1163 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1164 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1165 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001166 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001167 break;
1168 }
1169
1170 /*
1171 * Set Max hardware link rate.
1172 */
1173 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1174 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001175 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001176 break;
1177 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001178 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001179 break;
1180 default:
1181 break;
1182 }
1183
1184 /*
1185 * Set Max programmed link rate.
1186 */
1187 switch (phy_info->programmed_link_rate &
1188 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1189 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001190 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001191 break;
1192 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001193 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001194 break;
1195 default:
1196 break;
1197 }
1198
1199 /*
1200 * Set Min hardware link rate.
1201 */
1202 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1203 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001204 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001205 break;
1206 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001207 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001208 break;
1209 default:
1210 break;
1211 }
1212
1213 /*
1214 * Set Min programmed link rate.
1215 */
1216 switch (phy_info->programmed_link_rate &
1217 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1218 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001219 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001220 break;
1221 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001222 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001223 break;
1224 default:
1225 break;
1226 }
1227
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001228 if (local)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001229 phy->local_attached = 1;
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001230
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001231 error = sas_phy_add(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001232 if (error) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001233 sas_phy_free(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001234 return error;
1235 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001236 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001237
1238 if (phy_info->attached.handle) {
1239 struct sas_rphy *rphy;
1240
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001241 rphy = sas_rphy_alloc(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001242 if (!rphy)
1243 return 0; /* non-fatal: an rphy can be added later */
1244
1245 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1246 error = sas_rphy_add(rphy);
1247 if (error) {
1248 sas_rphy_free(rphy);
1249 return error;
1250 }
1251
1252 phy_info->rphy = rphy;
1253 }
1254
1255 return 0;
1256}
1257
1258static int
1259mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
1260{
1261 struct mptsas_portinfo *port_info;
1262 u32 handle = 0xFFFF;
1263 int error = -ENOMEM, i;
1264
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001265 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001266 if (!port_info)
1267 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001268
1269 error = mptsas_sas_io_unit_pg0(ioc, port_info);
1270 if (error)
1271 goto out_free_port_info;
1272
Moore, Eric816aa902006-01-13 16:25:20 -07001273 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001274 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001275 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001276 mutex_unlock(&ioc->sas_topology_mutex);
1277
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001278 for (i = 0; i < port_info->num_phys; i++) {
1279 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1280 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1281 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1282
1283 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1284 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1285 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001286 port_info->phy_info[i].identify.phy_id =
1287 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001288 handle = port_info->phy_info[i].identify.handle;
1289
1290 if (port_info->phy_info[i].attached.handle) {
1291 mptsas_sas_device_pg0(ioc,
1292 &port_info->phy_info[i].attached,
1293 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1294 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1295 port_info->phy_info[i].attached.handle);
1296 }
1297
1298 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001299 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001300 (*index)++;
1301 }
1302
1303 return 0;
1304
1305 out_free_port_info:
1306 kfree(port_info);
1307 out:
1308 return error;
1309}
1310
1311static int
1312mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1313{
1314 struct mptsas_portinfo *port_info, *p;
1315 int error = -ENOMEM, i, j;
1316
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001317 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001318 if (!port_info)
1319 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001320
1321 error = mptsas_sas_expander_pg0(ioc, port_info,
1322 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1323 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1324 if (error)
1325 goto out_free_port_info;
1326
1327 *handle = port_info->handle;
1328
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001329 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001330 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001331 mutex_unlock(&ioc->sas_topology_mutex);
1332
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001333 for (i = 0; i < port_info->num_phys; i++) {
1334 struct device *parent;
1335
1336 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1337 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1338 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1339
1340 if (port_info->phy_info[i].identify.handle) {
1341 mptsas_sas_device_pg0(ioc,
1342 &port_info->phy_info[i].identify,
1343 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1344 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1345 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001346 port_info->phy_info[i].identify.phy_id =
1347 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001348 }
1349
1350 if (port_info->phy_info[i].attached.handle) {
1351 mptsas_sas_device_pg0(ioc,
1352 &port_info->phy_info[i].attached,
1353 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1354 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1355 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001356 port_info->phy_info[i].attached.phy_id =
1357 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001358 }
1359
1360 /*
1361 * If we find a parent port handle this expander is
1362 * attached to another expander, else it hangs of the
1363 * HBA phys.
1364 */
1365 parent = &ioc->sh->shost_gendev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001366 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001367 list_for_each_entry(p, &ioc->sas_topology, list) {
1368 for (j = 0; j < p->num_phys; j++) {
1369 if (port_info->phy_info[i].identify.handle ==
1370 p->phy_info[j].attached.handle)
1371 parent = &p->phy_info[j].rphy->dev;
1372 }
1373 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001374 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001375
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001376 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1377 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001378 (*index)++;
1379 }
1380
1381 return 0;
1382
1383 out_free_port_info:
Moore, Ericdb9c9172006-03-14 09:14:18 -07001384 kfree(port_info->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001385 kfree(port_info);
1386 out:
1387 return error;
1388}
1389
1390static void
1391mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1392{
1393 u32 handle = 0xFFFF;
1394 int index = 0;
Moore, Ericf44e5462006-03-14 09:14:21 -07001395 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001396
1397 mptsas_probe_hba_phys(ioc, &index);
1398 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1399 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001400 /*
1401 Reporting RAID volumes.
1402 */
1403 if (!ioc->raid_data.pIocPg2)
1404 goto out;
1405 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1406 goto out;
1407 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1408 scsi_add_device(ioc->sh, ioc->num_ports,
1409 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1410 }
1411 out:
1412 return;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001413}
1414
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001415static struct mptsas_phyinfo *
1416mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1417{
1418 struct mptsas_portinfo *port_info;
1419 struct mptsas_devinfo device_info;
1420 struct mptsas_phyinfo *phy_info = NULL;
1421 int i, error;
1422
1423 /*
1424 * Retrieve the parent sas_address
1425 */
1426 error = mptsas_sas_device_pg0(ioc, &device_info,
1427 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1428 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1429 parent_handle);
1430 if (error) {
1431 printk("mptsas: failed to retrieve device page\n");
1432 return NULL;
1433 }
1434
1435 /*
1436 * The phy_info structures are never deallocated during lifetime of
1437 * a host, so the code below is safe without additional refcounting.
1438 */
1439 mutex_lock(&ioc->sas_topology_mutex);
1440 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1441 for (i = 0; i < port_info->num_phys; i++) {
1442 if (port_info->phy_info[i].identify.sas_address ==
1443 device_info.sas_address &&
1444 port_info->phy_info[i].phy_id == phy_id) {
1445 phy_info = &port_info->phy_info[i];
1446 break;
1447 }
1448 }
1449 }
1450 mutex_unlock(&ioc->sas_topology_mutex);
1451
1452 return phy_info;
1453}
1454
1455static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07001456mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001457{
1458 struct mptsas_portinfo *port_info;
1459 struct mptsas_phyinfo *phy_info = NULL;
1460 int i;
1461
1462 /*
1463 * The phy_info structures are never deallocated during lifetime of
1464 * a host, so the code below is safe without additional refcounting.
1465 */
1466 mutex_lock(&ioc->sas_topology_mutex);
1467 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Moore, Ericc73787ee2006-01-26 16:20:06 -07001468 for (i = 0; i < port_info->num_phys; i++)
1469 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1470 if (port_info->phy_info[i].attached.id == id) {
1471 phy_info = &port_info->phy_info[i];
1472 break;
1473 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001474 }
1475 mutex_unlock(&ioc->sas_topology_mutex);
1476
1477 return phy_info;
1478}
1479
Moore, Eric4b766472006-03-14 09:14:12 -07001480/*
1481 * Work queue thread to clear the persitency table
1482 */
1483static void
1484mptscsih_sas_persist_clear_table(void * arg)
1485{
1486 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
1487
1488 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
1489}
1490
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001491static void
Moore, Ericf44e5462006-03-14 09:14:21 -07001492mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
1493{
1494 sdev->no_uld_attach = data ? 1 : 0;
1495 scsi_device_reprobe(sdev);
1496}
1497
1498static void
1499mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
1500{
1501 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
1502 mptsas_reprobe_lun);
1503}
1504
1505static void
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001506mptsas_hotplug_work(void *arg)
1507{
1508 struct mptsas_hotplug_event *ev = arg;
1509 MPT_ADAPTER *ioc = ev->ioc;
1510 struct mptsas_phyinfo *phy_info;
1511 struct sas_rphy *rphy;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001512 struct scsi_device *sdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001513 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001514 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07001515 VirtTarget *vtarget;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001516
1517 switch (ev->event_type) {
1518 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001519
Moore, Ericc73787ee2006-01-26 16:20:06 -07001520 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Ericf44e5462006-03-14 09:14:21 -07001521 /*
1522 * Sanity checks, for non-existing phys and remote rphys.
1523 */
1524 if (!phy_info)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001525 break;
Moore, Ericf44e5462006-03-14 09:14:21 -07001526 if (!phy_info->rphy)
1527 break;
1528 if (phy_info->starget) {
1529 vtarget = phy_info->starget->hostdata;
1530
1531 if (!vtarget)
1532 break;
1533 /*
1534 * Handling RAID components
1535 */
1536 if (ev->phys_disk_num_valid) {
1537 vtarget->target_id = ev->phys_disk_num;
1538 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
1539 mptsas_reprobe_target(vtarget->starget, 1);
1540 break;
1541 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001542 }
1543
Moore, Ericc73787ee2006-01-26 16:20:06 -07001544 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1545 ds = "ssp";
1546 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1547 ds = "stp";
1548 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1549 ds = "sata";
1550
1551 printk(MYIOC_s_INFO_FMT
1552 "removing %s device, channel %d, id %d, phy %d\n",
1553 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1554
Moore, Ericf44e5462006-03-14 09:14:21 -07001555 sas_rphy_delete(phy_info->rphy);
1556 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
1557 phy_info->rphy = NULL;
1558 phy_info->starget = NULL;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001559 break;
1560 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001561
1562 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01001563 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07001564 */
Christoph Hellwige3094442006-02-16 13:25:36 +01001565 if (mptsas_sas_device_pg0(ioc, &sas_device,
1566 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1567 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
1568 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001569
1570 phy_info = mptsas_find_phyinfo_by_parent(ioc,
Christoph Hellwige3094442006-02-16 13:25:36 +01001571 sas_device.handle_parent, sas_device.phy_id);
Moore, Ericf44e5462006-03-14 09:14:21 -07001572 if (!phy_info)
1573 break;
1574 if (phy_info->starget) {
1575 vtarget = phy_info->starget->hostdata;
1576
1577 if (!vtarget)
1578 break;
1579 /*
1580 * Handling RAID components
1581 */
1582 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
1583 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
1584 vtarget->target_id = ev->id;
1585 mptsas_reprobe_target(phy_info->starget, 0);
1586 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001587 break;
1588 }
1589
Moore, Ericf44e5462006-03-14 09:14:21 -07001590 if (phy_info->rphy)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001591 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001592
Christoph Hellwige3094442006-02-16 13:25:36 +01001593 memcpy(&phy_info->attached, &sas_device,
1594 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001595
Moore, Ericc73787ee2006-01-26 16:20:06 -07001596 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1597 ds = "ssp";
1598 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1599 ds = "stp";
1600 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1601 ds = "sata";
1602
1603 printk(MYIOC_s_INFO_FMT
1604 "attaching %s device, channel %d, id %d, phy %d\n",
1605 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1606
1607
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001608 rphy = sas_rphy_alloc(phy_info->phy);
1609 if (!rphy)
1610 break; /* non-fatal: an rphy can be added later */
1611
1612 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1613 if (sas_rphy_add(rphy)) {
1614 sas_rphy_free(rphy);
1615 break;
1616 }
1617
1618 phy_info->rphy = rphy;
1619 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001620 case MPTSAS_ADD_RAID:
1621 sdev = scsi_device_lookup(
1622 ioc->sh,
1623 ioc->num_ports,
1624 ev->id,
1625 0);
1626 if (sdev) {
1627 scsi_device_put(sdev);
1628 break;
1629 }
1630 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07001631 "attaching raid volume, channel %d, id %d\n",
Moore, Ericc73787ee2006-01-26 16:20:06 -07001632 ioc->name, ioc->num_ports, ev->id);
1633 scsi_add_device(ioc->sh,
1634 ioc->num_ports,
1635 ev->id,
1636 0);
1637 mpt_findImVolumes(ioc);
1638 break;
1639 case MPTSAS_DEL_RAID:
1640 sdev = scsi_device_lookup(
1641 ioc->sh,
1642 ioc->num_ports,
1643 ev->id,
1644 0);
1645 if (!sdev)
1646 break;
1647 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07001648 "removing raid volume, channel %d, id %d\n",
Moore, Ericc73787ee2006-01-26 16:20:06 -07001649 ioc->name, ioc->num_ports, ev->id);
1650 scsi_remove_device(sdev);
1651 scsi_device_put(sdev);
1652 mpt_findImVolumes(ioc);
1653 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001654 }
1655
1656 kfree(ev);
1657}
1658
1659static void
1660mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1661 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1662{
1663 struct mptsas_hotplug_event *ev;
1664 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1665 __le64 sas_address;
1666
1667 if ((device_info &
1668 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1669 MPI_SAS_DEVICE_INFO_STP_TARGET |
1670 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1671 return;
1672
Moore, Eric4b766472006-03-14 09:14:12 -07001673 switch (sas_event_data->ReasonCode) {
1674 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
1675 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
1676 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1677 if (!ev) {
1678 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1679 break;
1680 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001681
Moore, Eric4b766472006-03-14 09:14:12 -07001682 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1683 ev->ioc = ioc;
1684 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1685 ev->parent_handle =
1686 le16_to_cpu(sas_event_data->ParentDevHandle);
1687 ev->channel = sas_event_data->Bus;
1688 ev->id = sas_event_data->TargetID;
1689 ev->phy_id = sas_event_data->PhyNum;
1690 memcpy(&sas_address, &sas_event_data->SASAddress,
1691 sizeof(__le64));
1692 ev->sas_address = le64_to_cpu(sas_address);
1693 ev->device_info = device_info;
1694
1695 if (sas_event_data->ReasonCode &
1696 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1697 ev->event_type = MPTSAS_ADD_DEVICE;
1698 else
1699 ev->event_type = MPTSAS_DEL_DEVICE;
1700 schedule_work(&ev->work);
1701 break;
1702 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
1703 /*
1704 * Persistent table is full.
1705 */
1706 INIT_WORK(&ioc->mptscsih_persistTask,
1707 mptscsih_sas_persist_clear_table,
1708 (void *)ioc);
1709 schedule_work(&ioc->mptscsih_persistTask);
1710 break;
1711 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
1712 /* TODO */
1713 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
1714 /* TODO */
1715 default:
1716 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001717 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001718}
1719
Moore, Ericc73787ee2006-01-26 16:20:06 -07001720static void
1721mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1722 EVENT_DATA_RAID *raid_event_data)
1723{
1724 struct mptsas_hotplug_event *ev;
1725 RAID_VOL0_STATUS * volumeStatus;
1726
1727 if (ioc->bus_type != SAS)
1728 return;
1729
1730 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1731 if (!ev) {
1732 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1733 return;
1734 }
1735
1736 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1737 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1738 ev->ioc = ioc;
1739 ev->id = raid_event_data->VolumeID;
1740
1741 switch (raid_event_data->ReasonCode) {
1742 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1743 ev->event_type = MPTSAS_ADD_DEVICE;
1744 break;
1745 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07001746 ioc->raid_data.isRaid = 1;
1747 ev->phys_disk_num_valid = 1;
1748 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001749 ev->event_type = MPTSAS_DEL_DEVICE;
1750 break;
1751 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1752 ev->event_type = MPTSAS_DEL_RAID;
1753 break;
1754 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1755 ev->event_type = MPTSAS_ADD_RAID;
1756 break;
1757 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1758 volumeStatus = (RAID_VOL0_STATUS *) &
1759 raid_event_data->SettingsStatus;
1760 ev->event_type = (volumeStatus->State ==
1761 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1762 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1763 break;
1764 default:
1765 break;
1766 }
1767 schedule_work(&ev->work);
1768}
1769
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001770static int
1771mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1772{
Moore, Ericc73787ee2006-01-26 16:20:06 -07001773 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001774 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1775
1776 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07001777 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001778
1779 switch (event) {
1780 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1781 mptscsih_send_sas_event(ioc,
1782 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001783 break;
1784 case MPI_EVENT_INTEGRATED_RAID:
1785 mptscsih_send_raid_event(ioc,
1786 (EVENT_DATA_RAID *)reply->Data);
1787 break;
Moore, Eric79de2782006-01-25 18:05:15 -07001788 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1789 INIT_WORK(&ioc->mptscsih_persistTask,
1790 mptscsih_sas_persist_clear_table,
1791 (void *)ioc);
1792 schedule_work(&ioc->mptscsih_persistTask);
1793 break;
Moore, Eric4b766472006-03-14 09:14:12 -07001794 case MPI_EVENT_SAS_DISCOVERY:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001795 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001796 rc = mptscsih_event_process(ioc, reply);
1797 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001798 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07001799 out:
1800
1801 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001802}
1803
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001804static int
1805mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1806{
1807 struct Scsi_Host *sh;
1808 MPT_SCSI_HOST *hd;
1809 MPT_ADAPTER *ioc;
1810 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001811 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001812 int numSGE = 0;
1813 int scale;
1814 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001815 int error=0;
1816 int r;
1817
1818 r = mpt_attach(pdev,id);
1819 if (r)
1820 return r;
1821
1822 ioc = pci_get_drvdata(pdev);
1823 ioc->DoneCtx = mptsasDoneCtx;
1824 ioc->TaskCtx = mptsasTaskCtx;
1825 ioc->InternalCtx = mptsasInternalCtx;
1826
1827 /* Added sanity check on readiness of the MPT adapter.
1828 */
1829 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1830 printk(MYIOC_s_WARN_FMT
1831 "Skipping because it's not operational!\n",
1832 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001833 error = -ENODEV;
1834 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001835 }
1836
1837 if (!ioc->active) {
1838 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1839 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001840 error = -ENODEV;
1841 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001842 }
1843
1844 /* Sanity check - ensure at least 1 port is INITIATOR capable
1845 */
1846 ioc_cap = 0;
1847 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1848 if (ioc->pfacts[ii].ProtocolFlags &
1849 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1850 ioc_cap++;
1851 }
1852
1853 if (!ioc_cap) {
1854 printk(MYIOC_s_WARN_FMT
1855 "Skipping ioc=%p because SCSI Initiator mode "
1856 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001857 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001858 }
1859
1860 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1861 if (!sh) {
1862 printk(MYIOC_s_WARN_FMT
1863 "Unable to register controller with SCSI subsystem\n",
1864 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001865 error = -1;
1866 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001867 }
1868
1869 spin_lock_irqsave(&ioc->FreeQlock, flags);
1870
1871 /* Attach the SCSI Host to the IOC structure
1872 */
1873 ioc->sh = sh;
1874
1875 sh->io_port = 0;
1876 sh->n_io_port = 0;
1877 sh->irq = 0;
1878
1879 /* set 16 byte cdb's */
1880 sh->max_cmd_len = 16;
1881
1882 sh->max_id = ioc->pfacts->MaxDevices + 1;
1883
1884 sh->transportt = mptsas_transport_template;
1885
1886 sh->max_lun = MPT_LAST_LUN + 1;
1887 sh->max_channel = 0;
1888 sh->this_id = ioc->pfacts[0].PortSCSIID;
1889
1890 /* Required entry.
1891 */
1892 sh->unique_id = ioc->id;
1893
1894 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001895 mutex_init(&ioc->sas_topology_mutex);
1896
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001897 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001898 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001899
1900 /* Verify that we won't exceed the maximum
1901 * number of chain buffers
1902 * We can optimize: ZZ = req_sz/sizeof(SGE)
1903 * For 32bit SGE's:
1904 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1905 * + (req_sz - 64)/sizeof(SGE)
1906 * A slightly different algorithm is required for
1907 * 64bit SGEs.
1908 */
1909 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1910 if (sizeof(dma_addr_t) == sizeof(u64)) {
1911 numSGE = (scale - 1) *
1912 (ioc->facts.MaxChainDepth-1) + scale +
1913 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1914 sizeof(u32));
1915 } else {
1916 numSGE = 1 + (scale - 1) *
1917 (ioc->facts.MaxChainDepth-1) + scale +
1918 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1919 sizeof(u32));
1920 }
1921
1922 if (numSGE < sh->sg_tablesize) {
1923 /* Reset this value */
1924 dprintk((MYIOC_s_INFO_FMT
1925 "Resetting sg_tablesize to %d from %d\n",
1926 ioc->name, numSGE, sh->sg_tablesize));
1927 sh->sg_tablesize = numSGE;
1928 }
1929
1930 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1931
1932 hd = (MPT_SCSI_HOST *) sh->hostdata;
1933 hd->ioc = ioc;
1934
1935 /* SCSI needs scsi_cmnd lookup table!
1936 * (with size equal to req_depth*PtrSz!)
1937 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001938 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1939 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001940 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001941 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001942 }
1943
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001944 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1945 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001946
1947 /* Allocate memory for the device structures.
1948 * A non-Null pointer at an offset
1949 * indicates a device exists.
1950 * max_id = 1 + maximum id (hosts.h)
1951 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001952 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1953 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001954 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001955 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001956 }
1957
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001958 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001959
1960 /* Clear the TM flags
1961 */
1962 hd->tmPending = 0;
1963 hd->tmState = TM_STATE_NONE;
1964 hd->resetPending = 0;
1965 hd->abortSCpnt = NULL;
1966
1967 /* Clear the pointer used to store
1968 * single-threaded commands, i.e., those
1969 * issued during a bus scan, dv and
1970 * configuration pages.
1971 */
1972 hd->cmdPtr = NULL;
1973
1974 /* Initialize this SCSI Hosts' timers
1975 * To use, set the timer expires field
1976 * and add_timer
1977 */
1978 init_timer(&hd->timer);
1979 hd->timer.data = (unsigned long) hd;
1980 hd->timer.function = mptscsih_timer_expired;
1981
1982 hd->mpt_pq_filter = mpt_pq_filter;
1983 ioc->sas_data.ptClear = mpt_pt_clear;
1984
1985 if (ioc->sas_data.ptClear==1) {
1986 mptbase_sas_persist_operation(
1987 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1988 }
1989
1990 ddvprintk((MYIOC_s_INFO_FMT
1991 "mpt_pq_filter %x mpt_pq_filter %x\n",
1992 ioc->name,
1993 mpt_pq_filter,
1994 mpt_pq_filter));
1995
1996 init_waitqueue_head(&hd->scandv_waitq);
1997 hd->scandv_wait_done = 0;
1998 hd->last_queue_full = 0;
1999
2000 error = scsi_add_host(sh, &ioc->pcidev->dev);
2001 if (error) {
2002 dprintk((KERN_ERR MYNAM
2003 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002004 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002005 }
2006
2007 mptsas_scan_sas_topology(ioc);
2008
2009 return 0;
2010
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002011out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002012
2013 mptscsih_remove(pdev);
2014 return error;
2015}
2016
2017static void __devexit mptsas_remove(struct pci_dev *pdev)
2018{
2019 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2020 struct mptsas_portinfo *p, *n;
2021
2022 sas_remove_host(ioc->sh);
2023
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002024 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002025 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2026 list_del(&p->list);
Moore, Ericdb9c9172006-03-14 09:14:18 -07002027 if (p->phy_info)
2028 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002029 kfree(p);
2030 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002031 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002032
2033 mptscsih_remove(pdev);
2034}
2035
2036static struct pci_device_id mptsas_pci_table[] = {
2037 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
2038 PCI_ANY_ID, PCI_ANY_ID },
2039 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
2040 PCI_ANY_ID, PCI_ANY_ID },
2041 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
2042 PCI_ANY_ID, PCI_ANY_ID },
2043 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
2044 PCI_ANY_ID, PCI_ANY_ID },
2045 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
2046 PCI_ANY_ID, PCI_ANY_ID },
2047 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
2048 PCI_ANY_ID, PCI_ANY_ID },
2049 {0} /* Terminating entry */
2050};
2051MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2052
2053
2054static struct pci_driver mptsas_driver = {
2055 .name = "mptsas",
2056 .id_table = mptsas_pci_table,
2057 .probe = mptsas_probe,
2058 .remove = __devexit_p(mptsas_remove),
2059 .shutdown = mptscsih_shutdown,
2060#ifdef CONFIG_PM
2061 .suspend = mptscsih_suspend,
2062 .resume = mptscsih_resume,
2063#endif
2064};
2065
2066static int __init
2067mptsas_init(void)
2068{
2069 show_mptmod_ver(my_NAME, my_VERSION);
2070
2071 mptsas_transport_template =
2072 sas_attach_transport(&mptsas_transport_functions);
2073 if (!mptsas_transport_template)
2074 return -ENODEV;
2075
2076 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2077 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2078 mptsasInternalCtx =
2079 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002080 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002081
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002082 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002083 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002084 ": Registered for IOC event notifications\n"));
2085 }
2086
2087 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2088 dprintk((KERN_INFO MYNAM
2089 ": Registered for IOC reset notifications\n"));
2090 }
2091
2092 return pci_register_driver(&mptsas_driver);
2093}
2094
2095static void __exit
2096mptsas_exit(void)
2097{
2098 pci_unregister_driver(&mptsas_driver);
2099 sas_release_transport(mptsas_transport_template);
2100
2101 mpt_reset_deregister(mptsasDoneCtx);
2102 mpt_event_deregister(mptsasDoneCtx);
2103
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002104 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002105 mpt_deregister(mptsasInternalCtx);
2106 mpt_deregister(mptsasTaskCtx);
2107 mpt_deregister(mptsasDoneCtx);
2108}
2109
2110module_init(mptsas_init);
2111module_exit(mptsas_exit);