blob: dc23adf9a30f6a43a1c653399f8b4dc49dc58e7d [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
Prakash, Sathyaf36789e2007-08-14 16:22:54 +05303 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
Christoph Hellwig0c33b272005-09-09 16:27:19 +02005 *
Prakash, Sathyacddc0ab2008-05-21 00:56:41 +05306 * Copyright (c) 1999-2008 LSI Corporation
Eric Moore16d20102007-06-13 16:31:07 -06007 * (mailto:DL-MPTFusionLinux@lsi.com)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02008 */
9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10/*
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; version 2 of the License.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 NO WARRANTY
21 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 solely responsible for determining the appropriateness of using and
26 distributing the Program and assumes all risks associated with its
27 exercise of rights under this Agreement, including but not limited to
28 the risks and costs of program errors, damage to or loss of data,
29 programs or equipment, and unavailability or interruption of operations.
30
31 DISCLAIMER OF LIABILITY
32 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43*/
44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
45
46#include <linux/module.h>
47#include <linux/kernel.h>
48#include <linux/init.h>
49#include <linux/errno.h>
Tim Schmielaucd354f12007-02-14 00:33:14 -080050#include <linux/jiffies.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020051#include <linux/workqueue.h>
Eric Moore547f9a22006-06-27 14:42:12 -060052#include <linux/delay.h> /* for mdelay */
Christoph Hellwig0c33b272005-09-09 16:27:19 +020053
Eric Moore547f9a22006-06-27 14:42:12 -060054#include <scsi/scsi.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020055#include <scsi/scsi_cmnd.h>
56#include <scsi/scsi_device.h>
57#include <scsi/scsi_host.h>
58#include <scsi/scsi_transport_sas.h>
Eric Moore547f9a22006-06-27 14:42:12 -060059#include <scsi/scsi_dbg.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020060
61#include "mptbase.h"
62#include "mptscsih.h"
Prakash, Sathya56af97a2007-08-14 16:15:38 +053063#include "mptsas.h"
Christoph Hellwig0c33b272005-09-09 16:27:19 +020064
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
James Bottomleye8bf3942006-07-11 17:49:34 -040070/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
Christoph Hellwig0c33b272005-09-09 16:27:19 +020075MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
Eric Moore9f4203b2007-01-04 20:47:47 -070078MODULE_VERSION(my_VERSION);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020079
Christoph Hellwig0c33b272005-09-09 16:27:19 +020080static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
Eric Mooreba856d32006-07-11 17:34:01 -060083 " Clear persistency table: enable=1 "
Christoph Hellwig0c33b272005-09-09 16:27:19 +020084 "(default=MPTSCSIH_PT_CLEAR=0)");
85
Eric Moore793955f2007-01-29 09:42:20 -070086/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
87#define MPTSAS_MAX_LUN (16895)
88static int max_lun = MPTSAS_MAX_LUN;
89module_param(max_lun, int, 0);
90MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
91
Prakash, Sathyaf606f572007-08-14 16:12:53 +053092static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
93static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
94static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
95static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020096
Eric Mooreb506ade2007-01-29 09:45:37 -070097static void mptsas_hotplug_work(struct work_struct *work);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020098
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +053099static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
100 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200101{
Eric Moore29dd3602007-09-14 18:46:51 -0600102 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
103 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
104 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
105 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
106 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
107 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
108 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
109 ioc->name, phy_data->Port));
110 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
111 ioc->name, phy_data->PortFlags));
112 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
113 ioc->name, phy_data->PhyFlags));
114 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
115 ioc->name, phy_data->NegotiatedLinkRate));
116 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
117 "Controller PHY Device Info=0x%X\n", ioc->name,
118 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
119 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
120 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200121}
122
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530123static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200124{
125 __le64 sas_address;
126
127 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
128
Eric Moore29dd3602007-09-14 18:46:51 -0600129 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
130 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
131 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
132 "Attached Device Handle=0x%X\n", ioc->name,
133 le16_to_cpu(pg0->AttachedDevHandle)));
134 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
135 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
136 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
137 "Attached PHY Identifier=0x%X\n", ioc->name,
138 pg0->AttachedPhyIdentifier));
139 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
140 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
141 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
142 ioc->name, pg0->ProgrammedLinkRate));
143 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
144 ioc->name, pg0->ChangeCount));
145 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
146 ioc->name, le32_to_cpu(pg0->PhyInfo)));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200147}
148
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530149static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200150{
Eric Moore29dd3602007-09-14 18:46:51 -0600151 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
152 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
153 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
154 ioc->name, pg1->InvalidDwordCount));
155 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
156 "Running Disparity Error Count=0x%x\n", ioc->name,
157 pg1->RunningDisparityErrorCount));
158 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
159 "Loss Dword Synch Count=0x%x\n", ioc->name,
160 pg1->LossDwordSynchCount));
161 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
162 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
163 pg1->PhyResetProblemCount));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200164}
165
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530166static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200167{
168 __le64 sas_address;
169
170 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
171
Eric Moore29dd3602007-09-14 18:46:51 -0600172 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
173 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
174 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
175 ioc->name, le16_to_cpu(pg0->DevHandle)));
176 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
177 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
178 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
179 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
180 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
181 ioc->name, le16_to_cpu(pg0->Slot)));
182 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
183 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
184 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
185 ioc->name, pg0->TargetID));
186 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
187 ioc->name, pg0->Bus));
188 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
189 ioc->name, pg0->PhyNum));
190 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
191 ioc->name, le16_to_cpu(pg0->AccessStatus)));
192 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
193 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
194 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
195 ioc->name, le16_to_cpu(pg0->Flags)));
196 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
197 ioc->name, pg0->PhysicalPort));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200198}
199
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530200static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
Christoph Hellwigb5141122005-10-28 22:07:41 +0200201{
Eric Moore29dd3602007-09-14 18:46:51 -0600202 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
203 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
204 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
205 ioc->name, pg1->PhysicalPort));
206 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
207 ioc->name, pg1->PhyIdentifier));
208 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
209 ioc->name, pg1->NegotiatedLinkRate));
210 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
211 ioc->name, pg1->ProgrammedLinkRate));
212 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
213 ioc->name, pg1->HwLinkRate));
214 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
215 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
216 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
217 "Attached Device Handle=0x%X\n\n", ioc->name,
218 le16_to_cpu(pg1->AttachedDevHandle)));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200219}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200220
Christoph Hellwige3094442006-02-16 13:25:36 +0100221static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
222{
223 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
224 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
225}
226
227static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
228{
229 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
230 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
231}
232
Michael Reed77483692008-03-20 17:32:05 -0500233static struct mptsas_portinfo *
234mptsas_get_hba_portinfo(MPT_ADAPTER *ioc)
235{
236 struct list_head *head = &ioc->sas_topology;
237 struct mptsas_portinfo *pi = NULL;
238
239 /* always the first entry on sas_topology list */
240
241 if (!list_empty(head))
242 pi = list_entry(head->next, struct mptsas_portinfo, list);
243
244 return pi;
245}
246
Moore, Erice6b2d762006-03-14 09:14:24 -0700247/*
248 * mptsas_find_portinfo_by_handle
249 *
250 * This function should be called with the sas_topology_mutex already held
251 */
252static struct mptsas_portinfo *
253mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
254{
255 struct mptsas_portinfo *port_info, *rc=NULL;
256 int i;
257
258 list_for_each_entry(port_info, &ioc->sas_topology, list)
259 for (i = 0; i < port_info->num_phys; i++)
260 if (port_info->phy_info[i].identify.handle == handle) {
261 rc = port_info;
262 goto out;
263 }
264 out:
265 return rc;
266}
267
Moore, Ericbd23e942006-04-17 12:43:04 -0600268/*
269 * Returns true if there is a scsi end device
270 */
271static inline int
272mptsas_is_end_device(struct mptsas_devinfo * attached)
273{
Eric Moore547f9a22006-06-27 14:42:12 -0600274 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600275 (attached->device_info &
276 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
277 ((attached->device_info &
278 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
279 (attached->device_info &
280 MPI_SAS_DEVICE_INFO_STP_TARGET) |
281 (attached->device_info &
282 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
283 return 1;
284 else
285 return 0;
286}
287
Eric Moore547f9a22006-06-27 14:42:12 -0600288/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600289static void
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530290mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
Eric Moore547f9a22006-06-27 14:42:12 -0600291{
292 struct mptsas_portinfo *port_info;
293 struct mptsas_phyinfo *phy_info;
294 u8 i;
295
296 if (!port_details)
297 return;
298
299 port_info = port_details->port_info;
300 phy_info = port_info->phy_info;
301
Eric Moore29dd3602007-09-14 18:46:51 -0600302 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700303 "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
Eric Mooref99be432007-01-04 20:46:54 -0700304 port_details->num_phys, (unsigned long long)
305 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600306
307 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
308 if(phy_info->port_details != port_details)
309 continue;
310 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
311 phy_info->port_details = NULL;
312 }
313 kfree(port_details);
314}
315
316static inline struct sas_rphy *
317mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
318{
319 if (phy_info->port_details)
320 return phy_info->port_details->rphy;
321 else
322 return NULL;
323}
324
325static inline void
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530326mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
Eric Moore547f9a22006-06-27 14:42:12 -0600327{
328 if (phy_info->port_details) {
329 phy_info->port_details->rphy = rphy;
Eric Moore29dd3602007-09-14 18:46:51 -0600330 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
331 ioc->name, rphy));
Eric Moore547f9a22006-06-27 14:42:12 -0600332 }
333
Eric Moore547f9a22006-06-27 14:42:12 -0600334 if (rphy) {
Eric Moorec51d0be2007-09-29 10:17:21 -0600335 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
336 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
Eric Moore29dd3602007-09-14 18:46:51 -0600337 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
338 ioc->name, rphy, rphy->dev.release));
Eric Moore547f9a22006-06-27 14:42:12 -0600339 }
Eric Moore547f9a22006-06-27 14:42:12 -0600340}
341
342static inline struct sas_port *
343mptsas_get_port(struct mptsas_phyinfo *phy_info)
344{
345 if (phy_info->port_details)
346 return phy_info->port_details->port;
347 else
348 return NULL;
349}
350
351static inline void
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530352mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
Eric Moore547f9a22006-06-27 14:42:12 -0600353{
354 if (phy_info->port_details)
355 phy_info->port_details->port = port;
356
Eric Moore547f9a22006-06-27 14:42:12 -0600357 if (port) {
Eric Moorec51d0be2007-09-29 10:17:21 -0600358 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
359 &port->dev, MYIOC_s_FMT "add:", ioc->name));
Eric Moore29dd3602007-09-14 18:46:51 -0600360 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
361 ioc->name, port, port->dev.release));
Eric Moore547f9a22006-06-27 14:42:12 -0600362 }
Eric Moore547f9a22006-06-27 14:42:12 -0600363}
364
365static inline struct scsi_target *
366mptsas_get_starget(struct mptsas_phyinfo *phy_info)
367{
368 if (phy_info->port_details)
369 return phy_info->port_details->starget;
370 else
371 return NULL;
372}
373
374static inline void
375mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
376starget)
377{
378 if (phy_info->port_details)
379 phy_info->port_details->starget = starget;
380}
381
382
383/*
384 * mptsas_setup_wide_ports
385 *
386 * Updates for new and existing narrow/wide port configuration
387 * in the sas_topology
388 */
Eric Moore376ac832006-06-29 17:36:26 -0600389static void
Eric Moore547f9a22006-06-27 14:42:12 -0600390mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
391{
392 struct mptsas_portinfo_details * port_details;
393 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
394 u64 sas_address;
395 int i, j;
396
397 mutex_lock(&ioc->sas_topology_mutex);
398
399 phy_info = port_info->phy_info;
400 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
401 if (phy_info->attached.handle)
402 continue;
403 port_details = phy_info->port_details;
404 if (!port_details)
405 continue;
406 if (port_details->num_phys < 2)
407 continue;
408 /*
409 * Removing a phy from a port, letting the last
410 * phy be removed by firmware events.
411 */
Eric Moore29dd3602007-09-14 18:46:51 -0600412 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
413 "%s: [%p]: deleting phy = %d\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700414 ioc->name, __func__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600415 port_details->num_phys--;
416 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
417 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
418 sas_port_delete_phy(port_details->port, phy_info->phy);
419 phy_info->port_details = NULL;
420 }
421
422 /*
423 * Populate and refresh the tree
424 */
425 phy_info = port_info->phy_info;
426 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
427 sas_address = phy_info->attached.sas_address;
Eric Moore29dd3602007-09-14 18:46:51 -0600428 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
429 ioc->name, i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600430 if (!sas_address)
431 continue;
432 port_details = phy_info->port_details;
433 /*
434 * Forming a port
435 */
436 if (!port_details) {
437 port_details = kzalloc(sizeof(*port_details),
438 GFP_KERNEL);
439 if (!port_details)
440 goto out;
441 port_details->num_phys = 1;
442 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600443 if (phy_info->phy_id < 64 )
444 port_details->phy_bitmask |=
445 (1 << phy_info->phy_id);
446 phy_info->sas_port_add_phy=1;
Eric Moore29dd3602007-09-14 18:46:51 -0600447 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
Eric Mooref99be432007-01-04 20:46:54 -0700448 "phy_id=%d sas_address=0x%018llX\n",
Eric Moore29dd3602007-09-14 18:46:51 -0600449 ioc->name, i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600450 phy_info->port_details = port_details;
451 }
452
453 if (i == port_info->num_phys - 1)
454 continue;
455 phy_info_cmp = &port_info->phy_info[i + 1];
456 for (j = i + 1 ; j < port_info->num_phys ; j++,
457 phy_info_cmp++) {
458 if (!phy_info_cmp->attached.sas_address)
459 continue;
460 if (sas_address != phy_info_cmp->attached.sas_address)
461 continue;
462 if (phy_info_cmp->port_details == port_details )
463 continue;
Eric Moore29dd3602007-09-14 18:46:51 -0600464 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooref99be432007-01-04 20:46:54 -0700465 "\t\tphy_id=%d sas_address=0x%018llX\n",
Eric Moore29dd3602007-09-14 18:46:51 -0600466 ioc->name, j, (unsigned long long)
Eric Mooref99be432007-01-04 20:46:54 -0700467 phy_info_cmp->attached.sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600468 if (phy_info_cmp->port_details) {
469 port_details->rphy =
470 mptsas_get_rphy(phy_info_cmp);
471 port_details->port =
472 mptsas_get_port(phy_info_cmp);
473 port_details->starget =
474 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600475 port_details->num_phys =
476 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600477 if (!phy_info_cmp->port_details->num_phys)
478 kfree(phy_info_cmp->port_details);
479 } else
480 phy_info_cmp->sas_port_add_phy=1;
481 /*
482 * Adding a phy to a port
483 */
484 phy_info_cmp->port_details = port_details;
485 if (phy_info_cmp->phy_id < 64 )
486 port_details->phy_bitmask |=
487 (1 << phy_info_cmp->phy_id);
488 port_details->num_phys++;
489 }
490 }
491
492 out:
493
Eric Moore547f9a22006-06-27 14:42:12 -0600494 for (i = 0; i < port_info->num_phys; i++) {
495 port_details = port_info->phy_info[i].port_details;
496 if (!port_details)
497 continue;
Eric Moore29dd3602007-09-14 18:46:51 -0600498 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooref99be432007-01-04 20:46:54 -0700499 "%s: [%p]: phy_id=%02d num_phys=%02d "
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700500 "bitmask=0x%016llX\n", ioc->name, __func__,
Eric Mooref99be432007-01-04 20:46:54 -0700501 port_details, i, port_details->num_phys,
502 (unsigned long long)port_details->phy_bitmask));
Eric Moore29dd3602007-09-14 18:46:51 -0600503 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
504 ioc->name, port_details->port, port_details->rphy));
Eric Moore547f9a22006-06-27 14:42:12 -0600505 }
Eric Moore29dd3602007-09-14 18:46:51 -0600506 dsaswideprintk(ioc, printk("\n"));
Eric Moore547f9a22006-06-27 14:42:12 -0600507 mutex_unlock(&ioc->sas_topology_mutex);
508}
509
Eric Mooredf9e0622007-01-29 09:46:21 -0700510/**
511 * csmisas_find_vtarget
512 *
513 * @ioc
514 * @volume_id
515 * @volume_bus
516 *
517 **/
518static VirtTarget *
519mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
Eric Moore547f9a22006-06-27 14:42:12 -0600520{
Eric Mooredf9e0622007-01-29 09:46:21 -0700521 struct scsi_device *sdev;
Eric Moorea69de502007-09-14 18:48:19 -0600522 VirtDevice *vdevice;
Eric Mooredf9e0622007-01-29 09:46:21 -0700523 VirtTarget *vtarget = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -0600524
Eric Mooredf9e0622007-01-29 09:46:21 -0700525 shost_for_each_device(sdev, ioc->sh) {
Eric Moorea69de502007-09-14 18:48:19 -0600526 if ((vdevice = sdev->hostdata) == NULL)
Eric Mooredf9e0622007-01-29 09:46:21 -0700527 continue;
Eric Moorea69de502007-09-14 18:48:19 -0600528 if (vdevice->vtarget->id == id &&
529 vdevice->vtarget->channel == channel)
530 vtarget = vdevice->vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -0600531 }
Eric Mooredf9e0622007-01-29 09:46:21 -0700532 return vtarget;
533}
534
535/**
536 * mptsas_target_reset
537 *
538 * Issues TARGET_RESET to end device using handshaking method
539 *
540 * @ioc
541 * @channel
542 * @id
543 *
544 * Returns (1) success
545 * (0) failure
546 *
547 **/
548static int
549mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
550{
551 MPT_FRAME_HDR *mf;
552 SCSITaskMgmt_t *pScsiTm;
553
554 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530555 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700556 ioc->name,__func__, __LINE__));
Eric Mooredf9e0622007-01-29 09:46:21 -0700557 return 0;
558 }
559
560 /* Format the Request
561 */
562 pScsiTm = (SCSITaskMgmt_t *) mf;
563 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
564 pScsiTm->TargetID = id;
565 pScsiTm->Bus = channel;
566 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
567 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
568 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
569
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530570 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
Eric Mooredf9e0622007-01-29 09:46:21 -0700571
Prakash, Sathya7a195f42007-08-14 16:08:40 +0530572 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
Eric Mooredf9e0622007-01-29 09:46:21 -0700573
574 return 1;
575}
576
577/**
578 * mptsas_target_reset_queue
579 *
580 * Receive request for TARGET_RESET after recieving an firmware
581 * event NOT_RESPONDING_EVENT, then put command in link list
582 * and queue if task_queue already in use.
583 *
584 * @ioc
585 * @sas_event_data
586 *
587 **/
588static void
589mptsas_target_reset_queue(MPT_ADAPTER *ioc,
590 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
591{
Eric Mooree7eae9f2007-09-29 10:15:59 -0600592 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
Eric Mooredf9e0622007-01-29 09:46:21 -0700593 VirtTarget *vtarget = NULL;
594 struct mptsas_target_reset_event *target_reset_list;
595 u8 id, channel;
596
597 id = sas_event_data->TargetID;
598 channel = sas_event_data->Bus;
599
600 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
601 return;
602
603 vtarget->deleted = 1; /* block IO */
604
605 target_reset_list = kzalloc(sizeof(*target_reset_list),
606 GFP_ATOMIC);
607 if (!target_reset_list) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530608 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700609 ioc->name,__func__, __LINE__));
Eric Mooredf9e0622007-01-29 09:46:21 -0700610 return;
611 }
612
613 memcpy(&target_reset_list->sas_event_data, sas_event_data,
614 sizeof(*sas_event_data));
615 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
616
617 if (hd->resetPending)
618 return;
619
620 if (mptsas_target_reset(ioc, channel, id)) {
621 target_reset_list->target_reset_issued = 1;
622 hd->resetPending = 1;
623 }
624}
625
626/**
627 * mptsas_dev_reset_complete
628 *
629 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
630 * enable work queue to finish off removing device from upper layers.
631 * then send next TARGET_RESET in the queue.
632 *
633 * @ioc
634 *
635 **/
636static void
637mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
638{
Eric Mooree7eae9f2007-09-29 10:15:59 -0600639 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
Eric Mooredf9e0622007-01-29 09:46:21 -0700640 struct list_head *head = &hd->target_reset_list;
641 struct mptsas_target_reset_event *target_reset_list;
642 struct mptsas_hotplug_event *ev;
643 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
644 u8 id, channel;
645 __le64 sas_address;
646
647 if (list_empty(head))
648 return;
649
650 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
651
652 sas_event_data = &target_reset_list->sas_event_data;
653 id = sas_event_data->TargetID;
654 channel = sas_event_data->Bus;
655 hd->resetPending = 0;
656
657 /*
658 * retry target reset
659 */
660 if (!target_reset_list->target_reset_issued) {
661 if (mptsas_target_reset(ioc, channel, id)) {
662 target_reset_list->target_reset_issued = 1;
663 hd->resetPending = 1;
664 }
665 return;
666 }
667
668 /*
669 * enable work queue to remove device from upper layers
670 */
671 list_del(&target_reset_list->list);
672
673 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
674 if (!ev) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +0530675 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -0700676 ioc->name,__func__, __LINE__));
Eric Mooredf9e0622007-01-29 09:46:21 -0700677 return;
678 }
679
680 INIT_WORK(&ev->work, mptsas_hotplug_work);
681 ev->ioc = ioc;
682 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
683 ev->parent_handle =
684 le16_to_cpu(sas_event_data->ParentDevHandle);
685 ev->channel = channel;
686 ev->id =id;
687 ev->phy_id = sas_event_data->PhyNum;
688 memcpy(&sas_address, &sas_event_data->SASAddress,
689 sizeof(__le64));
690 ev->sas_address = le64_to_cpu(sas_address);
691 ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
692 ev->event_type = MPTSAS_DEL_DEVICE;
693 schedule_work(&ev->work);
694 kfree(target_reset_list);
695
696 /*
697 * issue target reset to next device in the queue
698 */
699
700 head = &hd->target_reset_list;
701 if (list_empty(head))
702 return;
703
704 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
705 list);
706
707 sas_event_data = &target_reset_list->sas_event_data;
708 id = sas_event_data->TargetID;
709 channel = sas_event_data->Bus;
710
711 if (mptsas_target_reset(ioc, channel, id)) {
712 target_reset_list->target_reset_issued = 1;
713 hd->resetPending = 1;
714 }
715}
716
717/**
718 * mptsas_taskmgmt_complete
719 *
720 * @ioc
721 * @mf
722 * @mr
723 *
724 **/
725static int
726mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
727{
728 mptsas_dev_reset_complete(ioc);
729 return mptscsih_taskmgmt_complete(ioc, mf, mr);
730}
731
732/**
733 * mptscsih_ioc_reset
734 *
735 * @ioc
736 * @reset_phase
737 *
738 **/
739static int
740mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
741{
Judith Lebzelterba76ef22007-03-09 13:07:44 -0800742 MPT_SCSI_HOST *hd;
Eric Mooredf9e0622007-01-29 09:46:21 -0700743 struct mptsas_target_reset_event *target_reset_list, *n;
744 int rc;
745
746 rc = mptscsih_ioc_reset(ioc, reset_phase);
747
748 if (ioc->bus_type != SAS)
749 goto out;
750
751 if (reset_phase != MPT_IOC_POST_RESET)
752 goto out;
753
Judith Lebzelterba76ef22007-03-09 13:07:44 -0800754 if (!ioc->sh || !ioc->sh->hostdata)
755 goto out;
Eric Mooree7eae9f2007-09-29 10:15:59 -0600756 hd = shost_priv(ioc->sh);
Judith Lebzelterba76ef22007-03-09 13:07:44 -0800757 if (!hd->ioc)
Eric Mooredf9e0622007-01-29 09:46:21 -0700758 goto out;
759
760 if (list_empty(&hd->target_reset_list))
761 goto out;
762
763 /* flush the target_reset_list */
764 list_for_each_entry_safe(target_reset_list, n,
765 &hd->target_reset_list, list) {
766 list_del(&target_reset_list->list);
767 kfree(target_reset_list);
768 }
769
770 out:
771 return rc;
Eric Moore547f9a22006-06-27 14:42:12 -0600772}
773
Christoph Hellwige3094442006-02-16 13:25:36 +0100774static int
Moore, Eric52435432006-03-14 09:14:15 -0700775mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100776 u32 form, u32 form_specific)
777{
778 ConfigExtendedPageHeader_t hdr;
779 CONFIGPARMS cfg;
780 SasEnclosurePage0_t *buffer;
781 dma_addr_t dma_handle;
782 int error;
783 __le64 le_identifier;
784
785 memset(&hdr, 0, sizeof(hdr));
786 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
787 hdr.PageNumber = 0;
788 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
789 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
790
791 cfg.cfghdr.ehdr = &hdr;
792 cfg.physAddr = -1;
793 cfg.pageAddr = form + form_specific;
794 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
795 cfg.dir = 0; /* read */
796 cfg.timeout = 10;
797
798 error = mpt_config(ioc, &cfg);
799 if (error)
800 goto out;
801 if (!hdr.ExtPageLength) {
802 error = -ENXIO;
803 goto out;
804 }
805
806 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
807 &dma_handle);
808 if (!buffer) {
809 error = -ENOMEM;
810 goto out;
811 }
812
813 cfg.physAddr = dma_handle;
814 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
815
816 error = mpt_config(ioc, &cfg);
817 if (error)
818 goto out_free_consistent;
819
820 /* save config data */
821 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
822 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
823 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
824 enclosure->flags = le16_to_cpu(buffer->Flags);
825 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
826 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
827 enclosure->start_id = buffer->StartTargetID;
828 enclosure->start_channel = buffer->StartBus;
829 enclosure->sep_id = buffer->SEPTargetID;
830 enclosure->sep_channel = buffer->SEPBus;
831
832 out_free_consistent:
833 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
834 buffer, dma_handle);
835 out:
836 return error;
837}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200838
James Bottomleyf013db32006-03-18 14:54:36 -0600839static int
840mptsas_slave_configure(struct scsi_device *sdev)
841{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600842
James Bottomleye8bf3942006-07-11 17:49:34 -0400843 if (sdev->channel == MPTSAS_RAID_CHANNEL)
844 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600845
James Bottomleye8bf3942006-07-11 17:49:34 -0400846 sas_read_port_mode_page(sdev);
847
848 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600849 return mptscsih_slave_configure(sdev);
850}
851
Eric Moore547f9a22006-06-27 14:42:12 -0600852static int
853mptsas_target_alloc(struct scsi_target *starget)
854{
855 struct Scsi_Host *host = dev_to_shost(&starget->dev);
Eric Mooree7eae9f2007-09-29 10:15:59 -0600856 MPT_SCSI_HOST *hd = shost_priv(host);
Eric Moore547f9a22006-06-27 14:42:12 -0600857 VirtTarget *vtarget;
Eric Moore793955f2007-01-29 09:42:20 -0700858 u8 id, channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600859 struct sas_rphy *rphy;
860 struct mptsas_portinfo *p;
861 int i;
Eric Mooree80b0022007-09-14 18:49:03 -0600862 MPT_ADAPTER *ioc = hd->ioc;
Eric Moore547f9a22006-06-27 14:42:12 -0600863
864 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
865 if (!vtarget)
866 return -ENOMEM;
867
868 vtarget->starget = starget;
Eric Mooree80b0022007-09-14 18:49:03 -0600869 vtarget->ioc_id = ioc->id;
Eric Moore793955f2007-01-29 09:42:20 -0700870 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
871 id = starget->id;
Eric Moore547f9a22006-06-27 14:42:12 -0600872 channel = 0;
873
Eric Moore793955f2007-01-29 09:42:20 -0700874 /*
875 * RAID volumes placed beyond the last expected port.
876 */
877 if (starget->channel == MPTSAS_RAID_CHANNEL) {
Eric Mooree80b0022007-09-14 18:49:03 -0600878 for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
879 if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
880 channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
Eric Moore547f9a22006-06-27 14:42:12 -0600881 goto out;
Eric Moore793955f2007-01-29 09:42:20 -0700882 }
Eric Moore547f9a22006-06-27 14:42:12 -0600883
884 rphy = dev_to_rphy(starget->dev.parent);
Eric Mooree80b0022007-09-14 18:49:03 -0600885 mutex_lock(&ioc->sas_topology_mutex);
886 list_for_each_entry(p, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -0600887 for (i = 0; i < p->num_phys; i++) {
888 if (p->phy_info[i].attached.sas_address !=
889 rphy->identify.sas_address)
890 continue;
Eric Moore793955f2007-01-29 09:42:20 -0700891 id = p->phy_info[i].attached.id;
Eric Moore547f9a22006-06-27 14:42:12 -0600892 channel = p->phy_info[i].attached.channel;
893 mptsas_set_starget(&p->phy_info[i], starget);
894
895 /*
896 * Exposing hidden raid components
897 */
Eric Mooree80b0022007-09-14 18:49:03 -0600898 if (mptscsih_is_phys_disk(ioc, channel, id)) {
899 id = mptscsih_raid_id_to_num(ioc,
Eric Moore793955f2007-01-29 09:42:20 -0700900 channel, id);
Eric Moore547f9a22006-06-27 14:42:12 -0600901 vtarget->tflags |=
902 MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Mooreb506ade2007-01-29 09:45:37 -0700903 p->phy_info[i].attached.phys_disk_num = id;
Eric Moore547f9a22006-06-27 14:42:12 -0600904 }
Eric Mooree80b0022007-09-14 18:49:03 -0600905 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -0600906 goto out;
907 }
908 }
Eric Mooree80b0022007-09-14 18:49:03 -0600909 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -0600910
911 kfree(vtarget);
912 return -ENXIO;
913
914 out:
Eric Moore793955f2007-01-29 09:42:20 -0700915 vtarget->id = id;
916 vtarget->channel = channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600917 starget->hostdata = vtarget;
918 return 0;
919}
920
921static void
922mptsas_target_destroy(struct scsi_target *starget)
923{
924 struct Scsi_Host *host = dev_to_shost(&starget->dev);
Eric Mooree7eae9f2007-09-29 10:15:59 -0600925 MPT_SCSI_HOST *hd = shost_priv(host);
Eric Moore547f9a22006-06-27 14:42:12 -0600926 struct sas_rphy *rphy;
927 struct mptsas_portinfo *p;
928 int i;
Eric Mooree80b0022007-09-14 18:49:03 -0600929 MPT_ADAPTER *ioc = hd->ioc;
Eric Moore547f9a22006-06-27 14:42:12 -0600930
931 if (!starget->hostdata)
932 return;
933
James Bottomleye8bf3942006-07-11 17:49:34 -0400934 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600935 goto out;
936
937 rphy = dev_to_rphy(starget->dev.parent);
Eric Mooree80b0022007-09-14 18:49:03 -0600938 list_for_each_entry(p, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -0600939 for (i = 0; i < p->num_phys; i++) {
940 if (p->phy_info[i].attached.sas_address !=
941 rphy->identify.sas_address)
942 continue;
943 mptsas_set_starget(&p->phy_info[i], NULL);
944 goto out;
945 }
946 }
947
948 out:
949 kfree(starget->hostdata);
950 starget->hostdata = NULL;
951}
952
953
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200954static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700955mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200956{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700957 struct Scsi_Host *host = sdev->host;
Eric Mooree7eae9f2007-09-29 10:15:59 -0600958 MPT_SCSI_HOST *hd = shost_priv(host);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200959 struct sas_rphy *rphy;
960 struct mptsas_portinfo *p;
Eric Moorea69de502007-09-14 18:48:19 -0600961 VirtDevice *vdevice;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700962 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600963 int i;
Eric Mooree80b0022007-09-14 18:49:03 -0600964 MPT_ADAPTER *ioc = hd->ioc;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200965
Eric Moorea69de502007-09-14 18:48:19 -0600966 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
967 if (!vdevice) {
Eric Moore547f9a22006-06-27 14:42:12 -0600968 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Eric Mooree80b0022007-09-14 18:49:03 -0600969 ioc->name, sizeof(VirtDevice));
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200970 return -ENOMEM;
971 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700972 starget = scsi_target(sdev);
Eric Moorea69de502007-09-14 18:48:19 -0600973 vdevice->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200974
James Bottomleye8bf3942006-07-11 17:49:34 -0400975 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -0700976 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700977
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700978 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Eric Mooree80b0022007-09-14 18:49:03 -0600979 mutex_lock(&ioc->sas_topology_mutex);
980 list_for_each_entry(p, &ioc->sas_topology, list) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200981 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600982 if (p->phy_info[i].attached.sas_address !=
983 rphy->identify.sas_address)
984 continue;
Eric Moorea69de502007-09-14 18:48:19 -0600985 vdevice->lun = sdev->lun;
Eric Moore547f9a22006-06-27 14:42:12 -0600986 /*
987 * Exposing hidden raid components
988 */
Eric Mooree80b0022007-09-14 18:49:03 -0600989 if (mptscsih_is_phys_disk(ioc,
Eric Moore793955f2007-01-29 09:42:20 -0700990 p->phy_info[i].attached.channel,
991 p->phy_info[i].attached.id))
Eric Moore547f9a22006-06-27 14:42:12 -0600992 sdev->no_uld_attach = 1;
Eric Mooree80b0022007-09-14 18:49:03 -0600993 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -0600994 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200995 }
996 }
Eric Mooree80b0022007-09-14 18:49:03 -0600997 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200998
Eric Moorea69de502007-09-14 18:48:19 -0600999 kfree(vdevice);
Christoph Hellwig23f236e2006-01-30 19:00:43 +01001000 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001001
1002 out:
Eric Moorea69de502007-09-14 18:48:19 -06001003 vdevice->vtarget->num_luns++;
1004 sdev->hostdata = vdevice;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001005 return 0;
1006}
1007
Eric Moore547f9a22006-06-27 14:42:12 -06001008static int
1009mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001010{
Kashyap, Desai7b5a65b2009-05-29 16:38:14 +05301011 MPT_SCSI_HOST *hd;
1012 MPT_ADAPTER *ioc;
Eric Moorea69de502007-09-14 18:48:19 -06001013 VirtDevice *vdevice = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001014
Eric Moorea69de502007-09-14 18:48:19 -06001015 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
Eric Moore547f9a22006-06-27 14:42:12 -06001016 SCpnt->result = DID_NO_CONNECT << 16;
1017 done(SCpnt);
1018 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -07001019 }
Eric Moore547f9a22006-06-27 14:42:12 -06001020
Kashyap, Desai7b5a65b2009-05-29 16:38:14 +05301021 hd = shost_priv(SCpnt->device->host);
1022 ioc = hd->ioc;
1023
1024 if (ioc->sas_discovery_quiesce_io)
1025 return SCSI_MLQUEUE_HOST_BUSY;
1026
Eric Moore793955f2007-01-29 09:42:20 -07001027// scsi_print_command(SCpnt);
1028
Eric Moore547f9a22006-06-27 14:42:12 -06001029 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001030}
1031
Eric Moore547f9a22006-06-27 14:42:12 -06001032
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001033static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -07001034 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001035 .proc_name = "mptsas",
1036 .proc_info = mptscsih_proc_info,
1037 .name = "MPT SPI Host",
1038 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -06001039 .queuecommand = mptsas_qcmd,
1040 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001041 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -06001042 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -06001043 .target_destroy = mptsas_target_destroy,
1044 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001045 .change_queue_depth = mptscsih_change_queue_depth,
1046 .eh_abort_handler = mptscsih_abort,
1047 .eh_device_reset_handler = mptscsih_dev_reset,
1048 .eh_bus_reset_handler = mptscsih_bus_reset,
1049 .eh_host_reset_handler = mptscsih_host_reset,
1050 .bios_param = mptscsih_bios_param,
1051 .can_queue = MPT_FC_CAN_QUEUE,
1052 .this_id = -1,
1053 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1054 .max_sectors = 8192,
1055 .cmd_per_lun = 7,
1056 .use_clustering = ENABLE_CLUSTERING,
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301057 .shost_attrs = mptscsih_host_attrs,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001058};
1059
Christoph Hellwigb5141122005-10-28 22:07:41 +02001060static int mptsas_get_linkerrors(struct sas_phy *phy)
1061{
1062 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1063 ConfigExtendedPageHeader_t hdr;
1064 CONFIGPARMS cfg;
1065 SasPhyPage1_t *buffer;
1066 dma_addr_t dma_handle;
1067 int error;
1068
James Bottomleyf4ad7b52006-08-25 13:48:18 -05001069 /* FIXME: only have link errors on local phys */
1070 if (!scsi_is_sas_phy_local(phy))
1071 return -EINVAL;
1072
Christoph Hellwigb5141122005-10-28 22:07:41 +02001073 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1074 hdr.ExtPageLength = 0;
1075 hdr.PageNumber = 1 /* page number 1*/;
1076 hdr.Reserved1 = 0;
1077 hdr.Reserved2 = 0;
1078 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1079 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1080
1081 cfg.cfghdr.ehdr = &hdr;
1082 cfg.physAddr = -1;
1083 cfg.pageAddr = phy->identify.phy_identifier;
1084 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1085 cfg.dir = 0; /* read */
1086 cfg.timeout = 10;
1087
1088 error = mpt_config(ioc, &cfg);
1089 if (error)
1090 return error;
1091 if (!hdr.ExtPageLength)
1092 return -ENXIO;
1093
1094 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1095 &dma_handle);
1096 if (!buffer)
1097 return -ENOMEM;
1098
1099 cfg.physAddr = dma_handle;
1100 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1101
1102 error = mpt_config(ioc, &cfg);
1103 if (error)
1104 goto out_free_consistent;
1105
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301106 mptsas_print_phy_pg1(ioc, buffer);
Christoph Hellwigb5141122005-10-28 22:07:41 +02001107
1108 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1109 phy->running_disparity_error_count =
1110 le32_to_cpu(buffer->RunningDisparityErrorCount);
1111 phy->loss_of_dword_sync_count =
1112 le32_to_cpu(buffer->LossDwordSynchCount);
1113 phy->phy_reset_problem_count =
1114 le32_to_cpu(buffer->PhyResetProblemCount);
1115
1116 out_free_consistent:
1117 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1118 buffer, dma_handle);
1119 return error;
1120}
1121
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001122static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1123 MPT_FRAME_HDR *reply)
1124{
Kashyap, Desaif0f09d32009-05-29 16:40:57 +05301125 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001126 if (reply != NULL) {
Kashyap, Desaif0f09d32009-05-29 16:40:57 +05301127 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001128 memcpy(ioc->sas_mgmt.reply, reply,
1129 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1130 }
1131 complete(&ioc->sas_mgmt.done);
1132 return 1;
1133}
1134
1135static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1136{
1137 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1138 SasIoUnitControlRequest_t *req;
1139 SasIoUnitControlReply_t *reply;
1140 MPT_FRAME_HDR *mf;
1141 MPIHeader_t *hdr;
1142 unsigned long timeleft;
1143 int error = -ERESTARTSYS;
1144
James Bottomleyf4ad7b52006-08-25 13:48:18 -05001145 /* FIXME: fusion doesn't allow non-local phy reset */
1146 if (!scsi_is_sas_phy_local(phy))
1147 return -EINVAL;
1148
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001149 /* not implemented for expanders */
1150 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1151 return -ENXIO;
1152
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001153 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001154 goto out;
1155
1156 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1157 if (!mf) {
1158 error = -ENOMEM;
1159 goto out_unlock;
1160 }
1161
1162 hdr = (MPIHeader_t *) mf;
1163 req = (SasIoUnitControlRequest_t *)mf;
1164 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
1165 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
1166 req->MsgContext = hdr->MsgContext;
1167 req->Operation = hard_reset ?
1168 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
1169 req->PhyNum = phy->identify.phy_identifier;
1170
1171 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1172
1173 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
1174 10 * HZ);
1175 if (!timeleft) {
1176 /* On timeout reset the board */
1177 mpt_free_msg_frame(ioc, mf);
1178 mpt_HardResetHandler(ioc, CAN_SLEEP);
1179 error = -ETIMEDOUT;
1180 goto out_unlock;
1181 }
1182
1183 /* a reply frame is expected */
1184 if ((ioc->sas_mgmt.status &
Kashyap, Desaif0f09d32009-05-29 16:40:57 +05301185 MPT_MGMT_STATUS_RF_VALID) == 0) {
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001186 error = -ENXIO;
1187 goto out_unlock;
1188 }
1189
1190 /* process the completed Reply Message Frame */
1191 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
1192 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
Eric Moore29dd3602007-09-14 18:46:51 -06001193 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001194 ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001195 error = -ENXIO;
1196 goto out_unlock;
1197 }
1198
1199 error = 0;
1200
1201 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001202 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001203 out:
1204 return error;
1205}
Christoph Hellwigb5141122005-10-28 22:07:41 +02001206
Christoph Hellwige3094442006-02-16 13:25:36 +01001207static int
1208mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1209{
1210 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1211 int i, error;
1212 struct mptsas_portinfo *p;
1213 struct mptsas_enclosure enclosure_info;
1214 u64 enclosure_handle;
1215
1216 mutex_lock(&ioc->sas_topology_mutex);
1217 list_for_each_entry(p, &ioc->sas_topology, list) {
1218 for (i = 0; i < p->num_phys; i++) {
1219 if (p->phy_info[i].attached.sas_address ==
1220 rphy->identify.sas_address) {
1221 enclosure_handle = p->phy_info[i].
1222 attached.handle_enclosure;
1223 goto found_info;
1224 }
1225 }
1226 }
1227 mutex_unlock(&ioc->sas_topology_mutex);
1228 return -ENXIO;
1229
1230 found_info:
1231 mutex_unlock(&ioc->sas_topology_mutex);
1232 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001233 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001234 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1235 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1236 if (!error)
1237 *identifier = enclosure_info.enclosure_logical_id;
1238 return error;
1239}
1240
1241static int
1242mptsas_get_bay_identifier(struct sas_rphy *rphy)
1243{
1244 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1245 struct mptsas_portinfo *p;
1246 int i, rc;
1247
1248 mutex_lock(&ioc->sas_topology_mutex);
1249 list_for_each_entry(p, &ioc->sas_topology, list) {
1250 for (i = 0; i < p->num_phys; i++) {
1251 if (p->phy_info[i].attached.sas_address ==
1252 rphy->identify.sas_address) {
1253 rc = p->phy_info[i].attached.slot;
1254 goto out;
1255 }
1256 }
1257 }
1258 rc = -ENXIO;
1259 out:
1260 mutex_unlock(&ioc->sas_topology_mutex);
1261 return rc;
1262}
1263
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001264static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1265 struct request *req)
1266{
1267 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
1268 MPT_FRAME_HDR *mf;
1269 SmpPassthroughRequest_t *smpreq;
1270 struct request *rsp = req->next_rq;
1271 int ret;
1272 int flagsLength;
1273 unsigned long timeleft;
1274 char *psge;
1275 dma_addr_t dma_addr_in = 0;
1276 dma_addr_t dma_addr_out = 0;
1277 u64 sas_address = 0;
1278
1279 if (!rsp) {
Eric Moore29dd3602007-09-14 18:46:51 -06001280 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001281 ioc->name, __func__);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001282 return -EINVAL;
1283 }
1284
1285 /* do we need to support multiple segments? */
1286 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
Eric Moore29dd3602007-09-14 18:46:51 -06001287 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001288 ioc->name, __func__, req->bio->bi_vcnt, req->data_len,
Eric Moore29dd3602007-09-14 18:46:51 -06001289 rsp->bio->bi_vcnt, rsp->data_len);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001290 return -EINVAL;
1291 }
1292
1293 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
1294 if (ret)
1295 goto out;
1296
1297 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1298 if (!mf) {
1299 ret = -ENOMEM;
1300 goto out_unlock;
1301 }
1302
1303 smpreq = (SmpPassthroughRequest_t *)mf;
1304 memset(smpreq, 0, sizeof(*smpreq));
1305
1306 smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
1307 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
1308
1309 if (rphy)
1310 sas_address = rphy->identify.sas_address;
1311 else {
1312 struct mptsas_portinfo *port_info;
1313
1314 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05001315 port_info = mptsas_get_hba_portinfo(ioc);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001316 if (port_info && port_info->phy_info)
1317 sas_address =
1318 port_info->phy_info[0].phy->identify.sas_address;
1319 mutex_unlock(&ioc->sas_topology_mutex);
1320 }
1321
1322 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
1323
1324 psge = (char *)
1325 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
1326
1327 /* request */
1328 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1329 MPI_SGE_FLAGS_END_OF_BUFFER |
Kashyap, Desai14d0f0b2009-05-29 16:37:04 +05301330 MPI_SGE_FLAGS_DIRECTION)
1331 << MPI_SGE_FLAGS_SHIFT;
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001332 flagsLength |= (req->data_len - 4);
1333
1334 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
1335 req->data_len, PCI_DMA_BIDIRECTIONAL);
1336 if (!dma_addr_out)
1337 goto put_mf;
Kashyap, Desai14d0f0b2009-05-29 16:37:04 +05301338 ioc->add_sge(psge, flagsLength, dma_addr_out);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001339 psge += (sizeof(u32) + sizeof(dma_addr_t));
1340
1341 /* response */
1342 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
1343 flagsLength |= rsp->data_len + 4;
1344 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
1345 rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1346 if (!dma_addr_in)
1347 goto unmap;
Kashyap, Desai14d0f0b2009-05-29 16:37:04 +05301348 ioc->add_sge(psge, flagsLength, dma_addr_in);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001349
1350 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1351
1352 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
1353 if (!timeleft) {
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001354 printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __func__);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001355 /* On timeout reset the board */
1356 mpt_HardResetHandler(ioc, CAN_SLEEP);
1357 ret = -ETIMEDOUT;
1358 goto unmap;
1359 }
1360 mf = NULL;
1361
Kashyap, Desaif0f09d32009-05-29 16:40:57 +05301362 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001363 SmpPassthroughReply_t *smprep;
1364
1365 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
1366 memcpy(req->sense, smprep, sizeof(*smprep));
1367 req->sense_len = sizeof(*smprep);
FUJITA Tomonori38b31672007-12-30 19:34:52 +09001368 req->data_len = 0;
1369 rsp->data_len -= smprep->ResponseDataLength;
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001370 } else {
Eric Moore29dd3602007-09-14 18:46:51 -06001371 printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n",
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07001372 ioc->name, __func__);
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001373 ret = -ENXIO;
1374 }
1375unmap:
1376 if (dma_addr_out)
1377 pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
1378 PCI_DMA_BIDIRECTIONAL);
1379 if (dma_addr_in)
1380 pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
1381 PCI_DMA_BIDIRECTIONAL);
1382put_mf:
1383 if (mf)
1384 mpt_free_msg_frame(ioc, mf);
1385out_unlock:
1386 mutex_unlock(&ioc->sas_mgmt.mutex);
1387out:
1388 return ret;
1389}
1390
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001391static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001392 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001393 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1394 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001395 .phy_reset = mptsas_phy_reset,
FUJITA Tomonori159e36f2007-07-30 11:10:07 -06001396 .smp_handler = mptsas_smp_handler,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001397};
1398
1399static struct scsi_transport_template *mptsas_transport_template;
1400
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001401static int
1402mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1403{
1404 ConfigExtendedPageHeader_t hdr;
1405 CONFIGPARMS cfg;
1406 SasIOUnitPage0_t *buffer;
1407 dma_addr_t dma_handle;
1408 int error, i;
1409
1410 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1411 hdr.ExtPageLength = 0;
1412 hdr.PageNumber = 0;
1413 hdr.Reserved1 = 0;
1414 hdr.Reserved2 = 0;
1415 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1416 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1417
1418 cfg.cfghdr.ehdr = &hdr;
1419 cfg.physAddr = -1;
1420 cfg.pageAddr = 0;
1421 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1422 cfg.dir = 0; /* read */
1423 cfg.timeout = 10;
1424
1425 error = mpt_config(ioc, &cfg);
1426 if (error)
1427 goto out;
1428 if (!hdr.ExtPageLength) {
1429 error = -ENXIO;
1430 goto out;
1431 }
1432
1433 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1434 &dma_handle);
1435 if (!buffer) {
1436 error = -ENOMEM;
1437 goto out;
1438 }
1439
1440 cfg.physAddr = dma_handle;
1441 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1442
1443 error = mpt_config(ioc, &cfg);
1444 if (error)
1445 goto out_free_consistent;
1446
1447 port_info->num_phys = buffer->NumPhys;
1448 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001449 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001450 if (!port_info->phy_info) {
1451 error = -ENOMEM;
1452 goto out_free_consistent;
1453 }
1454
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301455 ioc->nvdata_version_persistent =
1456 le16_to_cpu(buffer->NvdataVersionPersistent);
1457 ioc->nvdata_version_default =
1458 le16_to_cpu(buffer->NvdataVersionDefault);
1459
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001460 for (i = 0; i < port_info->num_phys; i++) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301461 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001462 port_info->phy_info[i].phy_id = i;
1463 port_info->phy_info[i].port_id =
1464 buffer->PhyData[i].Port;
1465 port_info->phy_info[i].negotiated_link_rate =
1466 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001467 port_info->phy_info[i].portinfo = port_info;
Eric Moore2ecce492007-01-29 09:47:08 -07001468 port_info->phy_info[i].handle =
1469 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001470 }
1471
1472 out_free_consistent:
1473 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1474 buffer, dma_handle);
1475 out:
1476 return error;
1477}
1478
1479static int
Prakash, Sathyaedb90682007-07-17 14:39:14 +05301480mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
1481{
1482 ConfigExtendedPageHeader_t hdr;
1483 CONFIGPARMS cfg;
1484 SasIOUnitPage1_t *buffer;
1485 dma_addr_t dma_handle;
1486 int error;
1487 u16 device_missing_delay;
1488
1489 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
1490 memset(&cfg, 0, sizeof(CONFIGPARMS));
1491
1492 cfg.cfghdr.ehdr = &hdr;
1493 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1494 cfg.timeout = 10;
1495 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1496 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1497 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
1498 cfg.cfghdr.ehdr->PageNumber = 1;
1499
1500 error = mpt_config(ioc, &cfg);
1501 if (error)
1502 goto out;
1503 if (!hdr.ExtPageLength) {
1504 error = -ENXIO;
1505 goto out;
1506 }
1507
1508 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1509 &dma_handle);
1510 if (!buffer) {
1511 error = -ENOMEM;
1512 goto out;
1513 }
1514
1515 cfg.physAddr = dma_handle;
1516 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1517
1518 error = mpt_config(ioc, &cfg);
1519 if (error)
1520 goto out_free_consistent;
1521
1522 ioc->io_missing_delay =
1523 le16_to_cpu(buffer->IODeviceMissingDelay);
1524 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
1525 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
1526 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
1527 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1528
1529 out_free_consistent:
1530 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1531 buffer, dma_handle);
1532 out:
1533 return error;
1534}
1535
1536static int
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001537mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1538 u32 form, u32 form_specific)
1539{
1540 ConfigExtendedPageHeader_t hdr;
1541 CONFIGPARMS cfg;
1542 SasPhyPage0_t *buffer;
1543 dma_addr_t dma_handle;
1544 int error;
1545
1546 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1547 hdr.ExtPageLength = 0;
1548 hdr.PageNumber = 0;
1549 hdr.Reserved1 = 0;
1550 hdr.Reserved2 = 0;
1551 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1552 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1553
1554 cfg.cfghdr.ehdr = &hdr;
1555 cfg.dir = 0; /* read */
1556 cfg.timeout = 10;
1557
1558 /* Get Phy Pg 0 for each Phy. */
1559 cfg.physAddr = -1;
1560 cfg.pageAddr = form + form_specific;
1561 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1562
1563 error = mpt_config(ioc, &cfg);
1564 if (error)
1565 goto out;
1566
1567 if (!hdr.ExtPageLength) {
1568 error = -ENXIO;
1569 goto out;
1570 }
1571
1572 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1573 &dma_handle);
1574 if (!buffer) {
1575 error = -ENOMEM;
1576 goto out;
1577 }
1578
1579 cfg.physAddr = dma_handle;
1580 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1581
1582 error = mpt_config(ioc, &cfg);
1583 if (error)
1584 goto out_free_consistent;
1585
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301586 mptsas_print_phy_pg0(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001587
1588 phy_info->hw_link_rate = buffer->HwLinkRate;
1589 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1590 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1591 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1592
1593 out_free_consistent:
1594 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1595 buffer, dma_handle);
1596 out:
1597 return error;
1598}
1599
1600static int
1601mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1602 u32 form, u32 form_specific)
1603{
1604 ConfigExtendedPageHeader_t hdr;
1605 CONFIGPARMS cfg;
1606 SasDevicePage0_t *buffer;
1607 dma_addr_t dma_handle;
1608 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001609 int error=0;
1610
1611 if (ioc->sas_discovery_runtime &&
1612 mptsas_is_end_device(device_info))
1613 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001614
1615 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1616 hdr.ExtPageLength = 0;
1617 hdr.PageNumber = 0;
1618 hdr.Reserved1 = 0;
1619 hdr.Reserved2 = 0;
1620 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1621 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1622
1623 cfg.cfghdr.ehdr = &hdr;
1624 cfg.pageAddr = form + form_specific;
1625 cfg.physAddr = -1;
1626 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1627 cfg.dir = 0; /* read */
1628 cfg.timeout = 10;
1629
Moore, Ericdb9c9172006-03-14 09:14:18 -07001630 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001631 error = mpt_config(ioc, &cfg);
1632 if (error)
1633 goto out;
1634 if (!hdr.ExtPageLength) {
1635 error = -ENXIO;
1636 goto out;
1637 }
1638
1639 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1640 &dma_handle);
1641 if (!buffer) {
1642 error = -ENOMEM;
1643 goto out;
1644 }
1645
1646 cfg.physAddr = dma_handle;
1647 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1648
1649 error = mpt_config(ioc, &cfg);
1650 if (error)
1651 goto out_free_consistent;
1652
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301653 mptsas_print_device_pg0(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001654
1655 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001656 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001657 device_info->handle_enclosure =
1658 le16_to_cpu(buffer->EnclosureHandle);
1659 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001660 device_info->phy_id = buffer->PhyNum;
1661 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001662 device_info->id = buffer->TargetID;
Eric Mooreb506ade2007-01-29 09:45:37 -07001663 device_info->phys_disk_num = ~0;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001664 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001665 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1666 device_info->sas_address = le64_to_cpu(sas_address);
1667 device_info->device_info =
1668 le32_to_cpu(buffer->DeviceInfo);
1669
1670 out_free_consistent:
1671 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1672 buffer, dma_handle);
1673 out:
1674 return error;
1675}
1676
1677static int
1678mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1679 u32 form, u32 form_specific)
1680{
1681 ConfigExtendedPageHeader_t hdr;
1682 CONFIGPARMS cfg;
1683 SasExpanderPage0_t *buffer;
1684 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001685 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001686
1687 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1688 hdr.ExtPageLength = 0;
1689 hdr.PageNumber = 0;
1690 hdr.Reserved1 = 0;
1691 hdr.Reserved2 = 0;
1692 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1693 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1694
1695 cfg.cfghdr.ehdr = &hdr;
1696 cfg.physAddr = -1;
1697 cfg.pageAddr = form + form_specific;
1698 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1699 cfg.dir = 0; /* read */
1700 cfg.timeout = 10;
1701
Moore, Ericdb9c9172006-03-14 09:14:18 -07001702 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001703 error = mpt_config(ioc, &cfg);
1704 if (error)
1705 goto out;
1706
1707 if (!hdr.ExtPageLength) {
1708 error = -ENXIO;
1709 goto out;
1710 }
1711
1712 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1713 &dma_handle);
1714 if (!buffer) {
1715 error = -ENOMEM;
1716 goto out;
1717 }
1718
1719 cfg.physAddr = dma_handle;
1720 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1721
1722 error = mpt_config(ioc, &cfg);
1723 if (error)
1724 goto out_free_consistent;
1725
Krzysztof Oledzki51f39ea2008-03-04 14:56:23 -08001726 if (!buffer->NumPhys) {
1727 error = -ENODEV;
1728 goto out_free_consistent;
1729 }
1730
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001731 /* save config data */
1732 port_info->num_phys = buffer->NumPhys;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001733 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001734 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001735 if (!port_info->phy_info) {
1736 error = -ENOMEM;
1737 goto out_free_consistent;
1738 }
1739
Eric Moore2ecce492007-01-29 09:47:08 -07001740 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001741 port_info->phy_info[i].portinfo = port_info;
Eric Moore2ecce492007-01-29 09:47:08 -07001742 port_info->phy_info[i].handle =
1743 le16_to_cpu(buffer->DevHandle);
1744 }
Eric Moore547f9a22006-06-27 14:42:12 -06001745
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001746 out_free_consistent:
1747 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1748 buffer, dma_handle);
1749 out:
1750 return error;
1751}
1752
1753static int
1754mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1755 u32 form, u32 form_specific)
1756{
1757 ConfigExtendedPageHeader_t hdr;
1758 CONFIGPARMS cfg;
1759 SasExpanderPage1_t *buffer;
1760 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001761 int error=0;
1762
1763 if (ioc->sas_discovery_runtime &&
1764 mptsas_is_end_device(&phy_info->attached))
1765 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001766
1767 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1768 hdr.ExtPageLength = 0;
1769 hdr.PageNumber = 1;
1770 hdr.Reserved1 = 0;
1771 hdr.Reserved2 = 0;
1772 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1773 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1774
1775 cfg.cfghdr.ehdr = &hdr;
1776 cfg.physAddr = -1;
1777 cfg.pageAddr = form + form_specific;
1778 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1779 cfg.dir = 0; /* read */
1780 cfg.timeout = 10;
1781
1782 error = mpt_config(ioc, &cfg);
1783 if (error)
1784 goto out;
1785
1786 if (!hdr.ExtPageLength) {
1787 error = -ENXIO;
1788 goto out;
1789 }
1790
1791 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1792 &dma_handle);
1793 if (!buffer) {
1794 error = -ENOMEM;
1795 goto out;
1796 }
1797
1798 cfg.physAddr = dma_handle;
1799 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1800
1801 error = mpt_config(ioc, &cfg);
1802 if (error)
1803 goto out_free_consistent;
1804
1805
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05301806 mptsas_print_expander_pg1(ioc, buffer);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001807
1808 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001809 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001810 phy_info->port_id = buffer->PhysicalPort;
1811 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1812 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1813 phy_info->hw_link_rate = buffer->HwLinkRate;
1814 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1815 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1816
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001817 out_free_consistent:
1818 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1819 buffer, dma_handle);
1820 out:
1821 return error;
1822}
1823
1824static void
1825mptsas_parse_device_info(struct sas_identify *identify,
1826 struct mptsas_devinfo *device_info)
1827{
1828 u16 protocols;
1829
1830 identify->sas_address = device_info->sas_address;
1831 identify->phy_identifier = device_info->phy_id;
1832
1833 /*
1834 * Fill in Phy Initiator Port Protocol.
1835 * Bits 6:3, more than one bit can be set, fall through cases.
1836 */
1837 protocols = device_info->device_info & 0x78;
1838 identify->initiator_port_protocols = 0;
1839 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1840 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1841 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1842 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1843 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1844 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1845 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1846 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1847
1848 /*
1849 * Fill in Phy Target Port Protocol.
1850 * Bits 10:7, more than one bit can be set, fall through cases.
1851 */
1852 protocols = device_info->device_info & 0x780;
1853 identify->target_port_protocols = 0;
1854 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1855 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1856 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1857 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1858 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1859 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1860 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1861 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1862
1863 /*
1864 * Fill in Attached device type.
1865 */
1866 switch (device_info->device_info &
1867 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1868 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1869 identify->device_type = SAS_PHY_UNUSED;
1870 break;
1871 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1872 identify->device_type = SAS_END_DEVICE;
1873 break;
1874 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1875 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1876 break;
1877 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1878 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1879 break;
1880 }
1881}
1882
1883static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001884 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001885{
Moore, Erice6b2d762006-03-14 09:14:24 -07001886 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001887 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001888 struct sas_port *port;
1889 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001890
Eric Moore547f9a22006-06-27 14:42:12 -06001891 if (!dev) {
1892 error = -ENODEV;
1893 goto out;
1894 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001895
1896 if (!phy_info->phy) {
1897 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001898 if (!phy) {
1899 error = -ENOMEM;
1900 goto out;
1901 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001902 } else
1903 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001904
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001905 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001906
1907 /*
1908 * Set Negotiated link rate.
1909 */
1910 switch (phy_info->negotiated_link_rate) {
1911 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001912 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001913 break;
1914 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001915 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001916 break;
1917 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001918 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001919 break;
1920 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001921 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001922 break;
1923 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1924 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1925 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001926 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001927 break;
1928 }
1929
1930 /*
1931 * Set Max hardware link rate.
1932 */
1933 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1934 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001935 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001936 break;
1937 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001938 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001939 break;
1940 default:
1941 break;
1942 }
1943
1944 /*
1945 * Set Max programmed link rate.
1946 */
1947 switch (phy_info->programmed_link_rate &
1948 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1949 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001950 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001951 break;
1952 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001953 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001954 break;
1955 default:
1956 break;
1957 }
1958
1959 /*
1960 * Set Min hardware link rate.
1961 */
1962 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1963 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001964 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001965 break;
1966 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001967 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001968 break;
1969 default:
1970 break;
1971 }
1972
1973 /*
1974 * Set Min programmed link rate.
1975 */
1976 switch (phy_info->programmed_link_rate &
1977 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1978 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001979 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001980 break;
1981 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001982 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001983 break;
1984 default:
1985 break;
1986 }
1987
Moore, Erice6b2d762006-03-14 09:14:24 -07001988 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001989
Moore, Erice6b2d762006-03-14 09:14:24 -07001990 error = sas_phy_add(phy);
1991 if (error) {
1992 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001993 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001994 }
1995 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001996 }
1997
Eric Moore547f9a22006-06-27 14:42:12 -06001998 if (!phy_info->attached.handle ||
1999 !phy_info->port_details)
2000 goto out;
2001
2002 port = mptsas_get_port(phy_info);
2003 ioc = phy_to_ioc(phy_info->phy);
2004
2005 if (phy_info->sas_port_add_phy) {
2006
2007 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06002008 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06002009 if (!port) {
2010 error = -ENOMEM;
2011 goto out;
2012 }
2013 error = sas_port_add(port);
2014 if (error) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302015 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002016 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002017 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002018 goto out;
2019 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302020 mptsas_set_port(ioc, phy_info, port);
Eric Moore29dd3602007-09-14 18:46:51 -06002021 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Eric Mooredc22f162006-07-06 11:23:14 -06002022 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
Eric Moore29dd3602007-09-14 18:46:51 -06002023 ioc->name, port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06002024 }
Eric Moore29dd3602007-09-14 18:46:51 -06002025 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n",
2026 ioc->name, phy_info->phy_id));
Eric Moore547f9a22006-06-27 14:42:12 -06002027 sas_port_add_phy(port, phy_info->phy);
2028 phy_info->sas_port_add_phy = 0;
2029 }
2030
2031 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002032
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002033 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05002034 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06002035 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002036
James Bottomley2686de22006-06-30 12:54:02 -05002037 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07002038 /*
2039 * Let the hotplug_work thread handle processing
2040 * the adding/removing of devices that occur
2041 * after start of day.
2042 */
2043 if (ioc->sas_discovery_runtime &&
2044 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06002045 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07002046
James Bottomleyf013db32006-03-18 14:54:36 -06002047 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05002048 if (scsi_is_host_device(parent)) {
2049 struct mptsas_portinfo *port_info;
2050 int i;
2051
2052 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05002053 port_info = mptsas_get_hba_portinfo(ioc);
James Bottomley2686de22006-06-30 12:54:02 -05002054 mutex_unlock(&ioc->sas_topology_mutex);
2055
2056 for (i = 0; i < port_info->num_phys; i++)
2057 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04002058 identify.sas_address) {
2059 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05002060 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04002061 }
James Bottomley2686de22006-06-30 12:54:02 -05002062
2063 } else if (scsi_is_sas_rphy(parent)) {
2064 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2065 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04002066 parent_rphy->identify.sas_address) {
2067 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05002068 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04002069 }
James Bottomley2686de22006-06-30 12:54:02 -05002070 }
2071
James Bottomleyf013db32006-03-18 14:54:36 -06002072 switch (identify.device_type) {
2073 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06002074 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06002075 break;
2076 case SAS_EDGE_EXPANDER_DEVICE:
2077 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06002078 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06002079 break;
2080 default:
2081 rphy = NULL;
2082 break;
2083 }
Eric Moore547f9a22006-06-27 14:42:12 -06002084 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302085 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002086 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002087 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002088 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002089 }
2090
Eric Moore547f9a22006-06-27 14:42:12 -06002091 rphy->identify = identify;
2092 error = sas_rphy_add(rphy);
2093 if (error) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302094 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002095 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002096 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002097 sas_rphy_free(rphy);
2098 goto out;
2099 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302100 mptsas_set_rphy(ioc, phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002101 }
2102
Eric Moore547f9a22006-06-27 14:42:12 -06002103 out:
2104 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002105}
2106
2107static int
Moore, Erice6b2d762006-03-14 09:14:24 -07002108mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002109{
Moore, Erice6b2d762006-03-14 09:14:24 -07002110 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002111 int error = -ENOMEM, i;
2112
Moore, Erice6b2d762006-03-14 09:14:24 -07002113 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
2114 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002115 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002116
Moore, Erice6b2d762006-03-14 09:14:24 -07002117 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002118 if (error)
2119 goto out_free_port_info;
2120
Prakash, Sathyaedb90682007-07-17 14:39:14 +05302121 mptsas_sas_io_unit_pg1(ioc);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002122 mutex_lock(&ioc->sas_topology_mutex);
Michael Reed77483692008-03-20 17:32:05 -05002123 port_info = mptsas_get_hba_portinfo(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002124 if (!port_info) {
2125 port_info = hba;
2126 list_add_tail(&port_info->list, &ioc->sas_topology);
2127 } else {
Eric Moore2ecce492007-01-29 09:47:08 -07002128 for (i = 0; i < hba->num_phys; i++) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002129 port_info->phy_info[i].negotiated_link_rate =
2130 hba->phy_info[i].negotiated_link_rate;
Eric Moore2ecce492007-01-29 09:47:08 -07002131 port_info->phy_info[i].handle =
2132 hba->phy_info[i].handle;
2133 port_info->phy_info[i].port_id =
2134 hba->phy_info[i].port_id;
2135 }
Eric Moore547f9a22006-06-27 14:42:12 -06002136 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002137 kfree(hba);
2138 hba = NULL;
2139 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002140 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002141 for (i = 0; i < port_info->num_phys; i++) {
2142 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2143 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2144 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2145
2146 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
Eric Moore2ecce492007-01-29 09:47:08 -07002147 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2148 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2149 port_info->phy_info[i].handle);
Eric Moore024358e2005-10-21 20:56:36 +02002150 port_info->phy_info[i].identify.phy_id =
Eric Moore2ecce492007-01-29 09:47:08 -07002151 port_info->phy_info[i].phy_id = i;
Eric Moore547f9a22006-06-27 14:42:12 -06002152 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002153 mptsas_sas_device_pg0(ioc,
2154 &port_info->phy_info[i].attached,
2155 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2156 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2157 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06002158 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002159
Eric Moore547f9a22006-06-27 14:42:12 -06002160 mptsas_setup_wide_ports(ioc, port_info);
2161
2162 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002163 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07002164 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002165
2166 return 0;
2167
2168 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06002169 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002170 out:
2171 return error;
2172}
2173
2174static int
Moore, Erice6b2d762006-03-14 09:14:24 -07002175mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002176{
Moore, Erice6b2d762006-03-14 09:14:24 -07002177 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06002178 struct device *parent;
2179 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002180 int error = -ENOMEM, i, j;
2181
Moore, Erice6b2d762006-03-14 09:14:24 -07002182 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
2183 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002184 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002185
Moore, Erice6b2d762006-03-14 09:14:24 -07002186 error = mptsas_sas_expander_pg0(ioc, ex,
Eric Moore2ecce492007-01-29 09:47:08 -07002187 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2188 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002189 if (error)
2190 goto out_free_port_info;
2191
Eric Moore2ecce492007-01-29 09:47:08 -07002192 *handle = ex->phy_info[0].handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002193
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002194 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002195 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2196 if (!port_info) {
2197 port_info = ex;
2198 list_add_tail(&port_info->list, &ioc->sas_topology);
2199 } else {
Eric Moore2ecce492007-01-29 09:47:08 -07002200 for (i = 0; i < ex->num_phys; i++) {
2201 port_info->phy_info[i].handle =
2202 ex->phy_info[i].handle;
2203 port_info->phy_info[i].port_id =
2204 ex->phy_info[i].port_id;
2205 }
Eric Moore547f9a22006-06-27 14:42:12 -06002206 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002207 kfree(ex);
2208 ex = NULL;
2209 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002210 mutex_unlock(&ioc->sas_topology_mutex);
2211
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002212 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002213 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2214 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2215 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
2216
2217 if (port_info->phy_info[i].identify.handle) {
2218 mptsas_sas_device_pg0(ioc,
2219 &port_info->phy_info[i].identify,
2220 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2221 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2222 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02002223 port_info->phy_info[i].identify.phy_id =
2224 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002225 }
2226
2227 if (port_info->phy_info[i].attached.handle) {
2228 mptsas_sas_device_pg0(ioc,
2229 &port_info->phy_info[i].attached,
2230 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2231 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2232 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07002233 port_info->phy_info[i].attached.phy_id =
2234 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002235 }
Eric Moore547f9a22006-06-27 14:42:12 -06002236 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002237
Eric Moore547f9a22006-06-27 14:42:12 -06002238 parent = &ioc->sh->shost_gendev;
2239 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002240 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002241 list_for_each_entry(p, &ioc->sas_topology, list) {
2242 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002243 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002244 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06002245 continue;
2246 rphy = mptsas_get_rphy(&p->phy_info[j]);
2247 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002248 }
2249 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002250 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002251 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002252
Eric Moore547f9a22006-06-27 14:42:12 -06002253 mptsas_setup_wide_ports(ioc, port_info);
2254
2255 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02002256 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07002257 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002258
2259 return 0;
2260
2261 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07002262 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06002263 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002264 kfree(ex);
2265 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002266 out:
2267 return error;
2268}
2269
Moore, Erice6b2d762006-03-14 09:14:24 -07002270/*
2271 * mptsas_delete_expander_phys
2272 *
2273 *
2274 * This will traverse topology, and remove expanders
2275 * that are no longer present
2276 */
2277static void
2278mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
2279{
2280 struct mptsas_portinfo buffer;
2281 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06002282 struct mptsas_phyinfo *phy_info;
Eric Moore547f9a22006-06-27 14:42:12 -06002283 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07002284 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06002285 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07002286
2287 mutex_lock(&ioc->sas_topology_mutex);
2288 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
2289
Alan Coxd58069a2009-04-01 15:00:29 +01002290 if (!(port_info->phy_info[0].identify.device_info &
2291 MPI_SAS_DEVICE_INFO_SMP_TARGET))
Moore, Erice6b2d762006-03-14 09:14:24 -07002292 continue;
2293
2294 if (mptsas_sas_expander_pg0(ioc, &buffer,
2295 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
Eric Moore2ecce492007-01-29 09:47:08 -07002296 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2297 port_info->phy_info[0].handle)) {
Moore, Erice6b2d762006-03-14 09:14:24 -07002298
2299 /*
2300 * Obtain the port_info instance to the parent port
2301 */
2302 parent = mptsas_find_portinfo_by_handle(ioc,
2303 port_info->phy_info[0].identify.handle_parent);
2304
2305 if (!parent)
2306 goto next_port;
2307
Eric Moore547f9a22006-06-27 14:42:12 -06002308 expander_sas_address =
2309 port_info->phy_info[0].identify.sas_address;
2310
Moore, Erice6b2d762006-03-14 09:14:24 -07002311 /*
2312 * Delete rphys in the parent that point
2313 * to this expander. The transport layer will
2314 * cleanup all the children.
2315 */
Eric Moore547f9a22006-06-27 14:42:12 -06002316 phy_info = parent->phy_info;
2317 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2318 port = mptsas_get_port(phy_info);
2319 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07002320 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002321 if (phy_info->attached.sas_address !=
2322 expander_sas_address)
2323 continue;
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302324 dsaswideprintk(ioc,
Eric Moorec51d0be2007-09-29 10:17:21 -06002325 dev_printk(KERN_DEBUG, &port->dev,
2326 MYIOC_s_FMT "delete port (%d)\n", ioc->name,
2327 port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06002328 sas_port_delete(port);
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302329 mptsas_port_delete(ioc, phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07002330 }
2331 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06002332
2333 phy_info = port_info->phy_info;
2334 for (i = 0; i < port_info->num_phys; i++, phy_info++)
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302335 mptsas_port_delete(ioc, phy_info->port_details);
Eric Moore547f9a22006-06-27 14:42:12 -06002336
Moore, Erice6b2d762006-03-14 09:14:24 -07002337 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002338 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002339 kfree(port_info);
2340 }
2341 /*
2342 * Free this memory allocated from inside
2343 * mptsas_sas_expander_pg0
2344 */
Eric Moore547f9a22006-06-27 14:42:12 -06002345 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07002346 }
2347 mutex_unlock(&ioc->sas_topology_mutex);
2348}
2349
2350/*
2351 * Start of day discovery
2352 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002353static void
2354mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
2355{
2356 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07002357 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002358
Moore, Erice6b2d762006-03-14 09:14:24 -07002359 mutex_lock(&ioc->sas_discovery_mutex);
2360 mptsas_probe_hba_phys(ioc);
2361 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002362 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07002363 /*
2364 Reporting RAID volumes.
2365 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002366 if (!ioc->ir_firmware)
2367 goto out;
Moore, Ericf44e5462006-03-14 09:14:21 -07002368 if (!ioc->raid_data.pIocPg2)
2369 goto out;
2370 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
2371 goto out;
Eric Moore793955f2007-01-29 09:42:20 -07002372 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04002373 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07002374 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
2375 }
2376 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07002377 mutex_unlock(&ioc->sas_discovery_mutex);
2378}
2379
2380/*
2381 * Work queue thread to handle Runtime discovery
2382 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06002383 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07002384 */
2385static void
Eric Moore547f9a22006-06-27 14:42:12 -06002386__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07002387{
Moore, Erice6b2d762006-03-14 09:14:24 -07002388 u32 handle = 0xFFFF;
2389
Moore, Erice6b2d762006-03-14 09:14:24 -07002390 ioc->sas_discovery_runtime=1;
2391 mptsas_delete_expander_phys(ioc);
2392 mptsas_probe_hba_phys(ioc);
2393 while (!mptsas_probe_expander_phys(ioc, &handle))
2394 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002395 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002396}
2397
2398/*
2399 * Work queue thread to handle Runtime discovery
2400 * Mere purpose is the hot add/delete of expanders
2401 *(Mutex LOCKED)
2402 */
2403static void
David Howellsc4028952006-11-22 14:57:56 +00002404mptsas_discovery_work(struct work_struct *work)
Eric Moore547f9a22006-06-27 14:42:12 -06002405{
David Howellsc4028952006-11-22 14:57:56 +00002406 struct mptsas_discovery_event *ev =
2407 container_of(work, struct mptsas_discovery_event, work);
Eric Moore547f9a22006-06-27 14:42:12 -06002408 MPT_ADAPTER *ioc = ev->ioc;
2409
2410 mutex_lock(&ioc->sas_discovery_mutex);
2411 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002412 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002413 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002414}
2415
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002416static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002417mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002418{
2419 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002420 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002421 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002422
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002423 mutex_lock(&ioc->sas_topology_mutex);
2424 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2425 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002426 if (!mptsas_is_end_device(
2427 &port_info->phy_info[i].attached))
2428 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002429 if (port_info->phy_info[i].attached.sas_address
2430 != sas_address)
2431 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002432 phy_info = &port_info->phy_info[i];
2433 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002434 }
2435 }
2436 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002437 return phy_info;
2438}
2439
2440static struct mptsas_phyinfo *
Eric Mooreb506ade2007-01-29 09:45:37 -07002441mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002442{
2443 struct mptsas_portinfo *port_info;
2444 struct mptsas_phyinfo *phy_info = NULL;
2445 int i;
2446
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002447 mutex_lock(&ioc->sas_topology_mutex);
2448 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002449 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002450 if (!mptsas_is_end_device(
2451 &port_info->phy_info[i].attached))
2452 continue;
Eric Mooreb506ade2007-01-29 09:45:37 -07002453 if (port_info->phy_info[i].attached.id != id)
2454 continue;
2455 if (port_info->phy_info[i].attached.channel != channel)
2456 continue;
2457 phy_info = &port_info->phy_info[i];
2458 break;
2459 }
2460 }
2461 mutex_unlock(&ioc->sas_topology_mutex);
2462 return phy_info;
2463}
2464
2465static struct mptsas_phyinfo *
2466mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
2467{
2468 struct mptsas_portinfo *port_info;
2469 struct mptsas_phyinfo *phy_info = NULL;
2470 int i;
2471
2472 mutex_lock(&ioc->sas_topology_mutex);
2473 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2474 for (i = 0; i < port_info->num_phys; i++) {
2475 if (!mptsas_is_end_device(
2476 &port_info->phy_info[i].attached))
2477 continue;
2478 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
2479 continue;
2480 if (port_info->phy_info[i].attached.phys_disk_num != id)
2481 continue;
2482 if (port_info->phy_info[i].attached.channel != channel)
2483 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06002484 phy_info = &port_info->phy_info[i];
2485 break;
2486 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002487 }
2488 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002489 return phy_info;
2490}
2491
Moore, Eric4b766472006-03-14 09:14:12 -07002492/*
2493 * Work queue thread to clear the persitency table
2494 */
2495static void
David Howellsc4028952006-11-22 14:57:56 +00002496mptsas_persist_clear_table(struct work_struct *work)
Moore, Eric4b766472006-03-14 09:14:12 -07002497{
David Howellsc4028952006-11-22 14:57:56 +00002498 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002499
2500 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2501}
2502
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002503static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002504mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2505{
Eric Mooref99be432007-01-04 20:46:54 -07002506 int rc;
2507
Moore, Ericf44e5462006-03-14 09:14:21 -07002508 sdev->no_uld_attach = data ? 1 : 0;
Eric Mooref99be432007-01-04 20:46:54 -07002509 rc = scsi_device_reprobe(sdev);
Moore, Ericf44e5462006-03-14 09:14:21 -07002510}
2511
2512static void
2513mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2514{
2515 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2516 mptsas_reprobe_lun);
2517}
2518
Eric Mooreb506ade2007-01-29 09:45:37 -07002519static void
2520mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2521{
2522 CONFIGPARMS cfg;
2523 ConfigPageHeader_t hdr;
2524 dma_addr_t dma_handle;
2525 pRaidVolumePage0_t buffer = NULL;
2526 RaidPhysDiskPage0_t phys_disk;
2527 int i;
2528 struct mptsas_hotplug_event *ev;
2529
2530 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2531 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
2532 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
2533 cfg.pageAddr = (channel << 8) + id;
2534 cfg.cfghdr.hdr = &hdr;
2535 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2536
2537 if (mpt_config(ioc, &cfg) != 0)
2538 goto out;
2539
2540 if (!hdr.PageLength)
2541 goto out;
2542
2543 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
2544 &dma_handle);
2545
2546 if (!buffer)
2547 goto out;
2548
2549 cfg.physAddr = dma_handle;
2550 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2551
2552 if (mpt_config(ioc, &cfg) != 0)
2553 goto out;
2554
2555 if (!(buffer->VolumeStatus.Flags &
2556 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
2557 goto out;
2558
2559 if (!buffer->NumPhysDisks)
2560 goto out;
2561
2562 for (i = 0; i < buffer->NumPhysDisks; i++) {
2563
2564 if (mpt_raid_phys_disk_pg0(ioc,
2565 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2566 continue;
2567
2568 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2569 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002570 printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name);
Eric Mooreb506ade2007-01-29 09:45:37 -07002571 goto out;
2572 }
2573
2574 INIT_WORK(&ev->work, mptsas_hotplug_work);
2575 ev->ioc = ioc;
2576 ev->id = phys_disk.PhysDiskID;
2577 ev->channel = phys_disk.PhysDiskBus;
2578 ev->phys_disk_num_valid = 1;
2579 ev->phys_disk_num = phys_disk.PhysDiskNum;
2580 ev->event_type = MPTSAS_ADD_DEVICE;
2581 schedule_work(&ev->work);
2582 }
2583
2584 out:
2585 if (buffer)
2586 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
2587 dma_handle);
2588}
Moore, Erice6b2d762006-03-14 09:14:24 -07002589/*
2590 * Work queue thread to handle SAS hotplug events
2591 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002592static void
David Howellsc4028952006-11-22 14:57:56 +00002593mptsas_hotplug_work(struct work_struct *work)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002594{
David Howellsc4028952006-11-22 14:57:56 +00002595 struct mptsas_hotplug_event *ev =
2596 container_of(work, struct mptsas_hotplug_event, work);
Eric Mooreb506ade2007-01-29 09:45:37 -07002597
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002598 MPT_ADAPTER *ioc = ev->ioc;
2599 struct mptsas_phyinfo *phy_info;
2600 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002601 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002602 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002603 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002604 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002605 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002606 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002607 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002608 VirtDevice *vdevice;
2609
Moore, Erice6b2d762006-03-14 09:14:24 -07002610 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002611 switch (ev->event_type) {
2612 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002613
Eric Mooreb506ade2007-01-29 09:45:37 -07002614 phy_info = NULL;
2615 if (ev->phys_disk_num_valid) {
2616 if (ev->hidden_raid_component){
2617 if (mptsas_sas_device_pg0(ioc, &sas_device,
2618 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2619 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2620 (ev->channel << 8) + ev->id)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302621 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Mooreb506ade2007-01-29 09:45:37 -07002622 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002623 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002624 break;
2625 }
2626 phy_info = mptsas_find_phyinfo_by_sas_address(
2627 ioc, sas_device.sas_address);
2628 }else
2629 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2630 ioc, ev->channel, ev->phys_disk_num);
2631 }
2632
2633 if (!phy_info)
2634 phy_info = mptsas_find_phyinfo_by_target(ioc,
2635 ev->channel, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002636
Moore, Ericf44e5462006-03-14 09:14:21 -07002637 /*
2638 * Sanity checks, for non-existing phys and remote rphys.
2639 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002640 if (!phy_info){
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302641 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Mooreb506ade2007-01-29 09:45:37 -07002642 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002643 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002644 break;
2645 }
2646 if (!phy_info->port_details) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302647 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002648 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002649 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002650 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002651 }
2652 rphy = mptsas_get_rphy(phy_info);
2653 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302654 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002655 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002656 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002657 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002658 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002659
Eric Moore547f9a22006-06-27 14:42:12 -06002660 port = mptsas_get_port(phy_info);
2661 if (!port) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302662 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002663 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002664 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002665 break;
2666 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002667
Eric Moore547f9a22006-06-27 14:42:12 -06002668 starget = mptsas_get_starget(phy_info);
2669 if (starget) {
2670 vtarget = starget->hostdata;
2671
2672 if (!vtarget) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302673 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002674 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002675 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002676 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002677 }
2678
Moore, Ericf44e5462006-03-14 09:14:21 -07002679 /*
2680 * Handling RAID components
2681 */
Eric Mooreb506ade2007-01-29 09:45:37 -07002682 if (ev->phys_disk_num_valid &&
2683 ev->hidden_raid_component) {
2684 printk(MYIOC_s_INFO_FMT
2685 "RAID Hidding: channel=%d, id=%d, "
2686 "physdsk %d \n", ioc->name, ev->channel,
2687 ev->id, ev->phys_disk_num);
Eric Moore793955f2007-01-29 09:42:20 -07002688 vtarget->id = ev->phys_disk_num;
Eric Mooreb506ade2007-01-29 09:45:37 -07002689 vtarget->tflags |=
2690 MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002691 mptsas_reprobe_target(starget, 1);
Eric Mooreb506ade2007-01-29 09:45:37 -07002692 phy_info->attached.phys_disk_num =
2693 ev->phys_disk_num;
2694 break;
Moore, Ericf44e5462006-03-14 09:14:21 -07002695 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002696 }
2697
Eric Mooreb506ade2007-01-29 09:45:37 -07002698 if (phy_info->attached.device_info &
2699 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002700 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002701 if (phy_info->attached.device_info &
2702 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002703 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002704 if (phy_info->attached.device_info &
2705 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002706 ds = "sata";
2707
2708 printk(MYIOC_s_INFO_FMT
2709 "removing %s device, channel %d, id %d, phy %d\n",
2710 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
Eric Moorec51d0be2007-09-29 10:17:21 -06002711 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
Eric Moore29dd3602007-09-14 18:46:51 -06002712 "delete port (%d)\n", ioc->name, port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002713 sas_port_delete(port);
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302714 mptsas_port_delete(ioc, phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002715 break;
2716 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002717
Moore, Ericbd23e942006-04-17 12:43:04 -06002718 if (ev->phys_disk_num_valid)
2719 mpt_findImVolumes(ioc);
2720
Moore, Ericc73787ee2006-01-26 16:20:06 -07002721 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002722 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002723 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002724 if (mptsas_sas_device_pg0(ioc, &sas_device,
2725 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Mooreb506ade2007-01-29 09:45:37 -07002726 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2727 (ev->channel << 8) + ev->id)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302728 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002729 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002730 __func__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002731 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002732 }
2733
Eric Moore547f9a22006-06-27 14:42:12 -06002734 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002735
Eric Moore547f9a22006-06-27 14:42:12 -06002736 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2737 sas_device.sas_address);
2738
2739 if (!phy_info || !phy_info->port_details) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302740 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002741 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002742 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002743 break;
2744 }
2745
2746 starget = mptsas_get_starget(phy_info);
Eric Mooreb506ade2007-01-29 09:45:37 -07002747 if (starget && (!ev->hidden_raid_component)){
2748
Eric Moore547f9a22006-06-27 14:42:12 -06002749 vtarget = starget->hostdata;
2750
2751 if (!vtarget) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302752 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore29dd3602007-09-14 18:46:51 -06002753 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002754 __func__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002755 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002756 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002757 /*
2758 * Handling RAID components
2759 */
2760 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
Eric Mooreb506ade2007-01-29 09:45:37 -07002761 printk(MYIOC_s_INFO_FMT
2762 "RAID Exposing: channel=%d, id=%d, "
2763 "physdsk %d \n", ioc->name, ev->channel,
2764 ev->id, ev->phys_disk_num);
2765 vtarget->tflags &=
2766 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore793955f2007-01-29 09:42:20 -07002767 vtarget->id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002768 mptsas_reprobe_target(starget, 0);
Eric Mooreb506ade2007-01-29 09:45:37 -07002769 phy_info->attached.phys_disk_num = ~0;
Moore, Ericf44e5462006-03-14 09:14:21 -07002770 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002771 break;
2772 }
2773
Eric Moore547f9a22006-06-27 14:42:12 -06002774 if (mptsas_get_rphy(phy_info)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302775 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002776 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002777 __func__, __LINE__));
Eric Mooreb506ade2007-01-29 09:45:37 -07002778 if (ev->channel) printk("%d\n", __LINE__);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002779 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002780 }
Eric Mooreb506ade2007-01-29 09:45:37 -07002781
Eric Moore547f9a22006-06-27 14:42:12 -06002782 port = mptsas_get_port(phy_info);
2783 if (!port) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302784 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002785 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002786 __func__, __LINE__));
Eric Moore547f9a22006-06-27 14:42:12 -06002787 break;
2788 }
Christoph Hellwige3094442006-02-16 13:25:36 +01002789 memcpy(&phy_info->attached, &sas_device,
2790 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002791
Eric Mooreb506ade2007-01-29 09:45:37 -07002792 if (phy_info->attached.device_info &
2793 MPI_SAS_DEVICE_INFO_SSP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002794 ds = "ssp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002795 if (phy_info->attached.device_info &
2796 MPI_SAS_DEVICE_INFO_STP_TARGET)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002797 ds = "stp";
Eric Mooreb506ade2007-01-29 09:45:37 -07002798 if (phy_info->attached.device_info &
2799 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002800 ds = "sata";
2801
2802 printk(MYIOC_s_INFO_FMT
2803 "attaching %s device, channel %d, id %d, phy %d\n",
2804 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2805
James Bottomleyf013db32006-03-18 14:54:36 -06002806 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002807 rphy = sas_end_device_alloc(port);
2808 if (!rphy) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302809 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002810 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002811 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002812 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002813 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002814
James Bottomleyf013db32006-03-18 14:54:36 -06002815 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002816 if (sas_rphy_add(rphy)) {
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302817 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
Eric Moore547f9a22006-06-27 14:42:12 -06002818 "%s: exit at line=%d\n", ioc->name,
Harvey Harrisoncadbd4a2008-07-03 23:47:27 -07002819 __func__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002820 sas_rphy_free(rphy);
2821 break;
2822 }
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05302823 mptsas_set_rphy(ioc, phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002824 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002825 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002826 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2827 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002828 if (sdev) {
2829 scsi_device_put(sdev);
2830 break;
2831 }
2832 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002833 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002834 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2835 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002836 mpt_findImVolumes(ioc);
2837 break;
2838 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002839 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
Eric Mooreb506ade2007-01-29 09:45:37 -07002840 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002841 if (!sdev)
2842 break;
2843 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002844 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002845 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Mooreb506ade2007-01-29 09:45:37 -07002846 vdevice = sdev->hostdata;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002847 scsi_remove_device(sdev);
2848 scsi_device_put(sdev);
2849 mpt_findImVolumes(ioc);
2850 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002851 case MPTSAS_ADD_INACTIVE_VOLUME:
2852 mptsas_adding_inactive_raid_components(ioc,
2853 ev->channel, ev->id);
2854 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002855 case MPTSAS_IGNORE_EVENT:
2856 default:
2857 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002858 }
2859
Moore, Erice6b2d762006-03-14 09:14:24 -07002860 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002861 kfree(ev);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002862}
2863
2864static void
Eric Moore547f9a22006-06-27 14:42:12 -06002865mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002866 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2867{
2868 struct mptsas_hotplug_event *ev;
2869 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2870 __le64 sas_address;
2871
2872 if ((device_info &
2873 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2874 MPI_SAS_DEVICE_INFO_STP_TARGET |
2875 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2876 return;
2877
Moore, Eric4b766472006-03-14 09:14:12 -07002878 switch (sas_event_data->ReasonCode) {
Moore, Eric4b766472006-03-14 09:14:12 -07002879 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Mooredf9e0622007-01-29 09:46:21 -07002880
2881 mptsas_target_reset_queue(ioc, sas_event_data);
2882 break;
2883
2884 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
Eric Moore547f9a22006-06-27 14:42:12 -06002885 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002886 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002887 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
Moore, Eric4b766472006-03-14 09:14:12 -07002888 break;
2889 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002890
David Howellsc4028952006-11-22 14:57:56 +00002891 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Eric4b766472006-03-14 09:14:12 -07002892 ev->ioc = ioc;
2893 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2894 ev->parent_handle =
2895 le16_to_cpu(sas_event_data->ParentDevHandle);
2896 ev->channel = sas_event_data->Bus;
2897 ev->id = sas_event_data->TargetID;
2898 ev->phy_id = sas_event_data->PhyNum;
2899 memcpy(&sas_address, &sas_event_data->SASAddress,
2900 sizeof(__le64));
2901 ev->sas_address = le64_to_cpu(sas_address);
2902 ev->device_info = device_info;
2903
2904 if (sas_event_data->ReasonCode &
2905 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2906 ev->event_type = MPTSAS_ADD_DEVICE;
2907 else
2908 ev->event_type = MPTSAS_DEL_DEVICE;
2909 schedule_work(&ev->work);
2910 break;
2911 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2912 /*
2913 * Persistent table is full.
2914 */
Eric Moore547f9a22006-06-27 14:42:12 -06002915 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002916 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002917 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002918 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07002919 /*
2920 * TODO, handle other events
2921 */
Moore, Eric4b766472006-03-14 09:14:12 -07002922 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
Eric Mooreb506ade2007-01-29 09:45:37 -07002923 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
Moore, Eric4b766472006-03-14 09:14:12 -07002924 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
Eric Mooreb506ade2007-01-29 09:45:37 -07002925 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
2926 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2927 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2928 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
Moore, Eric4b766472006-03-14 09:14:12 -07002929 default:
2930 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002931 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002932}
Moore, Ericc73787ee2006-01-26 16:20:06 -07002933static void
Eric Moore547f9a22006-06-27 14:42:12 -06002934mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002935 EVENT_DATA_RAID *raid_event_data)
2936{
2937 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002938 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2939 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002940
2941 if (ioc->bus_type != SAS)
2942 return;
2943
Eric Moore547f9a22006-06-27 14:42:12 -06002944 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002945 if (!ev) {
Eric Moore29dd3602007-09-14 18:46:51 -06002946 printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002947 return;
2948 }
2949
David Howellsc4028952006-11-22 14:57:56 +00002950 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002951 ev->ioc = ioc;
2952 ev->id = raid_event_data->VolumeID;
Eric Mooreb506ade2007-01-29 09:45:37 -07002953 ev->channel = raid_event_data->VolumeBus;
Moore, Ericbd23e942006-04-17 12:43:04 -06002954 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002955
2956 switch (raid_event_data->ReasonCode) {
2957 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
Eric Mooreb506ade2007-01-29 09:45:37 -07002958 ev->phys_disk_num_valid = 1;
2959 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002960 ev->event_type = MPTSAS_ADD_DEVICE;
2961 break;
2962 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002963 ev->phys_disk_num_valid = 1;
2964 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002965 ev->hidden_raid_component = 1;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002966 ev->event_type = MPTSAS_DEL_DEVICE;
2967 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002968 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2969 switch (state) {
2970 case MPI_PD_STATE_ONLINE:
Eric Mooreb506ade2007-01-29 09:45:37 -07002971 case MPI_PD_STATE_NOT_COMPATIBLE:
Moore, Ericbd23e942006-04-17 12:43:04 -06002972 ev->phys_disk_num_valid = 1;
2973 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Eric Mooreb506ade2007-01-29 09:45:37 -07002974 ev->hidden_raid_component = 1;
Moore, Ericbd23e942006-04-17 12:43:04 -06002975 ev->event_type = MPTSAS_ADD_DEVICE;
2976 break;
2977 case MPI_PD_STATE_MISSING:
Moore, Ericbd23e942006-04-17 12:43:04 -06002978 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2979 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2980 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
Eric Mooreb506ade2007-01-29 09:45:37 -07002981 ev->phys_disk_num_valid = 1;
2982 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericbd23e942006-04-17 12:43:04 -06002983 ev->event_type = MPTSAS_DEL_DEVICE;
2984 break;
2985 default:
2986 break;
2987 }
2988 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002989 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2990 ev->event_type = MPTSAS_DEL_RAID;
2991 break;
2992 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2993 ev->event_type = MPTSAS_ADD_RAID;
2994 break;
2995 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002996 switch (state) {
2997 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2998 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2999 ev->event_type = MPTSAS_DEL_RAID;
3000 break;
3001 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
3002 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3003 ev->event_type = MPTSAS_ADD_RAID;
3004 break;
3005 default:
3006 break;
3007 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07003008 break;
3009 default:
3010 break;
3011 }
3012 schedule_work(&ev->work);
3013}
3014
Moore, Erice6b2d762006-03-14 09:14:24 -07003015static void
Eric Moore547f9a22006-06-27 14:42:12 -06003016mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07003017 EVENT_DATA_SAS_DISCOVERY *discovery_data)
3018{
3019 struct mptsas_discovery_event *ev;
Kashyap, Desai7b5a65b2009-05-29 16:38:14 +05303020 u32 discovery_status;
Moore, Erice6b2d762006-03-14 09:14:24 -07003021
3022 /*
3023 * DiscoveryStatus
3024 *
3025 * This flag will be non-zero when firmware
3026 * kicks off discovery, and return to zero
3027 * once its completed.
3028 */
Kashyap, Desai7b5a65b2009-05-29 16:38:14 +05303029 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
3030 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
3031 if (discovery_status)
Moore, Erice6b2d762006-03-14 09:14:24 -07003032 return;
3033
Eric Moore547f9a22006-06-27 14:42:12 -06003034 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07003035 if (!ev)
3036 return;
David Howellsc4028952006-11-22 14:57:56 +00003037 INIT_WORK(&ev->work, mptsas_discovery_work);
Moore, Erice6b2d762006-03-14 09:14:24 -07003038 ev->ioc = ioc;
3039 schedule_work(&ev->work);
3040};
3041
Eric Mooreb506ade2007-01-29 09:45:37 -07003042/*
3043 * mptsas_send_ir2_event - handle exposing hidden disk when
3044 * an inactive raid volume is added
3045 *
3046 * @ioc: Pointer to MPT_ADAPTER structure
3047 * @ir2_data
3048 *
3049 */
3050static void
3051mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
3052{
3053 struct mptsas_hotplug_event *ev;
3054
3055 if (ir2_data->ReasonCode !=
3056 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
3057 return;
3058
3059 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
3060 if (!ev)
3061 return;
3062
3063 INIT_WORK(&ev->work, mptsas_hotplug_work);
3064 ev->ioc = ioc;
3065 ev->id = ir2_data->TargetID;
3066 ev->channel = ir2_data->Bus;
3067 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3068
3069 schedule_work(&ev->work);
3070};
Moore, Erice6b2d762006-03-14 09:14:24 -07003071
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003072static int
3073mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3074{
Moore, Ericc73787ee2006-01-26 16:20:06 -07003075 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003076 u8 event = le32_to_cpu(reply->Event) & 0xFF;
3077
3078 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07003079 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003080
Moore, Erice6b2d762006-03-14 09:14:24 -07003081 /*
3082 * sas_discovery_ignore_events
3083 *
3084 * This flag is to prevent anymore processing of
3085 * sas events once mptsas_remove function is called.
3086 */
3087 if (ioc->sas_discovery_ignore_events) {
3088 rc = mptscsih_event_process(ioc, reply);
3089 goto out;
3090 }
3091
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003092 switch (event) {
3093 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06003094 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003095 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07003096 break;
3097 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06003098 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07003099 (EVENT_DATA_RAID *)reply->Data);
3100 break;
Moore, Eric79de2782006-01-25 18:05:15 -07003101 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06003102 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00003103 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06003104 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07003105 break;
Moore, Eric4b766472006-03-14 09:14:12 -07003106 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06003107 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07003108 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
3109 break;
Eric Mooreb506ade2007-01-29 09:45:37 -07003110 case MPI_EVENT_IR2:
3111 mptsas_send_ir2_event(ioc,
3112 (PTR_MPI_EVENT_DATA_IR2)reply->Data);
3113 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003114 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07003115 rc = mptscsih_event_process(ioc, reply);
3116 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003117 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07003118 out:
3119
3120 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003121}
3122
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003123static int
3124mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3125{
3126 struct Scsi_Host *sh;
3127 MPT_SCSI_HOST *hd;
3128 MPT_ADAPTER *ioc;
3129 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01003130 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003131 int numSGE = 0;
3132 int scale;
3133 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003134 int error=0;
3135 int r;
3136
3137 r = mpt_attach(pdev,id);
3138 if (r)
3139 return r;
3140
3141 ioc = pci_get_drvdata(pdev);
3142 ioc->DoneCtx = mptsasDoneCtx;
3143 ioc->TaskCtx = mptsasTaskCtx;
3144 ioc->InternalCtx = mptsasInternalCtx;
3145
3146 /* Added sanity check on readiness of the MPT adapter.
3147 */
3148 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3149 printk(MYIOC_s_WARN_FMT
3150 "Skipping because it's not operational!\n",
3151 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003152 error = -ENODEV;
3153 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003154 }
3155
3156 if (!ioc->active) {
3157 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3158 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003159 error = -ENODEV;
3160 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003161 }
3162
3163 /* Sanity check - ensure at least 1 port is INITIATOR capable
3164 */
3165 ioc_cap = 0;
3166 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3167 if (ioc->pfacts[ii].ProtocolFlags &
3168 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3169 ioc_cap++;
3170 }
3171
3172 if (!ioc_cap) {
3173 printk(MYIOC_s_WARN_FMT
3174 "Skipping ioc=%p because SCSI Initiator mode "
3175 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06003176 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003177 }
3178
3179 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3180 if (!sh) {
3181 printk(MYIOC_s_WARN_FMT
3182 "Unable to register controller with SCSI subsystem\n",
3183 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003184 error = -1;
3185 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003186 }
3187
3188 spin_lock_irqsave(&ioc->FreeQlock, flags);
3189
3190 /* Attach the SCSI Host to the IOC structure
3191 */
3192 ioc->sh = sh;
3193
3194 sh->io_port = 0;
3195 sh->n_io_port = 0;
3196 sh->irq = 0;
3197
3198 /* set 16 byte cdb's */
3199 sh->max_cmd_len = 16;
3200
Eric Moore793955f2007-01-29 09:42:20 -07003201 sh->max_id = ioc->pfacts[0].PortSCSIID;
3202 sh->max_lun = max_lun;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003203
3204 sh->transportt = mptsas_transport_template;
3205
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003206 /* Required entry.
3207 */
3208 sh->unique_id = ioc->id;
3209
3210 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003211 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07003212 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01003213 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003214 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003215
3216 /* Verify that we won't exceed the maximum
3217 * number of chain buffers
3218 * We can optimize: ZZ = req_sz/sizeof(SGE)
3219 * For 32bit SGE's:
3220 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
3221 * + (req_sz - 64)/sizeof(SGE)
3222 * A slightly different algorithm is required for
3223 * 64bit SGEs.
3224 */
Kashyap, Desai14d0f0b2009-05-29 16:37:04 +05303225 scale = ioc->req_sz/ioc->SGE_size;
3226 if (ioc->sg_addr_size == sizeof(u64)) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003227 numSGE = (scale - 1) *
3228 (ioc->facts.MaxChainDepth-1) + scale +
Kashyap, Desai14d0f0b2009-05-29 16:37:04 +05303229 (ioc->req_sz - 60) / ioc->SGE_size;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003230 } else {
3231 numSGE = 1 + (scale - 1) *
3232 (ioc->facts.MaxChainDepth-1) + scale +
Kashyap, Desai14d0f0b2009-05-29 16:37:04 +05303233 (ioc->req_sz - 64) / ioc->SGE_size;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003234 }
3235
3236 if (numSGE < sh->sg_tablesize) {
3237 /* Reset this value */
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303238 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003239 "Resetting sg_tablesize to %d from %d\n",
3240 ioc->name, numSGE, sh->sg_tablesize));
3241 sh->sg_tablesize = numSGE;
3242 }
3243
Eric Mooree7eae9f2007-09-29 10:15:59 -06003244 hd = shost_priv(sh);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003245 hd->ioc = ioc;
3246
3247 /* SCSI needs scsi_cmnd lookup table!
3248 * (with size equal to req_depth*PtrSz!)
3249 */
Eric Mooree8206382007-09-29 10:16:53 -06003250 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
3251 if (!ioc->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003252 error = -ENOMEM;
Eric Moorebc6e0892007-09-29 10:16:28 -06003253 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003254 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003255 }
Eric Mooree8206382007-09-29 10:16:53 -06003256 spin_lock_init(&ioc->scsi_lookup_lock);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003257
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303258 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
Eric Mooree8206382007-09-29 10:16:53 -06003259 ioc->name, ioc->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003260
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003261 /* Clear the TM flags
3262 */
3263 hd->tmPending = 0;
3264 hd->tmState = TM_STATE_NONE;
3265 hd->resetPending = 0;
3266 hd->abortSCpnt = NULL;
3267
3268 /* Clear the pointer used to store
3269 * single-threaded commands, i.e., those
3270 * issued during a bus scan, dv and
3271 * configuration pages.
3272 */
3273 hd->cmdPtr = NULL;
3274
3275 /* Initialize this SCSI Hosts' timers
3276 * To use, set the timer expires field
3277 * and add_timer
3278 */
3279 init_timer(&hd->timer);
3280 hd->timer.data = (unsigned long) hd;
3281 hd->timer.function = mptscsih_timer_expired;
3282
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003283 ioc->sas_data.ptClear = mpt_pt_clear;
3284
Eric Mooredf9e0622007-01-29 09:46:21 -07003285 init_waitqueue_head(&hd->scandv_waitq);
3286 hd->scandv_wait_done = 0;
3287 hd->last_queue_full = 0;
3288 INIT_LIST_HEAD(&hd->target_reset_list);
3289 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3290
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003291 if (ioc->sas_data.ptClear==1) {
3292 mptbase_sas_persist_operation(
3293 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
3294 }
3295
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003296 error = scsi_add_host(sh, &ioc->pcidev->dev);
3297 if (error) {
Eric Moore29dd3602007-09-14 18:46:51 -06003298 dprintk(ioc, printk(MYIOC_s_ERR_FMT
3299 "scsi_add_host failed\n", ioc->name));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07003300 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003301 }
3302
3303 mptsas_scan_sas_topology(ioc);
3304
3305 return 0;
3306
Eric Moore547f9a22006-06-27 14:42:12 -06003307 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003308
3309 mptscsih_remove(pdev);
3310 return error;
3311}
3312
Kashyap, Desai7b5a65b2009-05-29 16:38:14 +05303313void
3314mptsas_shutdown(struct pci_dev *pdev)
3315{
3316 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3317
3318 ioc->sas_discovery_quiesce_io = 0;
3319}
3320
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003321static void __devexit mptsas_remove(struct pci_dev *pdev)
3322{
3323 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3324 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06003325 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003326
Kashyap, Desai7b5a65b2009-05-29 16:38:14 +05303327 mptsas_shutdown(pdev);
3328
Eric Mooreb506ade2007-01-29 09:45:37 -07003329 ioc->sas_discovery_ignore_events = 1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003330 sas_remove_host(ioc->sh);
3331
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003332 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003333 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
3334 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06003335 for (i = 0 ; i < p->num_phys ; i++)
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303336 mptsas_port_delete(ioc, p->phy_info[i].port_details);
Eric Moore547f9a22006-06-27 14:42:12 -06003337 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003338 kfree(p);
3339 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01003340 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003341
3342 mptscsih_remove(pdev);
3343}
3344
3345static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06003346 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003347 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003348 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003349 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003350 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003351 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003352 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003353 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06003354 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003355 PCI_ANY_ID, PCI_ANY_ID },
3356 {0} /* Terminating entry */
3357};
3358MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
3359
3360
3361static struct pci_driver mptsas_driver = {
3362 .name = "mptsas",
3363 .id_table = mptsas_pci_table,
3364 .probe = mptsas_probe,
3365 .remove = __devexit_p(mptsas_remove),
Kashyap, Desai7b5a65b2009-05-29 16:38:14 +05303366 .shutdown = mptsas_shutdown,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003367#ifdef CONFIG_PM
3368 .suspend = mptscsih_suspend,
3369 .resume = mptscsih_resume,
3370#endif
3371};
3372
3373static int __init
3374mptsas_init(void)
3375{
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05303376 int error;
3377
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003378 show_mptmod_ver(my_NAME, my_VERSION);
3379
3380 mptsas_transport_template =
3381 sas_attach_transport(&mptsas_transport_functions);
3382 if (!mptsas_transport_template)
3383 return -ENODEV;
3384
3385 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
Eric Mooredf9e0622007-01-29 09:46:21 -07003386 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003387 mptsasInternalCtx =
3388 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003389 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003390
Prakash, Sathyad6ecdd62007-07-24 15:47:41 +05303391 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
3392 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003393
Prakash, Sathya57ce21b2007-07-02 17:04:10 +05303394 error = pci_register_driver(&mptsas_driver);
3395 if (error)
3396 sas_release_transport(mptsas_transport_template);
3397
3398 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003399}
3400
3401static void __exit
3402mptsas_exit(void)
3403{
3404 pci_unregister_driver(&mptsas_driver);
3405 sas_release_transport(mptsas_transport_template);
3406
3407 mpt_reset_deregister(mptsasDoneCtx);
3408 mpt_event_deregister(mptsasDoneCtx);
3409
Christoph Hellwigda4fa652005-10-19 20:01:42 +02003410 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02003411 mpt_deregister(mptsasInternalCtx);
3412 mpt_deregister(mptsasTaskCtx);
3413 mpt_deregister(mptsasDoneCtx);
3414}
3415
3416module_init(mptsas_init);
3417module_exit(mptsas_exit);