blob: 8e77837c07ec4e983618149596740883766091b4 [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;
107};
108
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200109/*
110 * SAS topology structures
111 *
112 * The MPT Fusion firmware interface spreads information about the
113 * SAS topology over many manufacture pages, thus we need some data
114 * structure to collect it and process it for the SAS transport class.
115 */
116
117struct mptsas_devinfo {
118 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700119 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200120 u8 phy_id; /* phy number of parent device */
121 u8 port_id; /* sas physical port this device
122 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100123 u8 id; /* logical target id of this device */
124 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200125 u64 sas_address; /* WWN of this device,
126 SATA is assigned by HBA,expander */
127 u32 device_info; /* bitfield detailed info about this device */
128};
129
130struct mptsas_phyinfo {
131 u8 phy_id; /* phy index */
132 u8 port_id; /* port number this phy is part of */
133 u8 negotiated_link_rate; /* nego'd link rate for this phy */
134 u8 hw_link_rate; /* hardware max/min phys link rate */
135 u8 programmed_link_rate; /* programmed max/min phy link rate */
136 struct mptsas_devinfo identify; /* point to phy device info */
137 struct mptsas_devinfo attached; /* point to attached device info */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100138 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200139 struct sas_rphy *rphy;
140};
141
142struct mptsas_portinfo {
143 struct list_head list;
144 u16 handle; /* unique id to address this */
145 u8 num_phys; /* number of phys */
146 struct mptsas_phyinfo *phy_info;
147};
148
Christoph Hellwigb5141122005-10-28 22:07:41 +0200149
150#ifdef SASDEBUG
151static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
152{
153 printk("---- IO UNIT PAGE 0 ------------\n");
154 printk("Handle=0x%X\n",
155 le16_to_cpu(phy_data->AttachedDeviceHandle));
156 printk("Controller Handle=0x%X\n",
157 le16_to_cpu(phy_data->ControllerDevHandle));
158 printk("Port=0x%X\n", phy_data->Port);
159 printk("Port Flags=0x%X\n", phy_data->PortFlags);
160 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
161 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
162 printk("Controller PHY Device Info=0x%X\n",
163 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
164 printk("DiscoveryStatus=0x%X\n",
165 le32_to_cpu(phy_data->DiscoveryStatus));
166 printk("\n");
167}
168
169static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
170{
171 __le64 sas_address;
172
173 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
174
175 printk("---- SAS PHY PAGE 0 ------------\n");
176 printk("Attached Device Handle=0x%X\n",
177 le16_to_cpu(pg0->AttachedDevHandle));
178 printk("SAS Address=0x%llX\n",
179 (unsigned long long)le64_to_cpu(sas_address));
180 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
181 printk("Attached Device Info=0x%X\n",
182 le32_to_cpu(pg0->AttachedDeviceInfo));
183 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
184 printk("Change Count=0x%X\n", pg0->ChangeCount);
185 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
186 printk("\n");
187}
188
189static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
190{
191 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200192 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
193 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200194 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200195 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
196 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
197 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200198}
199
200static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
201{
202 __le64 sas_address;
203
204 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
205
206 printk("---- SAS DEVICE PAGE 0 ---------\n");
207 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
208 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
209 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
210 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
211 printk("Target ID=0x%X\n", pg0->TargetID);
212 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200213 /* The PhyNum field specifies the PHY number of the parent
214 * device this device is linked to
215 */
216 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
217 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200218 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
219 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
220 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
221 printk("\n");
222}
223
224static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
225{
226 printk("---- SAS EXPANDER PAGE 1 ------------\n");
227
228 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200229 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200230 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
231 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
232 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
233 printk("Owner Device Handle=0x%X\n",
234 le16_to_cpu(pg1->OwnerDevHandle));
235 printk("Attached Device Handle=0x%X\n",
236 le16_to_cpu(pg1->AttachedDevHandle));
237}
238#else
239#define mptsas_print_phy_data(phy_data) do { } while (0)
240#define mptsas_print_phy_pg0(pg0) do { } while (0)
241#define mptsas_print_phy_pg1(pg1) do { } while (0)
242#define mptsas_print_device_pg0(pg0) do { } while (0)
243#define mptsas_print_expander_pg1(pg1) do { } while (0)
244#endif
245
246
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200247/*
248 * This is pretty ugly. We will be able to seriously clean it up
249 * once the DV code in mptscsih goes away and we can properly
250 * implement ->target_alloc.
251 */
252static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700253mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200254{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700255 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200256 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
257 struct sas_rphy *rphy;
258 struct mptsas_portinfo *p;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700259 VirtTarget *vtarget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200260 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700261 struct scsi_target *starget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200262 int i;
263
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100264 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200265 if (!vdev) {
266 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
267 hd->ioc->name, sizeof(VirtDevice));
268 return -ENOMEM;
269 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200270 vdev->ioc_id = hd->ioc->id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700271 sdev->hostdata = vdev;
272 starget = scsi_target(sdev);
273 vtarget = starget->hostdata;
274 vdev->vtarget = vtarget;
275 if (vtarget->num_luns == 0) {
276 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
277 hd->Targets[sdev->id] = vtarget;
278 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200279
Moore, Eric816aa902006-01-13 16:25:20 -0700280 /*
281 RAID volumes placed beyond the last expected port.
282 */
283 if (sdev->channel == hd->ioc->num_ports) {
284 vdev->target_id = sdev->id;
285 vdev->bus_id = 0;
286 vdev->lun = 0;
287 goto out;
288 }
289
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700290 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100291 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200292 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
293 for (i = 0; i < p->num_phys; i++) {
294 if (p->phy_info[i].attached.sas_address ==
295 rphy->identify.sas_address) {
296 vdev->target_id =
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100297 p->phy_info[i].attached.id;
298 vdev->bus_id = p->phy_info[i].attached.channel;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700299 vdev->lun = sdev->lun;
Moore, Eric816aa902006-01-13 16:25:20 -0700300 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200301 goto out;
302 }
303 }
304 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100305 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200306
307 printk("No matching SAS device found!!\n");
308 kfree(vdev);
309 return -ENODEV;
310
311 out:
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700312 vtarget->ioc_id = vdev->ioc_id;
313 vtarget->target_id = vdev->target_id;
314 vtarget->bus_id = vdev->bus_id;
315 vtarget->num_luns++;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200316 return 0;
317}
318
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100319static void
320mptsas_slave_destroy(struct scsi_device *sdev)
321{
322 struct Scsi_Host *host = sdev->host;
323 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
324 struct sas_rphy *rphy;
325 struct mptsas_portinfo *p;
326 int i;
327
328 /*
329 * Handle hotplug removal case.
330 * We need to clear out attached data structure.
331 */
332 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
333
334 mutex_lock(&hd->ioc->sas_topology_mutex);
335 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
336 for (i = 0; i < p->num_phys; i++) {
337 if (p->phy_info[i].attached.sas_address ==
338 rphy->identify.sas_address) {
339 memset(&p->phy_info[i].attached, 0,
340 sizeof(struct mptsas_devinfo));
341 p->phy_info[i].rphy = NULL;
342 goto out;
343 }
344 }
345 }
346
347 out:
348 mutex_unlock(&hd->ioc->sas_topology_mutex);
349 /*
350 * TODO: Issue target reset to flush firmware outstanding commands.
351 */
352 mptscsih_slave_destroy(sdev);
353}
354
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200355static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700356 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200357 .proc_name = "mptsas",
358 .proc_info = mptscsih_proc_info,
359 .name = "MPT SPI Host",
360 .info = mptscsih_info,
361 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700362 .target_alloc = mptscsih_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200363 .slave_alloc = mptsas_slave_alloc,
364 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700365 .target_destroy = mptscsih_target_destroy,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100366 .slave_destroy = mptsas_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200367 .change_queue_depth = mptscsih_change_queue_depth,
368 .eh_abort_handler = mptscsih_abort,
369 .eh_device_reset_handler = mptscsih_dev_reset,
370 .eh_bus_reset_handler = mptscsih_bus_reset,
371 .eh_host_reset_handler = mptscsih_host_reset,
372 .bios_param = mptscsih_bios_param,
373 .can_queue = MPT_FC_CAN_QUEUE,
374 .this_id = -1,
375 .sg_tablesize = MPT_SCSI_SG_DEPTH,
376 .max_sectors = 8192,
377 .cmd_per_lun = 7,
378 .use_clustering = ENABLE_CLUSTERING,
379};
380
Christoph Hellwigb5141122005-10-28 22:07:41 +0200381static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
382{
383 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
384 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
385}
386
387static int mptsas_get_linkerrors(struct sas_phy *phy)
388{
389 MPT_ADAPTER *ioc = phy_to_ioc(phy);
390 ConfigExtendedPageHeader_t hdr;
391 CONFIGPARMS cfg;
392 SasPhyPage1_t *buffer;
393 dma_addr_t dma_handle;
394 int error;
395
396 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
397 hdr.ExtPageLength = 0;
398 hdr.PageNumber = 1 /* page number 1*/;
399 hdr.Reserved1 = 0;
400 hdr.Reserved2 = 0;
401 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
402 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
403
404 cfg.cfghdr.ehdr = &hdr;
405 cfg.physAddr = -1;
406 cfg.pageAddr = phy->identify.phy_identifier;
407 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
408 cfg.dir = 0; /* read */
409 cfg.timeout = 10;
410
411 error = mpt_config(ioc, &cfg);
412 if (error)
413 return error;
414 if (!hdr.ExtPageLength)
415 return -ENXIO;
416
417 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
418 &dma_handle);
419 if (!buffer)
420 return -ENOMEM;
421
422 cfg.physAddr = dma_handle;
423 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
424
425 error = mpt_config(ioc, &cfg);
426 if (error)
427 goto out_free_consistent;
428
429 mptsas_print_phy_pg1(buffer);
430
431 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
432 phy->running_disparity_error_count =
433 le32_to_cpu(buffer->RunningDisparityErrorCount);
434 phy->loss_of_dword_sync_count =
435 le32_to_cpu(buffer->LossDwordSynchCount);
436 phy->phy_reset_problem_count =
437 le32_to_cpu(buffer->PhyResetProblemCount);
438
439 out_free_consistent:
440 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
441 buffer, dma_handle);
442 return error;
443}
444
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200445static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
446 MPT_FRAME_HDR *reply)
447{
448 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
449 if (reply != NULL) {
450 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
451 memcpy(ioc->sas_mgmt.reply, reply,
452 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
453 }
454 complete(&ioc->sas_mgmt.done);
455 return 1;
456}
457
458static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
459{
460 MPT_ADAPTER *ioc = phy_to_ioc(phy);
461 SasIoUnitControlRequest_t *req;
462 SasIoUnitControlReply_t *reply;
463 MPT_FRAME_HDR *mf;
464 MPIHeader_t *hdr;
465 unsigned long timeleft;
466 int error = -ERESTARTSYS;
467
468 /* not implemented for expanders */
469 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
470 return -ENXIO;
471
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100472 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200473 goto out;
474
475 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
476 if (!mf) {
477 error = -ENOMEM;
478 goto out_unlock;
479 }
480
481 hdr = (MPIHeader_t *) mf;
482 req = (SasIoUnitControlRequest_t *)mf;
483 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
484 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
485 req->MsgContext = hdr->MsgContext;
486 req->Operation = hard_reset ?
487 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
488 req->PhyNum = phy->identify.phy_identifier;
489
490 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
491
492 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
493 10 * HZ);
494 if (!timeleft) {
495 /* On timeout reset the board */
496 mpt_free_msg_frame(ioc, mf);
497 mpt_HardResetHandler(ioc, CAN_SLEEP);
498 error = -ETIMEDOUT;
499 goto out_unlock;
500 }
501
502 /* a reply frame is expected */
503 if ((ioc->sas_mgmt.status &
504 MPT_IOCTL_STATUS_RF_VALID) == 0) {
505 error = -ENXIO;
506 goto out_unlock;
507 }
508
509 /* process the completed Reply Message Frame */
510 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
511 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
512 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
513 __FUNCTION__,
514 reply->IOCStatus,
515 reply->IOCLogInfo);
516 error = -ENXIO;
517 goto out_unlock;
518 }
519
520 error = 0;
521
522 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100523 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200524 out:
525 return error;
526}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200527
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200528static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200529 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200530 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200531};
532
533static struct scsi_transport_template *mptsas_transport_template;
534
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200535static int
536mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
537{
538 ConfigExtendedPageHeader_t hdr;
539 CONFIGPARMS cfg;
540 SasIOUnitPage0_t *buffer;
541 dma_addr_t dma_handle;
542 int error, i;
543
544 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
545 hdr.ExtPageLength = 0;
546 hdr.PageNumber = 0;
547 hdr.Reserved1 = 0;
548 hdr.Reserved2 = 0;
549 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
550 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
551
552 cfg.cfghdr.ehdr = &hdr;
553 cfg.physAddr = -1;
554 cfg.pageAddr = 0;
555 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
556 cfg.dir = 0; /* read */
557 cfg.timeout = 10;
558
559 error = mpt_config(ioc, &cfg);
560 if (error)
561 goto out;
562 if (!hdr.ExtPageLength) {
563 error = -ENXIO;
564 goto out;
565 }
566
567 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
568 &dma_handle);
569 if (!buffer) {
570 error = -ENOMEM;
571 goto out;
572 }
573
574 cfg.physAddr = dma_handle;
575 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
576
577 error = mpt_config(ioc, &cfg);
578 if (error)
579 goto out_free_consistent;
580
581 port_info->num_phys = buffer->NumPhys;
582 port_info->phy_info = kcalloc(port_info->num_phys,
583 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
584 if (!port_info->phy_info) {
585 error = -ENOMEM;
586 goto out_free_consistent;
587 }
588
589 for (i = 0; i < port_info->num_phys; i++) {
590 mptsas_print_phy_data(&buffer->PhyData[i]);
591 port_info->phy_info[i].phy_id = i;
592 port_info->phy_info[i].port_id =
593 buffer->PhyData[i].Port;
594 port_info->phy_info[i].negotiated_link_rate =
595 buffer->PhyData[i].NegotiatedLinkRate;
596 }
597
598 out_free_consistent:
599 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
600 buffer, dma_handle);
601 out:
602 return error;
603}
604
605static int
606mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
607 u32 form, u32 form_specific)
608{
609 ConfigExtendedPageHeader_t hdr;
610 CONFIGPARMS cfg;
611 SasPhyPage0_t *buffer;
612 dma_addr_t dma_handle;
613 int error;
614
615 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
616 hdr.ExtPageLength = 0;
617 hdr.PageNumber = 0;
618 hdr.Reserved1 = 0;
619 hdr.Reserved2 = 0;
620 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
621 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
622
623 cfg.cfghdr.ehdr = &hdr;
624 cfg.dir = 0; /* read */
625 cfg.timeout = 10;
626
627 /* Get Phy Pg 0 for each Phy. */
628 cfg.physAddr = -1;
629 cfg.pageAddr = form + form_specific;
630 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
631
632 error = mpt_config(ioc, &cfg);
633 if (error)
634 goto out;
635
636 if (!hdr.ExtPageLength) {
637 error = -ENXIO;
638 goto out;
639 }
640
641 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
642 &dma_handle);
643 if (!buffer) {
644 error = -ENOMEM;
645 goto out;
646 }
647
648 cfg.physAddr = dma_handle;
649 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
650
651 error = mpt_config(ioc, &cfg);
652 if (error)
653 goto out_free_consistent;
654
655 mptsas_print_phy_pg0(buffer);
656
657 phy_info->hw_link_rate = buffer->HwLinkRate;
658 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
659 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
660 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
661
662 out_free_consistent:
663 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
664 buffer, dma_handle);
665 out:
666 return error;
667}
668
669static int
670mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
671 u32 form, u32 form_specific)
672{
673 ConfigExtendedPageHeader_t hdr;
674 CONFIGPARMS cfg;
675 SasDevicePage0_t *buffer;
676 dma_addr_t dma_handle;
677 __le64 sas_address;
678 int error;
679
680 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
681 hdr.ExtPageLength = 0;
682 hdr.PageNumber = 0;
683 hdr.Reserved1 = 0;
684 hdr.Reserved2 = 0;
685 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
686 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
687
688 cfg.cfghdr.ehdr = &hdr;
689 cfg.pageAddr = form + form_specific;
690 cfg.physAddr = -1;
691 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
692 cfg.dir = 0; /* read */
693 cfg.timeout = 10;
694
695 error = mpt_config(ioc, &cfg);
696 if (error)
697 goto out;
698 if (!hdr.ExtPageLength) {
699 error = -ENXIO;
700 goto out;
701 }
702
703 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
704 &dma_handle);
705 if (!buffer) {
706 error = -ENOMEM;
707 goto out;
708 }
709
710 cfg.physAddr = dma_handle;
711 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
712
713 error = mpt_config(ioc, &cfg);
714 if (error)
715 goto out_free_consistent;
716
717 mptsas_print_device_pg0(buffer);
718
719 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -0700720 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200721 device_info->phy_id = buffer->PhyNum;
722 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100723 device_info->id = buffer->TargetID;
724 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200725 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
726 device_info->sas_address = le64_to_cpu(sas_address);
727 device_info->device_info =
728 le32_to_cpu(buffer->DeviceInfo);
729
730 out_free_consistent:
731 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
732 buffer, dma_handle);
733 out:
734 return error;
735}
736
737static int
738mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
739 u32 form, u32 form_specific)
740{
741 ConfigExtendedPageHeader_t hdr;
742 CONFIGPARMS cfg;
743 SasExpanderPage0_t *buffer;
744 dma_addr_t dma_handle;
745 int error;
746
747 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
748 hdr.ExtPageLength = 0;
749 hdr.PageNumber = 0;
750 hdr.Reserved1 = 0;
751 hdr.Reserved2 = 0;
752 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
753 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
754
755 cfg.cfghdr.ehdr = &hdr;
756 cfg.physAddr = -1;
757 cfg.pageAddr = form + form_specific;
758 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
759 cfg.dir = 0; /* read */
760 cfg.timeout = 10;
761
762 error = mpt_config(ioc, &cfg);
763 if (error)
764 goto out;
765
766 if (!hdr.ExtPageLength) {
767 error = -ENXIO;
768 goto out;
769 }
770
771 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
772 &dma_handle);
773 if (!buffer) {
774 error = -ENOMEM;
775 goto out;
776 }
777
778 cfg.physAddr = dma_handle;
779 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
780
781 error = mpt_config(ioc, &cfg);
782 if (error)
783 goto out_free_consistent;
784
785 /* save config data */
786 port_info->num_phys = buffer->NumPhys;
787 port_info->handle = le16_to_cpu(buffer->DevHandle);
788 port_info->phy_info = kcalloc(port_info->num_phys,
789 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
790 if (!port_info->phy_info) {
791 error = -ENOMEM;
792 goto out_free_consistent;
793 }
794
795 out_free_consistent:
796 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
797 buffer, dma_handle);
798 out:
799 return error;
800}
801
802static int
803mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
804 u32 form, u32 form_specific)
805{
806 ConfigExtendedPageHeader_t hdr;
807 CONFIGPARMS cfg;
808 SasExpanderPage1_t *buffer;
809 dma_addr_t dma_handle;
810 int error;
811
812 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
813 hdr.ExtPageLength = 0;
814 hdr.PageNumber = 1;
815 hdr.Reserved1 = 0;
816 hdr.Reserved2 = 0;
817 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
818 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
819
820 cfg.cfghdr.ehdr = &hdr;
821 cfg.physAddr = -1;
822 cfg.pageAddr = form + form_specific;
823 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
824 cfg.dir = 0; /* read */
825 cfg.timeout = 10;
826
827 error = mpt_config(ioc, &cfg);
828 if (error)
829 goto out;
830
831 if (!hdr.ExtPageLength) {
832 error = -ENXIO;
833 goto out;
834 }
835
836 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
837 &dma_handle);
838 if (!buffer) {
839 error = -ENOMEM;
840 goto out;
841 }
842
843 cfg.physAddr = dma_handle;
844 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
845
846 error = mpt_config(ioc, &cfg);
847 if (error)
848 goto out_free_consistent;
849
850
851 mptsas_print_expander_pg1(buffer);
852
853 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +0200854 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200855 phy_info->port_id = buffer->PhysicalPort;
856 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
857 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
858 phy_info->hw_link_rate = buffer->HwLinkRate;
859 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
860 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
861
862
863 out_free_consistent:
864 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
865 buffer, dma_handle);
866 out:
867 return error;
868}
869
Moore, Ericc73787ee2006-01-26 16:20:06 -0700870/*
871 * Returns true if there is a scsi end device
872 */
873static inline int
874mptsas_is_end_device(struct mptsas_devinfo * attached)
875{
876 if ((attached->handle) &&
877 (attached->device_info &
878 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
879 ((attached->device_info &
880 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
881 (attached->device_info &
882 MPI_SAS_DEVICE_INFO_STP_TARGET) |
883 (attached->device_info &
884 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
885 return 1;
886 else
887 return 0;
888}
889
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200890static void
891mptsas_parse_device_info(struct sas_identify *identify,
892 struct mptsas_devinfo *device_info)
893{
894 u16 protocols;
895
896 identify->sas_address = device_info->sas_address;
897 identify->phy_identifier = device_info->phy_id;
898
899 /*
900 * Fill in Phy Initiator Port Protocol.
901 * Bits 6:3, more than one bit can be set, fall through cases.
902 */
903 protocols = device_info->device_info & 0x78;
904 identify->initiator_port_protocols = 0;
905 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
906 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
907 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
908 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
909 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
910 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
911 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
912 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
913
914 /*
915 * Fill in Phy Target Port Protocol.
916 * Bits 10:7, more than one bit can be set, fall through cases.
917 */
918 protocols = device_info->device_info & 0x780;
919 identify->target_port_protocols = 0;
920 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
921 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
922 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
923 identify->target_port_protocols |= SAS_PROTOCOL_STP;
924 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
925 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
926 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
927 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
928
929 /*
930 * Fill in Attached device type.
931 */
932 switch (device_info->device_info &
933 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
934 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
935 identify->device_type = SAS_PHY_UNUSED;
936 break;
937 case MPI_SAS_DEVICE_INFO_END_DEVICE:
938 identify->device_type = SAS_END_DEVICE;
939 break;
940 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
941 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
942 break;
943 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
944 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
945 break;
946 }
947}
948
949static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +0200950 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200951{
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100952 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200953 int error;
954
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100955 phy = sas_phy_alloc(dev, index);
956 if (!phy)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200957 return -ENOMEM;
958
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100959 phy->port_identifier = phy_info->port_id;
960 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200961
962 /*
963 * Set Negotiated link rate.
964 */
965 switch (phy_info->negotiated_link_rate) {
966 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100967 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200968 break;
969 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100970 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200971 break;
972 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100973 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200974 break;
975 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100976 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200977 break;
978 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
979 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
980 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100981 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200982 break;
983 }
984
985 /*
986 * Set Max hardware link rate.
987 */
988 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
989 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100990 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200991 break;
992 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100993 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200994 break;
995 default:
996 break;
997 }
998
999 /*
1000 * Set Max programmed link rate.
1001 */
1002 switch (phy_info->programmed_link_rate &
1003 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1004 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001005 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001006 break;
1007 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001008 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001009 break;
1010 default:
1011 break;
1012 }
1013
1014 /*
1015 * Set Min hardware link rate.
1016 */
1017 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1018 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001019 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001020 break;
1021 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001022 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001023 break;
1024 default:
1025 break;
1026 }
1027
1028 /*
1029 * Set Min programmed link rate.
1030 */
1031 switch (phy_info->programmed_link_rate &
1032 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1033 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001034 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001035 break;
1036 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001037 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001038 break;
1039 default:
1040 break;
1041 }
1042
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001043 if (local)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001044 phy->local_attached = 1;
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001045
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001046 error = sas_phy_add(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001047 if (error) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001048 sas_phy_free(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001049 return error;
1050 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001051 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001052
1053 if (phy_info->attached.handle) {
1054 struct sas_rphy *rphy;
1055
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001056 rphy = sas_rphy_alloc(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001057 if (!rphy)
1058 return 0; /* non-fatal: an rphy can be added later */
1059
1060 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1061 error = sas_rphy_add(rphy);
1062 if (error) {
1063 sas_rphy_free(rphy);
1064 return error;
1065 }
1066
1067 phy_info->rphy = rphy;
1068 }
1069
1070 return 0;
1071}
1072
1073static int
1074mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
1075{
1076 struct mptsas_portinfo *port_info;
1077 u32 handle = 0xFFFF;
1078 int error = -ENOMEM, i;
1079
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001080 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001081 if (!port_info)
1082 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001083
1084 error = mptsas_sas_io_unit_pg0(ioc, port_info);
1085 if (error)
1086 goto out_free_port_info;
1087
Moore, Eric816aa902006-01-13 16:25:20 -07001088 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001089 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001090 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001091 mutex_unlock(&ioc->sas_topology_mutex);
1092
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001093 for (i = 0; i < port_info->num_phys; i++) {
1094 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1095 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1096 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1097
1098 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1099 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1100 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001101 port_info->phy_info[i].identify.phy_id =
1102 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001103 handle = port_info->phy_info[i].identify.handle;
1104
1105 if (port_info->phy_info[i].attached.handle) {
1106 mptsas_sas_device_pg0(ioc,
1107 &port_info->phy_info[i].attached,
1108 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1109 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1110 port_info->phy_info[i].attached.handle);
1111 }
1112
1113 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001114 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001115 (*index)++;
1116 }
1117
1118 return 0;
1119
1120 out_free_port_info:
1121 kfree(port_info);
1122 out:
1123 return error;
1124}
1125
1126static int
1127mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1128{
1129 struct mptsas_portinfo *port_info, *p;
1130 int error = -ENOMEM, i, j;
1131
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001132 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001133 if (!port_info)
1134 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001135
1136 error = mptsas_sas_expander_pg0(ioc, port_info,
1137 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1138 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1139 if (error)
1140 goto out_free_port_info;
1141
1142 *handle = port_info->handle;
1143
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001144 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001145 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001146 mutex_unlock(&ioc->sas_topology_mutex);
1147
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001148 for (i = 0; i < port_info->num_phys; i++) {
1149 struct device *parent;
1150
1151 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1152 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1153 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1154
1155 if (port_info->phy_info[i].identify.handle) {
1156 mptsas_sas_device_pg0(ioc,
1157 &port_info->phy_info[i].identify,
1158 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1159 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1160 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001161 port_info->phy_info[i].identify.phy_id =
1162 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001163 }
1164
1165 if (port_info->phy_info[i].attached.handle) {
1166 mptsas_sas_device_pg0(ioc,
1167 &port_info->phy_info[i].attached,
1168 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1169 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1170 port_info->phy_info[i].attached.handle);
1171 }
1172
1173 /*
1174 * If we find a parent port handle this expander is
1175 * attached to another expander, else it hangs of the
1176 * HBA phys.
1177 */
1178 parent = &ioc->sh->shost_gendev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001179 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001180 list_for_each_entry(p, &ioc->sas_topology, list) {
1181 for (j = 0; j < p->num_phys; j++) {
1182 if (port_info->phy_info[i].identify.handle ==
1183 p->phy_info[j].attached.handle)
1184 parent = &p->phy_info[j].rphy->dev;
1185 }
1186 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001187 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001188
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001189 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1190 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001191 (*index)++;
1192 }
1193
1194 return 0;
1195
1196 out_free_port_info:
1197 kfree(port_info);
1198 out:
1199 return error;
1200}
1201
1202static void
1203mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1204{
1205 u32 handle = 0xFFFF;
1206 int index = 0;
1207
1208 mptsas_probe_hba_phys(ioc, &index);
1209 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1210 ;
1211}
1212
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001213static struct mptsas_phyinfo *
1214mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1215{
1216 struct mptsas_portinfo *port_info;
1217 struct mptsas_devinfo device_info;
1218 struct mptsas_phyinfo *phy_info = NULL;
1219 int i, error;
1220
1221 /*
1222 * Retrieve the parent sas_address
1223 */
1224 error = mptsas_sas_device_pg0(ioc, &device_info,
1225 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1226 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1227 parent_handle);
1228 if (error) {
1229 printk("mptsas: failed to retrieve device page\n");
1230 return NULL;
1231 }
1232
1233 /*
1234 * The phy_info structures are never deallocated during lifetime of
1235 * a host, so the code below is safe without additional refcounting.
1236 */
1237 mutex_lock(&ioc->sas_topology_mutex);
1238 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1239 for (i = 0; i < port_info->num_phys; i++) {
1240 if (port_info->phy_info[i].identify.sas_address ==
1241 device_info.sas_address &&
1242 port_info->phy_info[i].phy_id == phy_id) {
1243 phy_info = &port_info->phy_info[i];
1244 break;
1245 }
1246 }
1247 }
1248 mutex_unlock(&ioc->sas_topology_mutex);
1249
1250 return phy_info;
1251}
1252
1253static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07001254mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001255{
1256 struct mptsas_portinfo *port_info;
1257 struct mptsas_phyinfo *phy_info = NULL;
1258 int i;
1259
1260 /*
1261 * The phy_info structures are never deallocated during lifetime of
1262 * a host, so the code below is safe without additional refcounting.
1263 */
1264 mutex_lock(&ioc->sas_topology_mutex);
1265 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Moore, Ericc73787ee2006-01-26 16:20:06 -07001266 for (i = 0; i < port_info->num_phys; i++)
1267 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1268 if (port_info->phy_info[i].attached.id == id) {
1269 phy_info = &port_info->phy_info[i];
1270 break;
1271 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001272 }
1273 mutex_unlock(&ioc->sas_topology_mutex);
1274
1275 return phy_info;
1276}
1277
1278static void
1279mptsas_hotplug_work(void *arg)
1280{
1281 struct mptsas_hotplug_event *ev = arg;
1282 MPT_ADAPTER *ioc = ev->ioc;
1283 struct mptsas_phyinfo *phy_info;
1284 struct sas_rphy *rphy;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001285 struct scsi_device *sdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001286 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001287 struct mptsas_devinfo sas_device;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001288
1289 switch (ev->event_type) {
1290 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001291
Moore, Ericc73787ee2006-01-26 16:20:06 -07001292 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001293 if (!phy_info) {
1294 printk("mptsas: remove event for non-existant PHY.\n");
1295 break;
1296 }
1297
Moore, Ericc73787ee2006-01-26 16:20:06 -07001298 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1299 ds = "ssp";
1300 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1301 ds = "stp";
1302 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1303 ds = "sata";
1304
1305 printk(MYIOC_s_INFO_FMT
1306 "removing %s device, channel %d, id %d, phy %d\n",
1307 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1308
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001309 if (phy_info->rphy) {
1310 sas_rphy_delete(phy_info->rphy);
1311 phy_info->rphy = NULL;
1312 }
1313 break;
1314 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001315
1316 /*
1317 * When there is no sas address,
1318 * RAID volumes are being deleted,
1319 * and hidden phy disk are being added.
1320 * We don't know the SAS data yet,
1321 * so lookup sas device page to get
1322 * pertaining info
1323 */
1324 if (!ev->sas_address) {
1325 if (mptsas_sas_device_pg0(ioc,
1326 &sas_device, ev->id,
1327 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1328 MPI_SAS_DEVICE_PGAD_FORM_SHIFT)))
1329 break;
1330 ev->handle = sas_device.handle;
1331 ev->parent_handle = sas_device.handle_parent;
1332 ev->channel = sas_device.channel;
1333 ev->phy_id = sas_device.phy_id;
1334 ev->sas_address = sas_device.sas_address;
1335 ev->device_info = sas_device.device_info;
1336 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001337
1338 phy_info = mptsas_find_phyinfo_by_parent(ioc,
1339 ev->parent_handle, ev->phy_id);
1340 if (!phy_info) {
1341 printk("mptsas: add event for non-existant PHY.\n");
1342 break;
1343 }
1344
1345 if (phy_info->rphy) {
1346 printk("mptsas: trying to add existing device.\n");
1347 break;
1348 }
1349
1350 /* fill attached info */
1351 phy_info->attached.handle = ev->handle;
1352 phy_info->attached.phy_id = ev->phy_id;
1353 phy_info->attached.port_id = phy_info->identify.port_id;
1354 phy_info->attached.id = ev->id;
1355 phy_info->attached.channel = ev->channel;
1356 phy_info->attached.sas_address = ev->sas_address;
1357 phy_info->attached.device_info = ev->device_info;
1358
Moore, Ericc73787ee2006-01-26 16:20:06 -07001359 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1360 ds = "ssp";
1361 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1362 ds = "stp";
1363 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1364 ds = "sata";
1365
1366 printk(MYIOC_s_INFO_FMT
1367 "attaching %s device, channel %d, id %d, phy %d\n",
1368 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1369
1370
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001371 rphy = sas_rphy_alloc(phy_info->phy);
1372 if (!rphy)
1373 break; /* non-fatal: an rphy can be added later */
1374
Moore, Ericc73787ee2006-01-26 16:20:06 -07001375 rphy->scsi_target_id = phy_info->attached.id;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001376 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1377 if (sas_rphy_add(rphy)) {
1378 sas_rphy_free(rphy);
1379 break;
1380 }
1381
1382 phy_info->rphy = rphy;
1383 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001384 case MPTSAS_ADD_RAID:
1385 sdev = scsi_device_lookup(
1386 ioc->sh,
1387 ioc->num_ports,
1388 ev->id,
1389 0);
1390 if (sdev) {
1391 scsi_device_put(sdev);
1392 break;
1393 }
1394 printk(MYIOC_s_INFO_FMT
1395 "attaching device, channel %d, id %d\n",
1396 ioc->name, ioc->num_ports, ev->id);
1397 scsi_add_device(ioc->sh,
1398 ioc->num_ports,
1399 ev->id,
1400 0);
1401 mpt_findImVolumes(ioc);
1402 break;
1403 case MPTSAS_DEL_RAID:
1404 sdev = scsi_device_lookup(
1405 ioc->sh,
1406 ioc->num_ports,
1407 ev->id,
1408 0);
1409 if (!sdev)
1410 break;
1411 printk(MYIOC_s_INFO_FMT
1412 "removing device, channel %d, id %d\n",
1413 ioc->name, ioc->num_ports, ev->id);
1414 scsi_remove_device(sdev);
1415 scsi_device_put(sdev);
1416 mpt_findImVolumes(ioc);
1417 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001418 }
1419
1420 kfree(ev);
1421}
1422
1423static void
1424mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1425 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1426{
1427 struct mptsas_hotplug_event *ev;
1428 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1429 __le64 sas_address;
1430
1431 if ((device_info &
1432 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1433 MPI_SAS_DEVICE_INFO_STP_TARGET |
1434 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1435 return;
1436
1437 if ((sas_event_data->ReasonCode &
1438 (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
1439 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
1440 return;
1441
1442 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1443 if (!ev) {
1444 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1445 return;
1446 }
1447
1448
1449 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1450 ev->ioc = ioc;
1451 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1452 ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
1453 ev->channel = sas_event_data->Bus;
1454 ev->id = sas_event_data->TargetID;
1455 ev->phy_id = sas_event_data->PhyNum;
1456 memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
1457 ev->sas_address = le64_to_cpu(sas_address);
1458 ev->device_info = device_info;
1459
1460 if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1461 ev->event_type = MPTSAS_ADD_DEVICE;
1462 else
1463 ev->event_type = MPTSAS_DEL_DEVICE;
1464
1465 schedule_work(&ev->work);
1466}
1467
Moore, Ericc73787ee2006-01-26 16:20:06 -07001468static void
1469mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1470 EVENT_DATA_RAID *raid_event_data)
1471{
1472 struct mptsas_hotplug_event *ev;
1473 RAID_VOL0_STATUS * volumeStatus;
1474
1475 if (ioc->bus_type != SAS)
1476 return;
1477
1478 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1479 if (!ev) {
1480 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1481 return;
1482 }
1483
1484 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1485 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1486 ev->ioc = ioc;
1487 ev->id = raid_event_data->VolumeID;
1488
1489 switch (raid_event_data->ReasonCode) {
1490 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1491 ev->event_type = MPTSAS_ADD_DEVICE;
1492 break;
1493 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
1494 ev->event_type = MPTSAS_DEL_DEVICE;
1495 break;
1496 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1497 ev->event_type = MPTSAS_DEL_RAID;
1498 break;
1499 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1500 ev->event_type = MPTSAS_ADD_RAID;
1501 break;
1502 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1503 volumeStatus = (RAID_VOL0_STATUS *) &
1504 raid_event_data->SettingsStatus;
1505 ev->event_type = (volumeStatus->State ==
1506 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1507 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1508 break;
1509 default:
1510 break;
1511 }
1512 schedule_work(&ev->work);
1513}
1514
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001515static int
1516mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1517{
Moore, Ericc73787ee2006-01-26 16:20:06 -07001518 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001519 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1520
1521 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07001522 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001523
1524 switch (event) {
1525 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1526 mptscsih_send_sas_event(ioc,
1527 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001528 break;
1529 case MPI_EVENT_INTEGRATED_RAID:
1530 mptscsih_send_raid_event(ioc,
1531 (EVENT_DATA_RAID *)reply->Data);
1532 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001533 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001534 rc = mptscsih_event_process(ioc, reply);
1535 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001536 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07001537 out:
1538
1539 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001540}
1541
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001542static int
1543mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1544{
1545 struct Scsi_Host *sh;
1546 MPT_SCSI_HOST *hd;
1547 MPT_ADAPTER *ioc;
1548 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001549 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001550 int numSGE = 0;
1551 int scale;
1552 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001553 int error=0;
1554 int r;
1555
1556 r = mpt_attach(pdev,id);
1557 if (r)
1558 return r;
1559
1560 ioc = pci_get_drvdata(pdev);
1561 ioc->DoneCtx = mptsasDoneCtx;
1562 ioc->TaskCtx = mptsasTaskCtx;
1563 ioc->InternalCtx = mptsasInternalCtx;
1564
1565 /* Added sanity check on readiness of the MPT adapter.
1566 */
1567 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1568 printk(MYIOC_s_WARN_FMT
1569 "Skipping because it's not operational!\n",
1570 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001571 error = -ENODEV;
1572 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001573 }
1574
1575 if (!ioc->active) {
1576 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1577 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001578 error = -ENODEV;
1579 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001580 }
1581
1582 /* Sanity check - ensure at least 1 port is INITIATOR capable
1583 */
1584 ioc_cap = 0;
1585 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1586 if (ioc->pfacts[ii].ProtocolFlags &
1587 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1588 ioc_cap++;
1589 }
1590
1591 if (!ioc_cap) {
1592 printk(MYIOC_s_WARN_FMT
1593 "Skipping ioc=%p because SCSI Initiator mode "
1594 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001595 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001596 }
1597
1598 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1599 if (!sh) {
1600 printk(MYIOC_s_WARN_FMT
1601 "Unable to register controller with SCSI subsystem\n",
1602 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001603 error = -1;
1604 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001605 }
1606
1607 spin_lock_irqsave(&ioc->FreeQlock, flags);
1608
1609 /* Attach the SCSI Host to the IOC structure
1610 */
1611 ioc->sh = sh;
1612
1613 sh->io_port = 0;
1614 sh->n_io_port = 0;
1615 sh->irq = 0;
1616
1617 /* set 16 byte cdb's */
1618 sh->max_cmd_len = 16;
1619
1620 sh->max_id = ioc->pfacts->MaxDevices + 1;
1621
1622 sh->transportt = mptsas_transport_template;
1623
1624 sh->max_lun = MPT_LAST_LUN + 1;
1625 sh->max_channel = 0;
1626 sh->this_id = ioc->pfacts[0].PortSCSIID;
1627
1628 /* Required entry.
1629 */
1630 sh->unique_id = ioc->id;
1631
1632 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001633 mutex_init(&ioc->sas_topology_mutex);
1634
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001635 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001636 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001637
1638 /* Verify that we won't exceed the maximum
1639 * number of chain buffers
1640 * We can optimize: ZZ = req_sz/sizeof(SGE)
1641 * For 32bit SGE's:
1642 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1643 * + (req_sz - 64)/sizeof(SGE)
1644 * A slightly different algorithm is required for
1645 * 64bit SGEs.
1646 */
1647 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1648 if (sizeof(dma_addr_t) == sizeof(u64)) {
1649 numSGE = (scale - 1) *
1650 (ioc->facts.MaxChainDepth-1) + scale +
1651 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1652 sizeof(u32));
1653 } else {
1654 numSGE = 1 + (scale - 1) *
1655 (ioc->facts.MaxChainDepth-1) + scale +
1656 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1657 sizeof(u32));
1658 }
1659
1660 if (numSGE < sh->sg_tablesize) {
1661 /* Reset this value */
1662 dprintk((MYIOC_s_INFO_FMT
1663 "Resetting sg_tablesize to %d from %d\n",
1664 ioc->name, numSGE, sh->sg_tablesize));
1665 sh->sg_tablesize = numSGE;
1666 }
1667
1668 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1669
1670 hd = (MPT_SCSI_HOST *) sh->hostdata;
1671 hd->ioc = ioc;
1672
1673 /* SCSI needs scsi_cmnd lookup table!
1674 * (with size equal to req_depth*PtrSz!)
1675 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001676 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1677 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001678 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001679 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001680 }
1681
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001682 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1683 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001684
1685 /* Allocate memory for the device structures.
1686 * A non-Null pointer at an offset
1687 * indicates a device exists.
1688 * max_id = 1 + maximum id (hosts.h)
1689 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001690 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1691 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001692 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001693 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001694 }
1695
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001696 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001697
1698 /* Clear the TM flags
1699 */
1700 hd->tmPending = 0;
1701 hd->tmState = TM_STATE_NONE;
1702 hd->resetPending = 0;
1703 hd->abortSCpnt = NULL;
1704
1705 /* Clear the pointer used to store
1706 * single-threaded commands, i.e., those
1707 * issued during a bus scan, dv and
1708 * configuration pages.
1709 */
1710 hd->cmdPtr = NULL;
1711
1712 /* Initialize this SCSI Hosts' timers
1713 * To use, set the timer expires field
1714 * and add_timer
1715 */
1716 init_timer(&hd->timer);
1717 hd->timer.data = (unsigned long) hd;
1718 hd->timer.function = mptscsih_timer_expired;
1719
1720 hd->mpt_pq_filter = mpt_pq_filter;
1721 ioc->sas_data.ptClear = mpt_pt_clear;
1722
1723 if (ioc->sas_data.ptClear==1) {
1724 mptbase_sas_persist_operation(
1725 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1726 }
1727
1728 ddvprintk((MYIOC_s_INFO_FMT
1729 "mpt_pq_filter %x mpt_pq_filter %x\n",
1730 ioc->name,
1731 mpt_pq_filter,
1732 mpt_pq_filter));
1733
1734 init_waitqueue_head(&hd->scandv_waitq);
1735 hd->scandv_wait_done = 0;
1736 hd->last_queue_full = 0;
1737
1738 error = scsi_add_host(sh, &ioc->pcidev->dev);
1739 if (error) {
1740 dprintk((KERN_ERR MYNAM
1741 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001742 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001743 }
1744
1745 mptsas_scan_sas_topology(ioc);
1746
Moore, Eric816aa902006-01-13 16:25:20 -07001747 /*
1748 Reporting RAID volumes.
1749 */
1750 if (!ioc->raid_data.pIocPg2)
1751 return 0;
1752 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1753 return 0;
1754 for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
1755 scsi_add_device(sh,
1756 ioc->num_ports,
1757 ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
1758 0);
1759 }
1760
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001761 return 0;
1762
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001763out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001764
1765 mptscsih_remove(pdev);
1766 return error;
1767}
1768
1769static void __devexit mptsas_remove(struct pci_dev *pdev)
1770{
1771 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1772 struct mptsas_portinfo *p, *n;
1773
1774 sas_remove_host(ioc->sh);
1775
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001776 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001777 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1778 list_del(&p->list);
1779 kfree(p);
1780 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001781 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001782
1783 mptscsih_remove(pdev);
1784}
1785
1786static struct pci_device_id mptsas_pci_table[] = {
1787 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1788 PCI_ANY_ID, PCI_ANY_ID },
1789 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1790 PCI_ANY_ID, PCI_ANY_ID },
1791 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1792 PCI_ANY_ID, PCI_ANY_ID },
1793 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1794 PCI_ANY_ID, PCI_ANY_ID },
1795 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1796 PCI_ANY_ID, PCI_ANY_ID },
1797 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1798 PCI_ANY_ID, PCI_ANY_ID },
1799 {0} /* Terminating entry */
1800};
1801MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1802
1803
1804static struct pci_driver mptsas_driver = {
1805 .name = "mptsas",
1806 .id_table = mptsas_pci_table,
1807 .probe = mptsas_probe,
1808 .remove = __devexit_p(mptsas_remove),
1809 .shutdown = mptscsih_shutdown,
1810#ifdef CONFIG_PM
1811 .suspend = mptscsih_suspend,
1812 .resume = mptscsih_resume,
1813#endif
1814};
1815
1816static int __init
1817mptsas_init(void)
1818{
1819 show_mptmod_ver(my_NAME, my_VERSION);
1820
1821 mptsas_transport_template =
1822 sas_attach_transport(&mptsas_transport_functions);
1823 if (!mptsas_transport_template)
1824 return -ENODEV;
1825
1826 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
1827 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
1828 mptsasInternalCtx =
1829 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001830 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001831
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001832 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001833 devtprintk((KERN_INFO MYNAM
1834 ": Registered for IOC event notifications\n"));
1835 }
1836
1837 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
1838 dprintk((KERN_INFO MYNAM
1839 ": Registered for IOC reset notifications\n"));
1840 }
1841
1842 return pci_register_driver(&mptsas_driver);
1843}
1844
1845static void __exit
1846mptsas_exit(void)
1847{
1848 pci_unregister_driver(&mptsas_driver);
1849 sas_release_transport(mptsas_transport_template);
1850
1851 mpt_reset_deregister(mptsasDoneCtx);
1852 mpt_event_deregister(mptsasDoneCtx);
1853
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001854 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001855 mpt_deregister(mptsasInternalCtx);
1856 mpt_deregister(mptsasTaskCtx);
1857 mpt_deregister(mptsasDoneCtx);
1858}
1859
1860module_init(mptsas_init);
1861module_exit(mptsas_exit);