blob: b6a6f27082b64f800b422a0858d0e2de93b450c6 [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 Hellwige3094442006-02-16 13:25:36 +0100120 u16 handle_enclosure; /* enclosure identifier of the enclosure */
121 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200122 u8 phy_id; /* phy number of parent device */
123 u8 port_id; /* sas physical port this device
124 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100125 u8 id; /* logical target id of this device */
126 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200127 u64 sas_address; /* WWN of this device,
128 SATA is assigned by HBA,expander */
129 u32 device_info; /* bitfield detailed info about this device */
130};
131
132struct mptsas_phyinfo {
133 u8 phy_id; /* phy index */
134 u8 port_id; /* port number this phy is part of */
135 u8 negotiated_link_rate; /* nego'd link rate for this phy */
136 u8 hw_link_rate; /* hardware max/min phys link rate */
137 u8 programmed_link_rate; /* programmed max/min phy link rate */
138 struct mptsas_devinfo identify; /* point to phy device info */
139 struct mptsas_devinfo attached; /* point to attached device info */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100140 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200141 struct sas_rphy *rphy;
142};
143
144struct mptsas_portinfo {
145 struct list_head list;
146 u16 handle; /* unique id to address this */
147 u8 num_phys; /* number of phys */
148 struct mptsas_phyinfo *phy_info;
149};
150
Christoph Hellwige3094442006-02-16 13:25:36 +0100151struct mptsas_enclosure {
152 u64 enclosure_logical_id; /* The WWN for the enclosure */
153 u16 enclosure_handle; /* unique id to address this */
154 u16 flags; /* details enclosure management */
155 u16 num_slot; /* num slots */
156 u16 start_slot; /* first slot */
157 u8 start_id; /* starting logical target id */
158 u8 start_channel; /* starting logical channel id */
159 u8 sep_id; /* SEP device logical target id */
160 u8 sep_channel; /* SEP channel logical channel id */
161};
162
Christoph Hellwigb5141122005-10-28 22:07:41 +0200163
164#ifdef SASDEBUG
165static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
166{
167 printk("---- IO UNIT PAGE 0 ------------\n");
168 printk("Handle=0x%X\n",
169 le16_to_cpu(phy_data->AttachedDeviceHandle));
170 printk("Controller Handle=0x%X\n",
171 le16_to_cpu(phy_data->ControllerDevHandle));
172 printk("Port=0x%X\n", phy_data->Port);
173 printk("Port Flags=0x%X\n", phy_data->PortFlags);
174 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
175 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
176 printk("Controller PHY Device Info=0x%X\n",
177 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
178 printk("DiscoveryStatus=0x%X\n",
179 le32_to_cpu(phy_data->DiscoveryStatus));
180 printk("\n");
181}
182
183static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
184{
185 __le64 sas_address;
186
187 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
188
189 printk("---- SAS PHY PAGE 0 ------------\n");
190 printk("Attached Device Handle=0x%X\n",
191 le16_to_cpu(pg0->AttachedDevHandle));
192 printk("SAS Address=0x%llX\n",
193 (unsigned long long)le64_to_cpu(sas_address));
194 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
195 printk("Attached Device Info=0x%X\n",
196 le32_to_cpu(pg0->AttachedDeviceInfo));
197 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
198 printk("Change Count=0x%X\n", pg0->ChangeCount);
199 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
200 printk("\n");
201}
202
203static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
204{
205 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200206 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
207 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200208 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200209 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
210 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
211 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200212}
213
214static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
215{
216 __le64 sas_address;
217
218 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
219
220 printk("---- SAS DEVICE PAGE 0 ---------\n");
221 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100222 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200223 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
224 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
225 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
226 printk("Target ID=0x%X\n", pg0->TargetID);
227 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200228 /* The PhyNum field specifies the PHY number of the parent
229 * device this device is linked to
230 */
231 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
232 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200233 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
234 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
235 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
236 printk("\n");
237}
238
239static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
240{
241 printk("---- SAS EXPANDER PAGE 1 ------------\n");
242
243 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200244 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200245 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
246 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
247 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
248 printk("Owner Device Handle=0x%X\n",
249 le16_to_cpu(pg1->OwnerDevHandle));
250 printk("Attached Device Handle=0x%X\n",
251 le16_to_cpu(pg1->AttachedDevHandle));
252}
253#else
254#define mptsas_print_phy_data(phy_data) do { } while (0)
255#define mptsas_print_phy_pg0(pg0) do { } while (0)
256#define mptsas_print_phy_pg1(pg1) do { } while (0)
257#define mptsas_print_device_pg0(pg0) do { } while (0)
258#define mptsas_print_expander_pg1(pg1) do { } while (0)
259#endif
260
Christoph Hellwige3094442006-02-16 13:25:36 +0100261static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
262{
263 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
264 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
265}
266
267static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
268{
269 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
270 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
271}
272
273static int
Moore, Eric52435432006-03-14 09:14:15 -0700274mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100275 u32 form, u32 form_specific)
276{
277 ConfigExtendedPageHeader_t hdr;
278 CONFIGPARMS cfg;
279 SasEnclosurePage0_t *buffer;
280 dma_addr_t dma_handle;
281 int error;
282 __le64 le_identifier;
283
284 memset(&hdr, 0, sizeof(hdr));
285 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
286 hdr.PageNumber = 0;
287 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
288 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
289
290 cfg.cfghdr.ehdr = &hdr;
291 cfg.physAddr = -1;
292 cfg.pageAddr = form + form_specific;
293 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
294 cfg.dir = 0; /* read */
295 cfg.timeout = 10;
296
297 error = mpt_config(ioc, &cfg);
298 if (error)
299 goto out;
300 if (!hdr.ExtPageLength) {
301 error = -ENXIO;
302 goto out;
303 }
304
305 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
306 &dma_handle);
307 if (!buffer) {
308 error = -ENOMEM;
309 goto out;
310 }
311
312 cfg.physAddr = dma_handle;
313 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
314
315 error = mpt_config(ioc, &cfg);
316 if (error)
317 goto out_free_consistent;
318
319 /* save config data */
320 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
321 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
322 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
323 enclosure->flags = le16_to_cpu(buffer->Flags);
324 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
325 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
326 enclosure->start_id = buffer->StartTargetID;
327 enclosure->start_channel = buffer->StartBus;
328 enclosure->sep_id = buffer->SEPTargetID;
329 enclosure->sep_channel = buffer->SEPBus;
330
331 out_free_consistent:
332 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
333 buffer, dma_handle);
334 out:
335 return error;
336}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200337
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200338/*
339 * This is pretty ugly. We will be able to seriously clean it up
340 * once the DV code in mptscsih goes away and we can properly
341 * implement ->target_alloc.
342 */
343static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700344mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200345{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700346 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200347 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
348 struct sas_rphy *rphy;
349 struct mptsas_portinfo *p;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700350 VirtTarget *vtarget;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200351 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700352 struct scsi_target *starget;
Moore, Eric914c2d82006-03-14 09:19:36 -0700353 u32 target_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200354 int i;
355
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100356 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200357 if (!vdev) {
358 printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
359 hd->ioc->name, sizeof(VirtDevice));
360 return -ENOMEM;
361 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700362 sdev->hostdata = vdev;
363 starget = scsi_target(sdev);
364 vtarget = starget->hostdata;
Moore, Eric914c2d82006-03-14 09:19:36 -0700365 vtarget->ioc_id = hd->ioc->id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700366 vdev->vtarget = vtarget;
367 if (vtarget->num_luns == 0) {
368 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
369 hd->Targets[sdev->id] = vtarget;
370 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200371
Moore, Eric816aa902006-01-13 16:25:20 -0700372 /*
373 RAID volumes placed beyond the last expected port.
374 */
375 if (sdev->channel == hd->ioc->num_ports) {
Moore, Eric914c2d82006-03-14 09:19:36 -0700376 target_id = sdev->id;
377 vtarget->bus_id = 0;
Moore, Eric816aa902006-01-13 16:25:20 -0700378 vdev->lun = 0;
379 goto out;
380 }
381
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700382 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100383 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200384 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
385 for (i = 0; i < p->num_phys; i++) {
386 if (p->phy_info[i].attached.sas_address ==
387 rphy->identify.sas_address) {
Moore, Eric914c2d82006-03-14 09:19:36 -0700388 target_id = p->phy_info[i].attached.id;
389 vtarget->bus_id = p->phy_info[i].attached.channel;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700390 vdev->lun = sdev->lun;
Moore, Eric914c2d82006-03-14 09:19:36 -0700391 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200392 goto out;
393 }
394 }
395 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100396 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200397
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200398 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100399 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200400
401 out:
Moore, Eric914c2d82006-03-14 09:19:36 -0700402 vtarget->target_id = target_id;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700403 vtarget->num_luns++;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200404 return 0;
405}
406
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100407static void
408mptsas_slave_destroy(struct scsi_device *sdev)
409{
410 struct Scsi_Host *host = sdev->host;
411 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
412 struct sas_rphy *rphy;
413 struct mptsas_portinfo *p;
414 int i;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700415 VirtDevice *vdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100416
417 /*
418 * Handle hotplug removal case.
419 * We need to clear out attached data structure.
420 */
421 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
422
423 mutex_lock(&hd->ioc->sas_topology_mutex);
424 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
425 for (i = 0; i < p->num_phys; i++) {
426 if (p->phy_info[i].attached.sas_address ==
427 rphy->identify.sas_address) {
428 memset(&p->phy_info[i].attached, 0,
429 sizeof(struct mptsas_devinfo));
430 p->phy_info[i].rphy = NULL;
431 goto out;
432 }
433 }
434 }
435
436 out:
437 mutex_unlock(&hd->ioc->sas_topology_mutex);
438 /*
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700439 * Issue target reset to flush firmware outstanding commands.
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100440 */
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700441 vdev = sdev->hostdata;
442 if (vdev->configured_lun){
443 if (mptscsih_TMHandler(hd,
444 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
Moore, Eric914c2d82006-03-14 09:19:36 -0700445 vdev->vtarget->bus_id,
446 vdev->vtarget->target_id,
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700447 0, 0, 5 /* 5 second timeout */)
448 < 0){
449
450 /* The TM request failed!
451 * Fatal error case.
452 */
453 printk(MYIOC_s_WARN_FMT
454 "Error processing TaskMgmt id=%d TARGET_RESET\n",
455 hd->ioc->name,
Moore, Eric914c2d82006-03-14 09:19:36 -0700456 vdev->vtarget->target_id);
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700457
458 hd->tmPending = 0;
459 hd->tmState = TM_STATE_NONE;
460 }
461 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100462 mptscsih_slave_destroy(sdev);
463}
464
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200465static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700466 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200467 .proc_name = "mptsas",
468 .proc_info = mptscsih_proc_info,
469 .name = "MPT SPI Host",
470 .info = mptscsih_info,
471 .queuecommand = mptscsih_qcmd,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700472 .target_alloc = mptscsih_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200473 .slave_alloc = mptsas_slave_alloc,
474 .slave_configure = mptscsih_slave_configure,
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700475 .target_destroy = mptscsih_target_destroy,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100476 .slave_destroy = mptsas_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200477 .change_queue_depth = mptscsih_change_queue_depth,
478 .eh_abort_handler = mptscsih_abort,
479 .eh_device_reset_handler = mptscsih_dev_reset,
480 .eh_bus_reset_handler = mptscsih_bus_reset,
481 .eh_host_reset_handler = mptscsih_host_reset,
482 .bios_param = mptscsih_bios_param,
483 .can_queue = MPT_FC_CAN_QUEUE,
484 .this_id = -1,
485 .sg_tablesize = MPT_SCSI_SG_DEPTH,
486 .max_sectors = 8192,
487 .cmd_per_lun = 7,
488 .use_clustering = ENABLE_CLUSTERING,
489};
490
Christoph Hellwigb5141122005-10-28 22:07:41 +0200491static int mptsas_get_linkerrors(struct sas_phy *phy)
492{
493 MPT_ADAPTER *ioc = phy_to_ioc(phy);
494 ConfigExtendedPageHeader_t hdr;
495 CONFIGPARMS cfg;
496 SasPhyPage1_t *buffer;
497 dma_addr_t dma_handle;
498 int error;
499
500 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
501 hdr.ExtPageLength = 0;
502 hdr.PageNumber = 1 /* page number 1*/;
503 hdr.Reserved1 = 0;
504 hdr.Reserved2 = 0;
505 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
506 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
507
508 cfg.cfghdr.ehdr = &hdr;
509 cfg.physAddr = -1;
510 cfg.pageAddr = phy->identify.phy_identifier;
511 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
512 cfg.dir = 0; /* read */
513 cfg.timeout = 10;
514
515 error = mpt_config(ioc, &cfg);
516 if (error)
517 return error;
518 if (!hdr.ExtPageLength)
519 return -ENXIO;
520
521 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
522 &dma_handle);
523 if (!buffer)
524 return -ENOMEM;
525
526 cfg.physAddr = dma_handle;
527 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
528
529 error = mpt_config(ioc, &cfg);
530 if (error)
531 goto out_free_consistent;
532
533 mptsas_print_phy_pg1(buffer);
534
535 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
536 phy->running_disparity_error_count =
537 le32_to_cpu(buffer->RunningDisparityErrorCount);
538 phy->loss_of_dword_sync_count =
539 le32_to_cpu(buffer->LossDwordSynchCount);
540 phy->phy_reset_problem_count =
541 le32_to_cpu(buffer->PhyResetProblemCount);
542
543 out_free_consistent:
544 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
545 buffer, dma_handle);
546 return error;
547}
548
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200549static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
550 MPT_FRAME_HDR *reply)
551{
552 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
553 if (reply != NULL) {
554 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
555 memcpy(ioc->sas_mgmt.reply, reply,
556 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
557 }
558 complete(&ioc->sas_mgmt.done);
559 return 1;
560}
561
562static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
563{
564 MPT_ADAPTER *ioc = phy_to_ioc(phy);
565 SasIoUnitControlRequest_t *req;
566 SasIoUnitControlReply_t *reply;
567 MPT_FRAME_HDR *mf;
568 MPIHeader_t *hdr;
569 unsigned long timeleft;
570 int error = -ERESTARTSYS;
571
572 /* not implemented for expanders */
573 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
574 return -ENXIO;
575
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100576 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200577 goto out;
578
579 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
580 if (!mf) {
581 error = -ENOMEM;
582 goto out_unlock;
583 }
584
585 hdr = (MPIHeader_t *) mf;
586 req = (SasIoUnitControlRequest_t *)mf;
587 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
588 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
589 req->MsgContext = hdr->MsgContext;
590 req->Operation = hard_reset ?
591 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
592 req->PhyNum = phy->identify.phy_identifier;
593
594 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
595
596 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
597 10 * HZ);
598 if (!timeleft) {
599 /* On timeout reset the board */
600 mpt_free_msg_frame(ioc, mf);
601 mpt_HardResetHandler(ioc, CAN_SLEEP);
602 error = -ETIMEDOUT;
603 goto out_unlock;
604 }
605
606 /* a reply frame is expected */
607 if ((ioc->sas_mgmt.status &
608 MPT_IOCTL_STATUS_RF_VALID) == 0) {
609 error = -ENXIO;
610 goto out_unlock;
611 }
612
613 /* process the completed Reply Message Frame */
614 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
615 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
616 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
617 __FUNCTION__,
618 reply->IOCStatus,
619 reply->IOCLogInfo);
620 error = -ENXIO;
621 goto out_unlock;
622 }
623
624 error = 0;
625
626 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100627 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200628 out:
629 return error;
630}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200631
Christoph Hellwige3094442006-02-16 13:25:36 +0100632static int
633mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
634{
635 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
636 int i, error;
637 struct mptsas_portinfo *p;
638 struct mptsas_enclosure enclosure_info;
639 u64 enclosure_handle;
640
641 mutex_lock(&ioc->sas_topology_mutex);
642 list_for_each_entry(p, &ioc->sas_topology, list) {
643 for (i = 0; i < p->num_phys; i++) {
644 if (p->phy_info[i].attached.sas_address ==
645 rphy->identify.sas_address) {
646 enclosure_handle = p->phy_info[i].
647 attached.handle_enclosure;
648 goto found_info;
649 }
650 }
651 }
652 mutex_unlock(&ioc->sas_topology_mutex);
653 return -ENXIO;
654
655 found_info:
656 mutex_unlock(&ioc->sas_topology_mutex);
657 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -0700658 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +0100659 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
660 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
661 if (!error)
662 *identifier = enclosure_info.enclosure_logical_id;
663 return error;
664}
665
666static int
667mptsas_get_bay_identifier(struct sas_rphy *rphy)
668{
669 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
670 struct mptsas_portinfo *p;
671 int i, rc;
672
673 mutex_lock(&ioc->sas_topology_mutex);
674 list_for_each_entry(p, &ioc->sas_topology, list) {
675 for (i = 0; i < p->num_phys; i++) {
676 if (p->phy_info[i].attached.sas_address ==
677 rphy->identify.sas_address) {
678 rc = p->phy_info[i].attached.slot;
679 goto out;
680 }
681 }
682 }
683 rc = -ENXIO;
684 out:
685 mutex_unlock(&ioc->sas_topology_mutex);
686 return rc;
687}
688
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200689static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +0200690 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +0100691 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
692 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200693 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200694};
695
696static struct scsi_transport_template *mptsas_transport_template;
697
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200698static int
699mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
700{
701 ConfigExtendedPageHeader_t hdr;
702 CONFIGPARMS cfg;
703 SasIOUnitPage0_t *buffer;
704 dma_addr_t dma_handle;
705 int error, i;
706
707 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
708 hdr.ExtPageLength = 0;
709 hdr.PageNumber = 0;
710 hdr.Reserved1 = 0;
711 hdr.Reserved2 = 0;
712 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
713 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
714
715 cfg.cfghdr.ehdr = &hdr;
716 cfg.physAddr = -1;
717 cfg.pageAddr = 0;
718 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
719 cfg.dir = 0; /* read */
720 cfg.timeout = 10;
721
722 error = mpt_config(ioc, &cfg);
723 if (error)
724 goto out;
725 if (!hdr.ExtPageLength) {
726 error = -ENXIO;
727 goto out;
728 }
729
730 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
731 &dma_handle);
732 if (!buffer) {
733 error = -ENOMEM;
734 goto out;
735 }
736
737 cfg.physAddr = dma_handle;
738 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
739
740 error = mpt_config(ioc, &cfg);
741 if (error)
742 goto out_free_consistent;
743
744 port_info->num_phys = buffer->NumPhys;
745 port_info->phy_info = kcalloc(port_info->num_phys,
746 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
747 if (!port_info->phy_info) {
748 error = -ENOMEM;
749 goto out_free_consistent;
750 }
751
Moore, Ericdb9c9172006-03-14 09:14:18 -0700752 if (port_info->num_phys)
753 port_info->handle =
754 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200755 for (i = 0; i < port_info->num_phys; i++) {
756 mptsas_print_phy_data(&buffer->PhyData[i]);
757 port_info->phy_info[i].phy_id = i;
758 port_info->phy_info[i].port_id =
759 buffer->PhyData[i].Port;
760 port_info->phy_info[i].negotiated_link_rate =
761 buffer->PhyData[i].NegotiatedLinkRate;
762 }
763
764 out_free_consistent:
765 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
766 buffer, dma_handle);
767 out:
768 return error;
769}
770
771static int
772mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
773 u32 form, u32 form_specific)
774{
775 ConfigExtendedPageHeader_t hdr;
776 CONFIGPARMS cfg;
777 SasPhyPage0_t *buffer;
778 dma_addr_t dma_handle;
779 int error;
780
781 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
782 hdr.ExtPageLength = 0;
783 hdr.PageNumber = 0;
784 hdr.Reserved1 = 0;
785 hdr.Reserved2 = 0;
786 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
787 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
788
789 cfg.cfghdr.ehdr = &hdr;
790 cfg.dir = 0; /* read */
791 cfg.timeout = 10;
792
793 /* Get Phy Pg 0 for each Phy. */
794 cfg.physAddr = -1;
795 cfg.pageAddr = form + form_specific;
796 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
797
798 error = mpt_config(ioc, &cfg);
799 if (error)
800 goto out;
801
802 if (!hdr.ExtPageLength) {
803 error = -ENXIO;
804 goto out;
805 }
806
807 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
808 &dma_handle);
809 if (!buffer) {
810 error = -ENOMEM;
811 goto out;
812 }
813
814 cfg.physAddr = dma_handle;
815 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
816
817 error = mpt_config(ioc, &cfg);
818 if (error)
819 goto out_free_consistent;
820
821 mptsas_print_phy_pg0(buffer);
822
823 phy_info->hw_link_rate = buffer->HwLinkRate;
824 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
825 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
826 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
827
828 out_free_consistent:
829 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
830 buffer, dma_handle);
831 out:
832 return error;
833}
834
835static int
836mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
837 u32 form, u32 form_specific)
838{
839 ConfigExtendedPageHeader_t hdr;
840 CONFIGPARMS cfg;
841 SasDevicePage0_t *buffer;
842 dma_addr_t dma_handle;
843 __le64 sas_address;
844 int error;
845
846 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
847 hdr.ExtPageLength = 0;
848 hdr.PageNumber = 0;
849 hdr.Reserved1 = 0;
850 hdr.Reserved2 = 0;
851 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
852 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
853
854 cfg.cfghdr.ehdr = &hdr;
855 cfg.pageAddr = form + form_specific;
856 cfg.physAddr = -1;
857 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
858 cfg.dir = 0; /* read */
859 cfg.timeout = 10;
860
Moore, Ericdb9c9172006-03-14 09:14:18 -0700861 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200862 error = mpt_config(ioc, &cfg);
863 if (error)
864 goto out;
865 if (!hdr.ExtPageLength) {
866 error = -ENXIO;
867 goto out;
868 }
869
870 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
871 &dma_handle);
872 if (!buffer) {
873 error = -ENOMEM;
874 goto out;
875 }
876
877 cfg.physAddr = dma_handle;
878 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
879
880 error = mpt_config(ioc, &cfg);
881 if (error)
882 goto out_free_consistent;
883
884 mptsas_print_device_pg0(buffer);
885
886 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -0700887 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +0100888 device_info->handle_enclosure =
889 le16_to_cpu(buffer->EnclosureHandle);
890 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200891 device_info->phy_id = buffer->PhyNum;
892 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100893 device_info->id = buffer->TargetID;
894 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200895 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
896 device_info->sas_address = le64_to_cpu(sas_address);
897 device_info->device_info =
898 le32_to_cpu(buffer->DeviceInfo);
899
900 out_free_consistent:
901 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
902 buffer, dma_handle);
903 out:
904 return error;
905}
906
907static int
908mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
909 u32 form, u32 form_specific)
910{
911 ConfigExtendedPageHeader_t hdr;
912 CONFIGPARMS cfg;
913 SasExpanderPage0_t *buffer;
914 dma_addr_t dma_handle;
915 int error;
916
917 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
918 hdr.ExtPageLength = 0;
919 hdr.PageNumber = 0;
920 hdr.Reserved1 = 0;
921 hdr.Reserved2 = 0;
922 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
923 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
924
925 cfg.cfghdr.ehdr = &hdr;
926 cfg.physAddr = -1;
927 cfg.pageAddr = form + form_specific;
928 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
929 cfg.dir = 0; /* read */
930 cfg.timeout = 10;
931
Moore, Ericdb9c9172006-03-14 09:14:18 -0700932 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200933 error = mpt_config(ioc, &cfg);
934 if (error)
935 goto out;
936
937 if (!hdr.ExtPageLength) {
938 error = -ENXIO;
939 goto out;
940 }
941
942 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
943 &dma_handle);
944 if (!buffer) {
945 error = -ENOMEM;
946 goto out;
947 }
948
949 cfg.physAddr = dma_handle;
950 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
951
952 error = mpt_config(ioc, &cfg);
953 if (error)
954 goto out_free_consistent;
955
956 /* save config data */
957 port_info->num_phys = buffer->NumPhys;
958 port_info->handle = le16_to_cpu(buffer->DevHandle);
959 port_info->phy_info = kcalloc(port_info->num_phys,
960 sizeof(struct mptsas_phyinfo),GFP_KERNEL);
961 if (!port_info->phy_info) {
962 error = -ENOMEM;
963 goto out_free_consistent;
964 }
965
966 out_free_consistent:
967 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
968 buffer, dma_handle);
969 out:
970 return error;
971}
972
973static int
974mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
975 u32 form, u32 form_specific)
976{
977 ConfigExtendedPageHeader_t hdr;
978 CONFIGPARMS cfg;
979 SasExpanderPage1_t *buffer;
980 dma_addr_t dma_handle;
981 int error;
982
983 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
984 hdr.ExtPageLength = 0;
985 hdr.PageNumber = 1;
986 hdr.Reserved1 = 0;
987 hdr.Reserved2 = 0;
988 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
989 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
990
991 cfg.cfghdr.ehdr = &hdr;
992 cfg.physAddr = -1;
993 cfg.pageAddr = form + form_specific;
994 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
995 cfg.dir = 0; /* read */
996 cfg.timeout = 10;
997
998 error = mpt_config(ioc, &cfg);
999 if (error)
1000 goto out;
1001
1002 if (!hdr.ExtPageLength) {
1003 error = -ENXIO;
1004 goto out;
1005 }
1006
1007 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1008 &dma_handle);
1009 if (!buffer) {
1010 error = -ENOMEM;
1011 goto out;
1012 }
1013
1014 cfg.physAddr = dma_handle;
1015 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1016
1017 error = mpt_config(ioc, &cfg);
1018 if (error)
1019 goto out_free_consistent;
1020
1021
1022 mptsas_print_expander_pg1(buffer);
1023
1024 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001025 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001026 phy_info->port_id = buffer->PhysicalPort;
1027 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1028 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1029 phy_info->hw_link_rate = buffer->HwLinkRate;
1030 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1031 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1032
1033
1034 out_free_consistent:
1035 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1036 buffer, dma_handle);
1037 out:
1038 return error;
1039}
1040
Moore, Ericc73787ee2006-01-26 16:20:06 -07001041/*
1042 * Returns true if there is a scsi end device
1043 */
1044static inline int
1045mptsas_is_end_device(struct mptsas_devinfo * attached)
1046{
1047 if ((attached->handle) &&
1048 (attached->device_info &
1049 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
1050 ((attached->device_info &
1051 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
1052 (attached->device_info &
1053 MPI_SAS_DEVICE_INFO_STP_TARGET) |
1054 (attached->device_info &
1055 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
1056 return 1;
1057 else
1058 return 0;
1059}
1060
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001061static void
1062mptsas_parse_device_info(struct sas_identify *identify,
1063 struct mptsas_devinfo *device_info)
1064{
1065 u16 protocols;
1066
1067 identify->sas_address = device_info->sas_address;
1068 identify->phy_identifier = device_info->phy_id;
1069
1070 /*
1071 * Fill in Phy Initiator Port Protocol.
1072 * Bits 6:3, more than one bit can be set, fall through cases.
1073 */
1074 protocols = device_info->device_info & 0x78;
1075 identify->initiator_port_protocols = 0;
1076 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1077 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1078 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1079 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1080 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1081 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1082 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1083 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1084
1085 /*
1086 * Fill in Phy Target Port Protocol.
1087 * Bits 10:7, more than one bit can be set, fall through cases.
1088 */
1089 protocols = device_info->device_info & 0x780;
1090 identify->target_port_protocols = 0;
1091 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1092 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1093 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1094 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1095 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1096 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1097 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1098 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1099
1100 /*
1101 * Fill in Attached device type.
1102 */
1103 switch (device_info->device_info &
1104 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1105 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1106 identify->device_type = SAS_PHY_UNUSED;
1107 break;
1108 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1109 identify->device_type = SAS_END_DEVICE;
1110 break;
1111 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1112 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1113 break;
1114 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1115 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1116 break;
1117 }
1118}
1119
1120static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001121 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001122{
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001123 struct sas_phy *phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001124 int error;
1125
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001126 phy = sas_phy_alloc(dev, index);
1127 if (!phy)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001128 return -ENOMEM;
1129
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001130 phy->port_identifier = phy_info->port_id;
1131 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001132
1133 /*
1134 * Set Negotiated link rate.
1135 */
1136 switch (phy_info->negotiated_link_rate) {
1137 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001138 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001139 break;
1140 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001141 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001142 break;
1143 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001144 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001145 break;
1146 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001147 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001148 break;
1149 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1150 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1151 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001152 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001153 break;
1154 }
1155
1156 /*
1157 * Set Max hardware link rate.
1158 */
1159 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1160 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001161 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001162 break;
1163 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001164 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001165 break;
1166 default:
1167 break;
1168 }
1169
1170 /*
1171 * Set Max programmed link rate.
1172 */
1173 switch (phy_info->programmed_link_rate &
1174 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1175 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001176 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001177 break;
1178 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001179 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001180 break;
1181 default:
1182 break;
1183 }
1184
1185 /*
1186 * Set Min hardware link rate.
1187 */
1188 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1189 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001190 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001191 break;
1192 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001193 phy->minimum_linkrate_hw = 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 programmed link rate.
1201 */
1202 switch (phy_info->programmed_link_rate &
1203 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1204 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001205 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001206 break;
1207 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001208 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001209 break;
1210 default:
1211 break;
1212 }
1213
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001214 if (local)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001215 phy->local_attached = 1;
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001216
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001217 error = sas_phy_add(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001218 if (error) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001219 sas_phy_free(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001220 return error;
1221 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001222 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001223
1224 if (phy_info->attached.handle) {
1225 struct sas_rphy *rphy;
1226
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001227 rphy = sas_rphy_alloc(phy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001228 if (!rphy)
1229 return 0; /* non-fatal: an rphy can be added later */
1230
1231 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1232 error = sas_rphy_add(rphy);
1233 if (error) {
1234 sas_rphy_free(rphy);
1235 return error;
1236 }
1237
1238 phy_info->rphy = rphy;
1239 }
1240
1241 return 0;
1242}
1243
1244static int
1245mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
1246{
1247 struct mptsas_portinfo *port_info;
1248 u32 handle = 0xFFFF;
1249 int error = -ENOMEM, i;
1250
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001251 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001252 if (!port_info)
1253 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001254
1255 error = mptsas_sas_io_unit_pg0(ioc, port_info);
1256 if (error)
1257 goto out_free_port_info;
1258
Moore, Eric816aa902006-01-13 16:25:20 -07001259 ioc->num_ports = port_info->num_phys;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001260 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001261 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001262 mutex_unlock(&ioc->sas_topology_mutex);
1263
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001264 for (i = 0; i < port_info->num_phys; i++) {
1265 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1266 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1267 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1268
1269 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1270 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1271 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001272 port_info->phy_info[i].identify.phy_id =
1273 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001274 handle = port_info->phy_info[i].identify.handle;
1275
1276 if (port_info->phy_info[i].attached.handle) {
1277 mptsas_sas_device_pg0(ioc,
1278 &port_info->phy_info[i].attached,
1279 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1280 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1281 port_info->phy_info[i].attached.handle);
1282 }
1283
1284 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001285 &port_info->phy_info[i], *index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001286 (*index)++;
1287 }
1288
1289 return 0;
1290
1291 out_free_port_info:
1292 kfree(port_info);
1293 out:
1294 return error;
1295}
1296
1297static int
1298mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
1299{
1300 struct mptsas_portinfo *port_info, *p;
1301 int error = -ENOMEM, i, j;
1302
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001303 port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001304 if (!port_info)
1305 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001306
1307 error = mptsas_sas_expander_pg0(ioc, port_info,
1308 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1309 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1310 if (error)
1311 goto out_free_port_info;
1312
1313 *handle = port_info->handle;
1314
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001315 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001316 list_add_tail(&port_info->list, &ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001317 mutex_unlock(&ioc->sas_topology_mutex);
1318
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001319 for (i = 0; i < port_info->num_phys; i++) {
1320 struct device *parent;
1321
1322 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1323 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1324 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1325
1326 if (port_info->phy_info[i].identify.handle) {
1327 mptsas_sas_device_pg0(ioc,
1328 &port_info->phy_info[i].identify,
1329 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1330 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1331 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001332 port_info->phy_info[i].identify.phy_id =
1333 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001334 }
1335
1336 if (port_info->phy_info[i].attached.handle) {
1337 mptsas_sas_device_pg0(ioc,
1338 &port_info->phy_info[i].attached,
1339 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1340 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1341 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001342 port_info->phy_info[i].attached.phy_id =
1343 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001344 }
1345
1346 /*
1347 * If we find a parent port handle this expander is
1348 * attached to another expander, else it hangs of the
1349 * HBA phys.
1350 */
1351 parent = &ioc->sh->shost_gendev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001352 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001353 list_for_each_entry(p, &ioc->sas_topology, list) {
1354 for (j = 0; j < p->num_phys; j++) {
1355 if (port_info->phy_info[i].identify.handle ==
1356 p->phy_info[j].attached.handle)
1357 parent = &p->phy_info[j].rphy->dev;
1358 }
1359 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001360 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001361
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001362 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
1363 *index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001364 (*index)++;
1365 }
1366
1367 return 0;
1368
1369 out_free_port_info:
Moore, Ericdb9c9172006-03-14 09:14:18 -07001370 kfree(port_info->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001371 kfree(port_info);
1372 out:
1373 return error;
1374}
1375
1376static void
1377mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1378{
1379 u32 handle = 0xFFFF;
1380 int index = 0;
1381
1382 mptsas_probe_hba_phys(ioc, &index);
1383 while (!mptsas_probe_expander_phys(ioc, &handle, &index))
1384 ;
1385}
1386
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001387static struct mptsas_phyinfo *
1388mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
1389{
1390 struct mptsas_portinfo *port_info;
1391 struct mptsas_devinfo device_info;
1392 struct mptsas_phyinfo *phy_info = NULL;
1393 int i, error;
1394
1395 /*
1396 * Retrieve the parent sas_address
1397 */
1398 error = mptsas_sas_device_pg0(ioc, &device_info,
1399 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1400 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1401 parent_handle);
1402 if (error) {
1403 printk("mptsas: failed to retrieve device page\n");
1404 return NULL;
1405 }
1406
1407 /*
1408 * The phy_info structures are never deallocated during lifetime of
1409 * a host, so the code below is safe without additional refcounting.
1410 */
1411 mutex_lock(&ioc->sas_topology_mutex);
1412 list_for_each_entry(port_info, &ioc->sas_topology, list) {
1413 for (i = 0; i < port_info->num_phys; i++) {
1414 if (port_info->phy_info[i].identify.sas_address ==
1415 device_info.sas_address &&
1416 port_info->phy_info[i].phy_id == phy_id) {
1417 phy_info = &port_info->phy_info[i];
1418 break;
1419 }
1420 }
1421 }
1422 mutex_unlock(&ioc->sas_topology_mutex);
1423
1424 return phy_info;
1425}
1426
1427static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07001428mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001429{
1430 struct mptsas_portinfo *port_info;
1431 struct mptsas_phyinfo *phy_info = NULL;
1432 int i;
1433
1434 /*
1435 * The phy_info structures are never deallocated during lifetime of
1436 * a host, so the code below is safe without additional refcounting.
1437 */
1438 mutex_lock(&ioc->sas_topology_mutex);
1439 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Moore, Ericc73787ee2006-01-26 16:20:06 -07001440 for (i = 0; i < port_info->num_phys; i++)
1441 if (mptsas_is_end_device(&port_info->phy_info[i].attached))
1442 if (port_info->phy_info[i].attached.id == id) {
1443 phy_info = &port_info->phy_info[i];
1444 break;
1445 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001446 }
1447 mutex_unlock(&ioc->sas_topology_mutex);
1448
1449 return phy_info;
1450}
1451
Moore, Eric4b766472006-03-14 09:14:12 -07001452/*
1453 * Work queue thread to clear the persitency table
1454 */
1455static void
1456mptscsih_sas_persist_clear_table(void * arg)
1457{
1458 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
1459
1460 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
1461}
1462
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001463static void
1464mptsas_hotplug_work(void *arg)
1465{
1466 struct mptsas_hotplug_event *ev = arg;
1467 MPT_ADAPTER *ioc = ev->ioc;
1468 struct mptsas_phyinfo *phy_info;
1469 struct sas_rphy *rphy;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001470 struct scsi_device *sdev;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001471 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001472 struct mptsas_devinfo sas_device;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001473
1474 switch (ev->event_type) {
1475 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001476
Moore, Ericc73787ee2006-01-26 16:20:06 -07001477 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001478 if (!phy_info) {
1479 printk("mptsas: remove event for non-existant PHY.\n");
1480 break;
1481 }
1482
Moore, Ericc73787ee2006-01-26 16:20:06 -07001483 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1484 ds = "ssp";
1485 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1486 ds = "stp";
1487 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1488 ds = "sata";
1489
1490 printk(MYIOC_s_INFO_FMT
1491 "removing %s device, channel %d, id %d, phy %d\n",
1492 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
1493
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001494 if (phy_info->rphy) {
1495 sas_rphy_delete(phy_info->rphy);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001496 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001497 phy_info->rphy = NULL;
1498 }
1499 break;
1500 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001501
1502 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01001503 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07001504 */
Christoph Hellwige3094442006-02-16 13:25:36 +01001505 if (mptsas_sas_device_pg0(ioc, &sas_device,
1506 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
1507 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id))
1508 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001509
1510 phy_info = mptsas_find_phyinfo_by_parent(ioc,
Christoph Hellwige3094442006-02-16 13:25:36 +01001511 sas_device.handle_parent, sas_device.phy_id);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001512 if (!phy_info) {
1513 printk("mptsas: add event for non-existant PHY.\n");
1514 break;
1515 }
1516
1517 if (phy_info->rphy) {
1518 printk("mptsas: trying to add existing device.\n");
1519 break;
1520 }
1521
Christoph Hellwige3094442006-02-16 13:25:36 +01001522 memcpy(&phy_info->attached, &sas_device,
1523 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001524
Moore, Ericc73787ee2006-01-26 16:20:06 -07001525 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1526 ds = "ssp";
1527 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
1528 ds = "stp";
1529 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1530 ds = "sata";
1531
1532 printk(MYIOC_s_INFO_FMT
1533 "attaching %s device, channel %d, id %d, phy %d\n",
1534 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
1535
1536
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001537 rphy = sas_rphy_alloc(phy_info->phy);
1538 if (!rphy)
1539 break; /* non-fatal: an rphy can be added later */
1540
1541 mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
1542 if (sas_rphy_add(rphy)) {
1543 sas_rphy_free(rphy);
1544 break;
1545 }
1546
1547 phy_info->rphy = rphy;
1548 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07001549 case MPTSAS_ADD_RAID:
1550 sdev = scsi_device_lookup(
1551 ioc->sh,
1552 ioc->num_ports,
1553 ev->id,
1554 0);
1555 if (sdev) {
1556 scsi_device_put(sdev);
1557 break;
1558 }
1559 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07001560 "attaching raid volume, channel %d, id %d\n",
Moore, Ericc73787ee2006-01-26 16:20:06 -07001561 ioc->name, ioc->num_ports, ev->id);
1562 scsi_add_device(ioc->sh,
1563 ioc->num_ports,
1564 ev->id,
1565 0);
1566 mpt_findImVolumes(ioc);
1567 break;
1568 case MPTSAS_DEL_RAID:
1569 sdev = scsi_device_lookup(
1570 ioc->sh,
1571 ioc->num_ports,
1572 ev->id,
1573 0);
1574 if (!sdev)
1575 break;
1576 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07001577 "removing raid volume, channel %d, id %d\n",
Moore, Ericc73787ee2006-01-26 16:20:06 -07001578 ioc->name, ioc->num_ports, ev->id);
1579 scsi_remove_device(sdev);
1580 scsi_device_put(sdev);
1581 mpt_findImVolumes(ioc);
1582 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001583 }
1584
1585 kfree(ev);
1586}
1587
1588static void
1589mptscsih_send_sas_event(MPT_ADAPTER *ioc,
1590 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
1591{
1592 struct mptsas_hotplug_event *ev;
1593 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
1594 __le64 sas_address;
1595
1596 if ((device_info &
1597 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
1598 MPI_SAS_DEVICE_INFO_STP_TARGET |
1599 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
1600 return;
1601
Moore, Eric4b766472006-03-14 09:14:12 -07001602 switch (sas_event_data->ReasonCode) {
1603 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
1604 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
1605 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1606 if (!ev) {
1607 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1608 break;
1609 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001610
Moore, Eric4b766472006-03-14 09:14:12 -07001611 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1612 ev->ioc = ioc;
1613 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
1614 ev->parent_handle =
1615 le16_to_cpu(sas_event_data->ParentDevHandle);
1616 ev->channel = sas_event_data->Bus;
1617 ev->id = sas_event_data->TargetID;
1618 ev->phy_id = sas_event_data->PhyNum;
1619 memcpy(&sas_address, &sas_event_data->SASAddress,
1620 sizeof(__le64));
1621 ev->sas_address = le64_to_cpu(sas_address);
1622 ev->device_info = device_info;
1623
1624 if (sas_event_data->ReasonCode &
1625 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
1626 ev->event_type = MPTSAS_ADD_DEVICE;
1627 else
1628 ev->event_type = MPTSAS_DEL_DEVICE;
1629 schedule_work(&ev->work);
1630 break;
1631 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
1632 /*
1633 * Persistent table is full.
1634 */
1635 INIT_WORK(&ioc->mptscsih_persistTask,
1636 mptscsih_sas_persist_clear_table,
1637 (void *)ioc);
1638 schedule_work(&ioc->mptscsih_persistTask);
1639 break;
1640 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
1641 /* TODO */
1642 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
1643 /* TODO */
1644 default:
1645 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001646 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001647}
1648
Moore, Ericc73787ee2006-01-26 16:20:06 -07001649static void
1650mptscsih_send_raid_event(MPT_ADAPTER *ioc,
1651 EVENT_DATA_RAID *raid_event_data)
1652{
1653 struct mptsas_hotplug_event *ev;
1654 RAID_VOL0_STATUS * volumeStatus;
1655
1656 if (ioc->bus_type != SAS)
1657 return;
1658
1659 ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
1660 if (!ev) {
1661 printk(KERN_WARNING "mptsas: lost hotplug event\n");
1662 return;
1663 }
1664
1665 memset(ev,0,sizeof(struct mptsas_hotplug_event));
1666 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
1667 ev->ioc = ioc;
1668 ev->id = raid_event_data->VolumeID;
1669
1670 switch (raid_event_data->ReasonCode) {
1671 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
1672 ev->event_type = MPTSAS_ADD_DEVICE;
1673 break;
1674 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
1675 ev->event_type = MPTSAS_DEL_DEVICE;
1676 break;
1677 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
1678 ev->event_type = MPTSAS_DEL_RAID;
1679 break;
1680 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
1681 ev->event_type = MPTSAS_ADD_RAID;
1682 break;
1683 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
1684 volumeStatus = (RAID_VOL0_STATUS *) &
1685 raid_event_data->SettingsStatus;
1686 ev->event_type = (volumeStatus->State ==
1687 MPI_RAIDVOL0_STATUS_STATE_FAILED) ?
1688 MPTSAS_DEL_RAID : MPTSAS_ADD_RAID;
1689 break;
1690 default:
1691 break;
1692 }
1693 schedule_work(&ev->work);
1694}
1695
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001696static int
1697mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
1698{
Moore, Ericc73787ee2006-01-26 16:20:06 -07001699 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001700 u8 event = le32_to_cpu(reply->Event) & 0xFF;
1701
1702 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07001703 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001704
1705 switch (event) {
1706 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1707 mptscsih_send_sas_event(ioc,
1708 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001709 break;
1710 case MPI_EVENT_INTEGRATED_RAID:
1711 mptscsih_send_raid_event(ioc,
1712 (EVENT_DATA_RAID *)reply->Data);
1713 break;
Moore, Eric79de2782006-01-25 18:05:15 -07001714 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1715 INIT_WORK(&ioc->mptscsih_persistTask,
1716 mptscsih_sas_persist_clear_table,
1717 (void *)ioc);
1718 schedule_work(&ioc->mptscsih_persistTask);
1719 break;
Moore, Eric4b766472006-03-14 09:14:12 -07001720 case MPI_EVENT_SAS_DISCOVERY:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001721 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07001722 rc = mptscsih_event_process(ioc, reply);
1723 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001724 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07001725 out:
1726
1727 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001728}
1729
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001730static int
1731mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1732{
1733 struct Scsi_Host *sh;
1734 MPT_SCSI_HOST *hd;
1735 MPT_ADAPTER *ioc;
1736 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001737 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001738 int numSGE = 0;
1739 int scale;
1740 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001741 int error=0;
1742 int r;
1743
1744 r = mpt_attach(pdev,id);
1745 if (r)
1746 return r;
1747
1748 ioc = pci_get_drvdata(pdev);
1749 ioc->DoneCtx = mptsasDoneCtx;
1750 ioc->TaskCtx = mptsasTaskCtx;
1751 ioc->InternalCtx = mptsasInternalCtx;
1752
1753 /* Added sanity check on readiness of the MPT adapter.
1754 */
1755 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
1756 printk(MYIOC_s_WARN_FMT
1757 "Skipping because it's not operational!\n",
1758 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001759 error = -ENODEV;
1760 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001761 }
1762
1763 if (!ioc->active) {
1764 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
1765 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001766 error = -ENODEV;
1767 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001768 }
1769
1770 /* Sanity check - ensure at least 1 port is INITIATOR capable
1771 */
1772 ioc_cap = 0;
1773 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
1774 if (ioc->pfacts[ii].ProtocolFlags &
1775 MPI_PORTFACTS_PROTOCOL_INITIATOR)
1776 ioc_cap++;
1777 }
1778
1779 if (!ioc_cap) {
1780 printk(MYIOC_s_WARN_FMT
1781 "Skipping ioc=%p because SCSI Initiator mode "
1782 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06001783 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001784 }
1785
1786 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
1787 if (!sh) {
1788 printk(MYIOC_s_WARN_FMT
1789 "Unable to register controller with SCSI subsystem\n",
1790 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001791 error = -1;
1792 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001793 }
1794
1795 spin_lock_irqsave(&ioc->FreeQlock, flags);
1796
1797 /* Attach the SCSI Host to the IOC structure
1798 */
1799 ioc->sh = sh;
1800
1801 sh->io_port = 0;
1802 sh->n_io_port = 0;
1803 sh->irq = 0;
1804
1805 /* set 16 byte cdb's */
1806 sh->max_cmd_len = 16;
1807
1808 sh->max_id = ioc->pfacts->MaxDevices + 1;
1809
1810 sh->transportt = mptsas_transport_template;
1811
1812 sh->max_lun = MPT_LAST_LUN + 1;
1813 sh->max_channel = 0;
1814 sh->this_id = ioc->pfacts[0].PortSCSIID;
1815
1816 /* Required entry.
1817 */
1818 sh->unique_id = ioc->id;
1819
1820 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001821 mutex_init(&ioc->sas_topology_mutex);
1822
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001823 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001824 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001825
1826 /* Verify that we won't exceed the maximum
1827 * number of chain buffers
1828 * We can optimize: ZZ = req_sz/sizeof(SGE)
1829 * For 32bit SGE's:
1830 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
1831 * + (req_sz - 64)/sizeof(SGE)
1832 * A slightly different algorithm is required for
1833 * 64bit SGEs.
1834 */
1835 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
1836 if (sizeof(dma_addr_t) == sizeof(u64)) {
1837 numSGE = (scale - 1) *
1838 (ioc->facts.MaxChainDepth-1) + scale +
1839 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
1840 sizeof(u32));
1841 } else {
1842 numSGE = 1 + (scale - 1) *
1843 (ioc->facts.MaxChainDepth-1) + scale +
1844 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
1845 sizeof(u32));
1846 }
1847
1848 if (numSGE < sh->sg_tablesize) {
1849 /* Reset this value */
1850 dprintk((MYIOC_s_INFO_FMT
1851 "Resetting sg_tablesize to %d from %d\n",
1852 ioc->name, numSGE, sh->sg_tablesize));
1853 sh->sg_tablesize = numSGE;
1854 }
1855
1856 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
1857
1858 hd = (MPT_SCSI_HOST *) sh->hostdata;
1859 hd->ioc = ioc;
1860
1861 /* SCSI needs scsi_cmnd lookup table!
1862 * (with size equal to req_depth*PtrSz!)
1863 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001864 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
1865 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001866 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001867 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001868 }
1869
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001870 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
1871 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001872
1873 /* Allocate memory for the device structures.
1874 * A non-Null pointer at an offset
1875 * indicates a device exists.
1876 * max_id = 1 + maximum id (hosts.h)
1877 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001878 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
1879 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001880 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001881 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001882 }
1883
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01001884 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001885
1886 /* Clear the TM flags
1887 */
1888 hd->tmPending = 0;
1889 hd->tmState = TM_STATE_NONE;
1890 hd->resetPending = 0;
1891 hd->abortSCpnt = NULL;
1892
1893 /* Clear the pointer used to store
1894 * single-threaded commands, i.e., those
1895 * issued during a bus scan, dv and
1896 * configuration pages.
1897 */
1898 hd->cmdPtr = NULL;
1899
1900 /* Initialize this SCSI Hosts' timers
1901 * To use, set the timer expires field
1902 * and add_timer
1903 */
1904 init_timer(&hd->timer);
1905 hd->timer.data = (unsigned long) hd;
1906 hd->timer.function = mptscsih_timer_expired;
1907
1908 hd->mpt_pq_filter = mpt_pq_filter;
1909 ioc->sas_data.ptClear = mpt_pt_clear;
1910
1911 if (ioc->sas_data.ptClear==1) {
1912 mptbase_sas_persist_operation(
1913 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
1914 }
1915
1916 ddvprintk((MYIOC_s_INFO_FMT
1917 "mpt_pq_filter %x mpt_pq_filter %x\n",
1918 ioc->name,
1919 mpt_pq_filter,
1920 mpt_pq_filter));
1921
1922 init_waitqueue_head(&hd->scandv_waitq);
1923 hd->scandv_wait_done = 0;
1924 hd->last_queue_full = 0;
1925
1926 error = scsi_add_host(sh, &ioc->pcidev->dev);
1927 if (error) {
1928 dprintk((KERN_ERR MYNAM
1929 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001930 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001931 }
1932
1933 mptsas_scan_sas_topology(ioc);
1934
Moore, Eric816aa902006-01-13 16:25:20 -07001935 /*
1936 Reporting RAID volumes.
1937 */
1938 if (!ioc->raid_data.pIocPg2)
1939 return 0;
1940 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1941 return 0;
1942 for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
1943 scsi_add_device(sh,
1944 ioc->num_ports,
1945 ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
1946 0);
1947 }
1948
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001949 return 0;
1950
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07001951out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001952
1953 mptscsih_remove(pdev);
1954 return error;
1955}
1956
1957static void __devexit mptsas_remove(struct pci_dev *pdev)
1958{
1959 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
1960 struct mptsas_portinfo *p, *n;
1961
1962 sas_remove_host(ioc->sh);
1963
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001964 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001965 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
1966 list_del(&p->list);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001967 if (p->phy_info)
1968 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001969 kfree(p);
1970 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001971 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001972
1973 mptscsih_remove(pdev);
1974}
1975
1976static struct pci_device_id mptsas_pci_table[] = {
1977 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064,
1978 PCI_ANY_ID, PCI_ANY_ID },
1979 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066,
1980 PCI_ANY_ID, PCI_ANY_ID },
1981 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068,
1982 PCI_ANY_ID, PCI_ANY_ID },
1983 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1064E,
1984 PCI_ANY_ID, PCI_ANY_ID },
1985 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1066E,
1986 PCI_ANY_ID, PCI_ANY_ID },
1987 { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1068E,
1988 PCI_ANY_ID, PCI_ANY_ID },
1989 {0} /* Terminating entry */
1990};
1991MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
1992
1993
1994static struct pci_driver mptsas_driver = {
1995 .name = "mptsas",
1996 .id_table = mptsas_pci_table,
1997 .probe = mptsas_probe,
1998 .remove = __devexit_p(mptsas_remove),
1999 .shutdown = mptscsih_shutdown,
2000#ifdef CONFIG_PM
2001 .suspend = mptscsih_suspend,
2002 .resume = mptscsih_resume,
2003#endif
2004};
2005
2006static int __init
2007mptsas_init(void)
2008{
2009 show_mptmod_ver(my_NAME, my_VERSION);
2010
2011 mptsas_transport_template =
2012 sas_attach_transport(&mptsas_transport_functions);
2013 if (!mptsas_transport_template)
2014 return -ENODEV;
2015
2016 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2017 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2018 mptsasInternalCtx =
2019 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002020 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002021
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002022 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002023 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002024 ": Registered for IOC event notifications\n"));
2025 }
2026
2027 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2028 dprintk((KERN_INFO MYNAM
2029 ": Registered for IOC reset notifications\n"));
2030 }
2031
2032 return pci_register_driver(&mptsas_driver);
2033}
2034
2035static void __exit
2036mptsas_exit(void)
2037{
2038 pci_unregister_driver(&mptsas_driver);
2039 sas_release_transport(mptsas_transport_template);
2040
2041 mpt_reset_deregister(mptsasDoneCtx);
2042 mpt_event_deregister(mptsasDoneCtx);
2043
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002044 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002045 mpt_deregister(mptsasInternalCtx);
2046 mpt_deregister(mptsasTaskCtx);
2047 mpt_deregister(mptsasDoneCtx);
2048}
2049
2050module_init(mptsas_init);
2051module_exit(mptsas_exit);