Commit ecd4b48a authored by Ben Hutchings's avatar Ben Hutchings Committed by Roland Dreier

IB/qib: Use request_firmware() to load SD7220 firmware

Extract the microcode for the QLogic QLE7220 series IB HCA and use the
kernel microcode request facility to load the microcode.  This
supports Debian Linux's requirements to separate microcode which
doesn't have open source code available from the device driver.
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent e467e104
...@@ -6,7 +6,7 @@ ib_qib-y := qib_cq.o qib_diag.o qib_dma.o qib_driver.o qib_eeprom.o \ ...@@ -6,7 +6,7 @@ ib_qib-y := qib_cq.o qib_diag.o qib_dma.o qib_driver.o qib_eeprom.o \
qib_qp.o qib_qsfp.o qib_rc.o qib_ruc.o qib_sdma.o qib_srq.o \ qib_qp.o qib_qsfp.o qib_rc.o qib_ruc.o qib_sdma.o qib_srq.o \
qib_sysfs.o qib_twsi.o qib_tx.o qib_uc.o qib_ud.o \ qib_sysfs.o qib_twsi.o qib_tx.o qib_uc.o qib_ud.o \
qib_user_pages.o qib_user_sdma.o qib_verbs_mcast.o qib_iba7220.o \ qib_user_pages.o qib_user_sdma.o qib_verbs_mcast.o qib_iba7220.o \
qib_sd7220.o qib_sd7220_img.o qib_iba7322.o qib_verbs.o qib_sd7220.o qib_iba7322.o qib_verbs.o
# 6120 has no fallback if no MSI interrupts, others can do INTx # 6120 has no fallback if no MSI interrupts, others can do INTx
ib_qib-$(CONFIG_PCI_MSI) += qib_iba6120.o ib_qib-$(CONFIG_PCI_MSI) += qib_iba6120.o
......
...@@ -109,10 +109,6 @@ struct qib_chippport_specific { ...@@ -109,10 +109,6 @@ struct qib_chippport_specific {
*/ */
int qib_sd7220_presets(struct qib_devdata *dd); int qib_sd7220_presets(struct qib_devdata *dd);
int qib_sd7220_init(struct qib_devdata *dd); int qib_sd7220_init(struct qib_devdata *dd);
int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, u8 *img,
int len, int offset);
int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum, const u8 *img,
int len, int offset);
void qib_sd7220_clr_ibpar(struct qib_devdata *); void qib_sd7220_clr_ibpar(struct qib_devdata *);
/* /*
* Below used for sdnum parameter, selecting one of the two sections * Below used for sdnum parameter, selecting one of the two sections
...@@ -121,9 +117,6 @@ void qib_sd7220_clr_ibpar(struct qib_devdata *); ...@@ -121,9 +117,6 @@ void qib_sd7220_clr_ibpar(struct qib_devdata *);
*/ */
#define IB_7220_SERDES 2 #define IB_7220_SERDES 2
int qib_sd7220_ib_load(struct qib_devdata *dd);
int qib_sd7220_ib_vfy(struct qib_devdata *dd);
static inline u32 qib_read_kreg32(const struct qib_devdata *dd, static inline u32 qib_read_kreg32(const struct qib_devdata *dd,
const u16 regno) const u16 regno)
{ {
......
/* /*
* Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
* All rights reserved.
* Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
* *
* This software is available to you under a choice of one of two * This software is available to you under a choice of one of two
...@@ -37,10 +38,14 @@ ...@@ -37,10 +38,14 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/firmware.h>
#include "qib.h" #include "qib.h"
#include "qib_7220.h" #include "qib_7220.h"
#define SD7220_FW_NAME "qlogic/sd7220.fw"
MODULE_FIRMWARE(SD7220_FW_NAME);
/* /*
* Same as in qib_iba7220.c, but just the registers needed here. * Same as in qib_iba7220.c, but just the registers needed here.
* Could move whole set to qib_7220.h, but decided better to keep * Could move whole set to qib_7220.h, but decided better to keep
...@@ -102,6 +107,10 @@ static int qib_internal_presets(struct qib_devdata *dd); ...@@ -102,6 +107,10 @@ static int qib_internal_presets(struct qib_devdata *dd);
/* Tweak the register (CMUCTRL5) that contains the TRIMSELF controls */ /* Tweak the register (CMUCTRL5) that contains the TRIMSELF controls */
static int qib_sd_trimself(struct qib_devdata *dd, int val); static int qib_sd_trimself(struct qib_devdata *dd, int val);
static int epb_access(struct qib_devdata *dd, int sdnum, int claim); static int epb_access(struct qib_devdata *dd, int sdnum, int claim);
static int qib_sd7220_ib_load(struct qib_devdata *dd,
const struct firmware *fw);
static int qib_sd7220_ib_vfy(struct qib_devdata *dd,
const struct firmware *fw);
/* /*
* Below keeps track of whether the "once per power-on" initialization has * Below keeps track of whether the "once per power-on" initialization has
...@@ -110,10 +119,13 @@ static int epb_access(struct qib_devdata *dd, int sdnum, int claim); ...@@ -110,10 +119,13 @@ static int epb_access(struct qib_devdata *dd, int sdnum, int claim);
* state of the reset "pin", is no longer valid. Instead, we check for the * state of the reset "pin", is no longer valid. Instead, we check for the
* actual uC code having been loaded. * actual uC code having been loaded.
*/ */
static int qib_ibsd_ucode_loaded(struct qib_pportdata *ppd) static int qib_ibsd_ucode_loaded(struct qib_pportdata *ppd,
const struct firmware *fw)
{ {
struct qib_devdata *dd = ppd->dd; struct qib_devdata *dd = ppd->dd;
if (!dd->cspec->serdes_first_init_done && (qib_sd7220_ib_vfy(dd) > 0))
if (!dd->cspec->serdes_first_init_done &&
qib_sd7220_ib_vfy(dd, fw) > 0)
dd->cspec->serdes_first_init_done = 1; dd->cspec->serdes_first_init_done = 1;
return dd->cspec->serdes_first_init_done; return dd->cspec->serdes_first_init_done;
} }
...@@ -377,6 +389,7 @@ static void qib_sd_trimdone_monitor(struct qib_devdata *dd, ...@@ -377,6 +389,7 @@ static void qib_sd_trimdone_monitor(struct qib_devdata *dd,
*/ */
int qib_sd7220_init(struct qib_devdata *dd) int qib_sd7220_init(struct qib_devdata *dd)
{ {
const struct firmware *fw;
int ret = 1; /* default to failure */ int ret = 1; /* default to failure */
int first_reset, was_reset; int first_reset, was_reset;
...@@ -387,8 +400,15 @@ int qib_sd7220_init(struct qib_devdata *dd) ...@@ -387,8 +400,15 @@ int qib_sd7220_init(struct qib_devdata *dd)
qib_ibsd_reset(dd, 1); qib_ibsd_reset(dd, 1);
qib_sd_trimdone_monitor(dd, "Driver-reload"); qib_sd_trimdone_monitor(dd, "Driver-reload");
} }
ret = request_firmware(&fw, SD7220_FW_NAME, &dd->pcidev->dev);
if (ret) {
qib_dev_err(dd, "Failed to load IB SERDES image\n");
goto done;
}
/* Substitute our deduced value for was_reset */ /* Substitute our deduced value for was_reset */
ret = qib_ibsd_ucode_loaded(dd->pport); ret = qib_ibsd_ucode_loaded(dd->pport, fw);
if (ret < 0) if (ret < 0)
goto bail; goto bail;
...@@ -437,13 +457,13 @@ int qib_sd7220_init(struct qib_devdata *dd) ...@@ -437,13 +457,13 @@ int qib_sd7220_init(struct qib_devdata *dd)
int vfy; int vfy;
int trim_done; int trim_done;
ret = qib_sd7220_ib_load(dd); ret = qib_sd7220_ib_load(dd, fw);
if (ret < 0) { if (ret < 0) {
qib_dev_err(dd, "Failed to load IB SERDES image\n"); qib_dev_err(dd, "Failed to load IB SERDES image\n");
goto bail; goto bail;
} else { } else {
/* Loaded image, try to verify */ /* Loaded image, try to verify */
vfy = qib_sd7220_ib_vfy(dd); vfy = qib_sd7220_ib_vfy(dd, fw);
if (vfy != ret) { if (vfy != ret) {
qib_dev_err(dd, "SERDES PRAM VFY failed\n"); qib_dev_err(dd, "SERDES PRAM VFY failed\n");
goto bail; goto bail;
...@@ -506,6 +526,8 @@ int qib_sd7220_init(struct qib_devdata *dd) ...@@ -506,6 +526,8 @@ int qib_sd7220_init(struct qib_devdata *dd)
done: done:
/* start relock timer regardless, but start at 1 second */ /* start relock timer regardless, but start at 1 second */
set_7220_relock_poll(dd, -1); set_7220_relock_poll(dd, -1);
release_firmware(fw);
return ret; return ret;
} }
...@@ -829,8 +851,8 @@ static int qib_sd7220_ram_xfer(struct qib_devdata *dd, int sdnum, u32 loc, ...@@ -829,8 +851,8 @@ static int qib_sd7220_ram_xfer(struct qib_devdata *dd, int sdnum, u32 loc,
#define PROG_CHUNK 64 #define PROG_CHUNK 64
int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, static int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,
u8 *img, int len, int offset) const u8 *img, int len, int offset)
{ {
int cnt, sofar, req; int cnt, sofar, req;
...@@ -840,7 +862,7 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, ...@@ -840,7 +862,7 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,
if (req > PROG_CHUNK) if (req > PROG_CHUNK)
req = PROG_CHUNK; req = PROG_CHUNK;
cnt = qib_sd7220_ram_xfer(dd, sdnum, offset + sofar, cnt = qib_sd7220_ram_xfer(dd, sdnum, offset + sofar,
img + sofar, req, 0); (u8 *)img + sofar, req, 0);
if (cnt < req) { if (cnt < req) {
sofar = -1; sofar = -1;
break; break;
...@@ -853,8 +875,8 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum, ...@@ -853,8 +875,8 @@ int qib_sd7220_prog_ld(struct qib_devdata *dd, int sdnum,
#define VFY_CHUNK 64 #define VFY_CHUNK 64
#define SD_PRAM_ERROR_LIMIT 42 #define SD_PRAM_ERROR_LIMIT 42
int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum, static int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum,
const u8 *img, int len, int offset) const u8 *img, int len, int offset)
{ {
int cnt, sofar, req, idx, errors; int cnt, sofar, req, idx, errors;
unsigned char readback[VFY_CHUNK]; unsigned char readback[VFY_CHUNK];
...@@ -881,6 +903,18 @@ int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum, ...@@ -881,6 +903,18 @@ int qib_sd7220_prog_vfy(struct qib_devdata *dd, int sdnum,
return errors ? -errors : sofar; return errors ? -errors : sofar;
} }
static int
qib_sd7220_ib_load(struct qib_devdata *dd, const struct firmware *fw)
{
return qib_sd7220_prog_ld(dd, IB_7220_SERDES, fw->data, fw->size, 0);
}
static int
qib_sd7220_ib_vfy(struct qib_devdata *dd, const struct firmware *fw)
{
return qib_sd7220_prog_vfy(dd, IB_7220_SERDES, fw->data, fw->size, 0);
}
/* /*
* IRQ not set up at this point in init, so we poll. * IRQ not set up at this point in init, so we poll.
*/ */
......
This diff is collapsed.
...@@ -83,6 +83,7 @@ fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \ ...@@ -83,6 +83,7 @@ fw-shipped-$(CONFIG_SCSI_ADVANSYS) += advansys/mcode.bin advansys/38C1600.bin \
fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \ fw-shipped-$(CONFIG_SCSI_QLOGIC_1280) += qlogic/1040.bin qlogic/1280.bin \
qlogic/12160.bin qlogic/12160.bin
fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin fw-shipped-$(CONFIG_SCSI_QLOGICPTI) += qlogic/isp1000.bin
fw-shipped-$(CONFIG_INFINIBAND_QIB) += qlogic/sd7220.fw
fw-shipped-$(CONFIG_SMCTR) += tr_smctr.bin fw-shipped-$(CONFIG_SMCTR) += tr_smctr.bin
fw-shipped-$(CONFIG_SND_KORG1212) += korg/k1212.dsp fw-shipped-$(CONFIG_SND_KORG1212) += korg/k1212.dsp
fw-shipped-$(CONFIG_SND_MAESTRO3) += ess/maestro3_assp_kernel.fw \ fw-shipped-$(CONFIG_SND_MAESTRO3) += ess/maestro3_assp_kernel.fw \
......
...@@ -858,3 +858,43 @@ Licence: ...@@ -858,3 +858,43 @@ Licence:
Found in hex form in kernel source. Found in hex form in kernel source.
-------------------------------------------------------------------------- --------------------------------------------------------------------------
Driver: ib_qib - QLogic Infiniband
File: qlogic/sd7220.fw
Licence:
* Copyright (c) 2007, 2008 QLogic Corporation. All rights reserved.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
Found in hex form in kernel source.
--------------------------------------------------------------------------
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment